soloforge 1.2.18 → 1.2.20

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 (208) hide show
  1. package/dist/adapters/claude_code/pre_prompt_contract.js +2 -2
  2. package/dist/adapters/claude_code/pre_prompt_contract.js.map +1 -1
  3. package/dist/adapters/claude_code/server.d.ts.map +1 -1
  4. package/dist/adapters/claude_code/server.js +4 -2
  5. package/dist/adapters/claude_code/server.js.map +1 -1
  6. package/dist/adapters/claude_code/tools.d.ts +2 -2
  7. package/dist/adapters/claude_code/tools.d.ts.map +1 -1
  8. package/dist/adapters/claude_code/tools.js +348 -171
  9. package/dist/adapters/claude_code/tools.js.map +1 -1
  10. package/dist/adapters/codex/codex_config.d.ts.map +1 -1
  11. package/dist/adapters/codex/codex_config.js +16 -4
  12. package/dist/adapters/codex/codex_config.js.map +1 -1
  13. package/dist/adapters/trae/trae_config.d.ts +2 -1
  14. package/dist/adapters/trae/trae_config.d.ts.map +1 -1
  15. package/dist/adapters/trae/trae_config.js +4 -3
  16. package/dist/adapters/trae/trae_config.js.map +1 -1
  17. package/dist/bin/config_commands.d.ts +1 -1
  18. package/dist/bin/config_commands.js +4 -4
  19. package/dist/bin/config_commands.js.map +1 -1
  20. package/dist/bin/soloforge.d.ts.map +1 -1
  21. package/dist/bin/soloforge.js +85 -110
  22. package/dist/bin/soloforge.js.map +1 -1
  23. package/dist/engine/artifact_contract_registry.d.ts.map +1 -1
  24. package/dist/engine/artifact_contract_registry.js.map +1 -1
  25. package/dist/engine/audit_sampler.d.ts.map +1 -1
  26. package/dist/engine/audit_sampler.js +0 -4
  27. package/dist/engine/audit_sampler.js.map +1 -1
  28. package/dist/engine/batch1_manifest.d.ts.map +1 -1
  29. package/dist/engine/batch1_manifest.js +0 -7
  30. package/dist/engine/batch1_manifest.js.map +1 -1
  31. package/dist/engine/batch1_scenario_registry.js +7 -7
  32. package/dist/engine/batch1_scenario_registry.js.map +1 -1
  33. package/dist/engine/batch1_scenario_runners.js +32 -32
  34. package/dist/engine/batch1_scenario_runners.js.map +1 -1
  35. package/dist/engine/capability_action_advisor.js +16 -16
  36. package/dist/engine/capability_action_advisor.js.map +1 -1
  37. package/dist/engine/classifier.d.ts.map +1 -1
  38. package/dist/engine/classifier.js +4 -3
  39. package/dist/engine/classifier.js.map +1 -1
  40. package/dist/engine/code_reviewer.d.ts.map +1 -1
  41. package/dist/engine/code_reviewer.js +10 -9
  42. package/dist/engine/code_reviewer.js.map +1 -1
  43. package/dist/engine/command_execution_contract.js +14 -14
  44. package/dist/engine/command_execution_contract.js.map +1 -1
  45. package/dist/engine/contract_registry.d.ts +113 -0
  46. package/dist/engine/contract_registry.d.ts.map +1 -0
  47. package/dist/engine/contract_registry.js +1159 -0
  48. package/dist/engine/contract_registry.js.map +1 -0
  49. package/dist/engine/contract_state_store.d.ts +67 -0
  50. package/dist/engine/contract_state_store.d.ts.map +1 -0
  51. package/dist/engine/contract_state_store.js +167 -0
  52. package/dist/engine/contract_state_store.js.map +1 -0
  53. package/dist/engine/debug_log.d.ts +2 -0
  54. package/dist/engine/debug_log.d.ts.map +1 -0
  55. package/dist/engine/debug_log.js +7 -0
  56. package/dist/engine/debug_log.js.map +1 -0
  57. package/dist/engine/debugger.d.ts.map +1 -1
  58. package/dist/engine/debugger.js +30 -1
  59. package/dist/engine/debugger.js.map +1 -1
  60. package/dist/engine/degradation.d.ts +58 -0
  61. package/dist/engine/degradation.d.ts.map +1 -0
  62. package/dist/engine/degradation.js +74 -0
  63. package/dist/engine/degradation.js.map +1 -0
  64. package/dist/engine/delivery_readiness.d.ts +66 -0
  65. package/dist/engine/delivery_readiness.d.ts.map +1 -0
  66. package/dist/engine/delivery_readiness.js +176 -0
  67. package/dist/engine/delivery_readiness.js.map +1 -0
  68. package/dist/engine/deprecated_contract.d.ts +21 -0
  69. package/dist/engine/deprecated_contract.d.ts.map +1 -0
  70. package/dist/engine/deprecated_contract.js +14 -0
  71. package/dist/engine/deprecated_contract.js.map +1 -0
  72. package/dist/engine/developer_sovereignty.js +15 -15
  73. package/dist/engine/developer_sovereignty.js.map +1 -1
  74. package/dist/engine/diagnostic_registry.d.ts +64 -0
  75. package/dist/engine/diagnostic_registry.d.ts.map +1 -0
  76. package/dist/engine/diagnostic_registry.js +176 -0
  77. package/dist/engine/diagnostic_registry.js.map +1 -0
  78. package/dist/engine/diff_ownership_store.d.ts.map +1 -1
  79. package/dist/engine/diff_ownership_store.js +1 -2
  80. package/dist/engine/diff_ownership_store.js.map +1 -1
  81. package/dist/engine/dual_layer_mechanism_registry.js +1 -1
  82. package/dist/engine/dual_layer_mechanism_registry.js.map +1 -1
  83. package/dist/engine/enforcement_guard.d.ts +84 -0
  84. package/dist/engine/enforcement_guard.d.ts.map +1 -0
  85. package/dist/engine/enforcement_guard.js +305 -0
  86. package/dist/engine/enforcement_guard.js.map +1 -0
  87. package/dist/engine/evolver.d.ts.map +1 -1
  88. package/dist/engine/evolver.js +11 -10
  89. package/dist/engine/evolver.js.map +1 -1
  90. package/dist/engine/failure_report.d.ts +74 -0
  91. package/dist/engine/failure_report.d.ts.map +1 -0
  92. package/dist/engine/failure_report.js +143 -0
  93. package/dist/engine/failure_report.js.map +1 -0
  94. package/dist/engine/governance_report.d.ts +9 -1
  95. package/dist/engine/governance_report.d.ts.map +1 -1
  96. package/dist/engine/governance_report.js +24 -10
  97. package/dist/engine/governance_report.js.map +1 -1
  98. package/dist/engine/implementation_roadmap_registry.d.ts +1 -1
  99. package/dist/engine/implementation_roadmap_registry.d.ts.map +1 -1
  100. package/dist/engine/implementation_roadmap_registry.js +37 -29
  101. package/dist/engine/implementation_roadmap_registry.js.map +1 -1
  102. package/dist/engine/input_material_extractor.js +3 -3
  103. package/dist/engine/input_material_extractor.js.map +1 -1
  104. package/dist/engine/intent_expander.d.ts.map +1 -1
  105. package/dist/engine/intent_expander.js +15 -14
  106. package/dist/engine/intent_expander.js.map +1 -1
  107. package/dist/engine/intent_router.d.ts.map +1 -1
  108. package/dist/engine/intent_router.js +17 -16
  109. package/dist/engine/intent_router.js.map +1 -1
  110. package/dist/engine/java_quality_guard.js +10 -10
  111. package/dist/engine/java_quality_guard.js.map +1 -1
  112. package/dist/engine/knowledge_injection_boundary.d.ts +1 -1
  113. package/dist/engine/knowledge_injection_boundary.d.ts.map +1 -1
  114. package/dist/engine/knowledge_injection_boundary.js +61 -60
  115. package/dist/engine/knowledge_injection_boundary.js.map +1 -1
  116. package/dist/engine/knowledge_lifecycle.d.ts +23 -0
  117. package/dist/engine/knowledge_lifecycle.d.ts.map +1 -0
  118. package/dist/engine/knowledge_lifecycle.js +13 -0
  119. package/dist/engine/knowledge_lifecycle.js.map +1 -0
  120. package/dist/engine/language_policy.d.ts +21 -0
  121. package/dist/engine/language_policy.d.ts.map +1 -0
  122. package/dist/engine/language_policy.js +18 -0
  123. package/dist/engine/language_policy.js.map +1 -0
  124. package/dist/engine/language_policy_contract.d.ts +52 -0
  125. package/dist/engine/language_policy_contract.d.ts.map +1 -0
  126. package/dist/engine/language_policy_contract.js +78 -0
  127. package/dist/engine/language_policy_contract.js.map +1 -0
  128. package/dist/engine/main_path_integration_contract.js +16 -16
  129. package/dist/engine/main_path_integration_contract.js.map +1 -1
  130. package/dist/engine/mechanism_contract_registry.d.ts +3 -4
  131. package/dist/engine/mechanism_contract_registry.d.ts.map +1 -1
  132. package/dist/engine/mechanism_contract_registry.js +23 -24
  133. package/dist/engine/mechanism_contract_registry.js.map +1 -1
  134. package/dist/engine/mechanism_family_registry.d.ts +48 -0
  135. package/dist/engine/mechanism_family_registry.d.ts.map +1 -0
  136. package/dist/engine/mechanism_family_registry.js +197 -0
  137. package/dist/engine/mechanism_family_registry.js.map +1 -0
  138. package/dist/engine/onboarding.js +20 -20
  139. package/dist/engine/onboarding.js.map +1 -1
  140. package/dist/engine/policy_drift_detector.d.ts +20 -0
  141. package/dist/engine/policy_drift_detector.d.ts.map +1 -1
  142. package/dist/engine/policy_drift_detector.js +79 -0
  143. package/dist/engine/policy_drift_detector.js.map +1 -1
  144. package/dist/engine/privacy_secret_contract.d.ts.map +1 -1
  145. package/dist/engine/privacy_secret_contract.js +49 -48
  146. package/dist/engine/privacy_secret_contract.js.map +1 -1
  147. package/dist/engine/regression_matrix.js +21 -21
  148. package/dist/engine/regression_matrix.js.map +1 -1
  149. package/dist/engine/retention_policy.d.ts +46 -0
  150. package/dist/engine/retention_policy.d.ts.map +1 -0
  151. package/dist/engine/retention_policy.js +124 -0
  152. package/dist/engine/retention_policy.js.map +1 -0
  153. package/dist/engine/route_decision_contract_verifier.js +24 -24
  154. package/dist/engine/route_decision_contract_verifier.js.map +1 -1
  155. package/dist/engine/scope_controller.d.ts.map +1 -1
  156. package/dist/engine/scope_controller.js +4 -3
  157. package/dist/engine/scope_controller.js.map +1 -1
  158. package/dist/engine/scope_lease.d.ts.map +1 -1
  159. package/dist/engine/scope_lease.js +0 -1
  160. package/dist/engine/scope_lease.js.map +1 -1
  161. package/dist/engine/state_update_bypass.d.ts +19 -0
  162. package/dist/engine/state_update_bypass.d.ts.map +1 -0
  163. package/dist/engine/state_update_bypass.js +17 -0
  164. package/dist/engine/state_update_bypass.js.map +1 -0
  165. package/dist/engine/task_context.d.ts.map +1 -1
  166. package/dist/engine/task_context.js +11 -3
  167. package/dist/engine/task_context.js.map +1 -1
  168. package/dist/engine/test_generator.js +8 -8
  169. package/dist/engine/test_generator.js.map +1 -1
  170. package/dist/engine/test_strategy.d.ts +58 -0
  171. package/dist/engine/test_strategy.d.ts.map +1 -0
  172. package/dist/engine/test_strategy.js +93 -0
  173. package/dist/engine/test_strategy.js.map +1 -0
  174. package/dist/engine/tool_invocation_contract_registry.d.ts.map +1 -1
  175. package/dist/engine/tool_invocation_contract_registry.js +29 -19
  176. package/dist/engine/tool_invocation_contract_registry.js.map +1 -1
  177. package/dist/engine/traceability.js +6 -6
  178. package/dist/engine/traceability.js.map +1 -1
  179. package/dist/engine/user_feedback_contract.js +9 -9
  180. package/dist/engine/user_feedback_contract.js.map +1 -1
  181. package/dist/engine/verification_contract.d.ts +132 -0
  182. package/dist/engine/verification_contract.d.ts.map +1 -0
  183. package/dist/engine/verification_contract.js +296 -0
  184. package/dist/engine/verification_contract.js.map +1 -0
  185. package/dist/engine/verifier.d.ts.map +1 -1
  186. package/dist/engine/verifier.js +9 -8
  187. package/dist/engine/verifier.js.map +1 -1
  188. package/dist/engine/workspace_lease.d.ts +69 -0
  189. package/dist/engine/workspace_lease.d.ts.map +1 -0
  190. package/dist/engine/workspace_lease.js +153 -0
  191. package/dist/engine/workspace_lease.js.map +1 -0
  192. package/dist/engine/zero_config_init.d.ts.map +1 -1
  193. package/dist/engine/zero_config_init.js +84 -84
  194. package/dist/engine/zero_config_init.js.map +1 -1
  195. package/dist/git/operations.js +1 -1
  196. package/dist/git/operations.js.map +1 -1
  197. package/dist/index.d.ts +4 -3
  198. package/dist/index.d.ts.map +1 -1
  199. package/dist/index.js +16 -11
  200. package/dist/index.js.map +1 -1
  201. package/dist/knowledge/index_manager.d.ts.map +1 -1
  202. package/dist/knowledge/index_manager.js +18 -17
  203. package/dist/knowledge/index_manager.js.map +1 -1
  204. package/dist/knowledge/loader.js +2 -2
  205. package/dist/knowledge/loader.js.map +1 -1
  206. package/dist/types.d.ts +13 -1
  207. package/dist/types.d.ts.map +1 -1
  208. package/package.json +4 -2
