speccore 8.3.174 → 8.3.176

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.
Files changed (98) hide show
  1. package/dist/cli.js +42 -134
  2. package/dist/cli.js.map +1 -1
  3. package/dist/commands/analyze.d.ts.map +1 -1
  4. package/dist/commands/analyze.js +23 -49
  5. package/dist/commands/analyze.js.map +1 -1
  6. package/dist/commands/change.js +4 -4
  7. package/dist/commands/change.js.map +1 -1
  8. package/dist/commands/context-output.js +1 -1
  9. package/dist/commands/context-output.js.map +1 -1
  10. package/dist/commands/doc2spec.d.ts +1 -0
  11. package/dist/commands/doc2spec.d.ts.map +1 -1
  12. package/dist/commands/doc2spec.js +128 -4
  13. package/dist/commands/doc2spec.js.map +1 -1
  14. package/dist/commands/execute.js +6 -7
  15. package/dist/commands/execute.js.map +1 -1
  16. package/dist/commands/help.js +2 -2
  17. package/dist/commands/help.js.map +1 -1
  18. package/dist/commands/import.js +3 -3
  19. package/dist/commands/import.js.map +1 -1
  20. package/dist/commands/init.d.ts +1 -1
  21. package/dist/commands/init.js +17 -17
  22. package/dist/commands/init.js.map +1 -1
  23. package/dist/commands/iteration/split.d.ts.map +1 -1
  24. package/dist/commands/iteration/split.js +5 -9
  25. package/dist/commands/iteration/split.js.map +1 -1
  26. package/dist/commands/iteration-from-global.js +1 -1
  27. package/dist/commands/iteration-from-global.js.map +1 -1
  28. package/dist/commands/lifecycle.js +2 -2
  29. package/dist/commands/lifecycle.js.map +1 -1
  30. package/dist/commands/migrate.js +3 -3
  31. package/dist/commands/migrate.js.map +1 -1
  32. package/dist/commands/retro.js +3 -3
  33. package/dist/commands/retro.js.map +1 -1
  34. package/dist/commands/synthesize.d.ts +2 -2
  35. package/dist/commands/synthesize.js +11 -11
  36. package/dist/commands/synthesize.js.map +1 -1
  37. package/dist/commands/task/new.js +1 -1
  38. package/dist/commands/task/new.js.map +1 -1
  39. package/dist/commands/units.d.ts +10 -0
  40. package/dist/commands/units.d.ts.map +1 -0
  41. package/dist/commands/units.js +280 -0
  42. package/dist/commands/units.js.map +1 -0
  43. package/dist/commands/update.d.ts.map +1 -1
  44. package/dist/commands/update.js +14 -15
  45. package/dist/commands/update.js.map +1 -1
  46. package/dist/core/agent-adapter.js +1 -1
  47. package/dist/core/agent-adapter.js.map +1 -1
  48. package/dist/core/agents/index.js +1 -1
  49. package/dist/core/agents/index.js.map +1 -1
  50. package/dist/core/ai-context-generator.js +1 -1
  51. package/dist/core/ai-context-generator.js.map +1 -1
  52. package/dist/core/analyze-engine.js +4 -4
  53. package/dist/core/analyze-engine.js.map +1 -1
  54. package/dist/core/ask-config.js +1 -1
  55. package/dist/core/ask-config.js.map +1 -1
  56. package/dist/core/code-scanner.js +1 -1
  57. package/dist/core/code-scanner.js.map +1 -1
  58. package/dist/core/git-integration.d.ts +1 -1
  59. package/dist/core/git-integration.js +3 -3
  60. package/dist/core/git-integration.js.map +1 -1
  61. package/dist/core/global-artifacts.js +1 -1
  62. package/dist/core/global-artifacts.js.map +1 -1
  63. package/dist/core/global-counters.js +2 -2
  64. package/dist/core/global-counters.js.map +1 -1
  65. package/dist/core/handoff-generator.d.ts +14 -0
  66. package/dist/core/handoff-generator.d.ts.map +1 -0
  67. package/dist/core/handoff-generator.js +218 -0
  68. package/dist/core/handoff-generator.js.map +1 -0
  69. package/dist/core/knowledge-graph.js +8 -8
  70. package/dist/core/knowledge-graph.js.map +1 -1
  71. package/dist/core/prompt-builder.d.ts.map +1 -1
  72. package/dist/core/prompt-builder.js +5 -6
  73. package/dist/core/prompt-builder.js.map +1 -1
  74. package/dist/core/rag-engine.js +3 -3
  75. package/dist/core/rag-engine.js.map +1 -1
  76. package/dist/core/reindex-engine.js +1 -1
  77. package/dist/core/reindex-engine.js.map +1 -1
  78. package/dist/core/requirement-clarifier.d.ts +1 -1
  79. package/dist/core/requirement-clarifier.js +3 -3
  80. package/dist/core/requirement-clarifier.js.map +1 -1
  81. package/dist/core/spec-paths.d.ts +4 -4
  82. package/dist/core/spec-paths.js +10 -10
  83. package/dist/core/spec-paths.js.map +1 -1
  84. package/dist/core/spec-skeleton.js +1 -1
  85. package/dist/core/spec-skeleton.js.map +1 -1
  86. package/dist/core/state.js +6 -6
  87. package/dist/core/state.js.map +1 -1
  88. package/dist/core/streaming-analyzer.js +1 -1
  89. package/dist/core/task-paths.d.ts +2 -2
  90. package/dist/core/task-paths.js +3 -3
  91. package/dist/core/task-paths.js.map +1 -1
  92. package/dist/core/unified-config.d.ts +2 -2
  93. package/dist/core/unified-config.d.ts.map +1 -1
  94. package/dist/core/unified-config.js +2 -2
  95. package/dist/core/unified-config.js.map +1 -1
  96. package/dist/core/verify-engine.js +5 -5
  97. package/dist/core/verify-engine.js.map +1 -1
  98. package/package.json +1 -1
