@nick848/sf-cli 1.0.10 → 1.0.12
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/CHANGELOG.md +43 -6
- package/dist/cli/index.js +542 -35
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +540 -35
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +540 -35
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -73,14 +73,17 @@ async function handleNew(args, ctx) {
|
|
|
73
73
|
const requirement = args.join(" ").trim();
|
|
74
74
|
if (!requirement) {
|
|
75
75
|
return {
|
|
76
|
-
output: chalk9__default.default.red("\u8BF7\u8F93\u5165\u9700\u6C42\u63CF\u8FF0") + chalk9__default.default.gray("\n\u7528\u6CD5: /new <\u9700\u6C42\u63CF\u8FF0>")
|
|
76
|
+
output: chalk9__default.default.red("\u8BF7\u8F93\u5165\u9700\u6C42\u63CF\u8FF0") + chalk9__default.default.gray("\n\u7528\u6CD5: /new <\u9700\u6C42\u63CF\u8FF0>") + chalk9__default.default.gray("\n\n\u793A\u4F8B:") + chalk9__default.default.gray("\n /new \u5B9E\u73B0\u7528\u6237\u767B\u5F55\u529F\u80FD") + chalk9__default.default.gray("\n /new \u6DFB\u52A0\u6570\u636E\u5BFC\u51FA\u4E3AExcel\u7684\u529F\u80FD")
|
|
77
77
|
};
|
|
78
78
|
}
|
|
79
79
|
activeSession = {
|
|
80
80
|
id: generateSessionId(),
|
|
81
81
|
requirement,
|
|
82
|
+
refinedRequirement: requirement,
|
|
82
83
|
phase: "context",
|
|
83
84
|
context: null,
|
|
85
|
+
clarityScore: 0,
|
|
86
|
+
clarificationQuestions: [],
|
|
84
87
|
complexity: 0,
|
|
85
88
|
bddScenarios: [],
|
|
86
89
|
specItems: [],
|
|
@@ -98,10 +101,13 @@ function handleActiveSession(ctx) {
|
|
|
98
101
|
const lines = [];
|
|
99
102
|
lines.push(chalk9__default.default.cyan("\u{1F4CB} \u5F53\u524D\u5DE5\u4F5C\u6D41\u72B6\u6001"));
|
|
100
103
|
lines.push("");
|
|
101
|
-
lines.push(chalk9__default.default.white(`\u9700\u6C42: ${activeSession.requirement}`));
|
|
104
|
+
lines.push(chalk9__default.default.white(`\u9700\u6C42: ${activeSession.requirement.slice(0, 60)}${activeSession.requirement.length > 60 ? "..." : ""}`));
|
|
102
105
|
lines.push(chalk9__default.default.gray(`\u9636\u6BB5: ${getPhaseLabel(activeSession.phase)}`));
|
|
103
106
|
lines.push("");
|
|
104
|
-
if (activeSession.phase === "
|
|
107
|
+
if (activeSession.phase === "clarify") {
|
|
108
|
+
lines.push(chalk9__default.default.yellow("\u23F8\uFE0F \u7B49\u5F85\u9700\u6C42\u6F84\u6E05"));
|
|
109
|
+
lines.push(chalk9__default.default.gray('\u8BF7\u56DE\u7B54\u4E0A\u8FF0\u95EE\u9898\uFF0C\u6216\u8F93\u5165 "done" \u8868\u793A\u56DE\u7B54\u5B8C\u6210'));
|
|
110
|
+
} else if (activeSession.phase === "spec") {
|
|
105
111
|
lines.push(chalk9__default.default.yellow("\u23F8\uFE0F \u7B49\u5F85\u89C4\u683C\u786E\u8BA4"));
|
|
106
112
|
lines.push("");
|
|
107
113
|
lines.push(chalk9__default.default.green(" y - \u786E\u8BA4\u89C4\u683C\uFF0C\u7EE7\u7EED\u5DE5\u4F5C\u6D41"));
|
|
@@ -120,7 +126,7 @@ async function executeWorkflow(ctx) {
|
|
|
120
126
|
const lines = [];
|
|
121
127
|
try {
|
|
122
128
|
if (activeSession.phase === "context") {
|
|
123
|
-
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5 1/
|
|
129
|
+
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5 1/8: \u9879\u76EE\u4E0A\u4E0B\u6587\u83B7\u53D6 \u2501\u2501\u2501"));
|
|
124
130
|
lines.push("");
|
|
125
131
|
activeSession.context = await readProjectContext(ctx.options.workingDirectory);
|
|
126
132
|
lines.push(chalk9__default.default.gray(` \u9879\u76EE: ${activeSession.context.name}`));
|
|
@@ -130,13 +136,46 @@ async function executeWorkflow(ctx) {
|
|
|
130
136
|
if (activeSession.context.devStandards) {
|
|
131
137
|
lines.push(chalk9__default.default.green(" \u2713 \u5DF2\u8BFB\u53D6\u5F00\u53D1\u89C4\u8303"));
|
|
132
138
|
}
|
|
139
|
+
activeSession.phase = "clarify";
|
|
140
|
+
}
|
|
141
|
+
if (activeSession.phase === "clarify") {
|
|
142
|
+
lines.push("");
|
|
143
|
+
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5 2/8: \u9700\u6C42\u6F84\u6E05 \u2501\u2501\u2501"));
|
|
144
|
+
lines.push("");
|
|
145
|
+
const clarityResult = analyzeRequirementClarity(
|
|
146
|
+
activeSession.requirement,
|
|
147
|
+
activeSession.context
|
|
148
|
+
);
|
|
149
|
+
activeSession.clarityScore = clarityResult.score;
|
|
150
|
+
activeSession.clarificationQuestions = clarityResult.questions;
|
|
151
|
+
lines.push(chalk9__default.default.gray(` \u9700\u6C42\u6E05\u6670\u5EA6: ${Math.round(clarityResult.score * 100)}%`));
|
|
152
|
+
lines.push("");
|
|
153
|
+
if (clarityResult.score < CLARITY_THRESHOLD && clarityResult.questions.length > 0) {
|
|
154
|
+
lines.push(chalk9__default.default.yellow(" \u9700\u6C42\u4E0D\u591F\u660E\u786E\uFF0C\u8BF7\u8865\u5145\u4EE5\u4E0B\u4FE1\u606F\uFF1A"));
|
|
155
|
+
lines.push("");
|
|
156
|
+
const unansweredQuestions = clarityResult.questions.filter((q) => !q.answered);
|
|
157
|
+
for (let i = 0; i < Math.min(unansweredQuestions.length, 3); i++) {
|
|
158
|
+
const q = unansweredQuestions[i];
|
|
159
|
+
lines.push(chalk9__default.default.white(` ${i + 1}. ${q.question}`));
|
|
160
|
+
}
|
|
161
|
+
if (unansweredQuestions.length > 3) {
|
|
162
|
+
lines.push(chalk9__default.default.gray(` ... \u8FD8\u6709 ${unansweredQuestions.length - 3} \u4E2A\u95EE\u9898`));
|
|
163
|
+
}
|
|
164
|
+
lines.push("");
|
|
165
|
+
lines.push(chalk9__default.default.gray(' \u8BF7\u8F93\u5165\u56DE\u7B54\uFF0C\u6216\u8F93\u5165 "done" \u8DF3\u8FC7\u6F84\u6E05'));
|
|
166
|
+
return { output: lines.join("\n") };
|
|
167
|
+
}
|
|
168
|
+
lines.push(chalk9__default.default.green(" \u2713 \u9700\u6C42\u6E05\u6670\uFF0C\u7EE7\u7EED\u4E0B\u4E00\u6B65"));
|
|
133
169
|
activeSession.phase = "analysis";
|
|
134
170
|
}
|
|
135
171
|
if (activeSession.phase === "analysis") {
|
|
136
172
|
lines.push("");
|
|
137
|
-
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5
|
|
173
|
+
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5 3/8: \u590D\u6742\u5EA6\u8BC4\u4F30 \u2501\u2501\u2501"));
|
|
138
174
|
lines.push("");
|
|
139
|
-
activeSession.complexity = analyzeComplexity(
|
|
175
|
+
activeSession.complexity = analyzeComplexity(
|
|
176
|
+
activeSession.refinedRequirement,
|
|
177
|
+
activeSession.context
|
|
178
|
+
);
|
|
140
179
|
const complexityBar = generateComplexityBar(activeSession.complexity);
|
|
141
180
|
lines.push(chalk9__default.default.gray(` \u590D\u6742\u5EA6: ${complexityBar} ${activeSession.complexity}/10`));
|
|
142
181
|
if (activeSession.complexity >= COMPLEXITY_THRESHOLD) {
|
|
@@ -148,9 +187,13 @@ async function executeWorkflow(ctx) {
|
|
|
148
187
|
}
|
|
149
188
|
if (activeSession.phase === "bdd") {
|
|
150
189
|
lines.push("");
|
|
151
|
-
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5
|
|
190
|
+
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5 4/8: BDD \u573A\u666F\u62C6\u89E3 \u2501\u2501\u2501"));
|
|
152
191
|
lines.push("");
|
|
153
|
-
activeSession.bddScenarios = generateBDDScenarios(
|
|
192
|
+
activeSession.bddScenarios = generateBDDScenarios(
|
|
193
|
+
activeSession.refinedRequirement,
|
|
194
|
+
activeSession.context,
|
|
195
|
+
activeSession.clarificationQuestions
|
|
196
|
+
);
|
|
154
197
|
for (const scenario of activeSession.bddScenarios) {
|
|
155
198
|
lines.push(chalk9__default.default.white(` Feature: ${scenario.feature}`));
|
|
156
199
|
for (const s of scenario.scenarios.slice(0, 3)) {
|
|
@@ -164,9 +207,14 @@ async function executeWorkflow(ctx) {
|
|
|
164
207
|
}
|
|
165
208
|
if (activeSession.phase === "spec") {
|
|
166
209
|
lines.push("");
|
|
167
|
-
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5
|
|
210
|
+
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5 5/8: OpenSpec \u89C4\u683C \u2501\u2501\u2501"));
|
|
168
211
|
lines.push("");
|
|
169
|
-
activeSession.specItems = generateSpecItems(
|
|
212
|
+
activeSession.specItems = generateSpecItems(
|
|
213
|
+
activeSession.refinedRequirement,
|
|
214
|
+
activeSession.context,
|
|
215
|
+
activeSession.bddScenarios,
|
|
216
|
+
activeSession.clarificationQuestions
|
|
217
|
+
);
|
|
170
218
|
const specPath = await saveSpecFile(ctx.options.workingDirectory, activeSession);
|
|
171
219
|
lines.push(chalk9__default.default.green(" \u2713 \u89C4\u683C\u6587\u4EF6\u5DF2\u751F\u6210"));
|
|
172
220
|
lines.push(chalk9__default.default.gray(` \u8DEF\u5F84: ${specPath}`));
|
|
@@ -189,7 +237,7 @@ async function executeWorkflow(ctx) {
|
|
|
189
237
|
}
|
|
190
238
|
if (activeSession.phase === "tdd") {
|
|
191
239
|
lines.push("");
|
|
192
|
-
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5
|
|
240
|
+
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5 6/8: TDD \u6D4B\u8BD5\u751F\u6210 \u2501\u2501\u2501"));
|
|
193
241
|
lines.push("");
|
|
194
242
|
activeSession.testFiles = await generateTests(ctx.options.workingDirectory, activeSession);
|
|
195
243
|
lines.push(chalk9__default.default.green(" \u2713 \u6D4B\u8BD5\u6587\u4EF6\u5DF2\u751F\u6210"));
|
|
@@ -200,20 +248,69 @@ async function executeWorkflow(ctx) {
|
|
|
200
248
|
}
|
|
201
249
|
if (activeSession.phase === "develop") {
|
|
202
250
|
lines.push("");
|
|
203
|
-
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5
|
|
251
|
+
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5 7/8: \u5F00\u53D1\u5B9E\u73B0 \u2501\u2501\u2501"));
|
|
204
252
|
lines.push("");
|
|
205
|
-
lines.push(chalk9__default.default.yellow(" \u{
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
253
|
+
lines.push(chalk9__default.default.yellow(" \u{1F680} \u6B63\u5728\u8C03\u7528 AI \u751F\u6210\u4EE3\u7801..."));
|
|
254
|
+
try {
|
|
255
|
+
const developResult = await executeDevelopment(ctx, activeSession);
|
|
256
|
+
if (developResult.success) {
|
|
257
|
+
lines.push(chalk9__default.default.green(" \u2713 \u4EE3\u7801\u751F\u6210\u5B8C\u6210"));
|
|
258
|
+
for (const file of developResult.files) {
|
|
259
|
+
lines.push(chalk9__default.default.gray(` - ${file}`));
|
|
260
|
+
}
|
|
261
|
+
activeSession.implFiles = developResult.files;
|
|
262
|
+
activeSession.phase = "review";
|
|
263
|
+
} else {
|
|
264
|
+
lines.push(chalk9__default.default.red(` \u2717 \u4EE3\u7801\u751F\u6210\u5931\u8D25: ${developResult.error}`));
|
|
265
|
+
lines.push(chalk9__default.default.gray(" \u8BF7\u624B\u52A8\u5B9E\u73B0\u4EE3\u7801\u540E\u8F93\u5165 continue \u7EE7\u7EED"));
|
|
266
|
+
return { output: lines.join("\n") };
|
|
267
|
+
}
|
|
268
|
+
} catch (error) {
|
|
269
|
+
lines.push(chalk9__default.default.red(` \u2717 \u5F00\u53D1\u9636\u6BB5\u51FA\u9519: ${error.message}`));
|
|
270
|
+
lines.push(chalk9__default.default.gray(" \u8BF7\u624B\u52A8\u5B9E\u73B0\u4EE3\u7801\u540E\u8F93\u5165 continue \u7EE7\u7EED"));
|
|
271
|
+
return { output: lines.join("\n") };
|
|
272
|
+
}
|
|
209
273
|
}
|
|
210
274
|
if (activeSession.phase === "review") {
|
|
211
275
|
lines.push("");
|
|
212
|
-
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5
|
|
276
|
+
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5 8/8: \u4EE3\u7801\u5BA1\u6838 \u2501\u2501\u2501"));
|
|
213
277
|
lines.push("");
|
|
214
|
-
lines.push(chalk9__default.default.yellow(" \u{1F50D} \u4EE3\u7801\u5BA1\u6838
|
|
215
|
-
|
|
216
|
-
|
|
278
|
+
lines.push(chalk9__default.default.yellow(" \u{1F50D} \u6B63\u5728\u8FDB\u884C\u4EE3\u7801\u5BA1\u6838..."));
|
|
279
|
+
try {
|
|
280
|
+
const reviewResult = await executeReview(ctx, activeSession);
|
|
281
|
+
if (reviewResult.passed) {
|
|
282
|
+
lines.push(chalk9__default.default.green(" \u2713 \u4EE3\u7801\u5BA1\u6838\u901A\u8FC7"));
|
|
283
|
+
if (reviewResult.suggestions.length > 0) {
|
|
284
|
+
lines.push(chalk9__default.default.gray(" \u5EFA\u8BAE:"));
|
|
285
|
+
for (const s of reviewResult.suggestions.slice(0, 3)) {
|
|
286
|
+
lines.push(chalk9__default.default.gray(` - ${s}`));
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
await archiveWorkflow(ctx.options.workingDirectory);
|
|
290
|
+
const summary = activeSession.refinedRequirement;
|
|
291
|
+
activeSession = null;
|
|
292
|
+
lines.push("");
|
|
293
|
+
lines.push(chalk9__default.default.green.bold("\u{1F389} \u5DE5\u4F5C\u6D41\u5DF2\u5B8C\u6210\uFF01"));
|
|
294
|
+
lines.push(chalk9__default.default.gray(`\u9700\u6C42: ${summary.slice(0, 60)}${summary.length > 60 ? "..." : ""}`));
|
|
295
|
+
lines.push("");
|
|
296
|
+
lines.push(chalk9__default.default.cyan("\u4F7F\u7528 /new <\u9700\u6C42> \u5F00\u59CB\u65B0\u7684\u5DE5\u4F5C\u6D41"));
|
|
297
|
+
return { output: lines.join("\n") };
|
|
298
|
+
} else {
|
|
299
|
+
lines.push(chalk9__default.default.red(" \u2717 \u4EE3\u7801\u5BA1\u6838\u672A\u901A\u8FC7"));
|
|
300
|
+
lines.push(chalk9__default.default.gray(" \u95EE\u9898:"));
|
|
301
|
+
for (const issue of reviewResult.issues.slice(0, 5)) {
|
|
302
|
+
lines.push(chalk9__default.default.red(` - ${issue}`));
|
|
303
|
+
}
|
|
304
|
+
lines.push("");
|
|
305
|
+
lines.push(chalk9__default.default.yellow(" \u8BF7\u4FEE\u590D\u95EE\u9898\u540E\u8F93\u5165 y \u91CD\u65B0\u5BA1\u6838"));
|
|
306
|
+
lines.push(chalk9__default.default.gray(" \u6216\u8F93\u5165 n \u56DE\u9000\u5230\u89C4\u683C\u9636\u6BB5"));
|
|
307
|
+
return { output: lines.join("\n") };
|
|
308
|
+
}
|
|
309
|
+
} catch (error) {
|
|
310
|
+
lines.push(chalk9__default.default.red(` \u2717 \u5BA1\u6838\u9636\u6BB5\u51FA\u9519: ${error.message}`));
|
|
311
|
+
lines.push(chalk9__default.default.gray(" \u8F93\u5165 pass \u5F3A\u5236\u901A\u8FC7\uFF0C\u6216 fix \u4FEE\u590D\u95EE\u9898"));
|
|
312
|
+
return { output: lines.join("\n") };
|
|
313
|
+
}
|
|
217
314
|
}
|
|
218
315
|
return { output: lines.join("\n") };
|
|
219
316
|
} catch (error) {
|
|
@@ -230,14 +327,58 @@ async function handleWorkflowInput(input, ctx) {
|
|
|
230
327
|
output: chalk9__default.default.yellow("\u2713 \u5DE5\u4F5C\u6D41\u5DF2\u53D6\u6D88")
|
|
231
328
|
};
|
|
232
329
|
}
|
|
330
|
+
if (activeSession.phase === "clarify") {
|
|
331
|
+
if (trimmed === "done" || trimmed === "\u5B8C\u6210" || trimmed === "\u8DF3\u8FC7" || trimmed === "skip") {
|
|
332
|
+
activeSession.refinedRequirement = buildRefinedRequirement(activeSession);
|
|
333
|
+
activeSession.phase = "analysis";
|
|
334
|
+
return executeWorkflow(ctx);
|
|
335
|
+
}
|
|
336
|
+
activeSession.clarificationQuestions.filter((q) => q.answered).length;
|
|
337
|
+
const unansweredQuestions = activeSession.clarificationQuestions.filter((q) => !q.answered);
|
|
338
|
+
if (unansweredQuestions.length > 0) {
|
|
339
|
+
const question = unansweredQuestions[0];
|
|
340
|
+
question.answer = input.trim();
|
|
341
|
+
question.answered = true;
|
|
342
|
+
activeSession.refinedRequirement = buildRefinedRequirement(activeSession);
|
|
343
|
+
const remaining = activeSession.clarificationQuestions.filter((q) => !q.answered);
|
|
344
|
+
if (remaining.length > 0) {
|
|
345
|
+
activeSession.clarityScore = calculateClarityScore(activeSession.clarificationQuestions);
|
|
346
|
+
const lines = [];
|
|
347
|
+
lines.push(chalk9__default.default.green(" \u2713 \u5DF2\u8BB0\u5F55"));
|
|
348
|
+
lines.push("");
|
|
349
|
+
lines.push(chalk9__default.default.yellow(" \u7EE7\u7EED\u56DE\u7B54\uFF1A"));
|
|
350
|
+
for (let i = 0; i < Math.min(remaining.length, 3); i++) {
|
|
351
|
+
const q = remaining[i];
|
|
352
|
+
lines.push(chalk9__default.default.white(` ${i + 1}. ${q.question}`));
|
|
353
|
+
}
|
|
354
|
+
lines.push("");
|
|
355
|
+
lines.push(chalk9__default.default.gray(' \u8F93\u5165\u56DE\u7B54\uFF0C\u6216 "done" \u8DF3\u8FC7'));
|
|
356
|
+
return { output: lines.join("\n") };
|
|
357
|
+
}
|
|
358
|
+
activeSession.clarityScore = 1;
|
|
359
|
+
activeSession.phase = "analysis";
|
|
360
|
+
return executeWorkflow(ctx);
|
|
361
|
+
}
|
|
362
|
+
activeSession.phase = "analysis";
|
|
363
|
+
return executeWorkflow(ctx);
|
|
364
|
+
}
|
|
233
365
|
if (activeSession.phase === "spec") {
|
|
234
366
|
if (trimmed === "y" || trimmed === "yes" || trimmed === "\u786E\u8BA4") {
|
|
235
367
|
activeSession.phase = "tdd";
|
|
236
368
|
return executeWorkflow(ctx);
|
|
237
369
|
}
|
|
238
370
|
if (trimmed === "n" || trimmed === "no" || trimmed === "\u91CD\u65B0") {
|
|
239
|
-
activeSession.bddScenarios = generateBDDScenarios(
|
|
240
|
-
|
|
371
|
+
activeSession.bddScenarios = generateBDDScenarios(
|
|
372
|
+
activeSession.refinedRequirement,
|
|
373
|
+
activeSession.context,
|
|
374
|
+
activeSession.clarificationQuestions
|
|
375
|
+
);
|
|
376
|
+
activeSession.specItems = generateSpecItems(
|
|
377
|
+
activeSession.refinedRequirement,
|
|
378
|
+
activeSession.context,
|
|
379
|
+
activeSession.bddScenarios,
|
|
380
|
+
activeSession.clarificationQuestions
|
|
381
|
+
);
|
|
241
382
|
const specPath = await saveSpecFile(ctx.options.workingDirectory, activeSession);
|
|
242
383
|
return {
|
|
243
384
|
output: chalk9__default.default.cyan("\u{1F504} \u89C4\u683C\u5DF2\u91CD\u65B0\u751F\u6210") + chalk9__default.default.gray(`
|
|
@@ -252,24 +393,347 @@ async function handleWorkflowInput(input, ctx) {
|
|
|
252
393
|
}
|
|
253
394
|
}
|
|
254
395
|
if (activeSession.phase === "review") {
|
|
255
|
-
if (trimmed === "
|
|
396
|
+
if (trimmed === "pass" || trimmed === "\u901A\u8FC7" || trimmed === "\u5F3A\u5236\u901A\u8FC7") {
|
|
256
397
|
await archiveWorkflow(ctx.options.workingDirectory);
|
|
257
|
-
const summary = activeSession.
|
|
398
|
+
const summary = activeSession.refinedRequirement;
|
|
258
399
|
activeSession = null;
|
|
259
400
|
return {
|
|
260
401
|
output: chalk9__default.default.green("\u2713 \u5DE5\u4F5C\u6D41\u5DF2\u5B8C\u6210") + chalk9__default.default.gray(`
|
|
261
|
-
\u9700\u6C42: ${summary}`) + chalk9__default.default.cyan("\n\n\u4F7F\u7528 /new <\u9700\u6C42> \u5F00\u59CB\u65B0\u7684\u5DE5\u4F5C\u6D41")
|
|
402
|
+
\u9700\u6C42: ${summary.slice(0, 60)}${summary.length > 60 ? "..." : ""}`) + chalk9__default.default.cyan("\n\n\u4F7F\u7528 /new <\u9700\u6C42> \u5F00\u59CB\u65B0\u7684\u5DE5\u4F5C\u6D41")
|
|
262
403
|
};
|
|
263
404
|
}
|
|
264
|
-
if (trimmed === "
|
|
405
|
+
if (trimmed === "y" || trimmed === "yes" || trimmed === "\u91CD\u65B0\u5BA1\u6838" || trimmed === "retry") {
|
|
406
|
+
return executeWorkflow(ctx);
|
|
407
|
+
}
|
|
408
|
+
if (trimmed === "n" || trimmed === "no" || trimmed === "\u56DE\u9000" || trimmed === "rollback") {
|
|
265
409
|
activeSession.phase = "spec";
|
|
410
|
+
return executeWorkflow(ctx);
|
|
411
|
+
}
|
|
412
|
+
if (trimmed === "fix" || trimmed === "\u4FEE\u590D") {
|
|
266
413
|
return {
|
|
267
|
-
output: chalk9__default.default.yellow("\
|
|
414
|
+
output: chalk9__default.default.yellow("\u{1F4DD} \u8BF7\u624B\u52A8\u4FEE\u590D\u4EE3\u7801\u95EE\u9898") + chalk9__default.default.gray("\n\u4FEE\u590D\u5B8C\u6210\u540E\u8F93\u5165 y \u91CD\u65B0\u5BA1\u6838") + chalk9__default.default.gray("\n\u6216\u8F93\u5165 n \u56DE\u9000\u5230\u89C4\u683C\u9636\u6BB5")
|
|
268
415
|
};
|
|
269
416
|
}
|
|
270
417
|
}
|
|
271
418
|
return null;
|
|
272
419
|
}
|
|
420
|
+
function analyzeRequirementClarity(requirement, context) {
|
|
421
|
+
const questions = [];
|
|
422
|
+
let score = 0.5;
|
|
423
|
+
if (requirement.length < 10) {
|
|
424
|
+
score -= 0.2;
|
|
425
|
+
questions.push({
|
|
426
|
+
id: "q-length",
|
|
427
|
+
question: "\u9700\u6C42\u63CF\u8FF0\u8F83\u77ED\uFF0C\u80FD\u5426\u8BE6\u7EC6\u8BF4\u660E\u5177\u4F53\u8981\u5B9E\u73B0\u4EC0\u4E48\u529F\u80FD\uFF1F",
|
|
428
|
+
category: "scope",
|
|
429
|
+
answered: false
|
|
430
|
+
});
|
|
431
|
+
} else if (requirement.length >= 50) {
|
|
432
|
+
score += 0.1;
|
|
433
|
+
}
|
|
434
|
+
const actionKeywords = ["\u5B9E\u73B0", "\u6DFB\u52A0", "\u4FEE\u6539", "\u5220\u9664", "\u4F18\u5316", "\u4FEE\u590D", "\u91CD\u6784", "\u5F00\u53D1", "\u521B\u5EFA", "\u8BBE\u8BA1"];
|
|
435
|
+
const hasAction = actionKeywords.some((kw) => requirement.includes(kw));
|
|
436
|
+
if (!hasAction) {
|
|
437
|
+
score -= 0.15;
|
|
438
|
+
questions.push({
|
|
439
|
+
id: "q-action",
|
|
440
|
+
question: "\u8FD9\u662F\u4E00\u4E2A\u65B0\u529F\u80FD\u3001\u4FEE\u6539\u8FD8\u662F\u4FEE\u590D\uFF1F\u8BF7\u8BF4\u660E\u5177\u4F53\u8981\u505A\u4EC0\u4E48\u3002",
|
|
441
|
+
category: "scope",
|
|
442
|
+
answered: false
|
|
443
|
+
});
|
|
444
|
+
} else {
|
|
445
|
+
score += 0.1;
|
|
446
|
+
}
|
|
447
|
+
if (requirement.match(/界面|页面|组件|按钮|表单|弹窗|布局|样式|UI/)) {
|
|
448
|
+
score += 0.1;
|
|
449
|
+
if (!requirement.match(/在.*页面|在.*位置|显示在|位于/)) {
|
|
450
|
+
questions.push({
|
|
451
|
+
id: "q-ui-position",
|
|
452
|
+
question: "\u8FD9\u4E2A\u529F\u80FD\u5E94\u8BE5\u653E\u5728\u54EA\u4E2A\u9875\u9762\u6216\u4F4D\u7F6E\uFF1F",
|
|
453
|
+
category: "ui",
|
|
454
|
+
answered: false
|
|
455
|
+
});
|
|
456
|
+
}
|
|
457
|
+
} else {
|
|
458
|
+
questions.push({
|
|
459
|
+
id: "q-ui-need",
|
|
460
|
+
question: "\u8FD9\u4E2A\u529F\u80FD\u9700\u8981\u7528\u6237\u754C\u9762\u5417\uFF1F\u5982\u679C\u9700\u8981\uFF0C\u5927\u6982\u957F\u4EC0\u4E48\u6837\uFF1F",
|
|
461
|
+
category: "ui",
|
|
462
|
+
answered: false
|
|
463
|
+
});
|
|
464
|
+
}
|
|
465
|
+
if (requirement.match(/数据|存储|保存|读取|API|接口|数据库|缓存/)) {
|
|
466
|
+
score += 0.1;
|
|
467
|
+
if (!requirement.match(/从.*获取|调用.*接口|读取.*数据|来源/)) {
|
|
468
|
+
questions.push({
|
|
469
|
+
id: "q-data-source",
|
|
470
|
+
question: "\u6570\u636E\u4ECE\u54EA\u91CC\u6765\uFF1F\u662F\u8C03\u7528API\u3001\u672C\u5730\u5B58\u50A8\u8FD8\u662F\u5176\u4ED6\u6765\u6E90\uFF1F",
|
|
471
|
+
category: "data",
|
|
472
|
+
answered: false
|
|
473
|
+
});
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
if (requirement.match(/点击|输入|选择|拖动|滑动|交互|操作/)) {
|
|
477
|
+
score += 0.1;
|
|
478
|
+
} else {
|
|
479
|
+
if (hasAction && requirement.match(/功能|特性|模块/)) {
|
|
480
|
+
questions.push({
|
|
481
|
+
id: "q-interaction",
|
|
482
|
+
question: "\u7528\u6237\u5982\u4F55\u64CD\u4F5C\u8FD9\u4E2A\u529F\u80FD\uFF1F\u6709\u4EC0\u4E48\u4EA4\u4E92\u6D41\u7A0B\uFF1F",
|
|
483
|
+
category: "interaction",
|
|
484
|
+
answered: false
|
|
485
|
+
});
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
if (requirement.match(/异常|错误|失败|边界|特殊情况|空值|验证/)) {
|
|
489
|
+
score += 0.15;
|
|
490
|
+
} else {
|
|
491
|
+
if (requirement.match(/功能|输入|表单|数据/)) {
|
|
492
|
+
questions.push({
|
|
493
|
+
id: "q-edge",
|
|
494
|
+
question: "\u6709\u4EC0\u4E48\u7279\u6B8A\u60C5\u51B5\u6216\u8FB9\u754C\u6761\u4EF6\u9700\u8981\u5904\u7406\uFF1F\u6BD4\u5982\u8F93\u5165\u4E3A\u7A7A\u3001\u6570\u636E\u52A0\u8F7D\u5931\u8D25\u7B49\u3002",
|
|
495
|
+
category: "edge",
|
|
496
|
+
answered: false
|
|
497
|
+
});
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
if (requirement.match(/https?:\/\/|参考|参照|类似/)) {
|
|
501
|
+
score += 0.15;
|
|
502
|
+
}
|
|
503
|
+
if (context.framework) {
|
|
504
|
+
score += 0.05;
|
|
505
|
+
}
|
|
506
|
+
const limitedQuestions = questions.slice(0, 5);
|
|
507
|
+
score = Math.max(0, Math.min(1, score));
|
|
508
|
+
return { score, questions: limitedQuestions };
|
|
509
|
+
}
|
|
510
|
+
function calculateClarityScore(questions) {
|
|
511
|
+
const answered = questions.filter((q) => q.answered).length;
|
|
512
|
+
if (questions.length === 0) return 1;
|
|
513
|
+
return 0.5 + answered / questions.length * 0.5;
|
|
514
|
+
}
|
|
515
|
+
function buildRefinedRequirement(session) {
|
|
516
|
+
const parts = [session.requirement];
|
|
517
|
+
for (const q of session.clarificationQuestions) {
|
|
518
|
+
if (q.answered && q.answer) {
|
|
519
|
+
parts.push(`
|
|
520
|
+
\u3010${getCategoryLabel(q.category)}\u3011${q.answer}`);
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
return parts.join("");
|
|
524
|
+
}
|
|
525
|
+
function getCategoryLabel(category) {
|
|
526
|
+
const labels = {
|
|
527
|
+
scope: "\u8303\u56F4",
|
|
528
|
+
ui: "\u754C\u9762",
|
|
529
|
+
data: "\u6570\u636E",
|
|
530
|
+
interaction: "\u4EA4\u4E92",
|
|
531
|
+
edge: "\u8FB9\u754C",
|
|
532
|
+
tech: "\u6280\u672F"
|
|
533
|
+
};
|
|
534
|
+
return labels[category] || category;
|
|
535
|
+
}
|
|
536
|
+
async function executeDevelopment(ctx, session) {
|
|
537
|
+
const workingDir = ctx.options.workingDirectory;
|
|
538
|
+
const files = [];
|
|
539
|
+
try {
|
|
540
|
+
const systemPrompt = buildDevelopmentPrompt(session);
|
|
541
|
+
const messages = [
|
|
542
|
+
{
|
|
543
|
+
role: "system",
|
|
544
|
+
content: `\u4F60\u662F\u4E00\u4E2A\u4E13\u4E1A\u7684\u524D\u7AEF\u5F00\u53D1\u5DE5\u7A0B\u5E08\u3002\u8BF7\u6839\u636E\u9700\u6C42\u89C4\u683C\u751F\u6210\u4EE3\u7801\u5B9E\u73B0\u3002
|
|
545
|
+
|
|
546
|
+
\u8981\u6C42\uFF1A
|
|
547
|
+
1. \u751F\u6210\u5B8C\u6574\u3001\u53EF\u8FD0\u884C\u7684\u4EE3\u7801
|
|
548
|
+
2. \u9075\u5FAA\u9879\u76EE\u73B0\u6709\u7684\u4EE3\u7801\u98CE\u683C\u548C\u89C4\u8303
|
|
549
|
+
3. \u4F7F\u7528\u9879\u76EE\u6307\u5B9A\u7684\u6280\u672F\u6808
|
|
550
|
+
4. \u4EE3\u7801\u8981\u6709\u9002\u5F53\u7684\u6CE8\u91CA
|
|
551
|
+
5. \u8FD4\u56DE\u683C\u5F0F\uFF1A\u6BCF\u4E2A\u6587\u4EF6\u7528 \`\`\`filename \u4EE3\u7801 \`\`\` \u5305\u88F9
|
|
552
|
+
|
|
553
|
+
\u9879\u76EE\u4FE1\u606F\uFF1A
|
|
554
|
+
- \u540D\u79F0: ${session.context?.name}
|
|
555
|
+
- \u6846\u67B6: ${session.context?.framework || "\u672A\u6307\u5B9A"}
|
|
556
|
+
- \u6280\u672F\u6808: ${session.context?.techStack.join(", ") || "\u672A\u6307\u5B9A"}
|
|
557
|
+
|
|
558
|
+
${session.context?.devStandards ? `\u5F00\u53D1\u89C4\u8303\uFF1A
|
|
559
|
+
${session.context.devStandards.slice(0, 2e3)}` : ""}`
|
|
560
|
+
},
|
|
561
|
+
{
|
|
562
|
+
role: "user",
|
|
563
|
+
content: systemPrompt
|
|
564
|
+
}
|
|
565
|
+
];
|
|
566
|
+
const response = await ctx.modelService.sendMessage(messages, {
|
|
567
|
+
temperature: 0.3,
|
|
568
|
+
maxTokens: 8e3,
|
|
569
|
+
agent: "frontend-dev"
|
|
570
|
+
});
|
|
571
|
+
const codeBlocks = parseCodeBlocks(response.content);
|
|
572
|
+
for (const block of codeBlocks) {
|
|
573
|
+
const filePath = path4__namespace.join(workingDir, block.filename);
|
|
574
|
+
const dir = path4__namespace.dirname(filePath);
|
|
575
|
+
await fs4__namespace.mkdir(dir, { recursive: true });
|
|
576
|
+
await fs4__namespace.writeFile(filePath, block.code, "utf-8");
|
|
577
|
+
files.push(block.filename);
|
|
578
|
+
}
|
|
579
|
+
if (files.length === 0) {
|
|
580
|
+
const implDir = path4__namespace.join(workingDir, "src", "features");
|
|
581
|
+
await fs4__namespace.mkdir(implDir, { recursive: true });
|
|
582
|
+
const featureName = session.specItems[0]?.title || "feature";
|
|
583
|
+
const fileName = `${featureName.replace(/[^a-zA-Z0-9]/g, "_")}.ts`;
|
|
584
|
+
const filePath = path4__namespace.join(implDir, fileName);
|
|
585
|
+
const stubCode = `/**
|
|
586
|
+
* ${session.requirement}
|
|
587
|
+
*
|
|
588
|
+
* TODO: \u6B64\u6587\u4EF6\u7531 AI \u81EA\u52A8\u751F\u6210\uFF0C\u8BF7\u6839\u636E\u9700\u6C42\u5B8C\u5584\u5B9E\u73B0
|
|
589
|
+
*/
|
|
590
|
+
|
|
591
|
+
export function ${featureName.replace(/[^a-zA-Z0-9]/g, "")}() {
|
|
592
|
+
// TODO: \u5B9E\u73B0\u529F\u80FD
|
|
593
|
+
console.log('${featureName} - \u5F85\u5B9E\u73B0');
|
|
594
|
+
}
|
|
595
|
+
`;
|
|
596
|
+
await fs4__namespace.writeFile(filePath, stubCode, "utf-8");
|
|
597
|
+
files.push(`src/features/${fileName}`);
|
|
598
|
+
}
|
|
599
|
+
return { success: true, files };
|
|
600
|
+
} catch (error) {
|
|
601
|
+
return {
|
|
602
|
+
success: false,
|
|
603
|
+
files: [],
|
|
604
|
+
error: error.message
|
|
605
|
+
};
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
function buildDevelopmentPrompt(session) {
|
|
609
|
+
const lines = [];
|
|
610
|
+
lines.push("## \u9700\u6C42\u63CF\u8FF0");
|
|
611
|
+
lines.push(session.refinedRequirement);
|
|
612
|
+
lines.push("");
|
|
613
|
+
lines.push("## BDD \u573A\u666F");
|
|
614
|
+
for (const scenario of session.bddScenarios) {
|
|
615
|
+
lines.push(`### ${scenario.feature}`);
|
|
616
|
+
for (const s of scenario.scenarios) {
|
|
617
|
+
lines.push(`- ${s.name}`);
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
lines.push("");
|
|
621
|
+
lines.push("## \u4EFB\u52A1\u5217\u8868");
|
|
622
|
+
for (const item of session.specItems) {
|
|
623
|
+
lines.push(`- [${item.id}] ${item.title}: ${item.description}`);
|
|
624
|
+
}
|
|
625
|
+
lines.push("");
|
|
626
|
+
lines.push("\u8BF7\u6839\u636E\u4EE5\u4E0A\u9700\u6C42\u89C4\u683C\u751F\u6210\u4EE3\u7801\u5B9E\u73B0\u3002");
|
|
627
|
+
return lines.join("\n");
|
|
628
|
+
}
|
|
629
|
+
function parseCodeBlocks(content) {
|
|
630
|
+
const blocks = [];
|
|
631
|
+
const regex = /```(\S+)\n([\s\S]*?)```/g;
|
|
632
|
+
let match;
|
|
633
|
+
while ((match = regex.exec(content)) !== null) {
|
|
634
|
+
const filename = match[1];
|
|
635
|
+
const code = match[2].trim();
|
|
636
|
+
if (["text", "json", "markdown", "md"].includes(filename.toLowerCase())) {
|
|
637
|
+
continue;
|
|
638
|
+
}
|
|
639
|
+
blocks.push({ filename, code });
|
|
640
|
+
}
|
|
641
|
+
return blocks;
|
|
642
|
+
}
|
|
643
|
+
async function executeReview(ctx, session) {
|
|
644
|
+
const workingDir = ctx.options.workingDirectory;
|
|
645
|
+
const issues = [];
|
|
646
|
+
const suggestions = [];
|
|
647
|
+
try {
|
|
648
|
+
const codeContents = [];
|
|
649
|
+
for (const file of session.implFiles) {
|
|
650
|
+
try {
|
|
651
|
+
const content = await fs4__namespace.readFile(path4__namespace.join(workingDir, file), "utf-8");
|
|
652
|
+
codeContents.push(`// ${file}
|
|
653
|
+
${content}`);
|
|
654
|
+
} catch {
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
const testContents = [];
|
|
658
|
+
for (const file of session.testFiles) {
|
|
659
|
+
try {
|
|
660
|
+
const content = await fs4__namespace.readFile(path4__namespace.join(workingDir, file), "utf-8");
|
|
661
|
+
testContents.push(`// ${file}
|
|
662
|
+
${content}`);
|
|
663
|
+
} catch {
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
const messages = [
|
|
667
|
+
{
|
|
668
|
+
role: "system",
|
|
669
|
+
content: `\u4F60\u662F\u4E00\u4E2A\u4E13\u4E1A\u7684\u4EE3\u7801\u5BA1\u6838\u4E13\u5BB6\u3002\u8BF7\u5BA1\u6838\u4EE5\u4E0B\u4EE3\u7801\u5B9E\u73B0\u662F\u5426\u7B26\u5408\u9700\u6C42\u89C4\u683C\u3002
|
|
670
|
+
|
|
671
|
+
\u5BA1\u6838\u6807\u51C6\uFF1A
|
|
672
|
+
1. \u4EE3\u7801\u662F\u5426\u6B63\u786E\u5B9E\u73B0\u4E86\u9700\u6C42\u89C4\u683C\u4E2D\u7684\u529F\u80FD
|
|
673
|
+
2. \u4EE3\u7801\u8D28\u91CF\uFF08\u53EF\u8BFB\u6027\u3001\u53EF\u7EF4\u62A4\u6027\uFF09
|
|
674
|
+
3. \u6F5C\u5728\u7684 bug \u548C\u8FB9\u754C\u60C5\u51B5\u5904\u7406
|
|
675
|
+
4. \u4EE3\u7801\u98CE\u683C\u662F\u5426\u7B26\u5408\u9879\u76EE\u89C4\u8303
|
|
676
|
+
5. \u6D4B\u8BD5\u8986\u76D6\u662F\u5426\u5145\u5206
|
|
677
|
+
|
|
678
|
+
\u8FD4\u56DE\u683C\u5F0F\uFF1A
|
|
679
|
+
- \u5982\u679C\u901A\u8FC7\u5BA1\u6838\uFF0C\u8FD4\u56DE "\u5BA1\u6838\u901A\u8FC7" \u5E76\u5217\u51FA\u6539\u8FDB\u5EFA\u8BAE
|
|
680
|
+
- \u5982\u679C\u4E0D\u901A\u8FC7\uFF0C\u5217\u51FA\u5177\u4F53\u95EE\u9898
|
|
681
|
+
|
|
682
|
+
\u9879\u76EE\u4FE1\u606F\uFF1A
|
|
683
|
+
- \u6846\u67B6: ${session.context?.framework || "\u672A\u6307\u5B9A"}
|
|
684
|
+
- \u6280\u672F\u6808: ${session.context?.techStack.join(", ") || "\u672A\u6307\u5B9A"}
|
|
685
|
+
|
|
686
|
+
${session.context?.devStandards ? `\u5F00\u53D1\u89C4\u8303\uFF1A
|
|
687
|
+
${session.context.devStandards.slice(0, 1e3)}` : ""}`
|
|
688
|
+
},
|
|
689
|
+
{
|
|
690
|
+
role: "user",
|
|
691
|
+
content: `## \u9700\u6C42\u89C4\u683C
|
|
692
|
+
${session.refinedRequirement}
|
|
693
|
+
|
|
694
|
+
## \u4EFB\u52A1\u5217\u8868
|
|
695
|
+
${session.specItems.map((item) => `- [${item.id}] ${item.title}`).join("\n")}
|
|
696
|
+
|
|
697
|
+
## \u5B9E\u73B0\u4EE3\u7801
|
|
698
|
+
${codeContents.join("\n\n") || "\uFF08\u65E0\u4EE3\u7801\u6587\u4EF6\uFF09"}
|
|
699
|
+
|
|
700
|
+
## \u6D4B\u8BD5\u4EE3\u7801
|
|
701
|
+
${testContents.join("\n\n") || "\uFF08\u65E0\u6D4B\u8BD5\u6587\u4EF6\uFF09"}
|
|
702
|
+
|
|
703
|
+
\u8BF7\u5BA1\u6838\u4EE5\u4E0A\u4EE3\u7801\u5B9E\u73B0\u3002`
|
|
704
|
+
}
|
|
705
|
+
];
|
|
706
|
+
const response = await ctx.modelService.sendMessage(messages, {
|
|
707
|
+
temperature: 0.2,
|
|
708
|
+
maxTokens: 2e3,
|
|
709
|
+
agent: "code-reviewer"
|
|
710
|
+
});
|
|
711
|
+
const result = response.content;
|
|
712
|
+
const passed = result.includes("\u5BA1\u6838\u901A\u8FC7") || result.includes("\u901A\u8FC7") || !result.includes("\u4E0D\u901A\u8FC7");
|
|
713
|
+
const issueMatches = result.match(/问题[::]\s*([\s\S]*?)(?=建议|$)/i);
|
|
714
|
+
if (issueMatches) {
|
|
715
|
+
const issueList = issueMatches[1].split(/[\n-]/).filter((s) => s.trim());
|
|
716
|
+
issues.push(...issueList.map((s) => s.trim()).filter((s) => s));
|
|
717
|
+
}
|
|
718
|
+
const suggestionMatches = result.match(/建议[::]\s*([\s\S]*?)$/i);
|
|
719
|
+
if (suggestionMatches) {
|
|
720
|
+
const suggestionList = suggestionMatches[1].split(/[\n-]/).filter((s) => s.trim());
|
|
721
|
+
suggestions.push(...suggestionList.map((s) => s.trim()).filter((s) => s));
|
|
722
|
+
}
|
|
723
|
+
if (issues.length === 0 && !passed) {
|
|
724
|
+
const lines = result.split("\n").filter((l) => l.includes("\u95EE\u9898") || l.includes("\u9519\u8BEF") || l.includes("\u7F3A\u9677"));
|
|
725
|
+
issues.push(...lines.map((l) => l.replace(/^[-*]\s*/, "").trim()).filter((l) => l));
|
|
726
|
+
}
|
|
727
|
+
if (suggestions.length === 0) {
|
|
728
|
+
const lines = result.split("\n").filter((l) => l.includes("\u5EFA\u8BAE") || l.includes("\u6539\u8FDB") || l.includes("\u4F18\u5316"));
|
|
729
|
+
suggestions.push(...lines.map((l) => l.replace(/^[-*]\s*/, "").trim()).filter((l) => l));
|
|
730
|
+
}
|
|
731
|
+
return { passed, issues, suggestions };
|
|
732
|
+
} catch (error) {
|
|
733
|
+
suggestions.push(`\u5BA1\u6838\u8FC7\u7A0B\u51FA\u9519: ${error.message}`);
|
|
734
|
+
return { passed: true, issues, suggestions };
|
|
735
|
+
}
|
|
736
|
+
}
|
|
273
737
|
async function readProjectContext(workingDir) {
|
|
274
738
|
const context = {
|
|
275
739
|
name: path4__namespace.basename(workingDir),
|
|
@@ -351,8 +815,11 @@ function analyzeComplexity(requirement, context) {
|
|
|
351
815
|
if (!context.framework) score += 0.5;
|
|
352
816
|
return Math.max(1, Math.min(10, Math.round(score)));
|
|
353
817
|
}
|
|
354
|
-
function generateBDDScenarios(requirement, context) {
|
|
818
|
+
function generateBDDScenarios(requirement, context, questions) {
|
|
355
819
|
const scenarios = [];
|
|
820
|
+
questions.find((q) => q.category === "ui" && q.answered)?.answer;
|
|
821
|
+
const interactionAnswer = questions.find((q) => q.category === "interaction" && q.answered)?.answer;
|
|
822
|
+
const edgeAnswer = questions.find((q) => q.category === "edge" && q.answered)?.answer;
|
|
356
823
|
const features = extractFeatures(requirement);
|
|
357
824
|
for (const feature of features) {
|
|
358
825
|
const scenario = {
|
|
@@ -366,12 +833,20 @@ function generateBDDScenarios(requirement, context) {
|
|
|
366
833
|
when: [`\u7528\u6237\u6267\u884C "${feature.title}" \u64CD\u4F5C`],
|
|
367
834
|
then: [`\u7CFB\u7EDF\u5E94\u6B63\u786E\u5904\u7406\u5E76\u8FD4\u56DE\u9884\u671F\u7ED3\u679C`]
|
|
368
835
|
});
|
|
369
|
-
if (
|
|
836
|
+
if (interactionAnswer) {
|
|
370
837
|
scenario.scenarios.push({
|
|
371
|
-
name: `\
|
|
372
|
-
given: [`\u7528\u6237\u8FDB\u5165\
|
|
373
|
-
when: [`\u7528\u6237\
|
|
374
|
-
then: [`\u7CFB\u7EDF\u5E94\
|
|
838
|
+
name: `\u4EA4\u4E92\u6D41\u7A0B: \u7528\u6237\u64CD\u4F5C`,
|
|
839
|
+
given: [`\u7528\u6237\u8FDB\u5165\u529F\u80FD\u754C\u9762`],
|
|
840
|
+
when: [`\u7528\u6237\u6309\u7167\u4EE5\u4E0B\u6D41\u7A0B\u64CD\u4F5C: ${interactionAnswer}`],
|
|
841
|
+
then: [`\u7CFB\u7EDF\u54CD\u5E94\u5E76\u5B8C\u6210\u529F\u80FD`]
|
|
842
|
+
});
|
|
843
|
+
}
|
|
844
|
+
if (feature.hasInput || edgeAnswer) {
|
|
845
|
+
scenario.scenarios.push({
|
|
846
|
+
name: `\u8FB9\u754C\u60C5\u51B5: \u5F02\u5E38\u5904\u7406`,
|
|
847
|
+
given: [`\u7528\u6237\u8FDB\u5165\u529F\u80FD\u754C\u9762`],
|
|
848
|
+
when: [`\u53D1\u751F\u5F02\u5E38\u60C5\u51B5${edgeAnswer ? `: ${edgeAnswer}` : ""}`],
|
|
849
|
+
then: [`\u7CFB\u7EDF\u5E94\u6B63\u786E\u5904\u7406\u5F02\u5E38\u5E76\u7ED9\u51FA\u63D0\u793A`]
|
|
375
850
|
});
|
|
376
851
|
}
|
|
377
852
|
scenarios.push(scenario);
|
|
@@ -418,7 +893,7 @@ function extractFeatures(requirement) {
|
|
|
418
893
|
}
|
|
419
894
|
return features;
|
|
420
895
|
}
|
|
421
|
-
function generateSpecItems(requirement, context, bddScenarios) {
|
|
896
|
+
function generateSpecItems(requirement, context, bddScenarios, questions) {
|
|
422
897
|
const items = [];
|
|
423
898
|
let id = 1;
|
|
424
899
|
for (const scenario of bddScenarios) {
|
|
@@ -455,11 +930,33 @@ function formatSpecFile(session) {
|
|
|
455
930
|
lines.push(`# \u9700\u6C42\u89C4\u683C: ${session.requirement.slice(0, 50)}`);
|
|
456
931
|
lines.push("");
|
|
457
932
|
lines.push(`> \u53D8\u66F4ID: ${session.id}`);
|
|
933
|
+
lines.push(`> \u9700\u6C42\u6E05\u6670\u5EA6: ${Math.round(session.clarityScore * 100)}%`);
|
|
458
934
|
lines.push(`> \u590D\u6742\u5EA6: ${session.complexity}/10`);
|
|
459
935
|
lines.push(`> \u751F\u6210\u65F6\u95F4: ${session.createdAt.toISOString()}`);
|
|
460
936
|
lines.push("");
|
|
461
937
|
lines.push("---");
|
|
462
938
|
lines.push("");
|
|
939
|
+
if (session.refinedRequirement !== session.requirement) {
|
|
940
|
+
lines.push("## \u9700\u6C42\u8BE6\u60C5");
|
|
941
|
+
lines.push("");
|
|
942
|
+
lines.push(session.refinedRequirement);
|
|
943
|
+
lines.push("");
|
|
944
|
+
lines.push("---");
|
|
945
|
+
lines.push("");
|
|
946
|
+
}
|
|
947
|
+
if (session.clarificationQuestions.some((q) => q.answered)) {
|
|
948
|
+
lines.push("## \u9700\u6C42\u6F84\u6E05");
|
|
949
|
+
lines.push("");
|
|
950
|
+
for (const q of session.clarificationQuestions) {
|
|
951
|
+
if (q.answered) {
|
|
952
|
+
lines.push(`**Q: ${q.question}**`);
|
|
953
|
+
lines.push(`A: ${q.answer}`);
|
|
954
|
+
lines.push("");
|
|
955
|
+
}
|
|
956
|
+
}
|
|
957
|
+
lines.push("---");
|
|
958
|
+
lines.push("");
|
|
959
|
+
}
|
|
463
960
|
lines.push("## BDD \u573A\u666F");
|
|
464
961
|
lines.push("");
|
|
465
962
|
for (const scenario of session.bddScenarios) {
|
|
@@ -523,11 +1020,17 @@ async function archiveWorkflow(workingDir) {
|
|
|
523
1020
|
const content = `# \u5F52\u6863: ${activeSession.requirement.slice(0, 50)}
|
|
524
1021
|
|
|
525
1022
|
> \u5F52\u6863\u65F6\u95F4: ${(/* @__PURE__ */ new Date()).toISOString()}
|
|
1023
|
+
> \u9700\u6C42\u6E05\u6670\u5EA6: ${Math.round(activeSession.clarityScore * 100)}%
|
|
526
1024
|
> \u590D\u6742\u5EA6: ${activeSession.complexity}/10
|
|
527
1025
|
|
|
1026
|
+
## \u9700\u6C42\u8BE6\u60C5
|
|
1027
|
+
|
|
1028
|
+
${activeSession.refinedRequirement}
|
|
1029
|
+
|
|
528
1030
|
## \u5B8C\u6210\u60C5\u51B5
|
|
529
1031
|
|
|
530
1032
|
- [x] \u9879\u76EE\u4E0A\u4E0B\u6587\u83B7\u53D6
|
|
1033
|
+
- [x] \u9700\u6C42\u6F84\u6E05
|
|
531
1034
|
- [x] \u590D\u6742\u5EA6\u8BC4\u4F30
|
|
532
1035
|
- [x] BDD \u573A\u666F\u62C6\u89E3
|
|
533
1036
|
- [x] OpenSpec \u89C4\u683C
|
|
@@ -554,6 +1057,7 @@ function generateComplexityBar(score) {
|
|
|
554
1057
|
function getPhaseLabel(phase) {
|
|
555
1058
|
const labels = {
|
|
556
1059
|
context: "\u9879\u76EE\u4E0A\u4E0B\u6587\u83B7\u53D6",
|
|
1060
|
+
clarify: "\u9700\u6C42\u6F84\u6E05",
|
|
557
1061
|
analysis: "\u590D\u6742\u5EA6\u8BC4\u4F30",
|
|
558
1062
|
bdd: "BDD \u573A\u666F\u62C6\u89E3",
|
|
559
1063
|
spec: "OpenSpec \u89C4\u683C",
|
|
@@ -569,12 +1073,13 @@ function getActiveSession() {
|
|
|
569
1073
|
function clearActiveSession() {
|
|
570
1074
|
activeSession = null;
|
|
571
1075
|
}
|
|
572
|
-
var MAX_FILE_SIZE2, COMPLEXITY_THRESHOLD, activeSession, new_default;
|
|
1076
|
+
var MAX_FILE_SIZE2, COMPLEXITY_THRESHOLD, CLARITY_THRESHOLD, activeSession, new_default;
|
|
573
1077
|
var init_new = __esm({
|
|
574
1078
|
"src/commands/new.ts"() {
|
|
575
1079
|
init_cjs_shims();
|
|
576
1080
|
MAX_FILE_SIZE2 = 1024 * 1024;
|
|
577
1081
|
COMPLEXITY_THRESHOLD = 6;
|
|
1082
|
+
CLARITY_THRESHOLD = 0.6;
|
|
578
1083
|
activeSession = null;
|
|
579
1084
|
new_default = handleNew;
|
|
580
1085
|
}
|