@@ -2,52 +2,71 @@ import { z } from "zod";
2
2
  import path from "node:path";
3
3
  import fss from "node:fs";
4
4
  import crypto from "node:crypto";
5
+ import { verifyArtifact } from "../../engine/artifact_contract_registry.js";
5
6
  import { verifyRouteDecisionContract } from "../../engine/route_decision_contract_verifier.js";
6
7
  import { findToolInvocationContractByName, createToolTrace, validateToolInvocation, } from "../../engine/tool_invocation_contract_registry.js";
7
- import { classify } from "../../engine/classifier.js";
8
- import { shouldEnterSoloForge } from "../../engine/intent_router.js";
9
- import { expand } from "../../engine/intent_expander.js";
10
- import { generateVerifyCommands } from "../../engine/verifier.js";
11
- import { evolve } from "../../engine/evolver.js";
12
- import { planTask } from "../../engine/task_planner.js";
13
- import { analyzeImpact } from "../../engine/impact_analyzer.js";
14
- import { reviewCode } from "../../engine/code_reviewer.js";
15
- import { DebtTracker } from "../../engine/debt_tracker.js";
16
- import { generateScaffold } from "../../engine/scaffolder.js";
17
- import { deliver } from "../../engine/delivery.js";
18
- import { checkConflicts } from "../../engine/change_coordinator.js";
19
- import { getTeamStatus } from "../../engine/team_awareness.js";
20
- import { checkContractChanges } from "../../engine/contract_guard.js";
21
- import { onboard } from "../../engine/onboarding.js";
22
- import { realGitOps } from "../../engine/git_deps.js";
23
- import { auditKnowledge, addKnowledge, updateKnowledge } from "../../engine/knowledge_manager.js";
24
- import { checkFeasibility } from "../../engine/feasibility_checker.js";
25
- import { debugError } from "../../engine/debugger.js";
26
- import { generateReport } from "../../engine/observability.js";
27
- import { generateReport as generateGovernanceReport } from "../../engine/governance_report.js";
28
- import { resolveCurrentProjectConfigReports } from "../../engine/config_precedence_contract.js";
29
- import { analyzeMigration } from "../../engine/migration_guard.js";
30
- import { generateTestGuide } from "../../engine/test_generator.js";
31
- import { analyzeTestQuality } from "../../engine/test_quality.js";
32
- import { scanDependencies } from "../../engine/dependency_scanner.js";
33
- import { generateDebtReport } from "../../engine/debt_reporter.js";
34
- import { exploreSolutions } from "../../engine/exploration.js";
35
- import { scanAndResume } from "../../engine/workspace_resumer.js";
36
- import { LLMGateway } from "../../engine/llm_gateway.js";
37
- import { IOController } from "../../engine/io_controller.js";
38
- import { getSummary as getCapabilitySummary, getAllCapabilities } from "../../engine/capability_registry.js";
39
- import { validateDecisionOutput } from "../../engine/decision_contract.js";
40
- import { readMapJson, checkAnchorStaleness, filterRelevantAnchors } from "../../engine/cognitive_anchor.js";
41
- import { JobManager } from "../../engine/job_manager.js";
42
- import { AuditPool } from "../../engine/audit_pool.js";
43
- import { EscapeReportStore } from "../../engine/escape_report.js";
44
- import { sampleAuditItems } from "../../engine/audit_sampler.js";
45
- import { decideAction } from "../../engine/capability_action_advisor.js";
46
- import { CapabilityStateStore } from "../../engine/capability_state_store.js";
47
- import { auditIntegration, buildMainPathIntegrationContracts, } from "../../engine/main_path_integration_contract.js";
48
- import { validateMechanismLayerMaps, listMechanismLayerMaps, } from "../../engine/dual_layer_mechanism_registry.js";
49
- import { classifyIngestionStatus } from "../../engine/input_material_contract_registry.js";
50
- import { verifyArtifact, } from "../../engine/artifact_contract_registry.js";
8
+ function createLazy(loader) {
9
+ let mod = { loaded: null, promise: null };
10
+ return () => {
11
+ if (mod.loaded)
12
+ return Promise.resolve(mod.loaded);
13
+ if (!mod.promise)
14
+ mod.promise = loader().then(m => { mod.loaded = m; return m; });
15
+ return mod.promise;
16
+ };
17
+ }
18
+ const lazyClassifier = createLazy(() => import("../../engine/classifier.js"));
19
+ const lazyIntentRouter = createLazy(() => import("../../engine/intent_router.js"));
20
+ const lazyExpander = createLazy(() => import("../../engine/intent_expander.js"));
21
+ const lazyVerifier = createLazy(() => import("../../engine/verifier.js"));
22
+ const lazyEvolver = createLazy(() => import("../../engine/evolver.js"));
23
+ const lazyPlanner = createLazy(() => import("../../engine/task_planner.js"));
24
+ const lazyImpact = createLazy(() => import("../../engine/impact_analyzer.js"));
25
+ const lazyReviewer = createLazy(() => import("../../engine/code_reviewer.js"));
26
+ const lazyDebt = createLazy(() => import("../../engine/debt_tracker.js"));
27
+ const lazyScaffolder = createLazy(() => import("../../engine/scaffolder.js"));
28
+ const lazyDelivery = createLazy(() => import("../../engine/delivery.js"));
29
+ const lazyChangeCoord = createLazy(() => import("../../engine/change_coordinator.js"));
30
+ const lazyTeam = createLazy(() => import("../../engine/team_awareness.js"));
31
+ const lazyContractGuard = createLazy(() => import("../../engine/contract_guard.js"));
32
+ const lazyOnboarding = createLazy(() => import("../../engine/onboarding.js"));
33
+ const lazyGitDeps = createLazy(() => import("../../engine/git_deps.js"));
34
+ const lazyKnowledge = createLazy(() => import("../../engine/knowledge_manager.js"));
35
+ const lazyFeasibility = createLazy(() => import("../../engine/feasibility_checker.js"));
36
+ const lazyDebugger = createLazy(() => import("../../engine/debugger.js"));
37
+ const lazyObservability = createLazy(() => import("../../engine/observability.js"));
38
+ const lazyGovernance = createLazy(() => import("../../engine/governance_report.js"));
39
+ const lazyMigration = createLazy(() => import("../../engine/migration_guard.js"));
40
+ const lazyTestGen = createLazy(() => import("../../engine/test_generator.js"));
41
+ const lazyTestQuality = createLazy(() => import("../../engine/test_quality.js"));
42
+ const lazyDepScan = createLazy(() => import("../../engine/dependency_scanner.js"));
43
+ const lazyDebtReport = createLazy(() => import("../../engine/debt_reporter.js"));
44
+ const lazyExploration = createLazy(() => import("../../engine/exploration.js"));
45
+ const lazyWorkspaceResumer = createLazy(() => import("../../engine/workspace_resumer.js"));
46
+ const lazyLLM = createLazy(() => import("../../engine/llm_gateway.js"));
47
+ const lazyIO = createLazy(() => import("../../engine/io_controller.js"));
48
+ const lazyCapability = createLazy(() => import("../../engine/capability_registry.js"));
49
+ const lazyDecision = createLazy(() => import("../../engine/decision_contract.js"));
50
+ const lazyAnchor = createLazy(() => import("../../engine/cognitive_anchor.js"));
51
+ const lazyJob = createLazy(() => import("../../engine/job_manager.js"));
52
+ const lazyAuditPool = createLazy(() => import("../../engine/audit_pool.js"));
53
+ const lazyEscape = createLazy(() => import("../../engine/escape_report.js"));
54
+ const lazyAuditSampler = createLazy(() => import("../../engine/audit_sampler.js"));
55
+ const lazyCapAdvisor = createLazy(() => import("../../engine/capability_action_advisor.js"));
56
+ const lazyCapState = createLazy(() => import("../../engine/capability_state_store.js"));
57
+ const lazyMainPath = createLazy(() => import("../../engine/main_path_integration_contract.js"));
58
+ const lazyDualLayer = createLazy(() => import("../../engine/dual_layer_mechanism_registry.js"));
59
+ const lazyInputMaterial = createLazy(() => import("../../engine/input_material_contract_registry.js"));
60
+ const lazyConfigCmd = createLazy(() => import("../../bin/config_commands.js"));
61
+ const lazyConfigPrecedence = createLazy(() => import("../../engine/config_precedence_contract.js"));
62
+ const lazyEnforcementGuard = createLazy(() => import("../../engine/enforcement_guard.js"));
63
+ const lazyWorkspaceLease = createLazy(() => import("../../engine/workspace_lease.js"));
64
+ const lazyDeliveryReadiness = createLazy(() => import("../../engine/delivery_readiness.js"));
65
+ const lazyVerificationContract = createLazy(() => import("../../engine/verification_contract.js"));
66
+ const lazyFailureReport = createLazy(() => import("../../engine/failure_report.js"));
67
+ const lazyDegradation = createLazy(() => import("../../engine/degradation.js"));
68
+ const lazyRetentionPolicy = createLazy(() => import("../../engine/retention_policy.js"));
69
+ const lazyDiagnosticRegistry = createLazy(() => import("../../engine/diagnostic_registry.js"));
51
70
  // ── Zod Schema 定义 ──