@@ -78,10 +78,7 @@ const unit_context_assembler_1 = require("../core/unit-context-assembler");
78
78
  const pipeline_engine_1 = require("../core/pipeline-engine");
79
79
  const change_detection_1 = require("../core/change-detection");
80
80
  const streaming_analyzer_1 = require("../core/streaming-analyzer");
81
- // v6.80.0+: 需求澄清模块
82
81
  const requirement_clarifier_1 = require("../core/requirement-clarifier");
83
- // v6.83.0+: 专业 AI 角色定义
84
- // v6.84.0+: 迁移到规范数据库 (.speccore/AGENTS/),保留向后兼容
85
82
  const agents_1 = require("../core/agents");
86
83
  // v6.91.0+: 代码知识图谱摘要注入
87
84
  const code_graph_1 = require("../core/code-graph");
@@ -645,7 +642,6 @@ async function analyzeCommand(options) {
645
642
  const reqDir = (0, path_1.join)(iterDir, '010-requirements');
646
643
  const specDir = (0, path_1.join)(iterDir, '020-specs');
647
644
  await (0, fs_extra_1.ensureDir)(specDir);
648
- // v8.2.0+: 需求收集优先从黄金需求目录 020-specs/requirements/ 读取
649
645
  // 该目录存放经过 clarify 后的专业需求,作为分析和后续步骤的唯一依据
650
646
  const requirements = [];
651
647
  const goldenReqDir = (0, path_1.join)(specDir, 'requirements');
@@ -921,7 +917,6 @@ async function analyzeCommand(options) {
921
917
  prompt = await buildClarifyPhasePrompt(iter);
922
918
  }
923
919
  else if (currentStep === 'confirm-check') {
924
- // v6.80.0+: 需求确认阶段 — 输出质量报告提示
925
920
  prompt = await buildConfirmCheckPrompt(iter);
926
921
  }
927
922
  else if (currentStep === 'phase1-prompt') {
@@ -1047,7 +1042,6 @@ async function analyzeCommand(options) {
1047
1042
  // ── Prompt 模式 ──
1048
1043
  if (options.prompt) {
1049
1044
  const iter = options.scope === 'global' ? 'GLOBAL' : (options.iteration || await (0, context_1.getDefaultIteration)());
1050
- // v6.80.0+: 非 Pipeline 模式下也默认检测需求质量
1051
1045
  if (iter !== 'GLOBAL' && !options.skipClarify && !options.pipeline) {
1052
1046
  const iterDir = await (0, context_1.getIterationDir)(iter);
1053
1047
  const hasClarified = await (0, requirement_clarifier_1.hasValidClarifiedDocs)(iterDir);
@@ -1142,13 +1136,12 @@ ${singlePrompt}`);
1142
1136
  return;
1143
1137
  }
1144
1138
  }
1145
- // v8.3.161+: AI 上下文中禁止 --skip-clarify(质量门禁不可被 AI 自行绕过)
1146
1139
  if (options.skipClarify && !process.stdout.isTTY) {
1147
1140
  logger_1.logger.warn('⚠️ AI 上下文检测到 --skip-clarify,此行为不推荐');
1148
1141
  logger_1.logger.info(' 需求澄清是质量门禁,应由人类用户确认后使用');
1149
1142
  logger_1.logger.info(' 如果需求文档已经过 clarify 流程,会自动跳过澄清阶段');
1150
1143
  logger_1.logger.info(' 如需强制跳过,请在交互式终端中执行此命令');
1151
- // 不阻止,但输出强烈警告(保持向后兼容)
1144
+ // 不阻止,但输出强烈警告(输出警告)
1152
1145
  }
1153
1146
  // v8.3.0+: 解析 [CLARIFY:xxx] 标记 — 需求澄清是强制前置步骤
1154
1147
  const clarifyBlocks = parseClarifyMarkers(options.apply);
@@ -1212,7 +1205,6 @@ ${singlePrompt}`);
1212
1205
  try {
1213
1206
  const docs = JSON.parse(options.apply);
1214
1207
  const docEntries = Object.entries(docs);
1215
- // v8.3.161+: 批量 apply 防护 — JSON 模式同样限制文档数量
1216
1208
  const MAX_DOCS_PER_APPLY = 3;
1217
1209
  if (docEntries.length > MAX_DOCS_PER_APPLY) {
1218
1210
  logger_1.logger.error(`❌ 批量 apply 拦截: JSON 包含 ${docEntries.length} 个文档,超过单次上限 ${MAX_DOCS_PER_APPLY}`);
@@ -1226,7 +1218,6 @@ ${singlePrompt}`);
1226
1218
  logger_1.logger.info(' 原因:单会话内批量生成过多文档会导致上下文溢出、质量下降');
1227
1219
  return;
1228
1220
  }
1229
- // v8.3.161+: 迭代级 analyze 禁止直接写入 overview/REQUIREMENT.md
1230
1221
  if (!isGlobalScope) {
1231
1222
  for (const filename of Object.keys(docs)) {
1232
1223
  if (filename === 'overview/REQUIREMENT.md' || filename === 'REQUIREMENT.md') {
@@ -1252,7 +1243,7 @@ ${singlePrompt}`);
1252
1243
  const bk = await (0, task_utils_1.backupWithTimestamp)(fp);
1253
1244
  if (bk) {
1254
1245
  backups.push(bk);
1255
- logger_1.logger.info(` 📦 ${filename} 旧版已备份: ${(0, path_1.basename)(bk)}`);
1246
+ logger_1.logger.info(` 📦 ${filename} 已备份: ${(0, path_1.basename)(bk)}`);
1256
1247
  }
1257
1248
  await (0, fs_extra_1.writeFile)(fp, content);
1258
1249
  count++;
@@ -1325,7 +1316,7 @@ ${singlePrompt}`);
1325
1316
  const bk = await (0, task_utils_1.backupWithTimestamp)(fp);
1326
1317
  if (bk) {
1327
1318
  backups.push(bk);
1328
- logger_1.logger.info(` 📦 ${filename} 旧版已备份: ${(0, path_1.basename)(bk)}`);
1319
+ logger_1.logger.info(` 📦 ${filename} 已备份: ${(0, path_1.basename)(bk)}`);
1329
1320
  }
1330
1321
  await (0, fs_extra_1.writeFile)(fp, content);
1331
1322
  count++;
@@ -1373,8 +1364,7 @@ ${singlePrompt}`);
1373
1364
  }
1374
1365
  let skippedCount = 0;
1375
1366
  for (const [filename, content] of Object.entries(docs)) {
1376
- // v8.2.0+: 需求文档写入黄金需求目录 020-specs/requirements/
1377
- // 支持 010-requirements/ 路径(向后兼容,自动重定向)
1367
+ // 支持 010-requirements/ 路径(自动重定向)
1378
1368
  if (filename.startsWith('020-specs/requirements/')) {
1379
1369
  const reqFilePath = filename.slice('020-specs/requirements/'.length);
1380
1370
  const goldenDir = (0, path_1.join)(iterDir, '020-specs', 'requirements');
@@ -1390,10 +1380,8 @@ ${singlePrompt}`);
1390
1380
  count++;
1391
1381
  continue;
1392
1382
  }
1393
- // v6.80.0+: 向后兼容 — 010-requirements/ 路径自动重定向到黄金需求目录
1394
1383
  if (filename.startsWith('010-requirements/')) {
1395
1384
  const reqFilePath = filename.slice('010-requirements/'.length);
1396
- // v8.2.0+: clarify 结果写入 020-specs/requirements/ 而非 010-requirements/converted/
1397
1385
  const goldenDir = (0, path_1.join)(iterDir, '020-specs', 'requirements');
1398
1386
  const fp = (0, path_1.join)(goldenDir, reqFilePath.replace(/^converted\//, ''));
1399
1387
  await (0, fs_extra_1.ensureDir)((0, path_1.dirname)(fp));
@@ -1445,7 +1433,7 @@ ${singlePrompt}`);
1445
1433
  const bk = await (0, task_utils_1.backupWithTimestamp)(fp);
1446
1434
  if (bk) {
1447
1435
  backups.push(bk);
1448
- logger_1.logger.info(` 📦 ${filename} 旧版已备份: ${(0, path_1.basename)(bk)}`);
1436
+ logger_1.logger.info(` 📦 ${filename} 已备份: ${(0, path_1.basename)(bk)}`);
1449
1437
  }
1450
1438
  await writeFileMerged(fp, content, !!options.merge);
1451
1439
  if (options.merge)
@@ -1467,7 +1455,7 @@ ${singlePrompt}`);
1467
1455
  const bk = await (0, task_utils_1.backupWithTimestamp)(fp);
1468
1456
  if (bk) {
1469
1457
  backups.push(bk);
1470
- logger_1.logger.info(` 📦 ${filename} 旧版已备份: ${(0, path_1.basename)(bk)}`);
1458
+ logger_1.logger.info(` 📦 ${filename} 已备份: ${(0, path_1.basename)(bk)}`);
1471
1459
  }
1472
1460
  await writeFileMerged(fp, content, !!options.merge);
1473
1461
  if (options.merge)
@@ -1496,7 +1484,7 @@ ${singlePrompt}`);
1496
1484
  }
1497
1485
  // 综合文档写入 overview/ 子目录,端专属文档写入 {功能模块}/{端}/ 子目录
1498
1486
  // v8.3.24+: 按文件名前缀路由,支持多段指定
1499
- // v8.3.25+: 如果 AI 输出旧格式 {端}/{文件},尝试回退到功能模块路由
1487
+ // 如果 AI 输出 {端}/{文件},尝试回退到功能模块路由
1500
1488
  let targetDir;
1501
1489
  if (globalSet.has(cleanFilename)) {
1502
1490
  targetDir = (0, path_1.join)(specDir, spec_paths_1.GLOBAL_SPECS_DIR);
@@ -1537,7 +1525,7 @@ ${singlePrompt}`);
1537
1525
  const bk = await (0, task_utils_1.backupWithTimestamp)(fp);
1538
1526
  if (bk) {
1539
1527
  backups.push(bk);
1540
- logger_1.logger.info(` 📦 ${filename} 旧版已备份: ${(0, path_1.basename)(bk)}`);
1528
+ logger_1.logger.info(` 📦 ${filename} 已备份: ${(0, path_1.basename)(bk)}`);
1541
1529
  }
1542
1530
  await writeFileMerged(fp, content, !!options.merge);
1543
1531
  if (options.merge)
@@ -1689,10 +1677,8 @@ ${singlePrompt}`);
1689
1677
  // fallback to single-file mode
1690
1678
  }
1691
1679
  }
