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
@@ -16,6 +16,7 @@ import { cmdConfigResolve, cmdConfigExplain, cmdConfigConfirm, cmdConfigUnset, l
16
16
  import { resolveCurrentProjectConfigReports, validateConfigPrecedence, } from "../engine/config_precedence_contract.js";
17
17
  import { isReadForbidden } from "../engine/privacy_secret_contract.js";
18
18
  import { routeIntent } from "../engine/intent_router.js";
19
+ import { debugLog } from "../engine/debug_log.js";
19
20
  const command = process.argv[2];
20
21
  const args = process.argv.slice(3);
21
22
  async function main() {
@@ -115,7 +116,7 @@ async function main() {
115
116
  generate-claude-md 生成包含工作流规则的 CLAUDE.md
116
117
  generate-trae 生成 .trae/mcp.json 和 .trae/rules/project_rules.md
117
118
  generate-codex 生成 .codex/ 配置和 AGENTS.md
118
- check-write PreToolUse hook,用于范围检查(读取 TOOL_INPUT 环境变量)
119
+ check-write PreToolUse hook,用于范围检查(读取 stdin JSON)
119
120
  post-bash PostToolUse hook,用于跟踪 Bash 执行结果
120
121
  validate 验证项目配置和知识文件(config.yaml 可选,缺失时自动推断)
121
122
  validate-mechanisms 验证双层机制承载模型完整性(模板层 + 机制层)
@@ -147,12 +148,12 @@ async function cmdInitAuto() {
147
148
  const icon = field.confidence === "high" ? "✅" : field.confidence === "medium" ? "⚠️" : "❓";
148
149
  const valStr = typeof field.value === "object" ? JSON.stringify(field.value) : String(field.value);
149
150
  console.log(` ${icon} ${key}: ${valStr} (${field.confidence}, ${field.confidence_source})`);
150
- console.log(` evidence: ${field.evidence.join(", ")}`);
151
+ console.log(` 证据: ${field.evidence.join(", ")}`);
151
152
  }
152
153
  console.log("=".repeat(50));
153
154
  console.log(`综合置信度: ${draft.confidence}`);
154
155
  if (draft.advisory_notes.length > 0) {
155
- console.log("advisory:");
156
+ console.log("建议:");
156
157
  for (const note of draft.advisory_notes) {
157
158
  console.log(` - ${note}`);
158
159
  }
@@ -160,13 +161,13 @@ async function cmdInitAuto() {
160
161
  // Schema 校验 (advisory)
161
162
  const validation = validateConfigDraft(draft);
162
163
  if (validation.warnings.length > 0) {
163
- console.log("\nschema advisory:");
164
+ console.log("\nschema 建议:");
164
165
  for (const w of validation.warnings) {
165
166
  console.log(` ⚠️ ${w}`);
166
167
  }
167
168
  }
168
169
  if (!validation.valid) {
169
- console.log("\nschema errors:");
170
+ console.log("\nschema 错误:");
170
171
  for (const e of validation.errors) {
171
172
  console.log(` ❌ ${e}`);
172
173
  }
@@ -224,9 +225,9 @@ function writeConfigWithEvidence(projectPath, draft, evidence) {
224
225
  scope: draft.scope,
225
226
  };
226
227
  fss.writeFileSync(configPath, YAML.stringify(yamlConfig), "utf-8");
227
- // Write legacy evidence format (backward compat) + schema v2 entries
228
+ // 写入旧版 evidence 格式(向后兼容)+ schema v2 条目
228
229
  fss.writeFileSync(evidencePath, JSON.stringify(evidence, null, 2), "utf-8");
229
- // Also write schema v2 entries
230
+ // 同时写入 schema v2 条目
230
231
  const v2Entries = Object.entries(evidence.fields).map(([key, field]) => ({
231
232
  field_path: key,
232
233
  value_hash: hashConfigValue(JSON.stringify(field.value)),
@@ -236,7 +237,7 @@ function writeConfigWithEvidence(projectPath, draft, evidence) {
236
237
  lifetime: "project_persistent",
237
238
  collected_at: evidence.generated_at || new Date().toISOString(),
238
239
  }));
239
- // Merge v2 entries into the evidence file
240
+ // 合并 v2 条目到 evidence 文件
240
241
  try {
241
242
  const existing = JSON.parse(fss.readFileSync(evidencePath, "utf-8"));
242
243
  existing.entries = v2Entries;
@@ -274,7 +275,7 @@ async function cmdInitBlueprint() {
274
275
  console.log("支持的框架关键词: Spring Boot, Go, Rust, Gradle, React, Vue, Angular, Next.js, Nuxt");
275
276
  return;
276
277
  }
277
- // Build draft from parsed blueprint
278
+ // 从解析的蓝图构建草稿
278
279
  const draft = {
279
280
  name: path.basename(projectPath),
280
281
  tech_stack: {
@@ -294,7 +295,7 @@ async function cmdInitBlueprint() {
294
295
  confidence: "high",
295
296
  };
296
297
  const evidence = generateBlueprintEvidence(blueprintText, draft, projectPath);
297
- // Create dirs + write config + evidence
298
+ // 创建目录 + 写入配置 + evidence
298
299
  const dirs = [
299
300
  ".soloforge/state", ".soloforge/state/debt",
300
301
  ".soloforge/knowledge/patterns", ".soloforge/knowledge/patterns/core",
@@ -363,7 +364,7 @@ async function cmdInit() {
363
364
  if (interactive) {
364
365
  const config = await interactiveConfig(projectPath);
365
366
  if (config) {
366
- // config is { draft, evidence }
367
+ // config 结构为 { draft, evidence }
367
368
  writeConfigWithEvidence(projectPath, config.draft, config.evidence);
368
369
  }
369
370
  else if (!process.stdin.isTTY) {
@@ -388,7 +389,7 @@ async function cmdInit() {
388
389
  },
389
390
  };
390
391
  fss.writeFileSync(mcpPath, JSON.stringify(mcpConfig, null, 2), "utf-8");
391
- console.log("✅ .mcp.json created (soloforge + playwright)");
392
+ console.log("✅ .mcp.json 已创建(soloforge + playwright");
392
393
  }
393
394
  // 生成 hooks
394
395
  await cmdGenerateHooks(projectPath);
@@ -427,7 +428,7 @@ async function copyGlobalPatterns(projectPath) {
427
428
  fss.copyFileSync(src, dest);
428
429
  }
429
430
  }
430
- console.log(`✅ ${files.length} default patterns copied to ~/.soloforge/patterns/`);
431
+ console.log(`✅ ${files.length} 个默认模板已复制到 ~/.soloforge/patterns/`);
431
432
  }
432
433
  }
433
434
  async function copyKnowledgeTemplates(projectPath) {
@@ -452,7 +453,7 @@ async function copyKnowledgeTemplates(projectPath) {
452
453
  }
453
454
  }
454
455
  if (copiedCount > 0) {
455
- console.log(`✅ ${copiedCount} knowledge templates copied to .soloforge/knowledge/`);
456
+ console.log(`✅ ${copiedCount} 个知识模板已复制到 .soloforge/knowledge/`);
456
457
  }
457
458
  }
458
459
  }
@@ -467,7 +468,7 @@ async function generateAdapterConfigs(projectPath, adapter) {
467
468
  },
468
469
  };
469
470
  fss.writeFileSync(mcpPath, JSON.stringify(mcpConfig, null, 2), "utf-8");
470
- console.log("✅ .mcp.json created (soloforge + playwright)");
471
+ console.log("✅ .mcp.json 已创建(soloforge + playwright");
471
472
  }
472
473
  await cmdGenerateHooks(projectPath);
473
474
  await cmdGenerateClaudeMdInner(projectPath);
@@ -485,7 +486,7 @@ function ensureGitignore(projectPath) {
485
486
  if (missing.length > 0) {
486
487
  const addition = (content.endsWith("\n") ? "" : "\n") + missing.join("\n") + "\n";
487
488
  fss.appendFileSync(gitignorePath, addition, "utf-8");
488
- console.log(`✅ .gitignore updated with: ${missing.join(", ")}`);
489
+ console.log(`✅ .gitignore 已更新: ${missing.join(", ")}`);
489
490
  }
490
491
  }
491
492
  async function cmdGenerateHooks(projectPath) {
@@ -506,7 +507,7 @@ async function cmdGenerateHooks(projectPath) {
506
507
  // 仅 merge hooks 字段,保留用户的 permissions/env 等设置
507
508
  existing.hooks = hooksConfig.hooks;
508
509
  fss.writeFileSync(settingsPath, JSON.stringify(existing, null, 2), "utf-8");
509
- console.log("✅ .claude/settings.json updated with hooks");
510
+ console.log("✅ .claude/settings.json 已更新 hooks 配置");
510
511
  }
511
512
  async function cmdGenerateClaudeMd() {
512
513
  await cmdGenerateClaudeMdInner(process.cwd());
@@ -523,23 +524,23 @@ async function cmdGenerateCodexInner(projectPath) {
523
524
  fss.mkdirSync(codexDir, { recursive: true });
524
525
  const tomlContent = generateCodexMcpConfig(projectPath);
525
526
  fss.writeFileSync(path.join(codexDir, "config.toml"), tomlContent, "utf-8");
526
- console.log("✅ .codex/config.toml created");
527
+ console.log("✅ .codex/config.toml 已创建");
527
528
  // 生成 .codex/hooks.json
528
529
  const hooksContent = generateCodexHooksConfig();
529
530
  fss.writeFileSync(path.join(codexDir, "hooks.json"), hooksContent, "utf-8");
530
- console.log("✅ .codex/hooks.json created");
531
+ console.log("✅ .codex/hooks.json 已创建");
531
532
  // 生成 AGENTS.md
532
533
  const { config } = await resolveProjectConfig(projectPath);
533
534
  const agentsContent = generateCodexAgentsMd(config);
534
535
  fss.writeFileSync(path.join(projectPath, "AGENTS.md"), agentsContent, "utf-8");
535
- console.log("✅ AGENTS.md created");
536
+ console.log("✅ AGENTS.md 已创建");
536
537
  }
537
538
  async function cmdGenerateTraeInner(projectPath) {
538
539
  // 生成 .trae/mcp.json
539
540
  const traeDir = path.join(projectPath, ".trae");
540
541
  fss.mkdirSync(traeDir, { recursive: true });
541
542
  const traeMcpPath = path.join(traeDir, "mcp.json");
542
- const traeMcpConfig = generateTraeMcpConfig();
543
+ const traeMcpConfig = generateTraeMcpConfig(projectPath);
543
544
  fss.writeFileSync(traeMcpPath, JSON.stringify(traeMcpConfig, null, 2), "utf-8");
544
545
  console.log("✅ .trae/mcp.json created");
545
546
  // 生成 .trae/rules/project_rules.md
@@ -557,16 +558,11 @@ async function cmdGenerateClaudeMdInner(projectPath) {
557
558
  console.log("✅ CLAUDE.md created");
558
559
  }
559
560
  async function cmdCheckWrite() {
560
- console.error("[soloForge] CLI: 执行 cmdCheckWrite");
561
+ debugLog("CLI: 执行 cmdCheckWrite");
561
562
  try {
562
- // 检测运行环境: Claude Code 通过 TOOL_INPUT 环境变量,Codex 通过 stdin JSON
563
- const isClaudeCode = !!process.env.TOOL_INPUT;
563
+ // 所有适配器均通过 stdin 读取 JSON(Claude Code / Codex 统一)
564
564
  let toolInput;
565
- if (isClaudeCode) {
566
- toolInput = process.env.TOOL_INPUT;
567
- }
568
- else {
569
- // Codex: 从 stdin 读取 JSON
565
+ {
570
566
  const chunks = [];
571
567
  for await (const chunk of process.stdin) {
572
568
  chunks.push(chunk);
@@ -585,13 +581,11 @@ async function cmdCheckWrite() {
585
581
  const parsed = JSON.parse(toolInput);
586
582
  let filePath;
587
583
  let content;
588
- if (isClaudeCode) {
589
- filePath = parsed.file_path || parsed.path || "";
590
- content = parsed.content || parsed.new_string || "";
591
- }
592
- else {
593
- // Codex stdin JSON 使用不同的字段名
594
- const input = parsed.input || parsed;
584
+ {
585
+ // Claude Code: { tool_input: { file_path, content/new_string } } 格式
586
+ // Codex: { input: { file_path, content/new_string } } 格式
587
+ // 回退: 顶层 { file_path, content/new_string }
588
+ const input = parsed.tool_input || parsed.input || parsed;
595
589
  filePath = input.file_path || input.path || "";
596
590
  content = input.content || input.new_string || "";
597
591
  }
@@ -607,57 +601,36 @@ async function cmdCheckWrite() {
607
601
  // 使用 scope_controller 统一检查
608
602
  const { checkScope } = await import("../engine/scope_controller.js");
609
603
  const result = checkScope(filePath, allowedPaths, content || undefined);
610
- // Privacy / Secret Contract: forbidden read patterns
604
+ // 隐私/秘密契约:禁止读取的模式
611
605
  if (isReadForbidden(filePath)) {
612
- if (isClaudeCode) {
613
- console.error(JSON.stringify({
614
- allowed: false,
615
- reason: `隐私策略: ${filePath} 匹配禁止读取模式`,
616
- has_secrets: true,
617
- severity: "blocked",
618
- }));
619
- process.exit(1);
620
- }
621
- else {
622
- process.stdout.write(JSON.stringify({
623
- hookSpecificOutput: {
624
- hookEventName: "PreToolUse",
625
- permissionDecision: "deny",
626
- permissionDecisionReason: `隐私策略: ${filePath} 匹配禁止读取模式`,
627
- },
628
- }));
629
- process.exit(0);
630
- }
606
+ process.stdout.write(JSON.stringify({
607
+ hookSpecificOutput: {
608
+ hookEventName: "PreToolUse",
609
+ permissionDecision: "deny",
610
+ permissionDecisionReason: `隐私策略: ${filePath} 匹配禁止读取模式`,
611
+ },
612
+ }));
613
+ process.exit(0);
631
614
  }
632
615
  if (result.severity === "blocked") {
633
- if (isClaudeCode) {
634
- console.error(JSON.stringify(result));
635
- process.exit(1);
636
- }
637
- else {
638
- // Codex: stdout 输出特定 JSON 拒绝格式
639
- const denyOutput = {
640
- hookSpecificOutput: {
641
- hookEventName: "PreToolUse",
642
- permissionDecision: "deny",
643
- permissionDecisionReason: result.reason || "Write blocked by scope check",
644
- },
645
- };
646
- process.stdout.write(JSON.stringify(denyOutput));
647
- process.exit(0);
648
- }
616
+ const denyOutput = {
617
+ hookSpecificOutput: {
618
+ hookEventName: "PreToolUse",
619
+ permissionDecision: "deny",
620
+ permissionDecisionReason: result.reason || "范围检查阻止了写入",
621
+ },
622
+ };
623
+ process.stdout.write(JSON.stringify(denyOutput));
624
+ process.exit(0);
649
625
  }
650
626
  if (result.severity === "warning") {
651
- if (isClaudeCode) {
652
- console.error(JSON.stringify(result));
653
- }
654
- // 警告不阻止操作
627
+ console.error(JSON.stringify(result));
655
628
  }
656
629
  process.exit(0); // 允许
657
630
  }
658
631
  catch (e) {
659
- console.error(`SoloForge check-write error: ${e instanceof Error ? e.message : String(e)}`);
660
- process.exit(1); // 出错时拦截(fail-closed 策略:安全钩子宁可误拦也不放行)
632
+ console.error(`SoloForge 写入检查错误: ${e instanceof Error ? e.message : String(e)}`);
633
+ process.exit(1);
661
634
  }
662
635
  }
663
636
  function resolveProjectPath() {
@@ -679,16 +652,16 @@ function resolveProjectPath() {
679
652
  return process.cwd();
680
653
  }
681
654
  async function cmdPostBash() {
682
- console.error("[soloForge] CLI: 执行 cmdPostBash");
655
+ debugLog("CLI: 执行 cmdPostBash");
683
656
  // Bash 的 PostToolUse hook — 目前为空操作占位符
684
657
  // 未来: 跟踪命令结果,检测构建/测试失败
685
658
  process.exit(0);
686
659
  }
687
660
  export { buildHookAdditionalContext } from "../adapters/claude_code/pre_prompt_contract.js";
688
661
  async function cmdPrePrompt() {
689
- console.error("[soloForge] CLI: 执行 cmdPrePrompt");
662
+ debugLog("CLI: 执行 cmdPrePrompt");
690
663
  try {
691
- // UserPromptSubmit hook receives JSON on stdin with { prompt: "..." }
664
+ // UserPromptSubmit hook stdin 接收 JSON { prompt: "..." }
692
665
  const chunks = [];
693
666
  for await (const chunk of process.stdin) {
694
667
  chunks.push(chunk);
@@ -710,21 +683,23 @@ async function cmdPrePrompt() {
710
683
  process.exit(0);
711
684
  return;
712
685
  }
713
- // Use intent router to classify if route is SoloForge-worthy, inject structured context
686
+ // 使用意图路由器分类如果路由属于 SoloForge 范畴,注入结构化上下文
714
687
  const decision = routeIntent({ intent: userMessage });
715
688
  const additionalContext = buildHookAdditionalContext(decision);
716
689
  if (additionalContext) {
717
690
  const output = {
718
691
  hookSpecificOutput: {
719
692
  hookEventName: "UserPromptSubmit",
720
- additionalContext,
693
+ additionalContext: typeof additionalContext === "string"
694
+ ? additionalContext
695
+ : JSON.stringify(additionalContext),
721
696
  },
722
697
  };
723
698
  process.stdout.write(JSON.stringify(output));
724
699
  }
725
700
  }
726
701
  catch (e) {
727
- console.error("[soloForge] pre-prompt hook error:", e);
702
+ console.error("[soloForge] pre-prompt hook 错误:", e);
728
703
  }
729
704
  process.exit(0);
730
705
  }
@@ -736,19 +711,19 @@ async function checkEvidenceWarnings(projectPath) {
736
711
  if (!fss.existsSync(configPath))
737
712
  return warnings;
738
713
  if (!fss.existsSync(evidencePath)) {
739
- warnings.push("config.yaml exists but config.evidence.json is missing source traceability lost");
714
+ warnings.push("config.yaml 存在但 config.evidence.json 缺失来源追溯性丢失");
740
715
  return warnings;
741
716
  }
742
- // Check mtime staleness
717
+ // 检查 mtime 过期
743
718
  try {
744
719
  const configStat = fss.statSync(configPath);
745
720
  const evidenceStat = fss.statSync(evidencePath);
746
721
  if (configStat.mtimeMs > evidenceStat.mtimeMs) {
747
- warnings.push("config.evidence.json is stale (config.yaml was modified after evidence was generated)");
722
+ warnings.push("config.evidence.json 已过期(config.yaml evidence 生成后被修改)");
748
723
  }
749
724
  }
750
725
  catch { }
751
- // Legacy field consistency check (schema v1 evidence)
726
+ // 旧版字段一致性检查(schema v1 evidence
752
727
  try {
753
728
  const evidenceRaw = JSON.parse(fss.readFileSync(evidencePath, "utf-8"));
754
729
  const configContent = fss.readFileSync(configPath, "utf-8");
@@ -756,23 +731,23 @@ async function checkEvidenceWarnings(projectPath) {
756
731
  for (const [key, field] of Object.entries(evidenceRaw.fields)) {
757
732
  const actualValue = getConfigFieldValue(config, key);
758
733
  if (actualValue !== undefined && JSON.stringify(field.value) !== JSON.stringify(actualValue)) {
759
- warnings.push(`evidence field '${key}' value does not match config.yaml`);
734
+ warnings.push(`evidence 字段 '${key}' 的值与 config.yaml 不匹配`);
760
735
  }
761
736
  }
762
737
  }
763
738
  catch { }
764
- // Config precedence validation using schema v2 entries
739
+ // 使用 schema v2 条目验证配置优先级
765
740
  try {
766
741
  const entries = loadConfigEvidenceEntries(projectPath);
767
- // Check C-class auto-write violations
742
+ // 检查 C 类字段自动写入违规
768
743
  for (const e of entries) {
769
744
  if (e.source === "cli_flag" || e.source === "mcp_param") {
770
745
  if (e.lifetime === "project_persistent") {
771
- warnings.push(`CLI/MCP parameter (${e.source}) persisted to config — field: ${e.field_path}`);
746
+ warnings.push(`CLI/MCP 参数(${e.source})已持久化到 config — 字段: ${e.field_path}`);
772
747
  }
773
748
  }
774
749
  }
775
- // Run config precedence validation with live resolution
750
+ // 运行实时解析的配置优先级验证
776
751
  try {
777
752
  const { reports } = await resolveCurrentProjectConfigReports(projectPath);
778
753
  const findings = validateConfigPrecedence(reports, entries);
@@ -803,13 +778,13 @@ async function cmdValidate() {
803
778
  try {
804
779
  const { config, source } = await resolveProjectConfig(projectPath);
805
780
  if (source === "inferred") {
806
- console.log("ℹ️ No .soloforge/config.yaml found using auto-inferred configuration.");
807
- console.log(" Run 'soloforge init --auto' to persist.");
781
+ console.log("ℹ️ 未找到 .soloforge/config.yaml — 使用自动推断的配置。");
782
+ console.log(" 运行 'soloforge init --auto' 可持久化。");
808
783
  }
809
784
  else {
810
- console.log("✅ config.yaml is valid");
785
+ console.log("✅ config.yaml 有效");
811
786
  }
812
- // Config precedence validation using shared function
787
+ // 使用共享函数验证配置优先级
813
788
  let hasHardFail = false;
814
789
  try {
815
790
  const { reports, entries } = await resolveCurrentProjectConfigReports(projectPath);
@@ -834,7 +809,7 @@ async function cmdValidate() {
834
809
  }
835
810
  }
836
811
  catch { }
837
- // Evidence checks
812
+ // Evidence 检查
838
813
  const evidenceWarnings = await checkEvidenceWarnings(projectPath);
839
814
  for (const w of evidenceWarnings) {
840
815
  console.log(`⚠️ evidence: ${w}`);
@@ -846,10 +821,10 @@ async function cmdValidate() {
846
821
  const index = new KnowledgeIndexManager(config);
847
822
  await index.build();
848
823
  const entries = index.getAllEntries();
849
- console.log(`✅ ${entries.project.length} project knowledge entries indexed`);
824
+ console.log(`✅ ${entries.project.length} 条项目知识已索引`);
850
825
  const issues = await index.checkHealth();
851
826
  if (issues.length > 0) {
852
- console.log(`⚠️ ${issues.length} health issues found:`);
827
+ console.log(`⚠️ ${issues.length} 个健康问题:`);
853
828
  for (const { entry, issue } of issues) {
854
829
  console.log(` - ${entry.name}: ${issue}`);
855
830
  }
@@ -872,7 +847,7 @@ async function cmdValidate() {
872
847
  else {
873
848
  console.log(`✅ 双层机制验证: ${dlAdvisory.length} advisory, 0 hard_fail`);
874
849
  }
875
- } // end dual-layer check
850
+ } // 双层机制检查结束
876
851
  if (hasHardFail) {
877
852
  console.error("❌ validate 失败: 配置优先级存在 hard_fail");
878
853
  process.exit(1);
@@ -885,7 +860,7 @@ async function cmdValidate() {
885
860
  }
886
861
  async function cmdValidateMechanisms() {
887
862
  console.error("[soloForge] CLI: 执行 cmdValidateMechanisms");
888
- // Resolve root from compiled binary location: dist/bin/soloforge.js -> project root
863
+ // 从编译后的二进制位置推导根目录: dist/bin/soloforge.js -> 项目根
889
864
  const soloforgeRoot = path.resolve(import.meta.dirname, "..", "..");
890
865
  const projectPath = fss.existsSync(path.join(soloforgeRoot, "src", "engine"))
891
866
  ? soloforgeRoot
@@ -915,7 +890,7 @@ async function cmdValidateMechanisms() {
915
890
  process.exit(1);
916
891
  }
917
892
  console.log(`\n✅ 双层机制验证通过,${advisory.length} advisory findings`);
918
- // Audit summary
893
+ // 审计摘要
919
894
  try {
920
895
  const { auditTemplateMechanisms } = await import("../engine/template_mechanism_auditor.js");
921
896
  const audit = auditTemplateMechanisms(projectPath);
@@ -927,7 +902,7 @@ async function cmdValidateMechanisms() {
927
902
  }
928
903
  }
929
904
  catch {
930
- // audit is advisory, not blocking
905
+ // 审计仅为建议,不阻断
931
906
  }
932
907
  }
933
908
  catch (e) {
@@ -939,7 +914,7 @@ async function cmdAuditTemplateMechanisms() {
939
914
  console.error("[soloForge] CLI: 执行 cmdAuditTemplateMechanisms");
940
915
  const asJson = args.includes("--json");
941
916
  const changedOnly = args.includes("--changed-only");
942
- // Resolve root from compiled binary location
917
+ // 从编译后的二进制位置推导根目录
943
918
  const soloforgeRoot = path.resolve(import.meta.dirname, "..", "..");
944
919
  const projectPath = fss.existsSync(path.join(soloforgeRoot, "src", "engine"))
945
920
  ? soloforgeRoot
@@ -954,7 +929,7 @@ async function cmdAuditTemplateMechanisms() {
954
929
  }
955
930
  return;
956
931
  }
957
- // Human-readable output
932
+ // 人类可读输出
958
933
  console.log(`模板-机制审计报告 (${report.generated_at})`);
959
934
  console.log(` 模板文件: ${report.total_template_files}`);
960
935
  console.log(` 注册资产: ${report.total_registered_assets}`);
@@ -1067,7 +1042,7 @@ async function cmdValidateBatch1() {
1067
1042
  console.log(`${ri} ${r.rule}: ${r.evidence}`);
1068
1043
  }
1069
1044
  }
1070
- console.log(allPass ? "\nAll scenarios PASS" : "\nSome scenarios FAIL");
1045
+ console.log(allPass ? "\n所有场景通过" : "\n部分场景失败");
1071
1046
  }
1072
1047
  process.exit(allPass ? 0 : 1);
1073
1048
  }
@@ -1080,7 +1055,7 @@ async function cmdStatus() {
1080
1055
  console.log(` 产品: ${config.product_profile}`);
1081
1056
  console.log(` 后端: ${config.tech_stack.backend.framework || "未配置"}`);
1082
1057
  console.log(` 前端: ${config.tech_stack.frontend.framework || "未配置"}`);
1083
- // Per-field config precedence status
1058
+ // 逐字段配置优先级状态
1084
1059
  try {
1085
1060
  const { resolutions, entries } = await resolveCurrentProjectConfigReports(projectPath);
1086
1061
  if (resolutions.length > 0) {
@@ -1096,7 +1071,7 @@ async function cmdStatus() {
1096
1071
  if (fss.existsSync(schemaPath)) {
1097
1072
  try {
1098
1073
  const raw = JSON.parse(fss.readFileSync(schemaPath, "utf-8"));
1099
- console.log(` evidence: schema_version=${raw.schema_version ?? 1}, ${entries.length} entries`);
1074
+ console.log(` evidence: schema_version=${raw.schema_version ?? 1}, ${entries.length} 条`);
1100
1075
  }
1101
1076
  catch {
1102
1077
  console.log(" evidence: 无法解析");
@@ -1107,7 +1082,7 @@ async function cmdStatus() {
1107
1082
  }
1108
1083
  }
1109
1084
  catch { }
1110
- // Evidence warnings
1085
+ // Evidence 警告
1111
1086
  const evidenceWarnings = await checkEvidenceWarnings(projectPath);
1112
1087
  for (const w of evidenceWarnings) {
1113
1088
  console.log(` ⚠️ evidence: ${w}`);