speccore 6.77.6 → 6.80.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/cli.js +1 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/analyze.d.ts +1 -0
- package/dist/commands/analyze.d.ts.map +1 -1
- package/dist/commands/analyze.js +251 -59
- package/dist/commands/analyze.js.map +1 -1
- package/dist/commands/audit.js +5 -5
- package/dist/commands/audit.js.map +1 -1
- package/dist/commands/execute.d.ts.map +1 -1
- package/dist/commands/execute.js +47 -104
- package/dist/commands/execute.js.map +1 -1
- package/dist/commands/iteration/split.js +83 -35
- package/dist/commands/iteration/split.js.map +1 -1
- package/dist/core/ai-context-generator.js +1 -1
- package/dist/core/ai-context-generator.js.map +1 -1
- package/dist/core/analyze-context-guard.js +5 -5
- package/dist/core/analyze-context-guard.js.map +1 -1
- package/dist/core/ask-engine.d.ts.map +1 -1
- package/dist/core/ask-engine.js +12 -3
- package/dist/core/ask-engine.js.map +1 -1
- package/dist/core/incremental-analyzer.js +6 -6
- package/dist/core/incremental-analyzer.js.map +1 -1
- package/dist/core/intent-recognition.d.ts.map +1 -1
- package/dist/core/intent-recognition.js +8 -0
- package/dist/core/intent-recognition.js.map +1 -1
- package/dist/core/module-analyzer.js +15 -15
- package/dist/core/module-analyzer.js.map +1 -1
- package/dist/core/next-steps.js +1 -1
- package/dist/core/next-steps.js.map +1 -1
- package/dist/core/pipeline-engine.d.ts +2 -0
- package/dist/core/pipeline-engine.d.ts.map +1 -1
- package/dist/core/pipeline-engine.js +20 -0
- package/dist/core/pipeline-engine.js.map +1 -1
- package/dist/core/platform-addition.js +6 -6
- package/dist/core/platform-addition.js.map +1 -1
- package/dist/core/prompt-builder.d.ts.map +1 -1
- package/dist/core/prompt-builder.js +48 -6
- package/dist/core/prompt-builder.js.map +1 -1
- package/dist/core/requirement-clarifier.d.ts +32 -1
- package/dist/core/requirement-clarifier.d.ts.map +1 -1
- package/dist/core/requirement-clarifier.js +284 -1
- package/dist/core/requirement-clarifier.js.map +1 -1
- package/dist/core/spec-paths.d.ts +8 -8
- package/dist/core/spec-paths.d.ts.map +1 -1
- package/dist/core/spec-paths.js +14 -9
- package/dist/core/spec-paths.js.map +1 -1
- package/dist/core/streaming-analyzer.d.ts.map +1 -1
- package/dist/core/streaming-analyzer.js +22 -19
- package/dist/core/streaming-analyzer.js.map +1 -1
- package/dist/core/verify-engine.d.ts +7 -0
- package/dist/core/verify-engine.d.ts.map +1 -1
- package/dist/core/verify-engine.js +57 -0
- package/dist/core/verify-engine.js.map +1 -1
- package/package.json +1 -1
package/dist/commands/analyze.js
CHANGED
|
@@ -63,6 +63,8 @@ const unified_retrieval_1 = require("../core/unified-retrieval");
|
|
|
63
63
|
const pipeline_engine_1 = require("../core/pipeline-engine");
|
|
64
64
|
const change_detection_1 = require("../core/change-detection");
|
|
65
65
|
const streaming_analyzer_1 = require("../core/streaming-analyzer");
|
|
66
|
+
// v6.80.0+: 需求澄清模块
|
|
67
|
+
const requirement_clarifier_1 = require("../core/requirement-clarifier");
|
|
66
68
|
async function analyzeCommand(options) {
|
|
67
69
|
// ── --full / --phase 模式: 委托给 synthesizeCommand(原 synthesize 命令) ──
|
|
68
70
|
if (options.full || options.phase) {
|
|
@@ -538,15 +540,17 @@ async function analyzeCommand(options) {
|
|
|
538
540
|
initStep = 'init';
|
|
539
541
|
}
|
|
540
542
|
else {
|
|
541
|
-
// 迭代层:使用 createAnalyzePipeline(支持契约先行 + 逐端推进 + 变更感知 +
|
|
543
|
+
// 迭代层:使用 createAnalyzePipeline(支持契约先行 + 逐端推进 + 变更感知 + 关键路径优先 + 需求澄清)
|
|
542
544
|
const result = await (0, pipeline_engine_1.createAnalyzePipeline)(iter, process.cwd(), {
|
|
543
545
|
affectedPlatforms: affectedPlatforms && affectedPlatforms.length > 0 ? affectedPlatforms : undefined,
|
|
544
546
|
platformOrder: platformOrder && platformOrder.length > 0 ? platformOrder : undefined,
|
|
547
|
+
skipClarify: options.skipClarify,
|
|
545
548
|
});
|
|
546
549
|
engine = result.engine;
|
|
547
550
|
steps = result.steps;
|
|
548
551
|
pipelineKey = iter;
|
|
549
|
-
|
|
552
|
+
// v6.80.0+: 默认从 clarify 开始,skipClarify 时从 phase1 开始
|
|
553
|
+
initStep = options.skipClarify ? 'phase1-prompt' : 'clarify-prompt';
|
|
550
554
|
}
|
|
551
555
|
// 检查是否有活跃的 Pipeline(恢复模式)
|
|
552
556
|
const hasActive = await pipeline_engine_1.PipelineEngine.hasActivePipeline(process.cwd(), pipelineKey);
|
|
@@ -591,6 +595,14 @@ async function analyzeCommand(options) {
|
|
|
591
595
|
}, options);
|
|
592
596
|
}
|
|
593
597
|
}
|
|
598
|
+
else if (currentStep === 'clarify-prompt') {
|
|
599
|
+
// v6.80.0+: Phase 0 需求澄清
|
|
600
|
+
prompt = await buildClarifyPhasePrompt(iter);
|
|
601
|
+
}
|
|
602
|
+
else if (currentStep === 'confirm-check') {
|
|
603
|
+
// v6.80.0+: 需求确认阶段 — 输出质量报告提示
|
|
604
|
+
prompt = await buildConfirmCheckPrompt(iter);
|
|
605
|
+
}
|
|
594
606
|
else if (currentStep === 'phase1-prompt') {
|
|
595
607
|
prompt = await buildMultiDocPrompt('analyze', {
|
|
596
608
|
iteration: iter, task: options.task, type: options.type,
|
|
@@ -628,13 +640,17 @@ async function analyzeCommand(options) {
|
|
|
628
640
|
: '全局 Pipeline';
|
|
629
641
|
}
|
|
630
642
|
else {
|
|
631
|
-
progressLabel = currentStep === '
|
|
632
|
-
? 'Phase
|
|
633
|
-
: currentStep === '
|
|
634
|
-
? 'Phase
|
|
635
|
-
:
|
|
636
|
-
?
|
|
637
|
-
: '
|
|
643
|
+
progressLabel = currentStep === 'clarify-prompt'
|
|
644
|
+
? 'Phase 0/3: 需求澄清'
|
|
645
|
+
: currentStep === 'confirm-check'
|
|
646
|
+
? 'Phase 0/3: 需求确认'
|
|
647
|
+
: currentStep === 'phase1-prompt'
|
|
648
|
+
? 'Phase 1/3: 迭代综合文档'
|
|
649
|
+
: currentStep === 'contract-prompt'
|
|
650
|
+
? 'Phase 2/3: 契约定义'
|
|
651
|
+
: platformMatch
|
|
652
|
+
? `Phase 2/3: ${platformMatch[1]} 端专属文档`
|
|
653
|
+
: 'Pipeline';
|
|
638
654
|
}
|
|
639
655
|
const finalPrompt = prompt + `\n\n## ⚠️ Pipeline 模式:自动继续 (${progressLabel})\n\n` +
|
|
640
656
|
`当前是 Pipeline 模式(步骤 ${currentStepIndex + 1}/${totalSteps})。` +
|
|
@@ -647,6 +663,18 @@ async function analyzeCommand(options) {
|
|
|
647
663
|
// ── Prompt 模式 ──
|
|
648
664
|
if (options.prompt) {
|
|
649
665
|
const iter = options.scope === 'global' ? 'GLOBAL' : (options.iteration || await (0, context_1.getDefaultIteration)());
|
|
666
|
+
// v6.80.0+: 非 Pipeline 模式下也默认检测需求质量
|
|
667
|
+
if (iter !== 'GLOBAL' && !options.skipClarify && !options.pipeline) {
|
|
668
|
+
const iterDir = await (0, context_1.getIterationDir)(iter);
|
|
669
|
+
const hasClarified = await (0, requirement_clarifier_1.hasValidClarifiedDocs)(iterDir);
|
|
670
|
+
if (!hasClarified) {
|
|
671
|
+
// 未澄清过,先执行 clarify
|
|
672
|
+
const clarifyPrompt = await buildClarifyPhasePrompt(iter);
|
|
673
|
+
process.stdout.write(`[SPECCORE_PROMPT]\n${clarifyPrompt}`);
|
|
674
|
+
process.exitCode = 10;
|
|
675
|
+
return;
|
|
676
|
+
}
|
|
677
|
+
}
|
|
650
678
|
const prompt = await buildMultiDocPrompt('analyze', { iteration: iter, task: options.task, type: options.type, scope: options.scope, withCode: options.withCode, platform: options.platform, phase: options.phase, autoMode: options.auto }, options);
|
|
651
679
|
process.stdout.write(`[SPECCORE_PROMPT]\n${prompt}`);
|
|
652
680
|
process.exitCode = 10;
|
|
@@ -780,6 +808,22 @@ async function analyzeCommand(options) {
|
|
|
780
808
|
const validPlatforms = new Set([spec_paths_1.GLOBAL_SPECS_DIR, ...(await (0, spec_paths_1.parsePlatformList)())]);
|
|
781
809
|
let skippedCount = 0;
|
|
782
810
|
for (const [filename, content] of Object.entries(docs)) {
|
|
811
|
+
// v6.80.0+: 010-requirements/ 路径处理(clarify 结果写入)
|
|
812
|
+
if (filename.startsWith('010-requirements/')) {
|
|
813
|
+
const reqFilePath = filename.slice('010-requirements/'.length);
|
|
814
|
+
const reqDir = (0, path_1.join)(iterDir, '010-requirements');
|
|
815
|
+
const fp = (0, path_1.join)(reqDir, reqFilePath);
|
|
816
|
+
await (0, fs_extra_1.ensureDir)((0, path_1.dirname)(fp));
|
|
817
|
+
// 为 clarified 文件添加头部元信息
|
|
818
|
+
let finalContent = content;
|
|
819
|
+
if (reqFilePath.startsWith('converted/clarified-') && !content.startsWith('---')) {
|
|
820
|
+
finalContent = (0, requirement_clarifier_1.buildClarifiedHeader)(reqFilePath) + content;
|
|
821
|
+
}
|
|
822
|
+
await (0, fs_extra_1.writeFile)(fp, finalContent);
|
|
823
|
+
logger_1.logger.info(` 📝 需求文档已写入: ${reqFilePath}`);
|
|
824
|
+
count++;
|
|
825
|
+
continue;
|
|
826
|
+
}
|
|
783
827
|
// v6.72.0+: PATTERNS/ 文件特殊处理 → 写入 .speccore/PATTERNS/
|
|
784
828
|
if (filename.startsWith('PATTERNS/')) {
|
|
785
829
|
const patternsDir = (0, path_1.join)(process.cwd(), '.speccore', 'PATTERNS');
|
|
@@ -872,7 +916,7 @@ async function analyzeCommand(options) {
|
|
|
872
916
|
}
|
|
873
917
|
}
|
|
874
918
|
// v6.72.0+: FUNCTION_MAP.md 自检
|
|
875
|
-
const fmContent = docs['FUNCTION_MAP.md'] || docs['global/FUNCTION_MAP.md'];
|
|
919
|
+
const fmContent = docs['FUNCTION_MAP.md'] || docs['overview/FUNCTION_MAP.md'] || docs['global/FUNCTION_MAP.md'];
|
|
876
920
|
if (fmContent) {
|
|
877
921
|
const platforms = Array.from(validPlatforms);
|
|
878
922
|
const fmResult = validateFunctionMap(fmContent, platforms);
|
|
@@ -941,7 +985,7 @@ async function analyzeCommand(options) {
|
|
|
941
985
|
}
|
|
942
986
|
}
|
|
943
987
|
else {
|
|
944
|
-
// 迭代级:写 020-specs/
|
|
988
|
+
// 迭代级:写 020-specs/overview/(迭代综合文档,v6.78.0+)
|
|
945
989
|
const specDir = (0, path_1.join)(iterDir, '020-specs');
|
|
946
990
|
const globalDir = (0, path_1.join)(specDir, spec_paths_1.GLOBAL_SPECS_DIR);
|
|
947
991
|
await (0, fs_extra_1.ensureDir)(globalDir);
|
|
@@ -953,7 +997,7 @@ async function analyzeCommand(options) {
|
|
|
953
997
|
logger_1.logger.info(` 📦 旧版已备份: ${iterBackup.split('/').pop()}`);
|
|
954
998
|
}
|
|
955
999
|
await (0, fs_extra_1.writeFile)(iterAnalysisPath, options.apply);
|
|
956
|
-
logger_1.logger.success(`✅ ANALYSIS.md 已写入 020-specs/
|
|
1000
|
+
logger_1.logger.success(`✅ ANALYSIS.md 已写入 020-specs/overview/`);
|
|
957
1001
|
}
|
|
958
1002
|
else {
|
|
959
1003
|
logger_1.logger.info(` ⏭️ 用户取消覆盖`);
|
|
@@ -1050,6 +1094,13 @@ async function analyzeCommand(options) {
|
|
|
1050
1094
|
iteration: options.iteration || 'GLOBAL', scope: 'global', withCode: options.withCode,
|
|
1051
1095
|
});
|
|
1052
1096
|
}
|
|
1097
|
+
// v6.80.0+: clarify 阶段推进
|
|
1098
|
+
}
|
|
1099
|
+
else if (state.currentStep === 'clarify-prompt') {
|
|
1100
|
+
nextPrompt = await buildClarifyPhasePrompt(options.iteration);
|
|
1101
|
+
}
|
|
1102
|
+
else if (state.currentStep === 'confirm-check') {
|
|
1103
|
+
nextPrompt = await buildConfirmCheckPrompt(options.iteration);
|
|
1053
1104
|
}
|
|
1054
1105
|
else if (state.currentStep === 'contract-prompt') {
|
|
1055
1106
|
nextPrompt = await buildContractFirstPrompt(options.iteration);
|
|
@@ -1085,11 +1136,11 @@ async function analyzeCommand(options) {
|
|
|
1085
1136
|
// 检查是否有多个端
|
|
1086
1137
|
const platforms = await (0, spec_paths_1.parsePlatformList)();
|
|
1087
1138
|
// 只有多端项目(≥2 个端)才需要分两阶段:
|
|
1088
|
-
// - Phase 1: 生成综合文档(
|
|
1139
|
+
// - Phase 1: 生成综合文档(overview/REQUIREMENT.md、ANALYSIS.md、DEPS.md)
|
|
1089
1140
|
// - Phase 2: 生成各端专属文档({端}/TECH.md、TEST.md、UI_SPEC.md)
|
|
1090
1141
|
//
|
|
1091
1142
|
// 单端项目(=1 个端)不需要分阶段:
|
|
1092
|
-
// - Phase 1 生成的
|
|
1143
|
+
// - Phase 1 生成的 overview/TECH.md 本身就是该端的专属文档
|
|
1093
1144
|
// - 不需要再生成 {端}/TECH.md(会重复)
|
|
1094
1145
|
if (platforms.length >= 2) {
|
|
1095
1146
|
logger_1.logger.info('');
|
|
@@ -1788,7 +1839,7 @@ async function buildMultiDocPrompt(command, ctx, options) {
|
|
|
1788
1839
|
- 缓存策略/并发与事务/消息队列(如涉及)
|
|
1789
1840
|
- 安全:SQL注入防护/接口鉴权/数据脱敏
|
|
1790
1841
|
- 性能:QPS预估/慢查询优化/连接池配置
|
|
1791
|
-
- **不要写**用户旅程、业务场景、页面清单(这些在
|
|
1842
|
+
- **不要写**用户旅程、业务场景、页面清单(这些在 overview/REQUIREMENT.md 中)
|
|
1792
1843
|
|
|
1793
1844
|
### 前端端(h5 / admin-web / miniapp)— 产品+技术双视角
|
|
1794
1845
|
- **产品视角(主要)**:
|
|
@@ -1976,7 +2027,7 @@ sequenceDiagram
|
|
|
1976
2027
|
|
|
1977
2028
|
## 写作要求
|
|
1978
2029
|
|
|
1979
|
-
###
|
|
2030
|
+
### 迭代级 DEV_GUIDE.md(020-specs/overview/)
|
|
1980
2031
|
- **技术栈与选型决策**:每个技术点的选型理由、替代方案对比
|
|
1981
2032
|
- **代码分层规范**:目录结构、各层职责、代码组织方式
|
|
1982
2033
|
- **通用设计模式**:Repository 模式、Service 模式、策略模式等具体实现
|
|
@@ -2011,7 +2062,7 @@ sequenceDiagram
|
|
|
2011
2062
|
];
|
|
2012
2063
|
// 任务类型 × 文档矩阵: 每种类型生成哪些文档
|
|
2013
2064
|
const DOC_MATRIX = {
|
|
2014
|
-
feature: ['REQUIREMENT.md', 'ANALYSIS.md', 'TECH.md', 'TEST.md', 'REVIEW.md', 'RISK.md', 'DEPS.md', 'MONITOR.md', 'UI_SPEC.md', 'FUNCTION_MAP.md', 'INTERACTION_MAP.md'],
|
|
2065
|
+
feature: ['REQUIREMENT.md', 'ANALYSIS.md', 'TECH.md', 'TEST.md', 'REVIEW.md', 'RISK.md', 'DEPS.md', 'MONITOR.md', 'UI_SPEC.md', 'FUNCTION_MAP.md', 'INTERACTION_MAP.md', 'DEV_GUIDE.md'],
|
|
2015
2066
|
refactor: ['ANALYSIS.md', 'TECH.md', 'TEST.md', 'REVIEW.md', 'RISK.md'],
|
|
2016
2067
|
bugfix: ['ANALYSIS.md', 'TECH.md', 'TEST.md'],
|
|
2017
2068
|
research: ['ANALYSIS.md'],
|
|
@@ -2023,12 +2074,12 @@ sequenceDiagram
|
|
|
2023
2074
|
performance: ['ANALYSIS.md', 'TECH.md', 'TEST.md', 'MONITOR.md'],
|
|
2024
2075
|
};
|
|
2025
2076
|
let includeDocs = isTask ? (DOC_MATRIX[taskType] || DOC_MATRIX['feature']) : DOC_MATRIX['feature'];
|
|
2026
|
-
// v6.
|
|
2027
|
-
if (options?.devGuide) {
|
|
2028
|
-
includeDocs =
|
|
2077
|
+
// v6.78.0+: DEV_GUIDE.md 默认生成(--dev-guide 向后兼容,--no-dev-guide 可禁用)
|
|
2078
|
+
if (options?.devGuide === false) {
|
|
2079
|
+
includeDocs = includeDocs.filter(d => d !== 'DEV_GUIDE.md');
|
|
2029
2080
|
}
|
|
2030
2081
|
// ── v6.61.0+: 恢复 Phase 1/Phase 2 分步逻辑,但 CLI 自动触发 Phase 2 ──
|
|
2031
|
-
// Phase 1: 生成综合文档(
|
|
2082
|
+
// Phase 1: 生成综合文档(overview/REQUIREMENT.md、ANALYSIS.md、DEPS.md 等)
|
|
2032
2083
|
// Phase 2: 生成各端专属文档({端}/TECH.md、TEST.md、UI_SPEC.md 等)
|
|
2033
2084
|
const GLOBAL_DOCS = ['REQUIREMENT.md', 'ANALYSIS.md', 'TECH.md', 'RISK.md', 'DEPS.md', 'REVIEW.md', 'MONITOR.md', 'FUNCTION_MAP.md', 'INTERACTION_MAP.md'];
|
|
2034
2085
|
const PLATFORM_DOCS = ['TECH.md', 'TEST.md', 'UI_SPEC.md'];
|
|
@@ -2067,7 +2118,7 @@ sequenceDiagram
|
|
|
2067
2118
|
doc[1] = `# \u672c\u4efb\u52a1\u9700\u6c42\u89c4\u683c\n\n> ${iter} | ${ctx.task} | ${now}\n\n## \u5199\u4f5c\u8981\u6c42\n\u6839\u636e split \u4ea7\u51fa\u7684\u9700\u6c42\u5207\u7247\uff0c\u7ed3\u5408\u5168\u5c40\u4e0a\u4e0b\u6587\uff0c\u91cd\u65b0\u7ec4\u7ec7\u672c\u4efb\u52a1\u7684\u9700\u6c42\u89c4\u683c\uff1a\n- \u660e\u786e\u672c\u4efb\u52a1\u7684\u9a8c\u6536\u6807\u51c6\uff08\u53ef\u6d4b\u8bd5\u7684\u3001\u5177\u4f53\u7684\uff09\n- \u7ec6\u5316\u4e1a\u52a1\u89c4\u5219\u548c\u8fb9\u754c\u6761\u4ef6\n- \u5217\u51fa\u5f02\u5e38\u573a\u666f\u548c\u5904\u7406\u65b9\u5f0f\n- \u6807\u6ce8\u4e0e\u5176\u4ed6 Task \u7684\u4f9d\u8d56\u5173\u7cfb\n`;
|
|
2068
2119
|
}
|
|
2069
2120
|
else if (doc[0] === 'TECH.md') {
|
|
2070
|
-
doc[1] = `# \u672c\u4efb\u52a1\u6280\u672f\u65b9\u6848\n\n> ${iter} | ${ctx.task} | ${now}\n\n## \u5199\u4f5c\u8981\u6c42\n\u57fa\u4e8e
|
|
2121
|
+
doc[1] = `# \u672c\u4efb\u52a1\u6280\u672f\u65b9\u6848\n\n> ${iter} | ${ctx.task} | ${now}\n\n## \u5199\u4f5c\u8981\u6c42\n\u57fa\u4e8e overview/TECH.md \u7684\u6574\u4f53\u67b6\u6784\uff0c\u7ec6\u5316\u5230\u51fd\u6570/\u63a5\u53e3\u7ea7\u522b\uff1a\n- \u5177\u4f53\u7684\u63a5\u53e3\u5b9a\u4e49\uff08\u8def\u5f84/\u53c2\u6570/\u54cd\u5e94\uff09\n- \u6570\u636e\u6a21\u578b\u8bbe\u8ba1\uff08Entity/DTO/VO \u5b57\u6bb5\u6620\u5c04\uff09\n- \u6838\u5fc3\u4e1a\u52a1\u903b\u8f91\u7684\u4f2a\u4ee3\u7801\u6216\u6d41\u7a0b\u63cf\u8ff0\n- \u524d\u7aef\u7ec4\u4ef6\u62c6\u5206\u548c\u72b6\u6001\u8bbe\u8ba1\n- \u5fc5\u987b\u4e0e overview/TECH.md \u7684\u6574\u4f53\u67b6\u6784\u4fdd\u6301\u4e00\u81f4\n`;
|
|
2071
2122
|
}
|
|
2072
2123
|
else if (doc[0] === 'TASK.md') {
|
|
2073
2124
|
doc[1] = `# \u5b9e\u65bd\u8ba1\u5212\n\n> ${iter} | ${ctx.task} | ${now}\n\n## \u5199\u4f5c\u8981\u6c42\n\u6839\u636e\u672c\u4efb\u52a1\u7684\u9700\u6c42\u548c\u6280\u672f\u65b9\u6848\uff0c\u5236\u5b9a\u5177\u4f53\u5b9e\u65bd\u6b65\u9aa4\uff1a\n- \u6309\u5f00\u53d1\u987a\u5e8f\u5217\u51fa\u5177\u4f53\u6b65\u9aa4\n- \u6bcf\u4e2a\u6b65\u9aa4\u6709\u660e\u786e\u7684\u5b8c\u6210\u6807\u51c6\n- \u6807\u6ce8\u6b65\u9aa4\u95f4\u7684\u4f9d\u8d56\u5173\u7cfb\n- \u4f30\u7b97\u6bcf\u6b65\u7684\u5de5\u4f5c\u91cf\n`;
|
|
@@ -2098,17 +2149,44 @@ sequenceDiagram
|
|
|
2098
2149
|
// ── v6.60.0+: TECH.md 模板:global/ 侧重整体架构,{端}/ 侧重端专属方案 ──
|
|
2099
2150
|
const techDoc = taskDocs.find(([n]) => n === 'TECH.md');
|
|
2100
2151
|
if (techDoc) {
|
|
2101
|
-
//
|
|
2152
|
+
// overview/TECH.md: 整体架构
|
|
2102
2153
|
techDoc[1] = `# 技术架构(跨端全局)\n\n> ${iter}\n\n## 写作要求\n撰写整体技术架构,覆盖所有端的交互关系:\n- 系统整体分层设计(各端在架构中的位置)\n- 跨端交互协议(前端↔后端通信方式、数据流向)\n- 中间件选型(缓存、消息队列、网关等)\n- 数据库整体设计(核心表结构、ER 关系)\n- 技术栈选型及理由\n`;
|
|
2103
2154
|
}
|
|
2104
2155
|
let prompt = `\n# 任务: ${command}${task} (${taskDocs.length}个文档 · ${isTask ? `类型:${taskType}` : '迭代全量'}${ctx.phase ? ` · Phase ${ctx.phase}` : ''})\n\n`;
|
|
2156
|
+
// v6.80.0+: 注入需求质量上下文(迭代级分析时)
|
|
2157
|
+
if (!isGlobal && !isTask && ctx.iteration && ctx.iteration !== 'GLOBAL') {
|
|
2158
|
+
try {
|
|
2159
|
+
const iterDir = await (0, context_1.getIterationDir)(ctx.iteration);
|
|
2160
|
+
const reportPath = (0, path_1.join)(iterDir, '010-requirements', 'CLARIFY_REPORT.md');
|
|
2161
|
+
if (await (0, fs_extra_1.pathExists)(reportPath)) {
|
|
2162
|
+
const report = await (0, fs_extra_2.readFile)(reportPath, 'utf-8');
|
|
2163
|
+
// 提取汇总表和关键信息
|
|
2164
|
+
const summaryMatch = report.match(/## 质量评分汇总[\s\S]*?(?=## |$)/);
|
|
2165
|
+
if (summaryMatch) {
|
|
2166
|
+
prompt += `## 📋 需求文档质量声明\n\n`;
|
|
2167
|
+
prompt += `> 以下评价基于 Phase 0 需求澄清结果\n\n`;
|
|
2168
|
+
prompt += summaryMatch[0].split('\n').slice(0, 12).join('\n'); // 取汇总表前12行
|
|
2169
|
+
prompt += `\n\n`;
|
|
2170
|
+
// 检测是否有遗留问题
|
|
2171
|
+
const hasIssues = report.includes('待澄清') || report.includes('❌');
|
|
2172
|
+
if (hasIssues) {
|
|
2173
|
+
prompt += `⚠️ **遗留问题**: 部分需求文档仍有未解决问题,分析时请标注不确定性。\n\n`;
|
|
2174
|
+
}
|
|
2175
|
+
else {
|
|
2176
|
+
prompt += `✅ **质量确认**: 所有需求文档已通过澄清,可直接深入技术分析。\n\n`;
|
|
2177
|
+
}
|
|
2178
|
+
}
|
|
2179
|
+
}
|
|
2180
|
+
}
|
|
2181
|
+
catch { /* 忽略质量上下文注入失败 */ }
|
|
2182
|
+
}
|
|
2105
2183
|
// ── v6.67.0+: 在 prompt 开头就明确完整工作流程 ──
|
|
2106
2184
|
if (!ctx.phase && !isTask) {
|
|
2107
2185
|
const platforms = await (0, spec_paths_1.parsePlatformList)();
|
|
2108
2186
|
if (platforms.length >= 2) {
|
|
2109
2187
|
prompt += `## 📋 完整工作流程(两阶段分析)\n\n`;
|
|
2110
2188
|
prompt += `本项目检测到有 ${platforms.length} 个端(${platforms.join('、')}),需要分两阶段执行:\n\n`;
|
|
2111
|
-
prompt += `**Phase 1(当前阶段)**: 生成综合文档(
|
|
2189
|
+
prompt += `**Phase 1(当前阶段)**: 生成综合文档(overview/REQUIREMENT.md、ANALYSIS.md、DEPS.md 等)\n`;
|
|
2112
2190
|
prompt += `**Phase 2(下一阶段)**: 生成各端专属文档({端}/TECH.md、TEST.md、UI_SPEC.md 等)\n\n`;
|
|
2113
2191
|
prompt += `## ⚠️ 强制要求:Phase 1 完成后立即执行 Phase 2\n\n`;
|
|
2114
2192
|
prompt += `当你通过 --apply 写入所有综合文档后,**必须立即执行**以下命令进入 Phase 2:\n\n`;
|
|
@@ -2126,8 +2204,8 @@ sequenceDiagram
|
|
|
2126
2204
|
prompt += `- ✅ **正确行为**:只使用 CLI 预创建的 global/ 和 {端名}/ 目录,不要手动 mkdir 或 Write 到不存在的目录\n`;
|
|
2127
2205
|
prompt += `- ⚠️ **后果**:如果创建额外目录,会导致后续 split/execute 命令找不到文件,整个工作流失败\n\n`;
|
|
2128
2206
|
prompt += `### 绝对禁止直接用 Write 工具写文件\n`;
|
|
2129
|
-
prompt += `- ❌ **错误行为**:Write("020-specs/
|
|
2130
|
-
prompt += `- ✅ **正确行为**:必须通过 \`speccore analyze --apply '{"
|
|
2207
|
+
prompt += `- ❌ **错误行为**:Write("020-specs/overview/ANALYSIS.md", content) 或直接 Write 到任何路径\n`;
|
|
2208
|
+
prompt += `- ✅ **正确行为**:必须通过 \`speccore analyze --apply '{"overview/ANALYSIS.md":"...","admin-web/TECH.md":"..."}' -I ${iter}\` 写入\n`;
|
|
2131
2209
|
prompt += `- 💡 **Windows 兼容**:如果 JSON 在命令行中转义困难,先将 JSON 写入文件(如 result.json),然后执行 \`speccore analyze --apply @result.json -I ${iter}\`\n`;
|
|
2132
2210
|
prompt += `- ⚠️ **原因**:--apply 会让 CLI 自动路由文件到正确的子目录,直接 Write 会绕过这个机制,导致所有文件扁平在根目录\n\n`;
|
|
2133
2211
|
prompt += `### ✅ 正确的目录结构\n`;
|
|
@@ -2166,12 +2244,12 @@ sequenceDiagram
|
|
|
2166
2244
|
prompt += `### Step 2: 读取全局上下文(作为参考)\n`;
|
|
2167
2245
|
prompt += `- Read .speccore/CONSTITUTION.md → 项目配置\n`;
|
|
2168
2246
|
prompt += `- Read 020-specs/PLATFORMS.md → 端列表\n`;
|
|
2169
|
-
prompt += `- Read 020-specs/
|
|
2170
|
-
prompt += `- Read 020-specs/
|
|
2171
|
-
prompt += `- Read 020-specs/
|
|
2247
|
+
prompt += `- Read 020-specs/overview/REQUIREMENT.md → 迭代综合需求规格\n`;
|
|
2248
|
+
prompt += `- Read 020-specs/overview/TECH.md → 迭代综合技术架构\n`;
|
|
2249
|
+
prompt += `- Read 020-specs/overview/ANALYSIS.md → 迭代综合分析报告\n`;
|
|
2172
2250
|
prompt += `- Read 020-specs/{本任务端名}/TECH.md → 该端专属技术方案\n\n`;
|
|
2173
2251
|
prompt += `### Step 3: 撰写任务级深度分析文档\n\n`;
|
|
2174
|
-
prompt += `**REQ.md** — 本任务的需求规格(不是
|
|
2252
|
+
prompt += `**REQ.md** — 本任务的需求规格(不是 overview/REQUIREMENT.md 的复制):\n`;
|
|
2175
2253
|
prompt += `- 明确本任务的验收标准(可测试的、具体的)\n`;
|
|
2176
2254
|
prompt += `- 细化业务规则和边界条件\n`;
|
|
2177
2255
|
prompt += `- 列出本任务涉及的异常场景\n\n`;
|
|
@@ -2180,7 +2258,7 @@ sequenceDiagram
|
|
|
2180
2258
|
prompt += `- 数据模型设计(Entity/DTO/VO 字段映射)\n`;
|
|
2181
2259
|
prompt += `- 核心业务逻辑的伪代码或流程描述\n`;
|
|
2182
2260
|
prompt += `- 前端组件拆分和状态设计\n`;
|
|
2183
|
-
prompt += `- 必须与
|
|
2261
|
+
prompt += `- 必须与 overview/TECH.md 的整体架构保持一致\n\n`;
|
|
2184
2262
|
prompt += `**TASK.md** — 本任务的实施步骤:\n`;
|
|
2185
2263
|
prompt += `- 按开发顺序列出具体步骤\n`;
|
|
2186
2264
|
prompt += `- 每个步骤有明确的完成标准\n`;
|
|
@@ -2197,7 +2275,7 @@ sequenceDiagram
|
|
|
2197
2275
|
if (ctx.platform) {
|
|
2198
2276
|
prompt += `- **只分析 ${ctx.platform} 端**:从 CONSTITUTION.md 读取端列表,但只生成 ${ctx.platform} 端的专属文档\n`;
|
|
2199
2277
|
prompt += `- 在 020-specs/${ctx.platform}/ 下写入该端专属文档(ANALYSIS.md、TECH.md、TEST.md 等)\n`;
|
|
2200
|
-
prompt += `-
|
|
2278
|
+
prompt += `- 迭代综合文档写入 020-specs/overview/(REQUIREMENT.md、DEPS.md、RISK.md 等)\n`;
|
|
2201
2279
|
prompt += `- **不要生成**其他端的子目录和文档\n`;
|
|
2202
2280
|
}
|
|
2203
2281
|
// ── v6.61.0+: 阶段专属指令(Phase 2)──
|
|
@@ -2207,13 +2285,13 @@ sequenceDiagram
|
|
|
2207
2285
|
prompt += `依次 Read 以下文件,建立全局技术架构认知:\n`;
|
|
2208
2286
|
prompt += `- Read .speccore/CONSTITUTION.md\n`;
|
|
2209
2287
|
prompt += `- Read 020-specs/PLATFORMS.md → 获取端列表\n`;
|
|
2210
|
-
prompt += `- Read 020-specs/
|
|
2211
|
-
prompt += `- Read 020-specs/
|
|
2212
|
-
prompt += `- Read 020-specs/
|
|
2213
|
-
prompt += `- Read 020-specs/
|
|
2288
|
+
prompt += `- Read 020-specs/overview/REQUIREMENT.md → 需求规格\n`;
|
|
2289
|
+
prompt += `- Read 020-specs/overview/ANALYSIS.md → 分析报告\n`;
|
|
2290
|
+
prompt += `- Read 020-specs/overview/TECH.md → 整体技术架构\n`;
|
|
2291
|
+
prompt += `- Read 020-specs/overview/RISK.md、DEPS.md、REVIEW.md、MONITOR.md(如存在)\n\n`;
|
|
2214
2292
|
prompt += `### Step 2: 为每个端撰写专属文档\n`;
|
|
2215
2293
|
prompt += `根据全局上下文,为 PLATFORMS.md 中的**每个端**分别撰写:\n`;
|
|
2216
|
-
prompt += `- **{端}/TECH.md**:该端专属技术方案(必须对齐
|
|
2294
|
+
prompt += `- **{端}/TECH.md**:该端专属技术方案(必须对齐 overview/TECH.md 架构)\n`;
|
|
2217
2295
|
prompt += ` - ⚠️ **必须包含「业务-代码映射」章节**:在 TECH.md 末尾添加表格,列出本端涉及的业务模块及其对应的代码实体(文件/表/API/组件等),关系类型由你根据技术栈自主决定(如 api_controller、uses_table、page、component、route、middleware、interceptor、gateway 等)\n`;
|
|
2218
2296
|
prompt += ` - 表格格式:| 业务模块 | 代码实体 | 关系类型 | 说明 |\n`;
|
|
2219
2297
|
prompt += ` - 示例:| 会议室档案 | backend/RoomController.java | api_controller | REST 控制器 |\n`;
|
|
@@ -2221,7 +2299,7 @@ sequenceDiagram
|
|
|
2221
2299
|
prompt += `- **{端}/TEST.md**:该端专属测试计划\n`;
|
|
2222
2300
|
prompt += `- **{端}/UI_SPEC.md**:该端专属 UI 规格(仅前端端需要)\n\n`;
|
|
2223
2301
|
prompt += `### Step 3: 一致性检查\n`;
|
|
2224
|
-
prompt += `- 各端 TECH.md 的技术选型必须与
|
|
2302
|
+
prompt += `- 各端 TECH.md 的技术选型必须与 overview/TECH.md 一致\n`;
|
|
2225
2303
|
prompt += `- UI_SPEC.md 的字段映射必须与后端 API 响应字段一一对应\n`;
|
|
2226
2304
|
prompt += `- TEST.md 必须覆盖 REQUIREMENT.md 中该端的验收标准\n\n`;
|
|
2227
2305
|
prompt += `### 写入方式\n`;
|
|
@@ -2285,7 +2363,7 @@ sequenceDiagram
|
|
|
2285
2363
|
prompt += ` - 端的信息只在「功能模块清单」表格中标注,正文不区分端\n`;
|
|
2286
2364
|
// v6.49.14+: 功能模块清单必须含涉及端列 + 来源链接
|
|
2287
2365
|
// v6.71.3+: 增加「与全局层对比」列
|
|
2288
|
-
prompt += `9. **功能模块清单(重要)**:写入
|
|
2366
|
+
prompt += `9. **功能模块清单(重要)**:写入 overview/REQUIREMENT.md 时,功能模块清单表格必须包含以下列\n`;
|
|
2289
2367
|
prompt += ` - 表格格式:| # | 功能模块 | 涉及端 | 全局对比 | 来源 | 说明 |\n`;
|
|
2290
2368
|
prompt += ` - 「涉及端」:每个模块标注需要**新开发工作**的端(标准端名,逗号分隔)\n`;
|
|
2291
2369
|
prompt += ` - 「涉及」= 该端需要写新接口/新页面/新逻辑\n`;
|
|
@@ -2311,7 +2389,7 @@ sequenceDiagram
|
|
|
2311
2389
|
prompt += ` - 标注每个功能模块的「全局对比」类型(新增/扩展/重构/复用)\n`;
|
|
2312
2390
|
prompt += ` - 识别冲突:如迭代需求修改了全局层已有接口的字段/路径 → 在 RISK.md 中标注\n`;
|
|
2313
2391
|
prompt += ` - 识别依赖:如迭代的新功能依赖全局层的某个功能 → 在 FUNCTION_MAP.md「依赖任务」中标注\n\n`;
|
|
2314
|
-
prompt += `7b. **跨端功能映射表(重要)**:在 REQUIREMENT.md 完成后,必须生成
|
|
2392
|
+
prompt += `7b. **跨端功能映射表(重要)**:在 REQUIREMENT.md 完成后,必须生成 overview/FUNCTION_MAP.md\n`;
|
|
2315
2393
|
prompt += ` - 这是 split 阶段的核心输入,决定任务如何按功能单元拆分\n`;
|
|
2316
2394
|
prompt += ` - 表格格式:| # | 功能单元 | 涉及端 | 全局对比 | 共享能力 | 依赖任务 | 说明 |\n`;
|
|
2317
2395
|
prompt += ` - 「功能单元」必须与 REQUIREMENT.md 功能模块清单一一对应,不允许合并\n`;
|
|
@@ -2324,7 +2402,7 @@ sequenceDiagram
|
|
|
2324
2402
|
prompt += ` - **错误示例**(禁止):将"审批流程"和"定时任务"合并为一行\n`;
|
|
2325
2403
|
prompt += ` - FUNCTION_MAP.md 生成后,split 将**严格按此表**创建任务目录,不再由 AI 推断\n`;
|
|
2326
2404
|
// v6.70.0+: 跨端交互图谱(INTERACTION_MAP.md)
|
|
2327
|
-
prompt += `7c. **跨端交互图谱(重要)**:在 FUNCTION_MAP.md 完成后,必须生成
|
|
2405
|
+
prompt += `7c. **跨端交互图谱(重要)**:在 FUNCTION_MAP.md 完成后,必须生成 overview/INTERACTION_MAP.md\n`;
|
|
2328
2406
|
prompt += ` - 按功能单元组织,每个功能单元一个 Mermaid sequenceDiagram\n`;
|
|
2329
2407
|
prompt += ` - 展示完整的业务交互时序:用户操作 → 前端处理 → 后端调用 → 数据返回\n`;
|
|
2330
2408
|
prompt += ` - 明确标出后端服务之间的内部调用(产品文档写"系统处理"的地方)\n`;
|
|
@@ -2356,7 +2434,7 @@ sequenceDiagram
|
|
|
2356
2434
|
}
|
|
2357
2435
|
const dirStepNum = platformTypes.size > 0 ? 9 : 8;
|
|
2358
2436
|
prompt += `${dirStepNum}. **目录结构(严格遵循,禁止自创目录)**:\n`;
|
|
2359
|
-
prompt += ` - **综合文档**(跨端通用)→ 通过 --apply 写入,CLI 自动路由到 \`020-specs/
|
|
2437
|
+
prompt += ` - **综合文档**(跨端通用)→ 通过 --apply 写入,CLI 自动路由到 \`020-specs/overview/{文件名}\`\n`;
|
|
2360
2438
|
prompt += ` - REQUIREMENT.md(需求文档,含功能模块清单+涉及端列)\n`;
|
|
2361
2439
|
prompt += ` - ANALYSIS.md(需求分析)\n`;
|
|
2362
2440
|
prompt += ` - DEPS.md(依赖清单)\n`;
|
|
@@ -2383,7 +2461,7 @@ sequenceDiagram
|
|
|
2383
2461
|
prompt += `- 缓存策略/并发与事务/消息队列(如涉及)\n`;
|
|
2384
2462
|
prompt += `- 安全:SQL 注入防护/接口鉴权/数据脱敏\n`;
|
|
2385
2463
|
prompt += `- 性能:QPS 预估/慢查询优化/连接池配置\n`;
|
|
2386
|
-
prompt += `- **不需要**产品视角的需求描述(用户故事、业务场景已在
|
|
2464
|
+
prompt += `- **不需要**产品视角的需求描述(用户故事、业务场景已在 overview/REQUIREMENT.md 中)\n\n`;
|
|
2387
2465
|
prompt += `### 前端端(h5 / admin-web / miniapp)必含内容 — 产品+技术双视角\n`;
|
|
2388
2466
|
prompt += `- **产品视角(主要)**:\n`;
|
|
2389
2467
|
prompt += ` - 用户旅程:该端用户如何完成核心任务(步骤流程图)\n`;
|
|
@@ -2401,11 +2479,11 @@ sequenceDiagram
|
|
|
2401
2479
|
// v6.60.0+: 文档与端的对应关系(不再分 Phase)
|
|
2402
2480
|
// v6.71.0+: 前后端文档差异化
|
|
2403
2481
|
prompt += `### 文档与端的对应关系\n`;
|
|
2404
|
-
prompt += `- **
|
|
2405
|
-
prompt += `- **
|
|
2406
|
-
prompt += `- **
|
|
2407
|
-
prompt += `- **
|
|
2408
|
-
prompt += `- **
|
|
2482
|
+
prompt += `- **overview/REQUIREMENT.md**:整体需求(产品视角,按业务场景组织)\n`;
|
|
2483
|
+
prompt += `- **overview/ANALYSIS.md**:整体需求分析\n`;
|
|
2484
|
+
prompt += `- **overview/DEPS.md**:整体依赖清单\n`;
|
|
2485
|
+
prompt += `- **overview/FUNCTION_MAP.md**:功能单元 × 端映射表\n`;
|
|
2486
|
+
prompt += `- **overview/INTERACTION_MAP.md**:跨端交互时序图\n`;
|
|
2409
2487
|
prompt += `- **后端端(*service)/{端}/TECH.md**:纯技术视角 — 接口设计+数据模型+架构+性能\n`;
|
|
2410
2488
|
prompt += `- **前端端(h5/admin/miniapp)/{端}/TECH.md**:产品+技术双视角 — 用户旅程+页面清单+交互流程+API调用链\n`;
|
|
2411
2489
|
prompt += `- **前端端/{端}/UI_SPEC.md**:UI 规格(字段映射、组件设计、交互细节)\n`;
|
|
@@ -2526,11 +2604,11 @@ sequenceDiagram
|
|
|
2526
2604
|
prompt += `### 4. 跨文档引用一致性\n`;
|
|
2527
2605
|
prompt += `- [ ] 检查 UI_SPEC.md 中的字段映射是否与后端 API 响应字段一一对应\n`;
|
|
2528
2606
|
prompt += `- [ ] 检查 TEST.md 中的测试场景是否覆盖了 REQUIREMENT.md 中的所有验收标准\n`;
|
|
2529
|
-
prompt += `- [ ] 检查各端 TECH.md 的技术选型是否与
|
|
2607
|
+
prompt += `- [ ] 检查各端 TECH.md 的技术选型是否与 overview/TECH.md 的整体架构一致\n\n`;
|
|
2530
2608
|
prompt += `### 5. 目录结构合法性\n`;
|
|
2531
2609
|
prompt += `- [ ] 确认 --apply 的 JSON 键名只包含合法文件名或「合法端名/文件名」格式\n`;
|
|
2532
2610
|
prompt += `- [ ] **禁止**包含数字编号目录(如 1001/、1002/)、中文目录(如 错误码/)、特殊符号目录(如 .../)\n`;
|
|
2533
|
-
prompt += `- [ ] 合法格式示例:\`
|
|
2611
|
+
prompt += `- [ ] 合法格式示例:\`overview/ANALYSIS.md\`、\`admin-web/TECH.md\`、\`REQUIREMENT.md\`\n\n`;
|
|
2534
2612
|
prompt += `### 自检通过标准\n`;
|
|
2535
2613
|
prompt += `以上 5 项全部勾选通过后,方可执行 --apply 写入。如果任何一项未通过,先修正问题,重新自检,直到全部通过。\n`;
|
|
2536
2614
|
return prompt;
|
|
@@ -2560,11 +2638,11 @@ async function buildStreamingGlobalPrompt(command, ctx, options) {
|
|
|
2560
2638
|
prompt += `| :--- | :--- | :--- | :--- |\n`;
|
|
2561
2639
|
prompt += `| Phase 0 | 快速全局扫描 | 所有端并行索引 | platforms/{端}/_INDEX.md |\n`;
|
|
2562
2640
|
prompt += `| Phase 1 | 后端深度分析 | 拓扑排序,从依赖源头开始 | platforms/{后端端}/API_INVENTORY.md, DATA_MODEL.md, ... |\n`;
|
|
2563
|
-
prompt += `| Phase 2 |
|
|
2641
|
+
prompt += `| Phase 2 | 迭代综合实时更新 | 后端完成后更新迭代综合文档 | overview/API_CONTRACT.yaml, ARCHITECTURE.md, ... |\n`;
|
|
2564
2642
|
prompt += `| Phase 3 | 前端深度分析 | 对齐后端契约 | platforms/{前端端}/FEATURES.md, UI_SPEC.md, ... |\n`;
|
|
2565
|
-
prompt += `| Phase 4 | 横向关联检查 | 前后端字段/接口一致性 |
|
|
2566
|
-
prompt += `| Phase 5 | 纵向关联检查 | 功能模块跨端完整性 |
|
|
2567
|
-
prompt += `| Phase 6 | 最终核对检查 | 完整性+一致性+遗漏检测 |
|
|
2643
|
+
prompt += `| Phase 4 | 横向关联检查 | 前后端字段/接口一致性 | overview/CROSS_CHECK.md |\n`;
|
|
2644
|
+
prompt += `| Phase 5 | 纵向关联检查 | 功能模块跨端完整性 | overview/VERTICAL_CHECK.md |\n`;
|
|
2645
|
+
prompt += `| Phase 6 | 最终核对检查 | 完整性+一致性+遗漏检测 | overview/FINAL_AUDIT.md |\n\n`;
|
|
2568
2646
|
prompt += `## ⚠️ 实时关联调整机制\n\n`;
|
|
2569
2647
|
prompt += `分析过程中,如果当前阶段发现与前期文档冲突或不一致:\n`;
|
|
2570
2648
|
prompt += `1. **在当前阶段文档中标注冲突点**\n`;
|
|
@@ -2648,10 +2726,10 @@ async function buildContractFirstPrompt(iteration) {
|
|
|
2648
2726
|
prompt += `Phase 1 迭代分析已完成。现在需要在各端开始专属技术方案分析之前,**先定义跨端 API 契约**。\n\n`;
|
|
2649
2727
|
prompt += `## 读取内容\n\n`;
|
|
2650
2728
|
prompt += `1. Read .speccore/CONSTITUTION.md → 获取端列表和项目配置\n`;
|
|
2651
|
-
prompt += `2. Read 020-specs/
|
|
2652
|
-
prompt += `3. Read 020-specs/
|
|
2653
|
-
prompt += `4. Read 020-specs/
|
|
2654
|
-
prompt += `5. Read 020-specs/
|
|
2729
|
+
prompt += `2. Read 020-specs/overview/REQUIREMENT.md → 迭代综合需求规格\n`;
|
|
2730
|
+
prompt += `3. Read 020-specs/overview/ANALYSIS.md → 迭代综合分析报告\n`;
|
|
2731
|
+
prompt += `4. Read 020-specs/overview/TECH.md → 迭代综合技术架构\n`;
|
|
2732
|
+
prompt += `5. Read 020-specs/overview/DEPS.md → 依赖关系(如存在)\n\n`;
|
|
2655
2733
|
prompt += `## 输出要求\n\n`;
|
|
2656
2734
|
prompt += `基于上述文档,生成一份 **API_CONTRACT.yaml**,使用标准 YAML 格式:\n\n`;
|
|
2657
2735
|
prompt += `### 格式要求\n`;
|
|
@@ -2714,7 +2792,7 @@ async function buildContractFirstPrompt(iteration) {
|
|
|
2714
2792
|
prompt += `## 写入方式\n\n`;
|
|
2715
2793
|
prompt += `speccore analyze --apply '{"API_CONTRACT.yaml":"..."}' -I ${iteration}\n\n`;
|
|
2716
2794
|
prompt += `⚠️ **注意**:\n`;
|
|
2717
|
-
prompt += `- 契约文件写入 020-specs/
|
|
2795
|
+
prompt += `- 契约文件写入 020-specs/overview/API_CONTRACT.yaml(迭代综合共享)\n`;
|
|
2718
2796
|
prompt += `- 这是各端技术方案分析的**前置输入**,后续各端分析必须遵循此契约\n`;
|
|
2719
2797
|
prompt += `- 契约应**精确且完整**,避免后续各端分析时出现接口不一致\n\n`;
|
|
2720
2798
|
return prompt;
|
|
@@ -2759,4 +2837,118 @@ async function getSubtaskDirs(taskDir) {
|
|
|
2759
2837
|
}
|
|
2760
2838
|
return result;
|
|
2761
2839
|
}
|
|
2840
|
+
// ═══════════════════════════════════════════════════════════
|
|
2841
|
+
// v6.80.0+: 需求澄清 Phase Prompt 构建
|
|
2842
|
+
// ═══════════════════════════════════════════════════════════
|
|
2843
|
+
async function buildClarifyPhasePrompt(iteration) {
|
|
2844
|
+
const iterDir = await (0, context_1.getIterationDir)(iteration);
|
|
2845
|
+
const reqDir = (0, path_1.join)(iterDir, '010-requirements');
|
|
2846
|
+
// 收集所有需求文档
|
|
2847
|
+
const docPaths = [];
|
|
2848
|
+
for (const sub of ['sources', 'converted', 'features']) {
|
|
2849
|
+
const subDir = (0, path_1.join)(reqDir, sub);
|
|
2850
|
+
if (await (0, fs_extra_1.pathExists)(subDir)) {
|
|
2851
|
+
try {
|
|
2852
|
+
const entries = await (0, fs_extra_2.readdir)(subDir, { withFileTypes: true });
|
|
2853
|
+
for (const e of entries) {
|
|
2854
|
+
if (e.isFile() && e.name.endsWith('.md') && !e.name.startsWith('.')) {
|
|
2855
|
+
docPaths.push((0, path_1.join)(subDir, e.name));
|
|
2856
|
+
}
|
|
2857
|
+
else if (e.isDirectory()) {
|
|
2858
|
+
const files = await (0, fs_extra_2.readdir)((0, path_1.join)(subDir, e.name));
|
|
2859
|
+
for (const f of files) {
|
|
2860
|
+
if (f.endsWith('.md') && !f.startsWith('.'))
|
|
2861
|
+
docPaths.push((0, path_1.join)(subDir, e.name, f));
|
|
2862
|
+
}
|
|
2863
|
+
}
|
|
2864
|
+
}
|
|
2865
|
+
}
|
|
2866
|
+
catch { /* ignore */ }
|
|
2867
|
+
}
|
|
2868
|
+
}
|
|
2869
|
+
// 读取并评估每个文档
|
|
2870
|
+
const qualityReports = [];
|
|
2871
|
+
for (const p of docPaths) {
|
|
2872
|
+
try {
|
|
2873
|
+
const content = await (0, fs_extra_2.readFile)(p, 'utf-8');
|
|
2874
|
+
const report = (0, requirement_clarifier_1.assessRequirementQuality)(content, p);
|
|
2875
|
+
qualityReports.push(report);
|
|
2876
|
+
}
|
|
2877
|
+
catch { /* ignore */ }
|
|
2878
|
+
}
|
|
2879
|
+
// 生成质量报告文件
|
|
2880
|
+
if (qualityReports.length > 0) {
|
|
2881
|
+
await (0, requirement_clarifier_1.writeClarifyReport)(iterDir, qualityReports);
|
|
2882
|
+
}
|
|
2883
|
+
// 构建 Clarify Prompt
|
|
2884
|
+
let prompt = `\n# 任务: 需求专业化(Phase 0: 需求澄清)\n\n`;
|
|
2885
|
+
prompt += `## 你的角色\n`;
|
|
2886
|
+
prompt += `你是资深产品经理 + 领域专家。请将迭代 "${iteration}" 的需求文档整理为专业的 PRD 级需求规格说明书。\n\n`;
|
|
2887
|
+
prompt += `## 质量评价摘要\n\n`;
|
|
2888
|
+
for (const r of qualityReports) {
|
|
2889
|
+
const name = r.filePath.split('/').pop() || '-';
|
|
2890
|
+
prompt += `- **${name}**: 评分 ${r.overallScore}/100 (${r.level.toUpperCase()})\n`;
|
|
2891
|
+
for (const dim of r.dimensions) {
|
|
2892
|
+
if (dim.issues.length > 0) {
|
|
2893
|
+
prompt += ` - ${dim.name}: ${dim.score}分 — ${dim.issues.join('、')}\n`;
|
|
2894
|
+
}
|
|
2895
|
+
}
|
|
2896
|
+
}
|
|
2897
|
+
prompt += `\n## 读取需求文档\n\n`;
|
|
2898
|
+
prompt += `依次读取以下文档(按优先级):\n`;
|
|
2899
|
+
prompt += `1. \`010-requirements/INDEX.md\` — 需求全貌\n`;
|
|
2900
|
+
prompt += `2. \`010-requirements/sources/*.md\` — 原始需求(主要依据)\n`;
|
|
2901
|
+
prompt += `3. \`010-requirements/converted/*.md\` — 已转换文档\n`;
|
|
2902
|
+
prompt += `4. \`010-requirements/features/*/README.md\` — 功能级补充\n`;
|
|
2903
|
+
prompt += `5. \`010-requirements/prototypes/\` — 原型文件\n\n`;
|
|
2904
|
+
prompt += `## 整理要求\n\n`;
|
|
2905
|
+
prompt += `### 必须包含的章节\n`;
|
|
2906
|
+
prompt += `1. **背景与目标**:为什么要做这个功能,解决什么问题\n`;
|
|
2907
|
+
prompt += `2. **用户故事**:作为 [角色],我希望 [目标],以便 [价值]\n`;
|
|
2908
|
+
prompt += `3. **功能规格**:功能清单、详细描述、业务规则、异常场景\n`;
|
|
2909
|
+
prompt += `4. **验收标准(AC)**:可测试的、具体的验收条件,每条用 \`[ ]\` 标记\n`;
|
|
2910
|
+
prompt += `5. **非功能需求**:性能、安全、兼容性等(如适用)\n`;
|
|
2911
|
+
prompt += `6. **依赖与约束**:依赖的其他系统/模块\n`;
|
|
2912
|
+
prompt += `7. **功能边界**:明确「做什么」和「不做什么」\n\n`;
|
|
2913
|
+
prompt += `### 质量要求\n`;
|
|
2914
|
+
prompt += `- 为每个功能点分配唯一需求编号(如 R-01, R-02)\n`;
|
|
2915
|
+
prompt += `- 统一术语表述,不要同一概念用不同词汇\n`;
|
|
2916
|
+
prompt += `- 验收标准必须量化(如响应时间<200ms,成功率>99%)\n`;
|
|
2917
|
+
prompt += `- 如果原始描述不完整,标注「待补充」而不是编造\n`;
|
|
2918
|
+
prompt += `- 不要添加文档中未提及的功能\n\n`;
|
|
2919
|
+
prompt += `## 输出格式\n\n`;
|
|
2920
|
+
prompt += `直接输出整理后的 Markdown PRD 文档。\n`;
|
|
2921
|
+
prompt += `文档末尾附加「原始输入」章节。\n\n`;
|
|
2922
|
+
prompt += `## 写入方式\n\n`;
|
|
2923
|
+
prompt += `\`\`\`bash\n`;
|
|
2924
|
+
prompt += `speccore analyze --apply '{"010-requirements/converted/clarified-xxx.md":"..."}' -I ${iteration}\n`;
|
|
2925
|
+
prompt += `\`\`\`\n\n`;
|
|
2926
|
+
prompt += `> 注意:写入 clarified-*.md 后,CLI 会自动推进到需求确认阶段。\n`;
|
|
2927
|
+
return prompt;
|
|
2928
|
+
}
|
|
2929
|
+
async function buildConfirmCheckPrompt(iteration) {
|
|
2930
|
+
const iterDir = await (0, context_1.getIterationDir)(iteration);
|
|
2931
|
+
const reportPath = (0, path_1.join)(iterDir, '010-requirements', 'CLARIFY_REPORT.md');
|
|
2932
|
+
let prompt = `\n# 任务: 需求确认(Phase 0: 确认检查)\n\n`;
|
|
2933
|
+
if (await (0, fs_extra_1.pathExists)(reportPath)) {
|
|
2934
|
+
const report = await (0, fs_extra_2.readFile)(reportPath, 'utf-8');
|
|
2935
|
+
prompt += `## 需求澄清报告\n\n`;
|
|
2936
|
+
prompt += report.slice(0, 3000); // 截取前 3000 字符
|
|
2937
|
+
if (report.length > 3000) {
|
|
2938
|
+
prompt += `\n\n... (报告共 ${report.length} 字符,已截断)\n`;
|
|
2939
|
+
}
|
|
2940
|
+
}
|
|
2941
|
+
prompt += `\n## 确认要求\n\n`;
|
|
2942
|
+
prompt += `1. 检查 clarified-*.md 是否已写入 \`010-requirements/converted/\`\n`;
|
|
2943
|
+
prompt += `2. 确认验收标准是否可测试、可量化\n`;
|
|
2944
|
+
prompt += `3. 确认功能边界是否明确(不做什么)\n`;
|
|
2945
|
+
prompt += `4. 如有「待补充」项,确认是否已解决\n\n`;
|
|
2946
|
+
prompt += `## 操作\n\n`;
|
|
2947
|
+
prompt += `如果确认无误,直接执行以下命令进入技术方案生成阶段:\n\n`;
|
|
2948
|
+
prompt += `\`\`\`bash\n`;
|
|
2949
|
+
prompt += `speccore analyze --prompt -I ${iteration} --pipeline\n`;
|
|
2950
|
+
prompt += `\`\`\`\n\n`;
|
|
2951
|
+
prompt += `> 当前是 Pipeline 模式,确认后 CLI 会自动推进到 Phase 1。\n`;
|
|
2952
|
+
return prompt;
|
|
2953
|
+
}
|
|
2762
2954
|
//# sourceMappingURL=analyze.js.map
|