speccore 6.33.0 → 6.35.0
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/commands/iteration/split.d.ts.map +1 -1
- package/dist/commands/iteration/split.js +27 -10
- package/dist/commands/iteration/split.js.map +1 -1
- package/dist/core/analyze-engine.d.ts.map +1 -1
- package/dist/core/analyze-engine.js +179 -25
- package/dist/core/analyze-engine.js.map +1 -1
- package/dist/core/knowledge-graph.d.ts.map +1 -1
- package/dist/core/knowledge-graph.js +34 -19
- package/dist/core/knowledge-graph.js.map +1 -1
- package/dist/core/prompt-builder.d.ts.map +1 -1
- package/dist/core/prompt-builder.js +6 -3
- package/dist/core/prompt-builder.js.map +1 -1
- package/package.json +1 -1
|
@@ -1665,47 +1665,56 @@ async function generateSpecsFromRequirements(reqPaths, iteration, specDir) {
|
|
|
1665
1665
|
const now = new Date().toISOString().split('T')[0];
|
|
1666
1666
|
// 3. 生成各 Spec 文件
|
|
1667
1667
|
const files = [];
|
|
1668
|
-
//
|
|
1668
|
+
// ── 全局文档(跨端通用)──
|
|
1669
|
+
// REQUIREMENT.md — 结构化需求规格(业务功能 + API + 数据模型 + 业务规则)
|
|
1669
1670
|
files.push({
|
|
1670
1671
|
filename: 'REQUIREMENT.md',
|
|
1671
1672
|
content: buildRequirementSpec(iteration, now, features, apis, dataModels, businessRules),
|
|
1672
1673
|
});
|
|
1673
|
-
//
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
content: buildTechSpec(iteration, now, apis, dataModels, archImpact, platforms, features, uiPatterns),
|
|
1677
|
-
});
|
|
1678
|
-
// TEST.md — 测试计划
|
|
1674
|
+
// ANALYSIS.md — 需求分析报告(完整性检查 + 架构影响 + 待确认清单)
|
|
1675
|
+
const issues = scanCompleteness(fullContent);
|
|
1676
|
+
const archImpactForAnalysis = await analyzeArchitectureImpact(fullContent);
|
|
1679
1677
|
files.push({
|
|
1680
|
-
filename: '
|
|
1681
|
-
content:
|
|
1678
|
+
filename: 'ANALYSIS.md',
|
|
1679
|
+
content: buildIterationReqReport({}, issues, archImpactForAnalysis, {}),
|
|
1682
1680
|
});
|
|
1683
|
-
//
|
|
1681
|
+
// DEPS.md — 依赖清单(全局公共依赖)
|
|
1684
1682
|
files.push({
|
|
1685
|
-
filename: '
|
|
1686
|
-
content:
|
|
1683
|
+
filename: 'DEPS.md',
|
|
1684
|
+
content: buildDepsSpec(iteration, now, archImpact),
|
|
1687
1685
|
});
|
|
1688
|
-
// RISK.md —
|
|
1686
|
+
// RISK.md — 风险评估(全局风险)
|
|
1689
1687
|
files.push({
|
|
1690
1688
|
filename: 'RISK.md',
|
|
1691
1689
|
content: buildRiskSpec(iteration, now, archImpact),
|
|
1692
1690
|
});
|
|
1693
|
-
//
|
|
1694
|
-
files.push({
|
|
1695
|
-
filename: 'DEPS.md',
|
|
1696
|
-
content: buildDepsSpec(iteration, now, archImpact),
|
|
1697
|
-
});
|
|
1698
|
-
// MONITOR.md — 监控指标
|
|
1691
|
+
// MONITOR.md — 监控指标(全局指标)
|
|
1699
1692
|
files.push({
|
|
1700
1693
|
filename: 'MONITOR.md',
|
|
1701
1694
|
content: buildMonitorSpec(iteration, now, apis, features),
|
|
1702
1695
|
});
|
|
1703
|
-
//
|
|
1696
|
+
// REVIEW.md — 评审清单(全局评审要点)
|
|
1704
1697
|
files.push({
|
|
1705
|
-
filename: '
|
|
1706
|
-
content:
|
|
1698
|
+
filename: 'REVIEW.md',
|
|
1699
|
+
content: buildReviewSpec(iteration, now, apis, archImpact),
|
|
1707
1700
|
});
|
|
1708
|
-
//
|
|
1701
|
+
// ── 各端专属文档 ──
|
|
1702
|
+
for (const platform of platforms) {
|
|
1703
|
+
const platformDir = (0, path_1.join)(specDir, platform);
|
|
1704
|
+
await (0, fs_extra_1.ensureDir)(platformDir);
|
|
1705
|
+
// TECH.md — 该端技术方案
|
|
1706
|
+
const techContent = buildTechSpecForPlatform(iteration, now, apis, dataModels, archImpact, platform, features, uiPatterns);
|
|
1707
|
+
await (0, fs_extra_1.writeFile)((0, path_1.join)(platformDir, 'TECH.md'), techContent);
|
|
1708
|
+
// TEST.md — 该端测试计划
|
|
1709
|
+
const testContent = buildTestSpecForPlatform(iteration, now, features, apis, platform);
|
|
1710
|
+
await (0, fs_extra_1.writeFile)((0, path_1.join)(platformDir, 'TEST.md'), testContent);
|
|
1711
|
+
// UI_SPEC.md — 该端 UI 规格(仅前端)
|
|
1712
|
+
if (!isBackendPlatform(platform)) {
|
|
1713
|
+
const uiContent = buildUISpecForPlatform(iteration, now, uiPatterns, platform);
|
|
1714
|
+
await (0, fs_extra_1.writeFile)((0, path_1.join)(platformDir, 'UI_SPEC.md'), uiContent);
|
|
1715
|
+
}
|
|
1716
|
+
}
|
|
1717
|
+
// 4. 写入全局文件(覆盖空模板,不覆盖已有实质内容的文件)
|
|
1709
1718
|
let withContent = 0;
|
|
1710
1719
|
let skipped = 0;
|
|
1711
1720
|
await (0, fs_extra_1.ensureDir)(specDir);
|
|
@@ -1725,7 +1734,7 @@ async function generateSpecsFromRequirements(reqPaths, iteration, specDir) {
|
|
|
1725
1734
|
}
|
|
1726
1735
|
return {
|
|
1727
1736
|
files,
|
|
1728
|
-
summary: { total: files.length, withContent, skipped },
|
|
1737
|
+
summary: { total: files.length + platforms.length * 3, withContent, skipped },
|
|
1729
1738
|
};
|
|
1730
1739
|
}
|
|
1731
1740
|
// ── 信息提取工具函数 ──
|
|
@@ -1829,6 +1838,10 @@ function extractBusinessRules(content) {
|
|
|
1829
1838
|
}
|
|
1830
1839
|
return rules.slice(0, 15);
|
|
1831
1840
|
}
|
|
1841
|
+
// ── 辅助函数:判断是否为后端平台 ──
|
|
1842
|
+
function isBackendPlatform(platform) {
|
|
1843
|
+
return platform === 'backend' || platform.startsWith('后台') || platform.includes('服务');
|
|
1844
|
+
}
|
|
1832
1845
|
function stripTemplateNoise(content) {
|
|
1833
1846
|
// 移除模板占位符后计算有效内容长度
|
|
1834
1847
|
return content
|
|
@@ -1952,7 +1965,148 @@ function buildTechSpec(iter, now, apis, models, archImpact, platforms, features,
|
|
|
1952
1965
|
}
|
|
1953
1966
|
return md;
|
|
1954
1967
|
}
|
|
1955
|
-
// ──
|
|
1968
|
+
// ── 按端专属文档构建器 ──
|
|
1969
|
+
/**
|
|
1970
|
+
* 生成指定端的技术方案(该端专属内容)
|
|
1971
|
+
*/
|
|
1972
|
+
function buildTechSpecForPlatform(iter, now, apis, models, archImpact, platform, features, uiPatterns) {
|
|
1973
|
+
let md = `# ${platform} 端技术方案\n\n> 迭代: ${iter} | 端: ${platform} | 生成: ${now}\n\n`;
|
|
1974
|
+
if (isBackendPlatform(platform)) {
|
|
1975
|
+
// 后端专属内容
|
|
1976
|
+
md += `## 1. 接口设计\n\n`;
|
|
1977
|
+
const backendApis = apis.filter(a => !a.path.startsWith('/h5') && !a.path.startsWith('/admin'));
|
|
1978
|
+
if (backendApis.length > 0) {
|
|
1979
|
+
md += `| 方法 | 路径 | 说明 |\n| :--- | :--- | :--- |\n`;
|
|
1980
|
+
backendApis.forEach(a => { md += `| ${a.method} | \`${a.path}\` | ${a.desc || '—'} |\n`; });
|
|
1981
|
+
}
|
|
1982
|
+
else {
|
|
1983
|
+
md += `_未检测到后端 API,需根据需求补充。_\n`;
|
|
1984
|
+
}
|
|
1985
|
+
md += `\n## 2. 数据模型\n\n`;
|
|
1986
|
+
if (models.length > 0) {
|
|
1987
|
+
md += `| 表名 | 字段 | 说明 |\n| :--- | :--- | :--- |\n`;
|
|
1988
|
+
models.forEach(m => { md += `| \`${m.table}\` | ${m.fields || '待补充'} | ${m.desc} |\n`; });
|
|
1989
|
+
}
|
|
1990
|
+
else {
|
|
1991
|
+
md += `_需求中未检测到数据模型,需根据功能需求推导。_\n`;
|
|
1992
|
+
}
|
|
1993
|
+
md += `\n## 3. 业务逻辑\n\n`;
|
|
1994
|
+
md += `_待 AI 分析各功能的实现细节、事务约束、异常处理。_\n`;
|
|
1995
|
+
}
|
|
1996
|
+
else {
|
|
1997
|
+
// 前端专属内容
|
|
1998
|
+
md += `## 1. 页面结构\n\n`;
|
|
1999
|
+
const platformPages = uiPatterns.pages.filter(p => p.route.includes(`/${platform}`) || p.name.includes(platform));
|
|
2000
|
+
if (platformPages.length > 0) {
|
|
2001
|
+
md += `| 页面 | 路由 | 描述 |\n| :--- | :--- | :--- |\n`;
|
|
2002
|
+
platformPages.forEach(p => { md += `| ${p.name} | \`${p.route}\` | ${p.desc} |\n`; });
|
|
2003
|
+
}
|
|
2004
|
+
else {
|
|
2005
|
+
md += `_待补充:从需求中提取 ${platform} 端的页面清单。_\n`;
|
|
2006
|
+
}
|
|
2007
|
+
md += `\n## 2. 组件设计\n\n`;
|
|
2008
|
+
const platformComponents = uiPatterns.components.filter(c => c.page.includes(platform) || c.type.includes(platform));
|
|
2009
|
+
if (platformComponents.length > 0) {
|
|
2010
|
+
md += `| 组件 | 类型 | 所属页面 |\n| :--- | :--- | :--- |\n`;
|
|
2011
|
+
platformComponents.forEach(c => { md += `| ${c.name} | ${c.type} | ${c.page} |\n`; });
|
|
2012
|
+
}
|
|
2013
|
+
else {
|
|
2014
|
+
md += `_待补充:从需求中提取 ${platform} 端的组件清单。_\n`;
|
|
2015
|
+
}
|
|
2016
|
+
md += `\n## 3. 状态管理\n\n`;
|
|
2017
|
+
md += `_待 AI 分析 ${platform} 端的状态管理方案(Pinia/Redux/Context 等)。_\n`;
|
|
2018
|
+
md += `\n## 4. 交互设计\n\n`;
|
|
2019
|
+
if (platform === 'h5' || platform === 'miniapp') {
|
|
2020
|
+
md += `- 触摸交互优化\n- 弱网环境适配\n- 响应式布局\n`;
|
|
2021
|
+
}
|
|
2022
|
+
else if (platform === 'admin') {
|
|
2023
|
+
md += `- 表格/表单交互规范\n- 权限控制\n- 批量操作\n`;
|
|
2024
|
+
}
|
|
2025
|
+
else {
|
|
2026
|
+
md += `_待补充 ${platform} 端特有的交互要求。_\n`;
|
|
2027
|
+
}
|
|
2028
|
+
}
|
|
2029
|
+
return md;
|
|
2030
|
+
}
|
|
2031
|
+
/**
|
|
2032
|
+
* 生成指定端的测试计划(该端专属内容)
|
|
2033
|
+
*/
|
|
2034
|
+
function buildTestSpecForPlatform(iter, now, features, apis, platform) {
|
|
2035
|
+
let md = `# ${platform} 端测试计划\n\n> 迭代: ${iter} | 端: ${platform} | 生成: ${now}\n\n`;
|
|
2036
|
+
if (isBackendPlatform(platform)) {
|
|
2037
|
+
md += `## 1. 接口测试\n\n`;
|
|
2038
|
+
const backendApis = apis.filter(a => !a.path.startsWith('/h5') && !a.path.startsWith('/admin'));
|
|
2039
|
+
if (backendApis.length > 0) {
|
|
2040
|
+
backendApis.forEach(a => {
|
|
2041
|
+
md += `- [ ] ${a.method} ${a.path}: ${a.desc || '验证接口功能'}\n`;
|
|
2042
|
+
});
|
|
2043
|
+
}
|
|
2044
|
+
else {
|
|
2045
|
+
md += `_待补充:根据需求编写接口测试用例。_\n`;
|
|
2046
|
+
}
|
|
2047
|
+
md += `\n## 2. 性能测试\n\n`;
|
|
2048
|
+
md += `- QPS 目标:待补充\n- 响应时间 P99:待补充\n- 并发用户数:待补充\n`;
|
|
2049
|
+
}
|
|
2050
|
+
else {
|
|
2051
|
+
md += `## 1. 页面流转测试\n\n`;
|
|
2052
|
+
md += `_待 AI 分析 ${platform} 端的页面跳转流程、入口校验、权限拦截。_\n`;
|
|
2053
|
+
md += `\n## 2. 交互测试\n\n`;
|
|
2054
|
+
if (platform === 'h5' || platform === 'miniapp') {
|
|
2055
|
+
md += `- 触摸手势识别\n- 下拉刷新/上拉加载\n- 键盘弹出适配\n`;
|
|
2056
|
+
}
|
|
2057
|
+
else if (platform === 'admin') {
|
|
2058
|
+
md += `- 表格排序/筛选/分页\n- 表单校验提示\n- 批量操作确认\n`;
|
|
2059
|
+
}
|
|
2060
|
+
md += `\n## 3. 四态测试\n\n`;
|
|
2061
|
+
md += `- 空状态(无数据时展示)\n- 加载中状态\n- 错误状态(网络异常/超时)\n- 成功状态\n`;
|
|
2062
|
+
}
|
|
2063
|
+
return md;
|
|
2064
|
+
}
|
|
2065
|
+
/**
|
|
2066
|
+
* 生成指定端的 UI 规格(仅前端)
|
|
2067
|
+
*/
|
|
2068
|
+
function buildUISpecForPlatform(iter, now, uiPatterns, platform) {
|
|
2069
|
+
let md = `# ${platform} 端 UI 规格\n\n> 迭代: ${iter} | 端: ${platform} | 生成: ${now}\n\n`;
|
|
2070
|
+
md += `## 1. 路由表\n\n`;
|
|
2071
|
+
const platformPages = uiPatterns.pages.filter(p => p.route.includes(`/${platform}`) || p.name.includes(platform));
|
|
2072
|
+
if (platformPages.length > 0) {
|
|
2073
|
+
md += `| 页面 | 路由 | 入口 | 权限 |\n| :--- | :--- | :--- | :--- |\n`;
|
|
2074
|
+
platformPages.forEach(p => { md += `| ${p.name} | \`${p.route}\` | 待补充 | 待补充 |\n`; });
|
|
2075
|
+
}
|
|
2076
|
+
else {
|
|
2077
|
+
md += `_待补充:从需求中提取 ${platform} 端的路由配置。_\n`;
|
|
2078
|
+
}
|
|
2079
|
+
md += `\n## 2. 组件清单\n\n`;
|
|
2080
|
+
const platformComponents = uiPatterns.components.filter(c => c.page.includes(platform) || c.type.includes(platform));
|
|
2081
|
+
if (platformComponents.length > 0) {
|
|
2082
|
+
md += `| 组件 | 类型 | 复用性 |\n| :--- | :--- | :--- |\n`;
|
|
2083
|
+
platformComponents.forEach(c => { md += `| ${c.name} | ${c.type} | 高/中/低 |\n`; });
|
|
2084
|
+
}
|
|
2085
|
+
else {
|
|
2086
|
+
md += `_待补充:从需求中提取 ${platform} 端的组件清单。_\n`;
|
|
2087
|
+
}
|
|
2088
|
+
md += `\n## 3. 字段→UI 映射\n\n`;
|
|
2089
|
+
const platformFields = uiPatterns.formFields.filter(f => f.page.includes(platform));
|
|
2090
|
+
if (platformFields.length > 0) {
|
|
2091
|
+
md += `| 页面/表单 | 字段 | UI 组件 |\n| :--- | :--- | :--- |\n`;
|
|
2092
|
+
platformFields.forEach(f => { md += `| ${f.page} | ${f.fields.join(', ')} | Input/Select/DatePicker |\n`; });
|
|
2093
|
+
}
|
|
2094
|
+
else {
|
|
2095
|
+
md += `_待补充:从需求中提取 ${platform} 端的字段与 UI 映射关系。_\n`;
|
|
2096
|
+
}
|
|
2097
|
+
md += `\n## 4. 状态枚举\n\n`;
|
|
2098
|
+
if (uiPatterns.statusEnums.length > 0) {
|
|
2099
|
+
md += `| 字段 | 值 | 含义 |\n| :--- | :--- | :--- |\n`;
|
|
2100
|
+
uiPatterns.statusEnums.forEach(s => {
|
|
2101
|
+
md += `| ${s.field} | ${s.values.join(' / ')} | ${s.labels.join(' / ')} |\n`;
|
|
2102
|
+
});
|
|
2103
|
+
}
|
|
2104
|
+
else {
|
|
2105
|
+
md += `_待补充:前后端共享的状态值定义。_\n`;
|
|
2106
|
+
}
|
|
2107
|
+
return md;
|
|
2108
|
+
}
|
|
2109
|
+
// ─ UI 规格提取与构建 ──
|
|
1956
2110
|
function extractUIPatterns(content) {
|
|
1957
2111
|
const pages = [];
|
|
1958
2112
|
const components = [];
|