soloforge 1.2.17 → 1.2.19

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 (128) 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 +189 -170
  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_pool.d.ts.map +1 -1
  26. package/dist/engine/audit_pool.js +0 -1
  27. package/dist/engine/audit_pool.js.map +1 -1
  28. package/dist/engine/audit_sampler.d.ts.map +1 -1
  29. package/dist/engine/audit_sampler.js +0 -4
  30. package/dist/engine/audit_sampler.js.map +1 -1
  31. package/dist/engine/batch1_manifest.d.ts.map +1 -1
  32. package/dist/engine/batch1_manifest.js +0 -7
  33. package/dist/engine/batch1_manifest.js.map +1 -1
  34. package/dist/engine/batch1_scenario_registry.js +7 -7
  35. package/dist/engine/batch1_scenario_registry.js.map +1 -1
  36. package/dist/engine/batch1_scenario_runners.js +32 -32
  37. package/dist/engine/batch1_scenario_runners.js.map +1 -1
  38. package/dist/engine/capability_action_advisor.js +16 -16
  39. package/dist/engine/capability_action_advisor.js.map +1 -1
  40. package/dist/engine/classifier.d.ts.map +1 -1
  41. package/dist/engine/classifier.js +4 -3
  42. package/dist/engine/classifier.js.map +1 -1
  43. package/dist/engine/code_reviewer.d.ts.map +1 -1
  44. package/dist/engine/code_reviewer.js +10 -9
  45. package/dist/engine/code_reviewer.js.map +1 -1
  46. package/dist/engine/command_execution_contract.js +14 -14
  47. package/dist/engine/command_execution_contract.js.map +1 -1
  48. package/dist/engine/debug_log.d.ts +2 -0
  49. package/dist/engine/debug_log.d.ts.map +1 -0
  50. package/dist/engine/debug_log.js +7 -0
  51. package/dist/engine/debug_log.js.map +1 -0
  52. package/dist/engine/developer_sovereignty.js +15 -15
  53. package/dist/engine/developer_sovereignty.js.map +1 -1
  54. package/dist/engine/diff_ownership_store.d.ts.map +1 -1
  55. package/dist/engine/diff_ownership_store.js +1 -2
  56. package/dist/engine/diff_ownership_store.js.map +1 -1
  57. package/dist/engine/dual_layer_mechanism_registry.js +1 -1
  58. package/dist/engine/dual_layer_mechanism_registry.js.map +1 -1
  59. package/dist/engine/evolver.d.ts.map +1 -1
  60. package/dist/engine/evolver.js +11 -10
  61. package/dist/engine/evolver.js.map +1 -1
  62. package/dist/engine/governance_report.js +9 -9
  63. package/dist/engine/governance_report.js.map +1 -1
  64. package/dist/engine/implementation_roadmap_registry.js +5 -5
  65. package/dist/engine/implementation_roadmap_registry.js.map +1 -1
  66. package/dist/engine/input_material_extractor.js +3 -3
  67. package/dist/engine/input_material_extractor.js.map +1 -1
  68. package/dist/engine/intent_expander.d.ts.map +1 -1
  69. package/dist/engine/intent_expander.js +15 -14
  70. package/dist/engine/intent_expander.js.map +1 -1
  71. package/dist/engine/intent_router.d.ts.map +1 -1
  72. package/dist/engine/intent_router.js +17 -16
  73. package/dist/engine/intent_router.js.map +1 -1
  74. package/dist/engine/java_quality_guard.js +10 -10
  75. package/dist/engine/java_quality_guard.js.map +1 -1
  76. package/dist/engine/knowledge_injection_boundary.d.ts +1 -1
  77. package/dist/engine/knowledge_injection_boundary.d.ts.map +1 -1
  78. package/dist/engine/knowledge_injection_boundary.js +61 -60
  79. package/dist/engine/knowledge_injection_boundary.js.map +1 -1
  80. package/dist/engine/main_path_integration_contract.js +16 -16
  81. package/dist/engine/main_path_integration_contract.js.map +1 -1
  82. package/dist/engine/mechanism_contract_registry.d.ts +3 -4
  83. package/dist/engine/mechanism_contract_registry.d.ts.map +1 -1
  84. package/dist/engine/mechanism_contract_registry.js +23 -24
  85. package/dist/engine/mechanism_contract_registry.js.map +1 -1
  86. package/dist/engine/onboarding.js +20 -20
  87. package/dist/engine/onboarding.js.map +1 -1
  88. package/dist/engine/privacy_secret_contract.d.ts.map +1 -1
  89. package/dist/engine/privacy_secret_contract.js +49 -48
  90. package/dist/engine/privacy_secret_contract.js.map +1 -1
  91. package/dist/engine/regression_matrix.js +21 -21
  92. package/dist/engine/regression_matrix.js.map +1 -1
  93. package/dist/engine/route_decision_contract_verifier.js +24 -24
  94. package/dist/engine/route_decision_contract_verifier.js.map +1 -1
  95. package/dist/engine/scope_controller.d.ts.map +1 -1
  96. package/dist/engine/scope_controller.js +4 -3
  97. package/dist/engine/scope_controller.js.map +1 -1
  98. package/dist/engine/scope_lease.d.ts.map +1 -1
  99. package/dist/engine/scope_lease.js +0 -1
  100. package/dist/engine/scope_lease.js.map +1 -1
  101. package/dist/engine/task_context.js +3 -3
  102. package/dist/engine/task_context.js.map +1 -1
  103. package/dist/engine/test_generator.js +8 -8
  104. package/dist/engine/test_generator.js.map +1 -1
  105. package/dist/engine/tool_invocation_contract_registry.js +18 -18
  106. package/dist/engine/tool_invocation_contract_registry.js.map +1 -1
  107. package/dist/engine/traceability.js +6 -6
  108. package/dist/engine/traceability.js.map +1 -1
  109. package/dist/engine/user_feedback_contract.js +9 -9
  110. package/dist/engine/user_feedback_contract.js.map +1 -1
  111. package/dist/engine/verifier.d.ts.map +1 -1
  112. package/dist/engine/verifier.js +9 -8
  113. package/dist/engine/verifier.js.map +1 -1
  114. package/dist/engine/zero_config_init.d.ts.map +1 -1
  115. package/dist/engine/zero_config_init.js +84 -84
  116. package/dist/engine/zero_config_init.js.map +1 -1
  117. package/dist/git/operations.js +1 -1
  118. package/dist/git/operations.js.map +1 -1
  119. package/dist/index.d.ts +4 -3
  120. package/dist/index.d.ts.map +1 -1
  121. package/dist/index.js +16 -11
  122. package/dist/index.js.map +1 -1
  123. package/dist/knowledge/index_manager.d.ts.map +1 -1
  124. package/dist/knowledge/index_manager.js +18 -17
  125. package/dist/knowledge/index_manager.js.map +1 -1
  126. package/dist/knowledge/loader.js +2 -2
  127. package/dist/knowledge/loader.js.map +1 -1
  128. package/package.json +4 -2
@@ -2,52 +2,63 @@ 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"));
51
62
  // ── Zod Schema 定义 ──
