soloforge 1.2.8 → 1.2.9

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 (405) hide show
  1. package/README.md +105 -321
  2. package/dist/adapters/claude_code/claude_md.d.ts +5 -0
  3. package/dist/adapters/claude_code/claude_md.d.ts.map +1 -1
  4. package/dist/adapters/claude_code/claude_md.js +6 -0
  5. package/dist/adapters/claude_code/claude_md.js.map +1 -1
  6. package/dist/adapters/claude_code/hooks.d.ts +4 -0
  7. package/dist/adapters/claude_code/hooks.d.ts.map +1 -1
  8. package/dist/adapters/claude_code/hooks.js +5 -0
  9. package/dist/adapters/claude_code/hooks.js.map +1 -1
  10. package/dist/adapters/claude_code/server.d.ts.map +1 -1
  11. package/dist/adapters/claude_code/server.js +9 -21
  12. package/dist/adapters/claude_code/server.js.map +1 -1
  13. package/dist/adapters/claude_code/tools.d.ts +5 -0
  14. package/dist/adapters/claude_code/tools.d.ts.map +1 -1
  15. package/dist/adapters/claude_code/tools.js +619 -205
  16. package/dist/adapters/claude_code/tools.js.map +1 -1
  17. package/dist/adapters/codex/codex_config.d.ts +9 -0
  18. package/dist/adapters/codex/codex_config.d.ts.map +1 -1
  19. package/dist/adapters/codex/codex_config.js +11 -3
  20. package/dist/adapters/codex/codex_config.js.map +1 -1
  21. package/dist/adapters/codex/codex_rules.d.ts +5 -0
  22. package/dist/adapters/codex/codex_rules.d.ts.map +1 -1
  23. package/dist/adapters/codex/codex_rules.js +8 -1
  24. package/dist/adapters/codex/codex_rules.js.map +1 -1
  25. package/dist/adapters/shared/workflow_template.d.ts +5 -0
  26. package/dist/adapters/shared/workflow_template.d.ts.map +1 -1
  27. package/dist/adapters/shared/workflow_template.js +32 -79
  28. package/dist/adapters/shared/workflow_template.js.map +1 -1
  29. package/dist/adapters/trae/trae_config.d.ts +4 -0
  30. package/dist/adapters/trae/trae_config.d.ts.map +1 -1
  31. package/dist/adapters/trae/trae_config.js +5 -7
  32. package/dist/adapters/trae/trae_config.js.map +1 -1
  33. package/dist/adapters/trae/trae_rules.d.ts +5 -0
  34. package/dist/adapters/trae/trae_rules.d.ts.map +1 -1
  35. package/dist/adapters/trae/trae_rules.js +7 -1
  36. package/dist/adapters/trae/trae_rules.js.map +1 -1
  37. package/dist/bin/config_commands.d.ts +33 -0
  38. package/dist/bin/config_commands.d.ts.map +1 -0
  39. package/dist/bin/config_commands.js +222 -0
  40. package/dist/bin/config_commands.js.map +1 -0
  41. package/dist/bin/soloforge.js +609 -119
  42. package/dist/bin/soloforge.js.map +1 -1
  43. package/dist/engine/artifact_contract_registry.d.ts +138 -0
  44. package/dist/engine/artifact_contract_registry.d.ts.map +1 -0
  45. package/dist/engine/artifact_contract_registry.js +427 -0
  46. package/dist/engine/artifact_contract_registry.js.map +1 -0
  47. package/dist/engine/audit_pool.d.ts +40 -0
  48. package/dist/engine/audit_pool.d.ts.map +1 -1
  49. package/dist/engine/audit_pool.js +37 -1
  50. package/dist/engine/audit_pool.js.map +1 -1
  51. package/dist/engine/audit_sampler.d.ts +5 -0
  52. package/dist/engine/audit_sampler.d.ts.map +1 -1
  53. package/dist/engine/audit_sampler.js +6 -0
  54. package/dist/engine/audit_sampler.js.map +1 -1
  55. package/dist/engine/audit_verifier.d.ts.map +1 -1
  56. package/dist/engine/audit_verifier.js +5 -1
  57. package/dist/engine/audit_verifier.js.map +1 -1
  58. package/dist/engine/batch1_manifest.d.ts +61 -0
  59. package/dist/engine/batch1_manifest.d.ts.map +1 -0
  60. package/dist/engine/batch1_manifest.js +220 -0
  61. package/dist/engine/batch1_manifest.js.map +1 -0
  62. package/dist/engine/batch1_reality_gate.d.ts +40 -0
  63. package/dist/engine/batch1_reality_gate.d.ts.map +1 -0
  64. package/dist/engine/batch1_reality_gate.js +290 -0
  65. package/dist/engine/batch1_reality_gate.js.map +1 -0
  66. package/dist/engine/batch1_scenario_registry.d.ts +62 -0
  67. package/dist/engine/batch1_scenario_registry.d.ts.map +1 -0
  68. package/dist/engine/batch1_scenario_registry.js +392 -0
  69. package/dist/engine/batch1_scenario_registry.js.map +1 -0
  70. package/dist/engine/batch1_scenario_runners.d.ts +42 -0
  71. package/dist/engine/batch1_scenario_runners.d.ts.map +1 -0
  72. package/dist/engine/batch1_scenario_runners.js +292 -0
  73. package/dist/engine/batch1_scenario_runners.js.map +1 -0
  74. package/dist/engine/capability_action_advisor.d.ts +3 -0
  75. package/dist/engine/capability_action_advisor.d.ts.map +1 -1
  76. package/dist/engine/capability_action_advisor.js +10 -0
  77. package/dist/engine/capability_action_advisor.js.map +1 -1
  78. package/dist/engine/capability_registry.d.ts +21 -0
  79. package/dist/engine/capability_registry.d.ts.map +1 -1
  80. package/dist/engine/capability_registry.js +113 -0
  81. package/dist/engine/capability_registry.js.map +1 -1
  82. package/dist/engine/capability_state_store.d.ts +63 -0
  83. package/dist/engine/capability_state_store.d.ts.map +1 -1
  84. package/dist/engine/capability_state_store.js +49 -1
  85. package/dist/engine/capability_state_store.js.map +1 -1
  86. package/dist/engine/change_coordinator.d.ts.map +1 -1
  87. package/dist/engine/change_coordinator.js +5 -4
  88. package/dist/engine/change_coordinator.js.map +1 -1
  89. package/dist/engine/classifier.d.ts +15 -5
  90. package/dist/engine/classifier.d.ts.map +1 -1
  91. package/dist/engine/classifier.js +70 -69
  92. package/dist/engine/classifier.js.map +1 -1
  93. package/dist/engine/code_reviewer.d.ts +14 -0
  94. package/dist/engine/code_reviewer.d.ts.map +1 -1
  95. package/dist/engine/code_reviewer.js +109 -10
  96. package/dist/engine/code_reviewer.js.map +1 -1
  97. package/dist/engine/cognitive_anchor.d.ts +14 -0
  98. package/dist/engine/cognitive_anchor.d.ts.map +1 -1
  99. package/dist/engine/cognitive_anchor.js +26 -2
  100. package/dist/engine/cognitive_anchor.js.map +1 -1
  101. package/dist/engine/command_execution_contract.d.ts +226 -0
  102. package/dist/engine/command_execution_contract.d.ts.map +1 -0
  103. package/dist/engine/command_execution_contract.js +571 -0
  104. package/dist/engine/command_execution_contract.js.map +1 -0
  105. package/dist/engine/confidence_scorer.d.ts.map +1 -1
  106. package/dist/engine/confidence_scorer.js +1 -0
  107. package/dist/engine/confidence_scorer.js.map +1 -1
  108. package/dist/engine/config_precedence_contract.d.ts +269 -0
  109. package/dist/engine/config_precedence_contract.d.ts.map +1 -0
  110. package/dist/engine/config_precedence_contract.js +948 -0
  111. package/dist/engine/config_precedence_contract.js.map +1 -0
  112. package/dist/engine/conflict_gate.d.ts +13 -0
  113. package/dist/engine/conflict_gate.d.ts.map +1 -1
  114. package/dist/engine/conflict_gate.js +20 -2
  115. package/dist/engine/conflict_gate.js.map +1 -1
  116. package/dist/engine/consumable_asset_registry.d.ts +46 -0
  117. package/dist/engine/consumable_asset_registry.d.ts.map +1 -0
  118. package/dist/engine/consumable_asset_registry.js +758 -0
  119. package/dist/engine/consumable_asset_registry.js.map +1 -0
  120. package/dist/engine/contract_guard.d.ts +4 -0
  121. package/dist/engine/contract_guard.d.ts.map +1 -1
  122. package/dist/engine/contract_guard.js +15 -7
  123. package/dist/engine/contract_guard.js.map +1 -1
  124. package/dist/engine/convention_detector.d.ts.map +1 -1
  125. package/dist/engine/convention_detector.js +5 -2
  126. package/dist/engine/convention_detector.js.map +1 -1
  127. package/dist/engine/core_engineering_principles.d.ts +155 -0
  128. package/dist/engine/core_engineering_principles.d.ts.map +1 -0
  129. package/dist/engine/core_engineering_principles.js +426 -0
  130. package/dist/engine/core_engineering_principles.js.map +1 -0
  131. package/dist/engine/debt_reporter.d.ts.map +1 -1
  132. package/dist/engine/debt_reporter.js +3 -1
  133. package/dist/engine/debt_reporter.js.map +1 -1
  134. package/dist/engine/debt_tracker.d.ts.map +1 -1
  135. package/dist/engine/debt_tracker.js +9 -3
  136. package/dist/engine/debt_tracker.js.map +1 -1
  137. package/dist/engine/debugger.d.ts.map +1 -1
  138. package/dist/engine/debugger.js +2 -0
  139. package/dist/engine/debugger.js.map +1 -1
  140. package/dist/engine/decision_contract.d.ts +11 -2
  141. package/dist/engine/decision_contract.d.ts.map +1 -1
  142. package/dist/engine/decision_contract.js +17 -2
  143. package/dist/engine/decision_contract.js.map +1 -1
  144. package/dist/engine/delivery.d.ts +7 -0
  145. package/dist/engine/delivery.d.ts.map +1 -1
  146. package/dist/engine/delivery.js +89 -36
  147. package/dist/engine/delivery.js.map +1 -1
  148. package/dist/engine/dependency_scanner.d.ts.map +1 -1
  149. package/dist/engine/dependency_scanner.js +14 -9
  150. package/dist/engine/dependency_scanner.js.map +1 -1
  151. package/dist/engine/developer_sovereignty.d.ts.map +1 -1
  152. package/dist/engine/developer_sovereignty.js +8 -2
  153. package/dist/engine/developer_sovereignty.js.map +1 -1
  154. package/dist/engine/diff_ownership.d.ts.map +1 -1
  155. package/dist/engine/diff_ownership.js +8 -0
  156. package/dist/engine/diff_ownership.js.map +1 -1
  157. package/dist/engine/diff_ownership_store.d.ts +26 -10
  158. package/dist/engine/diff_ownership_store.d.ts.map +1 -1
  159. package/dist/engine/diff_ownership_store.js +47 -20
  160. package/dist/engine/diff_ownership_store.js.map +1 -1
  161. package/dist/engine/dual_layer_mechanism_registry.d.ts +66 -0
  162. package/dist/engine/dual_layer_mechanism_registry.d.ts.map +1 -0
  163. package/dist/engine/dual_layer_mechanism_registry.js +1077 -0
  164. package/dist/engine/dual_layer_mechanism_registry.js.map +1 -0
  165. package/dist/engine/escape_report.d.ts +50 -0
  166. package/dist/engine/escape_report.d.ts.map +1 -1
  167. package/dist/engine/escape_report.js +38 -0
  168. package/dist/engine/escape_report.js.map +1 -1
  169. package/dist/engine/evolver.d.ts.map +1 -1
  170. package/dist/engine/evolver.js +12 -2
  171. package/dist/engine/evolver.js.map +1 -1
  172. package/dist/engine/exploration.d.ts.map +1 -1
  173. package/dist/engine/exploration.js +87 -0
  174. package/dist/engine/exploration.js.map +1 -1
  175. package/dist/engine/failure_classifier.d.ts.map +1 -1
  176. package/dist/engine/failure_classifier.js +8 -0
  177. package/dist/engine/failure_classifier.js.map +1 -1
  178. package/dist/engine/feasibility_checker.d.ts +8 -0
  179. package/dist/engine/feasibility_checker.d.ts.map +1 -1
  180. package/dist/engine/feasibility_checker.js +12 -0
  181. package/dist/engine/feasibility_checker.js.map +1 -1
  182. package/dist/engine/git_deps.d.ts +4 -1
  183. package/dist/engine/git_deps.d.ts.map +1 -1
  184. package/dist/engine/git_deps.js +5 -1
  185. package/dist/engine/git_deps.js.map +1 -1
  186. package/dist/engine/governance_report.d.ts +57 -1
  187. package/dist/engine/governance_report.d.ts.map +1 -1
  188. package/dist/engine/governance_report.js +91 -1
  189. package/dist/engine/governance_report.js.map +1 -1
  190. package/dist/engine/impact_analyzer.d.ts.map +1 -1
  191. package/dist/engine/impact_analyzer.js +5 -1
  192. package/dist/engine/impact_analyzer.js.map +1 -1
  193. package/dist/engine/implementation_roadmap_registry.d.ts +105 -0
  194. package/dist/engine/implementation_roadmap_registry.d.ts.map +1 -0
  195. package/dist/engine/implementation_roadmap_registry.js +813 -0
  196. package/dist/engine/implementation_roadmap_registry.js.map +1 -0
  197. package/dist/engine/input_material_contract_registry.d.ts +185 -0
  198. package/dist/engine/input_material_contract_registry.d.ts.map +1 -0
  199. package/dist/engine/input_material_contract_registry.js +563 -0
  200. package/dist/engine/input_material_contract_registry.js.map +1 -0
  201. package/dist/engine/intent_expander.d.ts +8 -27
  202. package/dist/engine/intent_expander.d.ts.map +1 -1
  203. package/dist/engine/intent_expander.js +1170 -139
  204. package/dist/engine/intent_expander.js.map +1 -1
  205. package/dist/engine/intent_router.d.ts +82 -0
  206. package/dist/engine/intent_router.d.ts.map +1 -0
  207. package/dist/engine/intent_router.js +458 -0
  208. package/dist/engine/intent_router.js.map +1 -0
  209. package/dist/engine/io_controller.d.ts.map +1 -1
  210. package/dist/engine/io_controller.js +25 -13
  211. package/dist/engine/io_controller.js.map +1 -1
  212. package/dist/engine/java_quality_guard.d.ts.map +1 -1
  213. package/dist/engine/java_quality_guard.js +8 -4
  214. package/dist/engine/java_quality_guard.js.map +1 -1
  215. package/dist/engine/job_manager.d.ts +35 -0
  216. package/dist/engine/job_manager.d.ts.map +1 -1
  217. package/dist/engine/job_manager.js +53 -9
  218. package/dist/engine/job_manager.js.map +1 -1
  219. package/dist/engine/knowledge_config_loader.d.ts +12 -1
  220. package/dist/engine/knowledge_config_loader.d.ts.map +1 -1
  221. package/dist/engine/knowledge_config_loader.js +50 -10
  222. package/dist/engine/knowledge_config_loader.js.map +1 -1
  223. package/dist/engine/knowledge_injection_boundary.d.ts +56 -0
  224. package/dist/engine/knowledge_injection_boundary.d.ts.map +1 -0
  225. package/dist/engine/knowledge_injection_boundary.js +561 -0
  226. package/dist/engine/knowledge_injection_boundary.js.map +1 -0
  227. package/dist/engine/knowledge_manager.d.ts +73 -0
  228. package/dist/engine/knowledge_manager.d.ts.map +1 -1
  229. package/dist/engine/knowledge_manager.js +163 -21
  230. package/dist/engine/knowledge_manager.js.map +1 -1
  231. package/dist/engine/knowledge_sovereignty.d.ts +1 -0
  232. package/dist/engine/knowledge_sovereignty.d.ts.map +1 -1
  233. package/dist/engine/knowledge_sovereignty.js +8 -3
  234. package/dist/engine/knowledge_sovereignty.js.map +1 -1
  235. package/dist/engine/llm_gateway.d.ts +74 -3
  236. package/dist/engine/llm_gateway.d.ts.map +1 -1
  237. package/dist/engine/llm_gateway.js +75 -4
  238. package/dist/engine/llm_gateway.js.map +1 -1
  239. package/dist/engine/main_path_integration_contract.d.ts +383 -0
  240. package/dist/engine/main_path_integration_contract.d.ts.map +1 -0
  241. package/dist/engine/main_path_integration_contract.js +1581 -0
  242. package/dist/engine/main_path_integration_contract.js.map +1 -0
  243. package/dist/engine/mechanism_contract_registry.d.ts +59 -0
  244. package/dist/engine/mechanism_contract_registry.d.ts.map +1 -0
  245. package/dist/engine/mechanism_contract_registry.js +484 -0
  246. package/dist/engine/mechanism_contract_registry.js.map +1 -0
  247. package/dist/engine/migration_guard.d.ts.map +1 -1
  248. package/dist/engine/migration_guard.js +24 -15
  249. package/dist/engine/migration_guard.js.map +1 -1
  250. package/dist/engine/mutation_audit.d.ts +10 -0
  251. package/dist/engine/mutation_audit.d.ts.map +1 -1
  252. package/dist/engine/mutation_audit.js +19 -2
  253. package/dist/engine/mutation_audit.js.map +1 -1
  254. package/dist/engine/observability.d.ts.map +1 -1
  255. package/dist/engine/observability.js +17 -6
  256. package/dist/engine/observability.js.map +1 -1
  257. package/dist/engine/onboarding.d.ts.map +1 -1
  258. package/dist/engine/onboarding.js +20 -4
  259. package/dist/engine/onboarding.js.map +1 -1
  260. package/dist/engine/policy_drift_detector.d.ts +6 -0
  261. package/dist/engine/policy_drift_detector.d.ts.map +1 -1
  262. package/dist/engine/policy_drift_detector.js +16 -0
  263. package/dist/engine/policy_drift_detector.js.map +1 -1
  264. package/dist/engine/privacy_secret_contract.d.ts +320 -0
  265. package/dist/engine/privacy_secret_contract.d.ts.map +1 -0
  266. package/dist/engine/privacy_secret_contract.js +874 -0
  267. package/dist/engine/privacy_secret_contract.js.map +1 -0
  268. package/dist/engine/regression_matrix.d.ts +21 -8
  269. package/dist/engine/regression_matrix.d.ts.map +1 -1
  270. package/dist/engine/regression_matrix.js +37 -8
  271. package/dist/engine/regression_matrix.js.map +1 -1
  272. package/dist/engine/risk_sampler.d.ts +6 -0
  273. package/dist/engine/risk_sampler.d.ts.map +1 -1
  274. package/dist/engine/risk_sampler.js +9 -0
  275. package/dist/engine/risk_sampler.js.map +1 -1
  276. package/dist/engine/runtime_safety.d.ts.map +1 -1
  277. package/dist/engine/runtime_safety.js +7 -3
  278. package/dist/engine/runtime_safety.js.map +1 -1
  279. package/dist/engine/scaffolder.d.ts.map +1 -1
  280. package/dist/engine/scaffolder.js +7 -1
  281. package/dist/engine/scaffolder.js.map +1 -1
  282. package/dist/engine/scope_controller.d.ts.map +1 -1
  283. package/dist/engine/scope_controller.js +12 -1
  284. package/dist/engine/scope_controller.js.map +1 -1
  285. package/dist/engine/scope_lease.d.ts +43 -0
  286. package/dist/engine/scope_lease.d.ts.map +1 -1
  287. package/dist/engine/scope_lease.js +44 -0
  288. package/dist/engine/scope_lease.js.map +1 -1
  289. package/dist/engine/semantic_evidence.d.ts +6 -0
  290. package/dist/engine/semantic_evidence.d.ts.map +1 -1
  291. package/dist/engine/semantic_evidence.js +9 -0
  292. package/dist/engine/semantic_evidence.js.map +1 -1
  293. package/dist/engine/task_context.d.ts +36 -1
  294. package/dist/engine/task_context.d.ts.map +1 -1
  295. package/dist/engine/task_context.js +252 -13
  296. package/dist/engine/task_context.js.map +1 -1
  297. package/dist/engine/task_planner.d.ts.map +1 -1
  298. package/dist/engine/task_planner.js +13 -3
  299. package/dist/engine/task_planner.js.map +1 -1
  300. package/dist/engine/team_awareness.d.ts.map +1 -1
  301. package/dist/engine/team_awareness.js +8 -7
  302. package/dist/engine/team_awareness.js.map +1 -1
  303. package/dist/engine/template_mechanism_auditor.d.ts +93 -0
  304. package/dist/engine/template_mechanism_auditor.d.ts.map +1 -0
  305. package/dist/engine/template_mechanism_auditor.js +622 -0
  306. package/dist/engine/template_mechanism_auditor.js.map +1 -0
  307. package/dist/engine/test_generator.d.ts.map +1 -1
  308. package/dist/engine/test_generator.js +6 -0
  309. package/dist/engine/test_generator.js.map +1 -1
  310. package/dist/engine/test_quality.d.ts +6 -0
  311. package/dist/engine/test_quality.d.ts.map +1 -1
  312. package/dist/engine/test_quality.js +26 -10
  313. package/dist/engine/test_quality.js.map +1 -1
  314. package/dist/engine/tool_invocation_contract_registry.d.ts +136 -0
  315. package/dist/engine/tool_invocation_contract_registry.d.ts.map +1 -0
  316. package/dist/engine/tool_invocation_contract_registry.js +731 -0
  317. package/dist/engine/tool_invocation_contract_registry.js.map +1 -0
  318. package/dist/engine/traceability.d.ts +3 -0
  319. package/dist/engine/traceability.d.ts.map +1 -1
  320. package/dist/engine/traceability.js +12 -4
  321. package/dist/engine/traceability.js.map +1 -1
  322. package/dist/engine/user_feedback_contract.d.ts +162 -0
  323. package/dist/engine/user_feedback_contract.d.ts.map +1 -0
  324. package/dist/engine/user_feedback_contract.js +356 -0
  325. package/dist/engine/user_feedback_contract.js.map +1 -0
  326. package/dist/engine/verifier.d.ts +6 -1
  327. package/dist/engine/verifier.d.ts.map +1 -1
  328. package/dist/engine/verifier.js +114 -1
  329. package/dist/engine/verifier.js.map +1 -1
  330. package/dist/engine/workflow_contract_registry.d.ts +70 -0
  331. package/dist/engine/workflow_contract_registry.d.ts.map +1 -0
  332. package/dist/engine/workflow_contract_registry.js +501 -0
  333. package/dist/engine/workflow_contract_registry.js.map +1 -0
  334. package/dist/engine/workspace_resumer.d.ts.map +1 -1
  335. package/dist/engine/workspace_resumer.js +8 -0
  336. package/dist/engine/workspace_resumer.js.map +1 -1
  337. package/dist/engine/zero_config_init.d.ts +67 -2
  338. package/dist/engine/zero_config_init.d.ts.map +1 -1
  339. package/dist/engine/zero_config_init.js +410 -28
  340. package/dist/engine/zero_config_init.js.map +1 -1
  341. package/dist/git/operations.d.ts +101 -0
  342. package/dist/git/operations.d.ts.map +1 -1
  343. package/dist/git/operations.js +125 -9
  344. package/dist/git/operations.js.map +1 -1
  345. package/dist/index.d.ts +1 -1
  346. package/dist/index.js +16 -5
  347. package/dist/index.js.map +1 -1
  348. package/dist/knowledge/conflict_detector.d.ts +6 -0
  349. package/dist/knowledge/conflict_detector.d.ts.map +1 -1
  350. package/dist/knowledge/conflict_detector.js +7 -0
  351. package/dist/knowledge/conflict_detector.js.map +1 -1
  352. package/dist/knowledge/health_checker.d.ts +16 -0
  353. package/dist/knowledge/health_checker.d.ts.map +1 -1
  354. package/dist/knowledge/health_checker.js +24 -1
  355. package/dist/knowledge/health_checker.js.map +1 -1
  356. package/dist/knowledge/index_manager.d.ts +140 -2
  357. package/dist/knowledge/index_manager.d.ts.map +1 -1
  358. package/dist/knowledge/index_manager.js +186 -26
  359. package/dist/knowledge/index_manager.js.map +1 -1
  360. package/dist/knowledge/loader.d.ts +8 -1
  361. package/dist/knowledge/loader.d.ts.map +1 -1
  362. package/dist/knowledge/loader.js +56 -2
  363. package/dist/knowledge/loader.js.map +1 -1
  364. package/dist/knowledge/writer.d.ts +49 -1
  365. package/dist/knowledge/writer.d.ts.map +1 -1
  366. package/dist/knowledge/writer.js +55 -1
  367. package/dist/knowledge/writer.js.map +1 -1
  368. package/dist/types.d.ts +255 -1
  369. package/dist/types.d.ts.map +1 -1
  370. package/dist/utils/logger.d.ts +3 -0
  371. package/dist/utils/logger.d.ts.map +1 -0
  372. package/dist/utils/logger.js +29 -0
  373. package/dist/utils/logger.js.map +1 -0
  374. package/package.json +7 -7
  375. package/templates/knowledge/checklists//344/270/273/351/223/276/350/267/257/346/216/245/345/205/245/351/252/214/346/224/266/346/270/205/345/215/225.md +16 -0
  376. package/templates/knowledge/checklists//345/267/245/344/275/234/346/265/201/351/252/214/346/224/266/346/270/205/345/215/225.md +17 -0
  377. package/templates/knowledge/checklists//346/240/270/345/277/203/345/267/245/347/250/213/346/211/247/350/241/214/351/252/214/346/224/266/346/270/205/345/215/225.md +43 -0
  378. package/templates/knowledge/checklists//347/237/245/350/257/206/346/263/250/345/205/245/351/252/214/346/224/266/346/270/205/345/215/225.md +17 -0
  379. package/templates/knowledge/checklists//351/232/220/347/247/201/345/256/241/346/237/245/346/270/205/345/215/225.md +15 -0
  380. package/templates/knowledge/checklists//351/252/214/350/257/201/351/252/214/346/224/266/346/270/205/345/215/225.md +16 -0
  381. package/templates/knowledge/patterns/core//345/206/263/347/255/226/347/275/221/345/205/263.md +1 -0
  382. package/templates/knowledge/procedures//344/270/273/351/223/276/350/267/257/346/216/245/345/205/245/351/252/214/350/257/201/346/265/201/347/250/213.md +23 -0
  383. package/templates/knowledge/procedures//345/221/275/344/273/244/346/211/247/350/241/214/346/265/201/347/250/213.md +19 -0
  384. package/templates/knowledge/procedures//345/267/245/345/205/267/350/260/203/347/224/250/346/265/201/347/250/213.md +15 -0
  385. package/templates/knowledge/procedures//346/204/217/345/233/276/350/267/257/347/224/261/346/265/201/347/250/213.md +15 -0
  386. package/templates/knowledge/procedures//346/272/220/347/240/201/345/216/237/345/236/213/344/272/244/344/273/230/346/265/201/347/250/213.md +1 -1
  387. package/templates/knowledge/procedures//347/274/226/347/240/201/345/211/215/346/276/204/346/270/205/346/265/201/347/250/213.md +53 -0
  388. package/templates/knowledge/rules//344/272/247/347/211/251/345/245/221/347/272/246/350/247/204/345/210/231.md +21 -0
  389. package/templates/knowledge/rules//345/221/275/344/273/244/346/211/247/350/241/214/350/247/204/345/210/231.md +25 -0
  390. package/templates/knowledge/rules//345/267/245/344/275/234/346/265/201/345/245/221/347/272/246/350/247/204/345/210/231.md +20 -0
  391. package/templates/knowledge/rules//345/267/245/345/205/267/350/260/203/347/224/250/350/247/204/345/210/231.md +25 -0
  392. package/templates/knowledge/rules//346/204/217/345/233/276/350/267/257/347/224/261/350/247/204/345/210/231.md +26 -0
  393. package/templates/knowledge/rules//346/211/247/350/241/214/345/256/210/345/215/253/350/257/204/344/274/260/350/247/204/345/210/231.md +24 -0
  394. package/templates/knowledge/rules//346/225/217/346/204/237/344/277/241/346/201/257/345/244/204/347/220/206/350/247/204/345/210/231.md +20 -0
  395. package/templates/knowledge/rules//346/240/270/345/277/203/345/267/245/347/250/213/346/211/247/350/241/214/345/216/237/345/210/231.md +125 -0
  396. package/templates/knowledge/rules//346/263/250/345/206/214/350/241/250/345/237/272/347/241/200/350/256/276/346/226/275/350/247/204/345/210/231.md +26 -0
  397. 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 +22 -0
  398. package/templates/knowledge/rules//347/237/245/350/257/206/346/263/250/345/205/245/350/276/271/347/225/214/350/247/204/345/210/231.md +25 -0
  399. package/templates/knowledge/rules//350/276/223/345/205/245/346/235/220/346/226/231/345/245/221/347/272/246/350/247/204/345/210/231.md +27 -0
  400. package/templates/knowledge/rules//351/205/215/347/275/256/344/274/230/345/205/210/347/272/247/350/247/204/345/210/231.md +22 -0
  401. package/templates/knowledge/rules//351/230/262/345/255/244/345/262/233/345/256/236/347/216/260/350/247/204/345/210/231.md +24 -0
  402. package/templates/knowledge/rules//351/233/266/351/205/215/347/275/256/345/210/235/345/247/213/345/214/226/350/247/204/345/210/231.md +28 -0
  403. package/templates/knowledge/rules//351/252/214/350/257/201/345/245/221/347/272/246/350/247/204/345/210/231.md +25 -0
  404. package/templates/knowledge/templates/{review_summary.md → /345/256/241/346/237/245/346/221/230/350/246/201.md} +1 -1
  405. package/templates/config.yaml +0 -53
