soloforge 1.4.4 → 1.4.6

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 (96) hide show
  1. package/README.md +6 -5
  2. package/dist/adapters/claude_code/tools.d.ts.map +1 -1
  3. package/dist/adapters/claude_code/tools.js +50 -12
  4. package/dist/adapters/claude_code/tools.js.map +1 -1
  5. package/dist/adapters/shared/workflow_template.js +1 -1
  6. package/dist/bin/soloforge.d.ts.map +1 -1
  7. package/dist/bin/soloforge.js +73 -16
  8. package/dist/bin/soloforge.js.map +1 -1
  9. package/dist/engine/backend_implementation_contract.js +1 -1
  10. package/dist/engine/code_maintainability_observability_contract.js +7 -7
  11. package/dist/engine/code_maintainability_observability_contract.js.map +1 -1
  12. package/dist/engine/consumption_trace_store.d.ts +9 -1
  13. package/dist/engine/consumption_trace_store.d.ts.map +1 -1
  14. package/dist/engine/consumption_trace_store.js +3 -0
  15. package/dist/engine/consumption_trace_store.js.map +1 -1
  16. package/dist/engine/design_artifact_pack.d.ts +2 -0
  17. package/dist/engine/design_artifact_pack.d.ts.map +1 -1
  18. package/dist/engine/design_artifact_pack.js +30 -17
  19. package/dist/engine/design_artifact_pack.js.map +1 -1
  20. package/dist/engine/design_lifecycle_contract.d.ts +60 -0
  21. package/dist/engine/design_lifecycle_contract.d.ts.map +1 -0
  22. package/dist/engine/design_lifecycle_contract.js +499 -0
  23. package/dist/engine/design_lifecycle_contract.js.map +1 -0
  24. package/dist/engine/diagnostic_registry.js +2 -2
  25. package/dist/engine/diagnostic_registry.js.map +1 -1
  26. package/dist/engine/foundation_scenario_registry.js +2 -2
  27. package/dist/engine/foundation_scenario_registry.js.map +1 -1
  28. package/dist/engine/foundation_scenario_runners.js +9 -9
  29. package/dist/engine/foundation_scenario_runners.js.map +1 -1
  30. package/dist/engine/historical_issue_mechanization_matrix.js +1 -1
  31. package/dist/engine/historical_issue_mechanization_matrix.js.map +1 -1
  32. package/dist/engine/implementation_roadmap_registry.js +2 -2
  33. package/dist/engine/implementation_roadmap_registry.js.map +1 -1
  34. package/dist/engine/input_material_extractor.js +1 -1
  35. package/dist/engine/input_material_extractor.js.map +1 -1
  36. package/dist/engine/intent_expander.d.ts.map +1 -1
  37. package/dist/engine/intent_expander.js +38 -15
  38. package/dist/engine/intent_expander.js.map +1 -1
  39. package/dist/engine/knowledge_asset_consumer.d.ts.map +1 -1
  40. package/dist/engine/knowledge_asset_consumer.js +21 -13
  41. package/dist/engine/knowledge_asset_consumer.js.map +1 -1
  42. package/dist/engine/knowledge_injection_boundary.d.ts +2 -2
  43. package/dist/engine/knowledge_injection_boundary.d.ts.map +1 -1
  44. package/dist/engine/knowledge_injection_boundary.js +19 -7
  45. package/dist/engine/knowledge_injection_boundary.js.map +1 -1
  46. package/dist/engine/lifecycle_knowledge_contract.d.ts +59 -0
  47. package/dist/engine/lifecycle_knowledge_contract.d.ts.map +1 -0
  48. package/dist/engine/lifecycle_knowledge_contract.js +203 -0
  49. package/dist/engine/lifecycle_knowledge_contract.js.map +1 -0
  50. package/dist/engine/next_action_planner.d.ts.map +1 -1
  51. package/dist/engine/next_action_planner.js +142 -37
  52. package/dist/engine/next_action_planner.js.map +1 -1
  53. package/dist/engine/observed_consumption.d.ts.map +1 -1
  54. package/dist/engine/observed_consumption.js +2 -1
  55. package/dist/engine/observed_consumption.js.map +1 -1
  56. package/dist/engine/project_knowledge_contract.d.ts +75 -1
  57. package/dist/engine/project_knowledge_contract.d.ts.map +1 -1
  58. package/dist/engine/project_knowledge_contract.js +289 -33
  59. package/dist/engine/project_knowledge_contract.js.map +1 -1
  60. package/dist/engine/regression_matrix.js +1 -1
  61. package/dist/engine/regression_matrix.js.map +1 -1
  62. package/dist/engine/release_issue_scenario_registry.d.ts.map +1 -1
  63. package/dist/engine/release_issue_scenario_registry.js +15 -12
  64. package/dist/engine/release_issue_scenario_registry.js.map +1 -1
  65. package/dist/engine/release_readiness_gate.d.ts.map +1 -1
  66. package/dist/engine/release_readiness_gate.js +183 -54
  67. package/dist/engine/release_readiness_gate.js.map +1 -1
  68. package/dist/engine/stale_current_task_detector.d.ts +1 -1
  69. package/dist/engine/stale_current_task_detector.js +4 -4
  70. package/dist/engine/stale_current_task_detector.js.map +1 -1
  71. package/dist/engine/task_context.d.ts.map +1 -1
  72. package/dist/engine/task_context.js +2 -0
  73. package/dist/engine/task_context.js.map +1 -1
  74. package/dist/engine/traceability.d.ts +2 -2
  75. package/dist/engine/traceability.d.ts.map +1 -1
  76. package/dist/engine/traceability.js +86 -16
  77. package/dist/engine/traceability.js.map +1 -1
  78. package/dist/engine/workflow_navigation_contract.d.ts +11 -0
  79. package/dist/engine/workflow_navigation_contract.d.ts.map +1 -1
  80. package/dist/engine/workspace_resumer.d.ts.map +1 -1
  81. package/dist/engine/workspace_resumer.js +2 -1
  82. package/dist/engine/workspace_resumer.js.map +1 -1
  83. package/dist/knowledge/conflict_detector.d.ts +1 -1
  84. package/dist/knowledge/conflict_detector.d.ts.map +1 -1
  85. package/dist/knowledge/conflict_detector.js +88 -2
  86. package/dist/knowledge/conflict_detector.js.map +1 -1
  87. package/dist/types.d.ts +14 -0
  88. package/dist/types.d.ts.map +1 -1
  89. package/package.json +1 -1
  90. 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 +1 -1
  91. package/templates/knowledge/acceptance_templates//345/216/237/345/236/213/350/257/264/346/230/216/346/250/241/347/211/210.md +6 -6
  92. package/templates/knowledge/acceptance_templates//351/234/200/346/261/202/345/216/237/345/236/213/350/256/276/350/256/241/345/256/236/347/216/260/350/277/275/350/270/252/347/237/251/351/230/265/346/250/241/347/211/210.md +25 -20
  93. package/templates/knowledge/procedures//346/272/220/347/240/201/345/216/237/345/236/213/344/272/244/344/273/230/346/265/201/347/250/213.md +8 -5
  94. package/templates/knowledge/procedures//350/257/246/347/273/206/350/256/276/350/256/241/346/265/201/347/250/213.md +19 -6
  95. 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 +4 -4
  96. package/templates/knowledge/rules//350/256/276/350/256/241/344/272/247/347/211/251/345/214/205/350/247/204/345/210/231.md +16 -0
