@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/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 === "spec") {
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/7: \u9879\u76EE\u4E0A\u4E0B\u6587\u83B7\u53D6 \u2501\u2501\u2501"));
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 2/7: \u590D\u6742\u5EA6\u8BC4\u4F30 \u2501\u2501\u2501"));
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(activeSession.requirement, activeSession.context);
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 3/7: BDD \u573A\u666F\u62C6\u89E3 \u2501\u2501\u2501"));
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(activeSession.requirement, activeSession.context);
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 4/7: OpenSpec \u89C4\u683C \u2501\u2501\u2501"));
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(activeSession.requirement, activeSession.context, activeSession.bddScenarios);
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 5/7: TDD \u6D4B\u8BD5\u751F\u6210 \u2501\u2501\u2501"));
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 6/7: \u5F00\u53D1\u5B9E\u73B0 \u2501\u2501\u2501"));
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{1F4DD} \u5F00\u53D1\u9636\u6BB5"));
206
- lines.push(chalk9__default.default.gray(" \u8BF7\u8C03\u7528 $frontend-dev \u6267\u884C\u5F00\u53D1\u4EFB\u52A1"));
207
- lines.push(chalk9__default.default.gray(" \u6216\u624B\u52A8\u5B9E\u73B0\u4EE3\u7801\u540E\u8F93\u5165 continue \u7EE7\u7EED"));
208
- return { output: lines.join("\n") };
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 7/7: \u4EE3\u7801\u5BA1\u6838 \u2501\u2501\u2501"));
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\u9636\u6BB5"));
215
- lines.push(chalk9__default.default.gray(" \u8BF7\u8C03\u7528 $code-reviewer \u6267\u884C\u4EE3\u7801\u5BA1\u6838"));
216
- lines.push(chalk9__default.default.gray(" \u6216\u8F93\u5165 review \u5B8C\u6210\u5BA1\u6838"));
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(activeSession.requirement, activeSession.context);
240
- activeSession.specItems = generateSpecItems(activeSession.requirement, activeSession.context, activeSession.bddScenarios);
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 === "review" || trimmed === "\u5BA1\u6838" || trimmed === "pass" || trimmed === "\u901A\u8FC7") {
396
+ if (trimmed === "pass" || trimmed === "\u901A\u8FC7" || trimmed === "\u5F3A\u5236\u901A\u8FC7") {
256
397
  await archiveWorkflow(ctx.options.workingDirectory);
257
- const summary = activeSession.requirement;
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 === "fail" || trimmed === "\u5931\u8D25" || trimmed === "reject" || trimmed === "\u62D2\u7EDD") {
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("\u21A9\uFE0F \u5BA1\u6838\u672A\u901A\u8FC7\uFF0C\u56DE\u9000\u5230\u89C4\u683C\u9636\u6BB5") + chalk9__default.default.gray("\n\u8BF7\u91CD\u65B0\u786E\u8BA4\u6216\u4FEE\u6539\u89C4\u683C") + chalk9__default.default.yellow("\n\n\u4F7F\u7528 y \u786E\u8BA4\uFF0Cn \u91CD\u65B0\u751F\u6210")
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 (feature.hasInput) {
836
+ if (interactionAnswer) {
370
837
  scenario.scenarios.push({
371
- name: `\u8FB9\u754C\u60C5\u51B5: \u8F93\u5165\u9A8C\u8BC1`,
372
- given: [`\u7528\u6237\u8FDB\u5165\u8F93\u5165\u754C\u9762`],
373
- when: [`\u7528\u6237\u8F93\u5165\u8FB9\u754C\u503C\u6216\u7A7A\u503C`],
374
- then: [`\u7CFB\u7EDF\u5E94\u6B63\u786E\u5904\u7406\u8FB9\u754C\u60C5\u51B5`]
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
  }