@@ -1,7 +1,10 @@
1
1
  import { z } from "zod";
2
2
  import path from "node:path";
3
3
  import fss from "node:fs";
4
+ import crypto from "node:crypto";
5
+ import { findToolInvocationContractByName, createToolTrace, validateToolInvocation, } from "../../engine/tool_invocation_contract_registry.js";
4
6
  import { classify } from "../../engine/classifier.js";
7
+ import { shouldEnterSoloForge } from "../../engine/intent_router.js";
5
8
  import { expand } from "../../engine/intent_expander.js";
6
9
  import { generateVerifyCommands } from "../../engine/verifier.js";
7
10
  import { evolve } from "../../engine/evolver.js";
@@ -21,6 +24,7 @@ import { checkFeasibility } from "../../engine/feasibility_checker.js";
21
24
  import { debugError } from "../../engine/debugger.js";
22
25
  import { generateReport } from "../../engine/observability.js";
23
26
  import { generateReport as generateGovernanceReport } from "../../engine/governance_report.js";
27
+ import { resolveCurrentProjectConfigReports } from "../../engine/config_precedence_contract.js";
24
28
  import { analyzeMigration } from "../../engine/migration_guard.js";
25
29
  import { generateTestGuide } from "../../engine/test_generator.js";
26
30
  import { analyzeTestQuality } from "../../engine/test_quality.js";