1692
- // v8.2.0+: [DOC:xxx] 标记解析 —— 统一报告自动拆分
1693
1680
  // AI 输出格式: [DOC:REQUIREMENT.md]...内容...[DOC:TECH.md]...内容...
1694
1681
  const docBlocks = parseDocMarkers(options.apply);
1695
- // v8.3.161+: 批量 apply 防护 — 禁止单会话内批量写入过多文档
1696
1682
  const MAX_DOCS_PER_APPLY = 3;
1697
1683
  if (docBlocks.size > MAX_DOCS_PER_APPLY) {
1698
1684
  logger_1.logger.error(`❌ 批量 apply 拦截: 检测到 ${docBlocks.size} 个 [DOC:xxx] 文档,超过单次上限 ${MAX_DOCS_PER_APPLY}`);
@@ -1707,7 +1693,6 @@ ${singlePrompt}`);
1707
1693
  logger_1.logger.info(' 请在新会话中逐个批次执行,确保每个文档的质量深入');
1708
1694
  return;
1709
1695
  }
1710
- // v8.3.161+: 迭代级 analyze 禁止直接写入 overview/REQUIREMENT.md
1711
1696
  if (!isGlobalScope) {
1712
1697
  for (const docName of docBlocks.keys()) {
1713
1698
  if (docName === 'overview/REQUIREMENT.md' || docName === 'REQUIREMENT.md') {
@@ -1744,7 +1729,7 @@ ${singlePrompt}`);
1744
1729
  const bk = await (0, task_utils_1.backupWithTimestamp)(fp);
