@nick848/sf-cli 1.0.10 → 1.0.11

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.d.mts CHANGED
@@ -408,7 +408,7 @@ interface CLIConfig {
408
408
  theme: 'light' | 'dark' | 'auto';
409
409
  }
410
410
  type WorkflowStep = 'explore' | 'new' | 'continue' | 'apply' | 'archive' | 'propose';
411
- type WorkflowPhase = 'context' | 'analysis' | 'bdd' | 'spec' | 'tdd' | 'develop' | 'review';
411
+ type WorkflowPhase = 'context' | 'clarify' | 'analysis' | 'bdd' | 'spec' | 'tdd' | 'develop' | 'review';
412
412
  type WorkflowType = 'complex' | 'simple';
413
413
  type WorkflowStatus = 'pending' | 'running' | 'completed' | 'failed' | 'cancelled';
414
414
  interface WorkflowState {
package/dist/index.d.ts CHANGED
@@ -408,7 +408,7 @@ interface CLIConfig {
408
408
  theme: 'light' | 'dark' | 'auto';
409
409
  }
410
410
  type WorkflowStep = 'explore' | 'new' | 'continue' | 'apply' | 'archive' | 'propose';
411
- type WorkflowPhase = 'context' | 'analysis' | 'bdd' | 'spec' | 'tdd' | 'develop' | 'review';
411
+ type WorkflowPhase = 'context' | 'clarify' | 'analysis' | 'bdd' | 'spec' | 'tdd' | 'develop' | 'review';
412
412
  type WorkflowType = 'complex' | 'simple';
413
413
  type WorkflowStatus = 'pending' | 'running' | 'completed' | 'failed' | 'cancelled';
414
414
  interface WorkflowState {
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,7 +248,7 @@ 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
253
  lines.push(chalk9__default.default.yellow(" \u{1F4DD} \u5F00\u53D1\u9636\u6BB5"));
206
254
  lines.push(chalk9__default.default.gray(" \u8BF7\u8C03\u7528 $frontend-dev \u6267\u884C\u5F00\u53D1\u4EFB\u52A1"));
@@ -209,7 +257,7 @@ async function executeWorkflow(ctx) {
209
257
  }
210
258
  if (activeSession.phase === "review") {
211
259
  lines.push("");
212
- lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5 7/7: \u4EE3\u7801\u5BA1\u6838 \u2501\u2501\u2501"));
260
+ lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5 8/8: \u4EE3\u7801\u5BA1\u6838 \u2501\u2501\u2501"));
213
261
  lines.push("");
214
262
  lines.push(chalk9__default.default.yellow(" \u{1F50D} \u4EE3\u7801\u5BA1\u6838\u9636\u6BB5"));
215
263
  lines.push(chalk9__default.default.gray(" \u8BF7\u8C03\u7528 $code-reviewer \u6267\u884C\u4EE3\u7801\u5BA1\u6838"));
@@ -230,14 +278,58 @@ async function handleWorkflowInput(input, ctx) {
230
278
  output: chalk9__default.default.yellow("\u2713 \u5DE5\u4F5C\u6D41\u5DF2\u53D6\u6D88")
231
279
  };
232
280
  }
281
+ if (activeSession.phase === "clarify") {
282
+ if (trimmed === "done" || trimmed === "\u5B8C\u6210" || trimmed === "\u8DF3\u8FC7" || trimmed === "skip") {
283
+ activeSession.refinedRequirement = buildRefinedRequirement(activeSession);
284
+ activeSession.phase = "analysis";
285
+ return executeWorkflow(ctx);
286
+ }
287
+ activeSession.clarificationQuestions.filter((q) => q.answered).length;
288
+ const unansweredQuestions = activeSession.clarificationQuestions.filter((q) => !q.answered);
289
+ if (unansweredQuestions.length > 0) {
290
+ const question = unansweredQuestions[0];
291
+ question.answer = input.trim();
292
+ question.answered = true;
293
+ activeSession.refinedRequirement = buildRefinedRequirement(activeSession);
294
+ const remaining = activeSession.clarificationQuestions.filter((q) => !q.answered);
295
+ if (remaining.length > 0) {
296
+ activeSession.clarityScore = calculateClarityScore(activeSession.clarificationQuestions);
297
+ const lines = [];
298
+ lines.push(chalk9__default.default.green(" \u2713 \u5DF2\u8BB0\u5F55"));
299
+ lines.push("");
300
+ lines.push(chalk9__default.default.yellow(" \u7EE7\u7EED\u56DE\u7B54\uFF1A"));
301
+ for (let i = 0; i < Math.min(remaining.length, 3); i++) {
302
+ const q = remaining[i];
303
+ lines.push(chalk9__default.default.white(` ${i + 1}. ${q.question}`));
304
+ }
305
+ lines.push("");
306
+ lines.push(chalk9__default.default.gray(' \u8F93\u5165\u56DE\u7B54\uFF0C\u6216 "done" \u8DF3\u8FC7'));
307
+ return { output: lines.join("\n") };
308
+ }
309
+ activeSession.clarityScore = 1;
310
+ activeSession.phase = "analysis";
311
+ return executeWorkflow(ctx);
312
+ }
313
+ activeSession.phase = "analysis";
314
+ return executeWorkflow(ctx);
315
+ }
233
316
  if (activeSession.phase === "spec") {
234
317
  if (trimmed === "y" || trimmed === "yes" || trimmed === "\u786E\u8BA4") {
235
318
  activeSession.phase = "tdd";
236
319
  return executeWorkflow(ctx);
237
320
  }
238
321
  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);
322
+ activeSession.bddScenarios = generateBDDScenarios(
323
+ activeSession.refinedRequirement,
324
+ activeSession.context,
325
+ activeSession.clarificationQuestions
326
+ );
327
+ activeSession.specItems = generateSpecItems(
328
+ activeSession.refinedRequirement,
329
+ activeSession.context,
330
+ activeSession.bddScenarios,
331
+ activeSession.clarificationQuestions
332
+ );
241
333
  const specPath = await saveSpecFile(ctx.options.workingDirectory, activeSession);
242
334
  return {
243
335
  output: chalk9__default.default.cyan("\u{1F504} \u89C4\u683C\u5DF2\u91CD\u65B0\u751F\u6210") + chalk9__default.default.gray(`
@@ -254,11 +346,11 @@ async function handleWorkflowInput(input, ctx) {
254
346
  if (activeSession.phase === "review") {
255
347
  if (trimmed === "review" || trimmed === "\u5BA1\u6838" || trimmed === "pass" || trimmed === "\u901A\u8FC7") {
256
348
  await archiveWorkflow(ctx.options.workingDirectory);
257
- const summary = activeSession.requirement;
349
+ const summary = activeSession.refinedRequirement;
258
350
  activeSession = null;
259
351
  return {
260
352
  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")
353
+ \u9700\u6C42: ${summary.slice(0, 60)}...`) + chalk9__default.default.cyan("\n\n\u4F7F\u7528 /new <\u9700\u6C42> \u5F00\u59CB\u65B0\u7684\u5DE5\u4F5C\u6D41")
262
354
  };
263
355
  }
264
356
  if (trimmed === "fail" || trimmed === "\u5931\u8D25" || trimmed === "reject" || trimmed === "\u62D2\u7EDD") {
@@ -270,6 +362,122 @@ async function handleWorkflowInput(input, ctx) {
270
362
  }
271
363
  return null;
272
364
  }
365
+ function analyzeRequirementClarity(requirement, context) {
366
+ const questions = [];
367
+ let score = 0.5;
368
+ if (requirement.length < 10) {
369
+ score -= 0.2;
370
+ questions.push({
371
+ id: "q-length",
372
+ question: "\u9700\u6C42\u63CF\u8FF0\u8F83\u77ED\uFF0C\u80FD\u5426\u8BE6\u7EC6\u8BF4\u660E\u5177\u4F53\u8981\u5B9E\u73B0\u4EC0\u4E48\u529F\u80FD\uFF1F",
373
+ category: "scope",
374
+ answered: false
375
+ });
376
+ } else if (requirement.length >= 50) {
377
+ score += 0.1;
378
+ }
379
+ const actionKeywords = ["\u5B9E\u73B0", "\u6DFB\u52A0", "\u4FEE\u6539", "\u5220\u9664", "\u4F18\u5316", "\u4FEE\u590D", "\u91CD\u6784", "\u5F00\u53D1", "\u521B\u5EFA", "\u8BBE\u8BA1"];
380
+ const hasAction = actionKeywords.some((kw) => requirement.includes(kw));
381
+ if (!hasAction) {
382
+ score -= 0.15;
383
+ questions.push({
384
+ id: "q-action",
385
+ 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",
386
+ category: "scope",
387
+ answered: false
388
+ });
389
+ } else {
390
+ score += 0.1;
391
+ }
392
+ if (requirement.match(/界面|页面|组件|按钮|表单|弹窗|布局|样式|UI/)) {
393
+ score += 0.1;
394
+ if (!requirement.match(/在.*页面|在.*位置|显示在|位于/)) {
395
+ questions.push({
396
+ id: "q-ui-position",
397
+ question: "\u8FD9\u4E2A\u529F\u80FD\u5E94\u8BE5\u653E\u5728\u54EA\u4E2A\u9875\u9762\u6216\u4F4D\u7F6E\uFF1F",
398
+ category: "ui",
399
+ answered: false
400
+ });
401
+ }
402
+ } else {
403
+ questions.push({
404
+ id: "q-ui-need",
405
+ 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",
406
+ category: "ui",
407
+ answered: false
408
+ });
409
+ }
410
+ if (requirement.match(/数据|存储|保存|读取|API|接口|数据库|缓存/)) {
411
+ score += 0.1;
412
+ if (!requirement.match(/从.*获取|调用.*接口|读取.*数据|来源/)) {
413
+ questions.push({
414
+ id: "q-data-source",
415
+ question: "\u6570\u636E\u4ECE\u54EA\u91CC\u6765\uFF1F\u662F\u8C03\u7528API\u3001\u672C\u5730\u5B58\u50A8\u8FD8\u662F\u5176\u4ED6\u6765\u6E90\uFF1F",
416
+ category: "data",
417
+ answered: false
418
+ });
419
+ }
420
+ }
421
+ if (requirement.match(/点击|输入|选择|拖动|滑动|交互|操作/)) {
422
+ score += 0.1;
423
+ } else {
424
+ if (hasAction && requirement.match(/功能|特性|模块/)) {
425
+ questions.push({
426
+ id: "q-interaction",
427
+ question: "\u7528\u6237\u5982\u4F55\u64CD\u4F5C\u8FD9\u4E2A\u529F\u80FD\uFF1F\u6709\u4EC0\u4E48\u4EA4\u4E92\u6D41\u7A0B\uFF1F",
428
+ category: "interaction",
429
+ answered: false
430
+ });
431
+ }
432
+ }
433
+ if (requirement.match(/异常|错误|失败|边界|特殊情况|空值|验证/)) {
434
+ score += 0.15;
435
+ } else {
436
+ if (requirement.match(/功能|输入|表单|数据/)) {
437
+ questions.push({
438
+ id: "q-edge",
439
+ 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",
440
+ category: "edge",
441
+ answered: false
442
+ });
443
+ }
444
+ }
445
+ if (requirement.match(/https?:\/\/|参考|参照|类似/)) {
446
+ score += 0.15;
447
+ }
448
+ if (context.framework) {
449
+ score += 0.05;
450
+ }
451
+ const limitedQuestions = questions.slice(0, 5);
452
+ score = Math.max(0, Math.min(1, score));
453
+ return { score, questions: limitedQuestions };
454
+ }
455
+ function calculateClarityScore(questions) {
456
+ const answered = questions.filter((q) => q.answered).length;
457
+ if (questions.length === 0) return 1;
458
+ return 0.5 + answered / questions.length * 0.5;
459
+ }
460
+ function buildRefinedRequirement(session) {
461
+ const parts = [session.requirement];
462
+ for (const q of session.clarificationQuestions) {
463
+ if (q.answered && q.answer) {
464
+ parts.push(`
465
+ \u3010${getCategoryLabel(q.category)}\u3011${q.answer}`);
466
+ }
467
+ }
468
+ return parts.join("");
469
+ }
470
+ function getCategoryLabel(category) {
471
+ const labels = {
472
+ scope: "\u8303\u56F4",
473
+ ui: "\u754C\u9762",
474
+ data: "\u6570\u636E",
475
+ interaction: "\u4EA4\u4E92",
476
+ edge: "\u8FB9\u754C",
477
+ tech: "\u6280\u672F"
478
+ };
479
+ return labels[category] || category;
480
+ }
273
481
  async function readProjectContext(workingDir) {
274
482
  const context = {
275
483
  name: path4__namespace.basename(workingDir),
@@ -351,8 +559,11 @@ function analyzeComplexity(requirement, context) {
351
559
  if (!context.framework) score += 0.5;
352
560
  return Math.max(1, Math.min(10, Math.round(score)));
353
561
  }
354
- function generateBDDScenarios(requirement, context) {
562
+ function generateBDDScenarios(requirement, context, questions) {
355
563
  const scenarios = [];
564
+ questions.find((q) => q.category === "ui" && q.answered)?.answer;
565
+ const interactionAnswer = questions.find((q) => q.category === "interaction" && q.answered)?.answer;
566
+ const edgeAnswer = questions.find((q) => q.category === "edge" && q.answered)?.answer;
356
567
  const features = extractFeatures(requirement);
357
568
  for (const feature of features) {
358
569
  const scenario = {
@@ -366,12 +577,20 @@ function generateBDDScenarios(requirement, context) {
366
577
  when: [`\u7528\u6237\u6267\u884C "${feature.title}" \u64CD\u4F5C`],
367
578
  then: [`\u7CFB\u7EDF\u5E94\u6B63\u786E\u5904\u7406\u5E76\u8FD4\u56DE\u9884\u671F\u7ED3\u679C`]
368
579
  });
369
- if (feature.hasInput) {
580
+ if (interactionAnswer) {
370
581
  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`]
582
+ name: `\u4EA4\u4E92\u6D41\u7A0B: \u7528\u6237\u64CD\u4F5C`,
583
+ given: [`\u7528\u6237\u8FDB\u5165\u529F\u80FD\u754C\u9762`],
584
+ when: [`\u7528\u6237\u6309\u7167\u4EE5\u4E0B\u6D41\u7A0B\u64CD\u4F5C: ${interactionAnswer}`],
585
+ then: [`\u7CFB\u7EDF\u54CD\u5E94\u5E76\u5B8C\u6210\u529F\u80FD`]
586
+ });
587
+ }
588
+ if (feature.hasInput || edgeAnswer) {
589
+ scenario.scenarios.push({
590
+ name: `\u8FB9\u754C\u60C5\u51B5: \u5F02\u5E38\u5904\u7406`,
591
+ given: [`\u7528\u6237\u8FDB\u5165\u529F\u80FD\u754C\u9762`],
592
+ when: [`\u53D1\u751F\u5F02\u5E38\u60C5\u51B5${edgeAnswer ? `: ${edgeAnswer}` : ""}`],
593
+ then: [`\u7CFB\u7EDF\u5E94\u6B63\u786E\u5904\u7406\u5F02\u5E38\u5E76\u7ED9\u51FA\u63D0\u793A`]
375
594
  });
376
595
  }
377
596
  scenarios.push(scenario);
@@ -418,7 +637,7 @@ function extractFeatures(requirement) {
418
637
  }
419
638
  return features;
420
639
  }
421
- function generateSpecItems(requirement, context, bddScenarios) {
640
+ function generateSpecItems(requirement, context, bddScenarios, questions) {
422
641
  const items = [];
423
642
  let id = 1;
424
643
  for (const scenario of bddScenarios) {
@@ -455,11 +674,33 @@ function formatSpecFile(session) {
455
674
  lines.push(`# \u9700\u6C42\u89C4\u683C: ${session.requirement.slice(0, 50)}`);
456
675
  lines.push("");
457
676
  lines.push(`> \u53D8\u66F4ID: ${session.id}`);
677
+ lines.push(`> \u9700\u6C42\u6E05\u6670\u5EA6: ${Math.round(session.clarityScore * 100)}%`);
458
678
  lines.push(`> \u590D\u6742\u5EA6: ${session.complexity}/10`);
459
679
  lines.push(`> \u751F\u6210\u65F6\u95F4: ${session.createdAt.toISOString()}`);
460
680
  lines.push("");
461
681
  lines.push("---");
462
682
  lines.push("");
683
+ if (session.refinedRequirement !== session.requirement) {
684
+ lines.push("## \u9700\u6C42\u8BE6\u60C5");
685
+ lines.push("");
686
+ lines.push(session.refinedRequirement);
687
+ lines.push("");
688
+ lines.push("---");
689
+ lines.push("");
690
+ }
691
+ if (session.clarificationQuestions.some((q) => q.answered)) {
692
+ lines.push("## \u9700\u6C42\u6F84\u6E05");
693
+ lines.push("");
694
+ for (const q of session.clarificationQuestions) {
695
+ if (q.answered) {
696
+ lines.push(`**Q: ${q.question}**`);
697
+ lines.push(`A: ${q.answer}`);
698
+ lines.push("");
699
+ }
700
+ }
701
+ lines.push("---");
702
+ lines.push("");
703
+ }
463
704
  lines.push("## BDD \u573A\u666F");
464
705
  lines.push("");
465
706
  for (const scenario of session.bddScenarios) {
@@ -523,11 +764,17 @@ async function archiveWorkflow(workingDir) {
523
764
  const content = `# \u5F52\u6863: ${activeSession.requirement.slice(0, 50)}
524
765
 
525
766
  > \u5F52\u6863\u65F6\u95F4: ${(/* @__PURE__ */ new Date()).toISOString()}
767
+ > \u9700\u6C42\u6E05\u6670\u5EA6: ${Math.round(activeSession.clarityScore * 100)}%
526
768
  > \u590D\u6742\u5EA6: ${activeSession.complexity}/10
527
769
 
770
+ ## \u9700\u6C42\u8BE6\u60C5
771
+
772
+ ${activeSession.refinedRequirement}
773
+
528
774
  ## \u5B8C\u6210\u60C5\u51B5
529
775
 
530
776
  - [x] \u9879\u76EE\u4E0A\u4E0B\u6587\u83B7\u53D6
777
+ - [x] \u9700\u6C42\u6F84\u6E05
531
778
  - [x] \u590D\u6742\u5EA6\u8BC4\u4F30
532
779
  - [x] BDD \u573A\u666F\u62C6\u89E3
533
780
  - [x] OpenSpec \u89C4\u683C
@@ -554,6 +801,7 @@ function generateComplexityBar(score) {
554
801
  function getPhaseLabel(phase) {
555
802
  const labels = {
556
803
  context: "\u9879\u76EE\u4E0A\u4E0B\u6587\u83B7\u53D6",
804
+ clarify: "\u9700\u6C42\u6F84\u6E05",
557
805
  analysis: "\u590D\u6742\u5EA6\u8BC4\u4F30",
558
806
  bdd: "BDD \u573A\u666F\u62C6\u89E3",
559
807
  spec: "OpenSpec \u89C4\u683C",
@@ -569,12 +817,13 @@ function getActiveSession() {
569
817
  function clearActiveSession() {
570
818
  activeSession = null;
571
819
  }
572
- var MAX_FILE_SIZE2, COMPLEXITY_THRESHOLD, activeSession, new_default;
820
+ var MAX_FILE_SIZE2, COMPLEXITY_THRESHOLD, CLARITY_THRESHOLD, activeSession, new_default;
573
821
  var init_new = __esm({
574
822
  "src/commands/new.ts"() {
575
823
  init_cjs_shims();
576
824
  MAX_FILE_SIZE2 = 1024 * 1024;
577
825
  COMPLEXITY_THRESHOLD = 6;
826
+ CLARITY_THRESHOLD = 0.6;
578
827
  activeSession = null;
579
828
  new_default = handleNew;
580
829
  }