soloforge 1.3.2 → 1.3.4

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 (124) hide show
  1. package/README.md +14 -0
  2. package/dist/adapters/claude_code/server.js +1 -1
  3. package/dist/adapters/claude_code/server.js.map +1 -1
  4. package/dist/adapters/claude_code/tools.d.ts.map +1 -1
  5. package/dist/adapters/claude_code/tools.js +385 -15
  6. package/dist/adapters/claude_code/tools.js.map +1 -1
  7. package/dist/adapters/shared/workflow_template.d.ts.map +1 -1
  8. package/dist/adapters/shared/workflow_template.js +3 -2
  9. package/dist/adapters/shared/workflow_template.js.map +1 -1
  10. package/dist/bin/soloforge.d.ts.map +1 -1
  11. package/dist/bin/soloforge.js +296 -1
  12. package/dist/bin/soloforge.js.map +1 -1
  13. package/dist/engine/asset_manifest.d.ts.map +1 -1
  14. package/dist/engine/asset_manifest.js +24 -0
  15. package/dist/engine/asset_manifest.js.map +1 -1
  16. package/dist/engine/backend_implementation_contract.d.ts +51 -0
  17. package/dist/engine/backend_implementation_contract.d.ts.map +1 -0
  18. package/dist/engine/backend_implementation_contract.js +142 -0
  19. package/dist/engine/backend_implementation_contract.js.map +1 -0
  20. package/dist/engine/code_maintainability_observability_contract.d.ts +74 -0
  21. package/dist/engine/code_maintainability_observability_contract.d.ts.map +1 -0
  22. package/dist/engine/code_maintainability_observability_contract.js +473 -0
  23. package/dist/engine/code_maintainability_observability_contract.js.map +1 -0
  24. package/dist/engine/config_write_boundary.d.ts +29 -0
  25. package/dist/engine/config_write_boundary.d.ts.map +1 -0
  26. package/dist/engine/config_write_boundary.js +69 -0
  27. package/dist/engine/config_write_boundary.js.map +1 -0
  28. package/dist/engine/consumable_asset_registry.d.ts.map +1 -1
  29. package/dist/engine/consumable_asset_registry.js +182 -1
  30. package/dist/engine/consumable_asset_registry.js.map +1 -1
  31. package/dist/engine/diagnostic_registry.d.ts +12 -0
  32. package/dist/engine/diagnostic_registry.d.ts.map +1 -1
  33. package/dist/engine/diagnostic_registry.js +62 -0
  34. package/dist/engine/diagnostic_registry.js.map +1 -1
  35. package/dist/engine/dual_layer_mechanism_registry.d.ts.map +1 -1
  36. package/dist/engine/dual_layer_mechanism_registry.js +318 -1
  37. package/dist/engine/dual_layer_mechanism_registry.js.map +1 -1
  38. package/dist/engine/explicit_asset_registry.d.ts.map +1 -1
  39. package/dist/engine/explicit_asset_registry.js +338 -0
  40. package/dist/engine/explicit_asset_registry.js.map +1 -1
  41. package/dist/engine/implementation_roadmap_registry.d.ts.map +1 -1
  42. package/dist/engine/implementation_roadmap_registry.js +112 -2
  43. package/dist/engine/implementation_roadmap_registry.js.map +1 -1
  44. package/dist/engine/knowledge_governance_gate.d.ts +38 -0
  45. package/dist/engine/knowledge_governance_gate.d.ts.map +1 -0
  46. package/dist/engine/knowledge_governance_gate.js +123 -0
  47. package/dist/engine/knowledge_governance_gate.js.map +1 -0
  48. package/dist/engine/log_governance.d.ts +25 -0
  49. package/dist/engine/log_governance.d.ts.map +1 -0
  50. package/dist/engine/log_governance.js +76 -0
  51. package/dist/engine/log_governance.js.map +1 -0
  52. package/dist/engine/mechanism_contract_registry.d.ts +1 -0
  53. package/dist/engine/mechanism_contract_registry.d.ts.map +1 -1
  54. package/dist/engine/mechanism_contract_registry.js +172 -0
  55. package/dist/engine/mechanism_contract_registry.js.map +1 -1
  56. package/dist/engine/mechanism_health_check.d.ts +23 -0
  57. package/dist/engine/mechanism_health_check.d.ts.map +1 -0
  58. package/dist/engine/mechanism_health_check.js +140 -0
  59. package/dist/engine/mechanism_health_check.js.map +1 -0
  60. package/dist/engine/next_action_planner.d.ts +19 -0
  61. package/dist/engine/next_action_planner.d.ts.map +1 -0
  62. package/dist/engine/next_action_planner.js +453 -0
  63. package/dist/engine/next_action_planner.js.map +1 -0
  64. package/dist/engine/observability.js +1 -1
  65. package/dist/engine/observability.js.map +1 -1
  66. package/dist/engine/ood_solid_contract.d.ts +51 -0
  67. package/dist/engine/ood_solid_contract.d.ts.map +1 -0
  68. package/dist/engine/ood_solid_contract.js +115 -0
  69. package/dist/engine/ood_solid_contract.js.map +1 -0
  70. package/dist/engine/project_stage_detector.d.ts +17 -0
  71. package/dist/engine/project_stage_detector.d.ts.map +1 -0
  72. package/dist/engine/project_stage_detector.js +185 -0
  73. package/dist/engine/project_stage_detector.js.map +1 -0
  74. package/dist/engine/release_issue_scenario_registry.d.ts.map +1 -1
  75. package/dist/engine/release_issue_scenario_registry.js +230 -1
  76. package/dist/engine/release_issue_scenario_registry.js.map +1 -1
  77. package/dist/engine/release_readiness_gate.d.ts +3 -0
  78. package/dist/engine/release_readiness_gate.d.ts.map +1 -1
  79. package/dist/engine/release_readiness_gate.js +407 -9
  80. package/dist/engine/release_readiness_gate.js.map +1 -1
  81. package/dist/engine/stale_current_task_detector.d.ts +30 -0
  82. package/dist/engine/stale_current_task_detector.d.ts.map +1 -0
  83. package/dist/engine/stale_current_task_detector.js +168 -0
  84. package/dist/engine/stale_current_task_detector.js.map +1 -0
  85. package/dist/engine/task_stage_detector.d.ts +19 -0
  86. package/dist/engine/task_stage_detector.d.ts.map +1 -0
  87. package/dist/engine/task_stage_detector.js +201 -0
  88. package/dist/engine/task_stage_detector.js.map +1 -0
  89. package/dist/engine/team_awareness.js +6 -6
  90. package/dist/engine/team_awareness.js.map +1 -1
  91. package/dist/engine/tool_invocation_contract_registry.d.ts.map +1 -1
  92. package/dist/engine/tool_invocation_contract_registry.js +10 -0
  93. package/dist/engine/tool_invocation_contract_registry.js.map +1 -1
  94. package/dist/engine/workflow_navigation_contract.d.ts +115 -0
  95. package/dist/engine/workflow_navigation_contract.d.ts.map +1 -0
  96. package/dist/engine/workflow_navigation_contract.js +39 -0
  97. package/dist/engine/workflow_navigation_contract.js.map +1 -0
  98. package/dist/types.d.ts +12 -0
  99. package/dist/types.d.ts.map +1 -1
  100. package/package.json +1 -1
  101. package/templates/knowledge/acceptance_templates/OOD/350/256/276/350/256/241/346/221/230/350/246/201/346/250/241/347/211/210.md +60 -0
  102. package/templates/knowledge/acceptance_templates//344/273/243/347/240/201/346/263/250/351/207/212/344/270/216/346/227/245/345/277/227/351/252/214/346/224/266/346/250/241/346/235/277.md +78 -0
  103. package/templates/knowledge/acceptance_templates//345/220/216/347/253/257/345/256/236/347/216/260/351/252/214/346/224/266/346/270/205/345/215/225.md +46 -0
  104. package/templates/knowledge/procedures/OOD/350/256/276/350/256/241/345/267/245/344/275/234/346/265/201.md +50 -0
  105. package/templates/knowledge/procedures//345/205/250/347/224/237/345/221/275/345/221/250/346/234/237/345/267/245/344/275/234/346/265/201/345/257/274/350/210/252.md +100 -0
  106. package/templates/knowledge/procedures//345/220/216/347/253/257/346/216/245/345/217/243/345/256/236/347/216/260/345/267/245/344/275/234/346/265/201.md +50 -0
  107. package/templates/knowledge/review//344/273/243/347/240/201/345/217/257/347/273/264/346/212/244/346/200/247/344/270/216/345/217/257/350/247/202/346/265/213/346/200/247/345/256/241/346/237/245.md +81 -0
  108. package/templates/knowledge/review_rules/SOLID/344/273/243/347/240/201/345/256/241/346/237/245/350/247/204/345/210/231.md +40 -0
  109. package/templates/knowledge/review_rules//345/220/216/347/253/257/345/256/236/347/216/260/345/267/245/347/250/213/345/256/241/346/237/245/350/247/204/345/210/231.md +38 -0
  110. package/templates/knowledge/rules/OOD/344/270/216SOLID/350/256/276/350/256/241/350/247/204/345/210/231.md +62 -0
  111. package/templates/knowledge/rules//344/273/243/347/240/201/346/263/250/351/207/212/344/270/216/346/227/245/345/277/227/345/245/221/347/272/246/350/247/204/345/210/231.md +121 -0
  112. package/templates/knowledge/rules//345/220/216/347/253/257/345/256/236/347/216/260/345/267/245/347/250/213/345/245/221/347/272/246/350/247/204/345/210/231.md +55 -0
  113. package/templates/knowledge/rules//345/267/245/344/275/234/346/265/201/345/257/274/350/210/252/345/245/221/347/272/246/350/247/204/345/210/231.md +113 -0
  114. package/templates/knowledge/rules//346/225/217/346/204/237/344/277/241/346/201/257/346/227/245/345/277/227/350/247/204/345/210/231.md +69 -0
  115. package/templates/knowledge/rules//346/227/245/345/277/227/346/262/273/347/220/206/350/247/204/345/210/231.md +49 -0
  116. package/templates/knowledge/rules//346/234/272/345/210/266/350/207/252/346/262/273/347/220/206/350/247/204/345/210/231.md +48 -0
  117. package/templates/knowledge/rules//346/240/207/345/207/206/350/265/204/344/272/247/350/246/206/347/233/226/350/247/204/345/210/231.md +43 -0
  118. package/templates/knowledge/rules//346/250/241/346/235/277/350/265/204/344/272/247/345/217/257/350/247/201/346/200/247/350/247/204/345/210/231.md +44 -0
  119. package/templates/knowledge/rules//347/237/245/350/257/206/346/262/273/347/220/206/350/247/204/345/210/231.md +50 -0
  120. package/templates/knowledge/rules//351/200/232/347/224/250/345/206/263/347/255/226/347/240/224/350/256/250/350/247/204/345/210/231.md +47 -0
  121. package/templates/knowledge/rules//351/205/215/347/275/256/350/220/275/347/233/230/350/276/271/347/225/214/350/247/204/345/210/231.md +47 -0
  122. package/templates/knowledge/rules//351/252/214/346/224/266/346/250/241/346/235/277/350/276/223/345/207/272/345/245/221/347/272/246/350/247/204/345/210/231.md +46 -0
  123. package/templates/patterns/SOLID/350/256/276/350/256/241/350/247/204/350/214/203.md +39 -0
  124. package/templates/patterns//345/220/216/347/253/257/345/256/236/347/216/260/345/267/245/347/250/213/350/247/204/350/214/203.md +39 -0
