soloforge 1.4.3 → 1.4.5

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 (110) 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 +56 -13
  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 +186 -75
  8. package/dist/bin/soloforge.js.map +1 -1
  9. package/dist/engine/asset_manifest.js +1 -1
  10. package/dist/engine/asset_manifest.js.map +1 -1
  11. package/dist/engine/backend_implementation_contract.js +1 -1
  12. package/dist/engine/code_maintainability_observability_contract.js +7 -7
  13. package/dist/engine/code_maintainability_observability_contract.js.map +1 -1
  14. package/dist/engine/consumable_asset_registry.d.ts.map +1 -1
  15. package/dist/engine/consumable_asset_registry.js +1 -0
  16. package/dist/engine/consumable_asset_registry.js.map +1 -1
  17. package/dist/engine/consumption_trace_store.d.ts +9 -1
  18. package/dist/engine/consumption_trace_store.d.ts.map +1 -1
  19. package/dist/engine/consumption_trace_store.js +3 -0
  20. package/dist/engine/consumption_trace_store.js.map +1 -1
  21. package/dist/engine/control_plane_contract.d.ts.map +1 -1
  22. package/dist/engine/control_plane_contract.js +1 -0
  23. package/dist/engine/control_plane_contract.js.map +1 -1
  24. package/dist/engine/design_artifact_pack.d.ts +5 -0
  25. package/dist/engine/design_artifact_pack.d.ts.map +1 -1
  26. package/dist/engine/design_artifact_pack.js +23 -17
  27. package/dist/engine/design_artifact_pack.js.map +1 -1
  28. package/dist/engine/design_lifecycle_contract.d.ts +60 -0
  29. package/dist/engine/design_lifecycle_contract.d.ts.map +1 -0
  30. package/dist/engine/design_lifecycle_contract.js +497 -0
  31. package/dist/engine/design_lifecycle_contract.js.map +1 -0
  32. package/dist/engine/diagnostic_registry.js +2 -2
  33. package/dist/engine/diagnostic_registry.js.map +1 -1
  34. package/dist/engine/explicit_asset_registry.d.ts.map +1 -1
  35. package/dist/engine/explicit_asset_registry.js +16 -0
  36. package/dist/engine/explicit_asset_registry.js.map +1 -1
  37. package/dist/engine/foundation_scenario_registry.js +2 -2
  38. package/dist/engine/foundation_scenario_registry.js.map +1 -1
  39. package/dist/engine/foundation_scenario_runners.js +9 -9
  40. package/dist/engine/foundation_scenario_runners.js.map +1 -1
  41. package/dist/engine/historical_issue_mechanization_matrix.js +1 -1
  42. package/dist/engine/historical_issue_mechanization_matrix.js.map +1 -1
  43. package/dist/engine/implementation_roadmap_registry.js +2 -2
  44. package/dist/engine/implementation_roadmap_registry.js.map +1 -1
  45. package/dist/engine/input_material_extractor.js +1 -1
  46. package/dist/engine/input_material_extractor.js.map +1 -1
  47. package/dist/engine/intent_expander.d.ts.map +1 -1
  48. package/dist/engine/intent_expander.js +38 -15
  49. package/dist/engine/intent_expander.js.map +1 -1
  50. package/dist/engine/knowledge_asset_consumer.d.ts.map +1 -1
  51. package/dist/engine/knowledge_asset_consumer.js +21 -13
  52. package/dist/engine/knowledge_asset_consumer.js.map +1 -1
  53. package/dist/engine/knowledge_injection_boundary.d.ts +2 -2
  54. package/dist/engine/knowledge_injection_boundary.d.ts.map +1 -1
  55. package/dist/engine/knowledge_injection_boundary.js +19 -7
  56. package/dist/engine/knowledge_injection_boundary.js.map +1 -1
  57. package/dist/engine/lifecycle_knowledge_contract.d.ts +59 -0
  58. package/dist/engine/lifecycle_knowledge_contract.d.ts.map +1 -0
  59. package/dist/engine/lifecycle_knowledge_contract.js +203 -0
  60. package/dist/engine/lifecycle_knowledge_contract.js.map +1 -0
  61. package/dist/engine/next_action_planner.d.ts +9 -4
  62. package/dist/engine/next_action_planner.d.ts.map +1 -1
  63. package/dist/engine/next_action_planner.js +66 -23
  64. package/dist/engine/next_action_planner.js.map +1 -1
  65. package/dist/engine/observed_consumption.d.ts.map +1 -1
  66. package/dist/engine/observed_consumption.js +2 -1
  67. package/dist/engine/observed_consumption.js.map +1 -1
  68. package/dist/engine/project_knowledge_contract.d.ts +75 -1
  69. package/dist/engine/project_knowledge_contract.d.ts.map +1 -1
  70. package/dist/engine/project_knowledge_contract.js +267 -30
  71. package/dist/engine/project_knowledge_contract.js.map +1 -1
  72. package/dist/engine/regression_matrix.js +1 -1
  73. package/dist/engine/regression_matrix.js.map +1 -1
  74. package/dist/engine/release_issue_scenario_registry.d.ts.map +1 -1
  75. package/dist/engine/release_issue_scenario_registry.js +15 -12
  76. package/dist/engine/release_issue_scenario_registry.js.map +1 -1
  77. package/dist/engine/release_readiness_gate.d.ts.map +1 -1
  78. package/dist/engine/release_readiness_gate.js +211 -56
  79. package/dist/engine/release_readiness_gate.js.map +1 -1
  80. package/dist/engine/stale_current_task_detector.d.ts +1 -1
  81. package/dist/engine/stale_current_task_detector.js +4 -4
  82. package/dist/engine/stale_current_task_detector.js.map +1 -1
  83. package/dist/engine/task_context.d.ts.map +1 -1
  84. package/dist/engine/task_context.js +2 -0
  85. package/dist/engine/task_context.js.map +1 -1
  86. package/dist/engine/traceability.d.ts +7 -1
  87. package/dist/engine/traceability.d.ts.map +1 -1
  88. package/dist/engine/traceability.js +90 -15
  89. package/dist/engine/traceability.js.map +1 -1
  90. package/dist/engine/workflow_navigation_contract.d.ts +11 -0
  91. package/dist/engine/workflow_navigation_contract.d.ts.map +1 -1
  92. package/dist/engine/workspace_resumer.d.ts.map +1 -1
  93. package/dist/engine/workspace_resumer.js +2 -1
  94. package/dist/engine/workspace_resumer.js.map +1 -1
  95. package/dist/knowledge/conflict_detector.d.ts +1 -1
  96. package/dist/knowledge/conflict_detector.d.ts.map +1 -1
  97. package/dist/knowledge/conflict_detector.js +86 -2
  98. package/dist/knowledge/conflict_detector.js.map +1 -1
  99. package/dist/types.d.ts +14 -0
  100. package/dist/types.d.ts.map +1 -1
  101. package/package.json +1 -1
  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 +1 -1
  103. 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
  104. 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 +103 -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 +13 -0
  106. 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
  107. 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
  108. 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
  109. 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 +12 -0
  110. 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) {
@@ -2101,11 +2101,43 @@ async function checkReleaseIssueDesignPath(rootDir, hardFail, _info) {
2101
2101
  !toolsText.includes("TOOL_DIAGNOSTIC_CODES.traceabilityVerifyFailed")) {
2102
2102
  hardFail("RELEASE_ISSUE_TRACEABILITY_MAINLINE_MISSING", "问题七十三追踪契约未接入 sf_expand/sf_verify 主链路", ["src/adapters/claude_code/tools.ts", "src/engine/traceability.ts"], "problem-73", "只审计设计产物不能保证编码来自需求、原型、架构、详细设计和切片", "在 sf_expand 编码前门和 sf_verify changed_files 门接入追踪契约");
2103
2103
  }
2104
+ const traceabilityText = safeRead(path.join(rootDir, "src", "engine", "traceability.ts")) ?? "";
2105
+ const nextPlannerText = safeRead(path.join(rootDir, "src", "engine", "next_action_planner.ts")) ?? "";
2106
+ if (!traceabilityText.includes("DESIGN_IMPLEMENTATION_TRACEABILITY_TEMPLATE_PATH") ||
2107
+ !traceabilityText.includes("recovery_command") ||
2108
+ !traceabilityText.includes("recovery_zh") ||
2109
+ !nextPlannerText.includes("DESIGN_IMPLEMENTATION_TRACEABILITY_TEMPLATE_PATH") ||
2110
+ !cliText.includes("finding.template_path") ||
2111
+ !cliText.includes("finding.recovery_command")) {
2112
+ hardFail("RELEASE_ISSUE_TRACEABILITY_RECOVERY_PATH_MISSING", "问题七十三追踪矩阵强门禁缺少模板/引导/审计恢复路径", ["src/engine/traceability.ts", "src/engine/next_action_planner.ts", "src/bin/soloforge.ts"], "problem-73", "强门禁只阻断不给模板和恢复命令会导致用户无法闭环", "为追踪矩阵 finding、soloforge next 和 audit-design-artifacts 输出模板路径与恢复命令");
2113
+ }
2104
2114
  const designPackText = safeRead(path.join(rootDir, "src", "engine", "design_artifact_pack.ts")) ?? "";
2105
2115
  if (!designPackText.includes("traceability_matrix") ||
2106
2116
  !designPackText.includes("auditDesignImplementationTraceability")) {
2107
2117
  hardFail("RELEASE_ISSUE_TRACEABILITY_DESIGN_AUDIT_MISSING", "问题七十三未并入设计产物包审计", ["src/engine/design_artifact_pack.ts"], "problem-73", "追踪矩阵不进入 audit-design-artifacts 会导致用户设计阶段无法发现缺口", "把追踪矩阵作为设计产物包权威资产审计");
2108
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
+ }
2109
2141
  if (!cliText.includes("cmdAuditDesignArtifacts") ||
2110
2142
  !cliText.includes("cmdUpgradeDesignArtifacts") ||
2111
2143
  !cliText.includes("currentTask?.design_artifact_pack")) {
@@ -2139,6 +2171,26 @@ async function checkReleaseIssueDesignPath(rootDir, hardFail, _info) {
2139
2171
  try {
2140
2172
  const workshop = await import(path.join(rootDir, "dist", "engine", "architecture_decision_workshop.js"));
2141
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
+ }
2142
2194
  const draft = workshop.createArchitectureDecisionWorkshop("release-issue", "new_system");
2143
2195
  if (workshop.evaluateArchitectureDecisionWorkshop(draft).allowed) {
2144
2196
  hardFail("RELEASE_ISSUE_BEHAVIOR_FALSE_PASS", "问题六十一未确认六域的草稿错误放行", ["src/engine/architecture_decision_workshop.ts"], "problem-61", "必须有负向行为证据", "修复研讨生成门");
@@ -2163,29 +2215,30 @@ async function checkReleaseIssueDesignPath(rootDir, hardFail, _info) {
2163
2215
  "# 需求原型设计实现追踪矩阵",
2164
2216
  "| 需求 | 原型 | 架构 | 详细设计 | 切片 | 验收 |",
2165
2217
  "| --- | --- | --- | --- | --- | --- |",
2166
- "| 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 |",
2167
2219
  ].join("\n"));
2168
- write("docs/architecture/04-详细设计文档.md", "# 详细设计\nARCH-001 -> DD-001");
2169
- 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");
2170
2223
  const bindingFail = traceability.verifyChangedFilesAgainstDesignTraceability(tmp, ["src/main/java/demo/BedService.java"], {
2171
2224
  task_id: "trace-gate",
2172
2225
  created_at: new Date().toISOString(),
2173
- intent: "实现床位管理",
2226
+ intent: "实现资源管理",
2174
2227
  product_profile: "default",
2175
2228
  status: "executing",
2176
2229
  });
2177
2230
  if (bindingFail.passed || !bindingFail.findings.some((f) => f.code === "TRACEABILITY_CODE_BINDING_MISSING")) {
2178
- 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 追踪绑定门");
2179
2232
  }
2180
2233
  const bindingPass = traceability.verifyChangedFilesAgainstDesignTraceability(tmp, ["src/main/java/demo/BedService.java"], {
2181
2234
  task_id: "trace-gate-ok",
2182
2235
  created_at: new Date().toISOString(),
2183
- intent: "实现床位管理 SLICE-001 DD-001 AC-001",
2236
+ intent: "实现资源管理 PHASE-001 SLICE-001 DD-T001 DD-A001 AC-001",
2184
2237
  product_profile: "default",
2185
2238
  status: "executing",
2186
2239
  });
2187
2240
  if (!bindingPass.passed) {
2188
- 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 校验");
2189
2242
  }
2190
2243
  }
2191
2244
  catch (error) {
@@ -2529,26 +2582,26 @@ async function checkCodeObservabilityBehavior(rootDir, hardFail, _info) {
2529
2582
  }
2530
2583
  // 行为验证: 普通 Spring 后端 Slice 的 CRUD/事务双写无日志无注释也必须被检测。
2531
2584
  const smartCareSliceFindings = obs.verifyChangedFilesObservability({
2532
- 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"],
2533
2586
  file_contents: {
2534
- "src/main/java/com/smartcare/staff/service/impl/StaffServiceImpl.java": `@Service
2535
- public class StaffServiceImpl implements StaffService {
2587
+ "src/main/java/com/demoapp/account/service/impl/AccountServiceImpl.java": `@Service
2588
+ public class AccountServiceImpl implements AccountService {
2536
2589
  @Transactional
2537
- public StaffVO create(StaffCreateRequest request) {
2538
- Staff staff = convert(request);
2539
- staffMapper.insert(staff);
2590
+ public AccountVO create(AccountCreateRequest request) {
2591
+ Account account = convert(request);
2592
+ accountMapper.insert(account);
2540
2593
  SysUser user = buildUser(request);
2541
2594
  sysUserMapper.insert(user);
2542
- return toVO(staff);
2595
+ return toVO(account);
2543
2596
  }
2544
2597
  @Transactional
2545
- public void resign(Long staffId) {
2546
- staffMapper.updateStatus(staffId, StaffStatus.RESIGNED);
2547
- sysUserMapper.updateAccountStatus(staffId, 0);
2598
+ public void resign(Long accountId) {
2599
+ accountMapper.updateStatus(accountId, AccountStatus.RESIGNED);
2600
+ sysUserMapper.updateAccountStatus(accountId, 0);
2548
2601
  }
2549
2602
  }`,
2550
2603
  },
2551
- intent: "完成 Slice 2 机构设施与员工管理后端实现",
2604
+ intent: "完成 Slice 2 资源目录与账号管理后端实现",
2552
2605
  });
2553
2606
  const smartCareBlocked = smartCareSliceFindings.some((f) => f.category === "missing_log_business_write" && f.severity === "hard_fail")
2554
2607
  && smartCareSliceFindings.some((f) => f.category === "missing_comment_complex");
@@ -2556,46 +2609,46 @@ public class StaffServiceImpl implements StaffService {
2556
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");
2557
2610
  }
2558
2611
  const javaDocAndChineseFindings = obs.verifyChangedFilesObservability({
2559
- 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"],
2560
2613
  file_contents: {
2561
- "src/main/java/com/smartcare/staff/service/impl/StaffServiceImpl.java": `@Service
2562
- public class StaffServiceImpl implements StaffService {
2563
- public StaffVO create(StaffCreateRequest request) {
2564
- Staff staff = convert(request);
2565
- staffMapper.insert(staff);
2566
- logger.info("staff created staffId=" + staff.getId());
2567
- 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);
2568
2621
  }
2569
2622
  }`,
2570
2623
  },
2571
- intent: "完成 Slice 2 员工管理后端实现",
2624
+ intent: "完成 Slice 2 账号管理后端实现",
2572
2625
  });
2573
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"));
2574
2627
  if (!javaDocAndChineseBlocked) {
2575
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 和关键行注释");
2576
2629
  }
2577
2630
  const crossStackFindings = obs.verifyChangedFilesObservability({
2578
- 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"],
2579
2632
  file_contents: {
2580
- "src/routes/staff.route.ts": `router.post('/staff', async (req, res) => {
2581
- const staff = await staffRepo.create(req.body);
2582
- await userRepo.create({ staffId: staff.id });
2583
- 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);
2584
2637
  });`,
2585
- "app/api/staff.py": `@router.post("/staff")
2586
- async def create_staff(payload: StaffCreate):
2587
- staff = await staff_repo.create(payload)
2588
- await user_repo.create(staff_id=staff.id)
2589
- return staff`,
2590
- "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() {
2591
2644
  async function handleSubmit(values) {
2592
- await apiClient.post('/api/institution/staff', values);
2645
+ await apiClient.post('/api/tenant/users', values);
2593
2646
  setStatus('created');
2594
2647
  }
2595
2648
  return <form onSubmit={handleSubmit}>...</form>;
2596
2649
  }`,
2597
2650
  },
2598
- intent: "实现员工新增前后端接口与表单",
2651
+ intent: "实现账号新增前后端接口与表单",
2599
2652
  });
2600
2653
  const crossStackBlocked = crossStackFindings.filter((f) => f.category === "missing_log_business_write" && f.severity === "hard_fail").length >= 3;
2601
2654
  if (!crossStackBlocked) {
@@ -2753,7 +2806,7 @@ async function checkTemplateAndProjectKnowledgeHygiene(rootDir, hardFail, _info)
2753
2806
  }
2754
2807
  try {
2755
2808
  const obs = await import(path.join(rootDir, "dist", "engine", "code_maintainability_observability_contract.js"));
2756
- const ordinaryApiImplementationTriggers = obs.requiresCodeObservabilityContract?.("实现机构端入住列表接口", "code_change") === true;
2809
+ const ordinaryApiImplementationTriggers = obs.requiresCodeObservabilityContract?.("实现业务端业务办理列表接口", "code_change") === true;
2757
2810
  if (!ordinaryApiImplementationTriggers) {
2758
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 聚合返回工作包");
2759
2812
  }
@@ -2766,7 +2819,7 @@ async function checkTemplateAndProjectKnowledgeHygiene(rootDir, hardFail, _info)
2766
2819
  const goodDir = path.join(tmp, ".soloforge", "knowledge", "rules");
2767
2820
  fs.mkdirSync(goodDir, { recursive: true });
2768
2821
  fs.writeFileSync(path.join(goodDir, "API响应规则.md"), `---
2769
- id: smartcare-api-response-rule
2822
+ id: demo-api-response-rule
2770
2823
  asset_kind: hard_rule
2771
2824
  routes:
2772
2825
  - code_change
@@ -2785,21 +2838,56 @@ enforcement:
2785
2838
  必须使用项目统一响应结构,错误码、字段表和 OpenAPI 保持一致。
2786
2839
  `, "utf-8");
2787
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"));
2788
2842
  const report = projectKnowledge.auditProjectKnowledge(tmp);
2789
2843
  if (report.hard_fail_count !== 0 || report.injectable < 1) {
2790
2844
  hardFail("PROJECT_KNOWLEDGE_RULE_NOT_CONSUMABLE", "用户项目 .soloforge/knowledge hard rule 未被识别为可消费规则", ["src/engine/project_knowledge_contract.ts"], "project-knowledge-consumption", "旧链路只同步/索引内置模板,未证明用户项目自定义规则可被承载消费", "修复项目知识合同审计与选择逻辑");
2791
2845
  }
2792
- const selected = projectKnowledge.selectProjectKnowledgeForTask(report, {
2793
- intent: "实现机构端 API 接口统一响应",
2846
+ const selected = projectKnowledge.selectProjectKnowledgeForTaskWithReasons(report, {
2847
+ intent: "实现业务端 API 接口统一响应",
2794
2848
  route: "code_change",
2795
2849
  tech_stack: ["spring"],
2796
2850
  });
2797
- if (!selected.some((asset) => asset.id === "smartcare-api-response-rule")) {
2851
+ if (!selected.selected.some((decision) => decision.asset.id === "demo-api-response-rule")) {
2798
2852
  hardFail("PROJECT_KNOWLEDGE_RULE_NOT_SELECTED", "用户项目自定义 hard rule 未按意图/路由/技术栈被选中", ["src/engine/project_knowledge_contract.ts"], "project-knowledge-consumption", "索引存在不等于任务会消费", "补齐 selectProjectKnowledgeForTask 行为和门禁");
2799
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
+ }
2800
2888
  const expander = await import(path.join(rootDir, "dist", "engine", "intent_expander.js"));
2801
2889
  const expandResult = await expander.expand({
2802
- intent: "实现机构端 API 接口统一响应",
2890
+ intent: "实现业务端 API 接口统一响应",
2803
2891
  classification: {
2804
2892
  task_type: "feature",
2805
2893
  risk: "low",
@@ -2842,8 +2930,10 @@ enforcement:
2842
2930
  decision_version: 1,
2843
2931
  },
2844
2932
  });
2845
- if (!expandResult.project_knowledge?.selected?.some((asset) => asset.id === "smartcare-api-response-rule")
2846
- || !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)) {
2847
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 并补主链路测试");
2848
2938
  }
2849
2939
  const nextPlanner = await import(path.join(rootDir, "dist", "engine", "next_action_planner.js"));
@@ -2851,11 +2941,24 @@ enforcement:
2851
2941
  if (!nextPlan.project_knowledge_context || nextPlan.project_knowledge_context.total < 1) {
2852
2942
  hardFail("PROJECT_KNOWLEDGE_NOT_IN_NEXT", "soloforge next 未携带项目知识上下文,用户无法知道下一步会应用哪些项目规则", ["src/engine/next_action_planner.ts", "src/bin/soloforge.ts"], "project-knowledge-consumption", "旧导航只看阶段,不看项目规则", "将项目知识上下文接入 next JSON 和人类输出");
2853
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
+ }
2854
2948
  const badTmp = fs.mkdtempSync(path.join(os.tmpdir(), "soloforge-project-knowledge-bad-"));
2855
2949
  try {
2856
2950
  const badDir = path.join(badTmp, ".soloforge", "knowledge", "rules");
2857
2951
  fs.mkdirSync(badDir, { recursive: true });
2858
- 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");
2859
2962
  const badReport = projectKnowledge.auditProjectKnowledge(badTmp);
2860
2963
  if (badReport.hard_fail_count === 0) {
2861
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");
@@ -2904,6 +3007,42 @@ enforcement:
2904
3007
  finally {
2905
3008
  fs.rmSync(conflictTmp, { recursive: true, force: true });
2906
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
+ }
2907
3046
  }
2908
3047
  catch (e) {
2909
3048
  hardFail("PROJECT_KNOWLEDGE_AUDIT_FAILED", `用户项目知识消费行为审计执行失败: ${e.message}`, ["src/engine/project_knowledge_contract.ts"], "project-knowledge-consumption", "项目知识消费必须有可执行行为门禁", "修复项目知识合同模块和编译产物");
@@ -3066,8 +3205,24 @@ async function checkControlPlaneTrustBehavior(rootDir, hardFail) {
3066
3205
  }
3067
3206
  if (!cliText.includes("仍处于 ${currentTask.status}") ||
3068
3207
  !cliText.includes("缺少 design_artifact_pack") ||
3069
- !cliText.includes("没有受控 SoloForge 任务")) {
3070
- hardFail("CONTROLLED_IMPLEMENTATION_WRITE_GATE_MISSING", "check-write 未覆盖 expanding 卡死、设计产物存在但缺 design_artifact_pack、无受控任务三类直接编码旁路", ["src/bin/soloforge.ts"], "problem-72", "旧 gate 只在交付层发现非 MCP 来源,未在写入入口阻断真实用户项目旁路", "在 check-write 对业务实现文件增加受控任务与设计产物包前置门");
3208
+ !cliText.includes("没有受控 SoloForge 任务") ||
3209
+ !cliText.includes("不得取消/归档当前任务后改用 Bash/Edit/Write") ||
3210
+ !cliText.includes("禁止通过 Bash 直接写业务实现文件")) {
3211
+ hardFail("CONTROLLED_IMPLEMENTATION_WRITE_GATE_MISSING", "check-write/check-bash 未覆盖 expanding 卡死、设计产物存在但缺 design_artifact_pack、无受控任务和 Bash 直接编码旁路", ["src/bin/soloforge.ts"], "problem-72", "旧 gate 只在交付层发现非 MCP 来源,未在写入入口阻断真实用户项目旁路", "在 check-write/check-bash 对业务实现文件增加受控任务与设计产物包前置门");
3212
+ }
3213
+ const assetManifestText = safeRead(path.join(rootDir, "src", "engine", "asset_manifest.ts")) ?? "";
3214
+ const workflowRuleText = safeRead(path.join(rootDir, "templates", "knowledge", "rules", "工作流导航契约规则.md")) ?? "";
3215
+ const lifecycleProcedureText = safeRead(path.join(rootDir, "templates", "knowledge", "procedures", "全生命周期工作流导航.md")) ?? "";
3216
+ const antiBypassNeedles = [
3217
+ "不得建议取消任务后直接写",
3218
+ "不得建议“先用 Bash 直接修改业务代码”",
3219
+ "不得手动删除 `.soloforge/state`",
3220
+ "归档后仍必须重新 `sf_classify -> sf_expand`",
3221
+ ];
3222
+ const antiBypassText = `${assetManifestText}\n${workflowRuleText}\n${lifecycleProcedureText}`;
3223
+ const missingAntiBypassNeedles = antiBypassNeedles.filter((needle) => !antiBypassText.includes(needle));
3224
+ if (missingAntiBypassNeedles.length > 0) {
3225
+ hardFail("CONTROL_PLANE_BLOCKED_RECOVERY_PROMPT_MISSING", `适配器/知识规则缺少阻断恢复反旁路硬规则: ${missingAntiBypassNeedles.join(", ")}`, ["src/engine/asset_manifest.ts", "templates/knowledge/rules/工作流导航契约规则.md", "templates/knowledge/procedures/全生命周期工作流导航.md"], "problem-72", "运行时 hook 能拦截写入,但模型仍可能口头建议取消任务、Bash 直写或手动清状态", "把阻断恢复反旁路协议注入 adapter workflow 和工作流导航知识资产");
3071
3226
  }
3072
3227
  }
3073
3228
  catch (e) {