@@ -1625,7 +1625,7 @@ async function checkWorkflowNavigationBehavior(rootDir, hardFail, _info) {
1625
1625
  fs.mkdirSync(sfDir, { recursive: true });
1626
1626
  fs.writeFileSync(path.join(sfDir, "config.yaml"), [
1627
1627
  "schema_version: 1",
1628
- "name: smartcare",
1628
+ "name: demo-saas",
1629
1629
  "tech_stack:",
1630
1630
  " backend:",
1631
1631
  " lang: java",
@@ -1647,8 +1647,8 @@ async function checkWorkflowNavigationBehavior(rootDir, hardFail, _info) {
1647
1647
  " test: npm test",
1648
1648
  " full: npm run build && npm test",
1649
1649
  "scope:",
1650
- " backend: smartcare-saas-backend",
1651
- " frontend: smartcare-saas-frontend",
1650
+ " backend: demo-saas-backend",
1651
+ " frontend: demo-saas-frontend",
1652
1652
  ].join("\n"), "utf-8");
1653
1653
  fs.writeFileSync(path.join(sfDir, "config.evidence.json"), JSON.stringify({
1654
1654
  schema_version: 2,
@@ -1763,8 +1763,8 @@ async function checkImplementationContractBehavior(rootDir, hardFail, _info) {
1763
1763
  hardFail("BACKEND_API_OPENAPI_DRIFT_FALSE_PASS", "problem-67: Markdown API 与 OpenAPI endpoint 漂移未阻断", ["src/engine/backend_implementation_contract.ts"], "problem-67", "契约对齐必须由行为检查证明", "修复 API/OpenAPI 漂移检测");
1764
1764
  }
1765
1765
  const lombokFindings = backend.reviewBackendImplementationFiles({
1766
- "src/main/java/com/smartcare/staff/entity/Staff.java": "import jakarta.persistence.Entity; import lombok.Data; @Entity @Data public class Staff { private Long id; }",
1767
- "src/main/java/com/smartcare/staff/dto/StaffCreateRequest.java": "import lombok.Getter; import lombok.Setter; @Getter @Setter public class StaffCreateRequest { private String name; }",
1766
+ "src/main/java/com/demoapp/account/entity/Account.java": "import jakarta.persistence.Entity; import lombok.Data; @Entity @Data public class Account { private Long id; }",
1767
+ "src/main/java/com/demoapp/account/dto/AccountCreateRequest.java": "import lombok.Getter; import lombok.Setter; @Getter @Setter public class AccountCreateRequest { private String name; }",
1768
1768
  });
1769
1769
  const modelContractFindings = lombokFindings.filter((item) => item.category === "model_lombok_contract" && item.severity === "hard_fail");
1770
1770
  if (modelContractFindings.length < 2) {
@@ -2116,6 +2116,28 @@ async function checkReleaseIssueDesignPath(rootDir, hardFail, _info) {
2116
2116
  !designPackText.includes("auditDesignImplementationTraceability")) {
2117
2117
  hardFail("RELEASE_ISSUE_TRACEABILITY_DESIGN_AUDIT_MISSING", "问题七十三未并入设计产物包审计", ["src/engine/design_artifact_pack.ts"], "problem-73", "追踪矩阵不进入 audit-design-artifacts 会导致用户设计阶段无法发现缺口", "把追踪矩阵作为设计产物包权威资产审计");
2118
2118
  }
2119
+ const lifecycleContractText = safeRead(path.join(rootDir, "src", "engine", "design_lifecycle_contract.ts")) ?? "";
2120
+ const lifecycleKnowledgeText = safeRead(path.join(rootDir, "src", "engine", "lifecycle_knowledge_contract.ts")) ?? "";
2121
+ if (!lifecycleContractText.includes("detail_design") ||
2122
+ !lifecycleContractText.includes("docs/architecture/02-数据库设计文档.md") ||
2123
+ !lifecycleContractText.includes("docs/architecture/03-API接口规格文档.md") ||
2124
+ !lifecycleContractText.includes("optional_implementation_detail_document") ||
2125
+ !lifecycleContractText.includes("docs/architecture/04-开发切片计划.md") ||
2126
+ !lifecycleContractText.includes("DESIGN_LIFECYCLE_LEGACY_SLICE_PLAN_PATHS") ||
2127
+ !lifecycleContractText.includes("slice_planning") ||
2128
+ !designPackText.includes("getDesignLifecycleArtifactPaths")) {
2129
+ hardFail("RELEASE_ISSUE_DESIGN_LIFECYCLE_CONTRACT_MISSING", "设计、实现、测试、验收生命周期 I/O 合同缺失或未被设计产物包消费", ["src/engine/design_lifecycle_contract.ts", "src/engine/design_artifact_pack.ts"], "problem-62/problem-73", "没有中心合同会导致后续门禁凭空新增输入输出,详细设计又被误判成单文件", "建立中心生命周期合同,并让设计产物包、追踪审计和 hook 消费同一合同");
2130
+ }
2131
+ if (!lifecycleKnowledgeText.includes("evaluateLifecycleKnowledgeDecision") ||
2132
+ !lifecycleKnowledgeText.includes("selectProjectKnowledgeForTaskWithReasons") ||
2133
+ !lifecycleKnowledgeText.includes("auditDesignImplementationTraceability") ||
2134
+ !lifecycleKnowledgeText.includes("assessControlledGenerationChain")) {
2135
+ hardFail("RELEASE_ISSUE_UNIFIED_LIFECYCLE_KNOWLEDGE_CONTRACT_MISSING", "生命周期、项目知识选择和证据消费仍未收口到统一决策合同", ["src/engine/lifecycle_knowledge_contract.ts"], "problem-62/problem-73/project-knowledge-control-plane", "三个并行机制会导致 next/expand/verify/deliver 各自新增局部口径", "建立并强制消费 evaluateLifecycleKnowledgeDecision");
2136
+ }
2137
+ const injectionBoundaryText = safeRead(path.join(rootDir, "src", "engine", "knowledge_injection_boundary.ts")) ?? "";
2138
+ if (injectionBoundaryText.includes("buildTemplateAssetContracts(process.cwd())")) {
2139
+ hardFail("RELEASE_ISSUE_KNOWLEDGE_CONTRACT_CWD_DRIFT", "知识注入边界仍用 process.cwd() 读取模板合同", ["src/engine/knowledge_injection_boundary.ts"], "project-knowledge-consumption", "用户项目、全局安装和测试目录会取错合同根目录", "改为从模块根或显式合同根读取模板合同");
2140
+ }
2119
2141
  if (!cliText.includes("cmdAuditDesignArtifacts") ||
2120
2142
  !cliText.includes("cmdUpgradeDesignArtifacts") ||
2121
2143
  !cliText.includes("currentTask?.design_artifact_pack")) {
@@ -2149,6 +2171,26 @@ async function checkReleaseIssueDesignPath(rootDir, hardFail, _info) {
2149
2171
  try {
2150
2172
  const workshop = await import(path.join(rootDir, "dist", "engine", "architecture_decision_workshop.js"));
2151
2173
  const designPack = await import(path.join(rootDir, "dist", "engine", "design_artifact_pack.js"));
2174
+ const lifecycle = await import(path.join(rootDir, "dist", "engine", "design_lifecycle_contract.js"));
2175
+ const lifecycleFindings = lifecycle.validateDesignLifecycleContract();
2176
+ if (lifecycleFindings.length > 0) {
2177
+ hardFail("RELEASE_ISSUE_DESIGN_LIFECYCLE_CONTRACT_INVALID", `设计生命周期合同不满足不变量: ${lifecycleFindings.map((finding) => finding.code).join(",")}`, ["src/engine/design_lifecycle_contract.ts"], "problem-62/problem-73", "生命周期合同必须明确设计、实现、测试、验收节点的输入输出和门禁", "修复 validateDesignLifecycleContract 报告的不变量缺口");
2178
+ }
2179
+ const detailStage = lifecycle.getDesignLifecycleStageContract("detail_design");
2180
+ const detailRequiredOutputs = detailStage.outputs.filter((artifact) => artifact.required).map((artifact) => artifact.path);
2181
+ if (!detailRequiredOutputs.includes("docs/architecture/02-数据库设计文档.md") ||
2182
+ !detailRequiredOutputs.includes("docs/architecture/03-API接口规格文档.md") ||
2183
+ detailRequiredOutputs.includes("docs/architecture/04-详细设计文档.md")) {
2184
+ hardFail("RELEASE_ISSUE_DETAIL_DESIGN_TOPOLOGY_INVALID", "详细设计阶段输出拓扑错误", ["src/engine/design_lifecycle_contract.ts"], "problem-62/problem-73", "详细设计必需载体是数据库设计和 API 规格,04-详细设计文档只能是可选兼容", "修复 detail_design 生命周期合同");
2185
+ }
2186
+ const lifecyclePaths = lifecycle.getDesignLifecycleArtifactPaths();
2187
+ if (lifecyclePaths.slice_plan !== "docs/architecture/04-开发切片计划.md") {
2188
+ hardFail("RELEASE_ISSUE_SLICE_PLAN_CANONICAL_PATH_INVALID", "开发切片计划仍绑定到固定阶段文件", ["src/engine/design_lifecycle_contract.ts"], "problem-62/problem-73", "切片计划是全项目调度权威资产,不能命名成第一阶段", "将 canonical slice_plan 改为 docs/architecture/04-开发切片计划.md,旧第一阶段文件仅作为 alias");
2189
+ }
2190
+ const packPaths = designPack.defaultDesignArtifactPaths();
2191
+ if (JSON.stringify(lifecyclePaths) !== JSON.stringify(packPaths)) {
2192
+ hardFail("RELEASE_ISSUE_DESIGN_PACK_PATH_DRIFT", "设计产物包路径与生命周期合同漂移", ["src/engine/design_lifecycle_contract.ts", "src/engine/design_artifact_pack.ts"], "problem-62/problem-73", "设计产物包不得独立硬编码另一套输入输出路径", "让 defaultDesignArtifactPaths 从 getDesignLifecycleArtifactPaths 派生");
2193
+ }
2152
2194
  const draft = workshop.createArchitectureDecisionWorkshop("release-issue", "new_system");
2153
2195
  if (workshop.evaluateArchitectureDecisionWorkshop(draft).allowed) {
2154
2196
  hardFail("RELEASE_ISSUE_BEHAVIOR_FALSE_PASS", "问题六十一未确认六域的草稿错误放行", ["src/engine/architecture_decision_workshop.ts"], "problem-61", "必须有负向行为证据", "修复研讨生成门");
@@ -2173,29 +2215,30 @@ async function checkReleaseIssueDesignPath(rootDir, hardFail, _info) {
2173
2215
  "# 需求原型设计实现追踪矩阵",
2174
2216
  "| 需求 | 原型 | 架构 | 详细设计 | 切片 | 验收 |",
2175
2217
  "| --- | --- | --- | --- | --- | --- |",
2176
- "| REQ-001 | PROTO-001 | ARCH-001 | DD-001 | SLICE-001 | AC-001 |",
2218
+ "| REQ-001 | PROTO-001 | ARCH-001 | DD-T001, DD-A001 | PHASE-001, SLICE-001 | AC-001 |",
2177
2219
  ].join("\n"));
2178
- write("docs/architecture/04-详细设计文档.md", "# 详细设计\nARCH-001 -> DD-001");
2179
- write("docs/architecture/05-切片计划.md", "# 切片\nSLICE-001\n来源 DD-001\n验收 AC-001");
2220
+ write("docs/architecture/02-数据库设计文档.md", "# 数据库设计\nARCH-001 -> DD-T001");
2221
+ write("docs/architecture/03-API接口规格文档.md", "# API 设计\nARCH-001 -> DD-A001");
2222
+ write("docs/architecture/04-开发切片计划.md", "# 开发切片计划\nPHASE-001\nSLICE-001\n来源 DD-T001, DD-A001\n验收 AC-001");
2180
2223
  const bindingFail = traceability.verifyChangedFilesAgainstDesignTraceability(tmp, ["src/main/java/demo/BedService.java"], {
2181
2224
  task_id: "trace-gate",
2182
2225
  created_at: new Date().toISOString(),
2183
- intent: "实现床位管理",
2226
+ intent: "实现资源管理",
2184
2227
  product_profile: "default",
2185
2228
  status: "executing",
2186
2229
  });
2187
2230
  if (bindingFail.passed || !bindingFail.findings.some((f) => f.code === "TRACEABILITY_CODE_BINDING_MISSING")) {
2188
- hardFail("RELEASE_ISSUE_TRACEABILITY_CODE_BINDING_FALSE_PASS", "问题七十三编码缺少 SLICE/DD/AC 绑定时错误放行", ["src/engine/traceability.ts", "src/adapters/claude_code/tools.ts"], "problem-73", "实现代码必须能追溯到详细设计、切片和验收", "修复 sf_expand/sf_verify 追踪绑定门");
2231
+ hardFail("RELEASE_ISSUE_TRACEABILITY_CODE_BINDING_FALSE_PASS", "问题七十三编码缺少 PHASE/SLICE/DD/AC 绑定时错误放行", ["src/engine/traceability.ts", "src/adapters/claude_code/tools.ts"], "problem-73", "实现代码必须能追溯到详细设计、切片和验收", "修复 sf_expand/sf_verify 追踪绑定门");
2189
2232
  }
2190
2233
  const bindingPass = traceability.verifyChangedFilesAgainstDesignTraceability(tmp, ["src/main/java/demo/BedService.java"], {
2191
2234
  task_id: "trace-gate-ok",
2192
2235
  created_at: new Date().toISOString(),
2193
- intent: "实现床位管理 SLICE-001 DD-001 AC-001",
2236
+ intent: "实现资源管理 PHASE-001 SLICE-001 DD-T001 DD-A001 AC-001",
2194
2237
  product_profile: "default",
2195
2238
  status: "executing",
2196
2239
  });
2197
2240
  if (!bindingPass.passed) {
2198
- hardFail("RELEASE_ISSUE_TRACEABILITY_CODE_BINDING_FALSE_BLOCK", "问题七十三合法 SLICE/DD/AC 绑定被错误阻断", ["src/engine/traceability.ts"], "problem-73", "合法追踪绑定应允许编码验证继续", "修复 traceability binding 校验");
2241
+ hardFail("RELEASE_ISSUE_TRACEABILITY_CODE_BINDING_FALSE_BLOCK", "问题七十三合法 PHASE/SLICE/DD/AC 绑定被错误阻断", ["src/engine/traceability.ts"], "problem-73", "合法追踪绑定应允许编码验证继续", "修复 traceability binding 校验");
2199
2242
  }
2200
2243
  }
2201
2244
  catch (error) {
@@ -2539,26 +2582,26 @@ async function checkCodeObservabilityBehavior(rootDir, hardFail, _info) {
2539
2582
  }
2540
2583
  // 行为验证: 普通 Spring 后端 Slice 的 CRUD/事务双写无日志无注释也必须被检测。
2541
2584
  const smartCareSliceFindings = obs.verifyChangedFilesObservability({
2542
- changed_files: ["src/main/java/com/smartcare/staff/service/impl/StaffServiceImpl.java"],
2585
+ changed_files: ["src/main/java/com/demoapp/account/service/impl/AccountServiceImpl.java"],
2543
2586
  file_contents: {
2544
- "src/main/java/com/smartcare/staff/service/impl/StaffServiceImpl.java": `@Service
2545
- public class StaffServiceImpl implements StaffService {
2587
+ "src/main/java/com/demoapp/account/service/impl/AccountServiceImpl.java": `@Service
2588
+ public class AccountServiceImpl implements AccountService {
2546
2589
  @Transactional
2547
- public StaffVO create(StaffCreateRequest request) {
2548
- Staff staff = convert(request);
2549
- staffMapper.insert(staff);
2590
+ public AccountVO create(AccountCreateRequest request) {
2591
+ Account account = convert(request);
2592
+ accountMapper.insert(account);
2550
2593
  SysUser user = buildUser(request);
2551
2594
  sysUserMapper.insert(user);
2552
- return toVO(staff);
2595
+ return toVO(account);
2553
2596
  }
2554
2597
  @Transactional
2555
- public void resign(Long staffId) {
2556
- staffMapper.updateStatus(staffId, StaffStatus.RESIGNED);
2557
- sysUserMapper.updateAccountStatus(staffId, 0);
2598
+ public void resign(Long accountId) {
2599
+ accountMapper.updateStatus(accountId, AccountStatus.RESIGNED);
2600
+ sysUserMapper.updateAccountStatus(accountId, 0);
2558
2601
  }
2559
2602
  }`,
2560
2603
  },
2561
- intent: "完成 Slice 2 机构设施与员工管理后端实现",
2604
+ intent: "完成 Slice 2 资源目录与账号管理后端实现",
2562
2605
  });
2563
2606
  const smartCareBlocked = smartCareSliceFindings.some((f) => f.category === "missing_log_business_write" && f.severity === "hard_fail")
2564
2607
  && smartCareSliceFindings.some((f) => f.category === "missing_comment_complex");
@@ -2566,46 +2609,46 @@ public class StaffServiceImpl implements StaffService {
2566
2609
  hardFail("CODE_OBSERVABILITY_BACKEND_SLICE_FALSE_PASS", "problem-68: 普通后端 Slice 的 Controller/Service 事务双写和级联规则无日志无注释未被阻断", ["src/engine/code_maintainability_observability_contract.ts"], "problem-68", "旧门禁只覆盖支付/安全/迁移,真实 CRUD 后端实现仍可无日志无注释通过", "扩展后端实现文件检测,覆盖 Controller/Service/DTO/Entity");
2567
2610
  }
2568
2611
  const javaDocAndChineseFindings = obs.verifyChangedFilesObservability({
2569
- changed_files: ["src/main/java/com/smartcare/staff/service/impl/StaffServiceImpl.java"],
2612
+ changed_files: ["src/main/java/com/demoapp/account/service/impl/AccountServiceImpl.java"],
2570
2613
  file_contents: {
2571
- "src/main/java/com/smartcare/staff/service/impl/StaffServiceImpl.java": `@Service
2572
- public class StaffServiceImpl implements StaffService {
2573
- public StaffVO create(StaffCreateRequest request) {
2574
- Staff staff = convert(request);
2575
- staffMapper.insert(staff);
2576
- logger.info("staff created staffId=" + staff.getId());
2577
- return toVO(staff);
2614
+ "src/main/java/com/demoapp/account/service/impl/AccountServiceImpl.java": `@Service
2615
+ public class AccountServiceImpl implements AccountService {
2616
+ public AccountVO create(AccountCreateRequest request) {
2617
+ Account account = convert(request);
2618
+ accountMapper.insert(account);
2619
+ logger.info("account created accountId=" + account.getId());
2620
+ return toVO(account);
2578
2621
  }
2579
2622
  }`,
2580
2623
  },
2581
- intent: "完成 Slice 2 员工管理后端实现",
2624
+ intent: "完成 Slice 2 账号管理后端实现",
2582
2625
  });
2583
2626
  const javaDocAndChineseBlocked = ["missing_class_doc", "missing_method_doc", "missing_important_line_comment", "non_chinese_log"].every((category) => javaDocAndChineseFindings.some((f) => f.category === category && f.severity === "hard_fail"));
2584
2627
  if (!javaDocAndChineseBlocked) {
2585
2628
  hardFail("CODE_OBSERVABILITY_CHINESE_DOC_CONTRACT_FALSE_PASS", "problem-68: 后端类/方法中文 Javadoc、关键行中文注释或中文日志缺失未被阻断", ["src/engine/code_maintainability_observability_contract.ts"], "problem-68", "只检查是否有日志/注释会放过英文日志、无类说明、无方法入参出参说明和关键行业务意图缺失", "扩展 reviewCommentQuality/reviewMissingLogs,强制中文日志、中文注释、类 Javadoc、方法 Javadoc 和关键行注释");
2586
2629
  }
2587
2630
  const crossStackFindings = obs.verifyChangedFilesObservability({
2588
- changed_files: ["src/routes/staff.route.ts", "app/api/staff.py", "src/pages/StaffForm.tsx"],
2631
+ changed_files: ["src/routes/account.route.ts", "app/api/account.py", "src/pages/AccountForm.tsx"],
2589
2632
  file_contents: {
2590
- "src/routes/staff.route.ts": `router.post('/staff', async (req, res) => {
2591
- const staff = await staffRepo.create(req.body);
2592
- await userRepo.create({ staffId: staff.id });
2593
- res.json(staff);
2633
+ "src/routes/account.route.ts": `router.post('/account', async (req, res) => {
2634
+ const account = await accountRepo.create(req.body);
2635
+ await userRepo.create({ accountId: account.id });
2636
+ res.json(account);
2594
2637
  });`,
2595
- "app/api/staff.py": `@router.post("/staff")
2596
- async def create_staff(payload: StaffCreate):
2597
- staff = await staff_repo.create(payload)
2598
- await user_repo.create(staff_id=staff.id)
2599
- return staff`,
2600
- "src/pages/StaffForm.tsx": `export function StaffForm() {
2638
+ "app/api/account.py": `@router.post("/account")
2639
+ async def create_account(payload: AccountCreate):
2640
+ account = await account_repo.create(payload)
2641
+ await user_repo.create(account_id=account.id)
2642
+ return account`,
2643
+ "src/pages/AccountForm.tsx": `export function AccountForm() {
2601
2644
  async function handleSubmit(values) {
2602
- await apiClient.post('/api/institution/staff', values);
2645
+ await apiClient.post('/api/tenant/users', values);
2603
2646
  setStatus('created');
2604
2647
  }
2605
2648
  return <form onSubmit={handleSubmit}>...</form>;
2606
2649
  }`,
2607
2650
  },
2608
- intent: "实现员工新增前后端接口与表单",
2651
+ intent: "实现账号新增前后端接口与表单",
2609
2652
  });
2610
2653
  const crossStackBlocked = crossStackFindings.filter((f) => f.category === "missing_log_business_write" && f.severity === "hard_fail").length >= 3;
2611
2654
  if (!crossStackBlocked) {
@@ -2763,7 +2806,7 @@ async function checkTemplateAndProjectKnowledgeHygiene(rootDir, hardFail, _info)
2763
2806
  }
2764
2807
  try {
2765
2808
  const obs = await import(path.join(rootDir, "dist", "engine", "code_maintainability_observability_contract.js"));
2766
- const ordinaryApiImplementationTriggers = obs.requiresCodeObservabilityContract?.("实现机构端入住列表接口", "code_change") === true;
2809
+ const ordinaryApiImplementationTriggers = obs.requiresCodeObservabilityContract?.("实现业务端业务办理列表接口", "code_change") === true;
2767
2810
  if (!ordinaryApiImplementationTriggers) {
2768
2811
  hardFail("CODE_OBSERVABILITY_BUSINESS_API_NOT_TRIGGERED", "problem-68: 普通业务接口实现未触发代码注释与日志契约,真实项目会绕过问题六十八", ["src/engine/code_maintainability_observability_contract.ts", "src/adapters/claude_code/tools.ts"], "problem-68", "旧行为只覆盖支付/安全等关键词,未覆盖普通 Controller/API/Service 编码", "扩展触发条件并在 sf_expand 聚合返回工作包");
2769
2812
  }
@@ -2776,7 +2819,7 @@ async function checkTemplateAndProjectKnowledgeHygiene(rootDir, hardFail, _info)
2776
2819
  const goodDir = path.join(tmp, ".soloforge", "knowledge", "rules");
2777
2820
  fs.mkdirSync(goodDir, { recursive: true });
2778
2821
  fs.writeFileSync(path.join(goodDir, "API响应规则.md"), `---
2779
- id: smartcare-api-response-rule
2822
+ id: demo-api-response-rule
2780
2823
  asset_kind: hard_rule
2781
2824
  routes:
2782
2825
  - code_change
@@ -2795,21 +2838,56 @@ enforcement:
2795
2838
  必须使用项目统一响应结构,错误码、字段表和 OpenAPI 保持一致。
2796
2839
  `, "utf-8");
2797
2840
  const projectKnowledge = await import(path.join(rootDir, "dist", "engine", "project_knowledge_contract.js"));
2841
+ const lifecycleKnowledge = await import(path.join(rootDir, "dist", "engine", "lifecycle_knowledge_contract.js"));
2798
2842
  const report = projectKnowledge.auditProjectKnowledge(tmp);
2799
2843
  if (report.hard_fail_count !== 0 || report.injectable < 1) {
2800
2844
  hardFail("PROJECT_KNOWLEDGE_RULE_NOT_CONSUMABLE", "用户项目 .soloforge/knowledge hard rule 未被识别为可消费规则", ["src/engine/project_knowledge_contract.ts"], "project-knowledge-consumption", "旧链路只同步/索引内置模板,未证明用户项目自定义规则可被承载消费", "修复项目知识合同审计与选择逻辑");
2801
2845
  }
2802
- const selected = projectKnowledge.selectProjectKnowledgeForTask(report, {
2803
- intent: "实现机构端 API 接口统一响应",
2846
+ const selected = projectKnowledge.selectProjectKnowledgeForTaskWithReasons(report, {
2847
+ intent: "实现业务端 API 接口统一响应",
2804
2848
  route: "code_change",
2805
2849
  tech_stack: ["spring"],
2806
2850
  });
2807
- if (!selected.some((asset) => asset.id === "smartcare-api-response-rule")) {
2851
+ if (!selected.selected.some((decision) => decision.asset.id === "demo-api-response-rule")) {
2808
2852
  hardFail("PROJECT_KNOWLEDGE_RULE_NOT_SELECTED", "用户项目自定义 hard rule 未按意图/路由/技术栈被选中", ["src/engine/project_knowledge_contract.ts"], "project-knowledge-consumption", "索引存在不等于任务会消费", "补齐 selectProjectKnowledgeForTask 行为和门禁");
2809
2853
  }
2854
+ const selection = projectKnowledge.selectProjectKnowledgeForTaskWithReasons(report, {
2855
+ intent: "实现业务端 API 接口统一响应 PHASE-001 SLICE-001 DD-A001 AC-001",
2856
+ route: "code_change",
2857
+ tech_stack: ["spring"],
2858
+ lifecycle_stage: "implementation",
2859
+ changed_files: ["backend/web/src/main/java/com/example/web/tenant/TenantUserController.java"],
2860
+ traceability_ids: ["PHASE-001", "SLICE-001", "DD-A001", "AC-001"],
2861
+ });
2862
+ const selectedDecision = selection.selected.find((decision) => decision.asset.id === "demo-api-response-rule");
2863
+ if (!selectedDecision || !selectedDecision.reason_zh || !Array.isArray(selectedDecision.matched_signals)) {
2864
+ hardFail("PROJECT_KNOWLEDGE_SELECTION_REASON_MISSING", "用户项目规则选择缺少 why selected / matched_signals 结构化解释", ["src/engine/project_knowledge_contract.ts", "src/engine/intent_expander.ts"], "project-knowledge-consumption", "用户不知道为什么规则被选中就无法判断必须确认和修复路径", "让项目知识选择返回 SelectionDecision 而不是裸资产");
2865
+ }
2866
+ const unifiedDecision = lifecycleKnowledge.evaluateLifecycleKnowledgeDecision({
2867
+ projectPath: tmp,
2868
+ consumer: "sf_expand",
2869
+ intent: "实现业务端 API 接口统一响应 PHASE-001 SLICE-001 DD-A001 AC-001",
2870
+ route: "code_change",
2871
+ lifecycle_stage: "implementation",
2872
+ changed_files: ["backend/web/src/main/java/com/example/web/tenant/TenantUserController.java"],
2873
+ verified_files: ["backend/web/src/main/java/com/example/web/tenant/TenantUserController.java"],
2874
+ traceability_ids: ["PHASE-001", "SLICE-001", "DD-A001", "AC-001"],
2875
+ tech_stack: ["spring"],
2876
+ generation_traces: [
2877
+ { tool_name: "sf_classify", status: "passed", evidence_kind: "result" },
2878
+ { tool_name: "sf_expand", status: "passed", evidence_kind: "result" },
2879
+ ],
2880
+ record_trace: true,
2881
+ });
2882
+ if (unifiedDecision.contract_id !== "lifecycle_knowledge_contract/v1" ||
2883
+ !unifiedDecision.knowledge_selection.selected.some((decision) => decision.asset.id === "demo-api-response-rule") ||
2884
+ !unifiedDecision.authoritative_paths.traceability_matrix ||
2885
+ !Array.isArray(unifiedDecision.recovery_commands)) {
2886
+ hardFail("LIFECYCLE_KNOWLEDGE_DECISION_BUNDLE_INVALID", "统一生命周期知识决策包未同时携带权威路径、SelectionDecision、恢复命令和消费 trace", ["src/engine/lifecycle_knowledge_contract.ts", "src/engine/project_knowledge_contract.ts"], "project-knowledge-consumption", "next/expand/verify/deliver 如果不消费同一决策包,会再次产生局部口径", "修复 evaluateLifecycleKnowledgeDecision 返回结构和入口消费");
2887
+ }
2810
2888
  const expander = await import(path.join(rootDir, "dist", "engine", "intent_expander.js"));
2811
2889
  const expandResult = await expander.expand({
2812
- intent: "实现机构端 API 接口统一响应",
2890
+ intent: "实现业务端 API 接口统一响应",
2813
2891
  classification: {
2814
2892
  task_type: "feature",
2815
2893
  risk: "low",
@@ -2852,8 +2930,10 @@ enforcement:
2852
2930
  decision_version: 1,
2853
2931
  },
2854
2932
  });
2855
- if (!expandResult.project_knowledge?.selected?.some((asset) => asset.id === "smartcare-api-response-rule")
2856
- || !String(expandResult.prompt).includes("## 用户项目规则")) {
2933
+ if (!expandResult.project_knowledge?.selected?.some((asset) => asset.id === "demo-api-response-rule")
2934
+ || !String(expandResult.prompt).includes("## 用户项目规则")
2935
+ || !String(expandResult.prompt).includes("选中原因")
2936
+ || !expandResult.project_knowledge?.selection_decisions?.some((decision) => decision.id === "demo-api-response-rule" && decision.reason_zh)) {
2857
2937
  hardFail("PROJECT_KNOWLEDGE_NOT_IN_EXPAND_MAINPATH", "用户项目规则未进入 sf_expand 真实 prompt 和结构化结果", ["src/engine/intent_expander.ts", "src/engine/project_knowledge_contract.ts"], "project-knowledge-consumption", "审计/选择通过不等于 MCP 主链路会消费", "将项目规则接入 sf_expand 并补主链路测试");
2858
2938
  }
2859
2939
  const nextPlanner = await import(path.join(rootDir, "dist", "engine", "next_action_planner.js"));
@@ -2861,11 +2941,24 @@ enforcement:
2861
2941
  if (!nextPlan.project_knowledge_context || nextPlan.project_knowledge_context.total < 1) {
2862
2942
  hardFail("PROJECT_KNOWLEDGE_NOT_IN_NEXT", "soloforge next 未携带项目知识上下文,用户无法知道下一步会应用哪些项目规则", ["src/engine/next_action_planner.ts", "src/bin/soloforge.ts"], "project-knowledge-consumption", "旧导航只看阶段,不看项目规则", "将项目知识上下文接入 next JSON 和人类输出");
2863
2943
  }
2944
+ if (nextPlan.project_knowledge_context?.selected?.length
2945
+ && !nextPlan.project_knowledge_context.selected.some((item) => item.reason_zh && item.enforcement)) {
2946
+ hardFail("PROJECT_KNOWLEDGE_NEXT_REASON_MISSING", "soloforge next 项目规则上下文缺少选中原因或强制级别", ["src/engine/next_action_planner.ts", "src/bin/soloforge.ts"], "project-knowledge-consumption", "next 只列规则名不能支撑用户确认哪些必须满足", "在 next 中展示 SelectionDecision 的 reason/enforcement/verification");
2947
+ }
2864
2948
  const badTmp = fs.mkdtempSync(path.join(os.tmpdir(), "soloforge-project-knowledge-bad-"));
2865
2949
  try {
2866
2950
  const badDir = path.join(badTmp, ".soloforge", "knowledge", "rules");
2867
2951
  fs.mkdirSync(badDir, { recursive: true });
2868
- fs.writeFileSync(path.join(badDir, "未路由强规则.md"), "# 未路由强规则\n\n必须使用统一响应。", "utf-8");
2952
+ fs.writeFileSync(path.join(badDir, "未路由强规则.md"), `---
2953
+ id: unrouted-hard-rule
2954
+ asset_kind: hard_rule
2955
+ enforcement:
2956
+ level: hard_rule
2957
+ ---
2958
+ # 未路由强规则
2959
+
2960
+ 必须使用统一响应。
2961
+ `, "utf-8");
2869
2962
  const badReport = projectKnowledge.auditProjectKnowledge(badTmp);
2870
2963
  if (badReport.hard_fail_count === 0) {
2871
2964
  hardFail("PROJECT_KNOWLEDGE_UNROUTED_RULE_FALSE_PASS", "用户项目 hard rule 缺少 routes/primary_triggers 时错误放行", ["src/engine/project_knowledge_contract.ts"], "project-knowledge-consumption", "规则文件存在不等于可稳定消费", "对未路由 hard rule fail-closed");
@@ -2914,6 +3007,42 @@ enforcement:
2914
3007
  finally {
2915
3008
  fs.rmSync(conflictTmp, { recursive: true, force: true });
2916
3009
  }
3010
+ const semanticConflictTmp = fs.mkdtempSync(path.join(os.tmpdir(), "soloforge-project-knowledge-semantic-conflict-"));
3011
+ try {
3012
+ const semanticDir = path.join(semanticConflictTmp, ".soloforge", "knowledge", "rules");
3013
+ fs.mkdirSync(semanticDir, { recursive: true });
3014
+ fs.writeFileSync(path.join(semanticDir, "响应ApiResponse.md"), `---
3015
+ id: response-api-response
3016
+ asset_kind: hard_rule
3017
+ routes: [code_change]
3018
+ primary_triggers: [API响应]
3019
+ enforcement:
3020
+ level: hard_rule
3021
+ ---
3022
+ # API 响应
3023
+
3024
+ 必须使用 ApiResponse。
3025
+ `, "utf-8");
3026
+ fs.writeFileSync(path.join(semanticDir, "响应Result.md"), `---
3027
+ id: response-result
3028
+ asset_kind: hard_rule
3029
+ routes: [code_change]
3030
+ primary_triggers: [接口响应]
3031
+ enforcement:
3032
+ level: hard_rule
3033
+ ---
3034
+ # 接口响应
3035
+
3036
+ 必须使用 Result。
3037
+ `, "utf-8");
3038
+ const semanticConflictReport = projectKnowledge.auditProjectKnowledge(semanticConflictTmp);
3039
+ if (!semanticConflictReport.assets.some((asset) => asset.findings.some((finding) => finding.code === "PROJECT_KNOWLEDGE_RULE_CONFLICT"))) {
3040
+ hardFail("PROJECT_KNOWLEDGE_SEMANTIC_CONFLICT_FALSE_PASS", "API 响应格式语义冲突依赖手写 conflict_group,未自动进入用户确认", ["src/engine/project_knowledge_contract.ts"], "project-knowledge-consumption", "项目规则冲突不能要求用户预先正确标注才能发现", "补 API 响应/分页/日志/DB/权限语义冲突检测");
3041
+ }
3042
+ }
3043
+ finally {
3044
+ fs.rmSync(semanticConflictTmp, { recursive: true, force: true });
3045
+ }
2917
3046
  }
2918
3047
  catch (e) {
2919
3048
  hardFail("PROJECT_KNOWLEDGE_AUDIT_FAILED", `用户项目知识消费行为审计执行失败: ${e.message}`, ["src/engine/project_knowledge_contract.ts"], "project-knowledge-consumption", "项目知识消费必须有可执行行为门禁", "修复项目知识合同模块和编译产物");