52
71
  const ClassifySchema = {
53
72
  intent: z.string().describe("开发者意图描述"),
@@ -92,6 +111,19 @@ const ReviewSchema = {
92
111
  const ScaffoldSchema = {
93
112
  task_id: z.string().describe("sf_classify 返回的任务 ID(task_type 应为 scaffold)"),
94
113
  };
114
+ const RecordVerificationExecutionSchema = {
115
+ task_id: z.string().describe("任务 ID"),
116
+ plan_id: z.string().describe("关联的 VerificationPlan ID"),
117
+ execution_records: z.array(z.object({
118
+ command: z.string().describe("执行的验证命令"),
119
+ exit_code: z.number().describe("命令退出码,0 表示通过"),
120
+ stdout_hash: z.string().describe("stdout 的 SHA256 hash"),
121
+ stderr_hash: z.string().describe("stderr 的 SHA256 hash"),
122
+ started_at: z.string().describe("命令开始时间 ISO 8601"),
123
+ finished_at: z.string().describe("命令结束时间 ISO 8601"),
124
+ evidence_id: z.string().describe("执行证据 ID"),
125
+ })).describe("真实执行记录列表"),
126
+ };
95
127
  const DeliverSchema = {
96
128
  task_id: z.string().describe("任务 ID"),
97
129
  changed_files: z.array(z.string()).optional().describe("变更文件列表(不传则使用任务记录中的文件)"),
@@ -161,14 +193,14 @@ const ExploreSchema = {
161
193
  * @param server - McpServer 实例
162
194
  * @param deps - 工具依赖项(配置、知识索引、任务上下文)
163
195
  */
164
- export function registerTools(server, deps) {
196
+ export async function registerTools(server, deps) {
165
197
  console.error("[soloForge] 工具注册: 开始注册 MCP 工具...");
166
198
  const { config, knowledgeIndex, taskContext } = deps;
167
199
  const projectPath = config._projectPath || process.cwd();
168
200
  // H1: LLM Gateway — Token 预算熔断,防止单任务 Token 超支
169
- const gateway = deps.gateway ?? new LLMGateway();
201
+ const gateway = deps.gateway ?? new (await lazyLLM()).LLMGateway();
170
202
  // H4: IO Controller — 工作区互斥锁,防止外部修改导致的静默覆盖
171
- const ioController = new IOController(projectPath);
203
+ const ioController = new (await lazyIO()).IOController(projectPath);
172
204
  // ── 统一网关 : 唯一工具调用边界 ──
173
205
  /** 计算 sf_status cancel 的动态 category */
174
206
  function computeEffectiveCategory(toolName, args, contract) {
@@ -187,48 +219,50 @@ export function registerTools(server, deps) {
187
219
  /** State precheck: validate task status before contract guard */
188
220
  const STATE_PRECHECKS = {
189
221
  sf_verify: ["executing", "retrying"],
222
+ sf_record_verification_execution: ["verifying", "executing"],
190
223
  sf_learn: ["verifying", "executing"],
191
224
  sf_expand: ["classifying", "expanding", "clarifying"],
192
225
  };
193
226
  const STATE_ERROR_LABELS = {
194
227
  sf_verify: "不可验证",
228
+ sf_record_verification_execution: "不可录入验证结果",
195
229
  sf_learn: "不可学习",
196
230
  sf_expand: "不可膨胀",
197
231
  };
198
232
  /** 授权模型: explicit > dynamic write gate > destructive gate > workflow gate > category default */
199
233
  function checkAuth(toolName, args, contract, ctx, effectiveCategory) {
200
- // 1. Explicit confirmation
234
+ // 1. 显式确认
201
235
  if (args.confirm === true || args.authorized === true || args.authorization_token) {
202
236
  return { required: true, granted: true, reason: "explicit confirmation" };
203
237
  }
204
- // 2. Dynamic write upgrade: cancel/job_cancel from read_only to write → must confirm
238
+ // 2. 动态写入升级: cancel/job_cancel read_only 变为 write → 必须确认
205
239
  if (effectiveCategory && effectiveCategory !== contract.category && effectiveCategory !== "read_only_bypass") {
206
240
  return { required: true, granted: false, reason: "dynamic write upgrade requires explicit confirmation" };
207
241
  }
208
- // 3. Destructive side effects always require explicit
242
+ // 3. 破坏性副作用始终需要显式确认
209
243
  const destructive = ["git_commit", "git_push", "pr_create", "external_write"];
210
244
  if (contract.side_effects.some((e) => destructive.includes(e))) {
211
245
  return { required: true, granted: false, reason: "destructive side effects require explicit confirmation" };
212
246
  }
213
- // 4. Standalone strict tools (no workflow required, no task context) handler does own checks
247
+ // 4. 独立严格工具(无 workflow 要求,无 task context)→ handler 自行检查
214
248
  if (contract.category === "strict_controlled" && !ctx && !contract.requires_workflow) {
215
249
  return { required: false, granted: true, reason: "standalone strict tool" };
216
250
  }
217
- // 5. Workflow contract gate for strict_controlled
251
+ // 5. strict_controlled workflow 合同门控
218
252
  if (contract.category === "strict_controlled" && ctx?.last_tool_trace) {
219
253
  const allowed = ctx.last_tool_trace.next_allowed_tools ?? [];
220
254
  if (allowed.includes(toolName)) {
221
255
  return { required: true, granted: true, reason: "workflow contract gate" };
222
256
  }
223
257
  }
224
- // 5b. State-based fallback: strict tool with valid-state task but no tool_trace
258
+ // 5b. 基于状态的回退: 严格工具且任务处于有效状态但无 tool_trace
225
259
  if (contract.category === "strict_controlled" && ctx && !ctx.last_tool_trace && contract.requires_workflow) {
226
260
  const validStates = STATE_PRECHECKS[toolName];
227
261
  if (validStates && validStates.includes(ctx.status)) {
228
262
  return { required: true, granted: true, reason: "task in valid state for tool" };
229
263
  }
230
264
  }
231
- // 5c. Non-strict tools: auto-grant unless requires_authorization
265
+ // 5c. 非严格工具: 自动授权,除非 requires_authorization
232
266
  if (contract.category === "read_only_bypass" || contract.category === "normal_controlled") {
233
267
  if (contract.requires_authorization) {
234
268
  return { required: true, granted: false, reason: "tool requires explicit authorization" };
@@ -242,7 +276,7 @@ export function registerTools(server, deps) {
242
276
  const invocationId = `inv-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
243
277
  const taskId = args.task_id;
244
278
  const contract = findToolInvocationContractByName(name);
245
- // No contract → hard fail
279
+ // 无合同 → hard fail
246
280
  if (!contract) {
247
281
  return {
248
282
  content: [{ type: "text", text: JSON.stringify({ error: `工具 ${name} 未注册契约` }) }],
@@ -251,12 +285,12 @@ export function registerTools(server, deps) {
251
285
  }
252
286
  const effectiveCategory = computeEffectiveCategory(name, args, contract);
253
287
  const effectiveSideEffects = computeEffectiveSideEffects(name, args, contract);
254
- // Load TaskContext
288
+ // 加载 TaskContext
255
289
  let ctx = null;
256
290
  if (taskId) {
257
291
  ctx = await taskContext.load(taskId);
258
292
  }
259
- // State precheck: validate task status before contract guard
293
+ // 状态预检: 在合同守卫之前验证任务状态
260
294
  if (taskId && STATE_PRECHECKS[name] && ctx) {
261
295
  const validStates = STATE_PRECHECKS[name];
262
296
  if (!validStates.includes(ctx.status)) {
@@ -270,7 +304,7 @@ export function registerTools(server, deps) {
270
304
  };
271
305
  }
272
306
  }
273
- // Strict controlled without task_id
307
+ // 严格受控但缺少 task_id
274
308
  const isStandaloneStrict = !contract.requires_workflow;
275
309
  if (contract.category === "strict_controlled" && !taskId && !isStandaloneStrict) {
276
310
  return {
@@ -278,11 +312,11 @@ export function registerTools(server, deps) {
278
312
  isError: true,
279
313
  };
280
314
  }
281
- // Authorization
315
+ // 授权检查
282
316
  const authorization = checkAuth(name, args, contract, ctx ?? undefined, effectiveCategory);
283
- // Authorization denied → hard fail for gateway-level denials only
284
- // (dynamic write upgrade, destructive ops, strict_controlled with no auth source)
285
- // Handler-level authorization (e.g. sf_capability_update confirm) is left to the handler
317
+ // 授权拒绝仅对网关级拒绝执行 hard fail
318
+ // (动态写入升级、破坏性操作、无授权源的 strict_controlled
319
+ // Handler 级授权(如 sf_capability_update confirm)由 handler 自行处理
286
320
  const gatewayDenial = !authorization.granted &&
287
321
  authorization.reason !== "tool requires explicit authorization";
288
322
  if (gatewayDenial) {
@@ -312,17 +346,17 @@ export function registerTools(server, deps) {
312
346
  isError: true,
313
347
  };
314
348
  }
315
- // Bypass for read_only_bypass
349
+ // read_only_bypass 的旁路处理
316
350
  const bypass = effectiveCategory === "read_only_bypass"
317
351
  ? { allowed: true, reason: "read_only" } : undefined;
318
- // Contract validation
352
+ // 合同验证
319
353
  const lastTrace = ctx?.last_tool_trace;
320
- // Build effective contract override for dynamic tools (e.g., sf_status cancel)
354
+ // 为动态工具构建有效的合同覆盖(如 sf_status cancel
321
355
  let contractOverride;
322
356
  if (effectiveCategory !== contract.category || effectiveSideEffects !== contract.side_effects) {
323
357
  contractOverride = { ...contract, category: effectiveCategory, side_effects: effectiveSideEffects };
324
358
  }
325
- // Workflow ID: only from real expansion trace
359
+ // Workflow ID: 仅来自真实的 expansion trace
326
360
  const explicitWorkflowId = ctx?.expansion?.workflow_trace?.workflow_id;
327
361
  const violations = validateToolInvocation({
328
362
  tool_name: name,
@@ -334,7 +368,7 @@ export function registerTools(server, deps) {
334
368
  workflow_id: explicitWorkflowId,
335
369
  _contractOverride: contractOverride,
336
370
  });
337
- // State-based fallback: downgrade contract_state_mismatch from hard_fail to require_human
371
+ // 基于状态的回退: contract_state_mismatch hard_fail 降级为 require_human
338
372
  if (authorization.reason === "task in valid state for tool") {
339
373
  for (const v of violations) {
340
374
  if (v.violation_type === "contract_state_mismatch" && v.severity === "hard_fail") {
@@ -343,7 +377,7 @@ export function registerTools(server, deps) {
343
377
  }
344
378
  }
345
379
  }
346
- // Hard-fail violationsblock
380
+ // Hard-fail 违规阻止
347
381
  const hardFail = violations.find(v => v.severity === "hard_fail");
348
382
  if (hardFail) {
349
383
  const blockedTrace = createToolTrace({
@@ -366,17 +400,17 @@ export function registerTools(server, deps) {
366
400
  isError: true,
367
401
  };
368
402
  }
369
- // Execute handler
403
+ // 执行 handler
370
404
  try {
371
405
  const raw = await handler(args);
372
- // Pass through if handler returned { content } directly
406
+ // 如果 handler 直接返回 { content } 则透传
373
407
  if (raw && typeof raw === "object" && "content" in raw && Array.isArray(raw.content)) {
374
408
  return raw;
375
409
  }
376
- // Extract data from { result } pattern
410
+ // { result } 模式中提取数据
377
411
  const data = raw?.result !== undefined ? raw.result : raw;
378
412
  const hasError = !!(data && typeof data === "object" && "error" in data);
379
- // Build trace
413
+ // 构建 trace
380
414
  const trace = createToolTrace({
381
415
  tool_name: name, invocation_id: invocationId, task_id: taskId,
382
416
  workflow_id: ctx?.expansion?.workflow_trace?.workflow_id,
@@ -385,18 +419,18 @@ export function registerTools(server, deps) {
385
419
  forbidden_tools: contract.forbidden_next_tools,
386
420
  authorization, bypass,
387
421
  });
388
- // Write trace to TaskContext
422
+ // trace 写入 TaskContext
389
423
  if (taskId) {
390
424
  await taskContext.setToolTrace(taskId, trace, violations.length > 0 ? violations : undefined);
391
425
  }
392
- // Decorate response with trace + next/forbidden
426
+ // trace + next/forbidden 装饰响应
393
427
  const response = {
394
428
  ...data,
395
429
  tool_trace: trace,
396
430
  next_allowed_tools: contract.default_next_tools,
397
431
  forbidden_tools: contract.forbidden_next_tools,
398
432
  };
399
- // State-based fallback: expose degraded workflow in response
433
+ // 基于状态的回退: 在响应中暴露降级 workflow
400
434
  if (authorization.reason === "task in valid state for tool") {
401
435
  response.degraded_workflow = true;
402
436
  response.workflow_source = "state-based-fallback";
@@ -433,14 +467,14 @@ export function registerTools(server, deps) {
433
467
  });
434
468
  }
435
469
  // 加载认知锚点上下文 — 必须提供相关性参数,禁止全量加载
436
- function loadRelevantAnchors(query) {
470
+ async function loadRelevantAnchors(query) {
437
471
  console.error("[soloForge] 工具注册: 加载认知锚点");
438
472
  return _loadRelevantAnchorsInner(query);
439
473
  }
440
- function _loadRelevantAnchorsInner(query) {
474
+ async function _loadRelevantAnchorsInner(query) {
441
475
  const stateDir = taskContext.getStateDir();
442
476
  const mapPath = path.join(stateDir, "cognitive.map.json");
443
- const mapData = readMapJson(mapPath);
477
+ const mapData = (await lazyAnchor()).readMapJson(mapPath);
444
478
  if (!mapData || mapData.anchors.length === 0)
445
479
  return undefined;
446
480
  const existingFiles = new Set();
@@ -454,15 +488,15 @@ export function registerTools(server, deps) {
454
488
  }
455
489
  }
456
490
  catch { /* ignore */ }
457
- const checked = checkAnchorStaleness(mapData.anchors, existingFiles);
491
+ const checked = (await lazyAnchor()).checkAnchorStaleness(mapData.anchors, existingFiles);
458
492
  // 必须有 module 或 file_paths,否则不返回任何锚点(禁止全量加载)
459
493
  if (!query.module && (!query.file_paths || query.file_paths.length === 0))
460
494
  return undefined;
461
- // Collect anchors matching ANY of the provided file_paths or module
495
+ // 收集与任意提供的 file_paths module 匹配的锚点
462
496
  const seen = new Set();
463
497
  const relevant = [];
464
498
  if (query.module) {
465
- for (const a of filterRelevantAnchors(checked, { module: query.module })) {
499
+ for (const a of (await lazyAnchor()).filterRelevantAnchors(checked, { module: query.module })) {
466
500
  if (!seen.has(a.anchor_id)) {
467
501
  seen.add(a.anchor_id);
468
502
  relevant.push(a);
@@ -471,7 +505,7 @@ export function registerTools(server, deps) {
471
505
  }
472
506
  if (query.file_paths) {
473
507
  for (const fp of query.file_paths) {
474
- for (const a of filterRelevantAnchors(checked, { file_path: fp })) {
508
+ for (const a of (await lazyAnchor()).filterRelevantAnchors(checked, { file_path: fp })) {
475
509
  if (!seen.has(a.anchor_id)) {
476
510
  seen.add(a.anchor_id);
477
511
  relevant.push(a);
@@ -508,10 +542,10 @@ export function registerTools(server, deps) {
508
542
  // 创建任务上下文
509
543
  const ctx = await taskContext.create(args.intent, config.product_profile);
510
544
  const input = { intent: args.intent, project_path: projectPath, task_id: ctx.task_id };
511
- const classification = classify(input);
545
+ const classification = (await lazyClassifier()).classify(input);
512
546
  // 存储分类结果
513
547
  await taskContext.setClassification(ctx.task_id, classification);
514
- if (!shouldEnterSoloForge(classification.route_decision)) {
548
+ if (!(await lazyIntentRouter()).shouldEnterSoloForge(classification.route_decision)) {
515
549
  await taskContext.updateStatus(ctx.task_id, "done");
516
550
  }
517
551
  return {
@@ -577,7 +611,7 @@ export function registerTools(server, deps) {
577
611
  }
578
612
  let expansion;
579
613
  try {
580
- expansion = await expand({
614
+ expansion = await (await lazyExpander()).expand({
581
615
  intent: ctx.intent,
582
616
  classification: ctx.classification,
583
617
  projectPath,
@@ -610,14 +644,22 @@ export function registerTools(server, deps) {
610
644
  // Privacy Gate: 隐私/敏感信息策略阻断
611
645
  const isBlocked = expansion.prompt.startsWith("## 阻塞:输入材料禁止读取")
612
646
  || expansion.prompt.startsWith("## 阻塞:隐私/敏感信息策略");
613
- const isMaterialClarification = expansion.prompt.startsWith("## 澄清请求") && expansion.input_materials?.some((m) => m.access_mode !== "forbidden" && classifyIngestionStatus(m.path_or_ref) === "requires_confirmation");
647
+ let isMaterialClarification = false;
648
+ if (expansion.prompt.startsWith("## 澄清请求") && expansion.input_materials) {
649
+ for (const m of expansion.input_materials) {
650
+ if (m.access_mode !== "forbidden" && (await lazyInputMaterial()).classifyIngestionStatus(m.path_or_ref) === "requires_confirmation") {
651
+ isMaterialClarification = true;
652
+ break;
653
+ }
654
+ }
655
+ }
614
656
  // 注入 H1/H4 advisory warnings
615
657
  const advisories = {};
616
658
  if (h1Warning)
617
659
  advisories.h1_advisory = h1Warning;
618
660
  if (h4LockWarning)
619
661
  advisories.h4_advisory = h4LockWarning;
620
- // Config precedence warnings
662
+ // 配置优先级警告
621
663
  if (expansion.config_resolution_reports && expansion.config_resolution_reports.length > 0) {
622
664
  const configWarnings = expansion.config_resolution_reports
623
665
  .filter(r => r.conflicts.length > 0)
@@ -627,7 +669,7 @@ export function registerTools(server, deps) {
627
669
  }
628
670
  }
629
671
  // 决策契约 advisory: 校验 expand 输出是否包含默认决策字段
630
- const decisionContract = validateDecisionOutput(expansion);
672
+ const decisionContract = (await lazyDecision()).validateDecisionOutput(expansion);
631
673
  if (!decisionContract.passed) {
632
674
  advisories.decision_contract_advisory = decisionContract.advisory;
633
675
  }
@@ -684,7 +726,7 @@ export function registerTools(server, deps) {
684
726
  result: { error: "任务不存在" },
685
727
  };
686
728
  }
687
- // RouteDecision contract verification unconditional, before state precheck
729
+ // RouteDecision 合同验证无条件,在状态预检之前
688
730
  const rdFromCtx = ctx.route_decision ?? ctx.classification?.route_decision ?? null;
689
731
  const wtFromCtx = ctx.workflow_trace ?? ctx.expansion?.workflow_trace ?? null;
690
732
  const rdContractInput = {
@@ -719,13 +761,30 @@ export function registerTools(server, deps) {
719
761
  const h4Warning = !integrity.clean
720
762
  ? { warning: `H4 advisory: ${integrity.message}`, dirty_files: integrity.dirty_files }
721
763
  : undefined;
722
- const verifyResult = generateVerifyCommands(config, args.changed_files, acceptanceItems, ctx?.expansion?.workflow_trace?.route);
764
+ const verifyResult = (await lazyVerifier()).generateVerifyCommands(config, args.changed_files, acceptanceItems, ctx?.expansion?.workflow_trace?.route);
723
765
  verifyResult.task_id = args.task_id;
724
- // Artifact lifecycle check : draft → verified requires ArtifactVerificationResult.passed
766
+ // Batch2: 创建 VerificationPlan(plan_only,非执行结果)
767
+ const vcModule = await lazyVerificationContract();
768
+ const allCommands = [
769
+ ...(verifyResult.checks?.build ?? []),
770
+ ...(verifyResult.checks?.tests ?? []),
771
+ ].map((c) => c.command);
772
+ const batch2Plan = vcModule.createVerificationPlan(args.task_id, allCommands, acceptanceItems.map((a) => a.description));
773
+ // Batch2: sf_verify 仅生成计划,不执行命令 — 始终保存 not_executed
774
+ // 真实执行结果必须通过 recordVerificationExecution 单独录入
775
+ const batch2Result = vcModule.createNotExecutedResult(args.task_id, batch2Plan.plan_id, "sf_verify 生成命令,等待执行");
776
+ // 存储 Batch2 验证契约到任务上下文
777
+ const ctxForBatch2 = await taskContext.load(args.task_id);
778
+ if (ctxForBatch2) {
779
+ ctxForBatch2.batch2_verification_plan = batch2Plan;
780
+ ctxForBatch2.batch2_verification_result = batch2Result;
781
+ await taskContext.save(ctxForBatch2);
782
+ }
783
+ // 产物生命周期检查: draft → verified 需要 ArtifactVerificationResult.passed
725
784
  let artifactVerificationResult;
726
785
  let artifactFileMissing = false;
727
786
  if (ctx.artifact_output && ctx.artifact_output.status === "draft") {
728
- // Resolve artifact file and compute hash before verification
787
+ // 验证前解析产物文件并计算 hash
729
788
  const artifact = ctx.artifact_output;
730
789
  const fullPath = path.join(projectPath, artifact.path);
731
790
  if (fss.existsSync(fullPath)) {
@@ -735,7 +794,7 @@ export function registerTools(server, deps) {
735
794
  if (!artifact.evidence_refs.some(r => r.startsWith("file:artifact:"))) {
736
795
  artifact.evidence_refs.push(`file:artifact:path=${artifact.path} hash=sha256:${hash}`);
737
796
  }
738
- // Save updated artifact with hash
797
+ // 保存更新后的产物(含 hash
739
798
  const ctxForHash = await taskContext.load(args.task_id);
740
799
  if (ctxForHash?.artifact_output) {
741
800
  ctxForHash.artifact_output.hash = artifact.hash;
@@ -751,8 +810,25 @@ export function registerTools(server, deps) {
751
810
  artifactVerificationResult = verifyArtifact(artifact.kind, artifact);
752
811
  }
753
812
  // 记录变更文件
813
+ // Batch2: 写入护栏 — 检查变更文件是否在允许范围
814
+ if (args.changed_files.length > 0) {
815
+ const guardModule = await lazyEnforcementGuard();
816
+ const scopePaths = ctx.expansion?.scope?.allowed_paths ?? [];
817
+ for (const cf of args.changed_files) {
818
+ const writeFindings = guardModule.evaluateWriteGuard(ctx.classification?.route_decision?.route ?? "code_execution", cf, scopePaths, "command_execution_contract");
819
+ if (writeFindings.some((f) => f.blocked)) {
820
+ return {
821
+ result: {
822
+ error: `Batch2 写入护栏阻断: ${writeFindings[0].reason_zh}`,
823
+ blocked_file: cf,
824
+ guard_id: writeFindings[0].guard_id,
825
+ },
826
+ };
827
+ }
828
+ }
829
+ }
754
830
  await taskContext.setExecution(args.task_id, args.changed_files);
755
- // Mark no_change_artifact when no real files changed but artifact exists
831
+ // 无实际文件变更但存在产物时标记 no_change_artifact
756
832
  if (args.changed_files.length === 0 && ctx.artifact_output) {
757
833
  const execCtx = await taskContext.load(args.task_id);
758
834
  if (execCtx?.execution) {
@@ -767,7 +843,7 @@ export function registerTools(server, deps) {
767
843
  await taskContext.updateStatus(args.task_id, "verifying");
768
844
  // 存储验证结果
769
845
  await taskContext.setVerification(args.task_id, verifyResult);
770
- // Artifact lifecycle transition: draft → verified only if ArtifactVerificationResult.passed
846
+ // 产物生命周期转换: draft → verified 仅在 ArtifactVerificationResult.passed
771
847
  if (ctx.artifact_output && ctx.artifact_output.status === "draft" && artifactVerificationResult?.passed) {
772
848
  const evidenceRef = `verification:${ctx.task_id}:checks=${artifactVerificationResult.checks.length}:summary=${artifactVerificationResult.summary.slice(0, 60)}`;
773
849
  try {
@@ -778,11 +854,11 @@ export function registerTools(server, deps) {
778
854
  });
779
855
  }
780
856
  catch {
781
- // Transition blocked artifact stays draft, pipeline continues
857
+ // 转换被阻止产物保持 draft,流水线继续
782
858
  }
783
859
  }
784
860
  // 认知锚点上下文回放(按变更文件相关性)
785
- const verifyAnchors = loadRelevantAnchors({ file_paths: args.changed_files });
861
+ const verifyAnchors = await loadRelevantAnchors({ file_paths: args.changed_files });
786
862
  const verifyExtras = {};
787
863
  if (h4Warning)
788
864
  verifyExtras.h4_advisory = h4Warning;
@@ -795,13 +871,46 @@ export function registerTools(server, deps) {
795
871
  verifyExtras.artifact_warning = `产物验收检查未通过: ${reason}`;
796
872
  verifyExtras.artifact_verification = artifactVerificationResult;
797
873
  }
874
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
798
875
  const verifyPayload = Object.keys(verifyExtras).length > 0
799
876
  ? { ...verifyResult, ...verifyExtras }
800
- : verifyResult;
877
+ : { ...verifyResult };
878
+ // Batch2: 附加验证契约引用到返回结果
879
+ verifyPayload.batch2_verification_plan = batch2Plan;
880
+ verifyPayload.batch2_verification_result = batch2Result;
801
881
  return {
802
882
  result: verifyPayload,
803
883
  };
804
884
  });
885
+ // ── sf_record_verification_execution: 录入真实验证执行结果(唯一 passed 入口) ──
886
+ registerSafeTool("sf_record_verification_execution", "录入真实验证执行结果,VerificationResult.status=passed 的唯一合法入口", RecordVerificationExecutionSchema, async (args) => {
887
+ const ctx = await taskContext.load(args.task_id);
888
+ if (!ctx) {
889
+ return { result: { error: "任务不存在" } };
890
+ }
891
+ // 必须有 VerificationPlan
892
+ if (!ctx.batch2_verification_plan) {
893
+ return { result: { error: "任务无 VerificationPlan,先执行 sf_verify 生成计划" } };
894
+ }
895
+ // plan_id 必须与 TaskContext 中当前 plan 一致
896
+ if (args.plan_id !== ctx.batch2_verification_plan.plan_id) {
897
+ return {
898
+ result: {
899
+ error: `plan_id 不匹配: 请求 "${args.plan_id}",当前任务计划 "${ctx.batch2_verification_plan.plan_id}" [SF-VERIFY-5002]`,
900
+ diagnostic_code: "SF-VERIFY-5002",
901
+ },
902
+ };
903
+ }
904
+ const vcModule = await lazyVerificationContract();
905
+ const result = vcModule.recordVerificationExecution(args.task_id, args.plan_id, args.execution_records, ctx.batch2_verification_plan);
906
+ // 持久化到 TaskContext
907
+ const ctxForSave = await taskContext.load(args.task_id);
908
+ if (ctxForSave) {
909
+ ctxForSave.batch2_verification_result = result;
910
+ await taskContext.save(ctxForSave);
911
+ }
912
+ return { result };
913
+ });
805
914
  // ── sf_learn: 从执行结果中提取知识,支持重试循环控制 ──
806
915
  registerSafeTool("sf_learn", "从任务执行结果中提取知识,低置信度暂存,高置信度直接入库", LearnSchema, async (args) => {
807
916
  const ctx = await taskContext.load(args.task_id);
@@ -826,10 +935,37 @@ export function registerTools(server, deps) {
826
935
  : "unknown failure",
827
936
  timestamp: new Date().toISOString(),
828
937
  });
938
+ // Batch2: 创建 FailureReport(脱敏,非 raw error_output)
939
+ const frModule = await lazyFailureReport();
940
+ const failureClass = args.failure_type;
941
+ const errorOutput = args.verify_output
942
+ ? `build=${args.verify_output.build_passed} tests=${args.verify_output.tests_passed}`
943
+ : "unknown failure";
944
+ const retryCount = (ctx.execution?.attempt_count ?? 0) + 1;
945
+ const policy = frModule.getRecoveryPolicy(failureClass);
946
+ const batch2FailureReport = frModule.createFailureReport(args.task_id, failureClass, errorOutput, retryCount, policy?.max_retries ?? 0);
947
+ // 存储 FailureReport 到任务上下文
948
+ const ctxForFailure = await taskContext.load(args.task_id);
949
+ if (ctxForFailure) {
950
+ ctxForFailure.batch2_failure_report = batch2FailureReport;
951
+ await taskContext.save(ctxForFailure);
952
+ }
953
+ // Batch2: verifier 不可用时创建 DegradationEvent
954
+ if (!args.verify_output) {
955
+ const degModule = await lazyDegradation();
956
+ const degradationEvent = degModule.createDegradationEvent(args.task_id, "verifier", "full", "验证器输出不可用,无法判断 build/test 结果", ["verification_execution"]);
957
+ if (degradationEvent) {
958
+ const ctxForDeg = await taskContext.load(args.task_id);
959
+ if (ctxForDeg) {
960
+ ctxForDeg.batch2_degradation_event = degradationEvent;
961
+ await taskContext.save(ctxForDeg);
962
+ }
963
+ }
964
+ }
829
965
  }
830
966
  // 转换到学习阶段
831
967
  await taskContext.updateStatus(args.task_id, "learning");
832
- const learnResult = await evolve({
968
+ const learnResult = await (await lazyEvolver()).evolve({
833
969
  taskContext: ctx,
834
970
  result: args.result,
835
971
  verifyOutput: args.verify_output,
@@ -872,14 +1008,14 @@ export function registerTools(server, deps) {
872
1008
  // ── sf_status: 任务状态查询(current/recent/resume/cancel) ──
873
1009
  registerSafeTool("sf_status", "查询当前任务状态、列出近期任务、恢复中断任务或取消任务", StatusSchema, async (args) => {
874
1010
  const action = args.action || "current";
875
- // Job actions — advisory, independent of task actions
1011
+ // Job 操作 — advisory,独立于任务操作
876
1012
  if (args.job_action) {
877
1013
  if (!args.job_id) {
878
1014
  return {
879
1015
  result: { error: "job 操作需要 job_id" },
880
1016
  };
881
1017
  }
882
- const jm = new JobManager(taskContext.getStateDir());
1018
+ const jm = new (await lazyJob()).JobManager(taskContext.getStateDir());
883
1019
  const taskId = args.task_id ?? await jm.resolveTaskId(args.job_id) ?? "";
884
1020
  if (args.job_action === "job_status") {
885
1021
  const status = await jm.getJobStatus(args.job_id, taskId);
@@ -921,12 +1057,12 @@ export function registerTools(server, deps) {
921
1057
  };
922
1058
  }
923
1059
  }
924
- // Auto-fail stale non-terminal tasks before reading
1060
+ // 读取前自动将过期非终态任务标记为失败
925
1061
  try {
926
1062
  await taskContext.autoFailStale();
927
1063
  }
928
1064
  catch (e) {
929
- console.error("[soloForge] autoFailStale error:", e);
1065
+ console.error("[soloForge] autoFailStale 出错:", e);
930
1066
  }
931
1067
  switch (action) {
932
1068
  case "current": {
@@ -960,7 +1096,7 @@ export function registerTools(server, deps) {
960
1096
  }
961
1097
  // JobManager advisory: 查询关联 job 状态
962
1098
  try {
963
- const jm = new JobManager(taskContext.getStateDir());
1099
+ const jm = new (await lazyJob()).JobManager(taskContext.getStateDir());
964
1100
  const activeJobs = await jm.listActiveJobs();
965
1101
  const relatedJob = activeJobs.find((j) => j.task_id === ctx.task_id);
966
1102
  if (relatedJob) {
@@ -974,7 +1110,7 @@ export function registerTools(server, deps) {
974
1110
  }
975
1111
  }
976
1112
  catch {
977
- // JobManager advisory — ignore errors
1113
+ // JobManager advisory — 忽略错误
978
1114
  }
979
1115
  return {
980
1116
  result: result,
@@ -1012,7 +1148,7 @@ export function registerTools(server, deps) {
1012
1148
  if (ctx.execution)
1013
1149
  resumeResult.execution = ctx.execution;
1014
1150
  const resumeAnchors = ctx.execution?.changed_files
1015
- ? loadRelevantAnchors({ file_paths: ctx.execution.changed_files })
1151
+ ? await loadRelevantAnchors({ file_paths: ctx.execution.changed_files })
1016
1152
  : undefined;
1017
1153
  if (resumeAnchors && resumeAnchors.length > 0)
1018
1154
  resumeResult.cognitive_anchors = resumeAnchors;
@@ -1043,7 +1179,7 @@ export function registerTools(server, deps) {
1043
1179
  result: { error: "任务不存在或尚未分类" },
1044
1180
  };
1045
1181
  }
1046
- const result = planTask({
1182
+ const result = (await lazyPlanner()).planTask({
1047
1183
  intent: ctx.intent,
1048
1184
  classification: ctx.classification,
1049
1185
  config,
@@ -1105,7 +1241,7 @@ export function registerTools(server, deps) {
1105
1241
  result: { error: "任务尚未膨胀,请先调用 sf_expand" },
1106
1242
  };
1107
1243
  }
1108
- const result = await analyzeImpact({
1244
+ const result = await (await lazyImpact()).analyzeImpact({
1109
1245
  intent: ctx.intent,
1110
1246
  classification: ctx.classification,
1111
1247
  expansion: ctx.expansion,
@@ -1114,7 +1250,7 @@ export function registerTools(server, deps) {
1114
1250
  });
1115
1251
  result.task_id = args.task_id;
1116
1252
  // 决策契约 advisory: 校验 analyze 输出
1117
- const decisionContract = validateDecisionOutput(result);
1253
+ const decisionContract = (await lazyDecision()).validateDecisionOutput(result);
1118
1254
  const advisoryExtras = {};
1119
1255
  if (!decisionContract.passed) {
1120
1256
  advisoryExtras.decision_contract_advisory = decisionContract.advisory;
@@ -1129,8 +1265,8 @@ export function registerTools(server, deps) {
1129
1265
  result: { error: "任务不存在" },
1130
1266
  };
1131
1267
  }
1132
- const tracker = new DebtTracker(projectPath);
1133
- const result = await reviewCode({
1268
+ const tracker = new (await lazyDebt()).DebtTracker(projectPath);
1269
+ const result = await (await lazyReviewer()).reviewCode({
1134
1270
  changedFiles: args.changed_files,
1135
1271
  projectPath,
1136
1272
  config,
@@ -1142,7 +1278,7 @@ export function registerTools(server, deps) {
1142
1278
  result.task_id = args.task_id;
1143
1279
  await taskContext.setCodeReview(args.task_id, result);
1144
1280
  // 决策契约 advisory: 校验 review 输出
1145
- const decisionContract = validateDecisionOutput(result);
1281
+ const decisionContract = (await lazyDecision()).validateDecisionOutput(result);
1146
1282
  const reviewExtras = {};
1147
1283
  if (!decisionContract.passed) {
1148
1284
  reviewExtras.decision_contract_advisory = decisionContract.advisory;
@@ -1165,7 +1301,7 @@ export function registerTools(server, deps) {
1165
1301
  },
1166
1302
  };
1167
1303
  }
1168
- const result = await generateScaffold({
1304
+ const result = await (await lazyScaffolder()).generateScaffold({
1169
1305
  intent: ctx.intent,
1170
1306
  classification: ctx.classification,
1171
1307
  config,
@@ -1189,7 +1325,7 @@ export function registerTools(server, deps) {
1189
1325
  const h4DeliverWarning = !deliverIntegrity.clean
1190
1326
  ? { warning: `H4 advisory: ${deliverIntegrity.message}`, dirty_files: deliverIntegrity.dirty_files }
1191
1327
  : undefined;
1192
- // Artifact status gate : deliver requires artifact status = accepted with evidence
1328
+ // 产物状态门控: deliver 需要产物状态为 accepted 且有证据
1193
1329
  if (ctx.artifact_output) {
1194
1330
  const status = ctx.artifact_output.status;
1195
1331
  if (status === "draft") {
@@ -1210,7 +1346,7 @@ export function registerTools(server, deps) {
1210
1346
  },
1211
1347
  };
1212
1348
  }
1213
- // accepted must have confirmation evidence
1349
+ // accepted 必须有确认证据
1214
1350
  if (status === "accepted") {
1215
1351
  const hasAcceptanceEvidence = ctx.artifact_output.evidence_refs.some((r) => r.includes("acceptance") || r.includes("workflow_adoption"));
1216
1352
  if (!hasAcceptanceEvidence) {
@@ -1224,27 +1360,68 @@ export function registerTools(server, deps) {
1224
1360
  }
1225
1361
  }
1226
1362
  }
1227
- const result = await deliver({
1363
+ // Batch2: 交付 lease 互斥检查
1364
+ const leaseModule = await lazyWorkspaceLease();
1365
+ const deliverLease = leaseModule.acquireLease(args.task_id, "delivery", [projectPath]);
1366
+ if (deliverLease.lease?.status === "conflicted" || deliverLease.conflicts.length > 0) {
1367
+ return {
1368
+ result: {
1369
+ error: `交付 lease 冲突: ${deliverLease.conflicts.map((c) => `${c.conflict_type}: ${c.conflict_path}`).join(", ")}`,
1370
+ conflicts: deliverLease.conflicts,
1371
+ },
1372
+ };
1373
+ }
1374
+ // Batch2: 交付就绪评估 — delivery_allowed=false 必须阻断交付
1375
+ const drModule = await lazyDeliveryReadiness();
1376
+ const guardModule = await lazyEnforcementGuard();
1377
+ const guardFindings = guardModule.evaluateDeliveryReadinessGuard(ctx.batch2_verification_result, ctx.batch2_verification_plan);
1378
+ const readinessReport = drModule.evaluateDeliveryReadiness(args.task_id, ctx.batch2_verification_result, guardFindings, true, // scope_check — 已在 sf_verify 写入护栏中检查
1379
+ deliverLease.conflicts.length === 0, // lease_check — 无冲突即通过
1380
+ true, // privacy_check — 已在任务创建时脱敏
1381
+ true);
1382
+ // 保存就绪报告到任务上下文
1383
+ const ctxForReadiness = await taskContext.load(args.task_id);
1384
+ if (ctxForReadiness) {
1385
+ ctxForReadiness.batch2_delivery_readiness = readinessReport;
1386
+ await taskContext.save(ctxForReadiness);
1387
+ }
1388
+ if (!readinessReport.delivery_allowed) {
1389
+ // 释放 lease 并阻断交付
1390
+ if (deliverLease.lease) {
1391
+ leaseModule.releaseLease(deliverLease.lease.lease_id);
1392
+ }
1393
+ return {
1394
+ result: {
1395
+ error: `Batch2 交付就绪检查未通过: ${readinessReport.blocking_findings.map((f) => f.message_zh).join("; ")}`,
1396
+ delivery_readiness: readinessReport,
1397
+ },
1398
+ };
1399
+ }
1400
+ const result = await (await lazyDelivery()).deliver({
1228
1401
  taskContext: ctx,
1229
1402
  config,
1230
1403
  knowledgeIndex,
1231
1404
  projectPath,
1232
- gitOps: realGitOps,
1405
+ gitOps: (await lazyGitDeps()).realGitOps,
1233
1406
  skipPush: args.skip_push,
1234
1407
  skipPr: args.skip_pr,
1235
1408
  });
1236
1409
  await taskContext.setDelivery(args.task_id, result);
1410
+ // Batch2: 交付完成后释放 lease
1411
+ if (deliverLease.lease) {
1412
+ leaseModule.releaseLease(deliverLease.lease.lease_id);
1413
+ }
1237
1414
  return {
1238
1415
  result: h4DeliverWarning ? { ...result, h4_advisory: h4DeliverWarning } : result,
1239
1416
  };
1240
1417
  });
1241
1418
  // ── sf_coord_check: 预测性冲突检测和跨仓库协调 ──
1242
1419
  registerSafeTool("sf_coord_check", "预测性冲突检测和跨仓库协调提示,检查分支状态、本地变更和潜在冲突", CoordCheckSchema, async (args) => {
1243
- const result = await checkConflicts({
1420
+ const result = await (await lazyChangeCoord()).checkConflicts({
1244
1421
  projectPath,
1245
1422
  config,
1246
1423
  branch: args.branch,
1247
- gitOps: realGitOps,
1424
+ gitOps: (await lazyGitDeps()).realGitOps,
1248
1425
  });
1249
1426
  return {
1250
1427
  result: result,
@@ -1252,11 +1429,11 @@ export function registerTools(server, deps) {
1252
1429
  });
1253
1430
  // ── sf_team_status: 团队活动流和工作负载查询 ──
1254
1431
  registerSafeTool("sf_team_status", "查询团队活动流、成员工作负载、过期分支和知识库更新状态", TeamStatusSchema, async (args) => {
1255
- const result = await getTeamStatus({
1432
+ const result = await (await lazyTeam()).getTeamStatus({
1256
1433
  projectPath,
1257
1434
  config,
1258
1435
  since: args.since,
1259
- gitOps: realGitOps,
1436
+ gitOps: (await lazyGitDeps()).realGitOps,
1260
1437
  knowledgeIndex: args.include_knowledge ? knowledgeIndex : undefined,
1261
1438
  });
1262
1439
  return {
@@ -1270,11 +1447,11 @@ export function registerTools(server, deps) {
1270
1447
  const ctx = await taskContext.load(args.task_id);
1271
1448
  changedFiles = ctx?.execution?.changed_files ?? [];
1272
1449
  }
1273
- const result = await checkContractChanges({
1450
+ const result = await (await lazyContractGuard()).checkContractChanges({
1274
1451
  changedFiles,
1275
1452
  projectPath,
1276
1453
  config,
1277
- gitOps: realGitOps,
1454
+ gitOps: (await lazyGitDeps()).realGitOps,
1278
1455
  });
1279
1456
  return {
1280
1457
  result: result,
@@ -1282,11 +1459,11 @@ export function registerTools(server, deps) {
1282
1459
  });
1283
1460
  // ── sf_onboard: 新人分步引导 ──
1284
1461
  registerSafeTool("sf_onboard", "新人分步引导:项目概览 → 代码导览 → 知识回顾 → 首个任务建议", OnboardSchema, async (args) => {
1285
- const result = await onboard({
1462
+ const result = await (await lazyOnboarding()).onboard({
1286
1463
  config,
1287
1464
  projectPath,
1288
1465
  knowledgeIndex,
1289
- gitOps: realGitOps,
1466
+ gitOps: (await lazyGitDeps()).realGitOps,
1290
1467
  currentStep: args.step,
1291
1468
  reset: args.reset,
1292
1469
  });
@@ -1302,7 +1479,7 @@ export function registerTools(server, deps) {
1302
1479
  result: { error: "任务不存在或未完成分类,请先调用 sf_classify" },
1303
1480
  };
1304
1481
  }
1305
- const result = checkFeasibility(ctx.classification, config);
1482
+ const result = (await lazyFeasibility()).checkFeasibility(ctx.classification, config);
1306
1483
  return {
1307
1484
  result: result,
1308
1485
  };
@@ -1313,7 +1490,7 @@ export function registerTools(server, deps) {
1313
1490
  ...config.scope.backend,
1314
1491
  ...config.scope.frontend,
1315
1492
  ];
1316
- const result = debugError(args.error_output, args.task_id || `debug-${Date.now()}`, projectScope);
1493
+ const result = (await lazyDebugger()).debugError(args.error_output, args.task_id || `debug-${Date.now()}`, projectScope);
1317
1494
  return {
1318
1495
  result: result,
1319
1496
  };
@@ -1321,8 +1498,8 @@ export function registerTools(server, deps) {
1321
1498
  // ── sf_observability: 系统可观测和运行报告 ──
1322
1499
  registerSafeTool("sf_observability", "系统可观测:运行指标、成本估算、告警检测、能力状态、周期报告", ObservabilitySchema, async (args) => {
1323
1500
  const stateDir = taskContext.getStateDir();
1324
- const result = await generateReport(stateDir, args.period_days);
1325
- const capability = getCapabilitySummary();
1501
+ const result = await (await lazyObservability()).generateReport(stateDir, args.period_days);
1502
+ const capability = (await lazyCapability()).getSummary();
1326
1503
  const output = { ...result, capability };
1327
1504
  return {
1328
1505
  result: output,
@@ -1330,36 +1507,36 @@ export function registerTools(server, deps) {
1330
1507
  });
1331
1508
  // ── sf_migration_check: 数据库迁移安全性分析 ──
1332
1509
  registerSafeTool("sf_migration_check", "分析数据库迁移文件安全性:检测破坏性操作(DROP/DELETE/TRUNCATE)并生成回滚建议", MigrationCheckSchema, async (args) => {
1333
- const result = analyzeMigration(args.content, args.filename);
1510
+ const result = (await lazyMigration()).analyzeMigration(args.content, args.filename);
1334
1511
  return {
1335
1512
  result: result,
1336
1513
  };
1337
1514
  });
1338
1515
  // ── sf_test_guide: 基于变更文件生成测试指引 ──
1339
1516
  registerSafeTool("sf_test_guide", "根据变更文件类型生成测试指引:推荐测试类型、场景、Mock 点和断言模板", TestGuideSchema, async (args) => {
1340
- const result = generateTestGuide(args.changed_files, [], config);
1517
+ const result = (await lazyTestGen()).generateTestGuide(args.changed_files, [], config);
1341
1518
  return {
1342
1519
  result: result,
1343
1520
  };
1344
1521
  });
1345
1522
  // ── sf_test_quality: 测试文件质量五维评分 ──
1346
1523
  registerSafeTool("sf_test_quality", "评估测试文件质量:断言密度、边界覆盖、命名、重复率、场景覆盖五维评分", TestQualitySchema, async (args) => {
1347
- const result = analyzeTestQuality(args.content, args.filename);
1524
+ const result = (await lazyTestQuality()).analyzeTestQuality(args.content, args.filename);
1348
1525
  return {
1349
1526
  result: result,
1350
1527
  };
1351
1528
  });
1352
1529
  // ── sf_dependency_scan: 依赖漏洞扫描 ──
1353
1530
  registerSafeTool("sf_dependency_scan", "扫描依赖声明文件漏洞:已知 CVE 规则匹配、未锁定版本检测、支持 npm/maven/gradle", DependencyScanSchema, async (args) => {
1354
- const result = scanDependencies(args.content, args.filename);
1531
+ const result = (await lazyDepScan()).scanDependencies(args.content, args.filename);
1355
1532
  return {
1356
1533
  result: result,
1357
1534
  };
1358
1535
  });
1359
1536
  // ── sf_debt_report: 技术债务报告生成 ──
1360
1537
  registerSafeTool("sf_debt_report", "生成技术债务报告:按分类/严重度聚合、30 天趋势、优先级排序 Top 5", {}, async () => {
1361
- const tracker = new DebtTracker(projectPath);
1362
- const result = await generateDebtReport(tracker);
1538
+ const tracker = new (await lazyDebt()).DebtTracker(projectPath);
1539
+ const result = await (await lazyDebtReport()).generateDebtReport(tracker);
1363
1540
  return {
1364
1541
  result: result,
1365
1542
  };
@@ -1371,14 +1548,14 @@ export function registerTools(server, deps) {
1371
1548
  const ctx = await taskContext.load(args.task_id);
1372
1549
  classification = ctx?.classification;
1373
1550
  }
1374
- const result = exploreSolutions({
1551
+ const result = (await lazyExploration()).exploreSolutions({
1375
1552
  domain_query: args.domain_query,
1376
1553
  projectConfig: config,
1377
1554
  classification,
1378
1555
  knowledgeIndex,
1379
1556
  });
1380
1557
  // 决策契约 advisory: sf_explore 应始终通过(10 字段已内置)
1381
- const decisionContract = validateDecisionOutput(result);
1558
+ const decisionContract = (await lazyDecision()).validateDecisionOutput(result);
1382
1559
  const exploreExtras = {};
1383
1560
  if (!decisionContract.passed) {
1384
1561
  exploreExtras.decision_contract_advisory = decisionContract.advisory;
@@ -1387,7 +1564,7 @@ export function registerTools(server, deps) {
1387
1564
  });
1388
1565
  // ── sf_knowledge_audit: 知识库健康审计 ──
1389
1566
  registerSafeTool("sf_knowledge_audit", "审计知识库:识别过时条目、重复触发词、格式缺失、覆盖缺口。定期执行或手动触发", {}, async () => {
1390
- const result = await auditKnowledge(knowledgeIndex, config);
1567
+ const result = await (await lazyKnowledge()).auditKnowledge(knowledgeIndex, config);
1391
1568
  return {
1392
1569
  result: result,
1393
1570
  };
@@ -1403,7 +1580,7 @@ export function registerTools(server, deps) {
1403
1580
  auto_enrich: z.boolean().optional().describe("是否返回行业最佳实践探索指引(默认 true,宿主 AI 将自动执行探索并填充内容)"),
1404
1581
  };
1405
1582
  registerSafeTool("sf_knowledge_add", "新增知识条目。默认保存为草稿到 .soloforge/knowledge/drafts/,人工确认后移入正式目录", KnowledgeAddSchema, async (args) => {
1406
- const result = await addKnowledge({
1583
+ const result = await (await lazyKnowledge()).addKnowledge({
1407
1584
  title: args.title,
1408
1585
  type: args.type,
1409
1586
  scope: args.scope,
@@ -1425,7 +1602,7 @@ export function registerTools(server, deps) {
1425
1602
  status: z.enum(["active", "deprecated"]).optional().describe("更新条目状态"),
1426
1603
  };
1427
1604
  registerSafeTool("sf_knowledge_update", "更新已有知识条目:追加规则、更新触发词、标记废弃。自动创建备份", KnowledgeUpdateSchema, async (args) => {
1428
- const result = await updateKnowledge({
1605
+ const result = await (await lazyKnowledge()).updateKnowledge({
1429
1606
  entry_name: args.entry_name,
1430
1607
  updates: {
1431
1608
  when_triggers: args.when_triggers,
@@ -1444,13 +1621,13 @@ export function registerTools(server, deps) {
1444
1621
  });
1445
1622
  // ── sf_resume_workspace: 工作区状态唤醒(解决前端刷新导致UUID丢失) ──
1446
1623
  registerSafeTool("sf_resume_workspace", "扫描 .soloforge/state/ 目录,恢复中断工单并播报当前进度。新会话启动时必须优先调用", {}, async () => {
1447
- const result = await scanAndResume(taskContext);
1624
+ const result = await (await lazyWorkspaceResumer()).scanAndResume(taskContext);
1448
1625
  // 认知锚点:按恢复任务的 changed_files 相关性加载,禁止全量
1449
1626
  if (result.task) {
1450
1627
  const ctx = await taskContext.load(result.task.task_id);
1451
1628
  const changedFiles = ctx?.execution?.changed_files;
1452
1629
  if (changedFiles && changedFiles.length > 0) {
1453
- const anchors = loadRelevantAnchors({ file_paths: changedFiles });
1630
+ const anchors = await loadRelevantAnchors({ file_paths: changedFiles });
1454
1631
  if (anchors && anchors.length > 0) {
1455
1632
  result.cognitive_anchors = anchors;
1456
1633
  }
@@ -1458,7 +1635,7 @@ export function registerTools(server, deps) {
1458
1635
  }
1459
1636
  // JobManager advisory: 查询活跃 jobs
1460
1637
  try {
1461
- const jm = new JobManager(taskContext.getStateDir());
1638
+ const jm = new (await lazyJob()).JobManager(taskContext.getStateDir());
1462
1639
  const activeJobs = await jm.listActiveJobs();
1463
1640
  if (activeJobs.length > 0) {
1464
1641
  result.active_jobs = activeJobs.map((j) => ({
@@ -1472,7 +1649,7 @@ export function registerTools(server, deps) {
1472
1649
  }
1473
1650
  }
1474
1651
  catch {
1475
- // JobManager advisory — ignore errors
1652
+ // JobManager advisory — 忽略错误
1476
1653
  }
1477
1654
  return {
1478
1655
  result: result,
@@ -1484,10 +1661,10 @@ export function registerTools(server, deps) {
1484
1661
  };
1485
1662
  registerSafeTool("sf_audit_sample", "从审计池按风险加权抽样,生成抽检清单(SamplingDecision 列表)。只读,不落盘,不生成逃逸报告,不改能力状态", AuditSampleSchema, async (args) => {
1486
1663
  const stateDir = taskContext.getStateDir();
1487
- const pool = new AuditPool(stateDir);
1664
+ const pool = new (await lazyAuditPool()).AuditPool(stateDir);
1488
1665
  const items = pool.list();
1489
1666
  const seed = args.seed ?? 0;
1490
- const result = sampleAuditItems(items, seed);
1667
+ const result = (await lazyAuditSampler()).sampleAuditItems(items, seed);
1491
1668
  return {
1492
1669
  result: result,
1493
1670
  };
@@ -1510,7 +1687,7 @@ export function registerTools(server, deps) {
1510
1687
  };
1511
1688
  registerSafeTool("sf_escape_report", "记录逃逸、误伤或工具故障报告。只落盘记录,不自动降级,不改能力状态", EscapeReportSchema, async (args) => {
1512
1689
  const stateDir = taskContext.getStateDir();
1513
- const store = new EscapeReportStore(stateDir);
1690
+ const store = new (await lazyEscape()).EscapeReportStore(stateDir);
1514
1691
  const report = {
1515
1692
  escape_id: args.escape_id,
1516
1693
  task_id: args.task_id,
@@ -1543,10 +1720,10 @@ export function registerTools(server, deps) {
1543
1720
  };
1544
1721
  registerSafeTool("sf_capability_update", "根据复盘结果更新 Capability Registry 状态。支持 dry_run 校验、证据校验、人工确认。不会自动触发,必须显式调用", CapabilityUpdateSchema, async (args) => {
1545
1722
  const stateDir = taskContext.getStateDir();
1546
- const escapeStore = new EscapeReportStore(stateDir);
1547
- const stateStore = new CapabilityStateStore(stateDir);
1723
+ const escapeStore = new (await lazyEscape()).EscapeReportStore(stateDir);
1724
+ const stateStore = new (await lazyCapState()).CapabilityStateStore(stateDir);
1548
1725
  const escapeReports = escapeStore.list();
1549
- const capabilities = getAllCapabilities();
1726
+ const capabilities = (await lazyCapability()).getAllCapabilities();
1550
1727
  const cap = capabilities.find((c) => c.policy_id === args.policy_id);
1551
1728
  const currentState = stateStore.getEffectiveState(args.policy_id, cap?.state ?? "experimental");
1552
1729
  const result = stateStore.apply({
@@ -1569,25 +1746,25 @@ export function registerTools(server, deps) {
1569
1746
  registerSafeTool("sf_governance_report", "生成治理健康报告:汇总审计池、逃逸报告、能力动作决策。只读,不改状态", GovernanceReportSchema, async (args) => {
1570
1747
  const stateDir = taskContext.getStateDir();
1571
1748
  const seed = args.seed ?? 0;
1572
- const pool = new AuditPool(stateDir);
1573
- const escapeStore = new EscapeReportStore(stateDir);
1749
+ const pool = new (await lazyAuditPool()).AuditPool(stateDir);
1750
+ const escapeStore = new (await lazyEscape()).EscapeReportStore(stateDir);
1574
1751
  const auditItems = pool.list();
1575
1752
  const auditStats = pool.stats();
1576
1753
  const escapeReports = escapeStore.list();
1577
1754
  const escapeStats = escapeStore.stats();
1578
- // Generate action decisions for all capabilities (using effective states)
1579
- const capabilities = getAllCapabilities();
1580
- const stateStore = new CapabilityStateStore(stateDir);
1581
- const decisions = capabilities.map((cap) => {
1755
+ // 为所有能力生成动作决策(使用有效状态)
1756
+ const capabilities = (await lazyCapability()).getAllCapabilities();
1757
+ const stateStore = new (await lazyCapState()).CapabilityStateStore(stateDir);
1758
+ const decisions = await Promise.all(capabilities.map(async (cap) => {
1582
1759
  const effectiveState = stateStore.getEffectiveState(cap.policy_id, cap.state);
1583
- return decideAction(escapeReports, effectiveState, cap.policy_id);
1584
- });
1585
- // Generate sample decisions for sampled_count
1586
- const sampleResult = sampleAuditItems(auditItems, seed);
1587
- // Dual-layer mechanism findings
1588
- const dlFindings = validateMechanismLayerMaps();
1589
- const dlMechanismCount = listMechanismLayerMaps().length;
1590
- // Collect artifact records from recent tasks
1760
+ return (await lazyCapAdvisor()).decideAction(escapeReports, effectiveState, cap.policy_id);
1761
+ }));
1762
+ // sampled_count 生成抽样决策
1763
+ const sampleResult = (await lazyAuditSampler()).sampleAuditItems(auditItems, seed);
1764
+ // 双层机制发现
1765
+ const dlFindings = (await lazyDualLayer()).validateMechanismLayerMaps();
1766
+ const dlMechanismCount = (await lazyDualLayer()).listMechanismLayerMaps().length;
1767
+ // 收集近期任务的产物记录
1591
1768
  const recentTasks = await taskContext.listRecent(20);
1592
1769
  const artifacts = [];
1593
1770
  for (const t of recentTasks) {
@@ -1595,25 +1772,25 @@ export function registerTools(server, deps) {
1595
1772
  if (tCtx?.artifact_output)
1596
1773
  artifacts.push(tCtx.artifact_output);
1597
1774
  }
1598
- // Collect config resolution reports use shared function for real data
1775
+ // 收集配置解析报告使用共享函数获取真实数据
1599
1776
  let configReports = [];
1600
1777
  let configEntries = [];
1601
1778
  try {
1602
- const resolved = await resolveCurrentProjectConfigReports(projectPath);
1779
+ const resolved = await (await lazyConfigPrecedence()).resolveCurrentProjectConfigReports(projectPath);
1603
1780
  configReports = resolved.reports;
1604
1781
  configEntries = resolved.entries;
1605
1782
  }
1606
1783
  catch (e) {
1607
1784
  console.error(`[soloForge] 配置报告解析失败: ${e instanceof Error ? e.message : String(e)}`);
1608
1785
  }
1609
- // Also include reports from recent task contexts
1786
+ // 同时包含近期任务上下文中的报告
1610
1787
  for (const t of recentTasks) {
1611
1788
  const tCtx = await taskContext.load(t.task_id);
1612
1789
  if (tCtx?.expansion?.config_resolution_reports) {
1613
1790
  configReports.push(...tCtx.expansion.config_resolution_reports);
1614
1791
  }
1615
1792
  }
1616
- 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);
1793
+ const report = (await lazyGovernance()).generateReport(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);
1617
1794
  return {
1618
1795
  result: report,
1619
1796
  };
@@ -1625,7 +1802,7 @@ export function registerTools(server, deps) {
1625
1802
  };
1626
1803
  registerSafeTool("sf_audit_integration", "审计生产代码的主链路集成状态,检测孤岛模块(只被测试导入、无生产代码调用的模块)", AuditIntegrationSchema, async (args) => {
1627
1804
  const projectPath = config._projectPath || process.cwd();
1628
- // Use scope-aware production file collection (supports multi-repo, multi-lang)
1805
+ // 使用作用域感知的生产文件收集(支持多仓库、多语言)
1629
1806
  const { collectAllProductionFiles } = await import("../../engine/main_path_integration_contract.js");
1630
1807
  const allProdFiles = collectAllProductionFiles(projectPath, config);
1631
1808
  if (allProdFiles.length === 0) {
@@ -1636,8 +1813,8 @@ export function registerTools(server, deps) {
1636
1813
  const targetFiles = args.changed_files
1637
1814
  ? allProdFiles.filter((rel) => args.changed_files.some((cf) => rel === cf || rel.startsWith(cf.replace(/\.(ts|tsx|js|jsx|java|kt|go|py)$/, ""))))
1638
1815
  : allProdFiles;
1639
- const contracts = buildMainPathIntegrationContracts(projectPath, targetFiles, config);
1640
- const report = auditIntegration(contracts);
1816
+ const contracts = (await lazyMainPath()).buildMainPathIntegrationContracts(projectPath, targetFiles, config);
1817
+ const report = (await lazyMainPath()).auditIntegration(contracts);
1641
1818
  if (args.json_output) {
1642
1819
  return {
1643
1820
  result: report,