soloforge 1.3.1 → 1.3.3

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 (158) hide show
  1. package/README.md +11 -3
  2. package/dist/adapters/claude_code/claude_md.d.ts.map +1 -1
  3. package/dist/adapters/claude_code/claude_md.js +4 -0
  4. package/dist/adapters/claude_code/claude_md.js.map +1 -1
  5. package/dist/adapters/claude_code/tools.d.ts +10 -10
  6. package/dist/adapters/claude_code/tools.d.ts.map +1 -1
  7. package/dist/adapters/claude_code/tools.js +603 -18
  8. package/dist/adapters/claude_code/tools.js.map +1 -1
  9. package/dist/adapters/shared/workflow_template.d.ts +26 -0
  10. package/dist/adapters/shared/workflow_template.d.ts.map +1 -1
  11. package/dist/adapters/shared/workflow_template.js +140 -46
  12. package/dist/adapters/shared/workflow_template.js.map +1 -1
  13. package/dist/bin/soloforge.d.ts.map +1 -1
  14. package/dist/bin/soloforge.js +316 -54
  15. package/dist/bin/soloforge.js.map +1 -1
  16. package/dist/engine/asset_manifest.d.ts +7 -1
  17. package/dist/engine/asset_manifest.d.ts.map +1 -1
  18. package/dist/engine/asset_manifest.js +41 -18
  19. package/dist/engine/asset_manifest.js.map +1 -1
  20. package/dist/engine/backend_implementation_contract.d.ts +51 -0
  21. package/dist/engine/backend_implementation_contract.d.ts.map +1 -0
  22. package/dist/engine/backend_implementation_contract.js +142 -0
  23. package/dist/engine/backend_implementation_contract.js.map +1 -0
  24. package/dist/engine/consumable_asset_registry.d.ts.map +1 -1
  25. package/dist/engine/consumable_asset_registry.js +159 -0
  26. package/dist/engine/consumable_asset_registry.js.map +1 -1
  27. package/dist/engine/consumption_trace_store.d.ts +8 -8
  28. package/dist/engine/consumption_trace_store.d.ts.map +1 -1
  29. package/dist/engine/consumption_trace_store.js +11 -7
  30. package/dist/engine/consumption_trace_store.js.map +1 -1
  31. package/dist/engine/decision_workshop.d.ts +160 -0
  32. package/dist/engine/decision_workshop.d.ts.map +1 -0
  33. package/dist/engine/decision_workshop.js +279 -0
  34. package/dist/engine/decision_workshop.js.map +1 -0
  35. package/dist/engine/dual_layer_mechanism_registry.d.ts.map +1 -1
  36. package/dist/engine/dual_layer_mechanism_registry.js +300 -2
  37. package/dist/engine/dual_layer_mechanism_registry.js.map +1 -1
  38. package/dist/engine/explicit_asset_registry.d.ts +30 -0
  39. package/dist/engine/explicit_asset_registry.d.ts.map +1 -0
  40. package/dist/engine/explicit_asset_registry.js +3712 -0
  41. package/dist/engine/explicit_asset_registry.js.map +1 -0
  42. package/dist/engine/implementation_roadmap_registry.d.ts +2 -2
  43. package/dist/engine/implementation_roadmap_registry.d.ts.map +1 -1
  44. package/dist/engine/implementation_roadmap_registry.js +110 -16
  45. package/dist/engine/implementation_roadmap_registry.js.map +1 -1
  46. package/dist/engine/intent_expander.d.ts.map +1 -1
  47. package/dist/engine/intent_expander.js +46 -2
  48. package/dist/engine/intent_expander.js.map +1 -1
  49. package/dist/engine/intent_router.d.ts +1 -1
  50. package/dist/engine/intent_router.d.ts.map +1 -1
  51. package/dist/engine/intent_router.js +2 -1
  52. package/dist/engine/intent_router.js.map +1 -1
  53. package/dist/engine/knowledge_injection_boundary.d.ts +3 -0
  54. package/dist/engine/knowledge_injection_boundary.d.ts.map +1 -1
  55. package/dist/engine/knowledge_injection_boundary.js +48 -5
  56. package/dist/engine/knowledge_injection_boundary.js.map +1 -1
  57. package/dist/engine/mechanism_contract_registry.d.ts +1 -1
  58. package/dist/engine/mechanism_contract_registry.d.ts.map +1 -1
  59. package/dist/engine/mechanism_contract_registry.js +142 -2
  60. package/dist/engine/mechanism_contract_registry.js.map +1 -1
  61. package/dist/engine/next_action_planner.d.ts +19 -0
  62. package/dist/engine/next_action_planner.d.ts.map +1 -0
  63. package/dist/engine/next_action_planner.js +453 -0
  64. package/dist/engine/next_action_planner.js.map +1 -0
  65. package/dist/engine/observed_consumption.d.ts +54 -0
  66. package/dist/engine/observed_consumption.d.ts.map +1 -0
  67. package/dist/engine/observed_consumption.js +377 -0
  68. package/dist/engine/observed_consumption.js.map +1 -0
  69. package/dist/engine/ood_solid_contract.d.ts +51 -0
  70. package/dist/engine/ood_solid_contract.d.ts.map +1 -0
  71. package/dist/engine/ood_solid_contract.js +115 -0
  72. package/dist/engine/ood_solid_contract.js.map +1 -0
  73. package/dist/engine/project_stage_detector.d.ts +17 -0
  74. package/dist/engine/project_stage_detector.d.ts.map +1 -0
  75. package/dist/engine/project_stage_detector.js +185 -0
  76. package/dist/engine/project_stage_detector.js.map +1 -0
  77. package/dist/engine/release_issue_scenario_registry.d.ts +64 -0
  78. package/dist/engine/release_issue_scenario_registry.d.ts.map +1 -0
  79. package/dist/engine/release_issue_scenario_registry.js +1362 -0
  80. package/dist/engine/release_issue_scenario_registry.js.map +1 -0
  81. package/dist/engine/release_readiness_gate.d.ts +1 -1
  82. package/dist/engine/release_readiness_gate.d.ts.map +1 -1
  83. package/dist/engine/release_readiness_gate.js +721 -47
  84. package/dist/engine/release_readiness_gate.js.map +1 -1
  85. package/dist/engine/release_tool_harness.d.ts +71 -0
  86. package/dist/engine/release_tool_harness.d.ts.map +1 -0
  87. package/dist/engine/release_tool_harness.js +161 -0
  88. package/dist/engine/release_tool_harness.js.map +1 -0
  89. package/dist/engine/scaffolder.d.ts.map +1 -1
  90. package/dist/engine/scaffolder.js +144 -7
  91. package/dist/engine/scaffolder.js.map +1 -1
  92. package/dist/engine/stale_current_task_detector.d.ts +30 -0
  93. package/dist/engine/stale_current_task_detector.d.ts.map +1 -0
  94. package/dist/engine/stale_current_task_detector.js +168 -0
  95. package/dist/engine/stale_current_task_detector.js.map +1 -0
  96. package/dist/engine/standard_asset_contract.d.ts +75 -0
  97. package/dist/engine/standard_asset_contract.d.ts.map +1 -0
  98. package/dist/engine/standard_asset_contract.js +388 -0
  99. package/dist/engine/standard_asset_contract.js.map +1 -0
  100. package/dist/engine/standard_asset_coverage.d.ts +45 -0
  101. package/dist/engine/standard_asset_coverage.d.ts.map +1 -0
  102. package/dist/engine/standard_asset_coverage.js +220 -0
  103. package/dist/engine/standard_asset_coverage.js.map +1 -0
  104. package/dist/engine/task_stage_detector.d.ts +19 -0
  105. package/dist/engine/task_stage_detector.d.ts.map +1 -0
  106. package/dist/engine/task_stage_detector.js +201 -0
  107. package/dist/engine/task_stage_detector.js.map +1 -0
  108. package/dist/engine/template_asset_contract_registry.d.ts +162 -0
  109. package/dist/engine/template_asset_contract_registry.d.ts.map +1 -0
  110. package/dist/engine/template_asset_contract_registry.js +598 -0
  111. package/dist/engine/template_asset_contract_registry.js.map +1 -0
  112. package/dist/engine/template_asset_visibility.d.ts +109 -0
  113. package/dist/engine/template_asset_visibility.d.ts.map +1 -0
  114. package/dist/engine/template_asset_visibility.js +321 -0
  115. package/dist/engine/template_asset_visibility.js.map +1 -0
  116. package/dist/engine/template_init_sync.d.ts +68 -0
  117. package/dist/engine/template_init_sync.d.ts.map +1 -0
  118. package/dist/engine/template_init_sync.js +218 -0
  119. package/dist/engine/template_init_sync.js.map +1 -0
  120. package/dist/engine/template_manifest_io.d.ts +10 -0
  121. package/dist/engine/template_manifest_io.d.ts.map +1 -1
  122. package/dist/engine/template_manifest_io.js +63 -30
  123. package/dist/engine/template_manifest_io.js.map +1 -1
  124. package/dist/engine/template_mechanism_auditor.d.ts +3 -1
  125. package/dist/engine/template_mechanism_auditor.d.ts.map +1 -1
  126. package/dist/engine/template_mechanism_auditor.js +27 -24
  127. package/dist/engine/template_mechanism_auditor.js.map +1 -1
  128. package/dist/engine/tool_invocation_contract_registry.d.ts.map +1 -1
  129. package/dist/engine/tool_invocation_contract_registry.js +21 -1
  130. package/dist/engine/tool_invocation_contract_registry.js.map +1 -1
  131. package/dist/engine/workflow_navigation_contract.d.ts +115 -0
  132. package/dist/engine/workflow_navigation_contract.d.ts.map +1 -0
  133. package/dist/engine/workflow_navigation_contract.js +39 -0
  134. package/dist/engine/workflow_navigation_contract.js.map +1 -0
  135. package/dist/knowledge/index_manager.d.ts +20 -0
  136. package/dist/knowledge/index_manager.d.ts.map +1 -1
  137. package/dist/knowledge/index_manager.js +234 -3
  138. package/dist/knowledge/index_manager.js.map +1 -1
  139. package/dist/types.d.ts +44 -1
  140. package/dist/types.d.ts.map +1 -1
  141. package/package.json +2 -2
  142. package/templates/knowledge/acceptance_templates/OOD/350/256/276/350/256/241/346/221/230/350/246/201/346/250/241/347/211/210.md +60 -0
  143. package/templates/knowledge/acceptance_templates//345/220/216/347/253/257/345/256/236/347/216/260/351/252/214/346/224/266/346/270/205/345/215/225.md +46 -0
  144. package/templates/knowledge/procedures/OOD/350/256/276/350/256/241/345/267/245/344/275/234/346/265/201.md +50 -0
  145. package/templates/knowledge/procedures//345/205/250/347/224/237/345/221/275/345/221/250/346/234/237/345/267/245/344/275/234/346/265/201/345/257/274/350/210/252.md +100 -0
  146. package/templates/knowledge/procedures//345/220/216/347/253/257/346/216/245/345/217/243/345/256/236/347/216/260/345/267/245/344/275/234/346/265/201.md +50 -0
  147. package/templates/knowledge/review_rules/SOLID/344/273/243/347/240/201/345/256/241/346/237/245/350/247/204/345/210/231.md +40 -0
  148. package/templates/knowledge/review_rules//345/220/216/347/253/257/345/256/236/347/216/260/345/267/245/347/250/213/345/256/241/346/237/245/350/247/204/345/210/231.md +38 -0
  149. package/templates/knowledge/rules/OOD/344/270/216SOLID/350/256/276/350/256/241/350/247/204/345/210/231.md +62 -0
  150. package/templates/knowledge/rules//345/220/216/347/253/257/345/256/236/347/216/260/345/267/245/347/250/213/345/245/221/347/272/246/350/247/204/345/210/231.md +55 -0
  151. package/templates/knowledge/rules//345/267/245/344/275/234/346/265/201/345/257/274/350/210/252/345/245/221/347/272/246/350/247/204/345/210/231.md +113 -0
  152. package/templates/knowledge/rules//346/240/207/345/207/206/350/265/204/344/272/247/350/246/206/347/233/226/350/247/204/345/210/231.md +72 -0
  153. package/templates/knowledge/rules//346/250/241/346/235/277/350/265/204/344/272/247/345/217/257/350/247/201/346/200/247/350/247/204/345/210/231.md +71 -0
  154. package/templates/knowledge/rules//347/224/250/346/210/267/345/217/215/351/246/210/345/245/221/347/272/246/350/247/204/345/210/231.md +62 -1
  155. package/templates/knowledge/rules//351/200/232/347/224/250/345/206/263/347/255/226/347/240/224/350/256/250/350/247/204/345/210/231.md +77 -0
  156. package/templates/knowledge/rules//351/252/214/346/224/266/346/250/241/346/235/277/350/276/223/345/207/272/345/245/221/347/272/246/350/247/204/345/210/231.md +96 -0
  157. package/templates/patterns/SOLID/350/256/276/350/256/241/350/247/204/350/214/203.md +39 -0
  158. package/templates/patterns//345/220/216/347/253/257/345/256/236/347/216/260/345/267/245/347/250/213/350/247/204/350/214/203.md +39 -0
