speccore 8.3.180 → 8.3.182
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/analyze.d.ts.map +1 -1
- package/dist/commands/analyze.js +104 -18
- package/dist/commands/analyze.js.map +1 -1
- package/dist/core/prompt-builder.d.ts.map +1 -1
- package/dist/core/prompt-builder.js +100 -16
- package/dist/core/prompt-builder.js.map +1 -1
- package/dist/core/requirement-clarifier.d.ts +8 -1
- package/dist/core/requirement-clarifier.d.ts.map +1 -1
- package/dist/core/requirement-clarifier.js +53 -18
- package/dist/core/requirement-clarifier.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analyze.d.ts","sourceRoot":"","sources":["../../src/commands/analyze.ts"],"names":[],"mappings":"AA6EA,MAAM,WAAW,cAAc;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,QAAQ,GAAG,WAAW,GAAG,MAAM,GAAG,UAAU,CAAC;IACrD,KAAK,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;IACpC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,YAAY,CAAC,EAAE,OAAO,CAAC;IAEvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAuGD,wBAAsB,cAAc,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"analyze.d.ts","sourceRoot":"","sources":["../../src/commands/analyze.ts"],"names":[],"mappings":"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"}
|
package/dist/commands/analyze.js
CHANGED
|
@@ -1181,17 +1181,24 @@ ${singlePrompt}`);
|
|
|
1181
1181
|
// 不阻止,但输出强烈警告(输出警告)
|
|
1182
1182
|
}
|
|
1183
1183
|
// v8.3.0+: 解析 [CLARIFY:xxx] 标记 — 需求澄清是强制前置步骤
|
|
1184
|
+
// v8.3.181+: 支持两级澄清路径(overview/CLARIFY.md 和 {feature}/overview/CLARIFY.md)
|
|
1184
1185
|
const clarifyBlocks = parseClarifyMarkers(options.apply);
|
|
1185
1186
|
if (clarifyBlocks.size > 0 && !isGlobalScope) {
|
|
1186
|
-
logger_1.logger.info(`📋 检测到 ${clarifyBlocks.size}
|
|
1187
|
-
const goldenDir = (0, path_1.join)(iterDir, '020-specs', 'requirements');
|
|
1188
|
-
await (0, fs_extra_1.ensureDir)(goldenDir);
|
|
1187
|
+
logger_1.logger.info(`📋 检测到 ${clarifyBlocks.size} 个澄清文档,先写入...`);
|
|
1189
1188
|
for (const [filename, content] of clarifyBlocks) {
|
|
1190
1189
|
const { parseClarifiedRequirement, buildClarifiedHeader } = await Promise.resolve().then(() => __importStar(require('../core/requirement-clarifier')));
|
|
1191
1190
|
const { content: cleaned } = parseClarifiedRequirement(content);
|
|
1192
1191
|
const header = buildClarifiedHeader(filename);
|
|
1193
1192
|
const finalContent = header + cleaned;
|
|
1194
|
-
|
|
1193
|
+
// 解析写入路径:支持新格式(overview/、{feature}/overview/)和旧格式(requirements/)
|
|
1194
|
+
let fp;
|
|
1195
|
+
if (filename.includes('/') || filename.includes('\\')) {
|
|
1196
|
+
fp = (0, path_1.join)(iterDir, '020-specs', filename);
|
|
1197
|
+
}
|
|
1198
|
+
else {
|
|
1199
|
+
// 兼容旧格式:无路径前缀的文件名写入 requirements/
|
|
1200
|
+
fp = (0, path_1.join)(iterDir, '020-specs', 'requirements', filename);
|
|
1201
|
+
}
|
|
1195
1202
|
await (0, fs_extra_1.ensureDir)((0, path_1.dirname)(fp));
|
|
1196
1203
|
await (0, fs_extra_1.writeFile)(fp, finalContent);
|
|
1197
1204
|
logger_1.logger.info(` ✅ 澄清文档已写入: ${(0, path_1.relative)(_projectRoot, fp)}`);
|
|
@@ -1200,8 +1207,8 @@ ${singlePrompt}`);
|
|
|
1200
1207
|
}
|
|
1201
1208
|
// v8.3.0+: 需求澄清验证 — 如果需求质量不足但未澄清,拒绝写入
|
|
1202
1209
|
if (!isGlobalScope && !isTaskLevel && !options.skipClarify) {
|
|
1203
|
-
const
|
|
1204
|
-
const hasClarifiedDocs = await (
|
|
1210
|
+
const { hasValidClarifiedDocs } = await Promise.resolve().then(() => __importStar(require('../core/requirement-clarifier')));
|
|
1211
|
+
const hasClarifiedDocs = await hasValidClarifiedDocs(iterDir);
|
|
1205
1212
|
if (!hasClarifiedDocs && clarifyBlocks.size === 0) {
|
|
1206
1213
|
// 重新检测需求质量
|
|
1207
1214
|
const { detectProfessionalLevel } = await Promise.resolve().then(() => __importStar(require('../core/requirement-clarifier')));
|
|
@@ -1228,7 +1235,7 @@ ${singlePrompt}`);
|
|
|
1228
1235
|
logger_1.logger.error(` ${lowQualityCount} 个需求文档质量不足,必须先澄清为 PRD`);
|
|
1229
1236
|
logger_1.logger.info('');
|
|
1230
1237
|
logger_1.logger.info('解决方式:');
|
|
1231
|
-
logger_1.logger.info(' 1. 在 AI 输出中先包含 [CLARIFY:
|
|
1238
|
+
logger_1.logger.info(' 1. 在 AI 输出中先包含 [CLARIFY:{feature}/overview/CLARIFY.md] 标记的澄清文档');
|
|
1232
1239
|
logger_1.logger.info(' 2. 或先手动运行: speccore clarify --from "<需求文件>" --to ' + options.iteration + ' --prompt');
|
|
1233
1240
|
logger_1.logger.info('');
|
|
1234
1241
|
logger_1.logger.info(' 如需跳过澄清(不推荐):');
|
|
@@ -4558,6 +4565,24 @@ sequenceDiagram
|
|
|
4558
4565
|
const GLOBAL_INDEX_DOCS = ['FUNCTION_MAP.md', 'INTERACTION_MAP.md', 'PLATFORMS.md'];
|
|
4559
4566
|
const FEATURE_OVERVIEW_DOCS_LIST = ['REQUIREMENT.md', 'ANALYSIS.md', 'TECH.md', 'RISK.md', 'DEPS.md', 'REVIEW.md', 'MONITOR.md', 'DEV_GUIDE.md'];
|
|
4560
4567
|
const PLATFORM_DOCS = ['TECH.md', 'TEST.md', 'UI_SPEC.md', 'DEV_GUIDE.md'];
|
|
4568
|
+
// v8.3.182+: 显式文档路由表,定义每类文档的归属(索引类 vs 内容类)
|
|
4569
|
+
const DOC_ROUTING = {
|
|
4570
|
+
// 索引类 → overview/(跨功能全局可见)
|
|
4571
|
+
'FUNCTION_MAP.md': 'overview',
|
|
4572
|
+
'INTERACTION_MAP.md': 'overview',
|
|
4573
|
+
'PLATFORMS.md': 'overview',
|
|
4574
|
+
'CLARIFY.md': 'overview', // 全局澄清(跨功能共性问题)
|
|
4575
|
+
'API_CONTRACT.yaml': 'overview', // 跨功能接口契约
|
|
4576
|
+
// 内容类 → {feature}/overview/(功能模块专属)
|
|
4577
|
+
'REQUIREMENT.md': '{feature}/overview',
|
|
4578
|
+
'ANALYSIS.md': '{feature}/overview',
|
|
4579
|
+
'TECH.md': '{feature}/overview',
|
|
4580
|
+
'RISK.md': '{feature}/overview',
|
|
4581
|
+
'DEPS.md': '{feature}/overview',
|
|
4582
|
+
'REVIEW.md': '{feature}/overview',
|
|
4583
|
+
'MONITOR.md': '{feature}/overview',
|
|
4584
|
+
'DEV_GUIDE.md': '{feature}/overview',
|
|
4585
|
+
};
|
|
4561
4586
|
// GLOBAL_DOCS 引用
|
|
4562
4587
|
const GLOBAL_DOCS = [...GLOBAL_INDEX_DOCS, ...FEATURE_OVERVIEW_DOCS_LIST];
|
|
4563
4588
|
let taskDocs = docs.filter(([n]) => includeDocs.includes(n));
|
|
@@ -4774,9 +4799,9 @@ sequenceDiagram
|
|
|
4774
4799
|
prompt += `**Step 1**: 读取上述每个需求文档的原始内容\n`;
|
|
4775
4800
|
prompt += `**Step 2**: 将口语化/非专业描述整理为 PRD 级专业文档\n`;
|
|
4776
4801
|
prompt += `**Step 3**: 补充:验收标准(AC)、功能边界、业务规则、异常处理、数据模型\n`;
|
|
4777
|
-
prompt += `**Step 4**:
|
|
4802
|
+
prompt += `**Step 4**: 输出澄清后的文档,使用以下标记格式(v8.3.181+ 推荐新路径):\n`;
|
|
4778
4803
|
prompt += `\`\`\`
|
|
4779
|
-
[CLARIFY:
|
|
4804
|
+
[CLARIFY:{feature-name}/overview/CLARIFY.md]
|
|
4780
4805
|
---
|
|
4781
4806
|
source: "原始文档路径"
|
|
4782
4807
|
clarified-at: "${now}"
|
|
@@ -4804,11 +4829,11 @@ status: "clarified"
|
|
|
4804
4829
|
...
|
|
4805
4830
|
\`\`\`
|
|
4806
4831
|
`;
|
|
4807
|
-
prompt += `**Step 5**: 用 Read 工具验证文件已正确写入 \`{迭代}/020-specs/
|
|
4832
|
+
prompt += `**Step 5**: 用 Read 工具验证文件已正确写入 \`{迭代}/020-specs/{feature-name}/overview/CLARIFY.md\`\n`;
|
|
4808
4833
|
prompt += `**Step 6**: 基于澄清后的需求继续 Phase 1 分析\n\n`;
|
|
4809
4834
|
prompt += `### ⚠️ 重要提醒\n\n`;
|
|
4810
4835
|
prompt += `- **如果输出中没有 [CLARIFY:xxx] 标记的澄清文档,--apply 阶段将拒绝写入所有分析结果**\n`;
|
|
4811
|
-
prompt += `- CLI 会在接收 --apply 时先解析 [CLARIFY:xxx] 标记,写入 020-specs/
|
|
4836
|
+
prompt += `- CLI 会在接收 --apply 时先解析 [CLARIFY:xxx] 标记,写入 020-specs/{feature}/overview/CLARIFY.md(模块)或 020-specs/overview/CLARIFY.md(全局),然后才处理 [DOC:xxx] 标记\n`;
|
|
4812
4837
|
prompt += `- 不要跳过此步骤,不要假设需求已经够清晰\n`;
|
|
4813
4838
|
prompt += `- 如果原始描述不完整,在澄清文档中标注「待补充」而不是自行编造\n\n`;
|
|
4814
4839
|
prompt += `---\n\n`;
|
|
@@ -4935,15 +4960,49 @@ status: "clarified"
|
|
|
4935
4960
|
const iterDirForCtx = await (0, context_1.getIterationDir)(iter);
|
|
4936
4961
|
if (iterDirForCtx) {
|
|
4937
4962
|
// v8.3.160+: 路径引用模式 — 列出文档清单,让 AI 按需 Read
|
|
4963
|
+
// v8.3.181+: 优先加载两级澄清文档(全局 + 模块),其次兼容旧路径
|
|
4938
4964
|
const docList = [];
|
|
4939
|
-
const
|
|
4965
|
+
const specsDir = (0, path_1.join)(iterDirForCtx, '020-specs');
|
|
4966
|
+
// 1. 全局澄清
|
|
4967
|
+
const globalClarify = (0, path_1.join)(specsDir, 'overview', 'CLARIFY.md');
|
|
4968
|
+
if (await (0, fs_extra_1.pathExists)(globalClarify)) {
|
|
4969
|
+
docList.push('020-specs/overview/CLARIFY.md');
|
|
4970
|
+
}
|
|
4971
|
+
// 2. 模块澄清(v8.3.182+: 同时确保全局澄清被加载,供模块澄清引用)
|
|
4972
|
+
try {
|
|
4973
|
+
if (await (0, fs_extra_1.pathExists)(specsDir)) {
|
|
4974
|
+
const entries = await (0, fs_extra_2.readdir)(specsDir, { withFileTypes: true });
|
|
4975
|
+
for (const e of entries) {
|
|
4976
|
+
if (e.isDirectory() && e.name !== 'overview') {
|
|
4977
|
+
const moduleClarify = (0, path_1.join)(specsDir, e.name, 'overview', 'CLARIFY.md');
|
|
4978
|
+
if (await (0, fs_extra_1.pathExists)(moduleClarify)) {
|
|
4979
|
+
docList.push(`020-specs/${e.name}/overview/CLARIFY.md`);
|
|
4980
|
+
}
|
|
4981
|
+
}
|
|
4982
|
+
}
|
|
4983
|
+
}
|
|
4984
|
+
}
|
|
4985
|
+
catch { /* 忽略 */ }
|
|
4986
|
+
// 如果有模块澄清但 docList 中还没有全局澄清,确保全局澄清在最前面
|
|
4987
|
+
if (docList.some(p => p.includes('/overview/CLARIFY.md') && !p.startsWith('020-specs/overview/'))) {
|
|
4988
|
+
const globalClarifyPath = '020-specs/overview/CLARIFY.md';
|
|
4989
|
+
if (!docList.includes(globalClarifyPath)) {
|
|
4990
|
+
const globalClarifyFull = (0, path_1.join)(specsDir, 'overview', 'CLARIFY.md');
|
|
4991
|
+
if (await (0, fs_extra_1.pathExists)(globalClarifyFull)) {
|
|
4992
|
+
docList.unshift(globalClarifyPath);
|
|
4993
|
+
}
|
|
4994
|
+
}
|
|
4995
|
+
}
|
|
4996
|
+
// 3. 兼容旧路径:020-specs/requirements/
|
|
4997
|
+
const goldenReqDir = (0, path_1.join)(specsDir, 'requirements');
|
|
4940
4998
|
if (await (0, fs_extra_1.pathExists)(goldenReqDir)) {
|
|
4941
4999
|
const files = (await Promise.resolve().then(() => __importStar(require('fs-extra')))).readdirSync(goldenReqDir).filter((f) => f.endsWith('.md')).slice(0, 10);
|
|
4942
5000
|
for (const f of files) {
|
|
4943
5001
|
docList.push(`020-specs/requirements/${f}`);
|
|
4944
5002
|
}
|
|
4945
5003
|
}
|
|
4946
|
-
|
|
5004
|
+
// 4. 如果没有澄清文档,回退到原始需求文档
|
|
5005
|
+
if (docList.length === 0) {
|
|
4947
5006
|
const reqDir = (0, path_1.join)(iterDirForCtx, '010-requirements');
|
|
4948
5007
|
const prdSources = (0, path_1.join)(reqDir, 'sources');
|
|
4949
5008
|
const prdConverted = (0, path_1.join)(reqDir, 'converted');
|
|
@@ -5251,7 +5310,33 @@ status: "clarified"
|
|
|
5251
5310
|
}
|
|
5252
5311
|
prompt += `\n`;
|
|
5253
5312
|
}
|
|
5254
|
-
|
|
5313
|
+
// v8.3.182+: 显式文档路由表
|
|
5314
|
+
prompt += `## 📋 文档路由表(v8.3.182+)\n\n`;
|
|
5315
|
+
prompt += `> 以下表格明确每类文档的写入路径。索引类放 overview/,内容类放 {feature}/overview/,端专属放 {feature}/{端}/。\n\n`;
|
|
5316
|
+
prompt += `| 文档名 | 路由目标 | 文档类型 | 说明 |\n`;
|
|
5317
|
+
prompt += `| :--- | :--- | :--- | :--- |\n`;
|
|
5318
|
+
prompt += `| FUNCTION_MAP.md | 020-specs/overview/ | 索引类 | 功能单元 × 端映射表(全局) |\n`;
|
|
5319
|
+
prompt += `| INTERACTION_MAP.md | 020-specs/overview/ | 索引类 | 跨端交互时序图(全局) |\n`;
|
|
5320
|
+
prompt += `| PLATFORMS.md | 020-specs/overview/ | 索引类 | 端列表(全局) |\n`;
|
|
5321
|
+
prompt += `| CLARIFY.md | 020-specs/overview/ | 索引类 | 全局澄清(跨功能共性问题) |\n`;
|
|
5322
|
+
prompt += `| API_CONTRACT.yaml | 020-specs/overview/ | 索引类 | 跨功能接口契约(全局) |\n`;
|
|
5323
|
+
prompt += `| REQUIREMENT.md | 020-specs/{feature}/overview/ | 内容类 | 该功能模块的需求规格 |\n`;
|
|
5324
|
+
prompt += `| ANALYSIS.md | 020-specs/{feature}/overview/ | 内容类 | 该功能模块的需求分析 |\n`;
|
|
5325
|
+
prompt += `| TECH.md | 020-specs/{feature}/overview/ | 内容类 | 该功能模块的技术方案(Phase 1) |\n`;
|
|
5326
|
+
prompt += `| RISK.md | 020-specs/{feature}/overview/ | 内容类 | 该功能模块的风险评估 |\n`;
|
|
5327
|
+
prompt += `| DEPS.md | 020-specs/{feature}/overview/ | 内容类 | 该功能模块的依赖清单 |\n`;
|
|
5328
|
+
prompt += `| REVIEW.md | 020-specs/{feature}/overview/ | 内容类 | 该功能模块的评审检查项 |\n`;
|
|
5329
|
+
prompt += `| MONITOR.md | 020-specs/{feature}/overview/ | 内容类 | 该功能模块的监控指标 |\n`;
|
|
5330
|
+
prompt += `| DEV_GUIDE.md | 020-specs/{feature}/overview/ | 内容类 | 该功能模块的实现指南(Phase 1) |\n`;
|
|
5331
|
+
prompt += `| TECH.md | 020-specs/{feature}/{端}/ | 端专属 | 该模块该端的技术方案(Phase 2) |\n`;
|
|
5332
|
+
prompt += `| TEST.md | 020-specs/{feature}/{端}/ | 端专属 | 该模块该端的测试用例(Phase 2) |\n`;
|
|
5333
|
+
prompt += `| UI_SPEC.md | 020-specs/{feature}/{端}/ | 端专属 | 该模块该端的 UI 规范(Phase 2) |\n`;
|
|
5334
|
+
prompt += `| DEV_GUIDE.md | 020-specs/{feature}/{端}/ | 端专属 | 该模块该端的实现指南(Phase 2) |\n\n`;
|
|
5335
|
+
prompt += `> **重要规则**:\n`;
|
|
5336
|
+
prompt += `> - 索引类文档(FUNCTION_MAP.md / INTERACTION_MAP.md / PLATFORMS.md / CLARIFY.md / API_CONTRACT.yaml)**必须**写入 020-specs/overview/,严禁写入 {feature}/overview/\n`;
|
|
5337
|
+
prompt += `> - 内容类文档(REQUIREMENT.md / ANALYSIS.md / TECH.md / RISK.md / DEPS.md / REVIEW.md / MONITOR.md / DEV_GUIDE.md)**必须**写入 020-specs/{feature}/overview/,严禁写入 020-specs/overview/\n`;
|
|
5338
|
+
prompt += `> - ANALYSIS.md 属于内容类,严禁放在 020-specs/overview/ 下\n\n`;
|
|
5339
|
+
const dirStepNum = platformTypes.size > 0 ? 10 : 9;
|
|
5255
5340
|
prompt += `${dirStepNum}. **目录结构(严格遵循,禁止自创目录)**:\n`;
|
|
5256
5341
|
prompt += ` - **全局索引**(跨端汇总)→ 通过 --apply 写入,CLI 自动路由到 \`020-specs/overview/{文件名}\`\n`;
|
|
5257
5342
|
prompt += ` - FUNCTION_MAP.md(功能单元 × 端映射表)\n`;
|
|
@@ -5909,14 +5994,15 @@ async function buildClarifyPhasePrompt(iteration) {
|
|
|
5909
5994
|
prompt += ` - 记录取舍:每轮迭代记录「采纳/拒绝/待确认」的决策\n\n`;
|
|
5910
5995
|
prompt += `## Step 5: 确认写入\n\n`;
|
|
5911
5996
|
prompt += `当用户确认 "满意,可以写入" 后:\n\n`;
|
|
5912
|
-
prompt += `**必须为每份源文档分别生成独立的澄清文档**,使用 \`[CLARIFY:
|
|
5997
|
+
prompt += `**必须为每份源文档分别生成独立的澄清文档**,使用 \`[CLARIFY:{feature-name}/overview/CLARIFY.md]\` 标记分隔:\n\n`;
|
|
5998
|
+
prompt += `> v8.3.181+ 推荐使用新路径。旧格式 \`[CLARIFY:requirements/xxx-clarified.md]\` 仍兼容。\n\n`;
|
|
5913
5999
|
if (docPaths.length > 1) {
|
|
5914
6000
|
prompt += `本次共 ${docPaths.length} 份源文档,需要输出 ${docPaths.length} 个 \`[CLARIFY:...]\` 标记块:\n\n`;
|
|
5915
6001
|
for (const p of docPaths) {
|
|
5916
6002
|
const name = p.split('/').pop() || '-';
|
|
5917
6003
|
const baseName = name.replace(/\.md$/, '');
|
|
5918
6004
|
prompt += `\`\`\`\n`;
|
|
5919
|
-
prompt += `[CLARIFY
|
|
6005
|
+
prompt += `[CLARIFY:${baseName}/overview/CLARIFY.md]\n`;
|
|
5920
6006
|
prompt += `---\n`;
|
|
5921
6007
|
prompt += `source: "010-requirements/.../${name}"\n`;
|
|
5922
6008
|
prompt += `clarified-at: "${new Date().toISOString()}"\n`;
|
|
@@ -5941,10 +6027,10 @@ async function buildClarifyPhasePrompt(iteration) {
|
|
|
5941
6027
|
}
|
|
5942
6028
|
prompt += `> ⚠️ **禁止合并**:每份源文档必须对应一份独立的 \`-clarified.md\`,即使内容有关联也要分开输出。\n\n`;
|
|
5943
6029
|
prompt += `同时生成对应的对比报告文件(可选):\n`;
|
|
5944
|
-
prompt += `- \`020-specs/
|
|
6030
|
+
prompt += `- \`020-specs/{源文件名}/overview/CLARIFY-diff.md\` — 保存最终对比报告\n\n`;
|
|
5945
6031
|
prompt += `使用以下命令写入:\n\n`;
|
|
5946
6032
|
prompt += `\`\`\`bash\n`;
|
|
5947
|
-
prompt += `speccore analyze --apply '{"020-specs/
|
|
6033
|
+
prompt += `speccore analyze --apply '{"020-specs/xxx/overview/CLARIFY.md":"...","020-specs/xxx/overview/CLARIFY-diff.md":"..."}' -I ${iteration}\n`;
|
|
5948
6034
|
prompt += `\`\`\`\n\n`;
|
|
5949
6035
|
prompt += `> 注意:写入后 CLI 会自动推进到需求确认阶段。\n`;
|
|
5950
6036
|
return await injectGraphSummary(prompt);
|