@@ -21,6 +21,9 @@
21
21
  * 13. 第五批一致性校验
22
22
  * 14. 依赖漏洞扫描
23
23
  * 15. 发布问题架构决策与设计产物真实消费
24
+ * 18. 代码可维护性与可观测性契约行为验证
25
+ * 19. 历史问题长期机制化行为验证
26
+ * 20. 诊断码集中治理检查
24
27
  */
25
28
  import fs from "node:fs";
26
29
  import os from "node:os";
@@ -1136,13 +1139,13 @@ async function checkBatchIssueFormatConsistency(rootDir, hardFail, _info) {
1136
1139
  hardFail("BATCH_ISSUE_FORMAT_INCONSISTENT", "loadBatchIssueDetails 导出未找到", ["scripts/batch_issue_details.mjs"], "构建系统", "共享解析脚本导出不正确", "修复脚本");
1137
1140
  return;
1138
1141
  }
1139
- const expectedCounts = { 1: 19, 2: 12, 3: 9, 4: 13, 5: 6, 6: 4 };
1142
+ const expectedCounts = { 1: 19, 2: 12, 3: 9, 4: 13, 5: 6, 6: 5, 7: 2, 8: 1 };
1140
1143
  const requiredPerProblemSections = [
1141
1144
  "问题背景", "用户反馈 / 触发场景", "根因分析", "解决方案", "方案细节",
1142
1145
  "硬规则", "非目标", "影响范围", "落地文件", "验收标准", "回归风险",
1143
1146
  "与其他问题的关联", "发布门禁要求",
1144
1147
  ];
