speccore 7.4.5 → 7.5.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.
@@ -1804,6 +1804,52 @@ async function injectGraphSummary(prompt) {
1804
1804
  return prompt;
1805
1805
  }
1806
1806
  }
1807
+ // ── v7.5.0+: 检测迭代级文档生成进度 ──
1808
+ // 检查 020-specs/overview/ 和 020-specs/{platform}/ 下哪些文档已存在
1809
+ async function detectIterationDocsStatus(iterDir) {
1810
+ const specsDir = (0, path_1.join)(iterDir, '020-specs');
1811
+ const overviewDir = (0, path_1.join)(specsDir, spec_paths_1.GLOBAL_SPECS_DIR);
1812
+ const PHASE1_DOCS = ['REQUIREMENT.md', 'ANALYSIS.md', 'TECH.md', 'DEPS.md', 'RISK.md', 'REVIEW.md', 'MONITOR.md', 'FUNCTION_MAP.md'];
1813
+ const PLATFORM_DOCS = ['TECH.md', 'TEST.md', 'UI_SPEC.md'];
1814
+ const existing = [];
1815
+ const missing = [];
1816
+ // Phase 1: 检查 overview/ 下的文档
1817
+ for (const doc of PHASE1_DOCS) {
1818
+ const fp = (0, path_1.join)(overviewDir, doc);
1819
+ if (await (0, fs_extra_1.pathExists)(fp)) {
1820
+ existing.push(`overview/${doc}`);
1821
+ }
1822
+ else {
1823
+ missing.push(`overview/${doc}`);
1824
+ }
1825
+ }
1826
+ const phase1Complete = missing.filter(m => m.startsWith('overview/')).length === 0;
1827
+ // Phase 2: 检查各端目录下的文档
1828
+ const platforms = await (0, spec_paths_1.parsePlatformList)();
1829
+ for (const platform of platforms) {
1830
+ const platformDir = (0, path_1.join)(specsDir, platform);
1831
+ if (await (0, fs_extra_1.pathExists)(platformDir)) {
1832
+ for (const doc of PLATFORM_DOCS) {
1833
+ const fp = (0, path_1.join)(platformDir, doc);
1834
+ if (await (0, fs_extra_1.pathExists)(fp)) {
1835
+ existing.push(`${platform}/${doc}`);
1836
+ }
1837
+ else {
1838
+ missing.push(`${platform}/${doc}`);
1839
+ }
1840
+ }
1841
+ }
1842
+ else {
1843
+ for (const doc of PLATFORM_DOCS) {
1844
+ missing.push(`${platform}/${doc}`);
1845
+ }
1846
+ }
1847
+ }
1848
+ const phase2Complete = missing.filter(m => !m.startsWith('overview/')).length === 0;
1849
+ // 下一个缺失的文档(Phase 1 优先)
1850
+ const nextDoc = missing.length > 0 ? missing[0] : null;
1851
+ return { existing, missing, nextDoc, phase1Complete, phase2Complete };
1852
+ }
1807
1853
  // ── v7.2.0+: 检测全局分析当前进度 ──
1808
1854
  // Layer 4 拆分为子层: 4a=产品文档, 4b=全局技术核心, 4c=全局技术扩展, 4d=各端技术
1809
1855
  async function detectGlobalLayerProgress() {
@@ -2668,82 +2714,176 @@ async function buildMultiDocPrompt(command, ctx, options) {
2668
2714
  }
2669
2715
  }