1745
1730
  if (bk) {
1746
1731
  backups.push(bk);
1747
- logger_1.logger.info(` 📦 ${filename} 旧版已备份: ${(0, path_1.basename)(bk)}`);
1732
+ logger_1.logger.info(` 📦 ${filename} 已备份: ${(0, path_1.basename)(bk)}`);
1748
1733
  }
1749
1734
  await (0, fs_extra_1.writeFile)(fp, content);
1750
1735
  count++;
@@ -1806,7 +1791,7 @@ ${singlePrompt}`);
1806
1791
  const bk = await (0, task_utils_1.backupWithTimestamp)(fp);
1807
1792
  if (bk) {
1808
1793
  backups.push(bk);
1809
- logger_1.logger.info(` 📦 ${filename} 旧版已备份: ${(0, path_1.basename)(bk)}`);
1794
+ logger_1.logger.info(` 📦 ${filename} 已备份: ${(0, path_1.basename)(bk)}`);
1810
1795
  }
1811
1796
  await (0, fs_extra_1.writeFile)(fp, content);
1812
1797
  count++;
@@ -1820,7 +1805,6 @@ ${singlePrompt}`);
1820
1805
  const validPlatforms = new Set([spec_paths_1.GLOBAL_SPECS_DIR, ...(await (0, spec_paths_1.parsePlatformList)())]);