1145
- for (let batch = 1; batch <= 6; batch++) {
1148
+ for (let batch = 1; batch <= 8; batch++) {
1146
1149
  const details = loadBatchIssueDetails(batch, rootDir);
1147
1150
  if (!details.loaded) {
1148
1151
  hardFail("BATCH_ISSUE_FORMAT_INCONSISTENT", `Batch${batch} 问题集未加载: ${details.error}`, [`docs/SoloForge-Batch${batch}问题集.md`], `Batch${batch}`, "旧 gate 只检查文档存在,不验证是否可解析", "第 3 步统一格式");
@@ -1341,7 +1344,7 @@ async function checkKnowledgeAssetSchema(rootDir, hardFail, _info) {
1341
1344
  }
1342
1345
  }
1343
1346
  }
1344
- // ── Phase 11: engine console.log 检查 ──
1347
+ // ── Phase 11: engine console 直写检查 ──
1345
1348
  function checkEngineConsoleLog(rootDir, hardFail) {
1346
1349
  // 扫描全 src/ 目录(不仅 engine)
1347
1350
  const srcDir = path.join(rootDir, "src");
@@ -1359,12 +1362,13 @@ function checkEngineConsoleLog(rootDir, hardFail) {
1359
1362
  continue;
1360
1363
  if (/"console\.log"|`console\.log`|'console\.log'|console\\.log/.test(line))
1361
1364
  continue;
1362
- // 日志模块内部 stdout 封装允许 console.log
1363
- if (/logger\.ts$/.test(file) && /^\s*console\.log\(/.test(line))
1365
+ // 日志模块内部 stdout/stderr 封装允许 console.log / console.error
1366
+ if (/logger\.ts$/.test(file) && /^\s*console\.(log|error)\(/.test(line))
1364
1367
  continue;
1365
- if (/console\.log\s*\(/.test(line)) {
1368
+ const directConsole = line.match(/console\.(log|warn|error|debug)\s*\(/);
1369
+ if (directConsole) {
1366
1370
  const rel = path.relative(rootDir, file);
1367
- hardFail("ENGINE_CONSOLE_LOG", `${rel}:${i + 1} 使用 console.log(应使用 logger console.error 写 stderr)`, [rel], "发布门禁 console 检查", "旧 gate 不检查 src/ 全目录 console.log", "替换为 logger 模块调用");
1371
+ hardFail("ENGINE_DIRECT_CONSOLE", `${rel}:${i + 1} 使用 console.${directConsole[1]}(应使用 logger 模块)`, [rel], "发布门禁 console 检查", "旧 gate 不检查 src/ 全目录 console 直写", "替换为 logger 模块调用");
1368
1372
  }
1369
1373
  }
1370
1374
  }
@@ -1508,6 +1512,144 @@ function checkDependencyAudit(rootDir, hardFail, _info) {
1508
1512
  hardFail("DEPENDENCY_AUDIT", "漏洞扫描报告格式无效", ["package.json"], "依赖健康", "旧 gate 不验证报告格式", "删除 .soloforge/advisory-report.json 并重新运行 npm run audit-deps");
1509
1513
  }
1510
1514
  }
1515
+ // ── 16. 工作流导航契约行为验证(问题六十五) ──
1516
+ async function checkWorkflowNavigationBehavior(rootDir, hardFail, _info) {
1517
+ // 1. 编译产物存在性
1518
+ const navPath = path.join(rootDir, "dist", "engine", "next_action_planner.js");
1519
+ if (!fs.existsSync(navPath)) {
1520
+ hardFail("NAVIGATION_MODULE_MISSING", "problem-65: next_action_planner.js 未编译到 dist/", ["src/engine/next_action_planner.ts"], "problem-65", "发布门禁不检查问题-65 导航机制是否存在", "实现 next_action_planner 并编译");
1521
+ return;
1522
+ }
1523
+ // 2. 核心导出存在性
1524
+ let nav;
1525
+ try {
1526
+ nav = await import(navPath);
1527
+ }
1528
+ catch (e) {
1529
+ hardFail("NAVIGATION_IMPORT_ERROR", `problem-65: next_action_planner 导入失败: ${e.message}`, ["src/engine/next_action_planner.ts"], "problem-65", "导航模块存在但不可导入", "修复导入错误");
1530
+ return;
1531
+ }
1532
+ if (typeof nav.planNextAction !== "function") {
1533
+ hardFail("NAVIGATION_EXPORT_MISSING", "problem-65: next_action_planner 未导出 planNextAction 函数", ["src/engine/next_action_planner.ts"], "problem-65", "导航模块缺少核心导出", "添加 planNextAction 导出");
1534
+ }
1535
+ if (typeof nav.computeDisallowedActions !== "function") {
1536
+ hardFail("NAVIGATION_DISALLOWED_MISSING", "problem-65: next_action_planner 未导出 computeDisallowedActions 函数", ["src/engine/next_action_planner.ts"], "problem-65", "禁止动作规则计算函数缺失", "添加 computeDisallowedActions 导出");
1537
+ }
1538
+ // 3. 行为验证: 未初始化项目应返回 uninitialized
1539
+ const tmpDir = path.join(rootDir, ".soloforge-gate-nav-test-" + Date.now());
1540
+ try {
1541
+ fs.mkdirSync(tmpDir, { recursive: true });
1542
+ const plan = await nav.planNextAction(tmpDir);
1543
+ if (plan.project_stage !== "uninitialized") {
1544
+ hardFail("NAVIGATION_BEHAVIOR_UNINIT", `problem-65: 未初始化项目的阶段应为 uninitialized,实际为 ${plan.project_stage}`, ["src/engine/project_stage_detector.ts"], "problem-65", "导航未正确检测未初始化项目", "修复 detectProjectStage 逻辑");
1545
+ }
1546
+ if (!plan.work_package || plan.work_package.action !== "sf_init") {
1547
+ hardFail("NAVIGATION_BEHAVIOR_INIT_WP", `problem-65: 未初始化项目的工作包应为 sf_init,实际为 ${plan.work_package?.action ?? "null"}`, ["src/engine/next_action_planner.ts"], "problem-65", "导航工作包未正确推荐初始化", "修复 computeWorkPackage 逻辑");
1548
+ }
1549
+ }
1550
+ catch (e) {
1551
+ hardFail("NAVIGATION_BEHAVIOR_ERROR", `problem-65: 行为级检查执行失败: ${e.message}`, ["src/engine/next_action_planner.ts"], "problem-65", "导航机制行为检查不可执行", "修复导航机制代码");
1552
+ }
1553
+ finally {
1554
+ try {
1555
+ fs.rmSync(tmpDir, { recursive: true });
1556
+ }
1557
+ catch { }
1558
+ }
1559
+ // 4. 知识文件存在性
1560
+ const rulePath = path.join(rootDir, "templates", "knowledge", "rules", "工作流导航契约规则.md");
1561
+ if (!fs.existsSync(rulePath)) {
1562
+ hardFail("NAVIGATION_RULE_MISSING", "problem-65: 缺少知识规则文件 工作流导航契约规则.md", ["templates/knowledge/rules/工作流导航契约规则.md"], "problem-65", "导航知识规则缺失", "创建知识规则文件");
1563
+ }
1564
+ const procedurePath = path.join(rootDir, "templates", "knowledge", "procedures", "全生命周期工作流导航.md");
1565
+ if (!fs.existsSync(procedurePath)) {
1566
+ hardFail("NAVIGATION_PROCEDURE_MISSING", "problem-65: 缺少知识流程文件 全生命周期工作流导航.md", ["templates/knowledge/procedures/全生命周期工作流导航.md"], "problem-65", "导航知识流程缺失", "创建知识流程文件");
1567
+ }
1568
+ // 5. CLI 命令存在性
1569
+ const cliDist = fs.readFileSync(path.join(rootDir, "dist", "bin", "soloforge.js"), "utf-8");
1570
+ if (!cliDist.includes('case "next"') && !cliDist.includes("cmdNext")) {
1571
+ hardFail("NAVIGATION_CLI_MISSING", "problem-65: CLI 缺少 next 命令入口", ["src/bin/soloforge.ts"], "problem-65", "CLI 无 next 命令", "添加 case 'next' dispatch");
1572
+ }
1573
+ if (!cliDist.includes('case "stage"') && !cliDist.includes("cmdStage")) {
1574
+ hardFail("NAVIGATION_CLI_STAGE_MISSING", "problem-65: CLI 缺少 stage 命令入口", ["src/bin/soloforge.ts"], "problem-65", "CLI 无 stage 命令", "添加 case 'stage' dispatch");
1575
+ }
1576
+ _info(" problem-65 工作流导航行为验证完成");
1577
+ }
1578
+ // ── 17. 实现工程契约行为验证(问题六十六/六十七) ──
1579
+ async function checkImplementationContractBehavior(rootDir, hardFail, _info) {
1580
+ const oodPath = path.join(rootDir, "dist", "engine", "ood_solid_contract.js");
1581
+ const backendPath = path.join(rootDir, "dist", "engine", "backend_implementation_contract.js");
1582
+ if (!fs.existsSync(oodPath) || !fs.existsSync(backendPath)) {
1583
+ hardFail("IMPLEMENTATION_CONTRACT_MODULE_MISSING", "problem-66/67: OOD/SOLID 或后端工程契约未编译到 dist/", ["src/engine/ood_solid_contract.ts", "src/engine/backend_implementation_contract.ts"], "problem-66/problem-67", "仅登记问题而未验证运行时模块", "实现并编译两个工程契约模块");
1584
+ return;
1585
+ }
1586
+ try {
1587
+ const ood = await import(oodPath);
1588
+ const backend = await import(backendPath);
1589
+ const blockedOod = ood.evaluateOodDesignGate({
1590
+ task_id: "gate-ood",
1591
+ intent: "实现订单领域服务状态流转策略",
1592
+ route: "code_change",
1593
+ });
1594
+ if (blockedOod.allowed || blockedOod.status !== "blocked") {
1595
+ hardFail("OOD_SUMMARY_FALSE_PASS", "problem-66: 复杂业务编码缺少 OOD 摘要仍被放行", ["src/engine/ood_solid_contract.ts"], "problem-66", "文件存在不能证明编码前门禁有效", "修复 evaluateOodDesignGate 的缺摘要阻断");
1596
+ }
1597
+ const lowRisk = ood.evaluateOodDesignGate({
1598
+ task_id: "gate-ood-low",
1599
+ intent: "修复 README 文案错别字",
1600
+ route: "code_change",
1601
+ });
1602
+ if (!lowRisk.allowed || lowRisk.status !== "not_applicable") {
1603
+ hardFail("OOD_LOW_RISK_OVERBLOCK", "problem-66: 低风险文案任务被 OOD 门禁误阻断", ["src/engine/ood_solid_contract.ts"], "problem-66", "门禁不能以流程重量替代适用性判断", "修复低风险跳过判断");
1604
+ }
1605
+ const solidFindings = ood.reviewSolidCode({
1606
+ "src/OrderController.ts": "class OrderController { save(){ return this.repository.save(this.calculate()); } }",
1607
+ });
1608
+ if (!ood.hasBlockingSolidFindings(solidFindings)) {
1609
+ hardFail("SOLID_REVIEW_FALSE_PASS", "problem-66: Controller 职责膨胀没有产生阻断 finding", ["src/engine/ood_solid_contract.ts"], "problem-66", "必须用真实代码内容验证审查能力", "修复 SRP 阻断识别");
1610
+ }
1611
+ const blockedBackend = backend.evaluateBackendImplementationGate({
1612
+ task_id: "gate-backend",
1613
+ intent: "实现后端 API 支付接口",
1614
+ route: "code_change",
1615
+ });
1616
+ if (blockedBackend.allowed || blockedBackend.status !== "blocked") {
1617
+ hardFail("BACKEND_WORK_PACKAGE_FALSE_PASS", "problem-67: 后端实现缺少工程工作包仍被放行", ["src/engine/backend_implementation_contract.ts"], "problem-67", "文件存在不能证明编码前门禁有效", "修复 evaluateBackendImplementationGate");
1618
+ }
1619
+ const backendFindings = backend.reviewBackendImplementationFiles({
1620
+ "src/PaymentController.java": "@PostMapping(\"/pay\") @Transactional public PaymentEntity pay(@RequestBody PaymentEntity value) { webClient.post(); return value; }",
1621
+ });
1622
+ if (!backend.hasBlockingBackendFindings(backendFindings)) {
1623
+ hardFail("BACKEND_REVIEW_FALSE_PASS", "problem-67: 实体暴露或事务内外调没有产生阻断 finding", ["src/engine/backend_implementation_contract.ts"], "problem-67", "必须用真实代码内容验证后端审查能力", "修复后端工程 finding 检测");
1624
+ }
1625
+ if (backend.requiresBackendImplementationContract("实现简单 GET 详情只读接口", "code_change")) {
1626
+ hardFail("BACKEND_LOW_RISK_OVERBLOCK", "problem-67: 简单只读接口被完整后端工程工作包误阻断", ["src/engine/backend_implementation_contract.ts"], "problem-67", "后端契约必须具备适用性边界", "修复低风险只读任务跳过逻辑");
1627
+ }
1628
+ const alignmentFindings = backend.verifyBackendArtifactAlignment({
1629
+ apiDocumentText: "GET /api/payments/{id}",
1630
+ openapiText: "paths:\n /api/orders/{id}:",
1631
+ migrationText: "create table payment(id bigint);",
1632
+ });
1633
+ if (!backend.hasBlockingBackendFindings(alignmentFindings)) {
1634
+ hardFail("BACKEND_API_OPENAPI_DRIFT_FALSE_PASS", "problem-67: Markdown API 与 OpenAPI endpoint 漂移未阻断", ["src/engine/backend_implementation_contract.ts"], "problem-67", "契约对齐必须由行为检查证明", "修复 API/OpenAPI 漂移检测");
1635
+ }
1636
+ }
1637
+ catch (e) {
1638
+ hardFail("IMPLEMENTATION_CONTRACT_EXECUTION_ERROR", `problem-66/67: 实现工程行为检查执行失败: ${e.message}`, ["src/engine/ood_solid_contract.ts", "src/engine/backend_implementation_contract.ts"], "problem-66/problem-67", "契约模块必须可运行并返回确定结果", "修复运行时异常");
1639
+ }
1640
+ const toolsText = safeRead(path.join(rootDir, "src", "adapters", "claude_code", "tools.ts")) ?? "";
1641
+ const requiredHooks = [
1642
+ "lazyOodSolid", "lazyBackendImplementation", "evaluateOodDesignGate",
1643
+ "evaluateBackendImplementationGate", "reviewSolidCode",
1644
+ "reviewBackendImplementationFiles", "hasBlockingSolidFindings", "hasBlockingBackendFindings",
1645
+ ];
1646
+ for (const hook of requiredHooks) {
1647
+ if (!toolsText.includes(hook)) {
1648
+ hardFail("IMPLEMENTATION_CONTRACT_MAINPATH_MISSING", `problem-66/67: MCP 主链路缺少真实消费点 ${hook}`, ["src/adapters/claude_code/tools.ts"], "problem-66/problem-67", "只实现引擎函数不能证明用户路径受约束", "接入 sf_expand/sf_review/sf_verify/sf_deliver");
1649
+ }
1650
+ }
1651
+ _info(" problem-66/67 实现工程契约行为验证完成");
1652
+ }
1511
1653
  // ── 15. 发布问题全局合同 ──
1512
1654
  async function checkReleaseIssueDesignPath(rootDir, hardFail, _info) {
1513
1655
  const toolsText = safeRead(path.join(rootDir, "src", "adapters", "claude_code", "tools.ts")) ?? "";
@@ -1555,6 +1697,7 @@ async function checkReleaseIssueDesignPath(rootDir, hardFail, _info) {
1555
1697
  "problem-62": ["release-scenario-design-pack-"],
1556
1698
  "problem-63": ["release-scenario-template-contract-"],
1557
1699
  "problem-64": ["release-scenario-template-visibility-"],
1700
+ "problem-68": ["release-scenario-code-observability-"],
1558
1701
  };
1559
1702
  for (const [problem, prefixes] of Object.entries(problemPrefixes)) {
1560
1703
  const problemScenarios = execResults.filter(r => prefixes.some(p => r.scenario_id.startsWith(p)));
@@ -1850,7 +1993,7 @@ async function checkReleaseIssueDesignPath(rootDir, hardFail, _info) {
1850
1993
  hardFail("RELEASE_ISSUE_CONTRACT_MISSING", "问题六十三缺少模板契约匹配、产物验证或修复重验函数", ["src/engine/standard_asset_contract.ts"], "problem-63", "缺少核心函数不能实现契约验证", "实现 matchTemplateContract / verifyOutputAgainstContract / createRepairReverifyDirective");
1851
1994
  }
1852
1995
  // sf_verify 必须按文件逐一匹配契约(不得使用 changed_files[0] 的契约校验全部文件)
1853
- if (!toolsText.includes("lazyStandardAssetContract") || !toolsText.includes("SF-CONTRACT-0003") || !toolsText.includes("repair_reverify_directive")) {
1996
+ if (!toolsText.includes("lazyStandardAssetContract") || !toolsText.includes("TOOL_DIAGNOSTIC_CODES.contractDraft") || !toolsText.includes("repair_reverify_directive")) {
1854
1997
  hardFail("RELEASE_ISSUE_CONTRACT_MAINLINE_MISSING", "问题六十三未接入 sf_verify 模板契约验证和 sf_deliver 修复重验阻断", ["src/adapters/claude_code/tools.ts"], "problem-63", "仅有契约定义不能阻断交付", "在 sf_verify 消费模板契约验证、sf_deliver 消费修复重验阻断");
1855
1998
  }
1856
1999
  // 必须检查 per-file 匹配(不得 changed_files[0] 统一匹配)
@@ -2079,6 +2222,241 @@ async function checkReleaseIssueDesignPath(rootDir, hardFail, _info) {
2079
2222
  }
2080
2223
  }
2081
2224
  }
2225
+ // ── 18. 代码可维护性与可观测性契约行为验证(问题六十八) ──
2226
+ async function checkCodeObservabilityBehavior(rootDir, hardFail, _info) {
2227
+ const obsPath = path.join(rootDir, "dist", "engine", "code_maintainability_observability_contract.js");
2228
+ if (!fs.existsSync(obsPath)) {
2229
+ hardFail("CODE_OBSERVABILITY_MODULE_MISSING", "problem-68: code_maintainability_observability_contract.js 未编译到 dist/", ["src/engine/code_maintainability_observability_contract.ts"], "problem-68", "发布门禁不检查问题-68 实现是否存在", "实现 code_maintainability_observability_contract 并编译");
2230
+ return;
2231
+ }
2232
+ let obs;
2233
+ try {
2234
+ obs = await import(obsPath);
2235
+ }
2236
+ catch (e) {
2237
+ hardFail("CODE_OBSERVABILITY_IMPORT_ERROR", `problem-68: code_maintainability_observability_contract 导入失败: ${e.message}`, ["src/engine/code_maintainability_observability_contract.ts"], "problem-68", "可观测性模块存在但不可导入", "修复导入错误");
2238
+ return;
2239
+ }
2240
+ // 核心导出存在性
2241
+ const requiredExports = ["reviewMissingLogs", "detectSensitiveLogs", "reviewCommentQuality", "hasBlockingObservabilityFindings", "requiresCodeObservabilityContract", "isLowRiskChange", "detectProjectLogger", "verifyChangedFilesObservability", "evaluateDeliveryBlock"];
2242
+ for (const exp of requiredExports) {
2243
+ if (typeof obs[exp] !== "function") {
2244
+ hardFail("CODE_OBSERVABILITY_EXPORT_MISSING", `problem-68: code_maintainability_observability_contract.ts 缺少导出函数: ${exp}`, ["src/engine/code_maintainability_observability_contract.ts"], "problem-68", "可观测性模块缺少核心导出", `添加 ${exp} 导出`);
2245
+ }
2246
+ }
2247
+ // 行为验证: 支付写操作无日志必须被检测
2248
+ try {
2249
+ const paymentFindings = obs.reviewMissingLogs({
2250
+ "PaymentService.java": `public void refund(String orderId, BigDecimal amount) {
2251
+ orderRepository.save(order);
2252
+ paymentGateway.refund(orderId, amount);
2253
+ }`,
2254
+ });
2255
+ if (!obs.hasBlockingObservabilityFindings(paymentFindings)) {
2256
+ hardFail("CODE_OBSERVABILITY_PAYMENT_FALSE_PASS", "problem-68: 支付写操作无日志未被检测到", ["src/engine/code_maintainability_observability_contract.ts"], "problem-68", "文件存在不能证明审查能力有效", "修复 reviewMissingLogs 检测逻辑");
2257
+ }
2258
+ // 行为验证: catch 吞异常无日志必须被检测
2259
+ const catchFindings = obs.reviewMissingLogs({
2260
+ "OrderService.ts": `async processOrder(orderId: string) {
2261
+ try {
2262
+ await this.client.submit(orderId);
2263
+ } catch (e) {
2264
+ return false;
2265
+ }
2266
+ }`,
2267
+ });
2268
+ if (!obs.hasBlockingObservabilityFindings(catchFindings)) {
2269
+ hardFail("CODE_OBSERVABILITY_CATCH_FALSE_PASS", "problem-68: catch 吞异常无日志未被检测到", ["src/engine/code_maintainability_observability_contract.ts"], "problem-68", "catch 吞异常必须产生阻断 finding", "修复 reviewMissingLogs 检测逻辑");
2270
+ }
2271
+ // 行为验证: 敏感信息日志泄漏必须被检测
2272
+ const sensitiveFindings = obs.detectSensitiveLogs({
2273
+ "UserService.ts": `function login(user) {
2274
+ logger.info("user login", { token: "eyJhbGciOiJIUzI1NiJ9.xxxxx", password: user.password, phone: "13812345678" });
2275
+ }`,
2276
+ });
2277
+ if (!obs.hasBlockingObservabilityFindings(sensitiveFindings)) {
2278
+ hardFail("CODE_OBSERVABILITY_SENSITIVE_FALSE_PASS", "problem-68: 敏感信息日志泄漏未被检测到", ["src/engine/code_maintainability_observability_contract.ts"], "problem-68", "token/password/手机号泄漏必须被阻断", "修复 detectSensitiveLogs 检测逻辑");
2279
+ }
2280
+ // 行为验证: 低风险任务不应触发
2281
+ const notTriggered = !obs.requiresCodeObservabilityContract("修复 README 错别字", "code_change");
2282
+ if (!notTriggered) {
2283
+ hardFail("CODE_OBSERVABILITY_LOW_RISK_OVERBLOCK", "problem-68: 低风险文案任务错误触发可观测性检查", ["src/engine/code_maintainability_observability_contract.ts"], "problem-68", "低风险任务不应触发检查", "修复 requiresCodeObservabilityContract 判断逻辑");
2284
+ }
2285
+ // 行为验证: 项目 logger 类型检测
2286
+ const javaLogger = obs.detectProjectLogger({
2287
+ "Application.java": "import org.slf4j.LoggerFactory; private static final Logger log = LoggerFactory.getLogger(App.class);",
2288
+ });
2289
+ if (javaLogger.type !== "slf4j") {
2290
+ hardFail("CODE_OBSERVABILITY_LOGGER_DETECT_FAIL", `problem-68: SLF4J logger 未被正确识别 (got: ${javaLogger.type})`, ["src/engine/code_maintainability_observability_contract.ts"], "problem-68", "项目 logger 类型检测必须准确", "修复 detectProjectLogger 逻辑");
2291
+ }
2292
+ // 行为验证: 迁移脚本无审计日志必须被检测
2293
+ const migrationFindings = obs.reviewMissingLogs({
2294
+ "scripts/data_fix_order_status.ts": `async function migrateOrderStatus() {
2295
+ const orders = await db.query("SELECT * FROM orders WHERE status IS NULL");
2296
+ for (const order of orders) {
2297
+ await db.update("UPDATE orders SET status = 'pending' WHERE id = ?", [order.id]);
2298
+ }
2299
+ }`,
2300
+ });
2301
+ if (!obs.hasBlockingObservabilityFindings(migrationFindings)) {
2302
+ hardFail("CODE_OBSERVABILITY_MIGRATION_FALSE_PASS", "problem-68: 迁移脚本无审计日志未被检测到", ["src/engine/code_maintainability_observability_contract.ts"], "problem-68", "数据修复脚本必须有审计日志", "修复 reviewMissingLogs 迁移脚本检测逻辑");
2303
+ }
2304
+ }
2305
+ catch (e) {
2306
+ hardFail("CODE_OBSERVABILITY_EXECUTION_ERROR", `problem-68: 可观测性行为检查执行失败: ${e.message}`, ["src/engine/code_maintainability_observability_contract.ts"], "problem-68", "契约模块必须可运行并返回确定结果", "修复运行时异常");
2307
+ }
2308
+ // 主链路消费检查 — sf_verify 必须调用 verifyChangedFilesObservability
2309
+ const toolsText = safeRead(path.join(rootDir, "src", "adapters", "claude_code", "tools.ts")) ?? "";
2310
+ const requiredHooks = [
2311
+ "lazyCodeObservability", "reviewCodeObservability",
2312
+ "hasBlockingObservabilityFindings", "requiresCodeObservabilityContract",
2313
+ "evaluateCodeObservabilityGate", "evaluateDeliveryBlock",
2314
+ "verifyChangedFilesObservability",
2315
+ ];
2316
+ for (const hook of requiredHooks) {
2317
+ if (!toolsText.includes(hook)) {
2318
+ hardFail("CODE_OBSERVABILITY_MAINPATH_MISSING", `problem-68: MCP 主链路缺少真实消费点 ${hook}`, ["src/adapters/claude_code/tools.ts"], "problem-68", "只实现引擎函数不能证明用户路径受约束", "接入 sf_expand/sf_review/sf_verify/sf_deliver");
2319
+ }
2320
+ }
2321
+ // 行为验证: sf_verify 必须真实消费 verifyChangedFilesObservability — 编译后检查
2322
+ try {
2323
+ const toolsJsPath = path.join(rootDir, "dist", "adapters", "claude_code", "tools.js");
2324
+ if (fs.existsSync(toolsJsPath)) {
2325
+ const toolsJs = safeRead(toolsJsPath) ?? "";
2326
+ const hasObsVerifyCall = toolsJs.includes("codeObservabilityFinding")
2327
+ && toolsJs.includes("verifyChangedFilesObservability");
2328
+ if (!hasObsVerifyCall) {
2329
+ hardFail("CODE_OBSERVABILITY_SF_VERIFY_NOT_CONSUMING", "problem-68: sf_verify 编译产物未包含可观测性诊断常量或 verifyChangedFilesObservability 调用", ["src/adapters/claude_code/tools.ts"], "problem-68", "字符串引用不能证明 sf_verify 真实消费可观测性检查", "在 sf_verify implementationFiles 分支中调用 verifyChangedFilesObservability 并处理结果");
2330
+ }
2331
+ }
2332
+ }
2333
+ catch {
2334
+ // 编译产物不存在时由 build 门禁处理
2335
+ }
2336
+ // 行为验证: sf_verify 必须能阻断 — 敏感信息 + 支付写操作必须产生 hard_fail
2337
+ try {
2338
+ const mustFailFindings = obs.verifyChangedFilesObservability({
2339
+ changed_files: ["PaymentService.ts"],
2340
+ file_contents: {
2341
+ "PaymentService.ts": `const api_key = "sk_live_abcdef123456";
2342
+ async function processPayment(order) { order.save(); }`,
2343
+ },
2344
+ intent: "添加支付退款日志和脱敏处理",
2345
+ });
2346
+ if (!obs.hasBlockingObservabilityFindings(mustFailFindings)) {
2347
+ hardFail("CODE_OBSERVABILITY_VERIFY_MUST_FAIL_PASS", "problem-68: sf_verify 未对敏感信息泄漏+支付无日志场景产生阻断", ["src/engine/code_maintainability_observability_contract.ts"], "problem-68", "verifyChangedFilesObservability 必须对支付敏感信息场景 hard_fail", "修复 verifyChangedFilesObservability 检测逻辑");
2348
+ }
2349
+ // sf_verify 必须允许合规代码通过
2350
+ const mustPassFindings = obs.verifyChangedFilesObservability({
2351
+ changed_files: ["RefundService.ts"],
2352
+ file_contents: {
2353
+ "RefundService.ts": `const logger = require('./logger');
2354
+ async function processRefund(orderId: string) {
2355
+ await db.refund(orderId);
2356
+ logger.info("退款成功 orderId=" + orderId);
2357
+ }`,
2358
+ },
2359
+ intent: "添加支付退款日志和脱敏处理",
2360
+ });
2361
+ if (obs.hasBlockingObservabilityFindings(mustPassFindings)) {
2362
+ hardFail("CODE_OBSERVABILITY_VERIFY_FALSE_BLOCK", "problem-68: sf_verify 对合规代码错误阻断", ["src/engine/code_maintainability_observability_contract.ts"], "problem-68", "合规代码不应被阻断", "修复 verifyChangedFilesObservability 检测逻辑");
2363
+ }
2364
+ // 行为验证: logger.info("退款成功") 无可定位字段必须 hard_fail
2365
+ const unlocatableFailFindings = obs.verifyChangedFilesObservability({
2366
+ changed_files: ["RefundService.ts"],
2367
+ file_contents: {
2368
+ "RefundService.ts": `const logger = require('./logger');
2369
+ async function refund(order) { order.save(); logger.info("退款成功"); }`,
2370
+ },
2371
+ intent: "添加支付退款日志和脱敏处理",
2372
+ });
2373
+ const unlocatableHardFails = unlocatableFailFindings.filter((f) => f.category === "unlocatable_log" && f.severity === "hard_fail");
2374
+ if (unlocatableHardFails.length === 0) {
2375
+ hardFail("CODE_OBSERVABILITY_UNLOCATABLE_LOG_PASS", "problem-68: logger.info('退款成功') 无可定位字段未被阻断", ["src/engine/code_maintainability_observability_contract.ts"], "problem-68", "仅含事件词的日志不可通过支付写操作检查", "修复可定位字段判断逻辑");
2376
+ }
2377
+ // 行为验证: logger.info("退款成功 orderId=" + orderId) 必须通过
2378
+ const unlocatablePassFindings = obs.verifyChangedFilesObservability({
2379
+ changed_files: ["RefundService.ts"],
2380
+ file_contents: {
2381
+ "RefundService.ts": `const logger = require('./logger');
2382
+ async function refund(order) { order.save(); logger.info("退款成功 orderId=" + orderId); }`,
2383
+ },
2384
+ intent: "添加支付退款日志和脱敏处理",
2385
+ });
2386
+ const unlocatableBlockers = unlocatablePassFindings.filter((f) => f.category === "unlocatable_log" && f.severity === "hard_fail");
2387
+ if (unlocatableBlockers.length > 0) {
2388
+ hardFail("CODE_OBSERVABILITY_LOCATABLE_FALSE_BLOCK", "problem-68: logger.info('退款成功 orderId=...') 含可定位字段被错误阻断", ["src/engine/code_maintainability_observability_contract.ts"], "problem-68", "包含对象 ID 的日志不应被阻断", "修复可定位字段判断逻辑");
2389
+ }
2390
+ }
2391
+ catch (e) {
2392
+ hardFail("CODE_OBSERVABILITY_VERIFY_EXECUTION_ERROR", `problem-68: sf_verify 行为检查执行失败: ${e.message}`, ["src/engine/code_maintainability_observability_contract.ts"], "problem-68", "verifyChangedFilesObservability 必须可运行并返回确定结果", "修复运行时异常");
2393
+ }
2394
+ _info(" problem-68 代码可维护性与可观测性行为验证完成");
2395
+ }
2396
+ async function checkLongTermMechanization(rootDir, hardFail, _info) {
2397
+ try {
2398
+ const health = await import("./mechanism_health_check.js");
2399
+ const report = health.runFullHealthCheck(rootDir);
2400
+ for (const finding of report.findings.filter((f) => f.severity === "hard_fail")) {
2401
+ hardFail("LONGTERM_MECHANISM_HEALTH", finding.message_zh, [finding.target], "历史问题长期机制化", "旧 gate 不检查机制死代码/未消费资产", "修复机制消费链路");
2402
+ }
2403
+ }
2404
+ catch (e) {
2405
+ hardFail("LONGTERM_MECHANISM_HEALTH_EXCEPTION", `机制运行时健康度检查异常: ${e.message}`, ["src/engine/mechanism_health_check.ts"], "历史问题长期机制化", "旧 gate 不执行机制健康检查", "修复检查模块");
2406
+ }
2407
+ try {
2408
+ const kg = await import("./knowledge_governance_gate.js");
2409
+ const report = kg.runKnowledgeGovernanceCheck({
2410
+ project_language: "zh",
2411
+ contents: [{ id: "release-gate", domain: "user_feedback", content: "发布门禁保持中文语义优先" }],
2412
+ });
2413
+ if (report.hard_fail_count > 0) {
2414
+ hardFail("LONGTERM_KNOWLEDGE_GOVERNANCE", `知识治理存在 ${report.hard_fail_count} 个 hard_fail`, ["src/engine/knowledge_governance_gate.ts"], "历史问题长期机制化", "旧 gate 只跑历史知识场景,不接统一治理入口", "修复知识治理检查");
2415
+ }
2416
+ }
2417
+ catch (e) {
2418
+ hardFail("LONGTERM_KNOWLEDGE_GOVERNANCE_EXCEPTION", `知识治理检查异常: ${e.message}`, ["src/engine/knowledge_governance_gate.ts"], "历史问题长期机制化", "旧 gate 不执行知识治理入口", "修复检查模块");
2419
+ }
2420
+ try {
2421
+ const logGov = await import("./log_governance.js");
2422
+ const clean = logGov.enforceLogGovernance("用户可见输出保持中文且无内部噪音");
2423
+ const noisy = logGov.enforceLogGovernance("[soloForge] internal trace validate-release");
2424
+ if (!clean.passed || noisy.passed) {
2425
+ hardFail("LONGTERM_LOG_GOVERNANCE_BEHAVIOR", "日志治理 must-pass/must-fail 行为不成立", ["src/engine/log_governance.ts"], "历史问题长期机制化", "旧 gate 只扫描 console,不验证输出治理行为", "修复 log_governance 行为");
2426
+ }
2427
+ }
2428
+ catch (e) {
2429
+ hardFail("LONGTERM_LOG_GOVERNANCE_EXCEPTION", `日志治理检查异常: ${e.message}`, ["src/engine/log_governance.ts"], "历史问题长期机制化", "旧 gate 不执行日志治理入口", "修复检查模块");
2430
+ }
2431
+ try {
2432
+ const cfg = await import("./config_write_boundary.js");
2433
+ const runtimeCtx = cfg.classifyConfigContext(rootDir, { runtime_inference: true });
2434
+ const runtimeDecision = cfg.isWriteAllowed(runtimeCtx, path.join(rootDir, ".soloforge", "config.yaml"));
2435
+ const greenfieldDecision = cfg.isWriteAllowed({ kind: "greenfield", project_path: rootDir, evidence: ["empty_project"], confirmed: false }, path.join(rootDir, ".soloforge", "config.yaml"));
2436
+ if (runtimeDecision.allowed || !greenfieldDecision.allowed) {
2437
+ hardFail("LONGTERM_CONFIG_BOUNDARY_BEHAVIOR", "配置落盘边界 must-pass/must-fail 行为不成立", ["src/engine/config_write_boundary.ts"], "历史问题长期机制化", "旧 gate 不区分运行时推断与空项目写入", "修复配置写入边界");
2438
+ }
2439
+ }
2440
+ catch (e) {
2441
+ hardFail("LONGTERM_CONFIG_BOUNDARY_EXCEPTION", `配置落盘边界检查异常: ${e.message}`, ["src/engine/config_write_boundary.ts"], "历史问题长期机制化", "旧 gate 不执行配置落盘边界", "修复检查模块");
2442
+ }
2443
+ _info(" 历史问题长期机制化行为验证完成");
2444
+ }
2445
+ async function checkDiagnosticCentralization(rootDir, hardFail) {
2446
+ const toolsPath = path.join(rootDir, "src", "adapters", "claude_code", "tools.ts");
2447
+ const toolsText = safeRead(toolsPath) ?? "";
2448
+ const literalMatches = [...toolsText.matchAll(/["'`]SF-[A-Z]+-\d{4}["'`]/g)];
2449
+ if (literalMatches.length > 0) {
2450
+ hardFail("DIAGNOSTIC_CODE_HARDCODED_IN_TOOLS", `tools.ts 仍有 ${literalMatches.length} 个硬编码诊断码字面量`, ["src/adapters/claude_code/tools.ts"], "problem-36", "旧 gate 不检查诊断码集中治理", "改用 diagnostic_registry 导出的 TOOL_DIAGNOSTIC_CODES");
2451
+ }
2452
+ const registry = await import("./diagnostic_registry.js");
2453
+ const required = Object.values(registry.TOOL_DIAGNOSTIC_CODES);
2454
+ const registered = new Set(registry.listAllDiagnostics().map((d) => d.code));
2455
+ const missing = required.filter((code) => !registered.has(code));
2456
+ if (missing.length > 0) {
2457
+ hardFail("DIAGNOSTIC_CODE_REGISTRY_MISSING", `诊断码常量未在注册表登记: ${missing.join(", ")}`, ["src/engine/diagnostic_registry.ts"], "problem-36", "旧 gate 不检查诊断码注册完整性", "补齐 BUILTIN_DIAGNOSTICS");
2458
+ }
2459
+ }
2082
2460
  // ── 主入口 ──
2083
2461
  export async function runReleaseReadinessGate(rootDir) {
2084
2462
  const hardFails = [];
@@ -2165,10 +2543,30 @@ export async function runReleaseReadinessGate(rootDir) {
2165
2543
  beginPhase("依赖漏洞扫描");
2166
2544
  checkDependencyAudit(rootDir, hardFail, _info);
2167
2545
  endPhase("依赖漏洞扫描");
2168
- // 15: 发布问题全局合同(问题六十一至六十四)
2546
+ // 15: 发布问题全局合同(问题六十一至六十五)
2169
2547
  beginPhase("发布问题全局合同");
2170
2548
  await checkReleaseIssueDesignPath(rootDir, hardFail, _info);
2171
2549
  endPhase("发布问题全局合同");
2550
+ // 16: 工作流导航契约行为验证(问题六十五)
2551
+ beginPhase("工作流导航契约行为验证");
2552
+ await checkWorkflowNavigationBehavior(rootDir, hardFail, _info);
2553
+ endPhase("工作流导航契约行为验证");
2554
+ // 17: OOD/SOLID 与后端实现工程契约行为验证(问题六十六/六十七)
2555
+ beginPhase("实现工程契约行为验证");
2556
+ await checkImplementationContractBehavior(rootDir, hardFail, _info);
2557
+ endPhase("实现工程契约行为验证");
2558
+ // 18: 代码可维护性与可观测性契约行为验证(问题六十八)
2559
+ beginPhase("代码可维护性与可观测性行为验证");
2560
+ await checkCodeObservabilityBehavior(rootDir, hardFail, _info);
2561
+ endPhase("代码可维护性与可观测性行为验证");
2562
+ // 19: 历史问题长期机制化行为验证
2563
+ beginPhase("历史问题长期机制化行为验证");
2564
+ await checkLongTermMechanization(rootDir, hardFail, _info);
2565
+ endPhase("历史问题长期机制化行为验证");
2566
+ // 20: 诊断码集中治理检查
2567
+ beginPhase("诊断码集中治理检查");
2568
+ await checkDiagnosticCentralization(rootDir, hardFail);
2569
+ endPhase("诊断码集中治理检查");
2172
2570
  // 恢复 console.error 和日志器
2173
2571
  console.error = origConsoleError;
2174
2572
  resetLogger();