@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/cli/index.js
CHANGED
|
@@ -1794,14 +1794,17 @@ async function handleNew(args, ctx) {
|
|
|
1794
1794
|
const requirement = args.join(" ").trim();
|
|
1795
1795
|
if (!requirement) {
|
|
1796
1796
|
return {
|
|
1797
|
-
output: chalk9__default.default.red("\u8BF7\u8F93\u5165\u9700\u6C42\u63CF\u8FF0") + chalk9__default.default.gray("\n\u7528\u6CD5: /new <\u9700\u6C42\u63CF\u8FF0>")
|
|
1797
|
+
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")
|
|
1798
1798
|
};
|
|
1799
1799
|
}
|
|
1800
1800
|
activeSession = {
|
|
1801
1801
|
id: generateSessionId(),
|
|
1802
1802
|
requirement,
|
|
1803
|
+
refinedRequirement: requirement,
|
|
1803
1804
|
phase: "context",
|
|
1804
1805
|
context: null,
|
|
1806
|
+
clarityScore: 0,
|
|
1807
|
+
clarificationQuestions: [],
|
|
1805
1808
|
complexity: 0,
|
|
1806
1809
|
bddScenarios: [],
|
|
1807
1810
|
specItems: [],
|
|
@@ -1819,10 +1822,13 @@ function handleActiveSession(ctx) {
|
|
|
1819
1822
|
const lines = [];
|
|
1820
1823
|
lines.push(chalk9__default.default.cyan("\u{1F4CB} \u5F53\u524D\u5DE5\u4F5C\u6D41\u72B6\u6001"));
|
|
1821
1824
|
lines.push("");
|
|
1822
|
-
lines.push(chalk9__default.default.white(`\u9700\u6C42: ${activeSession.requirement}`));
|
|
1825
|
+
lines.push(chalk9__default.default.white(`\u9700\u6C42: ${activeSession.requirement.slice(0, 60)}${activeSession.requirement.length > 60 ? "..." : ""}`));
|
|
1823
1826
|
lines.push(chalk9__default.default.gray(`\u9636\u6BB5: ${getPhaseLabel(activeSession.phase)}`));
|
|
1824
1827
|
lines.push("");
|
|
1825
|
-
if (activeSession.phase === "
|
|
1828
|
+
if (activeSession.phase === "clarify") {
|
|
1829
|
+
lines.push(chalk9__default.default.yellow("\u23F8\uFE0F \u7B49\u5F85\u9700\u6C42\u6F84\u6E05"));
|
|
1830
|
+
lines.push(chalk9__default.default.gray('\u8BF7\u56DE\u7B54\u4E0A\u8FF0\u95EE\u9898\uFF0C\u6216\u8F93\u5165 "done" \u8868\u793A\u56DE\u7B54\u5B8C\u6210'));
|
|
1831
|
+
} else if (activeSession.phase === "spec") {
|
|
1826
1832
|
lines.push(chalk9__default.default.yellow("\u23F8\uFE0F \u7B49\u5F85\u89C4\u683C\u786E\u8BA4"));
|
|
1827
1833
|
lines.push("");
|
|
1828
1834
|
lines.push(chalk9__default.default.green(" y - \u786E\u8BA4\u89C4\u683C\uFF0C\u7EE7\u7EED\u5DE5\u4F5C\u6D41"));
|
|
@@ -1841,7 +1847,7 @@ async function executeWorkflow(ctx) {
|
|
|
1841
1847
|
const lines = [];
|
|
1842
1848
|
try {
|
|
1843
1849
|
if (activeSession.phase === "context") {
|
|
1844
|
-
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5 1/
|
|
1850
|
+
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5 1/8: \u9879\u76EE\u4E0A\u4E0B\u6587\u83B7\u53D6 \u2501\u2501\u2501"));
|
|
1845
1851
|
lines.push("");
|
|
1846
1852
|
activeSession.context = await readProjectContext(ctx.options.workingDirectory);
|
|
1847
1853
|
lines.push(chalk9__default.default.gray(` \u9879\u76EE: ${activeSession.context.name}`));
|
|
@@ -1851,13 +1857,46 @@ async function executeWorkflow(ctx) {
|
|
|
1851
1857
|
if (activeSession.context.devStandards) {
|
|
1852
1858
|
lines.push(chalk9__default.default.green(" \u2713 \u5DF2\u8BFB\u53D6\u5F00\u53D1\u89C4\u8303"));
|
|
1853
1859
|
}
|
|
1860
|
+
activeSession.phase = "clarify";
|
|
1861
|
+
}
|
|
1862
|
+
if (activeSession.phase === "clarify") {
|
|
1863
|
+
lines.push("");
|
|
1864
|
+
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5 2/8: \u9700\u6C42\u6F84\u6E05 \u2501\u2501\u2501"));
|
|
1865
|
+
lines.push("");
|
|
1866
|
+
const clarityResult = analyzeRequirementClarity(
|
|
1867
|
+
activeSession.requirement,
|
|
1868
|
+
activeSession.context
|
|
1869
|
+
);
|
|
1870
|
+
activeSession.clarityScore = clarityResult.score;
|
|
1871
|
+
activeSession.clarificationQuestions = clarityResult.questions;
|
|
1872
|
+
lines.push(chalk9__default.default.gray(` \u9700\u6C42\u6E05\u6670\u5EA6: ${Math.round(clarityResult.score * 100)}%`));
|
|
1873
|
+
lines.push("");
|
|
1874
|
+
if (clarityResult.score < CLARITY_THRESHOLD && clarityResult.questions.length > 0) {
|
|
1875
|
+
lines.push(chalk9__default.default.yellow(" \u9700\u6C42\u4E0D\u591F\u660E\u786E\uFF0C\u8BF7\u8865\u5145\u4EE5\u4E0B\u4FE1\u606F\uFF1A"));
|
|
1876
|
+
lines.push("");
|
|
1877
|
+
const unansweredQuestions = clarityResult.questions.filter((q) => !q.answered);
|
|
1878
|
+
for (let i = 0; i < Math.min(unansweredQuestions.length, 3); i++) {
|
|
1879
|
+
const q = unansweredQuestions[i];
|
|
1880
|
+
lines.push(chalk9__default.default.white(` ${i + 1}. ${q.question}`));
|
|
1881
|
+
}
|
|
1882
|
+
if (unansweredQuestions.length > 3) {
|
|
1883
|
+
lines.push(chalk9__default.default.gray(` ... \u8FD8\u6709 ${unansweredQuestions.length - 3} \u4E2A\u95EE\u9898`));
|
|
1884
|
+
}
|
|
1885
|
+
lines.push("");
|
|
1886
|
+
lines.push(chalk9__default.default.gray(' \u8BF7\u8F93\u5165\u56DE\u7B54\uFF0C\u6216\u8F93\u5165 "done" \u8DF3\u8FC7\u6F84\u6E05'));
|
|
1887
|
+
return { output: lines.join("\n") };
|
|
1888
|
+
}
|
|
1889
|
+
lines.push(chalk9__default.default.green(" \u2713 \u9700\u6C42\u6E05\u6670\uFF0C\u7EE7\u7EED\u4E0B\u4E00\u6B65"));
|
|
1854
1890
|
activeSession.phase = "analysis";
|
|
1855
1891
|
}
|
|
1856
1892
|
if (activeSession.phase === "analysis") {
|
|
1857
1893
|
lines.push("");
|
|
1858
|
-
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5
|
|
1894
|
+
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5 3/8: \u590D\u6742\u5EA6\u8BC4\u4F30 \u2501\u2501\u2501"));
|
|
1859
1895
|
lines.push("");
|
|
1860
|
-
activeSession.complexity = analyzeComplexity(
|
|
1896
|
+
activeSession.complexity = analyzeComplexity(
|
|
1897
|
+
activeSession.refinedRequirement,
|
|
1898
|
+
activeSession.context
|
|
1899
|
+
);
|
|
1861
1900
|
const complexityBar = generateComplexityBar(activeSession.complexity);
|
|
1862
1901
|
lines.push(chalk9__default.default.gray(` \u590D\u6742\u5EA6: ${complexityBar} ${activeSession.complexity}/10`));
|
|
1863
1902
|
if (activeSession.complexity >= COMPLEXITY_THRESHOLD) {
|
|
@@ -1869,9 +1908,13 @@ async function executeWorkflow(ctx) {
|
|
|
1869
1908
|
}
|
|
1870
1909
|
if (activeSession.phase === "bdd") {
|
|
1871
1910
|
lines.push("");
|
|
1872
|
-
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5
|
|
1911
|
+
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5 4/8: BDD \u573A\u666F\u62C6\u89E3 \u2501\u2501\u2501"));
|
|
1873
1912
|
lines.push("");
|
|
1874
|
-
activeSession.bddScenarios = generateBDDScenarios(
|
|
1913
|
+
activeSession.bddScenarios = generateBDDScenarios(
|
|
1914
|
+
activeSession.refinedRequirement,
|
|
1915
|
+
activeSession.context,
|
|
1916
|
+
activeSession.clarificationQuestions
|
|
1917
|
+
);
|
|
1875
1918
|
for (const scenario of activeSession.bddScenarios) {
|
|
1876
1919
|
lines.push(chalk9__default.default.white(` Feature: ${scenario.feature}`));
|
|
1877
1920
|
for (const s of scenario.scenarios.slice(0, 3)) {
|
|
@@ -1885,9 +1928,14 @@ async function executeWorkflow(ctx) {
|
|
|
1885
1928
|
}
|
|
1886
1929
|
if (activeSession.phase === "spec") {
|
|
1887
1930
|
lines.push("");
|
|
1888
|
-
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5
|
|
1931
|
+
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5 5/8: OpenSpec \u89C4\u683C \u2501\u2501\u2501"));
|
|
1889
1932
|
lines.push("");
|
|
1890
|
-
activeSession.specItems = generateSpecItems(
|
|
1933
|
+
activeSession.specItems = generateSpecItems(
|
|
1934
|
+
activeSession.refinedRequirement,
|
|
1935
|
+
activeSession.context,
|
|
1936
|
+
activeSession.bddScenarios,
|
|
1937
|
+
activeSession.clarificationQuestions
|
|
1938
|
+
);
|
|
1891
1939
|
const specPath = await saveSpecFile(ctx.options.workingDirectory, activeSession);
|
|
1892
1940
|
lines.push(chalk9__default.default.green(" \u2713 \u89C4\u683C\u6587\u4EF6\u5DF2\u751F\u6210"));
|
|
1893
1941
|
lines.push(chalk9__default.default.gray(` \u8DEF\u5F84: ${specPath}`));
|
|
@@ -1910,7 +1958,7 @@ async function executeWorkflow(ctx) {
|
|
|
1910
1958
|
}
|
|
1911
1959
|
if (activeSession.phase === "tdd") {
|
|
1912
1960
|
lines.push("");
|
|
1913
|
-
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5
|
|
1961
|
+
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5 6/8: TDD \u6D4B\u8BD5\u751F\u6210 \u2501\u2501\u2501"));
|
|
1914
1962
|
lines.push("");
|
|
1915
1963
|
activeSession.testFiles = await generateTests(ctx.options.workingDirectory, activeSession);
|
|
1916
1964
|
lines.push(chalk9__default.default.green(" \u2713 \u6D4B\u8BD5\u6587\u4EF6\u5DF2\u751F\u6210"));
|
|
@@ -1921,20 +1969,69 @@ async function executeWorkflow(ctx) {
|
|
|
1921
1969
|
}
|
|
1922
1970
|
if (activeSession.phase === "develop") {
|
|
1923
1971
|
lines.push("");
|
|
1924
|
-
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5
|
|
1972
|
+
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5 7/8: \u5F00\u53D1\u5B9E\u73B0 \u2501\u2501\u2501"));
|
|
1925
1973
|
lines.push("");
|
|
1926
|
-
lines.push(chalk9__default.default.yellow(" \u{
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1974
|
+
lines.push(chalk9__default.default.yellow(" \u{1F680} \u6B63\u5728\u8C03\u7528 AI \u751F\u6210\u4EE3\u7801..."));
|
|
1975
|
+
try {
|
|
1976
|
+
const developResult = await executeDevelopment(ctx, activeSession);
|
|
1977
|
+
if (developResult.success) {
|
|
1978
|
+
lines.push(chalk9__default.default.green(" \u2713 \u4EE3\u7801\u751F\u6210\u5B8C\u6210"));
|
|
1979
|
+
for (const file of developResult.files) {
|
|
1980
|
+
lines.push(chalk9__default.default.gray(` - ${file}`));
|
|
1981
|
+
}
|
|
1982
|
+
activeSession.implFiles = developResult.files;
|
|
1983
|
+
activeSession.phase = "review";
|
|
1984
|
+
} else {
|
|
1985
|
+
lines.push(chalk9__default.default.red(` \u2717 \u4EE3\u7801\u751F\u6210\u5931\u8D25: ${developResult.error}`));
|
|
1986
|
+
lines.push(chalk9__default.default.gray(" \u8BF7\u624B\u52A8\u5B9E\u73B0\u4EE3\u7801\u540E\u8F93\u5165 continue \u7EE7\u7EED"));
|
|
1987
|
+
return { output: lines.join("\n") };
|
|
1988
|
+
}
|
|
1989
|
+
} catch (error) {
|
|
1990
|
+
lines.push(chalk9__default.default.red(` \u2717 \u5F00\u53D1\u9636\u6BB5\u51FA\u9519: ${error.message}`));
|
|
1991
|
+
lines.push(chalk9__default.default.gray(" \u8BF7\u624B\u52A8\u5B9E\u73B0\u4EE3\u7801\u540E\u8F93\u5165 continue \u7EE7\u7EED"));
|
|
1992
|
+
return { output: lines.join("\n") };
|
|
1993
|
+
}
|
|
1930
1994
|
}
|
|
1931
1995
|
if (activeSession.phase === "review") {
|
|
1932
1996
|
lines.push("");
|
|
1933
|
-
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5
|
|
1997
|
+
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5 8/8: \u4EE3\u7801\u5BA1\u6838 \u2501\u2501\u2501"));
|
|
1934
1998
|
lines.push("");
|
|
1935
|
-
lines.push(chalk9__default.default.yellow(" \u{1F50D} \u4EE3\u7801\u5BA1\u6838
|
|
1936
|
-
|
|
1937
|
-
|
|
1999
|
+
lines.push(chalk9__default.default.yellow(" \u{1F50D} \u6B63\u5728\u8FDB\u884C\u4EE3\u7801\u5BA1\u6838..."));
|
|
2000
|
+
try {
|
|
2001
|
+
const reviewResult = await executeReview(ctx, activeSession);
|
|
2002
|
+
if (reviewResult.passed) {
|
|
2003
|
+
lines.push(chalk9__default.default.green(" \u2713 \u4EE3\u7801\u5BA1\u6838\u901A\u8FC7"));
|
|
2004
|
+
if (reviewResult.suggestions.length > 0) {
|
|
2005
|
+
lines.push(chalk9__default.default.gray(" \u5EFA\u8BAE:"));
|
|
2006
|
+
for (const s of reviewResult.suggestions.slice(0, 3)) {
|
|
2007
|
+
lines.push(chalk9__default.default.gray(` - ${s}`));
|
|
2008
|
+
}
|
|
2009
|
+
}
|
|
2010
|
+
await archiveWorkflow(ctx.options.workingDirectory);
|
|
2011
|
+
const summary = activeSession.refinedRequirement;
|
|
2012
|
+
activeSession = null;
|
|
2013
|
+
lines.push("");
|
|
2014
|
+
lines.push(chalk9__default.default.green.bold("\u{1F389} \u5DE5\u4F5C\u6D41\u5DF2\u5B8C\u6210\uFF01"));
|
|
2015
|
+
lines.push(chalk9__default.default.gray(`\u9700\u6C42: ${summary.slice(0, 60)}${summary.length > 60 ? "..." : ""}`));
|
|
2016
|
+
lines.push("");
|
|
2017
|
+
lines.push(chalk9__default.default.cyan("\u4F7F\u7528 /new <\u9700\u6C42> \u5F00\u59CB\u65B0\u7684\u5DE5\u4F5C\u6D41"));
|
|
2018
|
+
return { output: lines.join("\n") };
|
|
2019
|
+
} else {
|
|
2020
|
+
lines.push(chalk9__default.default.red(" \u2717 \u4EE3\u7801\u5BA1\u6838\u672A\u901A\u8FC7"));
|
|
2021
|
+
lines.push(chalk9__default.default.gray(" \u95EE\u9898:"));
|
|
2022
|
+
for (const issue of reviewResult.issues.slice(0, 5)) {
|
|
2023
|
+
lines.push(chalk9__default.default.red(` - ${issue}`));
|
|
2024
|
+
}
|
|
2025
|
+
lines.push("");
|
|
2026
|
+
lines.push(chalk9__default.default.yellow(" \u8BF7\u4FEE\u590D\u95EE\u9898\u540E\u8F93\u5165 y \u91CD\u65B0\u5BA1\u6838"));
|
|
2027
|
+
lines.push(chalk9__default.default.gray(" \u6216\u8F93\u5165 n \u56DE\u9000\u5230\u89C4\u683C\u9636\u6BB5"));
|
|
2028
|
+
return { output: lines.join("\n") };
|
|
2029
|
+
}
|
|
2030
|
+
} catch (error) {
|
|
2031
|
+
lines.push(chalk9__default.default.red(` \u2717 \u5BA1\u6838\u9636\u6BB5\u51FA\u9519: ${error.message}`));
|
|
2032
|
+
lines.push(chalk9__default.default.gray(" \u8F93\u5165 pass \u5F3A\u5236\u901A\u8FC7\uFF0C\u6216 fix \u4FEE\u590D\u95EE\u9898"));
|
|
2033
|
+
return { output: lines.join("\n") };
|
|
2034
|
+
}
|
|
1938
2035
|
}
|
|
1939
2036
|
return { output: lines.join("\n") };
|
|
1940
2037
|
} catch (error) {
|
|
@@ -1951,14 +2048,58 @@ async function handleWorkflowInput(input, ctx) {
|
|
|
1951
2048
|
output: chalk9__default.default.yellow("\u2713 \u5DE5\u4F5C\u6D41\u5DF2\u53D6\u6D88")
|
|
1952
2049
|
};
|
|
1953
2050
|
}
|
|
2051
|
+
if (activeSession.phase === "clarify") {
|
|
2052
|
+
if (trimmed === "done" || trimmed === "\u5B8C\u6210" || trimmed === "\u8DF3\u8FC7" || trimmed === "skip") {
|
|
2053
|
+
activeSession.refinedRequirement = buildRefinedRequirement(activeSession);
|
|
2054
|
+
activeSession.phase = "analysis";
|
|
2055
|
+
return executeWorkflow(ctx);
|
|
2056
|
+
}
|
|
2057
|
+
activeSession.clarificationQuestions.filter((q) => q.answered).length;
|
|
2058
|
+
const unansweredQuestions = activeSession.clarificationQuestions.filter((q) => !q.answered);
|
|
2059
|
+
if (unansweredQuestions.length > 0) {
|
|
2060
|
+
const question = unansweredQuestions[0];
|
|
2061
|
+
question.answer = input.trim();
|
|
2062
|
+
question.answered = true;
|
|
2063
|
+
activeSession.refinedRequirement = buildRefinedRequirement(activeSession);
|
|
2064
|
+
const remaining = activeSession.clarificationQuestions.filter((q) => !q.answered);
|
|
2065
|
+
if (remaining.length > 0) {
|
|
2066
|
+
activeSession.clarityScore = calculateClarityScore(activeSession.clarificationQuestions);
|
|
2067
|
+
const lines = [];
|
|
2068
|
+
lines.push(chalk9__default.default.green(" \u2713 \u5DF2\u8BB0\u5F55"));
|
|
2069
|
+
lines.push("");
|
|
2070
|
+
lines.push(chalk9__default.default.yellow(" \u7EE7\u7EED\u56DE\u7B54\uFF1A"));
|
|
2071
|
+
for (let i = 0; i < Math.min(remaining.length, 3); i++) {
|
|
2072
|
+
const q = remaining[i];
|
|
2073
|
+
lines.push(chalk9__default.default.white(` ${i + 1}. ${q.question}`));
|
|
2074
|
+
}
|
|
2075
|
+
lines.push("");
|
|
2076
|
+
lines.push(chalk9__default.default.gray(' \u8F93\u5165\u56DE\u7B54\uFF0C\u6216 "done" \u8DF3\u8FC7'));
|
|
2077
|
+
return { output: lines.join("\n") };
|
|
2078
|
+
}
|
|
2079
|
+
activeSession.clarityScore = 1;
|
|
2080
|
+
activeSession.phase = "analysis";
|
|
2081
|
+
return executeWorkflow(ctx);
|
|
2082
|
+
}
|
|
2083
|
+
activeSession.phase = "analysis";
|
|
2084
|
+
return executeWorkflow(ctx);
|
|
2085
|
+
}
|
|
1954
2086
|
if (activeSession.phase === "spec") {
|
|
1955
2087
|
if (trimmed === "y" || trimmed === "yes" || trimmed === "\u786E\u8BA4") {
|
|
1956
2088
|
activeSession.phase = "tdd";
|
|
1957
2089
|
return executeWorkflow(ctx);
|
|
1958
2090
|
}
|
|
1959
2091
|
if (trimmed === "n" || trimmed === "no" || trimmed === "\u91CD\u65B0") {
|
|
1960
|
-
activeSession.bddScenarios = generateBDDScenarios(
|
|
1961
|
-
|
|
2092
|
+
activeSession.bddScenarios = generateBDDScenarios(
|
|
2093
|
+
activeSession.refinedRequirement,
|
|
2094
|
+
activeSession.context,
|
|
2095
|
+
activeSession.clarificationQuestions
|
|
2096
|
+
);
|
|
2097
|
+
activeSession.specItems = generateSpecItems(
|
|
2098
|
+
activeSession.refinedRequirement,
|
|
2099
|
+
activeSession.context,
|
|
2100
|
+
activeSession.bddScenarios,
|
|
2101
|
+
activeSession.clarificationQuestions
|
|
2102
|
+
);
|
|
1962
2103
|
const specPath = await saveSpecFile(ctx.options.workingDirectory, activeSession);
|
|
1963
2104
|
return {
|
|
1964
2105
|
output: chalk9__default.default.cyan("\u{1F504} \u89C4\u683C\u5DF2\u91CD\u65B0\u751F\u6210") + chalk9__default.default.gray(`
|
|
@@ -1973,24 +2114,347 @@ async function handleWorkflowInput(input, ctx) {
|
|
|
1973
2114
|
}
|
|
1974
2115
|
}
|
|
1975
2116
|
if (activeSession.phase === "review") {
|
|
1976
|
-
if (trimmed === "
|
|
2117
|
+
if (trimmed === "pass" || trimmed === "\u901A\u8FC7" || trimmed === "\u5F3A\u5236\u901A\u8FC7") {
|
|
1977
2118
|
await archiveWorkflow(ctx.options.workingDirectory);
|
|
1978
|
-
const summary = activeSession.
|
|
2119
|
+
const summary = activeSession.refinedRequirement;
|
|
1979
2120
|
activeSession = null;
|
|
1980
2121
|
return {
|
|
1981
2122
|
output: chalk9__default.default.green("\u2713 \u5DE5\u4F5C\u6D41\u5DF2\u5B8C\u6210") + chalk9__default.default.gray(`
|
|
1982
|
-
\u9700\u6C42: ${summary}`) + chalk9__default.default.cyan("\n\n\u4F7F\u7528 /new <\u9700\u6C42> \u5F00\u59CB\u65B0\u7684\u5DE5\u4F5C\u6D41")
|
|
2123
|
+
\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")
|
|
1983
2124
|
};
|
|
1984
2125
|
}
|
|
1985
|
-
if (trimmed === "
|
|
2126
|
+
if (trimmed === "y" || trimmed === "yes" || trimmed === "\u91CD\u65B0\u5BA1\u6838" || trimmed === "retry") {
|
|
2127
|
+
return executeWorkflow(ctx);
|
|
2128
|
+
}
|
|
2129
|
+
if (trimmed === "n" || trimmed === "no" || trimmed === "\u56DE\u9000" || trimmed === "rollback") {
|
|
1986
2130
|
activeSession.phase = "spec";
|
|
2131
|
+
return executeWorkflow(ctx);
|
|
2132
|
+
}
|
|
2133
|
+
if (trimmed === "fix" || trimmed === "\u4FEE\u590D") {
|
|
1987
2134
|
return {
|
|
1988
|
-
output: chalk9__default.default.yellow("\
|
|
2135
|
+
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")
|
|
1989
2136
|
};
|
|
1990
2137
|
}
|
|
1991
2138
|
}
|
|
1992
2139
|
return null;
|
|
1993
2140
|
}
|
|
2141
|
+
function analyzeRequirementClarity(requirement, context) {
|
|
2142
|
+
const questions = [];
|
|
2143
|
+
let score = 0.5;
|
|
2144
|
+
if (requirement.length < 10) {
|
|
2145
|
+
score -= 0.2;
|
|
2146
|
+
questions.push({
|
|
2147
|
+
id: "q-length",
|
|
2148
|
+
question: "\u9700\u6C42\u63CF\u8FF0\u8F83\u77ED\uFF0C\u80FD\u5426\u8BE6\u7EC6\u8BF4\u660E\u5177\u4F53\u8981\u5B9E\u73B0\u4EC0\u4E48\u529F\u80FD\uFF1F",
|
|
2149
|
+
category: "scope",
|
|
2150
|
+
answered: false
|
|
2151
|
+
});
|
|
2152
|
+
} else if (requirement.length >= 50) {
|
|
2153
|
+
score += 0.1;
|
|
2154
|
+
}
|
|
2155
|
+
const actionKeywords = ["\u5B9E\u73B0", "\u6DFB\u52A0", "\u4FEE\u6539", "\u5220\u9664", "\u4F18\u5316", "\u4FEE\u590D", "\u91CD\u6784", "\u5F00\u53D1", "\u521B\u5EFA", "\u8BBE\u8BA1"];
|
|
2156
|
+
const hasAction = actionKeywords.some((kw) => requirement.includes(kw));
|
|
2157
|
+
if (!hasAction) {
|
|
2158
|
+
score -= 0.15;
|
|
2159
|
+
questions.push({
|
|
2160
|
+
id: "q-action",
|
|
2161
|
+
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",
|
|
2162
|
+
category: "scope",
|
|
2163
|
+
answered: false
|
|
2164
|
+
});
|
|
2165
|
+
} else {
|
|
2166
|
+
score += 0.1;
|
|
2167
|
+
}
|
|
2168
|
+
if (requirement.match(/界面|页面|组件|按钮|表单|弹窗|布局|样式|UI/)) {
|
|
2169
|
+
score += 0.1;
|
|
2170
|
+
if (!requirement.match(/在.*页面|在.*位置|显示在|位于/)) {
|
|
2171
|
+
questions.push({
|
|
2172
|
+
id: "q-ui-position",
|
|
2173
|
+
question: "\u8FD9\u4E2A\u529F\u80FD\u5E94\u8BE5\u653E\u5728\u54EA\u4E2A\u9875\u9762\u6216\u4F4D\u7F6E\uFF1F",
|
|
2174
|
+
category: "ui",
|
|
2175
|
+
answered: false
|
|
2176
|
+
});
|
|
2177
|
+
}
|
|
2178
|
+
} else {
|
|
2179
|
+
questions.push({
|
|
2180
|
+
id: "q-ui-need",
|
|
2181
|
+
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",
|
|
2182
|
+
category: "ui",
|
|
2183
|
+
answered: false
|
|
2184
|
+
});
|
|
2185
|
+
}
|
|
2186
|
+
if (requirement.match(/数据|存储|保存|读取|API|接口|数据库|缓存/)) {
|
|
2187
|
+
score += 0.1;
|
|
2188
|
+
if (!requirement.match(/从.*获取|调用.*接口|读取.*数据|来源/)) {
|
|
2189
|
+
questions.push({
|
|
2190
|
+
id: "q-data-source",
|
|
2191
|
+
question: "\u6570\u636E\u4ECE\u54EA\u91CC\u6765\uFF1F\u662F\u8C03\u7528API\u3001\u672C\u5730\u5B58\u50A8\u8FD8\u662F\u5176\u4ED6\u6765\u6E90\uFF1F",
|
|
2192
|
+
category: "data",
|
|
2193
|
+
answered: false
|
|
2194
|
+
});
|
|
2195
|
+
}
|
|
2196
|
+
}
|
|
2197
|
+
if (requirement.match(/点击|输入|选择|拖动|滑动|交互|操作/)) {
|
|
2198
|
+
score += 0.1;
|
|
2199
|
+
} else {
|
|
2200
|
+
if (hasAction && requirement.match(/功能|特性|模块/)) {
|
|
2201
|
+
questions.push({
|
|
2202
|
+
id: "q-interaction",
|
|
2203
|
+
question: "\u7528\u6237\u5982\u4F55\u64CD\u4F5C\u8FD9\u4E2A\u529F\u80FD\uFF1F\u6709\u4EC0\u4E48\u4EA4\u4E92\u6D41\u7A0B\uFF1F",
|
|
2204
|
+
category: "interaction",
|
|
2205
|
+
answered: false
|
|
2206
|
+
});
|
|
2207
|
+
}
|
|
2208
|
+
}
|
|
2209
|
+
if (requirement.match(/异常|错误|失败|边界|特殊情况|空值|验证/)) {
|
|
2210
|
+
score += 0.15;
|
|
2211
|
+
} else {
|
|
2212
|
+
if (requirement.match(/功能|输入|表单|数据/)) {
|
|
2213
|
+
questions.push({
|
|
2214
|
+
id: "q-edge",
|
|
2215
|
+
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",
|
|
2216
|
+
category: "edge",
|
|
2217
|
+
answered: false
|
|
2218
|
+
});
|
|
2219
|
+
}
|
|
2220
|
+
}
|
|
2221
|
+
if (requirement.match(/https?:\/\/|参考|参照|类似/)) {
|
|
2222
|
+
score += 0.15;
|
|
2223
|
+
}
|
|
2224
|
+
if (context.framework) {
|
|
2225
|
+
score += 0.05;
|
|
2226
|
+
}
|
|
2227
|
+
const limitedQuestions = questions.slice(0, 5);
|
|
2228
|
+
score = Math.max(0, Math.min(1, score));
|
|
2229
|
+
return { score, questions: limitedQuestions };
|
|
2230
|
+
}
|
|
2231
|
+
function calculateClarityScore(questions) {
|
|
2232
|
+
const answered = questions.filter((q) => q.answered).length;
|
|
2233
|
+
if (questions.length === 0) return 1;
|
|
2234
|
+
return 0.5 + answered / questions.length * 0.5;
|
|
2235
|
+
}
|
|
2236
|
+
function buildRefinedRequirement(session) {
|
|
2237
|
+
const parts = [session.requirement];
|
|
2238
|
+
for (const q of session.clarificationQuestions) {
|
|
2239
|
+
if (q.answered && q.answer) {
|
|
2240
|
+
parts.push(`
|
|
2241
|
+
\u3010${getCategoryLabel(q.category)}\u3011${q.answer}`);
|
|
2242
|
+
}
|
|
2243
|
+
}
|
|
2244
|
+
return parts.join("");
|
|
2245
|
+
}
|
|
2246
|
+
function getCategoryLabel(category) {
|
|
2247
|
+
const labels = {
|
|
2248
|
+
scope: "\u8303\u56F4",
|
|
2249
|
+
ui: "\u754C\u9762",
|
|
2250
|
+
data: "\u6570\u636E",
|
|
2251
|
+
interaction: "\u4EA4\u4E92",
|
|
2252
|
+
edge: "\u8FB9\u754C",
|
|
2253
|
+
tech: "\u6280\u672F"
|
|
2254
|
+
};
|
|
2255
|
+
return labels[category] || category;
|
|
2256
|
+
}
|
|
2257
|
+
async function executeDevelopment(ctx, session) {
|
|
2258
|
+
const workingDir = ctx.options.workingDirectory;
|
|
2259
|
+
const files = [];
|
|
2260
|
+
try {
|
|
2261
|
+
const systemPrompt = buildDevelopmentPrompt(session);
|
|
2262
|
+
const messages = [
|
|
2263
|
+
{
|
|
2264
|
+
role: "system",
|
|
2265
|
+
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
|
|
2266
|
+
|
|
2267
|
+
\u8981\u6C42\uFF1A
|
|
2268
|
+
1. \u751F\u6210\u5B8C\u6574\u3001\u53EF\u8FD0\u884C\u7684\u4EE3\u7801
|
|
2269
|
+
2. \u9075\u5FAA\u9879\u76EE\u73B0\u6709\u7684\u4EE3\u7801\u98CE\u683C\u548C\u89C4\u8303
|
|
2270
|
+
3. \u4F7F\u7528\u9879\u76EE\u6307\u5B9A\u7684\u6280\u672F\u6808
|
|
2271
|
+
4. \u4EE3\u7801\u8981\u6709\u9002\u5F53\u7684\u6CE8\u91CA
|
|
2272
|
+
5. \u8FD4\u56DE\u683C\u5F0F\uFF1A\u6BCF\u4E2A\u6587\u4EF6\u7528 \`\`\`filename \u4EE3\u7801 \`\`\` \u5305\u88F9
|
|
2273
|
+
|
|
2274
|
+
\u9879\u76EE\u4FE1\u606F\uFF1A
|
|
2275
|
+
- \u540D\u79F0: ${session.context?.name}
|
|
2276
|
+
- \u6846\u67B6: ${session.context?.framework || "\u672A\u6307\u5B9A"}
|
|
2277
|
+
- \u6280\u672F\u6808: ${session.context?.techStack.join(", ") || "\u672A\u6307\u5B9A"}
|
|
2278
|
+
|
|
2279
|
+
${session.context?.devStandards ? `\u5F00\u53D1\u89C4\u8303\uFF1A
|
|
2280
|
+
${session.context.devStandards.slice(0, 2e3)}` : ""}`
|
|
2281
|
+
},
|
|
2282
|
+
{
|
|
2283
|
+
role: "user",
|
|
2284
|
+
content: systemPrompt
|
|
2285
|
+
}
|
|
2286
|
+
];
|
|
2287
|
+
const response = await ctx.modelService.sendMessage(messages, {
|
|
2288
|
+
temperature: 0.3,
|
|
2289
|
+
maxTokens: 8e3,
|
|
2290
|
+
agent: "frontend-dev"
|
|
2291
|
+
});
|
|
2292
|
+
const codeBlocks = parseCodeBlocks(response.content);
|
|
2293
|
+
for (const block of codeBlocks) {
|
|
2294
|
+
const filePath = path7__namespace.join(workingDir, block.filename);
|
|
2295
|
+
const dir = path7__namespace.dirname(filePath);
|
|
2296
|
+
await fs7__namespace.mkdir(dir, { recursive: true });
|
|
2297
|
+
await fs7__namespace.writeFile(filePath, block.code, "utf-8");
|
|
2298
|
+
files.push(block.filename);
|
|
2299
|
+
}
|
|
2300
|
+
if (files.length === 0) {
|
|
2301
|
+
const implDir = path7__namespace.join(workingDir, "src", "features");
|
|
2302
|
+
await fs7__namespace.mkdir(implDir, { recursive: true });
|
|
2303
|
+
const featureName = session.specItems[0]?.title || "feature";
|
|
2304
|
+
const fileName = `${featureName.replace(/[^a-zA-Z0-9]/g, "_")}.ts`;
|
|
2305
|
+
const filePath = path7__namespace.join(implDir, fileName);
|
|
2306
|
+
const stubCode = `/**
|
|
2307
|
+
* ${session.requirement}
|
|
2308
|
+
*
|
|
2309
|
+
* TODO: \u6B64\u6587\u4EF6\u7531 AI \u81EA\u52A8\u751F\u6210\uFF0C\u8BF7\u6839\u636E\u9700\u6C42\u5B8C\u5584\u5B9E\u73B0
|
|
2310
|
+
*/
|
|
2311
|
+
|
|
2312
|
+
export function ${featureName.replace(/[^a-zA-Z0-9]/g, "")}() {
|
|
2313
|
+
// TODO: \u5B9E\u73B0\u529F\u80FD
|
|
2314
|
+
console.log('${featureName} - \u5F85\u5B9E\u73B0');
|
|
2315
|
+
}
|
|
2316
|
+
`;
|
|
2317
|
+
await fs7__namespace.writeFile(filePath, stubCode, "utf-8");
|
|
2318
|
+
files.push(`src/features/${fileName}`);
|
|
2319
|
+
}
|
|
2320
|
+
return { success: true, files };
|
|
2321
|
+
} catch (error) {
|
|
2322
|
+
return {
|
|
2323
|
+
success: false,
|
|
2324
|
+
files: [],
|
|
2325
|
+
error: error.message
|
|
2326
|
+
};
|
|
2327
|
+
}
|
|
2328
|
+
}
|
|
2329
|
+
function buildDevelopmentPrompt(session) {
|
|
2330
|
+
const lines = [];
|
|
2331
|
+
lines.push("## \u9700\u6C42\u63CF\u8FF0");
|
|
2332
|
+
lines.push(session.refinedRequirement);
|
|
2333
|
+
lines.push("");
|
|
2334
|
+
lines.push("## BDD \u573A\u666F");
|
|
2335
|
+
for (const scenario of session.bddScenarios) {
|
|
2336
|
+
lines.push(`### ${scenario.feature}`);
|
|
2337
|
+
for (const s of scenario.scenarios) {
|
|
2338
|
+
lines.push(`- ${s.name}`);
|
|
2339
|
+
}
|
|
2340
|
+
}
|
|
2341
|
+
lines.push("");
|
|
2342
|
+
lines.push("## \u4EFB\u52A1\u5217\u8868");
|
|
2343
|
+
for (const item of session.specItems) {
|
|
2344
|
+
lines.push(`- [${item.id}] ${item.title}: ${item.description}`);
|
|
2345
|
+
}
|
|
2346
|
+
lines.push("");
|
|
2347
|
+
lines.push("\u8BF7\u6839\u636E\u4EE5\u4E0A\u9700\u6C42\u89C4\u683C\u751F\u6210\u4EE3\u7801\u5B9E\u73B0\u3002");
|
|
2348
|
+
return lines.join("\n");
|
|
2349
|
+
}
|
|
2350
|
+
function parseCodeBlocks(content) {
|
|
2351
|
+
const blocks = [];
|
|
2352
|
+
const regex = /```(\S+)\n([\s\S]*?)```/g;
|
|
2353
|
+
let match;
|
|
2354
|
+
while ((match = regex.exec(content)) !== null) {
|
|
2355
|
+
const filename = match[1];
|
|
2356
|
+
const code = match[2].trim();
|
|
2357
|
+
if (["text", "json", "markdown", "md"].includes(filename.toLowerCase())) {
|
|
2358
|
+
continue;
|
|
2359
|
+
}
|
|
2360
|
+
blocks.push({ filename, code });
|
|
2361
|
+
}
|
|
2362
|
+
return blocks;
|
|
2363
|
+
}
|
|
2364
|
+
async function executeReview(ctx, session) {
|
|
2365
|
+
const workingDir = ctx.options.workingDirectory;
|
|
2366
|
+
const issues = [];
|
|
2367
|
+
const suggestions = [];
|
|
2368
|
+
try {
|
|
2369
|
+
const codeContents = [];
|
|
2370
|
+
for (const file of session.implFiles) {
|
|
2371
|
+
try {
|
|
2372
|
+
const content = await fs7__namespace.readFile(path7__namespace.join(workingDir, file), "utf-8");
|
|
2373
|
+
codeContents.push(`// ${file}
|
|
2374
|
+
${content}`);
|
|
2375
|
+
} catch {
|
|
2376
|
+
}
|
|
2377
|
+
}
|
|
2378
|
+
const testContents = [];
|
|
2379
|
+
for (const file of session.testFiles) {
|
|
2380
|
+
try {
|
|
2381
|
+
const content = await fs7__namespace.readFile(path7__namespace.join(workingDir, file), "utf-8");
|
|
2382
|
+
testContents.push(`// ${file}
|
|
2383
|
+
${content}`);
|
|
2384
|
+
} catch {
|
|
2385
|
+
}
|
|
2386
|
+
}
|
|
2387
|
+
const messages = [
|
|
2388
|
+
{
|
|
2389
|
+
role: "system",
|
|
2390
|
+
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
|
|
2391
|
+
|
|
2392
|
+
\u5BA1\u6838\u6807\u51C6\uFF1A
|
|
2393
|
+
1. \u4EE3\u7801\u662F\u5426\u6B63\u786E\u5B9E\u73B0\u4E86\u9700\u6C42\u89C4\u683C\u4E2D\u7684\u529F\u80FD
|
|
2394
|
+
2. \u4EE3\u7801\u8D28\u91CF\uFF08\u53EF\u8BFB\u6027\u3001\u53EF\u7EF4\u62A4\u6027\uFF09
|
|
2395
|
+
3. \u6F5C\u5728\u7684 bug \u548C\u8FB9\u754C\u60C5\u51B5\u5904\u7406
|
|
2396
|
+
4. \u4EE3\u7801\u98CE\u683C\u662F\u5426\u7B26\u5408\u9879\u76EE\u89C4\u8303
|
|
2397
|
+
5. \u6D4B\u8BD5\u8986\u76D6\u662F\u5426\u5145\u5206
|
|
2398
|
+
|
|
2399
|
+
\u8FD4\u56DE\u683C\u5F0F\uFF1A
|
|
2400
|
+
- \u5982\u679C\u901A\u8FC7\u5BA1\u6838\uFF0C\u8FD4\u56DE "\u5BA1\u6838\u901A\u8FC7" \u5E76\u5217\u51FA\u6539\u8FDB\u5EFA\u8BAE
|
|
2401
|
+
- \u5982\u679C\u4E0D\u901A\u8FC7\uFF0C\u5217\u51FA\u5177\u4F53\u95EE\u9898
|
|
2402
|
+
|
|
2403
|
+
\u9879\u76EE\u4FE1\u606F\uFF1A
|
|
2404
|
+
- \u6846\u67B6: ${session.context?.framework || "\u672A\u6307\u5B9A"}
|
|
2405
|
+
- \u6280\u672F\u6808: ${session.context?.techStack.join(", ") || "\u672A\u6307\u5B9A"}
|
|
2406
|
+
|
|
2407
|
+
${session.context?.devStandards ? `\u5F00\u53D1\u89C4\u8303\uFF1A
|
|
2408
|
+
${session.context.devStandards.slice(0, 1e3)}` : ""}`
|
|
2409
|
+
},
|
|
2410
|
+
{
|
|
2411
|
+
role: "user",
|
|
2412
|
+
content: `## \u9700\u6C42\u89C4\u683C
|
|
2413
|
+
${session.refinedRequirement}
|
|
2414
|
+
|
|
2415
|
+
## \u4EFB\u52A1\u5217\u8868
|
|
2416
|
+
${session.specItems.map((item) => `- [${item.id}] ${item.title}`).join("\n")}
|
|
2417
|
+
|
|
2418
|
+
## \u5B9E\u73B0\u4EE3\u7801
|
|
2419
|
+
${codeContents.join("\n\n") || "\uFF08\u65E0\u4EE3\u7801\u6587\u4EF6\uFF09"}
|
|
2420
|
+
|
|
2421
|
+
## \u6D4B\u8BD5\u4EE3\u7801
|
|
2422
|
+
${testContents.join("\n\n") || "\uFF08\u65E0\u6D4B\u8BD5\u6587\u4EF6\uFF09"}
|
|
2423
|
+
|
|
2424
|
+
\u8BF7\u5BA1\u6838\u4EE5\u4E0A\u4EE3\u7801\u5B9E\u73B0\u3002`
|
|
2425
|
+
}
|
|
2426
|
+
];
|
|
2427
|
+
const response = await ctx.modelService.sendMessage(messages, {
|
|
2428
|
+
temperature: 0.2,
|
|
2429
|
+
maxTokens: 2e3,
|
|
2430
|
+
agent: "code-reviewer"
|
|
2431
|
+
});
|
|
2432
|
+
const result = response.content;
|
|
2433
|
+
const passed = result.includes("\u5BA1\u6838\u901A\u8FC7") || result.includes("\u901A\u8FC7") || !result.includes("\u4E0D\u901A\u8FC7");
|
|
2434
|
+
const issueMatches = result.match(/问题[::]\s*([\s\S]*?)(?=建议|$)/i);
|
|
2435
|
+
if (issueMatches) {
|
|
2436
|
+
const issueList = issueMatches[1].split(/[\n-]/).filter((s) => s.trim());
|
|
2437
|
+
issues.push(...issueList.map((s) => s.trim()).filter((s) => s));
|
|
2438
|
+
}
|
|
2439
|
+
const suggestionMatches = result.match(/建议[::]\s*([\s\S]*?)$/i);
|
|
2440
|
+
if (suggestionMatches) {
|
|
2441
|
+
const suggestionList = suggestionMatches[1].split(/[\n-]/).filter((s) => s.trim());
|
|
2442
|
+
suggestions.push(...suggestionList.map((s) => s.trim()).filter((s) => s));
|
|
2443
|
+
}
|
|
2444
|
+
if (issues.length === 0 && !passed) {
|
|
2445
|
+
const lines = result.split("\n").filter((l) => l.includes("\u95EE\u9898") || l.includes("\u9519\u8BEF") || l.includes("\u7F3A\u9677"));
|
|
2446
|
+
issues.push(...lines.map((l) => l.replace(/^[-*]\s*/, "").trim()).filter((l) => l));
|
|
2447
|
+
}
|
|
2448
|
+
if (suggestions.length === 0) {
|
|
2449
|
+
const lines = result.split("\n").filter((l) => l.includes("\u5EFA\u8BAE") || l.includes("\u6539\u8FDB") || l.includes("\u4F18\u5316"));
|
|
2450
|
+
suggestions.push(...lines.map((l) => l.replace(/^[-*]\s*/, "").trim()).filter((l) => l));
|
|
2451
|
+
}
|
|
2452
|
+
return { passed, issues, suggestions };
|
|
2453
|
+
} catch (error) {
|
|
2454
|
+
suggestions.push(`\u5BA1\u6838\u8FC7\u7A0B\u51FA\u9519: ${error.message}`);
|
|
2455
|
+
return { passed: true, issues, suggestions };
|
|
2456
|
+
}
|
|
2457
|
+
}
|
|
1994
2458
|
async function readProjectContext(workingDir) {
|
|
1995
2459
|
const context = {
|
|
1996
2460
|
name: path7__namespace.basename(workingDir),
|
|
@@ -2072,8 +2536,11 @@ function analyzeComplexity(requirement, context) {
|
|
|
2072
2536
|
if (!context.framework) score += 0.5;
|
|
2073
2537
|
return Math.max(1, Math.min(10, Math.round(score)));
|
|
2074
2538
|
}
|
|
2075
|
-
function generateBDDScenarios(requirement, context) {
|
|
2539
|
+
function generateBDDScenarios(requirement, context, questions) {
|
|
2076
2540
|
const scenarios = [];
|
|
2541
|
+
questions.find((q) => q.category === "ui" && q.answered)?.answer;
|
|
2542
|
+
const interactionAnswer = questions.find((q) => q.category === "interaction" && q.answered)?.answer;
|
|
2543
|
+
const edgeAnswer = questions.find((q) => q.category === "edge" && q.answered)?.answer;
|
|
2077
2544
|
const features = extractFeatures(requirement);
|
|
2078
2545
|
for (const feature of features) {
|
|
2079
2546
|
const scenario = {
|
|
@@ -2087,12 +2554,20 @@ function generateBDDScenarios(requirement, context) {
|
|
|
2087
2554
|
when: [`\u7528\u6237\u6267\u884C "${feature.title}" \u64CD\u4F5C`],
|
|
2088
2555
|
then: [`\u7CFB\u7EDF\u5E94\u6B63\u786E\u5904\u7406\u5E76\u8FD4\u56DE\u9884\u671F\u7ED3\u679C`]
|
|
2089
2556
|
});
|
|
2090
|
-
if (
|
|
2557
|
+
if (interactionAnswer) {
|
|
2091
2558
|
scenario.scenarios.push({
|
|
2092
|
-
name: `\
|
|
2093
|
-
given: [`\u7528\u6237\u8FDB\u5165\
|
|
2094
|
-
when: [`\u7528\u6237\
|
|
2095
|
-
then: [`\u7CFB\u7EDF\u5E94\
|
|
2559
|
+
name: `\u4EA4\u4E92\u6D41\u7A0B: \u7528\u6237\u64CD\u4F5C`,
|
|
2560
|
+
given: [`\u7528\u6237\u8FDB\u5165\u529F\u80FD\u754C\u9762`],
|
|
2561
|
+
when: [`\u7528\u6237\u6309\u7167\u4EE5\u4E0B\u6D41\u7A0B\u64CD\u4F5C: ${interactionAnswer}`],
|
|
2562
|
+
then: [`\u7CFB\u7EDF\u54CD\u5E94\u5E76\u5B8C\u6210\u529F\u80FD`]
|
|
2563
|
+
});
|
|
2564
|
+
}
|
|
2565
|
+
if (feature.hasInput || edgeAnswer) {
|
|
2566
|
+
scenario.scenarios.push({
|
|
2567
|
+
name: `\u8FB9\u754C\u60C5\u51B5: \u5F02\u5E38\u5904\u7406`,
|
|
2568
|
+
given: [`\u7528\u6237\u8FDB\u5165\u529F\u80FD\u754C\u9762`],
|
|
2569
|
+
when: [`\u53D1\u751F\u5F02\u5E38\u60C5\u51B5${edgeAnswer ? `: ${edgeAnswer}` : ""}`],
|
|
2570
|
+
then: [`\u7CFB\u7EDF\u5E94\u6B63\u786E\u5904\u7406\u5F02\u5E38\u5E76\u7ED9\u51FA\u63D0\u793A`]
|
|
2096
2571
|
});
|
|
2097
2572
|
}
|
|
2098
2573
|
scenarios.push(scenario);
|
|
@@ -2139,7 +2614,7 @@ function extractFeatures(requirement) {
|
|
|
2139
2614
|
}
|
|
2140
2615
|
return features;
|
|
2141
2616
|
}
|
|
2142
|
-
function generateSpecItems(requirement, context, bddScenarios) {
|
|
2617
|
+
function generateSpecItems(requirement, context, bddScenarios, questions) {
|
|
2143
2618
|
const items = [];
|
|
2144
2619
|
let id = 1;
|
|
2145
2620
|
for (const scenario of bddScenarios) {
|
|
@@ -2176,11 +2651,33 @@ function formatSpecFile(session) {
|
|
|
2176
2651
|
lines.push(`# \u9700\u6C42\u89C4\u683C: ${session.requirement.slice(0, 50)}`);
|
|
2177
2652
|
lines.push("");
|
|
2178
2653
|
lines.push(`> \u53D8\u66F4ID: ${session.id}`);
|
|
2654
|
+
lines.push(`> \u9700\u6C42\u6E05\u6670\u5EA6: ${Math.round(session.clarityScore * 100)}%`);
|
|
2179
2655
|
lines.push(`> \u590D\u6742\u5EA6: ${session.complexity}/10`);
|
|
2180
2656
|
lines.push(`> \u751F\u6210\u65F6\u95F4: ${session.createdAt.toISOString()}`);
|
|
2181
2657
|
lines.push("");
|
|
2182
2658
|
lines.push("---");
|
|
2183
2659
|
lines.push("");
|
|
2660
|
+
if (session.refinedRequirement !== session.requirement) {
|
|
2661
|
+
lines.push("## \u9700\u6C42\u8BE6\u60C5");
|
|
2662
|
+
lines.push("");
|
|
2663
|
+
lines.push(session.refinedRequirement);
|
|
2664
|
+
lines.push("");
|
|
2665
|
+
lines.push("---");
|
|
2666
|
+
lines.push("");
|
|
2667
|
+
}
|
|
2668
|
+
if (session.clarificationQuestions.some((q) => q.answered)) {
|
|
2669
|
+
lines.push("## \u9700\u6C42\u6F84\u6E05");
|
|
2670
|
+
lines.push("");
|
|
2671
|
+
for (const q of session.clarificationQuestions) {
|
|
2672
|
+
if (q.answered) {
|
|
2673
|
+
lines.push(`**Q: ${q.question}**`);
|
|
2674
|
+
lines.push(`A: ${q.answer}`);
|
|
2675
|
+
lines.push("");
|
|
2676
|
+
}
|
|
2677
|
+
}
|
|
2678
|
+
lines.push("---");
|
|
2679
|
+
lines.push("");
|
|
2680
|
+
}
|
|
2184
2681
|
lines.push("## BDD \u573A\u666F");
|
|
2185
2682
|
lines.push("");
|
|
2186
2683
|
for (const scenario of session.bddScenarios) {
|
|
@@ -2244,11 +2741,17 @@ async function archiveWorkflow(workingDir) {
|
|
|
2244
2741
|
const content = `# \u5F52\u6863: ${activeSession.requirement.slice(0, 50)}
|
|
2245
2742
|
|
|
2246
2743
|
> \u5F52\u6863\u65F6\u95F4: ${(/* @__PURE__ */ new Date()).toISOString()}
|
|
2744
|
+
> \u9700\u6C42\u6E05\u6670\u5EA6: ${Math.round(activeSession.clarityScore * 100)}%
|
|
2247
2745
|
> \u590D\u6742\u5EA6: ${activeSession.complexity}/10
|
|
2248
2746
|
|
|
2747
|
+
## \u9700\u6C42\u8BE6\u60C5
|
|
2748
|
+
|
|
2749
|
+
${activeSession.refinedRequirement}
|
|
2750
|
+
|
|
2249
2751
|
## \u5B8C\u6210\u60C5\u51B5
|
|
2250
2752
|
|
|
2251
2753
|
- [x] \u9879\u76EE\u4E0A\u4E0B\u6587\u83B7\u53D6
|
|
2754
|
+
- [x] \u9700\u6C42\u6F84\u6E05
|
|
2252
2755
|
- [x] \u590D\u6742\u5EA6\u8BC4\u4F30
|
|
2253
2756
|
- [x] BDD \u573A\u666F\u62C6\u89E3
|
|
2254
2757
|
- [x] OpenSpec \u89C4\u683C
|
|
@@ -2275,6 +2778,7 @@ function generateComplexityBar(score) {
|
|
|
2275
2778
|
function getPhaseLabel(phase) {
|
|
2276
2779
|
const labels = {
|
|
2277
2780
|
context: "\u9879\u76EE\u4E0A\u4E0B\u6587\u83B7\u53D6",
|
|
2781
|
+
clarify: "\u9700\u6C42\u6F84\u6E05",
|
|
2278
2782
|
analysis: "\u590D\u6742\u5EA6\u8BC4\u4F30",
|
|
2279
2783
|
bdd: "BDD \u573A\u666F\u62C6\u89E3",
|
|
2280
2784
|
spec: "OpenSpec \u89C4\u683C",
|
|
@@ -2290,12 +2794,13 @@ function getActiveSession() {
|
|
|
2290
2794
|
function clearActiveSession() {
|
|
2291
2795
|
activeSession = null;
|
|
2292
2796
|
}
|
|
2293
|
-
var MAX_FILE_SIZE2, COMPLEXITY_THRESHOLD, activeSession, new_default;
|
|
2797
|
+
var MAX_FILE_SIZE2, COMPLEXITY_THRESHOLD, CLARITY_THRESHOLD, activeSession, new_default;
|
|
2294
2798
|
var init_new = __esm({
|
|
2295
2799
|
"src/commands/new.ts"() {
|
|
2296
2800
|
init_cjs_shims();
|
|
2297
2801
|
MAX_FILE_SIZE2 = 1024 * 1024;
|
|
2298
2802
|
COMPLEXITY_THRESHOLD = 6;
|
|
2803
|
+
CLARITY_THRESHOLD = 0.6;
|
|
2299
2804
|
activeSession = null;
|
|
2300
2805
|
new_default = handleNew;
|
|
2301
2806
|
}
|
|
@@ -6879,6 +7384,7 @@ var STEP_DISPLAY_NAMES = {
|
|
|
6879
7384
|
"apply": "\u5BA1\u67E5",
|
|
6880
7385
|
"archive": "\u5F52\u6863",
|
|
6881
7386
|
"context": "\u4E0A\u4E0B\u6587",
|
|
7387
|
+
"clarify": "\u6F84\u6E05",
|
|
6882
7388
|
"analysis": "\u5206\u6790",
|
|
6883
7389
|
"bdd": "BDD",
|
|
6884
7390
|
"spec": "\u89C4\u683C",
|
|
@@ -6894,6 +7400,7 @@ var STEP_COLORS = {
|
|
|
6894
7400
|
"apply": chalk9__default.default.yellow,
|
|
6895
7401
|
"archive": chalk9__default.default.gray,
|
|
6896
7402
|
"context": chalk9__default.default.magenta,
|
|
7403
|
+
"clarify": chalk9__default.default.yellow,
|
|
6897
7404
|
"analysis": chalk9__default.default.blue,
|
|
6898
7405
|
"bdd": chalk9__default.default.cyan,
|
|
6899
7406
|
"spec": chalk9__default.default.green,
|