1821
1806
  let skippedCount = 0;
1822
1807
  for (const [filename, content] of Object.entries(docs)) {
1823
- // v8.2.0+: 黄金需求目录支持
1824
1808
  if (filename.startsWith('020-specs/requirements/')) {
1825
1809
  const reqFilePath = filename.slice('020-specs/requirements/'.length);
1826
1810
  const goldenDir = (0, path_1.join)(iterDir, '020-specs', 'requirements');
@@ -1836,7 +1820,7 @@ ${singlePrompt}`);
1836
1820
  count++;
1837
1821
  continue;
1838
1822
  }
1839
- // 向后兼容:010-requirements/ 自动重定向到黄金需求目录
1823
+ // 010-requirements/ 自动重定向到黄金需求目录
1840
1824
  if (filename.startsWith('010-requirements/')) {
1841
1825
  const reqFilePath = filename.slice('010-requirements/'.length);
1842
1826
  const goldenDir = (0, path_1.join)(iterDir, '020-specs', 'requirements');
@@ -1904,7 +1888,7 @@ ${singlePrompt}`);
1904
1888
  const bk = await (0, task_utils_1.backupWithTimestamp)(fp);
1905
1889
  if (bk) {
1906
1890
  backups.push(bk);
1907
- logger_1.logger.info(` 📦 ${filename} 旧版已备份: ${(0, path_1.basename)(bk)}`);
1891
+ logger_1.logger.info(` 📦 ${filename} 已备份: ${(0, path_1.basename)(bk)}`);
1908
1892
  }
1909
1893
  await (0, fs_extra_1.writeFile)(fp, content);
1910
1894
  count++;
@@ -1922,7 +1906,6 @@ ${singlePrompt}`);
1922
1906
  silent: true,
1923
1907
  });
1924
1908
  }
1925
- // v8.2.0+: 单元分析结果保存到缓存(供 --consolidate 汇总使用)
1926
1909
  if (options.unit && options.iteration) {
1927
1910
  try {
1928
1911
  const unitsCachePath = (0, path_1.join)(_projectRoot, exports.UNITS_CACHE_DIR, options.iteration, 'units.json');
@@ -1967,7 +1950,7 @@ ${singlePrompt}`);
1967
1950
  const taskBackup = await (0, task_utils_1.backupWithTimestamp)(taskAnalysisPath);