@@ -39,6 +43,10 @@ import { EscapeReportStore } from "../../engine/escape_report.js";
39
43
  import { sampleAuditItems } from "../../engine/audit_sampler.js";
40
44
  import { decideAction } from "../../engine/capability_action_advisor.js";
41
45
  import { CapabilityStateStore } from "../../engine/capability_state_store.js";
46
+ import { auditIntegration, buildMainPathIntegrationContracts, } from "../../engine/main_path_integration_contract.js";
47
+ import { validateMechanismLayerMaps, listMechanismLayerMaps, } from "../../engine/dual_layer_mechanism_registry.js";
48
+ import { classifyIngestionStatus } from "../../engine/input_material_contract_registry.js";
49
+ import { verifyArtifact, } from "../../engine/artifact_contract_registry.js";
42
50
  // ── Zod Schema 定义 ──
43
51
  const ClassifySchema = {
44
52
  intent: z.string().describe("开发者意图描述"),
@@ -47,6 +55,7 @@ const ClassifySchema = {
47
55
  const ExpandSchema = {
48
56
  task_id: z.string().describe("sf_classify 返回的任务 ID"),
49
57
  clarification_answers: z.array(z.string()).optional().describe("对澄清问题的回答"),
58
+ input_material_confirmations: z.array(z.string()).optional().describe("已确认安全的输入材料路径列表"),
50
59
  };
51
60
  const VerifySchema = {
52
61
  task_id: z.string().describe("任务 ID"),
@@ -146,22 +155,277 @@ const ExploreSchema = {
146
155
  * @param server - MCP 服务器实例
147
156
  * @param deps - SoloForge 核心依赖项
148
157
  */
158
+ /**
159
+ * 注册所有 MCP 工具到服务器实例。
160
+ * @param server - McpServer 实例
161
+ * @param deps - 工具依赖项(配置、知识索引、任务上下文)
162
+ */
149
163
  export function registerTools(server, deps) {
164
+ console.error("[soloForge] 工具注册: 开始注册 MCP 工具...");
150
165
  const { config, knowledgeIndex, taskContext } = deps;
151
166
  const projectPath = config._projectPath || process.cwd();
152
167
  // H1: LLM Gateway — Token 预算熔断,防止单任务 Token 超支
153
168
  const gateway = deps.gateway ?? new LLMGateway();
154
169
  // H4: IO Controller — 工作区互斥锁,防止外部修改导致的静默覆盖
155
170
  const ioController = new IOController(projectPath);
156
- // 统一错误处理包装器,捕获工具执行中的异常并返回结构化错误响应
171
+ // ── 统一网关 : 唯一工具调用边界 ──
172
+ /** 计算 sf_status cancel 的动态 category */
173
+ function computeEffectiveCategory(toolName, args, contract) {
174
+ if (toolName === "sf_status" && (args.action === "cancel" || args.job_action === "job_cancel")) {
175
+ return "normal_controlled";
176
+ }
177
+ return contract.category;
178
+ }
179
+ /** 计算 sf_status cancel 的动态 side_effects */
180
+ function computeEffectiveSideEffects(toolName, args, contract) {
181
+ if (toolName === "sf_status" && (args.action === "cancel" || args.job_action === "job_cancel")) {
182
+ return ["task_context_write"];
183
+ }
184
+ return contract.side_effects;
185
+ }
186
+ /** State precheck: validate task status before contract guard */
187
+ const STATE_PRECHECKS = {
188
+ sf_verify: ["executing", "retrying"],
189
+ sf_learn: ["verifying", "executing"],
190
+ sf_expand: ["classifying", "expanding", "clarifying"],
191
+ };
192
+ const STATE_ERROR_LABELS = {
193
+ sf_verify: "不可验证",
194
+ sf_learn: "不可学习",
195
+ sf_expand: "不可膨胀",
196
+ };
197
+ /** 授权模型: explicit > dynamic write gate > destructive gate > workflow gate > category default */
198
+ function checkAuth(toolName, args, contract, ctx, effectiveCategory) {
199
+ // 1. Explicit confirmation
200
+ if (args.confirm === true || args.authorized === true || args.authorization_token) {
201
+ return { required: true, granted: true, reason: "explicit confirmation" };
202
+ }
203
+ // 2. Dynamic write upgrade: cancel/job_cancel from read_only to write → must confirm
204
+ if (effectiveCategory && effectiveCategory !== contract.category && effectiveCategory !== "read_only_bypass") {
205
+ return { required: true, granted: false, reason: "dynamic write upgrade requires explicit confirmation" };
206
+ }
207
+ // 3. Destructive side effects always require explicit
208
+ const destructive = ["git_commit", "git_push", "pr_create", "external_write"];
209
+ if (contract.side_effects.some((e) => destructive.includes(e))) {
210
+ return { required: true, granted: false, reason: "destructive side effects require explicit confirmation" };
211
+ }
212
+ // 4. Standalone strict tools (no workflow required, no task context) → handler does own checks
213
+ if (contract.category === "strict_controlled" && !ctx && !contract.requires_workflow) {
214
+ return { required: false, granted: true, reason: "standalone strict tool" };
215
+ }
216
+ // 5. Workflow contract gate for strict_controlled
217
+ if (contract.category === "strict_controlled" && ctx?.last_tool_trace) {
218
+ const allowed = ctx.last_tool_trace.next_allowed_tools ?? [];
219
+ if (allowed.includes(toolName)) {
220
+ return { required: true, granted: true, reason: "workflow contract gate" };
221
+ }
222
+ }
223
+ // 5b. State-based fallback: strict tool with valid-state task but no tool_trace
224
+ if (contract.category === "strict_controlled" && ctx && !ctx.last_tool_trace && contract.requires_workflow) {
225
+ const validStates = STATE_PRECHECKS[toolName];
226
+ if (validStates && validStates.includes(ctx.status)) {
227
+ return { required: true, granted: true, reason: "task in valid state for tool" };
228
+ }
229
+ }
230
+ // 5c. Non-strict tools: auto-grant unless requires_authorization
231
+ if (contract.category === "read_only_bypass" || contract.category === "normal_controlled") {
232
+ if (contract.requires_authorization) {
233
+ return { required: true, granted: false, reason: "tool requires explicit authorization" };
234
+ }
235
+ return { required: false, granted: true, reason: "non-strict category" };
236
+ }
237
+ return { required: true, granted: false, reason: "no authorization source" };
238
+ }
157
239
  function registerSafeTool(name, desc, schema, handler) {
158
240
  server.tool(name, desc, schema, async (args) => {
241
+ const invocationId = `inv-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
242
+ const taskId = args.task_id;
243
+ const contract = findToolInvocationContractByName(name);
244
+ // No contract → hard fail
245
+ if (!contract) {
246
+ return {
247
+ content: [{ type: "text", text: JSON.stringify({ error: `工具 ${name} 未注册契约` }) }],
248
+ isError: true,
249
+ };
250
+ }
251
+ const effectiveCategory = computeEffectiveCategory(name, args, contract);
252
+ const effectiveSideEffects = computeEffectiveSideEffects(name, args, contract);
253
+ // Load TaskContext
254
+ let ctx = null;
255
+ if (taskId) {
256
+ ctx = await taskContext.load(taskId);
257
+ }
258
+ // State precheck: validate task status before contract guard
259
+ if (taskId && STATE_PRECHECKS[name] && ctx) {
260
+ const validStates = STATE_PRECHECKS[name];
261
+ if (!validStates.includes(ctx.status)) {
262
+ const label = STATE_ERROR_LABELS[name] ?? "状态不正确";
263
+ return {
264
+ content: [{ type: "text", text: JSON.stringify({
265
+ error: `任务状态 ${ctx.status} ${label},需要 ${validStates.join(" 或 ")}`,
266
+ status: ctx.status,
267
+ }) }],
268
+ isError: true,
269
+ };
270
+ }
271
+ }
272
+ // Strict controlled without task_id
273
+ const isStandaloneStrict = !contract.requires_workflow;
274
+ if (contract.category === "strict_controlled" && !taskId && !isStandaloneStrict) {
275
+ return {
276
+ content: [{ type: "text", text: JSON.stringify({ error: `strict controlled 工具 ${name} 需要 task_id` }) }],
277
+ isError: true,
278
+ };
279
+ }
280
+ // Authorization
281
+ const authorization = checkAuth(name, args, contract, ctx ?? undefined, effectiveCategory);
282
+ // Authorization denied → hard fail for gateway-level denials only
283
+ // (dynamic write upgrade, destructive ops, strict_controlled with no auth source)
284
+ // Handler-level authorization (e.g. sf_capability_update confirm) is left to the handler
285
+ const gatewayDenial = !authorization.granted &&
286
+ authorization.reason !== "tool requires explicit authorization";
287
+ if (gatewayDenial) {
288
+ const blockedTrace = createToolTrace({
289
+ tool_name: name, invocation_id: invocationId, task_id: taskId,
290
+ actual_side_effects: effectiveSideEffects,
291
+ next_allowed_tools: contract.default_next_tools,
292
+ forbidden_tools: contract.forbidden_next_tools,
293
+ authorization, bypass: undefined,
294
+ });
295
+ const authViolation = {
296
+ invocation_id: invocationId, tool_name: name,
297
+ violation_type: "missing_authorization", severity: "hard_fail",
298
+ reason: authorization.reason ?? "authorization denied",
299
+ recovery: "提供 confirm=true / authorized=true / authorization_token",
300
+ };
301
+ if (taskId && ctx) {
302
+ await taskContext.setToolTrace(taskId, blockedTrace, [authViolation]);
303
+ }
304
+ return {
305
+ content: [{ type: "text", text: JSON.stringify({
306
+ error: authViolation.reason, violation: authViolation,
307
+ tool_trace: blockedTrace,
308
+ next_allowed_tools: contract.default_next_tools,
309
+ forbidden_tools: contract.forbidden_next_tools,
310
+ }) }],
311
+ isError: true,
312
+ };
313
+ }
314
+ // Bypass for read_only_bypass
315
+ const bypass = effectiveCategory === "read_only_bypass"
316
+ ? { allowed: true, reason: "read_only" } : undefined;
317
+ // Contract validation
318
+ const lastTrace = ctx?.last_tool_trace;
319
+ // Build effective contract override for dynamic tools (e.g., sf_status cancel)
320
+ let contractOverride;
321
+ if (effectiveCategory !== contract.category || effectiveSideEffects !== contract.side_effects) {
322
+ contractOverride = { ...contract, category: effectiveCategory, side_effects: effectiveSideEffects };
323
+ }
324
+ // Workflow ID: only from real expansion trace
325
+ const explicitWorkflowId = ctx?.expansion?.workflow_trace?.workflow_id;
326
+ const violations = validateToolInvocation({
327
+ tool_name: name,
328
+ current_next_allowed: lastTrace?.next_allowed_tools ?? [],
329
+ current_forbidden: lastTrace?.forbidden_tools ?? [],
330
+ authorization,
331
+ bypass,
332
+ actual_side_effects: effectiveSideEffects,
333
+ workflow_id: explicitWorkflowId,
334
+ _contractOverride: contractOverride,
335
+ });
336
+ // State-based fallback: downgrade contract_state_mismatch from hard_fail to require_human
337
+ if (authorization.reason === "task in valid state for tool") {
338
+ for (const v of violations) {
339
+ if (v.violation_type === "contract_state_mismatch" && v.severity === "hard_fail") {
340
+ v.severity = "require_human";
341
+ v.reason += " (state-based fallback: no real workflow_id)";
342
+ }
343
+ }
344
+ }
345
+ // Hard-fail violations → block
346
+ const hardFail = violations.find(v => v.severity === "hard_fail");
347
+ if (hardFail) {
348
+ const blockedTrace = createToolTrace({
349
+ tool_name: name, invocation_id: invocationId, task_id: taskId,
350
+ actual_side_effects: effectiveSideEffects,
351
+ next_allowed_tools: contract.default_next_tools,
352
+ forbidden_tools: contract.forbidden_next_tools,
353
+ authorization, bypass,
354
+ });
355
+ if (taskId && ctx) {
356
+ await taskContext.setToolTrace(taskId, blockedTrace, violations);
357
+ }
358
+ return {
359
+ content: [{ type: "text", text: JSON.stringify({
360
+ error: hardFail.reason, violation: hardFail,
361
+ tool_trace: blockedTrace,
362
+ next_allowed_tools: contract.default_next_tools,
363
+ forbidden_tools: contract.forbidden_next_tools,
364
+ }) }],
365
+ isError: true,
366
+ };
367
+ }
368
+ // Execute handler
159
369
  try {
160
- return await handler(args);
370
+ const raw = await handler(args);
371
+ // Pass through if handler returned { content } directly
372
+ if (raw && typeof raw === "object" && "content" in raw && Array.isArray(raw.content)) {
373
+ return raw;
374
+ }
375
+ // Extract data from { result } pattern
376
+ const data = raw?.result !== undefined ? raw.result : raw;
377
+ const hasError = !!(data && typeof data === "object" && "error" in data);
378
+ // Build trace
379
+ const trace = createToolTrace({
380
+ tool_name: name, invocation_id: invocationId, task_id: taskId,
381
+ workflow_id: ctx?.expansion?.workflow_trace?.workflow_id,
382
+ actual_side_effects: effectiveSideEffects,
383
+ next_allowed_tools: contract.default_next_tools,
384
+ forbidden_tools: contract.forbidden_next_tools,
385
+ authorization, bypass,
386
+ });
387
+ // Write trace to TaskContext
388
+ if (taskId) {
389
+ await taskContext.setToolTrace(taskId, trace, violations.length > 0 ? violations : undefined);
390
+ }
391
+ // Decorate response with trace + next/forbidden
392
+ const response = {
393
+ ...data,
394
+ tool_trace: trace,
395
+ next_allowed_tools: contract.default_next_tools,
396
+ forbidden_tools: contract.forbidden_next_tools,
397
+ };
398
+ // State-based fallback: expose degraded workflow in response
399
+ if (authorization.reason === "task in valid state for tool") {
400
+ response.degraded_workflow = true;
401
+ response.workflow_source = "state-based-fallback";
402
+ }
403
+ return {
404
+ content: [{ type: "text", text: JSON.stringify(response, null, 2) }],
405
+ isError: hasError ? true : undefined,
406
+ };
161
407
  }
162
408
  catch (err) {
409
+ const errorTrace = createToolTrace({
410
+ tool_name: name, invocation_id: invocationId, task_id: taskId,
411
+ actual_side_effects: effectiveSideEffects,
412
+ next_allowed_tools: contract.default_next_tools,
413
+ forbidden_tools: contract.forbidden_next_tools,
414
+ authorization, bypass,
415
+ });
416
+ if (taskId) {
417
+ try {
418
+ await taskContext.setToolTrace(taskId, errorTrace);
419
+ }
420
+ catch { /* best effort */ }
421
+ }
163
422
  return {
164
- content: [{ type: "text", text: JSON.stringify({ error: err instanceof Error ? err.message : String(err) }) }],
423
+ content: [{ type: "text", text: JSON.stringify({
424
+ error: err instanceof Error ? err.message : String(err),
425
+ tool_trace: errorTrace,
426
+ next_allowed_tools: contract.default_next_tools,
427
+ forbidden_tools: contract.forbidden_next_tools,
428
+ }) }],
165
429
  isError: true,
166
430
  };
167
431
  }
@@ -169,6 +433,10 @@ export function registerTools(server, deps) {
169
433
  }
170
434
  // 加载认知锚点上下文 — 必须提供相关性参数,禁止全量加载
171
435
  function loadRelevantAnchors(query) {
436
+ console.error("[soloForge] 工具注册: 加载认知锚点");
437
+ return _loadRelevantAnchorsInner(query);
438
+ }
439
+ function _loadRelevantAnchorsInner(query) {
172
440
  const stateDir = taskContext.getStateDir();
173
441
  const mapPath = path.join(stateDir, "cognitive.map.json");
174
442
  const mapData = readMapJson(mapPath);
@@ -219,61 +487,52 @@ export function registerTools(server, deps) {
219
487
  stale_anchor: a.stale_anchor,
220
488
  }));
221
489
  }
490
+ console.error("[soloForge] 工具注册: 批量注册核心/辅助/知识维护工具...");
222
491
  // ── sf_classify: 意图分类入口,创建任务上下文并返回分类结果 ──
223
492
  registerSafeTool("sf_classify", "分析开发者意图,返回任务类型、风险、复杂度和执行策略", ClassifySchema, async (args) => {
224
493
  // 检查是否存在进行中的任务
225
494
  const existing = await taskContext.getCurrentTask();
226
495
  if (existing && !["done", "failed"].includes(existing.status)) {
227
496
  return {
228
- content: [{
229
- type: "text",
230
- text: JSON.stringify({
231
- warning: "存在未完成的任务",
232
- existing_task_id: existing.task_id,
233
- existing_status: existing.status,
234
- existing_intent: existing.intent,
235
- hint: "调用 sf_status action=cancel 取消旧任务,或继续完成它",
236
- }),
237
- }],
238
- isError: true,
497
+ result: {
498
+ error: "存在未完成的任务",
499
+ warning: "存在未完成的任务",
500
+ existing_task_id: existing.task_id,
501
+ existing_status: existing.status,
502
+ existing_intent: existing.intent,
503
+ hint: "调用 sf_status action=cancel 取消旧任务,或继续完成它",
504
+ },
239
505
  };
240
506
  }
241
507
  // 创建任务上下文
242
508
  const ctx = await taskContext.create(args.intent, config.product_profile);
243
- const input = { intent: args.intent, project_path: projectPath };
509
+ const input = { intent: args.intent, project_path: projectPath, task_id: ctx.task_id };
244
510
  const classification = classify(input);
245
511
  // 存储分类结果
246
512
  await taskContext.setClassification(ctx.task_id, classification);
247
- if (classification.strategy === "skip_soloForge") {
513
+ if (!shouldEnterSoloForge(classification.route_decision)) {
248
514
  await taskContext.updateStatus(ctx.task_id, "done");
249
515
  }
250
516
  return {
251
- content: [{
252
- type: "text",
253
- text: JSON.stringify({
254
- task_id: ctx.task_id,
255
- ...classification,
256
- }, null, 2),
257
- }],
517
+ result: {
518
+ task_id: ctx.task_id,
519
+ ...classification,
520
+ },
258
521
  };
259
522
  });
260
523
  // ── sf_expand: 意图膨胀,生成结构化 prompt 并注入计划上下文 ──
261
524
  registerSafeTool("sf_expand", "将意图膨胀为结构化 prompt,包含 scope、验收标准和知识匹配。当存在计划时自动注入当前阶段上下文和输出模板", ExpandSchema, async (args) => {
262
525
  const ctx = await taskContext.load(args.task_id);
263
526
  if (!ctx || !ctx.classification) {
264
- return {
265
- content: [{ type: "text", text: JSON.stringify({ error: "任务不存在或尚未分类,请先调用 sf_classify" }) }],
266
- isError: true,
267
- };
527
+ return { result: { error: "任务不存在或尚未分类,请先调用 sf_classify" } };
268
528
  }
269
- // 状态守卫:classifying → expanding 或允许 expanding 恢复(中断重试)
270
- if (ctx.status === "classifying") {
529
+ // 状态守卫:classifying/expanding/clarifying → expanding
530
+ if (ctx.status === "classifying" || ctx.status === "clarifying") {
271
531
  await taskContext.updateStatus(args.task_id, "expanding");
272
532
  }
273
533
  else if (ctx.status !== "expanding") {
274
534
  return {
275
- content: [{ type: "text", text: JSON.stringify({ error: `任务状态 ${ctx.status} 不可膨胀,需要 classifying 或 expanding`, status: ctx.status }) }],
276
- isError: true,
535
+ result: { error: `任务状态 ${ctx.status} 不可膨胀,需要 classifying 或 expanding`, status: ctx.status },
277
536
  };
278
537
  }
279
538
  // 构建计划上下文(如果存在计划)
@@ -324,7 +583,10 @@ export function registerTools(server, deps) {
324
583
  config,
325
584
  knowledgeIndex,
326
585
  clarificationAnswers: args.clarification_answers,
586
+ route_decision: ctx.classification?.route_decision,
327
587
  plan_context: planContext,
588
+ input_material_confirmations: args.input_material_confirmations,
589
+ task_id: args.task_id,
328
590
  });
329
591
  }
330
592
  catch (expandErr) {
@@ -343,12 +605,26 @@ export function registerTools(server, deps) {
343
605
  gateway.endTask();
344
606
  }
345
607
  expansion.task_id = args.task_id;
608
+ // Input Material Contract: 处理 hard-blocking 结果
609
+ // Privacy Gate: 隐私/敏感信息策略阻断
610
+ const isBlocked = expansion.prompt.startsWith("## 阻塞:输入材料禁止读取")
611
+ || expansion.prompt.startsWith("## 阻塞:隐私/敏感信息策略");
612
+ const isMaterialClarification = expansion.prompt.startsWith("## 澄清请求") && expansion.input_materials?.some((m) => m.access_mode !== "forbidden" && classifyIngestionStatus(m.path_or_ref) === "requires_confirmation");
346
613
  // 注入 H1/H4 advisory warnings
347
614
  const advisories = {};
348
615
  if (h1Warning)
349
616
  advisories.h1_advisory = h1Warning;
350
617
  if (h4LockWarning)
351
618
  advisories.h4_advisory = h4LockWarning;
619
+ // Config precedence warnings
620
+ if (expansion.config_resolution_reports && expansion.config_resolution_reports.length > 0) {
621
+ const configWarnings = expansion.config_resolution_reports
622
+ .filter(r => r.conflicts.length > 0)
623
+ .map(r => r.conflicts.map(c => `${c.reason}`).join("; "));
624
+ if (configWarnings.length > 0) {
625
+ advisories.config_precedence_warnings = configWarnings;
626
+ }
627
+ }
352
628
  // 决策契约 advisory: 校验 expand 输出是否包含默认决策字段
353
629
  const decisionContract = validateDecisionOutput(expansion);
354
630
  if (!decisionContract.passed) {
@@ -357,6 +633,10 @@ export function registerTools(server, deps) {
357
633
  // 存储膨胀结果
358
634
  try {
359
635
  await taskContext.setExpansion(args.task_id, expansion);
636
+ // 存储产物记录
637
+ if (expansion.output_artifact_record) {
638
+ await taskContext.setArtifact(args.task_id, expansion.output_artifact_record);
639
+ }
360
640
  }
361
641
  catch (setErr) {
362
642
  try {
@@ -367,9 +647,17 @@ export function registerTools(server, deps) {
367
647
  }
368
648
  throw setErr;
369
649
  }
370
- // 转换到执行阶段
650
+ // 转换到下一阶段:blocked → failed, clarification → clarifying, else → executing
371
651
  try {
372
- await taskContext.updateStatus(args.task_id, "executing");
652
+ if (isBlocked) {
653
+ await taskContext.updateStatus(args.task_id, "failed");
654
+ }
655
+ else if (expansion.prompt.startsWith("## 澄清请求")) {
656
+ await taskContext.updateStatus(args.task_id, "clarifying");
657
+ }
658
+ else {
659
+ await taskContext.updateStatus(args.task_id, "executing");
660
+ }
373
661
  }
374
662
  catch (updateErr) {
375
663
  try {
@@ -380,11 +668,11 @@ export function registerTools(server, deps) {
380
668
  }
381
669
  throw updateErr;
382
670
  }
671
+ const expandPayload = Object.keys(advisories).length > 0
672
+ ? { ...expansion, advisories }
673
+ : expansion;
383
674
  return {
384
- content: [{
385
- type: "text",
386
- text: JSON.stringify(Object.keys(advisories).length > 0 ? { ...expansion, advisories } : expansion, null, 2),
387
- }],
675
+ result: expandPayload,
388
676
  };
389
677
  });
390
678
  // ── sf_verify: 生成验证命令(构建、测试、验收检查) ──
@@ -392,15 +680,13 @@ export function registerTools(server, deps) {
392
680
  const ctx = await taskContext.load(args.task_id);
393
681
  if (!ctx) {
394
682
  return {
395
- content: [{ type: "text", text: JSON.stringify({ error: "任务不存在" }) }],
396
- isError: true,
683
+ result: { error: "任务不存在" },
397
684
  };
398
685
  }
399
686
  const VALID_VERIFY_STATES = ["executing", "retrying"];
400
687
  if (!VALID_VERIFY_STATES.includes(ctx.status)) {
401
688
  return {
402
- content: [{ type: "text", text: JSON.stringify({ error: `任务状态 ${ctx.status} 不可验证,需要 executing 或 retrying`, status: ctx.status }) }],
403
- isError: true,
689
+ result: { error: `任务状态 ${ctx.status} 不可验证,需要 executing 或 retrying`, status: ctx.status },
404
690
  };
405
691
  }
406
692
  const acceptanceItems = ctx.expansion
@@ -411,14 +697,68 @@ export function registerTools(server, deps) {
411
697
  const h4Warning = !integrity.clean
412
698
  ? { warning: `H4 advisory: ${integrity.message}`, dirty_files: integrity.dirty_files }
413
699
  : undefined;
414
- const verifyResult = generateVerifyCommands(config, args.changed_files, acceptanceItems);
700
+ const verifyResult = generateVerifyCommands(config, args.changed_files, acceptanceItems, ctx?.expansion?.workflow_trace?.route);
415
701
  verifyResult.task_id = args.task_id;
702
+ // Artifact lifecycle check : draft → verified requires ArtifactVerificationResult.passed
703
+ let artifactVerificationResult;
704
+ let artifactFileMissing = false;
705
+ if (ctx.artifact_output && ctx.artifact_output.status === "draft") {
706
+ // Resolve artifact file and compute hash before verification
707
+ const artifact = ctx.artifact_output;
708
+ const fullPath = path.join(projectPath, artifact.path);
709
+ if (fss.existsSync(fullPath)) {
710
+ const fileContent = fss.readFileSync(fullPath);
711
+ const hash = crypto.createHash("sha256").update(fileContent).digest("hex");
712
+ artifact.hash = `sha256:${hash}`;
713
+ if (!artifact.evidence_refs.some(r => r.startsWith("file:artifact:"))) {
714
+ artifact.evidence_refs.push(`file:artifact:path=${artifact.path} hash=sha256:${hash}`);
715
+ }
716
+ // Save updated artifact with hash
717
+ const ctxForHash = await taskContext.load(args.task_id);
718
+ if (ctxForHash?.artifact_output) {
719
+ ctxForHash.artifact_output.hash = artifact.hash;
720
+ if (!ctxForHash.artifact_output.evidence_refs.some(r => r.startsWith("file:artifact:"))) {
721
+ ctxForHash.artifact_output.evidence_refs.push(`file:artifact:path=${artifact.path} hash=sha256:${hash}`);
722
+ }
723
+ await taskContext.save(ctxForHash);
724
+ }
725
+ }
726
+ else {
727
+ artifactFileMissing = true;
728
+ }
729
+ artifactVerificationResult = verifyArtifact(artifact.kind, artifact);
730
+ }
416
731
  // 记录变更文件
417
732
  await taskContext.setExecution(args.task_id, args.changed_files);
733
+ // Mark no_change_artifact when no real files changed but artifact exists
734
+ if (args.changed_files.length === 0 && ctx.artifact_output) {
735
+ const execCtx = await taskContext.load(args.task_id);
736
+ if (execCtx?.execution) {
737
+ execCtx.execution.no_change_artifact = true;
738
+ await taskContext.save(execCtx);
739
+ }
740
+ }
418
741
  // 生成验证命令成功后再转换状态,避免操作失败导致任务卡在 verifying
742
+ if (ctx.status === "retrying") {
743
+ await taskContext.updateStatus(args.task_id, "executing");
744
+ }
419
745
  await taskContext.updateStatus(args.task_id, "verifying");
420
746
  // 存储验证结果
421
747
  await taskContext.setVerification(args.task_id, verifyResult);
748
+ // Artifact lifecycle transition: draft → verified only if ArtifactVerificationResult.passed
749
+ if (ctx.artifact_output && ctx.artifact_output.status === "draft" && artifactVerificationResult?.passed) {
750
+ const evidenceRef = `verification:${ctx.task_id}:checks=${artifactVerificationResult.checks.length}:summary=${artifactVerificationResult.summary.slice(0, 60)}`;
751
+ try {
752
+ await taskContext.updateArtifactStatus(args.task_id, {
753
+ status: "verified",
754
+ evidenceRef,
755
+ hasVerification: true,
756
+ });
757
+ }
758
+ catch {
759
+ // Transition blocked — artifact stays draft, pipeline continues
760
+ }
761
+ }
422
762
  // 认知锚点上下文回放(按变更文件相关性)
423
763
  const verifyAnchors = loadRelevantAnchors({ file_paths: args.changed_files });
424
764
  const verifyExtras = {};
@@ -426,11 +766,18 @@ export function registerTools(server, deps) {
426
766
  verifyExtras.h4_advisory = h4Warning;
427
767
  if (verifyAnchors && verifyAnchors.length > 0)
428
768
  verifyExtras.cognitive_anchors = verifyAnchors;
769
+ if (ctx.artifact_output && ctx.artifact_output.status === "draft" && artifactVerificationResult && !artifactVerificationResult.passed) {
770
+ const reason = artifactFileMissing
771
+ ? `产物文件不存在 (${ctx.artifact_output.path}),无法计算 hash`
772
+ : artifactVerificationResult.summary;
773
+ verifyExtras.artifact_warning = `产物验收检查未通过: ${reason}`;
774
+ verifyExtras.artifact_verification = artifactVerificationResult;
775
+ }
776
+ const verifyPayload = Object.keys(verifyExtras).length > 0
777
+ ? { ...verifyResult, ...verifyExtras }
778
+ : verifyResult;
429
779
  return {
430
- content: [{
431
- type: "text",
432
- text: JSON.stringify(Object.keys(verifyExtras).length > 0 ? { ...verifyResult, ...verifyExtras } : verifyResult, null, 2),
433
- }],
780
+ result: verifyPayload,
434
781
  };
435
782
  });
436
783
  // ── sf_learn: 从执行结果中提取知识,支持重试循环控制 ──
@@ -438,15 +785,13 @@ export function registerTools(server, deps) {
438
785
  const ctx = await taskContext.load(args.task_id);
439
786
  if (!ctx) {
440
787
  return {
441
- content: [{ type: "text", text: JSON.stringify({ error: "任务不存在" }) }],
442
- isError: true,
788
+ result: { error: "任务不存在" },
443
789
  };
444
790
  }
445
791
  const VALID_LEARN_STATES = ["verifying", "executing"];
446
792
  if (!VALID_LEARN_STATES.includes(ctx.status)) {
447
793
  return {
448
- content: [{ type: "text", text: JSON.stringify({ error: `任务状态 ${ctx.status} 不可学习,需要 verifying 或 executing`, status: ctx.status }) }],
449
- isError: true,
794
+ result: { error: `任务状态 ${ctx.status} 不可学习,需要 verifying 或 executing`, status: ctx.status },
450
795
  };
451
796
  }
452
797
  // 如适用,记录失败
@@ -478,15 +823,28 @@ export function registerTools(server, deps) {
478
823
  learnResult.retry_hint = `第 ${attemptCount}/${maxAttempts} 次尝试失败,${args.failure_type === "scope_insufficient" ? "需要扩大范围" : "请修复后重试"}`;
479
824
  }
480
825
  else {
481
- // 最终: 转换到完成(或所有重试耗尽后标记为失败)
482
- const finalStatus = args.result === "failure" ? "failed" : "done";
826
+ // 检查主链路集成 — 即使 build/test 全绿,孤岛仍阻断 done
827
+ const integrationBlocked = ctx.verification?.main_path_integration
828
+ && !ctx.verification.main_path_integration.passed;
829
+ // 核心工程执行原则门禁 — required 原则失败不能进入 completed
830
+ const principlesBlocked = ctx.verification?.core_principles
831
+ && !ctx.verification.core_principles.overall_passed;
832
+ const finalStatus = args.result === "failure"
833
+ ? "failed"
834
+ : (integrationBlocked || principlesBlocked) ? "retrying" : "done";
483
835
  await taskContext.updateStatus(args.task_id, finalStatus);
836
+ if (integrationBlocked && finalStatus === "retrying") {
837
+ learnResult.retry_hint = "主链路集成检查失败: 存在孤岛模块,请接入主链路后重试";
838
+ }
839
+ if (principlesBlocked && finalStatus === "retrying") {
840
+ const failedPrinciples = ctx.verification.core_principles.principles
841
+ .filter((p) => p.status === "failed")
842
+ .map((p) => p.principle_id);
843
+ learnResult.retry_hint = `核心工程执行原则检查失败: ${failedPrinciples.join(", ")},请修复后重试`;
844
+ }
484
845
  }
485
846
  return {
486
- content: [{
487
- type: "text",
488
- text: JSON.stringify(learnResult, null, 2),
489
- }],
847
+ result: learnResult,
490
848
  };
491
849
  });
492
850
  // ── sf_status: 任务状态查询(current/recent/resume/cancel) ──
@@ -496,8 +854,7 @@ export function registerTools(server, deps) {
496
854
  if (args.job_action) {
497
855
  if (!args.job_id) {
498
856
  return {
499
- content: [{ type: "text", text: JSON.stringify({ error: "job 操作需要 job_id" }) }],
500
- isError: true,
857
+ result: { error: "job 操作需要 job_id" },
501
858
  };
502
859
  }
503
860
  const jm = new JobManager(taskContext.getStateDir());
@@ -506,47 +863,39 @@ export function registerTools(server, deps) {
506
863
  const status = await jm.getJobStatus(args.job_id, taskId);
507
864
  if (!status) {
508
865
  return {
509
- content: [{ type: "text", text: JSON.stringify({ error: `job ${args.job_id} 不存在或已过期` }) }],
510
- isError: true,
866
+ result: { error: `job ${args.job_id} 不存在或已过期` },
511
867
  };
512
868
  }
513
869
  return {
514
- content: [{ type: "text", text: JSON.stringify({ job: status }, null, 2) }],
870
+ result: { job: status },
515
871
  };
516
872
  }
517
873
  if (args.job_action === "job_resume") {
518
874
  const checkpoint = await jm.resumeFromCheckpoint(args.job_id, taskId);
519
875
  if (!checkpoint) {
520
876
  return {
521
- content: [{ type: "text", text: JSON.stringify({ error: `job ${args.job_id} 无可恢复的 checkpoint` }) }],
522
- isError: true,
877
+ result: { error: `job ${args.job_id} 无可恢复的 checkpoint` },
523
878
  };
524
879
  }
525
880
  return {
526
- content: [{
527
- type: "text",
528
- text: JSON.stringify({
529
- advisory: "job 恢复为 advisory 操作,需确认 checkpoint 数据与当前状态一致",
530
- job_id: checkpoint.job_id,
531
- task_id: checkpoint.task_id,
532
- phase: checkpoint.phase,
533
- checkpoint_number: checkpoint.checkpoint_number,
534
- cognitive_anchor: checkpoint.cognitive_anchor,
535
- }, null, 2),
536
- }],
881
+ result: {
882
+ advisory: "job 恢复为 advisory 操作,需确认 checkpoint 数据与当前状态一致",
883
+ job_id: checkpoint.job_id,
884
+ task_id: checkpoint.task_id,
885
+ phase: checkpoint.phase,
886
+ checkpoint_number: checkpoint.checkpoint_number,
887
+ cognitive_anchor: checkpoint.cognitive_anchor,
888
+ },
537
889
  };
538
890
  }
539
891
  if (args.job_action === "job_cancel") {
540
892
  const removed = await jm.cancelJob(args.job_id, taskId);
541
893
  return {
542
- content: [{
543
- type: "text",
544
- text: JSON.stringify({
545
- advisory: "job 取消为 advisory 操作",
546
- job_id: args.job_id,
547
- cancelled: removed,
548
- }),
549
- }],
894
+ result: {
895
+ advisory: "job 取消为 advisory 操作",
896
+ job_id: args.job_id,
897
+ cancelled: removed,
898
+ },
550
899
  };
551
900
  }
552
901
  }
@@ -557,7 +906,7 @@ export function registerTools(server, deps) {
557
906
  : await taskContext.getCurrentTask();
558
907
  if (!ctx) {
559
908
  return {
560
- content: [{ type: "text", text: JSON.stringify({ message: "当前无活跃任务" }) }],
909
+ result: { message: "当前无活跃任务" },
561
910
  };
562
911
  }
563
912
  const resumable = taskContext.isResumable(ctx);
@@ -599,78 +948,61 @@ export function registerTools(server, deps) {
599
948
  // JobManager advisory — ignore errors
600
949
  }
601
950
  return {
602
- content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
951
+ result: result,
603
952
  };
604
953
  }
605
954
  case "recent": {
606
955
  const recent = await taskContext.listRecent(10);
607
956
  return {
608
- content: [{ type: "text", text: JSON.stringify({ tasks: recent }, null, 2) }],
957
+ result: { tasks: recent },
609
958
  };
610
959
  }
611
960
  case "resume": {
612
961
  if (!args.task_id) {
613
962
  return {
614
- content: [{ type: "text", text: JSON.stringify({ error: "恢复任务需要 task_id" }) }],
615
- isError: true,
963
+ result: { error: "恢复任务需要 task_id" },
616
964
  };
617
965
  }
618
966
  const ctx = await taskContext.load(args.task_id);
619
967
  if (!ctx) {
620
968
  return {
621
- content: [{ type: "text", text: JSON.stringify({ error: "任务不存在" }) }],
622
- isError: true,
969
+ result: { error: "任务不存在" },
623
970
  };
624
971
  }
625
972
  if (!taskContext.isResumable(ctx)) {
626
973
  return {
627
- content: [{ type: "text", text: JSON.stringify({ error: `任务状态 ${ctx.status} 不可恢复`, status: ctx.status }) }],
628
- isError: true,
974
+ result: { error: `任务状态 ${ctx.status} 不可恢复`, status: ctx.status },
629
975
  };
630
976
  }
631
- return {
632
- content: [{
633
- type: "text",
634
- text: JSON.stringify({
635
- task_id: ctx.task_id,
636
- intent: ctx.intent,
637
- status: ctx.status,
638
- resume_hint: taskContext.getResumeHint(ctx),
639
- classification: ctx.classification,
640
- expansion: ctx.expansion ? {
641
- scope: ctx.expansion.scope,
642
- matched_patterns: ctx.expansion.matched_patterns,
643
- } : undefined,
644
- execution: ctx.execution ? {
645
- changed_files: ctx.execution.changed_files,
646
- attempt_count: ctx.execution.attempt_count,
647
- } : undefined,
648
- cognitive_anchors: ctx.execution?.changed_files?.length
649
- ? loadRelevantAnchors({ file_paths: ctx.execution.changed_files })
650
- : undefined,
651
- }, null, 2),
652
- }],
977
+ const resumeResult = {
978
+ task_id: ctx.task_id,
979
+ intent: ctx.intent,
980
+ status: ctx.status,
981
+ resume_hint: taskContext.getResumeHint(ctx),
653
982
  };
983
+ if (ctx.execution)
984
+ resumeResult.execution = ctx.execution;
985
+ const resumeAnchors = ctx.execution?.changed_files
986
+ ? loadRelevantAnchors({ file_paths: ctx.execution.changed_files })
987
+ : undefined;
988
+ if (resumeAnchors && resumeAnchors.length > 0)
989
+ resumeResult.cognitive_anchors = resumeAnchors;
990
+ return { result: resumeResult };
654
991
  }
655
992
  case "cancel": {
656
993
  if (!args.task_id) {
657
994
  return {
658
- content: [{ type: "text", text: JSON.stringify({ error: "取消任务需要 task_id" }) }],
659
- isError: true,
995
+ result: { error: "取消任务需要 task_id" },
660
996
  };
661
997
  }
662
998
  const cancelled = await taskContext.cancel(args.task_id);
663
999
  return {
664
- content: [{
665
- type: "text",
666
- text: JSON.stringify({ task_id: args.task_id, cancelled }),
667
- }],
1000
+ result: { task_id: args.task_id, cancelled },
668
1001
  };
669
1002
  }
670
1003
  default:
671
1004
  return {
672
- content: [{ type: "text", text: JSON.stringify({ error: `未知操作: ${action}` }) }],
673
- isError: true,
1005
+ result: { error: `未知操作: ${action}` },
674
1006
  };
675
1007
  }
676
1008
  });
@@ -679,8 +1011,7 @@ export function registerTools(server, deps) {
679
1011
  const ctx = await taskContext.load(args.task_id);
680
1012
  if (!ctx?.classification) {
681
1013
  return {
682
- content: [{ type: "text", text: JSON.stringify({ error: "任务不存在或尚未分类" }) }],
683
- isError: true,
1014
+ result: { error: "任务不存在或尚未分类" },
684
1015
  };
685
1016
  }
686
1017
  const result = planTask({
@@ -692,7 +1023,7 @@ export function registerTools(server, deps) {
692
1023
  result.task_id = args.task_id;
693
1024
  await taskContext.setPlanning(args.task_id, result);
694
1025
  return {
695
- content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
1026
+ result: result,
696
1027
  };
697
1028
  });
698
1029
  // ── sf_plan_advance: 推进多阶段计划到下一步 ──
@@ -700,8 +1031,7 @@ export function registerTools(server, deps) {
700
1031
  const ctx = await taskContext.load(args.task_id);
701
1032
  if (!ctx?.planning || ctx.planning.sub_tasks.length === 0) {
702
1033
  return {
703
- content: [{ type: "text", text: JSON.stringify({ error: "任务没有多阶段计划,请先调用 sf_plan" }) }],
704
- isError: true,
1034
+ result: { error: "任务没有多阶段计划,请先调用 sf_plan" },
705
1035
  };
706
1036
  }
707
1037
  const plan = ctx.planning;
@@ -709,38 +1039,33 @@ export function registerTools(server, deps) {
709
1039
  const previousStepTitle = previousStep?.title ?? "未知";
710
1040
  const nextIndex = plan.current_step_index + 1;
711
1041
  if (nextIndex >= plan.sub_tasks.length) {
712
- return {
713
- content: [{ type: "text", text: JSON.stringify({
714
- task_id: args.task_id,
715
- previous_step: previousStepTitle,
716
- current_step_index: plan.current_step_index,
717
- total_steps: plan.sub_tasks.length,
718
- is_completed: true,
719
- message: `所有 ${plan.sub_tasks.length} 个阶段已完成`,
720
- }, null, 2) }],
721
- };
1042
+ return { result: {
1043
+ task_id: args.task_id,
1044
+ previous_step: previousStepTitle,
1045
+ current_step_index: plan.current_step_index,
1046
+ total_steps: plan.sub_tasks.length,
1047
+ is_completed: true,
1048
+ message: `所有 ${plan.sub_tasks.length} 个阶段已完成`,
1049
+ } };
722
1050
  }
723
1051
  // 推进阶段索引
724
1052
  plan.current_step_index = nextIndex;
725
1053
  await taskContext.setPlanning(args.task_id, plan);
726
1054
  const nextStep = plan.sub_tasks[nextIndex];
727
1055
  return {
728
- content: [{
729
- type: "text",
730
- text: JSON.stringify({
731
- task_id: args.task_id,
732
- previous_step: previousStepTitle,
733
- current_step_index: nextIndex,
734
- current_step: {
735
- id: nextStep.id,
736
- title: nextStep.title,
737
- output_path: nextStep.output_path,
738
- },
739
- total_steps: plan.sub_tasks.length,
740
- is_completed: false,
741
- message: `阶段推进: ${previousStepTitle} → ${nextStep.title}`,
742
- }, null, 2),
743
- }],
1056
+ result: {
1057
+ task_id: args.task_id,
1058
+ previous_step: previousStepTitle,
1059
+ current_step_index: nextIndex,
1060
+ current_step: {
1061
+ id: nextStep.id,
1062
+ title: nextStep.title,
1063
+ output_path: nextStep.output_path,
1064
+ },
1065
+ total_steps: plan.sub_tasks.length,
1066
+ is_completed: false,
1067
+ message: `阶段推进: ${previousStepTitle} → ${nextStep.title}`,
1068
+ },
744
1069
  };
745
1070
  });
746
1071
  // ── sf_analyze: 影响范围分析,建议是否扩大作用域 ──
@@ -748,8 +1073,7 @@ export function registerTools(server, deps) {
748
1073
  const ctx = await taskContext.load(args.task_id);
749
1074
  if (!ctx?.expansion) {
750
1075
  return {
751
- content: [{ type: "text", text: JSON.stringify({ error: "任务尚未膨胀,请先调用 sf_expand" }) }],
752
- isError: true,
1076
+ result: { error: "任务尚未膨胀,请先调用 sf_expand" },
753
1077
  };
754
1078
  }
755
1079
  const result = await analyzeImpact({
@@ -766,17 +1090,14 @@ export function registerTools(server, deps) {
766
1090
  if (!decisionContract.passed) {
767
1091
  advisoryExtras.decision_contract_advisory = decisionContract.advisory;
768
1092
  }
769
- return {
770
- content: [{ type: "text", text: JSON.stringify(Object.keys(advisoryExtras).length > 0 ? { ...result, ...advisoryExtras } : result, null, 2) }],
771
- };
1093
+ return { result: Object.keys(advisoryExtras).length > 0 ? { ...result, ...advisoryExtras } : result };
772
1094
  });
773
1095
  // ── sf_review: 代码审查(质量、安全、性能、技术债务) ──
774
1096
  registerSafeTool("sf_review", "审查代码变更的质量、安全、性能和技术债务。hotfix 场景可跳过。建议性,不强制修复", ReviewSchema, async (args) => {
775
1097
  const ctx = await taskContext.load(args.task_id);
776
1098
  if (!ctx) {
777
1099
  return {
778
- content: [{ type: "text", text: JSON.stringify({ error: "任务不存在" }) }],
779
- isError: true,
1100
+ result: { error: "任务不存在" },
780
1101
  };
781
1102
  }
782
1103
  const tracker = new DebtTracker(projectPath);
@@ -797,29 +1118,22 @@ export function registerTools(server, deps) {
797
1118
  if (!decisionContract.passed) {
798
1119
  reviewExtras.decision_contract_advisory = decisionContract.advisory;
799
1120
  }
800
- return {
801
- content: [{ type: "text", text: JSON.stringify(Object.keys(reviewExtras).length > 0 ? { ...result, ...reviewExtras } : result, null, 2) }],
802
- };
1121
+ return { result: Object.keys(reviewExtras).length > 0 ? { ...result, ...reviewExtras } : result };
803
1122
  });
804
1123
  // ── sf_scaffold: 生成标准化代码骨架 ──
805
1124
  registerSafeTool("sf_scaffold", "根据项目模板生成标准化代码骨架(Controller/Service/DTO/测试等)。仅在 task_type=scaffold 时使用", ScaffoldSchema, async (args) => {
806
1125
  const ctx = await taskContext.load(args.task_id);
807
1126
  if (!ctx?.classification) {
808
1127
  return {
809
- content: [{ type: "text", text: JSON.stringify({ error: "任务不存在或尚未分类" }) }],
810
- isError: true,
1128
+ result: { error: "任务不存在或尚未分类" },
811
1129
  };
812
1130
  }
813
1131
  if (ctx.classification.task_type !== "scaffold") {
814
1132
  return {
815
- content: [{
816
- type: "text",
817
- text: JSON.stringify({
818
- error: "sf_scaffold 仅适用于 scaffold 类型任务",
819
- current_type: ctx.classification.task_type,
820
- }),
821
- }],
822
- isError: true,
1133
+ result: {
1134
+ error: "sf_scaffold 仅适用于 scaffold 类型任务",
1135
+ current_type: ctx.classification.task_type,
1136
+ },
823
1137
  };
824
1138
  }
825
1139
  const result = await generateScaffold({
@@ -830,7 +1144,7 @@ export function registerTools(server, deps) {
830
1144
  });
831
1145
  result.task_id = args.task_id;
832
1146
  return {
833
- content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
1147
+ result: result,
834
1148
  };
835
1149
  });
836
1150
  // ── sf_deliver: 自动提交、推送、创建 PR ──
@@ -838,8 +1152,7 @@ export function registerTools(server, deps) {
838
1152
  const ctx = await taskContext.load(args.task_id);
839
1153
  if (!ctx) {
840
1154
  return {
841
- content: [{ type: "text", text: JSON.stringify({ error: "任务不存在" }) }],
842
- isError: true,
1155
+ result: { error: "任务不存在" },
843
1156
  };
844
1157
  }
845
1158
  // H4: 交付前工作区完整性检查 — advisory 模式,仅警告不阻断
@@ -847,6 +1160,41 @@ export function registerTools(server, deps) {
847
1160
  const h4DeliverWarning = !deliverIntegrity.clean
848
1161
  ? { warning: `H4 advisory: ${deliverIntegrity.message}`, dirty_files: deliverIntegrity.dirty_files }
849
1162
  : undefined;
1163
+ // Artifact status gate : deliver requires artifact status = accepted with evidence
1164
+ if (ctx.artifact_output) {
1165
+ const status = ctx.artifact_output.status;
1166
+ if (status === "draft") {
1167
+ return {
1168
+ result: {
1169
+ error: `产物状态为 ${status},需先通过验证 (verified) 并确认 (accepted) 才能交付`,
1170
+ artifact_id: ctx.artifact_output.artifact_id,
1171
+ current_status: status,
1172
+ },
1173
+ };
1174
+ }
1175
+ if (status === "verified") {
1176
+ return {
1177
+ result: {
1178
+ error: `产物状态为 ${status},需人工确认或后续 workflow 采用后变为 accepted 才能交付`,
1179
+ artifact_id: ctx.artifact_output.artifact_id,
1180
+ current_status: status,
1181
+ },
1182
+ };
1183
+ }
1184
+ // accepted must have confirmation evidence
1185
+ if (status === "accepted") {
1186
+ const hasAcceptanceEvidence = ctx.artifact_output.evidence_refs.some((r) => r.includes("acceptance") || r.includes("workflow_adoption"));
1187
+ if (!hasAcceptanceEvidence) {
1188
+ return {
1189
+ result: {
1190
+ error: `产物状态为 accepted 但缺少确认证据 (acceptance/workflow_adoption evidence_ref)`,
1191
+ artifact_id: ctx.artifact_output.artifact_id,
1192
+ current_status: status,
1193
+ },
1194
+ };
1195
+ }
1196
+ }
1197
+ }
850
1198
  const result = await deliver({
851
1199
  taskContext: ctx,
852
1200
  config,
@@ -858,10 +1206,7 @@ export function registerTools(server, deps) {
858
1206
  });
859
1207
  await taskContext.setDelivery(args.task_id, result);
860
1208
  return {
861
- content: [{
862
- type: "text",
863
- text: JSON.stringify(h4DeliverWarning ? { ...result, h4_advisory: h4DeliverWarning } : result, null, 2),
864
- }],
1209
+ result: h4DeliverWarning ? { ...result, h4_advisory: h4DeliverWarning } : result,
865
1210
  };
866
1211
  });
867
1212
  // ── sf_coord_check: 预测性冲突检测和跨仓库协调 ──
@@ -873,7 +1218,7 @@ export function registerTools(server, deps) {
873
1218
  gitOps: realGitOps,
874
1219
  });
875
1220
  return {
876
- content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
1221
+ result: result,
877
1222
  };
878
1223
  });
879
1224
  // ── sf_team_status: 团队活动流和工作负载查询 ──
@@ -886,7 +1231,7 @@ export function registerTools(server, deps) {
886
1231
  knowledgeIndex: args.include_knowledge ? knowledgeIndex : undefined,
887
1232
  });
888
1233
  return {
889
- content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
1234
+ result: result,
890
1235
  };
891
1236
  });
892
1237
  // ── sf_contract_check: API 契约变更检测 ──
@@ -903,7 +1248,7 @@ export function registerTools(server, deps) {
903
1248
  gitOps: realGitOps,
904
1249
  });
905
1250
  return {
906
- content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
1251
+ result: result,
907
1252
  };
908
1253
  });
909
1254
  // ── sf_onboard: 新人分步引导 ──
@@ -917,7 +1262,7 @@ export function registerTools(server, deps) {
917
1262
  reset: args.reset,
918
1263
  });
919
1264
  return {
920
- content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
1265
+ result: result,
921
1266
  };
922
1267
  });
923
1268
  // ── sf_feasibility_check: 任务可行性评估 ──
@@ -925,13 +1270,12 @@ export function registerTools(server, deps) {
925
1270
  const ctx = await taskContext.load(args.task_id);
926
1271
  if (!ctx?.classification) {
927
1272
  return {
928
- content: [{ type: "text", text: JSON.stringify({ error: "任务不存在或未完成分类,请先调用 sf_classify" }) }],
929
- isError: true,
1273
+ result: { error: "任务不存在或未完成分类,请先调用 sf_classify" },
930
1274
  };
931
1275
  }
932
1276
  const result = checkFeasibility(ctx.classification, config);
933
1277
  return {
934
- content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
1278
+ result: result,
935
1279
  };
936
1280
  });
937
1281
  // ── sf_debug: 智能排障(解析错误 → 根因分析 → 修复方案) ──
@@ -942,7 +1286,7 @@ export function registerTools(server, deps) {
942
1286
  ];
943
1287
  const result = debugError(args.error_output, args.task_id || `debug-${Date.now()}`, projectScope);
944
1288
  return {
945
- content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
1289
+ result: result,
946
1290
  };
947
1291
  });
948
1292
  // ── sf_observability: 系统可观测和运行报告 ──
@@ -952,35 +1296,35 @@ export function registerTools(server, deps) {
952
1296
  const capability = getCapabilitySummary();
953
1297
  const output = { ...result, capability };
954
1298
  return {
955
- content: [{ type: "text", text: JSON.stringify(output, null, 2) }],
1299
+ result: output,
956
1300
  };
957
1301
  });
958
1302
  // ── sf_migration_check: 数据库迁移安全性分析 ──
959
1303
  registerSafeTool("sf_migration_check", "分析数据库迁移文件安全性:检测破坏性操作(DROP/DELETE/TRUNCATE)并生成回滚建议", MigrationCheckSchema, async (args) => {
960
1304
  const result = analyzeMigration(args.content, args.filename);
961
1305
  return {
962
- content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
1306
+ result: result,
963
1307
  };
964
1308
  });
965
1309
  // ── sf_test_guide: 基于变更文件生成测试指引 ──
966
1310
  registerSafeTool("sf_test_guide", "根据变更文件类型生成测试指引:推荐测试类型、场景、Mock 点和断言模板", TestGuideSchema, async (args) => {
967
1311
  const result = generateTestGuide(args.changed_files, [], config);
968
1312
  return {
969
- content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
1313
+ result: result,
970
1314
  };
971
1315
  });
972
1316
  // ── sf_test_quality: 测试文件质量五维评分 ──
973
1317
  registerSafeTool("sf_test_quality", "评估测试文件质量:断言密度、边界覆盖、命名、重复率、场景覆盖五维评分", TestQualitySchema, async (args) => {
974
1318
  const result = analyzeTestQuality(args.content, args.filename);
975
1319
  return {
976
- content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
1320
+ result: result,
977
1321
  };
978
1322
  });
979
1323
  // ── sf_dependency_scan: 依赖漏洞扫描 ──
980
1324
  registerSafeTool("sf_dependency_scan", "扫描依赖声明文件漏洞:已知 CVE 规则匹配、未锁定版本检测、支持 npm/maven/gradle", DependencyScanSchema, async (args) => {
981
1325
  const result = scanDependencies(args.content, args.filename);
982
1326
  return {
983
- content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
1327
+ result: result,
984
1328
  };
985
1329
  });
986
1330
  // ── sf_debt_report: 技术债务报告生成 ──
@@ -988,7 +1332,7 @@ export function registerTools(server, deps) {
988
1332
  const tracker = new DebtTracker(projectPath);
989
1333
  const result = await generateDebtReport(tracker);
990
1334
  return {
991
- content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
1335
+ result: result,
992
1336
  };
993
1337
  });
994
1338
  // ── sf_explore: 自主技术选型与方案证伪 ──
@@ -1010,15 +1354,13 @@ export function registerTools(server, deps) {
1010
1354
  if (!decisionContract.passed) {
1011
1355
  exploreExtras.decision_contract_advisory = decisionContract.advisory;
1012
1356
  }
1013
- return {
1014
- content: [{ type: "text", text: JSON.stringify(Object.keys(exploreExtras).length > 0 ? { ...result, ...exploreExtras } : result, null, 2) }],
1015
- };
1357
+ return { result: Object.keys(exploreExtras).length > 0 ? { ...result, ...exploreExtras } : result };
1016
1358
  });
1017
1359
  // ── sf_knowledge_audit: 知识库健康审计 ──
1018
1360
  registerSafeTool("sf_knowledge_audit", "审计知识库:识别过时条目、重复触发词、格式缺失、覆盖缺口。定期执行或手动触发", {}, async () => {
1019
1361
  const result = await auditKnowledge(knowledgeIndex, config);
1020
1362
  return {
1021
- content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
1363
+ result: result,
1022
1364
  };
1023
1365
  });
1024
1366
  // ── sf_knowledge_add: 新增知识条目(默认保存为草稿) ──
@@ -1042,7 +1384,7 @@ export function registerTools(server, deps) {
1042
1384
  auto_enrich: args.auto_enrich,
1043
1385
  }, config);
1044
1386
  return {
1045
- content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
1387
+ result: result,
1046
1388
  };
1047
1389
  });
1048
1390
  // ── sf_knowledge_update: 更新已有知识条目(自动创建备份) ──
@@ -1068,7 +1410,7 @@ export function registerTools(server, deps) {
1068
1410
  await knowledgeIndex.reload();
1069
1411
  }
1070
1412
  return {
1071
- content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
1413
+ result: result,
1072
1414
  };
1073
1415
  });
1074
1416
  // ── sf_resume_workspace: 工作区状态唤醒(解决前端刷新导致UUID丢失) ──
@@ -1104,7 +1446,7 @@ export function registerTools(server, deps) {
1104
1446
  // JobManager advisory — ignore errors
1105
1447
  }
1106
1448
  return {
1107
- content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
1449
+ result: result,
1108
1450
  };
1109
1451
  });
1110
1452
  // ── sf_audit_sample: 从审计池按风险加权抽样生成抽检清单 ──
@@ -1118,7 +1460,7 @@ export function registerTools(server, deps) {
1118
1460
  const seed = args.seed ?? 0;
1119
1461
  const result = sampleAuditItems(items, seed);
1120
1462
  return {
1121
- content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
1463
+ result: result,
1122
1464
  };
1123
1465
  });
1124
1466
  // ── sf_escape_report: 记录逃逸/误伤/工具故障报告 ──
@@ -1157,7 +1499,7 @@ export function registerTools(server, deps) {
1157
1499
  };
1158
1500
  store.append(report);
1159
1501
  return {
1160
- content: [{ type: "text", text: JSON.stringify({ recorded: true, escape_id: report.escape_id }, null, 2) }],
1502
+ result: { recorded: true, escape_id: report.escape_id },
1161
1503
  };
1162
1504
  });
1163
1505
  // ── sf_capability_update: 根据复盘结果更新 Capability Registry ──
@@ -1188,7 +1530,7 @@ export function registerTools(server, deps) {
1188
1530
  confirm: args.confirm,
1189
1531
  }, currentState, cap?.id ?? null, escapeReports);
1190
1532
  return {
1191
- content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
1533
+ result: result,
1192
1534
  };
1193
1535
  });
1194
1536
  // ── sf_governance_report: 治理健康报告 ──
@@ -1213,9 +1555,81 @@ export function registerTools(server, deps) {
1213
1555
  });
1214
1556
  // Generate sample decisions for sampled_count
1215
1557
  const sampleResult = sampleAuditItems(auditItems, seed);
1216
- const report = generateGovernanceReport(auditStats, auditItems, escapeReports, escapeStats, decisions, new Date(), sampleResult.decisions);
1558
+ // Dual-layer mechanism findings
1559
+ const dlFindings = validateMechanismLayerMaps();
1560
+ const dlMechanismCount = listMechanismLayerMaps().length;
1561
+ // Collect artifact records from recent tasks
1562
+ const recentTasks = await taskContext.listRecent(20);
1563
+ const artifacts = [];
1564
+ for (const t of recentTasks) {
1565
+ const tCtx = await taskContext.load(t.task_id);
1566
+ if (tCtx?.artifact_output)
1567
+ artifacts.push(tCtx.artifact_output);
1568
+ }
1569
+ // Collect config resolution reports — use shared function for real data
1570
+ let configReports = [];
1571
+ let configEntries = [];
1572
+ try {
1573
+ const resolved = await resolveCurrentProjectConfigReports(projectPath);
1574
+ configReports = resolved.reports;
1575
+ configEntries = resolved.entries;
1576
+ }
1577
+ catch (e) {
1578
+ console.error(`[soloForge] 配置报告解析失败: ${e instanceof Error ? e.message : String(e)}`);
1579
+ }
1580
+ // Also include reports from recent task contexts
1581
+ for (const t of recentTasks) {
1582
+ const tCtx = await taskContext.load(t.task_id);
1583
+ if (tCtx?.expansion?.config_resolution_reports) {
1584
+ configReports.push(...tCtx.expansion.config_resolution_reports);
1585
+ }
1586
+ }
1587
+ const report = generateGovernanceReport(auditStats, auditItems, escapeReports, escapeStats, decisions, new Date(), sampleResult.decisions, dlFindings, dlMechanismCount, artifacts.length > 0 ? artifacts : undefined, configReports.length > 0 ? configReports : undefined, configEntries.length > 0 ? configEntries : undefined);
1588
+ return {
1589
+ result: report,
1590
+ };
1591
+ });
1592
+ // ── sf_audit_integration: 主链路集成审计 ──
1593
+ const AuditIntegrationSchema = {
1594
+ changed_files: z.array(z.string()).optional().describe("只审计指定的变更文件列表"),
1595
+ json_output: z.boolean().optional().describe("以 JSON 格式输出(默认为人类可读文本)"),
1596
+ };
1597
+ registerSafeTool("sf_audit_integration", "审计生产代码的主链路集成状态,检测孤岛模块(只被测试导入、无生产代码调用的模块)", AuditIntegrationSchema, async (args) => {
1598
+ const projectPath = config._projectPath || process.cwd();
1599
+ // Use scope-aware production file collection (supports multi-repo, multi-lang)
1600
+ const { collectAllProductionFiles } = await import("../../engine/main_path_integration_contract.js");
1601
+ const allProdFiles = collectAllProductionFiles(projectPath, config);
1602
+ if (allProdFiles.length === 0) {
1603
+ return {
1604
+ result: { error: "未找到生产源文件" },
1605
+ };
1606
+ }
1607
+ const targetFiles = args.changed_files
1608
+ ? allProdFiles.filter((rel) => args.changed_files.some((cf) => rel === cf || rel.startsWith(cf.replace(/\.(ts|tsx|js|jsx|java|kt|go|py)$/, ""))))
1609
+ : allProdFiles;
1610
+ const contracts = buildMainPathIntegrationContracts(projectPath, targetFiles, config);
1611
+ const report = auditIntegration(contracts);
1612
+ if (args.json_output) {
1613
+ return {
1614
+ result: report,
1615
+ };
1616
+ }
1617
+ const lines = [];
1618
+ lines.push("主链路集成审计报告");
1619
+ lines.push(`受检模块: ${targetFiles.length} | 孤岛: ${report.orphan_modules.length} | 仅测试: ${report.test_only_modules.length} | 仅注册: ${report.registry_only_modules.length}`);
1620
+ lines.push("");
1621
+ for (const finding of report.findings) {
1622
+ const icon = finding.severity === "hard_fail" ? "X" : finding.severity === "warning" ? "~" : "i";
1623
+ lines.push(`${icon} ${finding.module_path}: ${finding.reason}`);
1624
+ if (finding.recommended_action) {
1625
+ lines.push(` -> ${finding.recommended_action}`);
1626
+ }
1627
+ }
1628
+ if (report.findings.length === 0) {
1629
+ lines.push("所有受检模块已通过集成检查。");
1630
+ }
1217
1631
  return {
1218
- content: [{ type: "text", text: JSON.stringify(report, null, 2) }],
1632
+ result: { text: lines.join("\n") },
1219
1633
  };
1220
1634
  });
1221
1635
  }