52
63
  const ClassifySchema = {
53
64
  intent: z.string().describe("开发者意图描述"),
@@ -161,14 +172,14 @@ const ExploreSchema = {
161
172
  * @param server - McpServer 实例
162
173
  * @param deps - 工具依赖项(配置、知识索引、任务上下文)
163
174
  */
164
- export function registerTools(server, deps) {
175
+ export async function registerTools(server, deps) {
165
176
  console.error("[soloForge] 工具注册: 开始注册 MCP 工具...");
166
177
  const { config, knowledgeIndex, taskContext } = deps;
167
178
  const projectPath = config._projectPath || process.cwd();
168
179
  // H1: LLM Gateway — Token 预算熔断,防止单任务 Token 超支
169
- const gateway = deps.gateway ?? new LLMGateway();
180
+ const gateway = deps.gateway ?? new (await lazyLLM()).LLMGateway();
170
181
  // H4: IO Controller — 工作区互斥锁,防止外部修改导致的静默覆盖
171
- const ioController = new IOController(projectPath);
182
+ const ioController = new (await lazyIO()).IOController(projectPath);
172
183
  // ── 统一网关 : 唯一工具调用边界 ──
173
184
  /** 计算 sf_status cancel 的动态 category */
174
185
  function computeEffectiveCategory(toolName, args, contract) {
@@ -197,38 +208,38 @@ export function registerTools(server, deps) {
197
208
  };
198
209
  /** 授权模型: explicit > dynamic write gate > destructive gate > workflow gate > category default */
199
210
  function checkAuth(toolName, args, contract, ctx, effectiveCategory) {
200
- // 1. Explicit confirmation
211
+ // 1. 显式确认
201
212
  if (args.confirm === true || args.authorized === true || args.authorization_token) {
202
213
  return { required: true, granted: true, reason: "explicit confirmation" };
203
214
  }
204
- // 2. Dynamic write upgrade: cancel/job_cancel from read_only to write → must confirm
215
+ // 2. 动态写入升级: cancel/job_cancel read_only 变为 write → 必须确认
205
216
  if (effectiveCategory && effectiveCategory !== contract.category && effectiveCategory !== "read_only_bypass") {
206
217
  return { required: true, granted: false, reason: "dynamic write upgrade requires explicit confirmation" };
207
218
  }
208
- // 3. Destructive side effects always require explicit
219
+ // 3. 破坏性副作用始终需要显式确认
209
220
  const destructive = ["git_commit", "git_push", "pr_create", "external_write"];
210
221
  if (contract.side_effects.some((e) => destructive.includes(e))) {
211
222
  return { required: true, granted: false, reason: "destructive side effects require explicit confirmation" };
212
223
  }
213
- // 4. Standalone strict tools (no workflow required, no task context) handler does own checks
224
+ // 4. 独立严格工具(无 workflow 要求,无 task context)→ handler 自行检查
214
225
  if (contract.category === "strict_controlled" && !ctx && !contract.requires_workflow) {
215
226
  return { required: false, granted: true, reason: "standalone strict tool" };
216
227
  }
217
- // 5. Workflow contract gate for strict_controlled
228
+ // 5. strict_controlled workflow 合同门控
218
229
  if (contract.category === "strict_controlled" && ctx?.last_tool_trace) {
219
230
  const allowed = ctx.last_tool_trace.next_allowed_tools ?? [];
220
231
  if (allowed.includes(toolName)) {
221
232
  return { required: true, granted: true, reason: "workflow contract gate" };
222
233
  }
223
234
  }
224
- // 5b. State-based fallback: strict tool with valid-state task but no tool_trace
235
+ // 5b. 基于状态的回退: 严格工具且任务处于有效状态但无 tool_trace
225
236
  if (contract.category === "strict_controlled" && ctx && !ctx.last_tool_trace && contract.requires_workflow) {
226
237
  const validStates = STATE_PRECHECKS[toolName];
227
238
  if (validStates && validStates.includes(ctx.status)) {
228
239
  return { required: true, granted: true, reason: "task in valid state for tool" };
229
240
  }
230
241
  }
231
- // 5c. Non-strict tools: auto-grant unless requires_authorization
242
+ // 5c. 非严格工具: 自动授权,除非 requires_authorization
232
243
  if (contract.category === "read_only_bypass" || contract.category === "normal_controlled") {
233
244
  if (contract.requires_authorization) {
234
245
  return { required: true, granted: false, reason: "tool requires explicit authorization" };
@@ -242,7 +253,7 @@ export function registerTools(server, deps) {
242
253
  const invocationId = `inv-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
243
254
  const taskId = args.task_id;
244
255
  const contract = findToolInvocationContractByName(name);
245
- // No contract → hard fail
256
+ // 无合同 → hard fail
246
257
  if (!contract) {
247
258
  return {
248
259
  content: [{ type: "text", text: JSON.stringify({ error: `工具 ${name} 未注册契约` }) }],
@@ -251,12 +262,12 @@ export function registerTools(server, deps) {
251
262
  }
252
263
  const effectiveCategory = computeEffectiveCategory(name, args, contract);
253
264
  const effectiveSideEffects = computeEffectiveSideEffects(name, args, contract);
254
- // Load TaskContext
265
+ // 加载 TaskContext
255
266
  let ctx = null;
256
267
  if (taskId) {
257
268
  ctx = await taskContext.load(taskId);
258
269
  }
259
- // State precheck: validate task status before contract guard
270
+ // 状态预检: 在合同守卫之前验证任务状态
260
271
  if (taskId && STATE_PRECHECKS[name] && ctx) {
261
272
  const validStates = STATE_PRECHECKS[name];
262
273
  if (!validStates.includes(ctx.status)) {
@@ -270,7 +281,7 @@ export function registerTools(server, deps) {
270
281
  };
271
282
  }
272
283
  }
273
- // Strict controlled without task_id
284
+ // 严格受控但缺少 task_id
274
285
  const isStandaloneStrict = !contract.requires_workflow;
275
286
  if (contract.category === "strict_controlled" && !taskId && !isStandaloneStrict) {
276
287
  return {
@@ -278,11 +289,11 @@ export function registerTools(server, deps) {
278
289
  isError: true,
279
290
  };
280
291
  }
281
- // Authorization
292
+ // 授权检查
282
293
  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
294
+ // 授权拒绝仅对网关级拒绝执行 hard fail
295
+ // (动态写入升级、破坏性操作、无授权源的 strict_controlled
296
+ // Handler 级授权(如 sf_capability_update confirm)由 handler 自行处理
286
297
  const gatewayDenial = !authorization.granted &&
287
298
  authorization.reason !== "tool requires explicit authorization";
288
299
  if (gatewayDenial) {
@@ -312,17 +323,17 @@ export function registerTools(server, deps) {
312
323
  isError: true,
313
324
  };
314
325
  }
315
- // Bypass for read_only_bypass
326
+ // read_only_bypass 的旁路处理
316
327
  const bypass = effectiveCategory === "read_only_bypass"
317
328
  ? { allowed: true, reason: "read_only" } : undefined;
318
- // Contract validation
329
+ // 合同验证
319
330
  const lastTrace = ctx?.last_tool_trace;
320
- // Build effective contract override for dynamic tools (e.g., sf_status cancel)
331
+ // 为动态工具构建有效的合同覆盖(如 sf_status cancel
321
332
  let contractOverride;
322
333
  if (effectiveCategory !== contract.category || effectiveSideEffects !== contract.side_effects) {
323
334
  contractOverride = { ...contract, category: effectiveCategory, side_effects: effectiveSideEffects };
324
335
  }
325
- // Workflow ID: only from real expansion trace
336
+ // Workflow ID: 仅来自真实的 expansion trace
326
337
  const explicitWorkflowId = ctx?.expansion?.workflow_trace?.workflow_id;
327
338
  const violations = validateToolInvocation({
328
339
  tool_name: name,
@@ -334,7 +345,7 @@ export function registerTools(server, deps) {
334
345
  workflow_id: explicitWorkflowId,
335
346
  _contractOverride: contractOverride,
336
347
  });
337
- // State-based fallback: downgrade contract_state_mismatch from hard_fail to require_human
348
+ // 基于状态的回退: contract_state_mismatch hard_fail 降级为 require_human
338
349
  if (authorization.reason === "task in valid state for tool") {
339
350
  for (const v of violations) {
340
351
  if (v.violation_type === "contract_state_mismatch" && v.severity === "hard_fail") {
@@ -343,7 +354,7 @@ export function registerTools(server, deps) {
343
354
  }
344
355
  }
345
356
  }
346
- // Hard-fail violationsblock
357
+ // Hard-fail 违规阻止
347
358
  const hardFail = violations.find(v => v.severity === "hard_fail");
348
359
  if (hardFail) {
349
360
  const blockedTrace = createToolTrace({
@@ -366,17 +377,17 @@ export function registerTools(server, deps) {
366
377
  isError: true,
367
378
  };
368
379
  }
369
- // Execute handler
380
+ // 执行 handler
370
381
  try {
371
382
  const raw = await handler(args);
372
- // Pass through if handler returned { content } directly
383
+ // 如果 handler 直接返回 { content } 则透传
373
384
  if (raw && typeof raw === "object" && "content" in raw && Array.isArray(raw.content)) {
374
385
  return raw;
375
386
  }
376
- // Extract data from { result } pattern
387
+ // { result } 模式中提取数据
377
388
  const data = raw?.result !== undefined ? raw.result : raw;
378
389
  const hasError = !!(data && typeof data === "object" && "error" in data);
379
- // Build trace
390
+ // 构建 trace
380
391
  const trace = createToolTrace({
381
392
  tool_name: name, invocation_id: invocationId, task_id: taskId,
382
393
  workflow_id: ctx?.expansion?.workflow_trace?.workflow_id,
@@ -385,18 +396,18 @@ export function registerTools(server, deps) {
385
396
  forbidden_tools: contract.forbidden_next_tools,
386
397
  authorization, bypass,
387
398
  });
388
- // Write trace to TaskContext
399
+ // trace 写入 TaskContext
389
400
  if (taskId) {
390
401
  await taskContext.setToolTrace(taskId, trace, violations.length > 0 ? violations : undefined);
391
402
  }
392
- // Decorate response with trace + next/forbidden
403
+ // trace + next/forbidden 装饰响应
393
404
  const response = {
394
405
  ...data,
395
406
  tool_trace: trace,
396
407
  next_allowed_tools: contract.default_next_tools,
397
408
  forbidden_tools: contract.forbidden_next_tools,
398
409
  };
399
- // State-based fallback: expose degraded workflow in response
410
+ // 基于状态的回退: 在响应中暴露降级 workflow
400
411
  if (authorization.reason === "task in valid state for tool") {
401
412
  response.degraded_workflow = true;
402
413
  response.workflow_source = "state-based-fallback";
@@ -433,14 +444,14 @@ export function registerTools(server, deps) {
433
444
  });
434
445
  }
435
446
  // 加载认知锚点上下文 — 必须提供相关性参数,禁止全量加载
436
- function loadRelevantAnchors(query) {
447
+ async function loadRelevantAnchors(query) {
437
448
  console.error("[soloForge] 工具注册: 加载认知锚点");
438
449
  return _loadRelevantAnchorsInner(query);
439
450
  }
440
- function _loadRelevantAnchorsInner(query) {
451
+ async function _loadRelevantAnchorsInner(query) {
441
452
  const stateDir = taskContext.getStateDir();
442
453
  const mapPath = path.join(stateDir, "cognitive.map.json");
443
- const mapData = readMapJson(mapPath);
454
+ const mapData = (await lazyAnchor()).readMapJson(mapPath);
444
455
  if (!mapData || mapData.anchors.length === 0)
445
456
  return undefined;
446
457
  const existingFiles = new Set();
@@ -454,15 +465,15 @@ export function registerTools(server, deps) {
454
465
  }
455
466
  }
456
467
  catch { /* ignore */ }
457
- const checked = checkAnchorStaleness(mapData.anchors, existingFiles);
468
+ const checked = (await lazyAnchor()).checkAnchorStaleness(mapData.anchors, existingFiles);
458
469
  // 必须有 module 或 file_paths,否则不返回任何锚点(禁止全量加载)
459
470
  if (!query.module && (!query.file_paths || query.file_paths.length === 0))
460
471
  return undefined;
461
- // Collect anchors matching ANY of the provided file_paths or module
472
+ // 收集与任意提供的 file_paths module 匹配的锚点
462
473
  const seen = new Set();
463
474
  const relevant = [];
464
475
  if (query.module) {
465
- for (const a of filterRelevantAnchors(checked, { module: query.module })) {
476
+ for (const a of (await lazyAnchor()).filterRelevantAnchors(checked, { module: query.module })) {
466
477
  if (!seen.has(a.anchor_id)) {
467
478
  seen.add(a.anchor_id);
468
479
  relevant.push(a);
@@ -471,7 +482,7 @@ export function registerTools(server, deps) {
471
482
  }
472
483
  if (query.file_paths) {
473
484
  for (const fp of query.file_paths) {
474
- for (const a of filterRelevantAnchors(checked, { file_path: fp })) {
485
+ for (const a of (await lazyAnchor()).filterRelevantAnchors(checked, { file_path: fp })) {
475
486
  if (!seen.has(a.anchor_id)) {
476
487
  seen.add(a.anchor_id);
477
488
  relevant.push(a);
@@ -508,10 +519,10 @@ export function registerTools(server, deps) {
508
519
  // 创建任务上下文
509
520
  const ctx = await taskContext.create(args.intent, config.product_profile);
510
521
  const input = { intent: args.intent, project_path: projectPath, task_id: ctx.task_id };
511
- const classification = classify(input);
522
+ const classification = (await lazyClassifier()).classify(input);
512
523
  // 存储分类结果
513
524
  await taskContext.setClassification(ctx.task_id, classification);
514
- if (!shouldEnterSoloForge(classification.route_decision)) {
525
+ if (!(await lazyIntentRouter()).shouldEnterSoloForge(classification.route_decision)) {
515
526
  await taskContext.updateStatus(ctx.task_id, "done");
516
527
  }
517
528
  return {
@@ -577,7 +588,7 @@ export function registerTools(server, deps) {
577
588
  }
578
589
  let expansion;
579
590
  try {
580
- expansion = await expand({
591
+ expansion = await (await lazyExpander()).expand({
581
592
  intent: ctx.intent,
582
593
  classification: ctx.classification,
583
594
  projectPath,
@@ -610,14 +621,22 @@ export function registerTools(server, deps) {
610
621
  // Privacy Gate: 隐私/敏感信息策略阻断
611
622
  const isBlocked = expansion.prompt.startsWith("## 阻塞:输入材料禁止读取")
612
623
  || 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");
624
+ let isMaterialClarification = false;
625
+ if (expansion.prompt.startsWith("## 澄清请求") && expansion.input_materials) {
626
+ for (const m of expansion.input_materials) {
627
+ if (m.access_mode !== "forbidden" && (await lazyInputMaterial()).classifyIngestionStatus(m.path_or_ref) === "requires_confirmation") {
628
+ isMaterialClarification = true;
629
+ break;
630
+ }
631
+ }
632
+ }
614
633
  // 注入 H1/H4 advisory warnings
615
634
  const advisories = {};
616
635
  if (h1Warning)
617
636
  advisories.h1_advisory = h1Warning;
618
637
  if (h4LockWarning)
619
638
  advisories.h4_advisory = h4LockWarning;
620
- // Config precedence warnings
639
+ // 配置优先级警告
621
640
  if (expansion.config_resolution_reports && expansion.config_resolution_reports.length > 0) {
622
641
  const configWarnings = expansion.config_resolution_reports
623
642
  .filter(r => r.conflicts.length > 0)
@@ -627,7 +646,7 @@ export function registerTools(server, deps) {
627
646
  }
628
647
  }
629
648
  // 决策契约 advisory: 校验 expand 输出是否包含默认决策字段
630
- const decisionContract = validateDecisionOutput(expansion);
649
+ const decisionContract = (await lazyDecision()).validateDecisionOutput(expansion);
631
650
  if (!decisionContract.passed) {
632
651
  advisories.decision_contract_advisory = decisionContract.advisory;
633
652
  }
@@ -684,7 +703,7 @@ export function registerTools(server, deps) {
684
703
  result: { error: "任务不存在" },
685
704
  };
686
705
  }
687
- // RouteDecision contract verification unconditional, before state precheck
706
+ // RouteDecision 合同验证无条件,在状态预检之前
688
707
  const rdFromCtx = ctx.route_decision ?? ctx.classification?.route_decision ?? null;
689
708
  const wtFromCtx = ctx.workflow_trace ?? ctx.expansion?.workflow_trace ?? null;
690
709
  const rdContractInput = {
@@ -719,13 +738,13 @@ export function registerTools(server, deps) {
719
738
  const h4Warning = !integrity.clean
720
739
  ? { warning: `H4 advisory: ${integrity.message}`, dirty_files: integrity.dirty_files }
721
740
  : undefined;
722
- const verifyResult = generateVerifyCommands(config, args.changed_files, acceptanceItems, ctx?.expansion?.workflow_trace?.route);
741
+ const verifyResult = (await lazyVerifier()).generateVerifyCommands(config, args.changed_files, acceptanceItems, ctx?.expansion?.workflow_trace?.route);
723
742
  verifyResult.task_id = args.task_id;
724
- // Artifact lifecycle check : draft → verified requires ArtifactVerificationResult.passed
743
+ // 产物生命周期检查: draft → verified 需要 ArtifactVerificationResult.passed
725
744
  let artifactVerificationResult;
726
745
  let artifactFileMissing = false;
727
746
  if (ctx.artifact_output && ctx.artifact_output.status === "draft") {
728
- // Resolve artifact file and compute hash before verification
747
+ // 验证前解析产物文件并计算 hash
729
748
  const artifact = ctx.artifact_output;
730
749
  const fullPath = path.join(projectPath, artifact.path);
731
750
  if (fss.existsSync(fullPath)) {
@@ -735,7 +754,7 @@ export function registerTools(server, deps) {
735
754
  if (!artifact.evidence_refs.some(r => r.startsWith("file:artifact:"))) {
736
755
  artifact.evidence_refs.push(`file:artifact:path=${artifact.path} hash=sha256:${hash}`);
737
756
  }
738
- // Save updated artifact with hash
757
+ // 保存更新后的产物(含 hash
739
758
  const ctxForHash = await taskContext.load(args.task_id);
740
759
  if (ctxForHash?.artifact_output) {
741
760
  ctxForHash.artifact_output.hash = artifact.hash;
@@ -752,7 +771,7 @@ export function registerTools(server, deps) {
752
771
  }
753
772
  // 记录变更文件
754
773
  await taskContext.setExecution(args.task_id, args.changed_files);
755
- // Mark no_change_artifact when no real files changed but artifact exists
774
+ // 无实际文件变更但存在产物时标记 no_change_artifact
756
775
  if (args.changed_files.length === 0 && ctx.artifact_output) {
757
776
  const execCtx = await taskContext.load(args.task_id);
758
777
  if (execCtx?.execution) {
@@ -767,7 +786,7 @@ export function registerTools(server, deps) {
767
786
  await taskContext.updateStatus(args.task_id, "verifying");
768
787
  // 存储验证结果
769
788
  await taskContext.setVerification(args.task_id, verifyResult);
770
- // Artifact lifecycle transition: draft → verified only if ArtifactVerificationResult.passed
789
+ // 产物生命周期转换: draft → verified 仅在 ArtifactVerificationResult.passed
771
790
  if (ctx.artifact_output && ctx.artifact_output.status === "draft" && artifactVerificationResult?.passed) {
772
791
  const evidenceRef = `verification:${ctx.task_id}:checks=${artifactVerificationResult.checks.length}:summary=${artifactVerificationResult.summary.slice(0, 60)}`;
773
792
  try {
@@ -778,11 +797,11 @@ export function registerTools(server, deps) {
778
797
  });
779
798
  }
780
799
  catch {
781
- // Transition blocked artifact stays draft, pipeline continues
800
+ // 转换被阻止产物保持 draft,流水线继续
782
801
  }
783
802
  }
784
803
  // 认知锚点上下文回放(按变更文件相关性)
785
- const verifyAnchors = loadRelevantAnchors({ file_paths: args.changed_files });
804
+ const verifyAnchors = await loadRelevantAnchors({ file_paths: args.changed_files });
786
805
  const verifyExtras = {};
787
806
  if (h4Warning)
788
807
  verifyExtras.h4_advisory = h4Warning;
@@ -829,7 +848,7 @@ export function registerTools(server, deps) {
829
848
  }
830
849
  // 转换到学习阶段
831
850
  await taskContext.updateStatus(args.task_id, "learning");
832
- const learnResult = await evolve({
851
+ const learnResult = await (await lazyEvolver()).evolve({
833
852
  taskContext: ctx,
834
853
  result: args.result,
835
854
  verifyOutput: args.verify_output,
@@ -872,14 +891,14 @@ export function registerTools(server, deps) {
872
891
  // ── sf_status: 任务状态查询(current/recent/resume/cancel) ──
873
892
  registerSafeTool("sf_status", "查询当前任务状态、列出近期任务、恢复中断任务或取消任务", StatusSchema, async (args) => {
874
893
  const action = args.action || "current";
875
- // Job actions — advisory, independent of task actions
894
+ // Job 操作 — advisory,独立于任务操作
876
895
  if (args.job_action) {
877
896
  if (!args.job_id) {
878
897
  return {
879
898
  result: { error: "job 操作需要 job_id" },
880
899
  };
881
900
  }
882
- const jm = new JobManager(taskContext.getStateDir());
901
+ const jm = new (await lazyJob()).JobManager(taskContext.getStateDir());
883
902
  const taskId = args.task_id ?? await jm.resolveTaskId(args.job_id) ?? "";
884
903
  if (args.job_action === "job_status") {
885
904
  const status = await jm.getJobStatus(args.job_id, taskId);
@@ -921,12 +940,12 @@ export function registerTools(server, deps) {
921
940
  };
922
941
  }
923
942
  }
924
- // Auto-fail stale non-terminal tasks before reading
943
+ // 读取前自动将过期非终态任务标记为失败
925
944
  try {
926
945
  await taskContext.autoFailStale();
927
946
  }
928
947
  catch (e) {
929
- console.error("[soloForge] autoFailStale error:", e);
948
+ console.error("[soloForge] autoFailStale 出错:", e);
930
949
  }
931
950
  switch (action) {
932
951
  case "current": {
@@ -960,7 +979,7 @@ export function registerTools(server, deps) {
960
979
  }
961
980
  // JobManager advisory: 查询关联 job 状态
962
981
  try {
963
- const jm = new JobManager(taskContext.getStateDir());
982
+ const jm = new (await lazyJob()).JobManager(taskContext.getStateDir());
964
983
  const activeJobs = await jm.listActiveJobs();
965
984
  const relatedJob = activeJobs.find((j) => j.task_id === ctx.task_id);
966
985
  if (relatedJob) {
@@ -974,7 +993,7 @@ export function registerTools(server, deps) {
974
993
  }
975
994
  }
976
995
  catch {
977
- // JobManager advisory — ignore errors
996
+ // JobManager advisory — 忽略错误
978
997
  }
979
998
  return {
980
999
  result: result,
@@ -1012,7 +1031,7 @@ export function registerTools(server, deps) {
1012
1031
  if (ctx.execution)
1013
1032
  resumeResult.execution = ctx.execution;
1014
1033
  const resumeAnchors = ctx.execution?.changed_files
1015
- ? loadRelevantAnchors({ file_paths: ctx.execution.changed_files })
1034
+ ? await loadRelevantAnchors({ file_paths: ctx.execution.changed_files })
1016
1035
  : undefined;
1017
1036
  if (resumeAnchors && resumeAnchors.length > 0)
1018
1037
  resumeResult.cognitive_anchors = resumeAnchors;
@@ -1043,7 +1062,7 @@ export function registerTools(server, deps) {
1043
1062
  result: { error: "任务不存在或尚未分类" },
1044
1063
  };
1045
1064
  }
1046
- const result = planTask({
1065
+ const result = (await lazyPlanner()).planTask({
1047
1066
  intent: ctx.intent,
1048
1067
  classification: ctx.classification,
1049
1068
  config,
@@ -1105,7 +1124,7 @@ export function registerTools(server, deps) {
1105
1124
  result: { error: "任务尚未膨胀,请先调用 sf_expand" },
1106
1125
  };
1107
1126
  }
1108
- const result = await analyzeImpact({
1127
+ const result = await (await lazyImpact()).analyzeImpact({
1109
1128
  intent: ctx.intent,
1110
1129
  classification: ctx.classification,
1111
1130
  expansion: ctx.expansion,
@@ -1114,7 +1133,7 @@ export function registerTools(server, deps) {
1114
1133
  });
1115
1134
  result.task_id = args.task_id;
1116
1135
  // 决策契约 advisory: 校验 analyze 输出
1117
- const decisionContract = validateDecisionOutput(result);
1136
+ const decisionContract = (await lazyDecision()).validateDecisionOutput(result);
1118
1137
  const advisoryExtras = {};
1119
1138
  if (!decisionContract.passed) {
1120
1139
  advisoryExtras.decision_contract_advisory = decisionContract.advisory;
@@ -1129,8 +1148,8 @@ export function registerTools(server, deps) {
1129
1148
  result: { error: "任务不存在" },
1130
1149
  };
1131
1150
  }
1132
- const tracker = new DebtTracker(projectPath);
1133
- const result = await reviewCode({
1151
+ const tracker = new (await lazyDebt()).DebtTracker(projectPath);
1152
+ const result = await (await lazyReviewer()).reviewCode({
1134
1153
  changedFiles: args.changed_files,
1135
1154
  projectPath,
1136
1155
  config,
@@ -1142,7 +1161,7 @@ export function registerTools(server, deps) {
1142
1161
  result.task_id = args.task_id;
1143
1162
  await taskContext.setCodeReview(args.task_id, result);
1144
1163
  // 决策契约 advisory: 校验 review 输出
1145
- const decisionContract = validateDecisionOutput(result);
1164
+ const decisionContract = (await lazyDecision()).validateDecisionOutput(result);
1146
1165
  const reviewExtras = {};
1147
1166
  if (!decisionContract.passed) {
1148
1167
  reviewExtras.decision_contract_advisory = decisionContract.advisory;
@@ -1165,7 +1184,7 @@ export function registerTools(server, deps) {
1165
1184
  },
1166
1185
  };
1167
1186
  }
1168
- const result = await generateScaffold({
1187
+ const result = await (await lazyScaffolder()).generateScaffold({
1169
1188
  intent: ctx.intent,
1170
1189
  classification: ctx.classification,
1171
1190
  config,
@@ -1189,7 +1208,7 @@ export function registerTools(server, deps) {
1189
1208
  const h4DeliverWarning = !deliverIntegrity.clean
1190
1209
  ? { warning: `H4 advisory: ${deliverIntegrity.message}`, dirty_files: deliverIntegrity.dirty_files }
1191
1210
  : undefined;
1192
- // Artifact status gate : deliver requires artifact status = accepted with evidence
1211
+ // 产物状态门控: deliver 需要产物状态为 accepted 且有证据
1193
1212
  if (ctx.artifact_output) {
1194
1213
  const status = ctx.artifact_output.status;
1195
1214
  if (status === "draft") {
@@ -1210,7 +1229,7 @@ export function registerTools(server, deps) {
1210
1229
  },
1211
1230
  };
1212
1231
  }
1213
- // accepted must have confirmation evidence
1232
+ // accepted 必须有确认证据
1214
1233
  if (status === "accepted") {
1215
1234
  const hasAcceptanceEvidence = ctx.artifact_output.evidence_refs.some((r) => r.includes("acceptance") || r.includes("workflow_adoption"));
1216
1235
  if (!hasAcceptanceEvidence) {
@@ -1224,12 +1243,12 @@ export function registerTools(server, deps) {
1224
1243
  }
1225
1244
  }
1226
1245
  }
1227
- const result = await deliver({
1246
+ const result = await (await lazyDelivery()).deliver({
1228
1247
  taskContext: ctx,
1229
1248
  config,
1230
1249
  knowledgeIndex,
1231
1250
  projectPath,
1232
- gitOps: realGitOps,
1251
+ gitOps: (await lazyGitDeps()).realGitOps,
1233
1252
  skipPush: args.skip_push,
1234
1253
  skipPr: args.skip_pr,
1235
1254
  });
@@ -1240,11 +1259,11 @@ export function registerTools(server, deps) {
1240
1259
  });
1241
1260
  // ── sf_coord_check: 预测性冲突检测和跨仓库协调 ──
1242
1261
  registerSafeTool("sf_coord_check", "预测性冲突检测和跨仓库协调提示,检查分支状态、本地变更和潜在冲突", CoordCheckSchema, async (args) => {
1243
- const result = await checkConflicts({
1262
+ const result = await (await lazyChangeCoord()).checkConflicts({
1244
1263
  projectPath,
1245
1264
  config,
1246
1265
  branch: args.branch,
1247
- gitOps: realGitOps,
1266
+ gitOps: (await lazyGitDeps()).realGitOps,
1248
1267
  });
1249
1268
  return {
1250
1269
  result: result,
@@ -1252,11 +1271,11 @@ export function registerTools(server, deps) {
1252
1271
  });
1253
1272
  // ── sf_team_status: 团队活动流和工作负载查询 ──
1254
1273
  registerSafeTool("sf_team_status", "查询团队活动流、成员工作负载、过期分支和知识库更新状态", TeamStatusSchema, async (args) => {
1255
- const result = await getTeamStatus({
1274
+ const result = await (await lazyTeam()).getTeamStatus({
1256
1275
  projectPath,
1257
1276
  config,
1258
1277
  since: args.since,
1259
- gitOps: realGitOps,
1278
+ gitOps: (await lazyGitDeps()).realGitOps,
1260
1279
  knowledgeIndex: args.include_knowledge ? knowledgeIndex : undefined,
1261
1280
  });
1262
1281
  return {
@@ -1270,11 +1289,11 @@ export function registerTools(server, deps) {
1270
1289
  const ctx = await taskContext.load(args.task_id);
1271
1290
  changedFiles = ctx?.execution?.changed_files ?? [];
1272
1291
  }
1273
- const result = await checkContractChanges({
1292
+ const result = await (await lazyContractGuard()).checkContractChanges({
1274
1293
  changedFiles,
1275
1294
  projectPath,
1276
1295
  config,
1277
- gitOps: realGitOps,
1296
+ gitOps: (await lazyGitDeps()).realGitOps,
1278
1297
  });
1279
1298
  return {
1280
1299
  result: result,
@@ -1282,11 +1301,11 @@ export function registerTools(server, deps) {
1282
1301
  });
1283
1302
  // ── sf_onboard: 新人分步引导 ──
1284
1303
  registerSafeTool("sf_onboard", "新人分步引导:项目概览 → 代码导览 → 知识回顾 → 首个任务建议", OnboardSchema, async (args) => {
1285
- const result = await onboard({
1304
+ const result = await (await lazyOnboarding()).onboard({
1286
1305
  config,
1287
1306
  projectPath,
1288
1307
  knowledgeIndex,
1289
- gitOps: realGitOps,
1308
+ gitOps: (await lazyGitDeps()).realGitOps,
1290
1309
  currentStep: args.step,
1291
1310
  reset: args.reset,
1292
1311
  });
@@ -1302,7 +1321,7 @@ export function registerTools(server, deps) {
1302
1321
  result: { error: "任务不存在或未完成分类,请先调用 sf_classify" },
1303
1322
  };
1304
1323
  }
1305
- const result = checkFeasibility(ctx.classification, config);
1324
+ const result = (await lazyFeasibility()).checkFeasibility(ctx.classification, config);
1306
1325
  return {
1307
1326
  result: result,
1308
1327
  };
@@ -1313,7 +1332,7 @@ export function registerTools(server, deps) {
1313
1332
  ...config.scope.backend,
1314
1333
  ...config.scope.frontend,
1315
1334
  ];
1316
- const result = debugError(args.error_output, args.task_id || `debug-${Date.now()}`, projectScope);
1335
+ const result = (await lazyDebugger()).debugError(args.error_output, args.task_id || `debug-${Date.now()}`, projectScope);
1317
1336
  return {
1318
1337
  result: result,
1319
1338
  };
@@ -1321,8 +1340,8 @@ export function registerTools(server, deps) {
1321
1340
  // ── sf_observability: 系统可观测和运行报告 ──
1322
1341
  registerSafeTool("sf_observability", "系统可观测:运行指标、成本估算、告警检测、能力状态、周期报告", ObservabilitySchema, async (args) => {
1323
1342
  const stateDir = taskContext.getStateDir();
1324
- const result = await generateReport(stateDir, args.period_days);
1325
- const capability = getCapabilitySummary();
1343
+ const result = await (await lazyObservability()).generateReport(stateDir, args.period_days);
1344
+ const capability = (await lazyCapability()).getSummary();
1326
1345
  const output = { ...result, capability };
1327
1346
  return {
1328
1347
  result: output,
@@ -1330,36 +1349,36 @@ export function registerTools(server, deps) {
1330
1349
  });
1331
1350
  // ── sf_migration_check: 数据库迁移安全性分析 ──
1332
1351
  registerSafeTool("sf_migration_check", "分析数据库迁移文件安全性:检测破坏性操作(DROP/DELETE/TRUNCATE)并生成回滚建议", MigrationCheckSchema, async (args) => {
1333
- const result = analyzeMigration(args.content, args.filename);
1352
+ const result = (await lazyMigration()).analyzeMigration(args.content, args.filename);
1334
1353
  return {
1335
1354
  result: result,
1336
1355
  };
1337
1356
  });
1338
1357
  // ── sf_test_guide: 基于变更文件生成测试指引 ──
1339
1358
  registerSafeTool("sf_test_guide", "根据变更文件类型生成测试指引:推荐测试类型、场景、Mock 点和断言模板", TestGuideSchema, async (args) => {
1340
- const result = generateTestGuide(args.changed_files, [], config);
1359
+ const result = (await lazyTestGen()).generateTestGuide(args.changed_files, [], config);
1341
1360
  return {
1342
1361
  result: result,
1343
1362
  };
1344
1363
  });
1345
1364
  // ── sf_test_quality: 测试文件质量五维评分 ──
1346
1365
  registerSafeTool("sf_test_quality", "评估测试文件质量:断言密度、边界覆盖、命名、重复率、场景覆盖五维评分", TestQualitySchema, async (args) => {
1347
- const result = analyzeTestQuality(args.content, args.filename);
1366
+ const result = (await lazyTestQuality()).analyzeTestQuality(args.content, args.filename);
1348
1367
  return {
1349
1368
  result: result,
1350
1369
  };
1351
1370
  });
1352
1371
  // ── sf_dependency_scan: 依赖漏洞扫描 ──
1353
1372
  registerSafeTool("sf_dependency_scan", "扫描依赖声明文件漏洞:已知 CVE 规则匹配、未锁定版本检测、支持 npm/maven/gradle", DependencyScanSchema, async (args) => {
1354
- const result = scanDependencies(args.content, args.filename);
1373
+ const result = (await lazyDepScan()).scanDependencies(args.content, args.filename);
1355
1374
  return {
1356
1375
  result: result,
1357
1376
  };
1358
1377
  });
1359
1378
  // ── sf_debt_report: 技术债务报告生成 ──
1360
1379
  registerSafeTool("sf_debt_report", "生成技术债务报告:按分类/严重度聚合、30 天趋势、优先级排序 Top 5", {}, async () => {
1361
- const tracker = new DebtTracker(projectPath);
1362
- const result = await generateDebtReport(tracker);
1380
+ const tracker = new (await lazyDebt()).DebtTracker(projectPath);
1381
+ const result = await (await lazyDebtReport()).generateDebtReport(tracker);
1363
1382
  return {
1364
1383
  result: result,
1365
1384
  };
@@ -1371,14 +1390,14 @@ export function registerTools(server, deps) {
1371
1390
  const ctx = await taskContext.load(args.task_id);
1372
1391
  classification = ctx?.classification;
1373
1392
  }
1374
- const result = exploreSolutions({
1393
+ const result = (await lazyExploration()).exploreSolutions({
1375
1394
  domain_query: args.domain_query,
1376
1395
  projectConfig: config,
1377
1396
  classification,
1378
1397
  knowledgeIndex,
1379
1398
  });
1380
1399
  // 决策契约 advisory: sf_explore 应始终通过(10 字段已内置)
1381
- const decisionContract = validateDecisionOutput(result);
1400
+ const decisionContract = (await lazyDecision()).validateDecisionOutput(result);
1382
1401
  const exploreExtras = {};
1383
1402
  if (!decisionContract.passed) {
1384
1403
  exploreExtras.decision_contract_advisory = decisionContract.advisory;
@@ -1387,7 +1406,7 @@ export function registerTools(server, deps) {
1387
1406
  });
1388
1407
  // ── sf_knowledge_audit: 知识库健康审计 ──
1389
1408
  registerSafeTool("sf_knowledge_audit", "审计知识库:识别过时条目、重复触发词、格式缺失、覆盖缺口。定期执行或手动触发", {}, async () => {
1390
- const result = await auditKnowledge(knowledgeIndex, config);
1409
+ const result = await (await lazyKnowledge()).auditKnowledge(knowledgeIndex, config);
1391
1410
  return {
1392
1411
  result: result,
1393
1412
  };
@@ -1403,7 +1422,7 @@ export function registerTools(server, deps) {
1403
1422
  auto_enrich: z.boolean().optional().describe("是否返回行业最佳实践探索指引(默认 true,宿主 AI 将自动执行探索并填充内容)"),
1404
1423
  };
1405
1424
  registerSafeTool("sf_knowledge_add", "新增知识条目。默认保存为草稿到 .soloforge/knowledge/drafts/,人工确认后移入正式目录", KnowledgeAddSchema, async (args) => {
1406
- const result = await addKnowledge({
1425
+ const result = await (await lazyKnowledge()).addKnowledge({
1407
1426
  title: args.title,
1408
1427
  type: args.type,
1409
1428
  scope: args.scope,
@@ -1425,7 +1444,7 @@ export function registerTools(server, deps) {
1425
1444
  status: z.enum(["active", "deprecated"]).optional().describe("更新条目状态"),
1426
1445
  };
1427
1446
  registerSafeTool("sf_knowledge_update", "更新已有知识条目:追加规则、更新触发词、标记废弃。自动创建备份", KnowledgeUpdateSchema, async (args) => {
1428
- const result = await updateKnowledge({
1447
+ const result = await (await lazyKnowledge()).updateKnowledge({
1429
1448
  entry_name: args.entry_name,
1430
1449
  updates: {
1431
1450
  when_triggers: args.when_triggers,
@@ -1444,13 +1463,13 @@ export function registerTools(server, deps) {
1444
1463
  });
1445
1464
  // ── sf_resume_workspace: 工作区状态唤醒(解决前端刷新导致UUID丢失) ──
1446
1465
  registerSafeTool("sf_resume_workspace", "扫描 .soloforge/state/ 目录,恢复中断工单并播报当前进度。新会话启动时必须优先调用", {}, async () => {
1447
- const result = await scanAndResume(taskContext);
1466
+ const result = await (await lazyWorkspaceResumer()).scanAndResume(taskContext);
1448
1467
  // 认知锚点:按恢复任务的 changed_files 相关性加载,禁止全量
1449
1468
  if (result.task) {
1450
1469
  const ctx = await taskContext.load(result.task.task_id);
1451
1470
  const changedFiles = ctx?.execution?.changed_files;
1452
1471
  if (changedFiles && changedFiles.length > 0) {
1453
- const anchors = loadRelevantAnchors({ file_paths: changedFiles });
1472
+ const anchors = await loadRelevantAnchors({ file_paths: changedFiles });
1454
1473
  if (anchors && anchors.length > 0) {
1455
1474
  result.cognitive_anchors = anchors;
1456
1475
  }
@@ -1458,7 +1477,7 @@ export function registerTools(server, deps) {
1458
1477
  }
1459
1478
  // JobManager advisory: 查询活跃 jobs
1460
1479
  try {
1461
- const jm = new JobManager(taskContext.getStateDir());
1480
+ const jm = new (await lazyJob()).JobManager(taskContext.getStateDir());
1462
1481
  const activeJobs = await jm.listActiveJobs();
1463
1482
  if (activeJobs.length > 0) {
1464
1483
  result.active_jobs = activeJobs.map((j) => ({
@@ -1472,7 +1491,7 @@ export function registerTools(server, deps) {
1472
1491
  }
1473
1492
  }
1474
1493
  catch {
1475
- // JobManager advisory — ignore errors
1494
+ // JobManager advisory — 忽略错误
1476
1495
  }
1477
1496
  return {
1478
1497
  result: result,
@@ -1484,10 +1503,10 @@ export function registerTools(server, deps) {
1484
1503
  };
1485
1504
  registerSafeTool("sf_audit_sample", "从审计池按风险加权抽样,生成抽检清单(SamplingDecision 列表)。只读,不落盘,不生成逃逸报告,不改能力状态", AuditSampleSchema, async (args) => {
1486
1505
  const stateDir = taskContext.getStateDir();
1487
- const pool = new AuditPool(stateDir);
1506
+ const pool = new (await lazyAuditPool()).AuditPool(stateDir);
1488
1507
  const items = pool.list();
1489
1508
  const seed = args.seed ?? 0;
1490
- const result = sampleAuditItems(items, seed);
1509
+ const result = (await lazyAuditSampler()).sampleAuditItems(items, seed);
1491
1510
  return {
1492
1511
  result: result,
1493
1512
  };
@@ -1510,7 +1529,7 @@ export function registerTools(server, deps) {
1510
1529
  };
1511
1530
  registerSafeTool("sf_escape_report", "记录逃逸、误伤或工具故障报告。只落盘记录,不自动降级,不改能力状态", EscapeReportSchema, async (args) => {
1512
1531
  const stateDir = taskContext.getStateDir();
1513
- const store = new EscapeReportStore(stateDir);
1532
+ const store = new (await lazyEscape()).EscapeReportStore(stateDir);
1514
1533
  const report = {
1515
1534
  escape_id: args.escape_id,
1516
1535
  task_id: args.task_id,
@@ -1543,10 +1562,10 @@ export function registerTools(server, deps) {
1543
1562
  };
1544
1563
  registerSafeTool("sf_capability_update", "根据复盘结果更新 Capability Registry 状态。支持 dry_run 校验、证据校验、人工确认。不会自动触发,必须显式调用", CapabilityUpdateSchema, async (args) => {
1545
1564
  const stateDir = taskContext.getStateDir();
1546
- const escapeStore = new EscapeReportStore(stateDir);
1547
- const stateStore = new CapabilityStateStore(stateDir);
1565
+ const escapeStore = new (await lazyEscape()).EscapeReportStore(stateDir);
1566
+ const stateStore = new (await lazyCapState()).CapabilityStateStore(stateDir);
1548
1567
  const escapeReports = escapeStore.list();
1549
- const capabilities = getAllCapabilities();
1568
+ const capabilities = (await lazyCapability()).getAllCapabilities();
1550
1569
  const cap = capabilities.find((c) => c.policy_id === args.policy_id);
1551
1570
  const currentState = stateStore.getEffectiveState(args.policy_id, cap?.state ?? "experimental");
1552
1571
  const result = stateStore.apply({
@@ -1569,25 +1588,25 @@ export function registerTools(server, deps) {
1569
1588
  registerSafeTool("sf_governance_report", "生成治理健康报告:汇总审计池、逃逸报告、能力动作决策。只读,不改状态", GovernanceReportSchema, async (args) => {
1570
1589
  const stateDir = taskContext.getStateDir();
1571
1590
  const seed = args.seed ?? 0;
1572
- const pool = new AuditPool(stateDir);
1573
- const escapeStore = new EscapeReportStore(stateDir);
1591
+ const pool = new (await lazyAuditPool()).AuditPool(stateDir);
1592
+ const escapeStore = new (await lazyEscape()).EscapeReportStore(stateDir);
1574
1593
  const auditItems = pool.list();
1575
1594
  const auditStats = pool.stats();
1576
1595
  const escapeReports = escapeStore.list();
1577
1596
  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) => {
1597
+ // 为所有能力生成动作决策(使用有效状态)
1598
+ const capabilities = (await lazyCapability()).getAllCapabilities();
1599
+ const stateStore = new (await lazyCapState()).CapabilityStateStore(stateDir);
1600
+ const decisions = await Promise.all(capabilities.map(async (cap) => {
1582
1601
  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
1602
+ return (await lazyCapAdvisor()).decideAction(escapeReports, effectiveState, cap.policy_id);
1603
+ }));
1604
+ // sampled_count 生成抽样决策
1605
+ const sampleResult = (await lazyAuditSampler()).sampleAuditItems(auditItems, seed);
1606
+ // 双层机制发现
1607
+ const dlFindings = (await lazyDualLayer()).validateMechanismLayerMaps();
1608
+ const dlMechanismCount = (await lazyDualLayer()).listMechanismLayerMaps().length;
1609
+ // 收集近期任务的产物记录
1591
1610
  const recentTasks = await taskContext.listRecent(20);
1592
1611
  const artifacts = [];
1593
1612
  for (const t of recentTasks) {
@@ -1595,25 +1614,25 @@ export function registerTools(server, deps) {
1595
1614
  if (tCtx?.artifact_output)
1596
1615
  artifacts.push(tCtx.artifact_output);
1597
1616
  }
1598
- // Collect config resolution reports use shared function for real data
1617
+ // 收集配置解析报告使用共享函数获取真实数据
1599
1618
  let configReports = [];
1600
1619
  let configEntries = [];
1601
1620
  try {
1602
- const resolved = await resolveCurrentProjectConfigReports(projectPath);
1621
+ const resolved = await (await lazyConfigPrecedence()).resolveCurrentProjectConfigReports(projectPath);
1603
1622
  configReports = resolved.reports;
1604
1623
  configEntries = resolved.entries;
1605
1624
  }
1606
1625
  catch (e) {
1607
1626
  console.error(`[soloForge] 配置报告解析失败: ${e instanceof Error ? e.message : String(e)}`);
1608
1627
  }
1609
- // Also include reports from recent task contexts
1628
+ // 同时包含近期任务上下文中的报告
1610
1629
  for (const t of recentTasks) {
1611
1630
  const tCtx = await taskContext.load(t.task_id);
1612
1631
  if (tCtx?.expansion?.config_resolution_reports) {
1613
1632
  configReports.push(...tCtx.expansion.config_resolution_reports);
1614
1633
  }
1615
1634
  }
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);
1635
+ 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
1636
  return {
1618
1637
  result: report,
1619
1638
  };
@@ -1625,7 +1644,7 @@ export function registerTools(server, deps) {
1625
1644
  };
1626
1645
  registerSafeTool("sf_audit_integration", "审计生产代码的主链路集成状态,检测孤岛模块(只被测试导入、无生产代码调用的模块)", AuditIntegrationSchema, async (args) => {
1627
1646
  const projectPath = config._projectPath || process.cwd();
1628
- // Use scope-aware production file collection (supports multi-repo, multi-lang)
1647
+ // 使用作用域感知的生产文件收集(支持多仓库、多语言)
1629
1648
  const { collectAllProductionFiles } = await import("../../engine/main_path_integration_contract.js");
1630
1649
  const allProdFiles = collectAllProductionFiles(projectPath, config);
1631
1650
  if (allProdFiles.length === 0) {
@@ -1636,8 +1655,8 @@ export function registerTools(server, deps) {
1636
1655
  const targetFiles = args.changed_files
1637
1656
  ? allProdFiles.filter((rel) => args.changed_files.some((cf) => rel === cf || rel.startsWith(cf.replace(/\.(ts|tsx|js|jsx|java|kt|go|py)$/, ""))))
1638
1657
  : allProdFiles;
1639
- const contracts = buildMainPathIntegrationContracts(projectPath, targetFiles, config);
1640
- const report = auditIntegration(contracts);
1658
+ const contracts = (await lazyMainPath()).buildMainPathIntegrationContracts(projectPath, targetFiles, config);
1659
+ const report = (await lazyMainPath()).auditIntegration(contracts);
1641
1660
  if (args.json_output) {
1642
1661
  return {
1643
1662
  result: report,