1968
1951
  if (taskBackup) {
1969
1952
  backups.push(taskBackup);
1970
- logger_1.logger.info(` 📦 旧版已备份: ${taskBackup.split('/').pop()}`);
1953
+ logger_1.logger.info(` 📦 已备份: ${taskBackup.split('/').pop()}`);
1971
1954
  }
1972
1955
  await (0, fs_extra_1.writeFile)(taskAnalysisPath, options.apply);
1973
1956
  const platformLabel = options.platform ? `/${options.platform}` : '';
@@ -1986,7 +1969,7 @@ ${singlePrompt}`);
1986
1969
  const globalBackup = await (0, task_utils_1.backupWithTimestamp)(globalAnalysisPath);
1987
1970
  if (globalBackup) {
1988
1971
  backups.push(globalBackup);
1989
- logger_1.logger.info(` 📦 旧版已备份: ${globalBackup.split('/').pop()}`);
1972
+ logger_1.logger.info(` 📦 已备份: ${globalBackup.split('/').pop()}`);
1990
1973
  }
1991
1974
  await (0, fs_extra_1.writeFile)(globalAnalysisPath, options.apply);
1992
1975
  logger_1.logger.success(`✅ ANALYSIS.md 已写入 .speccore/GLOBAL/`);
@@ -2005,7 +1988,7 @@ ${singlePrompt}`);
2005
1988
  const iterBackup = await (0, task_utils_1.backupWithTimestamp)(iterAnalysisPath);
2006
1989
  if (iterBackup) {
2007
1990
  backups.push(iterBackup);
2008
- logger_1.logger.info(` 📦 旧版已备份: ${iterBackup.split('/').pop()}`);
1991
+ logger_1.logger.info(` 📦 已备份: ${iterBackup.split('/').pop()}`);
2009
1992
  }
2010
1993
  await (0, fs_extra_1.writeFile)(iterAnalysisPath, options.apply);
2011
1994
  logger_1.logger.success(`✅ ANALYSIS.md 已写入 020-specs/overview/`);