2670
2716
  else {
2671
- // 子层模式:每次只生成一个子层
2672
- prompt += `## 🌍 Layer 4: 全局汇总 — 子层 ${subLayerTarget}/4\n\n`;
2673
- prompt += `> ⚠️ **专注约束**: 你当前只执行 **子层 ${subLayerTarget}**,不要生成其他子层的文档。\n`;
2674
- prompt += `> 子层完成后执行: \`speccore analyze --scope global --layer 4\` 进入下一子层。\n\n`;
2717
+ // v7.5.0+: 子层内逐文档生成 — 检测当前子层中哪些文档已存在,每次只生成下一个缺失的
2718
+ const globalDir = (0, path_1.join)(process.cwd(), '.speccore', 'GLOBAL');
2719
+ const overviewDir = (0, path_1.join)(globalDir, 'overview');
2720
+ const requirementsDir = (0, path_1.join)(globalDir, 'requirements');
2721
+ const platformsDir = (0, path_1.join)(globalDir, 'platforms');
2722
+ // 定义每个子层的预期文档清单(按优先级排序)
2723
+ const SUB_LAYER_DOCS = {
2724
+ '4a': ['requirements/REQUIREMENT.md'],
2725
+ '4b': ['overview/FUNCTION_MAP.md', 'overview/ARCHITECTURE.md', 'overview/API_CONTRACT.yaml', 'overview/INTERACTION_MAP.md'],
2726
+ '4c': ['overview/SECURITY_AUDIT.md', 'overview/PERFORMANCE_BASELINE.md', 'overview/DATA_FLOW.md', 'overview/DEPLOYMENT.md', 'overview/CONSISTENCY_CHECK.md'],
2727
+ '4d': [],
2728
+ };
2729
+ // 4a: 追加各前端端的需求文档
2730
+ if (subLayerTarget === '4a') {
2731
+ const allPlatforms = await (0, spec_paths_1.parsePlatformList)();
2732
+ const frontendPlatforms = allPlatforms.filter(p => {
2733
+ const pt = (async () => { try {
2734
+ const m = await (0, spec_paths_1.parsePlatformTypes)();
2735
+ return m.get(p);
2736
+ }
2737
+ catch {
2738
+ return '';
2739
+ } })();
2740
+ return true; // 保守策略:所有非后端端都可能需要 REQUIREMENT.md
2741
+ });
2742
+ for (const p of allPlatforms) {
2743
+ SUB_LAYER_DOCS['4a'].push(`requirements/${p}/REQUIREMENT.md`);
2744
+ }
2745
+ }
2746
+ // 4d: 动态构建各端文档清单
2747
+ if (subLayerTarget === '4d') {
2748
+ try {
2749
+ const entries = await (0, fs_extra_2.readdir)(platformsDir, { withFileTypes: true });
2750
+ const platformNames = entries.filter(e => e.isDirectory() && e.name !== '_shared').map(e => e.name);
2751
+ for (const p of platformNames) {
2752
+ const isBackend = /service|server|api|backend/i.test(p);
2753
+ if (isBackend) {
2754
+ SUB_LAYER_DOCS['4d'].push(`platforms/${p}/API_INVENTORY.md`);
2755
+ SUB_LAYER_DOCS['4d'].push(`platforms/${p}/DATA_MODEL.md`);
2756
+ SUB_LAYER_DOCS['4d'].push(`platforms/${p}/BUSINESS_RULES.md`);
2757
+ }
2758
+ else {
2759
+ SUB_LAYER_DOCS['4d'].push(`platforms/${p}/UI_FLOW.md`);
2760
+ SUB_LAYER_DOCS['4d'].push(`platforms/${p}/API_CALL_MAP.md`);
2761
+ SUB_LAYER_DOCS['4d'].push(`platforms/${p}/STATE_MANAGEMENT.md`);
2762
+ }
2763
+ }
2764
+ }
2765
+ catch { }
2766
+ }
2767
+ // 检测当前子层中哪些文档已存在
2768
+ const expectedDocs = SUB_LAYER_DOCS[subLayerTarget] || [];
2769
+ const existingDocs = [];
2770
+ const missingDocs = [];
2771
+ for (const doc of expectedDocs) {
2772
+ const fullPath = (0, path_1.join)(process.cwd(), '.speccore', 'GLOBAL', doc);
2773
+ if (await (0, fs_extra_1.pathExists)(fullPath)) {
2774
+ existingDocs.push(doc);
2775
+ }
2776
+ else {
2777
+ missingDocs.push(doc);
2778
+ }
2779
+ }
2780
+ const nextDoc = missingDocs.length > 0 ? missingDocs[0] : null;
2781
+ prompt += `## 🌍 Layer 4: 全局汇总 — 子层 ${subLayerTarget}/4(v7.5.0+ 逐文档模式)\n\n`;
2782
+ prompt += `> ⚠️ **专注约束**: 你当前只执行 **子层 ${subLayerTarget}** 中的 **下一个缺失文档**。\n`;
2783
+ prompt += `> 已存在: ${existingDocs.length}/${expectedDocs.length} 份文档\n`;
2784
+ if (missingDocs.length > 0) {
2785
+ prompt += `> 缺失: ${missingDocs.slice(0, 5).join('、')}${missingDocs.length > 5 ? '...' : ''}\n`;
2786
+ }
2787
+ prompt += `\n`;
2675
2788
  prompt += `**强制输入**: \n`;
2676
2789
  prompt += `- Read Layer 1 的所有 _INDEX.md\n`;
2677
2790
  prompt += `- Read Layer 2 的 _ASSOCIATION.md + _MODULES.md\n`;
2678
2791
  prompt += `- Read Layer 3 的功能模块深入文档\n\n`;
2679
- if (subLayerTarget === '4a') {
2680
- prompt += `**子层 4a: 产品视角文档(2-3 份)**\n`;
2681
- prompt += `> ⚠️ **REQUIREMENT.md 是必须生成的核心文档**,不可跳过!\n\n`;
2682
- prompt += `1. \`requirements/REQUIREMENT.md\` — 全局需求总纲(**必须生成**)\n`;
2683
- prompt += ` - 产品愿景、目标用户画像、核心场景地图\n`;
2684
- prompt += ` - 按业务场景组织:用户故事 操作流程 业务规则 → 边界条件 → 验收标准\n`;
2685
- prompt += ` - 功能优先级矩阵(P0/P1/P2)\n`;
2686
- prompt += ` - 必须从 Layer 3 的功能模块分析中提取真实内容,不要臆造\n`;
2687
- prompt += `2. 各前端端 \`requirements/{端}/REQUIREMENT.md\` 只生成已有前端端的需求\n`;
2688
- prompt += ` - 信息架构、用户旅程、页面清单、交互设计\n`;
2689
- prompt += ` - 从 Layer 1 的前端 _INDEX.md 提取页面/路由信息\n`;
2690
- prompt += ` - Layer 3 的模块分析提取交互流程\n`;
2691
- }
2692
- else if (subLayerTarget === '4b') {
2693
- prompt += `**子层 4b: 全局技术核心文档(3-4 份)**\n`;
2694
- prompt += `1. \`overview/FUNCTION_MAP.md\` — 功能单元 × 端映射表\n`;
2695
- prompt += ` - 从 Layer 2 的 _MODULES.md 提取功能模块\n`;
2696
- prompt += ` - 每个功能单元标注:涉及端、核心页面、核心接口、状态枚举\n`;
2697
- prompt += ` - ⚠️ **必须使用 Markdown 表格格式**,表头:| # | 功能单元 | 涉及端 | 全局对比 | 共享能力 | 依赖任务 | 说明 |\n`;
2698
- prompt += ` - **禁止使用树形格式**(├── ...),split 无法解析树形格式\n`;
2699
- prompt += ` - 「涉及端」必须使用 CONSTITUTION.md 标准端名\n`;
2700
- prompt += `2. \`overview/ARCHITECTURE.md\` — 全局架构\n`;
2701
- prompt += ` - 服务拓扑(从 Layer 1 的后端 _INDEX.md 提取服务名和依赖)\n`;
2702
- prompt += ` - 数据流(从 Layer 3 的模块分析提取)\n`;
2703
- prompt += ` - 必须包含 Mermaid architecture diagram\n`;
2704
- prompt += `3. \`overview/API_CONTRACT.yaml\` — 全局接口契约\n`;
2705
- prompt += ` - 汇总所有后端端的 API_INVENTORY(从 Layer 1 提取)\n`;
2706
- prompt += ` - 标注 rate limit、幂等性、版本策略\n`;
2707
- prompt += `4. \`overview/INTERACTION_MAP.md\` — 跨端交互时序图\n`;
2708
- prompt += ` - Layer 3 的模块时序图汇总\n`;
2709
- prompt += ` - 必须包含 Mermaid sequenceDiagram\n`;
2710
- }
2711
- else if (subLayerTarget === '4c') {
2712
- prompt += `**子层 4c: 全局技术扩展文档(4-5 份)**\n`;
2713
- prompt += `1. \`overview/SECURITY_AUDIT.md\` 安全审计\n`;
2714
- prompt += `2. \`overview/PERFORMANCE_BASELINE.md\` — 性能基线\n`;
2715
- prompt += `3. \`overview/DATA_FLOW.md\` — 数据流与隐私\n`;
2716
- prompt += `4. \`overview/DEPLOYMENT.md\` — 部署运维\n`;
2717
- prompt += `5. \`overview/CONSISTENCY_CHECK.md\` 一致性校验\n`;
2718
- prompt += ` - 从 Layer 2 的关联分析提取不一致项\n`;
2792
+ if (nextDoc) {
2793
+ prompt += `## 🎯 本次只生成: \`${nextDoc}\`\n\n`;
2794
+ // 根据文档路径生成专属指令
2795
+ const docName = nextDoc.split('/').pop();
2796
+ const docDir = nextDoc.includes('/') ? nextDoc.split('/')[0] : '';
2797
+ if (docName === 'REQUIREMENT.md' && docDir === 'requirements') {
2798
+ prompt += `**全局需求总纲(产品视角)**\n`;
2799
+ prompt += `- 产品愿景、目标用户画像、核心场景地图\n`;
2800
+ prompt += `- 按业务场景组织:用户故事 操作流程 → 业务规则 → 边界条件 → 验收标准\n`;
2801
+ prompt += `- 功能优先级矩阵(P0/P1/P2)\n`;
2802
+ prompt += `- 功能模块清单表(含涉及端列)\n`;
2803
+ prompt += `- ⚠️ **以产品/用户视角撰写**,不写技术实现细节\n`;
2804
+ prompt += `- ⚠️ **必须从 Layer 3 的功能模块分析中提取真实内容,不要臆造**\n`;
2805
+ }
2806
+ else if (docName === 'REQUIREMENT.md') {
2807
+ prompt += `**${docDir} 端需求文档**\n`;
2808
+ prompt += `- 信息架构、用户旅程、页面清单、交互设计\n`;
2809
+ prompt += `- 从 Layer 1 的前端 _INDEX.md 提取页面/路由信息\n`;
2810
+ }
2811
+ else if (docName === 'FUNCTION_MAP.md') {
2812
+ prompt += `**功能单元 × 端映射表**\n`;
2813
+ prompt += `- 从 Layer 2 的 _MODULES.md 提取功能模块\n`;
2814
+ prompt += `- ⚠️ **必须使用 Markdown 表格格式**,表头:| # | 功能单元 | 涉及端 | 全局对比 | 共享能力 | 依赖任务 | 说明 |\n`;
2815
+ prompt += `- **禁止使用树形格式**(├── ...),split 无法解析\n`;
2816
+ prompt += `- 「涉及端」必须使用 CONSTITUTION.md 标准端名\n`;
2817
+ }
2818
+ else if (docName === 'ARCHITECTURE.md') {
2819
+ prompt += `**全局架构文档**\n`;
2820
+ prompt += `- 服务拓扑、数据流、技术栈选型\n`;
2821
+ prompt += `- 必须包含 Mermaid architecture diagram\n`;
2822
+ }
2823
+ else if (docName === 'API_CONTRACT.yaml') {
2824
+ prompt += `**全局接口契约**\n`;
2825
+ prompt += `- 汇总所有后端端的 API 清单\n`;
2826
+ prompt += `- 标注 rate limit、幂等性、版本策略\n`;
2827
+ }
2828
+ else if (docName === 'INTERACTION_MAP.md') {
2829
+ prompt += `**跨端交互时序图**\n`;
2830
+ prompt += `- 每个核心场景一个 Mermaid sequenceDiagram\n`;
2831
+ prompt += `- 标注接口路径和契约引用\n`;
2832
+ }
2833
+ else if (['SECURITY_AUDIT.md', 'PERFORMANCE_BASELINE.md', 'DATA_FLOW.md', 'DEPLOYMENT.md', 'CONSISTENCY_CHECK.md'].includes(docName)) {
2834
+ prompt += `**${docName.replace('.md', '')}**\n`;
2835
+ prompt += `- 从 Layer 1-3 的产出中提取相关内容\n`;
2836
+ prompt += `- 必须包含真实数据,禁止占位符\n`;
2837
+ }
2838
+ else if (['API_INVENTORY.md', 'DATA_MODEL.md', 'BUSINESS_RULES.md', 'UI_FLOW.md', 'API_CALL_MAP.md', 'STATE_MANAGEMENT.md'].includes(docName)) {
2839
+ prompt += `**${docDir} 端 ${docName.replace('.md', '')}**\n`;
2840
+ prompt += `- 从 Layer 1 的 _INDEX.md 和 Layer 3 的模块分析提取\n`;
2841
+ prompt += `- 必须包含真实数据,禁止占位符\n`;
2842
+ }
2843
+ // 自动链式推进
2844
+ if (missingDocs.length > 1) {
2845
+ prompt += `\n## 🔗 自动链式推进\n\n`;
2846
+ prompt += `> 当前文档写入完成后,**立即输出以下标记**推进下一个文档:\n\n`;
2847
+ prompt += `[SPECCORE_EXEC: speccore analyze --scope global --layer 4${options?.withCode ? ' --with-code' : ''}]\n\n`;
2848
+ prompt += `> 💡 CLI 会自动检测下一个缺失文档并聚焦生成。重复直到子层 ${subLayerTarget} 完成,然后进入下一子层。\n`;
2849
+ }
2850
+ else {
2851
+ prompt += `\n> 🎉 这是子层 ${subLayerTarget} 的最后一份文档!写入后将自动进入下一子层。\n`;
2852
+ }
2719
2853
  }
2720
- else if (subLayerTarget === '4d') {
2721
- prompt += `**子层 4d: 各端技术文档**\n`;
2722
- prompt += `后端端(每端 9 项,但本次只生成核心 3 项,其余后续补充):\n`;
2723
- prompt += `1. \`API_INVENTORY.md\` — 从 Layer 1 的 _INDEX.md 提取完整接口清单\n`;
2724
- prompt += `2. \`DATA_MODEL.md\` — 从 Layer 1 的 Entity 目录 + Layer 3 的模块分析提取\n`;
2725
- prompt += `3. \`BUSINESS_RULES.md\` — 从 Layer 3 的模块分析提取业务规则\n`;
2726
- prompt += `前端端(每端 9 项,但本次只生成核心 3 项):\n`;
2727
- prompt += `1. \`UI_FLOW.md\` — 从 Layer 1 的路由 + Layer 3 的模块分析提取\n`;
2728
- prompt += `2. \`API_CALL_MAP.md\` — 从 Layer 1 的 API 调用提取\n`;
2729
- prompt += `3. \`STATE_MANAGEMENT.md\` — 从 Layer 1 的 store 目录提取\n`;
2854
+ else {
2855
+ prompt += `> 子层 ${subLayerTarget} 所有文档已存在,请执行下一子层。\n`;
2856
+ prompt += `\`speccore analyze --scope global --layer 4\`\n`;
2730
2857
  }
2731
2858
  prompt += `\n**质量要求**: \n`;
2732
- prompt += `- 禁止写"待导入"、"待补充"等占位符\n`;
2859
+ prompt += `- 禁止写“待导入”、“待补充”等占位符\n`;
2733
2860
  prompt += `- 每个表格必须有真实数据(从 Layer 1-3 提取)\n`;
2734
- prompt += `- 如果信息不足,明确标注"信息不足: 需要读取 xxx"\n`;
2861
+ prompt += `- 如果信息不足,明确标注“信息不足: 需要读取 xxx”\n`;
2735
2862
  }
2736
2863
  }
2737
- // v7.4.5+: 量化深度标准 每层最低质量要求
2738
- prompt += `\n## 📏 深度标准(v7.4.5+ 强制)\n\n`;
2739
- prompt += `> ⚠️ 每个 Layer 的产出必须满足以下最低量化要求,不达标视为未完成。\n\n`;
2740
- prompt += `| Layer | 最低深度要求 |\n`;
2741
- prompt += `| :--- | :--- |\n`;
2742
- prompt += `| Layer 1 | 每个维度至少 3 个具体条目(接口名/路径/实体名),每个条目标注源文件路径 |\n`;
2743
- prompt += `| Layer 2 | 关联矩阵必须覆盖所有前后端组合,接口缺口/未使用接口至少列出已知项,Mermaid 图节点数 ≥ 5 |\n`;
2744
- prompt += `| Layer 3 | 每个功能模块至少 Read 5 个源文件,必须包含代码片段引用(至少 2 段),状态图/时序图至少 1 个 |\n`;
2745
- prompt += `| Layer 4 | 每份文档至少 3 个章节有实质内容,每个表格至少 3 行真实数据,Mermaid 图至少 1 个 |\n\n`;
2746
- prompt += `**禁止行为**: 写“待补充”、“TODO”、“示例”等占位内容。信息不足时标注“信息不足: 需要读取 xxx 文件”并说明原因。\n\n`;
2864
+ // v7.4.5+: 用户模板接入 + 深度标准(引用模板而非笼统数字)
2865
+ const globalUserTemplates = await loadUserTemplates('global');
2866
+ if (globalUserTemplates.size > 0) {
2867
+ prompt += `\n## 📄 用户自定义模板(v7.4.5+ 优先使用)\n\n`;
2868
+ prompt += `> 检测到 \`.speccore/templates/global/\` 下有用户自定义模板,**必须按这些模板的章节结构和风格生成文档**。\n\n`;
2869
+ for (const [docName, docContent] of globalUserTemplates) {
2870
+ prompt += `### ${docName}\n\`\`\`markdown\n${docContent.slice(0, 1500)}\n\`\`\`\n\n`;
2871
+ }
2872
+ prompt += `> 💡 以上模板定义了文档的章节结构和写作风格,请严格遵循。模板未覆盖的文档按下方默认格式生成。\n\n`;
2873
+ }
2874
+ prompt += `\n## 📏 深度标准\n\n`;
2875
+ prompt += `> ⚠️ 每份文档的格式和章节结构由**模板**定义(用户模板优先,否则按上方各 Layer 的文档格式说明)。\n\n`;
2876
+ prompt += `**通用质量要求**:\n`;
2877
+ prompt += `- 禁止写“待补充”、“TODO”、“示例”等占位内容\n`;
2878
+ prompt += `- 每个表格必须有真实数据(从代码/前序 Layer 提取)\n`;
2879
+ prompt += `- 每个结论必须引用证据(文件名/类名/方法名)\n`;
2880
+ prompt += `- 信息不足时标注「信息不足: 需要读取 xxx 文件」并说明原因\n`;
2881
+ prompt += `- 必须包含 Mermaid 图表(如适用)\n\n`;
2882
+ prompt += `**Layer 专项要求**:\n`;
2883
+ prompt += `- Layer 1: 每个扫描维度的每个条目必须标注源文件路径\n`;
2884
+ prompt += `- Layer 2: 关联矩阵必须覆盖所有前后端组合,不能只列匹配成功的\n`;
2885
+ prompt += `- Layer 3: 每个功能模块必须引用实际代码(文件路径 + 关键代码片段),不能只写名称\n`;
2886
+ prompt += `- Layer 4: 每份文档必须填满模板定义的所有章节,空章节标注原因\n\n`;
2747
2887
  prompt += `\n## 📝 写入方式\n`;
2748
2888
  prompt += `使用 \`speccore analyze --apply '{"文件路径":"内容"}' --scope global\` 写入。\n`;
2749
2889
  prompt += `- platforms/ 和 requirements/ 下的文件按原路径写(如 \`platforms/backend/_INDEX.md\`)\n`;
@@ -3075,6 +3215,34 @@ sequenceDiagram
3075
3215
  else if (ctx.phase === '2') {
3076
3216
  taskDocs = taskDocs.filter(([n]) => PLATFORM_DOCS.includes(n));
3077
3217
  }
3218
+ // v7.5.0+: 逐文档生成模式 — 检测已有文档,每次只生成下一个缺失的
3219
+ // 避免一次性生成 9+ 文档导致 AI 跳过或写错目录
3220
+ let perDocStatus = null;
3221
+ if (!isGlobal && !isTask && !ctx.phase && ctx.iteration && ctx.iteration !== 'GLOBAL') {
3222
+ try {
3223
+ const iterDir = await (0, context_1.getIterationDir)(ctx.iteration);
3224
+ if (iterDir) {
3225
+ perDocStatus = await detectIterationDocsStatus(iterDir);
3226
+ if (perDocStatus.missing.length > 0 && perDocStatus.nextDoc) {
3227
+ const nextDocName = perDocStatus.nextDoc.split('/').pop();
3228
+ const nextDocPlatform = perDocStatus.nextDoc.includes('/') ? perDocStatus.nextDoc.split('/')[0] : null;
3229
+ // 过滤 taskDocs 只保留下一个缺失的文档
3230
+ if (nextDocPlatform && nextDocPlatform !== spec_paths_1.GLOBAL_SPECS_DIR) {
3231
+ // Phase 2 文档(端专属)
3232
+ taskDocs = taskDocs.filter(([n]) => n === nextDocName);
3233
+ ctx.platform = nextDocPlatform;
3234
+ }
3235
+ else {
3236
+ // Phase 1 文档(overview)
3237
+ taskDocs = taskDocs.filter(([n]) => n === nextDocName);
3238
+ }
3239
+ }
3240
+ }
3241
+ }
3242
+ catch (e) {
3243
+ logger_1.logger.debug(`逐文档检测失败(非关键): ${e.message}`);
3244
+ }
3245
+ }
3078
3246
  // ── 任务级文档覆盖:00-specs/ 使用任务级文档集(v6.44.0+) ──
3079
3247
  if (isTask && !ctx.phase) {
3080
3248
  const TASK_DOCS = {
@@ -3603,6 +3771,28 @@ sequenceDiagram
3603
3771
  prompt += `请在生成综合文档后,**直接继续**生成各端专属文档(Phase 2)。\n`;
3604
3772
  prompt += `执行命令:\`speccore analyze --prompt -I ${iter} --phase 2\`\n\n`;
3605
3773
  }
3774
+ // v7.5.0+: 逐文档自动链式推进
3775
+ if (perDocStatus && perDocStatus.missing.length > 0) {
3776
+ const remainingAfterThis = perDocStatus.missing.length - 1;
3777
+ prompt += `\n## 🔗 逐文档自动链式推进(v7.5.0+)\n\n`;
3778
+ prompt += `> 当前为**单文档模式**:本次只生成 1 个文档,写入后立即推进下一个。\n`;
3779
+ prompt += `> 剩余缺失文档: ${perDocStatus.missing.length} 个(${perDocStatus.missing.slice(0, 5).join('、')}${perDocStatus.missing.length > 5 ? '...' : ''})\n\n`;
3780
+ if (remainingAfterThis > 0) {
3781
+ prompt += `**当前文档写入完成后,立即输出以下标记推进下一个文档**:\n\n`;
3782
+ prompt += `[SPECCORE_EXEC: speccore analyze --prompt -I ${iter}${options?.auto ? ' --auto' : ''}${options?.withCode ? ' --with-code' : ''}]\n\n`;
3783
+ prompt += `> 💡 CLI 会自动检测下一个缺失的文档并生成对应的 prompt。重复执行直到所有文档生成完毕。\n`;
3784
+ }
3785
+ else {
3786
+ prompt += `> 🎉 这是最后一个缺失文档!写入后所有迭代级分析文档将完整。\n`;
3787
+ const platforms = await (0, spec_paths_1.parsePlatformList)();
3788
+ if (platforms.length >= 2 && perDocStatus.phase2Complete === false) {
3789
+ prompt += `> 下一步: 生成各端专属文档 → \`speccore analyze --prompt -I ${iter} --phase 2\`\n`;
3790
+ }
3791
+ else {
3792
+ prompt += `> 下一步: 运行 \`speccore split -I ${iter}\` 进行任务拆分\n`;
3793
+ }
3794
+ }
3795
+ }
3606
3796
  // ── v6.52.0+: 图谱 RAG 上下文注入(analyze 阶段也检索项目关联内容)──
3607
3797
  if (!isTask && ctx.phase !== '2') {
3608
3798
  try {