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.
- package/dist/cli.js +42 -134
- package/dist/cli.js.map +1 -1
- package/dist/commands/analyze.d.ts.map +1 -1
- package/dist/commands/analyze.js +23 -49
- package/dist/commands/analyze.js.map +1 -1
- package/dist/commands/change.js +4 -4
- package/dist/commands/change.js.map +1 -1
- package/dist/commands/context-output.js +1 -1
- package/dist/commands/context-output.js.map +1 -1
- package/dist/commands/doc2spec.d.ts +1 -0
- package/dist/commands/doc2spec.d.ts.map +1 -1
- package/dist/commands/doc2spec.js +128 -4
- package/dist/commands/doc2spec.js.map +1 -1
- package/dist/commands/execute.js +6 -7
- package/dist/commands/execute.js.map +1 -1
- package/dist/commands/help.js +2 -2
- package/dist/commands/help.js.map +1 -1
- package/dist/commands/import.js +3 -3
- package/dist/commands/import.js.map +1 -1
- package/dist/commands/init.d.ts +1 -1
- package/dist/commands/init.js +17 -17
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/iteration/split.d.ts.map +1 -1
- package/dist/commands/iteration/split.js +5 -9
- package/dist/commands/iteration/split.js.map +1 -1
- package/dist/commands/iteration-from-global.js +1 -1
- package/dist/commands/iteration-from-global.js.map +1 -1
- package/dist/commands/lifecycle.js +2 -2
- package/dist/commands/lifecycle.js.map +1 -1
- package/dist/commands/migrate.js +3 -3
- package/dist/commands/migrate.js.map +1 -1
- package/dist/commands/retro.js +3 -3
- package/dist/commands/retro.js.map +1 -1
- package/dist/commands/synthesize.d.ts +2 -2
- package/dist/commands/synthesize.js +11 -11
- package/dist/commands/synthesize.js.map +1 -1
- package/dist/commands/task/new.js +1 -1
- package/dist/commands/task/new.js.map +1 -1
- package/dist/commands/units.d.ts +10 -0
- package/dist/commands/units.d.ts.map +1 -0
- package/dist/commands/units.js +280 -0
- package/dist/commands/units.js.map +1 -0
- package/dist/commands/update.d.ts.map +1 -1
- package/dist/commands/update.js +14 -15
- package/dist/commands/update.js.map +1 -1
- package/dist/core/agent-adapter.js +1 -1
- package/dist/core/agent-adapter.js.map +1 -1
- package/dist/core/agents/index.js +1 -1
- package/dist/core/agents/index.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-engine.js +4 -4
- package/dist/core/analyze-engine.js.map +1 -1
- package/dist/core/ask-config.js +1 -1
- package/dist/core/ask-config.js.map +1 -1
- package/dist/core/code-scanner.js +1 -1
- package/dist/core/code-scanner.js.map +1 -1
- package/dist/core/git-integration.d.ts +1 -1
- package/dist/core/git-integration.js +3 -3
- package/dist/core/git-integration.js.map +1 -1
- package/dist/core/global-artifacts.js +1 -1
- package/dist/core/global-artifacts.js.map +1 -1
- package/dist/core/global-counters.js +2 -2
- package/dist/core/global-counters.js.map +1 -1
- package/dist/core/handoff-generator.d.ts +14 -0
- package/dist/core/handoff-generator.d.ts.map +1 -0
- package/dist/core/handoff-generator.js +218 -0
- package/dist/core/handoff-generator.js.map +1 -0
- package/dist/core/knowledge-graph.js +8 -8
- 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 +5 -6
- package/dist/core/prompt-builder.js.map +1 -1
- package/dist/core/rag-engine.js +3 -3
- package/dist/core/rag-engine.js.map +1 -1
- package/dist/core/reindex-engine.js +1 -1
- package/dist/core/reindex-engine.js.map +1 -1
- package/dist/core/requirement-clarifier.d.ts +1 -1
- package/dist/core/requirement-clarifier.js +3 -3
- package/dist/core/requirement-clarifier.js.map +1 -1
- package/dist/core/spec-paths.d.ts +4 -4
- package/dist/core/spec-paths.js +10 -10
- package/dist/core/spec-paths.js.map +1 -1
- package/dist/core/spec-skeleton.js +1 -1
- package/dist/core/spec-skeleton.js.map +1 -1
- package/dist/core/state.js +6 -6
- package/dist/core/state.js.map +1 -1
- package/dist/core/streaming-analyzer.js +1 -1
- package/dist/core/task-paths.d.ts +2 -2
- package/dist/core/task-paths.js +3 -3
- package/dist/core/task-paths.js.map +1 -1
- package/dist/core/unified-config.d.ts +2 -2
- package/dist/core/unified-config.d.ts.map +1 -1
- package/dist/core/unified-config.js +2 -2
- package/dist/core/unified-config.js.map +1 -1
- package/dist/core/verify-engine.js +5 -5
- package/dist/core/verify-engine.js.map +1 -1
- package/package.json +1 -1
package/dist/commands/analyze.js
CHANGED
|
@@ -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}
|
|
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}
|
|
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
|
-
//
|
|
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}
|
|
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}
|
|
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
|
-
//
|
|
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}
|
|
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}
|
|
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}
|
|
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
|
-
//
|
|
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}
|
|
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(` 📦
|
|
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(` 📦
|
|
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(` 📦
|
|
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
|
-
//
|
|
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
|
-
//
|
|
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
|
|
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
|
-
//
|
|
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) {
|