@@ -2141,7 +2124,7 @@ ${singlePrompt}`);
2141
2124
  }));
2142
2125
  }
2143
2126
  else if (state.currentStep === 'phase2-prompt') {
2144
- // 兼容旧 Pipeline 步骤名
2127
+ // Pipeline 步骤名映射
2145
2128
  nextPrompt = (0, prompt_builder_1.buildPromptText)(await (0, prompt_builder_1.buildPrompt)('analyze', {
2146
2129
  iteration: options.iteration,
2147
2130
  analyzeOptions: { ...options, phase: '2' },
@@ -2457,7 +2440,7 @@ async function enrichTaskDocs(iteration, taskId, reqFiles) {
2457
2440
  return;
2458
2441
  }
2459
2442
  const fullTaskDir = (0, path_1.join)(iterDir, taskEntry.name);
2460
- // 向后兼容: _shared/ → 00-specs/
2443
+ // _shared/ → 00-specs/
2461
2444
  const specsDir = (await (0, fs_extra_1.pathExists)((0, path_1.join)(fullTaskDir, '_shared')))
2462
2445
  ? (0, path_1.join)(fullTaskDir, '_shared')
2463
2446
  : (0, path_1.join)(fullTaskDir, '00-specs');
@@ -2564,7 +2547,7 @@ async function enrichTaskDocs(iteration, taskId, reqFiles) {
2564
2547
  }
2565
2548
  // 创建缺失文件(v6.49.9+: 扫描平铺的端目录)
2566
2549
  const subtaskDirs = subtaskPaths;
2567
- // 旧结构回退
2550
+ // 结构回退
2568
2551
  if (subtaskDirs.length === 0) {
2569
2552
  const legacyArtifacts = (0, path_1.join)(fullTaskDir, '99-artifacts');
2570
2553
  if (await (0, fs_extra_1.pathExists)(legacyArtifacts))
@@ -2862,7 +2845,7 @@ async function detectGlobalLayerProgress() {
2862
2845
  }
2863
2846
  }
2864
2847
  else {
2865
- // 回退:检查各端 modules/ 目录是否有文档(旧逻辑)
2848
+ // 回退:检查各端 modules/ 目录是否有文档(兜底)
2866
2849
  const entries = await (0, fs_extra_2.readdir)(platformsDir, { withFileTypes: true });
2867
2850
  const platformDirs = entries.filter(e => e.isDirectory() && e.name !== '_shared').map(e => e.name);
2868
2851
  if (platformDirs.length === 0) {
@@ -3839,7 +3822,7 @@ async function buildMultiDocPrompt(command, ctx, options, clarifyCtx) {
3839
3822
  prompt += `3. **PATTERNS/*.md 特殊处理**: 不覆盖,只追加。Read 旧文件 → 合并新内容 → Write 回原文件(不生成备份)\n`;
3840
3823
  prompt += `4. 所有文件写完后,输出冲突汇总:\n`;
3841
3824
  prompt += ` \`\`\`\n`;
3842
- prompt += ` ⚠️ N 个文件有冲突,旧版已重命名为时间戳格式:\n`;
3825
+ prompt += ` ⚠️ N 个文件有冲突,已重命名为时间戳格式:\n`;
3843
3826
  prompt += ` 📄 .speccore/GLOBAL/platforms/xxx/API_INVENTORY.md\n`;
3844
3827
  prompt += ` 对比: diff API_INVENTORY.md API_INVENTORY-20260813143025.md\n`;
3845
3828
  prompt += ` 💡 请对比时间戳文件,合并自定义内容后删除\n`;
@@ -4538,7 +4521,7 @@ sequenceDiagram
4538
4521
  const GLOBAL_INDEX_DOCS = ['FUNCTION_MAP.md', 'INTERACTION_MAP.md', 'PLATFORMS.md'];
4539
4522
  const FEATURE_OVERVIEW_DOCS_LIST = ['REQUIREMENT.md', 'ANALYSIS.md', 'TECH.md', 'RISK.md', 'DEPS.md', 'REVIEW.md', 'MONITOR.md', 'DEV_GUIDE.md'];
4540
4523
  const PLATFORM_DOCS = ['TECH.md', 'TEST.md', 'UI_SPEC.md', 'DEV_GUIDE.md'];
4541
- // 向后兼容:保留 GLOBAL_DOCS 引用
4524
+ // GLOBAL_DOCS 引用
4542
4525
  const GLOBAL_DOCS = [...GLOBAL_INDEX_DOCS, ...FEATURE_OVERVIEW_DOCS_LIST];
4543
4526
  let taskDocs = docs.filter(([n]) => includeDocs.includes(n));
4544
4527
  if (ctx.phase === '1') {
@@ -4568,7 +4551,6 @@ sequenceDiagram
4568
4551
  if (perDocStatus.nextUnfilled) {
4569
4552
  const nextDocName = perDocStatus.nextUnfilled.docName;
4570
4553
  const nextDocPlatform = perDocStatus.nextUnfilled.platform || null;
4571
- // v8.2.0+: 功能单元聚焦模式不强制单文档过滤,让 AI 一次输出完整单元分析
4572
4554
  const isUnitMode = !!(options?.unit || options?.consolidate || options?.extractUnits);
4573
4555
  if (!isUnitMode) {
4574
4556
  // 过滤 taskDocs 只保留下一个未填充的文档(默认逐文档推进模式)
@@ -4839,7 +4821,6 @@ status: "clarified"
4839
4821
  logger_1.logger.warn(` ⚠️ 代码关联注入失败: ${e.message}`);
4840
4822
  }
4841
4823
  }
4842
- // v6.80.0+: 注入需求质量上下文(迭代级分析时)
4843
4824
  if (!isGlobal && !isTask && ctx.iteration && ctx.iteration !== 'GLOBAL') {
4844
4825
  try {
4845
4826
  const iterDir = await (0, context_1.getIterationDir)(ctx.iteration);
@@ -5655,11 +5636,9 @@ async function getSubtaskDirs(taskDir) {
5655
5636
  }
5656
5637
  catch { /* ignore */ }
5657
5638
  }
5658
- // v8.3.121+: 已移除 10-backend/20-frontend 旧结构回退
5659
5639
  return result;
5660
5640
  }
5661
5641
  // ═══════════════════════════════════════════════════════════