@@ -81,6 +81,9 @@ async function main() {
81
81
  case "validate-release":
82
82
  await cmdValidateReleaseGate();
83
83
  break;
84
+ case "audit-template-visibility":
85
+ await cmdAuditTemplateVisibility();
86
+ break;
84
87
  case "sync-templates":
85
88
  await cmdSyncTemplates();
86
89
  break;
@@ -132,6 +135,12 @@ async function main() {
132
135
  case "status":
133
136
  await cmdStatus();
134
137
  break;
138
+ case "next":
139
+ await cmdNext();
140
+ break;
141
+ case "stage":
142
+ await cmdStage();
143
+ break;
135
144
  case "cleanup":
136
145
  await cmdCleanup();
137
146
  break;
@@ -170,6 +179,11 @@ async function main() {
170
179
  config confirm <field> <value> 确认配置字段(写入 config + evidence)
171
180
  config unset <field> 移除确认配置
172
181
  status 显示当前项目的 SoloForge 状态
182
+ next 查询下一步操作和可执行工作包(默认只读)
183
+ next --json 纯 JSON 输出(无日志污染)
184
+ next --write-snapshot 将导航快照写入 .soloforge/navigation-snapshot.json
185
+ stage 显示当前项目阶段和任务阶段
186
+ stage --explain 详细解释当前阶段(判断依据、必要条件、下一阶段)
173
187
  cleanup 清理过期任务和 evidence(默认 dry-run,--apply 执行实际清理)
174
188
  `);
175
189
  }
@@ -460,56 +474,32 @@ async function cmdInit() {
460
474
  "请打开 Claude Code 开始使用。"}`);
461
475
  }
462
476
  async function copyGlobalPatterns(projectPath) {
477
+ const { copyPatternsToGlobal } = await import("../engine/template_init_sync.js");
463
478
  const globalDir = getGlobalPatternsDir();
464
- fss.mkdirSync(globalDir, { recursive: true });
465
- const templatesDir = path.resolve(import.meta.dirname, "..", "..", "templates", "patterns");
466
- if (fss.existsSync(templatesDir)) {
467
- const files = fss.readdirSync(templatesDir).filter((f) => f.endsWith(".md"));
468
- let copiedCount = 0;
469
- let skippedCount = 0;
470
- for (const f of files) {
471
- const src = path.join(templatesDir, f);
472
- const dest = path.join(globalDir, f);
473
- if (!fss.existsSync(dest)) {
474
- fss.copyFileSync(src, dest);
475
- copiedCount++;
476
- }
477
- else {
478
- skippedCount++;
479
- }
480
- }
481
- const parts = [];
482
- if (copiedCount > 0)
483
- parts.push(`新增 ${copiedCount} 个`);
484
- if (skippedCount > 0)
485
- parts.push(`跳过 ${skippedCount} 个(已存在)`);
486
- userInfo(`✅ 全局模板 ~/.soloforge/patterns/: ${parts.length > 0 ? parts.join(",") : `${files.length} 个(已全部存在)`}`);
479
+ const templatesRoot = path.resolve(import.meta.dirname, "..", "..");
480
+ const result = await copyPatternsToGlobal(templatesRoot, globalDir);
481
+ const parts = [];
482
+ if (result.copied > 0)
483
+ parts.push(`新增 ${result.copied} 个`);
484
+ if (result.skipped > 0)
485
+ parts.push(`跳过 ${result.skipped} 个(已存在)`);
486
+ if (parts.length > 0) {
487
+ userInfo(`✅ 全局模板 ~/.soloforge/patterns/: ${parts.join(",")}`);
487
488
  }
488
489
  }
489
490
  async function copyKnowledgeTemplates(projectPath) {
490
- const knowledgeTemplatesDir = path.resolve(import.meta.dirname, "..", "..", "templates", "knowledge");
491
- if (fss.existsSync(knowledgeTemplatesDir)) {
492
- const subDirs = ["procedures", "domain", "product_profiles", "acceptance_templates", "review_rules", "patterns/core", "checklists", "templates"];
493
- let copiedCount = 0;
494
- for (const subDir of subDirs) {
495
- const srcDir = path.join(knowledgeTemplatesDir, subDir);
496
- if (!fss.existsSync(srcDir))
497
- continue;
498
- const destDir = path.join(projectPath, ".soloforge", "knowledge", subDir);
499
- fss.mkdirSync(destDir, { recursive: true });
500
- const files = fss.readdirSync(srcDir).filter((f) => f.endsWith(".md") || f.endsWith(".yaml") || f.endsWith(".yml"));
501
- for (const f of files) {
502
- const src = path.join(srcDir, f);
503
- const dest = path.join(destDir, f);
504
- if (!fss.existsSync(dest)) {
505
- fss.copyFileSync(src, dest);
506
- copiedCount++;
507
- }
508
- }
509
- }
510
- if (copiedCount > 0) {
511
- userInfo(`✅ ${copiedCount} 个知识模板已复制到 .soloforge/knowledge/`);
512
- }
491
+ const { copyKnowledgeToProject } = await import("../engine/template_init_sync.js");
492
+ const templatesRoot = path.resolve(import.meta.dirname, "..", "..");
493
+ const result = await copyKnowledgeToProject(templatesRoot, projectPath);
494
+ const parts = [];
495
+ if (result.copied > 0)
496
+ parts.push(`${result.copied} 个已复制`);
497
+ if (result.skipped_internal > 0)
498
+ parts.push(`${result.skipped_internal} 个内部资产已跳过`);
499
+ if (result.skipped_no_contract > 0)
500
+ parts.push(`${result.skipped_no_contract} 个无合同已跳过`);
501
+ if (parts.length > 0) {
502
+ userInfo(`✅ 知识模板: ${parts.join(",")}`);
513
503
  }
514
504
  }
515
505
  async function generateAdapterConfigs(projectPath, adapter) {
@@ -870,8 +860,7 @@ async function cmdValidate() {
870
860
  try {
871
861
  const { config, source } = await resolveProjectConfig(projectPath);
872
862
  if (source === "inferred") {
873
- userInfo("ℹ️ 未找到 .soloforge/config.yaml — 使用自动推断的配置。");
874
- userInfo(" 运行 'soloforge init --auto' 可持久化。");
863
+ userInfo("ℹ️ 配置来源: 自动推断");
875
864
  }
876
865
  else {
877
866
  userInfo("✅ config.yaml 有效");
@@ -1068,6 +1057,18 @@ async function cmdValidate() {
1068
1057
  hasHardFail = true;
1069
1058
  }
1070
1059
  } // 双层机制检查结束
1060
+ try {
1061
+ const { planNextAction } = await import("../engine/next_action_planner.js");
1062
+ const navigation = await planNextAction(projectPath);
1063
+ userInfo(` 阶段: ${navigation.project_stage}${navigation.task_stage ? ` / ${navigation.task_stage}` : ""}`);
1064
+ if (navigation.blocking_reasons.length > 0) {
1065
+ userInfo(` 导航阻断: ${navigation.blocking_reasons.join("; ")}`);
1066
+ }
1067
+ userInfo(` 下一步: ${navigation.work_package?.goal_zh ?? navigation.recommended_prompt_zh}`);
1068
+ }
1069
+ catch (e) {
1070
+ userInfo(` ⚠ 导航摘要异常: ${e instanceof Error ? e.message : String(e)}`);
1071
+ }
1071
1072
  if (hasHardFail) {
1072
1073
  userError("❌ validate 失败: 配置优先级存在 hard_fail");
1073
1074
  process.exit(1);
@@ -1590,14 +1591,14 @@ async function cmdSyncTemplates() {
1590
1591
  else {
1591
1592
  userInfo(apply ? "模板同步: apply 模式" : "模板同步: dry-run 模式(不写入文件)");
1592
1593
  userInfo(` 资产总数: ${assets.length}`);
1593
- userInfo(` 安全检查: ${safeCheck.safe ? "" : ""}`);
1594
+ userInfo(` 应用安全: ${safeCheck.safe ? "安全" : "需确认"}`);
1594
1595
  userInfo(` 结果: ${syncResult.success ? "成功" : "失败"}`);
1595
1596
  userInfo(` 新增: ${syncResult.report.added.length}`);
1596
1597
  userInfo(` 更新: ${syncResult.report.updated.length}`);
1597
1598
  userInfo(` 跳过(用户修改): ${syncResult.report.skipped_user_modified.length}`);
1598
1599
  userInfo(` 废弃: ${syncResult.report.deprecated.length}`);
1599
1600
  if (!apply)
1600
- userInfo(" 使用 --apply --confirm 应用同步");
1601
+ userInfo(" 使用 --apply --confirm 应用同步;需确认表示 dry-run 发现现有用户资产,不会自动覆盖");
1601
1602
  }
1602
1603
  if (!syncResult.success)
1603
1604
  process.exit(1);
@@ -1973,8 +1974,8 @@ async function cmdValidateNewIssue() {
1973
1974
  userInfo(JSON.stringify(output, null, 2));
1974
1975
  }
1975
1976
  else {
1976
- userInfo(`问题演进门控: ${output.gate_status}`);
1977
- userInfo(` 已检查 ${allProblems.length} 个既有问题`);
1977
+ userInfo(`需求演进检查: ${output.gate_status}`);
1978
+ userInfo(` 已检查 ${allProblems.length} 个已有功能记录`);
1978
1979
  if (output.duplicate_detected) {
1979
1980
  userInfo(` ⚠ 重复检测: 发现 ${output.duplicates.join(", ")}`);
1980
1981
  for (const d of matchedDetails) {
@@ -1987,7 +1988,7 @@ async function cmdValidateNewIssue() {
1987
1988
  userInfo(` - ${r}`);
1988
1989
  }
1989
1990
  if (output.can_proceed) {
1990
- userInfo(` ✓ 可继续: 问题新增已通过演进门控 (候选ID: ${candidateId})`);
1991
+ userInfo(` ✓ 可继续: 需求新增已通过演进检查 (ID: ${candidateId})`);
1991
1992
  }
1992
1993
  }
1993
1994
  if (!output.can_proceed) {
@@ -1997,8 +1998,8 @@ async function cmdValidateNewIssue() {
1997
1998
  async function cmdStatus() {
1998
1999
  debug("CLI", "执行 cmdStatus");
1999
2000
  const projectPath = resolveProjectPath();
2000
- userInfo(`SoloForge 状态: ${projectPath}`);
2001
2001
  const { config, source } = await resolveProjectConfig(projectPath);
2002
+ userInfo(`SoloForge 状态: ${projectPath}`);
2002
2003
  userInfo(` 配置来源: ${source === "config_file" ? "config.yaml" : "自动推断"}`);
2003
2004
  userInfo(` 产品: ${config.product_profile}`);
2004
2005
  userInfo(` 后端: ${config.tech_stack.backend.framework || "未配置"}`);
@@ -2051,6 +2052,19 @@ async function cmdStatus() {
2051
2052
  else {
2052
2053
  userInfo(" 知识: 未初始化");
2053
2054
  }
2055
+ // 导航摘要(消费同一规划模块,包含阻断项和下一步)
2056
+ try {
2057
+ const { planNextAction } = await import("../engine/next_action_planner.js");
2058
+ const navigation = await planNextAction(projectPath);
2059
+ userInfo(` 阶段: ${navigation.project_stage}${navigation.task_stage ? ` / ${navigation.task_stage}` : ""}`);
2060
+ if (navigation.blocking_reasons.length > 0) {
2061
+ userInfo(` 导航阻断: ${navigation.blocking_reasons.join("; ")}`);
2062
+ }
2063
+ userInfo(` 下一步: ${navigation.work_package?.goal_zh ?? navigation.recommended_prompt_zh}`);
2064
+ }
2065
+ catch (e) {
2066
+ userInfo(` ⚠ 导航摘要异常: ${e instanceof Error ? e.message : String(e)}`);
2067
+ }
2054
2068
  }
2055
2069
  async function interactiveConfig(projectPath) {
2056
2070
  debug("CLI", "执行 interactiveConfig");
@@ -2113,6 +2127,200 @@ function cmdVersion() {
2113
2127
  userInfo("SoloForge v" + pkg.version);
2114
2128
  }
2115
2129
  }
2130
+ async function cmdNext() {
2131
+ debug("CLI", "执行 cmdNext");
2132
+ const projectPath = resolveProjectPath();
2133
+ const isJson = args.includes("--json");
2134
+ const writeSnapshot = args.includes("--write-snapshot");
2135
+ const { planNextAction } = await import("../engine/next_action_planner.js");
2136
+ const plan = await planNextAction(projectPath);
2137
+ if (isJson) {
2138
+ // JSON 模式: 纯 JSON 到 stdout,无日志污染
2139
+ const wp = plan.work_package;
2140
+ const output = {
2141
+ project_stage: plan.project_stage,
2142
+ task_stage: plan.task_stage,
2143
+ confidence: plan.confidence,
2144
+ stage_evidence: plan.stage_evidence,
2145
+ blocking_reasons: plan.blocking_reasons,
2146
+ recommended_commands: plan.recommended_commands,
2147
+ recommended_prompt: plan.recommended_prompt_zh,
2148
+ disallowed_next_actions: plan.disallowed_actions.map((da) => ({
2149
+ rule_id: da.rule_id,
2150
+ blocked_actions: da.blocked_actions,
2151
+ reason_zh: da.reason_zh,
2152
+ })),
2153
+ work_package: wp ? {
2154
+ id: wp.id,
2155
+ goal: wp.goal_zh,
2156
+ input_files: wp.input_files,
2157
+ must_read: wp.must_read,
2158
+ forbidden_changes: wp.forbidden_changes,
2159
+ expected_outputs: wp.expected_outputs,
2160
+ acceptance_commands: wp.acceptance_commands,
2161
+ user_confirmation_points: wp.user_confirmation_points,
2162
+ rollback_or_fallback: wp.rollback_or_fallback,
2163
+ } : null,
2164
+ };
2165
+ process.stdout.write(JSON.stringify(output, null, 2) + "\n");
2166
+ }
2167
+ else {
2168
+ // 人类可读输出
2169
+ userInfo(`\n项目阶段: ${plan.project_stage}`);
2170
+ if (plan.task_stage) {
2171
+ userInfo(`任务阶段: ${plan.task_stage}`);
2172
+ }
2173
+ else {
2174
+ userInfo("任务阶段: 无活跃任务");
2175
+ }
2176
+ userInfo(`置信度: ${plan.confidence}`);
2177
+ if (plan.stage_evidence.length > 0) {
2178
+ userInfo(`\n判断依据:`);
2179
+ for (const ev of plan.stage_evidence) {
2180
+ userInfo(` - ${ev}`);
2181
+ }
2182
+ }
2183
+ // 陈旧任务
2184
+ if (plan.stale_task?.is_stale) {
2185
+ userInfo(`\n⚠️ 检测到陈旧任务: ${plan.stale_task.reason_zh}`);
2186
+ userInfo(` 任务 ID: ${plan.stale_task.task_id}`);
2187
+ userInfo(` 建议操作: ${plan.stale_task.suggested_resolutions.join(" / ")}`);
2188
+ userInfo(` ⚠️ 不要绕过 SoloForge 状态直接操作`);
2189
+ }
2190
+ // 阻断项
2191
+ if (plan.blocking_reasons.length > 0) {
2192
+ userInfo(`\n阻断项:`);
2193
+ for (const r of plan.blocking_reasons) {
2194
+ userInfo(` - ${r}`);
2195
+ }
2196
+ }
2197
+ // 工作包
2198
+ if (plan.work_package) {
2199
+ const wp = plan.work_package;
2200
+ userInfo(`\n下一步: ${wp.goal_zh}`);
2201
+ userInfo(` 描述: ${wp.description_zh}`);
2202
+ if (wp.tool_name) {
2203
+ userInfo(` 工具: ${wp.tool_name}`);
2204
+ }
2205
+ if (wp.must_read.length > 0) {
2206
+ userInfo(` 必读文件:`);
2207
+ for (const f of wp.must_read)
2208
+ userInfo(` - ${f}`);
2209
+ }
2210
+ if (wp.forbidden_changes.length > 0) {
2211
+ userInfo(` 禁止操作:`);
2212
+ for (const f of wp.forbidden_changes)
2213
+ userInfo(` - ${f}`);
2214
+ }
2215
+ if (wp.expected_outputs.length > 0) {
2216
+ userInfo(` 预期产出:`);
2217
+ for (const e of wp.expected_outputs)
2218
+ userInfo(` - ${e}`);
2219
+ }
2220
+ if (wp.acceptance_commands.length > 0) {
2221
+ userInfo(` 验收命令:`);
2222
+ for (const c of wp.acceptance_commands)
2223
+ userInfo(` - ${c}`);
2224
+ }
2225
+ if (wp.user_confirmation_points.length > 0) {
2226
+ userInfo(` 需用户确认:`);
2227
+ for (const u of wp.user_confirmation_points)
2228
+ userInfo(` - ${u}`);
2229
+ }
2230
+ if (wp.rollback_or_fallback.length > 0) {
2231
+ userInfo(` 失败回退:`);
2232
+ for (const r of wp.rollback_or_fallback)
2233
+ userInfo(` - ${r}`);
2234
+ }
2235
+ }
2236
+ // 推荐命令
2237
+ if (plan.recommended_commands.length > 0) {
2238
+ userInfo(`\n推荐命令:`);
2239
+ for (const c of plan.recommended_commands) {
2240
+ userInfo(` ${c}`);
2241
+ }
2242
+ }
2243
+ // 禁止动作
2244
+ if (plan.disallowed_actions.length > 0) {
2245
+ userInfo(`\n禁止动作:`);
2246
+ for (const da of plan.disallowed_actions) {
2247
+ userInfo(` [${da.rule_id}] ${da.blocked_actions.join(", ")}: ${da.reason_zh}`);
2248
+ }
2249
+ }
2250
+ // 推荐给 AI 的指令
2251
+ userInfo(`\n推荐指令: ${plan.recommended_prompt_zh}`);
2252
+ }
2253
+ // 写入快照(只在显式 --write-snapshot 时)
2254
+ if (writeSnapshot) {
2255
+ const snapshotPath = path.join(projectPath, ".soloforge", "navigation-snapshot.json");
2256
+ const snapshot = {
2257
+ plan_id: plan.plan_id,
2258
+ generated_at: plan.generated_at,
2259
+ project_stage: plan.project_stage,
2260
+ task_stage: plan.task_stage,
2261
+ current_task_id: plan.current_task_id,
2262
+ work_package: plan.work_package,
2263
+ };
2264
+ fss.mkdirSync(path.join(projectPath, ".soloforge"), { recursive: true });
2265
+ fss.writeFileSync(snapshotPath, JSON.stringify(snapshot, null, 2));
2266
+ if (!isJson) {
2267
+ userInfo(`\n导航快照已写入: ${snapshotPath}`);
2268
+ }
2269
+ }
2270
+ }
2271
+ async function cmdStage() {
2272
+ debug("CLI", "执行 cmdStage");
2273
+ const projectPath = resolveProjectPath();
2274
+ const explain = args.includes("--explain");
2275
+ const isJson = args.includes("--json");
2276
+ const { detectProjectStage, explainProjectStage } = await import("../engine/project_stage_detector.js");
2277
+ const { detectTaskStage, explainTaskStage } = await import("../engine/task_stage_detector.js");
2278
+ const projectStage = await detectProjectStage(projectPath);
2279
+ // 加载当前任务
2280
+ let taskStage = null;
2281
+ let taskId = null;
2282
+ try {
2283
+ const { TaskContextManager } = await import("../engine/task_context.js");
2284
+ const stateDir = path.join(projectPath, ".soloforge", "state");
2285
+ if (fss.existsSync(stateDir)) {
2286
+ const manager = new TaskContextManager(stateDir);
2287
+ const ctx = await manager.getCurrentTask();
2288
+ if (ctx) {
2289
+ taskStage = detectTaskStage(ctx);
2290
+ taskId = ctx.task_id;
2291
+ }
2292
+ }
2293
+ }
2294
+ catch { }
2295
+ if (isJson) {
2296
+ const projExplanation = explainProjectStage(projectStage);
2297
+ process.stdout.write(JSON.stringify({
2298
+ project: projExplanation,
2299
+ task: taskStage ? explainTaskStage(taskStage) : null,
2300
+ task_id: taskId,
2301
+ }, null, 2) + "\n");
2302
+ return;
2303
+ }
2304
+ userInfo(`\n项目阶段: ${projectStage}`);
2305
+ if (explain) {
2306
+ const projExplanation = explainProjectStage(projectStage);
2307
+ userInfo(` ${projExplanation.description_zh}`);
2308
+ userInfo(` 必要条件: ${projExplanation.required_evidence.join(", ") || "无"}`);
2309
+ userInfo(` 下一步可能: ${projExplanation.next_possible_stages.join(", ")}`);
2310
+ }
2311
+ if (taskStage) {
2312
+ userInfo(`\n任务阶段: ${taskStage} (${taskId ?? "unknown"})`);
2313
+ if (explain) {
2314
+ const taskExplanation = explainTaskStage(taskStage);
2315
+ userInfo(` ${taskExplanation.description_zh}`);
2316
+ userInfo(` 必要条件: ${taskExplanation.required_evidence.join(", ")}`);
2317
+ userInfo(` 下一步可能: ${taskExplanation.next_possible_stages.join(", ")}`);
2318
+ }
2319
+ }
2320
+ else {
2321
+ userInfo("\n当前无活跃任务");
2322
+ }
2323
+ }
2116
2324
  async function cmdCleanup() {
2117
2325
  debug("CLI", "执行 cmdCleanup");
2118
2326
  const dryRun = !args.includes("--apply");
@@ -2266,4 +2474,58 @@ function getArgValue(flag) {
2266
2474
  return undefined;
2267
2475
  return result;
2268
2476
  }
2477
+ async function cmdAuditTemplateVisibility() {
2478
+ const projectPath = process.env.SOLOFORGE_PROJECT ?? process.cwd();
2479
+ const { auditStandardAssetCoverage } = await import("../engine/standard_asset_coverage.js");
2480
+ const { listBuiltinConsumableAssets } = await import("../engine/consumable_asset_registry.js");
2481
+ const { listTemplateAssetContracts, auditContractCoverage } = await import("../engine/template_asset_contract_registry.js");
2482
+ const { userInfo, userJson } = await import("../engine/logger.js");
2483
+ // 使用权威合同注册表作为单一数据源
2484
+ const contracts = listTemplateAssetContracts();
2485
+ const registeredAssets = listBuiltinConsumableAssets();
2486
+ const consumablePaths = new Set(registeredAssets.map((a) => a.path));
2487
+ const ownerMap = new Map(contracts.map((c) => [c.path, c.owner_mechanism_id]));
2488
+ const consumerMap = new Map(contracts.map((c) => [c.path, [c.mainline_consumer, c.validation_entrypoint].filter(Boolean)]));
2489
+ const visibilityMap = new Map(contracts.map((c) => [c.path, c.asset_visibility]));
2490
+ // 运行覆盖审计(使用真实合同数据)
2491
+ const report = auditStandardAssetCoverage(projectPath, consumablePaths, ownerMap, consumerMap, visibilityMap);
2492
+ // 合同覆盖统计
2493
+ const coverageReport = auditContractCoverage(projectPath);
2494
+ // 可见性统计(从权威合同直接计算)
2495
+ const internalCount = contracts.filter((c) => c.asset_visibility === "soloforge_internal" || c.asset_visibility === "scaffold_only").length;
2496
+ const userVisibleCount = contracts.filter((c) => c.user_visible).length;
2497
+ // 输出报告
2498
+ const isJson = args.includes("--json");
2499
+ const result = {
2500
+ total_assets: report.total_assets,
2501
+ contract_covered: coverageReport.contract_covered,
2502
+ uncovered_assets: coverageReport.uncovered,
2503
+ user_visible_count: userVisibleCount,
2504
+ internal_count: internalCount,
2505
+ unknown_visibility: coverageReport.visibility_unknown,
2506
+ conflict_count: 0,
2507
+ missing_bearer: report.missing_standard_bearer,
2508
+ missing_revalidation: report.missing_revalidation,
2509
+ missing_consumer: report.missing_consumer,
2510
+ missing_owner: report.missing_owner,
2511
+ unregistered: report.unregistered_assets,
2512
+ };
2513
+ if (isJson) {
2514
+ userJson(JSON.stringify(result, null, 2));
2515
+ }
2516
+ else {
2517
+ userInfo("═══ 模板资产可见性审计报告 ═══");
2518
+ userInfo(`总资产数: ${report.total_assets}`);
2519
+ userInfo(`合同覆盖: ${coverageReport.contract_covered}`);
2520
+ userInfo(`未覆盖: ${coverageReport.uncovered}`);
2521
+ userInfo(`用户可见: ${userVisibleCount}`);
2522
+ userInfo(`内部资产: ${internalCount}`);
2523
+ userInfo(`未知可见性: ${coverageReport.visibility_unknown}`);
2524
+ userInfo(`缺标准承载: ${report.missing_standard_bearer}`);
2525
+ userInfo(`缺复验入口: ${report.missing_revalidation}`);
2526
+ userInfo(`缺消费者: ${report.missing_consumer}`);
2527
+ userInfo(`缺 owner: ${report.missing_owner}`);
2528
+ userInfo(`未注册: ${report.unregistered_assets}`);
2529
+ }
2530
+ }
2269
2531
  //# sourceMappingURL=soloforge.js.map