5662
- // v6.80.0+: 需求澄清 Phase Prompt 构建
5663
5642
  // ═══════════════════════════════════════════════════════════
5664
5643
  async function buildClarifyPhasePrompt(iteration) {
5665
5644
  const iterDir = await (0, context_1.getIterationDir)(iteration);
@@ -5700,7 +5679,6 @@ async function buildClarifyPhasePrompt(iteration) {
5700
5679
  if (qualityReports.length > 0) {
5701
5680
  await (0, requirement_clarifier_1.writeClarifyReport)(iterDir, qualityReports);
5702
5681
  }
5703
- // v8.2.0+: 提取功能单元,支持单元化澄清(解决注意力漂移)
5704
5682
  let allDocContent = '';
5705
5683
  for (const p of docPaths) {
5706
5684
  try {
@@ -5710,7 +5688,6 @@ async function buildClarifyPhasePrompt(iteration) {
5710
5688
  }
5711
5689
  const extractedUnits = (0, requirement_clarifier_1.extractUnitsFromText)(allDocContent);
5712
5690
  const hasMultipleUnits = extractedUnits.length >= 2;
5713
- // v6.84.0+: 从 AGENTS 规范数据库动态加载角色
5714
5691
  let prompt = `\n# 任务: 需求专业化(Phase 0: 需求澄清,v6.84.0+)\n\n`;
5715
5692
  const projectRoot = (0, task_utils_1.findProjectRoot)() || ((0, task_utils_1.findProjectRoot)() || process.cwd());
5716
5693
  const agentContext = {
@@ -5727,7 +5704,7 @@ async function buildClarifyPhasePrompt(iteration) {
5727
5704
  }
5728
5705
  }
5729
5706
  else {
5730
- // 回退到硬编码角色(向后兼容)
5707
+ // 回退到硬编码角色(兜底)
5731
5708
  prompt += agents_1.PRODUCT_ANALYST_ROLE;
5732
5709
  prompt += '\n\n';
5733
5710
  prompt += agents_1.INTERACTION_DESIGNER_ROLE;
@@ -5735,7 +5712,7 @@ async function buildClarifyPhasePrompt(iteration) {
5735
5712
  }
5736
5713
  }
5737
5714
  catch {
5738
- // 回退到硬编码角色(向后兼容)
5715
+ // 回退到硬编码角色(兜底)
5739
5716
  prompt += agents_1.PRODUCT_ANALYST_ROLE;
5740
5717
  prompt += '\n\n';
5741
5718
  prompt += agents_1.INTERACTION_DESIGNER_ROLE;
@@ -5781,7 +5758,6 @@ async function buildClarifyPhasePrompt(iteration) {
5781
5758
  }
5782
5759
  prompt += `\n> ⚠️ **重要**:每份源文档对应一份独立的澄清文档,禁止将多份源文档合并为一份。\n\n`;
5783
5760
  }
5784
- // v8.2.0+: 如果检测到多个功能单元,启用单元化澄清模式
5785
5761
  if (hasMultipleUnits) {
5786
5762
  prompt += `## ⚠️ 功能单元拆分澄清模式(v8.2.0+)\n\n`;
5787
5763
  prompt += `检测到需求文档包含 ${extractedUnits.length} 个功能单元。为避免注意力漂移,请**按单元逐个澄清**:\n\n`;
@@ -5949,7 +5925,6 @@ async function buildConfirmCheckPrompt(iteration) {
5949
5925
  prompt += `\n\n... (报告共 ${report.length} 字符,已截断)\n`;
5950
5926
  }
5951
5927
  }
5952
- // v8.2.0+: 检查黄金需求目录是否有 diff 文件
5953
5928
  let diffFiles = [];
5954
5929
  if (await (0, fs_extra_1.pathExists)(goldenDir)) {
5955
5930
  try {
@@ -5992,7 +5967,6 @@ async function buildConfirmCheckPrompt(iteration) {
5992
5967
  return await injectGraphSummary(prompt);
5993
5968
  }
5994
5969
  // ================================================================
5995
- // v8.2.0+: 功能单元聚焦分析辅助函数(解决注意力漂移+空模板问题)
5996
5970
  // ================================================================
5997
5971
  /** 解析 [DOC:filename] 标记,将统一报告拆分为多文档 Map */
5998
5972
  function parseDocMarkers(text) {