soloforge 1.1.45 → 1.1.46

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 (269) hide show
  1. package/README.md +3 -3
  2. package/dist/context/contracts/lifecycle_knowledge_contract.d.ts.map +1 -1
  3. package/dist/context/contracts/lifecycle_knowledge_contract.js +2 -2
  4. package/dist/context/contracts/lifecycle_knowledge_contract.js.map +1 -1
  5. package/dist/core/task_context/manager.d.ts +0 -8
  6. package/dist/core/task_context/manager.d.ts.map +1 -1
  7. package/dist/core/task_context/manager.js +1 -19
  8. package/dist/core/task_context/manager.js.map +1 -1
  9. package/dist/core/task_context/state_fact_classifier.d.ts +0 -8
  10. package/dist/core/task_context/state_fact_classifier.d.ts.map +1 -1
  11. package/dist/core/task_context/state_fact_classifier.js +0 -36
  12. package/dist/core/task_context/state_fact_classifier.js.map +1 -1
  13. package/dist/domain/contracts/design_artifact_pack.d.ts +0 -1
  14. package/dist/domain/contracts/design_artifact_pack.d.ts.map +1 -1
  15. package/dist/domain/contracts/design_artifact_pack.js +1 -4
  16. package/dist/domain/contracts/design_artifact_pack.js.map +1 -1
  17. package/dist/domain/index.d.ts +1 -1
  18. package/dist/domain/index.d.ts.map +1 -1
  19. package/dist/domain/registry.d.ts +2 -2
  20. package/dist/domain/registry.d.ts.map +1 -1
  21. package/dist/domain/types.d.ts +1 -12
  22. package/dist/domain/types.d.ts.map +1 -1
  23. package/dist/domain/types.js +3 -0
  24. package/dist/domain/types.js.map +1 -1
  25. package/dist/gate/contracts/capability_registry.d.ts.map +1 -1
  26. package/dist/gate/contracts/capability_registry.js +0 -26
  27. package/dist/gate/contracts/capability_registry.js.map +1 -1
  28. package/dist/gate/contracts/control_plane_contract.d.ts +1 -1
  29. package/dist/gate/contracts/control_plane_contract.d.ts.map +1 -1
  30. package/dist/gate/contracts/control_plane_contract.js +1 -10
  31. package/dist/gate/contracts/control_plane_contract.js.map +1 -1
  32. package/dist/gate/contracts/tool_invocation_contract_registry.d.ts +1 -0
  33. package/dist/gate/contracts/tool_invocation_contract_registry.d.ts.map +1 -1
  34. package/dist/gate/contracts/tool_invocation_contract_registry.js +1 -1
  35. package/dist/gate/contracts/tool_invocation_contract_registry.js.map +1 -1
  36. package/dist/gate/index.d.ts +0 -2
  37. package/dist/gate/index.d.ts.map +1 -1
  38. package/dist/gate/index.js +0 -1
  39. package/dist/gate/index.js.map +1 -1
  40. package/dist/server/tools/index.d.ts.map +1 -1
  41. package/dist/server/tools/index.js +1 -3
  42. package/dist/server/tools/index.js.map +1 -1
  43. package/dist/server/tools/lazy_loaders.d.ts +0 -23
  44. package/dist/server/tools/lazy_loaders.d.ts.map +1 -1
  45. package/dist/server/tools/lazy_loaders.js +2 -33
  46. package/dist/server/tools/lazy_loaders.js.map +1 -1
  47. package/dist/server/tools/middleware.d.ts +2 -5
  48. package/dist/server/tools/middleware.d.ts.map +1 -1
  49. package/dist/server/tools/middleware.js +3 -33
  50. package/dist/server/tools/middleware.js.map +1 -1
  51. package/dist/server/tools/sf_task.js +2 -7
  52. package/dist/server/tools/sf_task.js.map +1 -1
  53. package/dist/server/tools/types.d.ts +0 -2
  54. package/dist/server/tools/types.d.ts.map +1 -1
  55. package/dist/types/pipeline_types.d.ts +1 -9
  56. package/dist/types/pipeline_types.d.ts.map +1 -1
  57. package/dist/verify/audit/verifier.d.ts.map +1 -1
  58. package/dist/verify/audit/verifier.js +0 -33
  59. package/dist/verify/audit/verifier.js.map +1 -1
  60. package/dist/verify/index.d.ts +1 -4
  61. package/dist/verify/index.d.ts.map +1 -1
  62. package/dist/verify/index.js +0 -3
  63. package/dist/verify/index.js.map +1 -1
  64. package/dist/verify/types.d.ts +0 -21
  65. package/dist/verify/types.d.ts.map +1 -1
  66. package/package.json +1 -1
  67. package/templates/shared//345/206/263/347/255/226/347/275/221/345/205/263.md +7 -21
  68. package/dist/context/engine/dependency_scanner.d.ts +0 -23
  69. package/dist/context/engine/dependency_scanner.d.ts.map +0 -1
  70. package/dist/context/engine/dependency_scanner.js +0 -309
  71. package/dist/context/engine/dependency_scanner.js.map +0 -1
  72. package/dist/context/engine/exploration.d.ts +0 -194
  73. package/dist/context/engine/exploration.d.ts.map +0 -1
  74. package/dist/context/engine/exploration.js +0 -712
  75. package/dist/context/engine/exploration.js.map +0 -1
  76. package/dist/context/knowledge/knowledge_acceptance_registry.d.ts +0 -42
  77. package/dist/context/knowledge/knowledge_acceptance_registry.d.ts.map +0 -1
  78. package/dist/context/knowledge/knowledge_acceptance_registry.js +0 -249
  79. package/dist/context/knowledge/knowledge_acceptance_registry.js.map +0 -1
  80. package/dist/context/knowledge/knowledge_scenario_registry.d.ts +0 -26
  81. package/dist/context/knowledge/knowledge_scenario_registry.d.ts.map +0 -1
  82. package/dist/context/knowledge/knowledge_scenario_registry.js +0 -267
  83. package/dist/context/knowledge/knowledge_scenario_registry.js.map +0 -1
  84. package/dist/context/knowledge/knowledge_sovereignty.d.ts +0 -65
  85. package/dist/context/knowledge/knowledge_sovereignty.d.ts.map +0 -1
  86. package/dist/context/knowledge/knowledge_sovereignty.js +0 -199
  87. package/dist/context/knowledge/knowledge_sovereignty.js.map +0 -1
  88. package/dist/context/team_awareness.d.ts +0 -42
  89. package/dist/context/team_awareness.d.ts.map +0 -1
  90. package/dist/context/team_awareness.js +0 -154
  91. package/dist/context/team_awareness.js.map +0 -1
  92. package/dist/context/templates/template_asset_visibility.d.ts +0 -116
  93. package/dist/context/templates/template_asset_visibility.d.ts.map +0 -1
  94. package/dist/context/templates/template_asset_visibility.js +0 -310
  95. package/dist/context/templates/template_asset_visibility.js.map +0 -1
  96. package/dist/gate/conflict_gate.d.ts +0 -53
  97. package/dist/gate/conflict_gate.d.ts.map +0 -1
  98. package/dist/gate/conflict_gate.js +0 -96
  99. package/dist/gate/conflict_gate.js.map +0 -1
  100. package/dist/gate/contracts/capability_action_advisor.d.ts +0 -34
  101. package/dist/gate/contracts/capability_action_advisor.d.ts.map +0 -1
  102. package/dist/gate/contracts/capability_action_advisor.js +0 -165
  103. package/dist/gate/contracts/capability_action_advisor.js.map +0 -1
  104. package/dist/gate/contracts/capability_state_store.d.ts +0 -121
  105. package/dist/gate/contracts/capability_state_store.d.ts.map +0 -1
  106. package/dist/gate/contracts/capability_state_store.js +0 -188
  107. package/dist/gate/contracts/capability_state_store.js.map +0 -1
  108. package/dist/gate/contracts/contract_guard.d.ts +0 -50
  109. package/dist/gate/contracts/contract_guard.d.ts.map +0 -1
  110. package/dist/gate/contracts/contract_guard.js +0 -611
  111. package/dist/gate/contracts/contract_guard.js.map +0 -1
  112. package/dist/gate/contracts/escape_report.d.ts +0 -103
  113. package/dist/gate/contracts/escape_report.d.ts.map +0 -1
  114. package/dist/gate/contracts/escape_report.js +0 -145
  115. package/dist/gate/contracts/escape_report.js.map +0 -1
  116. package/dist/gate/feasibility_checker.d.ts +0 -27
  117. package/dist/gate/feasibility_checker.d.ts.map +0 -1
  118. package/dist/gate/feasibility_checker.js +0 -114
  119. package/dist/gate/feasibility_checker.js.map +0 -1
  120. package/dist/gate/migration_guard.d.ts +0 -22
  121. package/dist/gate/migration_guard.d.ts.map +0 -1
  122. package/dist/gate/migration_guard.js +0 -277
  123. package/dist/gate/migration_guard.js.map +0 -1
  124. package/dist/gate/scope_lease.d.ts +0 -94
  125. package/dist/gate/scope_lease.d.ts.map +0 -1
  126. package/dist/gate/scope_lease.js +0 -180
  127. package/dist/gate/scope_lease.js.map +0 -1
  128. package/dist/git/git_deps.d.ts +0 -85
  129. package/dist/git/git_deps.d.ts.map +0 -1
  130. package/dist/git/git_deps.js +0 -22
  131. package/dist/git/git_deps.js.map +0 -1
  132. package/dist/git/operations.d.ts +0 -173
  133. package/dist/git/operations.d.ts.map +0 -1
  134. package/dist/git/operations.js +0 -350
  135. package/dist/git/operations.js.map +0 -1
  136. package/dist/server/tools/gate_engine.d.ts +0 -17
  137. package/dist/server/tools/gate_engine.d.ts.map +0 -1
  138. package/dist/server/tools/gate_engine.js +0 -17
  139. package/dist/server/tools/gate_engine.js.map +0 -1
  140. package/dist/server/tools/middleware/budget_check.d.ts +0 -35
  141. package/dist/server/tools/middleware/budget_check.d.ts.map +0 -1
  142. package/dist/server/tools/middleware/budget_check.js +0 -69
  143. package/dist/server/tools/middleware/budget_check.js.map +0 -1
  144. package/dist/shared/contracts/contract_registry/builtin_contracts_core.d.ts +0 -16
  145. package/dist/shared/contracts/contract_registry/builtin_contracts_core.d.ts.map +0 -1
  146. package/dist/shared/contracts/contract_registry/builtin_contracts_core.js +0 -306
  147. package/dist/shared/contracts/contract_registry/builtin_contracts_core.js.map +0 -1
  148. package/dist/shared/contracts/contract_registry/builtin_contracts_core_2.d.ts +0 -16
  149. package/dist/shared/contracts/contract_registry/builtin_contracts_core_2.d.ts.map +0 -1
  150. package/dist/shared/contracts/contract_registry/builtin_contracts_core_2.js +0 -304
  151. package/dist/shared/contracts/contract_registry/builtin_contracts_core_2.js.map +0 -1
  152. package/dist/shared/contracts/contract_registry/builtin_contracts_extended.d.ts +0 -16
  153. package/dist/shared/contracts/contract_registry/builtin_contracts_extended.d.ts.map +0 -1
  154. package/dist/shared/contracts/contract_registry/builtin_contracts_extended.js +0 -434
  155. package/dist/shared/contracts/contract_registry/builtin_contracts_extended.js.map +0 -1
  156. package/dist/shared/contracts/contract_registry/index.d.ts +0 -8
  157. package/dist/shared/contracts/contract_registry/index.d.ts.map +0 -1
  158. package/dist/shared/contracts/contract_registry/index.js +0 -7
  159. package/dist/shared/contracts/contract_registry/index.js.map +0 -1
  160. package/dist/shared/contracts/contract_registry/registry.d.ts +0 -62
  161. package/dist/shared/contracts/contract_registry/registry.d.ts.map +0 -1
  162. package/dist/shared/contracts/contract_registry/registry.js +0 -191
  163. package/dist/shared/contracts/contract_registry/registry.js.map +0 -1
  164. package/dist/shared/contracts/contract_registry/registry_internal.d.ts +0 -19
  165. package/dist/shared/contracts/contract_registry/registry_internal.d.ts.map +0 -1
  166. package/dist/shared/contracts/contract_registry/registry_internal.js +0 -54
  167. package/dist/shared/contracts/contract_registry/registry_internal.js.map +0 -1
  168. package/dist/shared/contracts/contract_registry/types.d.ts +0 -47
  169. package/dist/shared/contracts/contract_registry/types.d.ts.map +0 -1
  170. package/dist/shared/contracts/contract_registry/types.js +0 -5
  171. package/dist/shared/contracts/contract_registry/types.js.map +0 -1
  172. package/dist/shared/contracts/contract_registry/validation.d.ts +0 -25
  173. package/dist/shared/contracts/contract_registry/validation.d.ts.map +0 -1
  174. package/dist/shared/contracts/contract_registry/validation.js +0 -363
  175. package/dist/shared/contracts/contract_registry/validation.js.map +0 -1
  176. package/dist/shared/llm_gateway.d.ts +0 -186
  177. package/dist/shared/llm_gateway.d.ts.map +0 -1
  178. package/dist/shared/llm_gateway.js +0 -393
  179. package/dist/shared/llm_gateway.js.map +0 -1
  180. package/dist/verify/audit/audit_sampler.d.ts +0 -29
  181. package/dist/verify/audit/audit_sampler.d.ts.map +0 -1
  182. package/dist/verify/audit/audit_sampler.js +0 -42
  183. package/dist/verify/audit/audit_sampler.js.map +0 -1
  184. package/dist/verify/audit/debt_reporter.d.ts +0 -22
  185. package/dist/verify/audit/debt_reporter.d.ts.map +0 -1
  186. package/dist/verify/audit/debt_reporter.js +0 -107
  187. package/dist/verify/audit/debt_reporter.js.map +0 -1
  188. package/dist/verify/audit/debugger.d.ts +0 -25
  189. package/dist/verify/audit/debugger.d.ts.map +0 -1
  190. package/dist/verify/audit/debugger.js +0 -429
  191. package/dist/verify/audit/debugger.js.map +0 -1
  192. package/dist/verify/audit/degradation.d.ts +0 -62
  193. package/dist/verify/audit/degradation.d.ts.map +0 -1
  194. package/dist/verify/audit/degradation.js +0 -78
  195. package/dist/verify/audit/degradation.js.map +0 -1
  196. package/dist/verify/audit/developer_sovereignty.d.ts +0 -29
  197. package/dist/verify/audit/developer_sovereignty.d.ts.map +0 -1
  198. package/dist/verify/audit/developer_sovereignty.js +0 -137
  199. package/dist/verify/audit/developer_sovereignty.js.map +0 -1
  200. package/dist/verify/audit/failure_report.d.ts +0 -76
  201. package/dist/verify/audit/failure_report.d.ts.map +0 -1
  202. package/dist/verify/audit/failure_report.js +0 -145
  203. package/dist/verify/audit/failure_report.js.map +0 -1
  204. package/dist/verify/audit/governance_report.d.ts +0 -110
  205. package/dist/verify/audit/governance_report.d.ts.map +0 -1
  206. package/dist/verify/audit/governance_report.js +0 -194
  207. package/dist/verify/audit/governance_report.js.map +0 -1
  208. package/dist/verify/audit/mutation_audit.d.ts +0 -40
  209. package/dist/verify/audit/mutation_audit.d.ts.map +0 -1
  210. package/dist/verify/audit/mutation_audit.js +0 -154
  211. package/dist/verify/audit/mutation_audit.js.map +0 -1
  212. package/dist/verify/audit/risk_sampler.d.ts +0 -44
  213. package/dist/verify/audit/risk_sampler.d.ts.map +0 -1
  214. package/dist/verify/audit/risk_sampler.js +0 -80
  215. package/dist/verify/audit/risk_sampler.js.map +0 -1
  216. package/dist/verify/audit/runtime_safety.d.ts +0 -89
  217. package/dist/verify/audit/runtime_safety.d.ts.map +0 -1
  218. package/dist/verify/audit/runtime_safety.js +0 -209
  219. package/dist/verify/audit/runtime_safety.js.map +0 -1
  220. package/dist/verify/audit/semantic_evidence.d.ts +0 -36
  221. package/dist/verify/audit/semantic_evidence.d.ts.map +0 -1
  222. package/dist/verify/audit/semantic_evidence.js +0 -90
  223. package/dist/verify/audit/semantic_evidence.js.map +0 -1
  224. package/dist/verify/audit/test_generator.d.ts +0 -23
  225. package/dist/verify/audit/test_generator.d.ts.map +0 -1
  226. package/dist/verify/audit/test_generator.js +0 -278
  227. package/dist/verify/audit/test_generator.js.map +0 -1
  228. package/dist/verify/audit/test_quality.d.ts +0 -49
  229. package/dist/verify/audit/test_quality.d.ts.map +0 -1
  230. package/dist/verify/audit/test_quality.js +0 -684
  231. package/dist/verify/audit/test_quality.js.map +0 -1
  232. package/dist/verify/change_coordinator.d.ts +0 -45
  233. package/dist/verify/change_coordinator.d.ts.map +0 -1
  234. package/dist/verify/change_coordinator.js +0 -168
  235. package/dist/verify/change_coordinator.js.map +0 -1
  236. package/dist/verify/contracts/decision_contract.d.ts +0 -51
  237. package/dist/verify/contracts/decision_contract.d.ts.map +0 -1
  238. package/dist/verify/contracts/decision_contract.js +0 -70
  239. package/dist/verify/contracts/decision_contract.js.map +0 -1
  240. package/dist/verify/contracts/mechanism_contract_registry/contracts-audit.d.ts +0 -17
  241. package/dist/verify/contracts/mechanism_contract_registry/contracts-audit.d.ts.map +0 -1
  242. package/dist/verify/contracts/mechanism_contract_registry/contracts-audit.js +0 -428
  243. package/dist/verify/contracts/mechanism_contract_registry/contracts-audit.js.map +0 -1
  244. package/dist/verify/contracts/mechanism_contract_registry/contracts-governance.d.ts +0 -17
  245. package/dist/verify/contracts/mechanism_contract_registry/contracts-governance.d.ts.map +0 -1
  246. package/dist/verify/contracts/mechanism_contract_registry/contracts-governance.js +0 -429
  247. package/dist/verify/contracts/mechanism_contract_registry/contracts-governance.js.map +0 -1
  248. package/dist/verify/contracts/mechanism_contract_registry/contracts-pipeline.d.ts +0 -17
  249. package/dist/verify/contracts/mechanism_contract_registry/contracts-pipeline.d.ts.map +0 -1
  250. package/dist/verify/contracts/mechanism_contract_registry/contracts-pipeline.js +0 -194
  251. package/dist/verify/contracts/mechanism_contract_registry/contracts-pipeline.js.map +0 -1
  252. package/dist/verify/contracts/mechanism_contract_registry/contracts-platform.d.ts +0 -17
  253. package/dist/verify/contracts/mechanism_contract_registry/contracts-platform.d.ts.map +0 -1
  254. package/dist/verify/contracts/mechanism_contract_registry/contracts-platform.js +0 -365
  255. package/dist/verify/contracts/mechanism_contract_registry/contracts-platform.js.map +0 -1
  256. package/dist/verify/contracts/mechanism_contract_registry/index.d.ts +0 -19
  257. package/dist/verify/contracts/mechanism_contract_registry/index.d.ts.map +0 -1
  258. package/dist/verify/contracts/mechanism_contract_registry/index.js +0 -21
  259. package/dist/verify/contracts/mechanism_contract_registry/index.js.map +0 -1
  260. package/dist/verify/contracts/mechanism_contract_registry/types.d.ts +0 -33
  261. package/dist/verify/contracts/mechanism_contract_registry/types.d.ts.map +0 -1
  262. package/dist/verify/contracts/mechanism_contract_registry/types.js +0 -5
  263. package/dist/verify/contracts/mechanism_contract_registry/types.js.map +0 -1
  264. package/dist/verify/contracts/mechanism_contract_registry/validation.d.ts +0 -38
  265. package/dist/verify/contracts/mechanism_contract_registry/validation.d.ts.map +0 -1
  266. package/dist/verify/contracts/mechanism_contract_registry/validation.js +0 -136
  267. package/dist/verify/contracts/mechanism_contract_registry/validation.js.map +0 -1
  268. package/templates/shared/LLM/351/242/204/347/256/227/347/275/221/345/205/263.md +0 -54
  269. package/templates/shared//346/265/201/345/274/217/345/277/203/350/267/263.md +0 -64
@@ -1,50 +0,0 @@
1
- /**
2
- * Contract Guard — 契约层模块。
3
- *
4
- * 职责边界:
5
- * - 负责:ContractGuardInput 等 契约层职责
6
- * - 不负责:不属于本模块的职责由对应模块承担
7
- *
8
- * 被谁调用:契约验证、注册表查询
9
- * 调用谁:index、git_deps、logger、helpers
10
- *
11
- * 数据流:契约定义 → 验证逻辑 → 通过/拒绝结果
12
- * 持久化:读写本地文件(详见代码内路径)
13
- */
14
- import type { ProjectConfig, ContractCheckResult } from "../../types/index.js";
15
- import type { GitOperations } from "../../git/git_deps.js";
16
- /**
17
- * 契约守卫 — 检测代码变更中的 API 契约破坏性变更。
18
- *
19
- * 通过解析 Git diff,识别以下类型的契约变更:
20
- * - API 端点的新增/删除(Spring MVC 注解、Express 路由)
21
- * - HTTP 方法的变更(同一路径上方法改变)
22
- * - DTO/Entity 字段的新增/删除/类型变更(Java 和 TypeScript)
23
- * - 跨服务影响分析(多仓库场景下评估对前端的冲击)
24
- */
25
- /** 契约守卫输入参数 */
26
- export interface ContractGuardInput {
27
- /** 变更文件列表 */
28
- changedFiles: string[];
29
- /** 项目路径 */
30
- projectPath: string;
31
- /** 项目配置 */
32
- config: ProjectConfig;
33
- /** Git 操作接口 */
34
- gitOps: GitOperations;
35
- }
36
- /**
37
- * 检测变更文件中的 API 契约变更。
38
- *
39
- * 处理流程:
40
- * 1. 筛选出与 API 契约相关的文件
41
- * 2. 获取每个文件的 Git diff
42
- * 3. 解析 diff 中的端点变更和字段变更
43
- * 4. 后处理:将同一路径的删除+新增配对为方法变更
44
- * 5. 评估跨服务影响并生成摘要
45
- *
46
- * @param input - 契约检查输入,包含变更文件列表、项目路径、配置和 Git 操作接口
47
- * @returns 契约检查结果,包含变更列表、破坏性/兼容性变更计数和跨服务影响
48
- */
49
- export declare function checkContractChanges(input: ContractGuardInput): Promise<ContractCheckResult>;
50
- //# sourceMappingURL=contract_guard.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"contract_guard.d.ts","sourceRoot":"","sources":["../../../src/gate/contracts/contract_guard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EACV,aAAa,EAEb,mBAAmB,EACpB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAI3D;;;;;;;;GAQG;AAEH,eAAe;AACf,MAAM,WAAW,kBAAkB;IACjC,aAAa;IACb,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,WAAW;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW;IACX,MAAM,EAAE,aAAa,CAAC;IACtB,eAAe;IACf,MAAM,EAAE,aAAa,CAAC;CACvB;AAkBD;;;;;;;;;;;;GAYG;AACH,wBAAsB,oBAAoB,CACxC,KAAK,EAAE,kBAAkB,GACxB,OAAO,CAAC,mBAAmB,CAAC,CAwE9B"}
@@ -1,611 +0,0 @@
1
- /**
2
- * Contract Guard — 契约层模块。
3
- *
4
- * 职责边界:
5
- * - 负责:ContractGuardInput 等 契约层职责
6
- * - 不负责:不属于本模块的职责由对应模块承担
7
- *
8
- * 被谁调用:契约验证、注册表查询
9
- * 调用谁:index、git_deps、logger、helpers
10
- *
11
- * 数据流:契约定义 → 验证逻辑 → 通过/拒绝结果
12
- * 持久化:读写本地文件(详见代码内路径)
13
- */
14
- import { debug } from "../../shared/logger.js";
15
- import { safeMatchGroups } from "../../shared/helpers.js";
16
- /**
17
- * API 契约文件路径关键词。
18
- * 文件路径(小写)包含这些关键词的,被视为 API 契约相关文件,需要进行 diff 解析。
19
- */
20
- const API_PATH_KEYWORDS = [
21
- "controller",
22
- "route",
23
- "api",
24
- "dto",
25
- "request",
26
- "response",
27
- "model",
28
- "entity",
29
- "schema",
30
- ];
31
- /**
32
- * 检测变更文件中的 API 契约变更。
33
- *
34
- * 处理流程:
35
- * 1. 筛选出与 API 契约相关的文件
36
- * 2. 获取每个文件的 Git diff
37
- * 3. 解析 diff 中的端点变更和字段变更
38
- * 4. 后处理:将同一路径的删除+新增配对为方法变更
39
- * 5. 评估跨服务影响并生成摘要
40
- *
41
- * @param input - 契约检查输入,包含变更文件列表、项目路径、配置和 Git 操作接口
42
- * @returns 契约检查结果,包含变更列表、破坏性/兼容性变更计数和跨服务影响
43
- */
44
- export async function checkContractChanges(input) {
45
- const { changedFiles, projectPath, config, gitOps } = input;
46
- debug("契约守卫", "开始检测契约变更");
47
- const changes = [];
48
- // 筛选出 API 契约相关文件(controller、dto、route 等)
49
- const contractFiles = changedFiles.filter((f) => isApiContractFile(f));
50
- if (contractFiles.length === 0) {
51
- debug("契约守卫", "无 API 契约文件变更,跳过检测");
52
- return emptyResult("No API contract files changed.");
53
- }
54
- // 收集每个契约文件的 diff 内容(仅暂存区的变更)
55
- const diffs = [];
56
- for (const file of contractFiles) {
57
- try {
58
- const diff = await gitOps.getDiffPatch(projectPath, file, {
59
- cached: true,
60
- });
61
- if (diff.trim()) {
62
- diffs.push({ file, diff });
63
- }
64
- }
65
- catch (e) {
66
- debug("契约守卫", "获取文件diff失败 —", e);
67
- // 跳过无法获取 diff 的文件
68
- }
69
- }
70
- if (diffs.length === 0) {
71
- debug("契约守卫", "API 契约文件无 diff 内容,跳过检测");
72
- return emptyResult("No diff content found in API contract files.");
73
- }
74
- // 解析每个 diff 中的契约变更(端点变更、字段变更等)
75
- for (const { file, diff } of diffs) {
76
- const parsed = parseDiffForContractChanges(file, diff);
77
- changes.push(...parsed);
78
- }
79
- // 统计破坏性变更和兼容性变更
80
- const breaking = changes.filter((c) => c.severity === "breaking");
81
- const compatible = changes.filter((c) => c.severity === "compatible");
82
- // 跨服务影响分析(仅在多仓库场景下有意义)
83
- const crossServiceImpact = analyzeCrossServiceImpact(breaking, config);
84
- const summary = buildSummary(changes.length, breaking.length, compatible.length, crossServiceImpact);
85
- if (breaking.length > 0) {
86
- debug("契约守卫", `检测到 ${breaking.length} 个破坏性变更,需要人工审查`);
87
- }
88
- else {
89
- debug("契约守卫", `检测完成,共 ${changes.length} 个变更(${breaking.length} 破坏性,${compatible.length} 兼容性)`);
90
- }
91
- return {
92
- changes,
93
- breaking_count: breaking.length,
94
- compatible_count: compatible.length,
95
- cross_service_impact: crossServiceImpact,
96
- requires_review: breaking.length > 0,
97
- summary,
98
- };
99
- }
100
- /**
101
- * 判断文件是否为 API 契约相关文件。
102
- * 通过路径关键词匹配,覆盖 controller、route、dto、schema 等类型。
103
- * @param filePath - 文件路径
104
- * @returns true 表示该文件属于 API 契约文件
105
- */
106
- function isApiContractFile(filePath) {
107
- const lower = filePath.toLowerCase();
108
- return API_PATH_KEYWORDS.some((kw) => lower.includes(kw));
109
- }
110
- /**
111
- * 解析 Git diff 内容,识别其中的 API 契约变更。
112
- *
113
- * 解析策略(按优先级):
114
- * 1. Spring MVC 注解变更(@GetMapping、@PostMapping 等)
115
- * 2. Express 路由变更(router.get()、router.post() 等)
116
- * 3. DTO/Entity 字段变更(Java 和 TypeScript 字段定义)
117
- *
118
- * 后处理步骤:将同一路径的 path_removed + path_added 配对为 method_changed。
119
- *
120
- * @param file - 文件路径
121
- * @param diff - Git diff 文本
122
- * @returns 契约变更列表
123
- */
124
- function parseDiffForContractChanges(file, diff) {
125
- const changes = [];
126
- const lines = diff.split("\n");
127
- // 已消费的行索引集合,防止同一行被多个规则重复匹配
128
- const consumedIndices = new Set();
129
- for (let i = 0; i < lines.length; i++) {
130
- if (consumedIndices.has(i))
131
- continue;
132
- const line = lines[i];
133
- // 仅处理新增行(+)和删除行(-),跳过 diff 元数据行(+++、---)
134
- const isAdded = line.startsWith("+") && !line.startsWith("+++");
135
- const isRemoved = line.startsWith("-") && !line.startsWith("---");
136
- if (!isAdded && !isRemoved)
137
- continue;
138
- const content = line.slice(1); // 去掉行首的 +/- 和空格,获取实际内容
139
- // 检测 1: Spring MVC 注解变更
140
- const springChange = detectSpringAnnotationChange(content, isAdded, isRemoved, file);
141
- if (springChange) {
142
- changes.push(springChange);
143
- continue;
144
- }
145
- // 检测 2: Express 路由变更
146
- const expressChange = detectExpressRouteChange(content, isAdded, isRemoved, file);
147
- if (expressChange) {
148
- changes.push(expressChange);
149
- continue;
150
- }
151
- // 检测 3: DTO/Entity 字段变更
152
- const fieldChange = detectFieldChange(content, isAdded, isRemoved, file, lines, i, consumedIndices);
153
- if (fieldChange) {
154
- changes.push(fieldChange);
155
- if (fieldChange.change_type === "field_type_changed" && isRemoved) {
156
- // 字段类型变更已检测到,继续正常处理
157
- }
158
- }
159
- }
160
- // 后处理:检测同一路径上的 HTTP 方法变更
161
- // 将 path_removed + path_added 中 URL 路径相同的配对为 method_changed(破坏性变更)
162
- const methodChanged = detectMethodChanges(changes);
163
- return methodChanged;
164
- }
165
- /**
166
- * 检测 HTTP 方法变更。
167
- * 将同一路径的 path_removed 和 path_added 配对,
168
- * 如果 HTTP 方法不同则合并为一个 method_changed 变更。
169
- * @param changes - 原始契约变更列表
170
- * @returns 合并后的契约变更列表(method_changed + 未消费的原始变更)
171
- */
172
- function detectMethodChanges(changes) {
173
- const removed = new Map();
174
- const added = new Map();
175
- const consumed = new Set();
176
- // 按 URL 路径建立索引,用于快速配对删除和新增的端点
177
- for (let i = 0; i < changes.length; i++) {
178
- const change = changes[i];
179
- if (change.change_type === "path_removed") {
180
- const pathStr = extractPath(change.before ?? change.description);
181
- if (pathStr)
182
- removed.set(pathStr, change);
183
- }
184
- else if (change.change_type === "path_added") {
185
- const pathStr = extractPath(change.after ?? change.description);
186
- if (pathStr)
187
- added.set(pathStr, change);
188
- }
189
- }
190
- // 查找匹配对:同一 URL 路径但不同 HTTP 方法的删除+新增
191
- const result = [];
192
- for (const [urlPath, removedChange] of removed) {
193
- const addedChange = added.get(urlPath);
194
- if (addedChange) {
195
- const removedMethod = extractHttpMethod(removedChange.before ?? removedChange.description);
196
- const addedMethod = extractHttpMethod(addedChange.after ?? addedChange.description);
197
- if (removedMethod && addedMethod && removedMethod !== addedMethod) {
198
- consumed.add(changes.indexOf(removedChange));
199
- consumed.add(changes.indexOf(addedChange));
200
- result.push({
201
- file: removedChange.file,
202
- change_type: "method_changed",
203
- severity: "breaking",
204
- description: `HTTP method changed: ${removedMethod} ${urlPath} -> ${addedMethod} ${urlPath}`,
205
- before: `${removedMethod} ${urlPath}`,
206
- after: `${addedMethod} ${urlPath}`,
207
- });
208
- }
209
- }
210
- }
211
- // 返回 method_changed + 未消费的原始变更
212
- for (let i = 0; i < changes.length; i++) {
213
- if (!consumed.has(i)) {
214
- result.push(changes[i]);
215
- }
216
- }
217
- return result;
218
- }
219
- /**
220
- * 从端点描述字符串中提取 URL 路径。
221
- * 支持格式如 "GetMapping /api/v1/users" 或 "GET /api/v1/users"。
222
- * @param endpointStr - 端点描述字符串
223
- * @returns 提取到的 URL 路径,匹配失败返回 null
224
- */
225
- function extractPath(endpointStr) {
226
- // 匹配以 / 开头的路径,支持字母、数字、连字符、花括号(路径参数)、点和斜杠
227
- const match = endpointStr.match(/\/[\w\-{}./]+/);
228
- return match ? match[0] : null;
229
- }
230
- /**
231
- * 从端点描述字符串中提取 HTTP 方法。
232
- * 支持 Spring 注解风格(GetMapping)和标准 HTTP 方法风格(GET)。
233
- * @param endpointStr - 端点描述字符串
234
- * @returns HTTP 方法字符串,匹配失败返回 null
235
- */
236
- function extractHttpMethod(endpointStr) {
237
- // 匹配 Spring 注解风格的方法名(如 GetMapping、PostMapping)
238
- const match = endpointStr.match(/^(Get|Post|Put|Delete|Patch|Mapping)\w*\s/i);
239
- if (match) {
240
- const raw = match[1].toUpperCase();
241
- // 将 Spring 注解名映射为标准 HTTP 方法
242
- const methodMap = {
243
- GET: "GET", POST: "POST", PUT: "PUT", DELETE: "DELETE", PATCH: "PATCH",
244
- REQUESTMAPPING: "REQUEST", // 通用映射,不区分方法
245
- };
246
- return methodMap[raw] ?? raw;
247
- }
248
- // 回退:匹配标准大写 HTTP 方法(如 GET、POST)
249
- const httpMatch = endpointStr.match(/^(GET|POST|PUT|DELETE|PATCH)\s/);
250
- return httpMatch ? httpMatch[1] : null;
251
- }
252
- /**
253
- * 检测 Spring MVC 注解变更。
254
- * 匹配 @GetMapping、@PostMapping、@PutMapping、@DeleteMapping、@RequestMapping。
255
- * @param content - diff 行内容(已去除 +/- 前缀)
256
- * @param isAdded - 是否为新增行
257
- * @param isRemoved - 是否为删除行
258
- * @param file - 文件路径
259
- * @returns 契约变更对象,未匹配返回 null
260
- */
261
- function detectSpringAnnotationChange(content, isAdded, isRemoved, file) {
262
- // Spring MVC 注解正则:匹配 @XxxMapping(value="/path") 或 @XxxMapping("/path") 形式
263
- const springAnnotationRe = /^\s*@(?<method>RequestMapping|GetMapping|PostMapping|PutMapping|DeleteMapping)\s*\(?\s*(?:value\s*=\s*)?["'`](?<path>\/[^"'`]*)["'`]/;
264
- const match = content.match(springAnnotationRe);
265
- if (!match)
266
- return null;
267
- const path = safeMatchGroups(match).path;
268
- const httpMethod = safeMatchGroups(match).method;
269
- if (isAdded) {
270
- return {
271
- file,
272
- change_type: "path_added",
273
- severity: "compatible",
274
- description: `New endpoint added: ${httpMethod} ${path}`,
275
- after: `${httpMethod} ${path}`,
276
- };
277
- }
278
- if (isRemoved) {
279
- return {
280
- file,
281
- change_type: "path_removed",
282
- severity: "breaking",
283
- description: `Endpoint removed: ${httpMethod} ${path}`,
284
- before: `${httpMethod} ${path}`,
285
- };
286
- }
287
- return null;
288
- }
289
- /**
290
- * 检测 Express 路由变更。
291
- * 匹配 router.get()、router.post()、router.put()、router.delete()、router.patch() 形式。
292
- * @param content - diff 行内容(已去除 +/- 前缀)
293
- * @param isAdded - 是否为新增行
294
- * @param isRemoved - 是否为删除行
295
- * @param file - 文件路径
296
- * @returns 契约变更对象,未匹配返回 null
297
- */
298
- function detectExpressRouteChange(content, isAdded, isRemoved, file) {
299
- // Express 路由正则:匹配 router.method('/path') 形式
300
- const expressRouteRe = /router\.(?<method>get|post|put|delete|patch)\s*\(\s*['"`](?<path>\/[^'"`]*)['"`]/;
301
- const match = content.match(expressRouteRe);
302
- if (!match)
303
- return null;
304
- const path = safeMatchGroups(match).path;
305
- const httpMethod = safeMatchGroups(match).method.toUpperCase();
306
- if (isAdded) {
307
- return {
308
- file,
309
- change_type: "path_added",
310
- severity: "compatible",
311
- description: `New Express route added: ${httpMethod} ${path}`,
312
- after: `${httpMethod} ${path}`,
313
- };
314
- }
315
- if (isRemoved) {
316
- return {
317
- file,
318
- change_type: "path_removed",
319
- severity: "breaking",
320
- description: `Express route removed: ${httpMethod} ${path}`,
321
- before: `${httpMethod} ${path}`,
322
- };
323
- }
324
- return null;
325
- }
326
- /**
327
- * 检测 DTO/Entity 字段变更。
328
- * 支持 Java 字段声明(private Type name)和 TypeScript 字段声明(name: Type)。
329
- * 当同一字段名出现删除和新增时,会尝试识别为类型变更。
330
- * @param content - diff 行内容(已去除 +/- 前缀)
331
- * @param isAdded - 是否为新增行
332
- * @param isRemoved - 是否为删除行
333
- * @param file - 文件路径
334
- * @param lines - diff 全部行(用于向前/向后查找关联行)
335
- * @param currentIndex - 当前行索引
336
- * @param consumedIndices - 已消费行索引集合(用于避免重复匹配)
337
- * @returns 契约变更对象,未匹配返回 null
338
- */
339
- function detectFieldChange(content, isAdded, isRemoved, file, lines, currentIndex, consumedIndices) {
340
- // Java 字段正则:匹配 private/protected/public Type fieldName 形式
341
- const javaFieldRe = /^\s*(private|protected|public)\s+(?<type>[\w<>[\]]+)\s+(?<name>\w+)/;
342
- // TypeScript 字段正则:匹配 fieldName: Type 或 fieldName?: Type 形式
343
- const tsFieldRe = /^\s*(?<name>\w+)\s*(?<optional>\??):\s*(?<type>[\w<>[\]|.]+)\s*[;=]?/;
344
- const javaMatch = content.match(javaFieldRe);
345
- const tsMatch = !javaMatch ? content.match(tsFieldRe) : null;
346
- if (javaMatch) {
347
- const { type, name } = safeMatchGroups(javaMatch);
348
- const fieldName = `${name}: ${type}`;
349
- if (isAdded) {
350
- // 尝试在同一字段名下查找关联的删除行,检测类型变更
351
- const typeChange = detectTypeChangeForField(name, lines, currentIndex, consumedIndices);
352
- if (typeChange) {
353
- return {
354
- file,
355
- change_type: "field_type_changed",
356
- severity: "breaking",
357
- description: `Field type changed: ${name}`,
358
- before: typeChange.before,
359
- after: typeChange.after,
360
- };
361
- }
362
- return {
363
- file,
364
- change_type: "field_added",
365
- severity: "compatible",
366
- description: `Field added: ${fieldName}`,
367
- after: fieldName,
368
- };
369
- }
370
- if (isRemoved) {
371
- // 尝试在同一字段名下查找关联的新增行,检测类型变更
372
- const typeChange = detectTypeChangeForField(name, lines, currentIndex, consumedIndices);
373
- if (typeChange) {
374
- return {
375
- file,
376
- change_type: "field_type_changed",
377
- severity: "breaking",
378
- description: `Field type changed: ${name}`,
379
- before: typeChange.before,
380
- after: typeChange.after,
381
- };
382
- }
383
- return {
384
- file,
385
- change_type: "field_removed",
386
- severity: "breaking",
387
- description: `Field removed: ${fieldName}`,
388
- before: fieldName,
389
- };
390
- }
391
- }
392
- if (tsMatch) {
393
- const { type, name } = safeMatchGroups(tsMatch);
394
- const optional = safeMatchGroups(tsMatch).optional === "?";
395
- const fieldName = `${name}${optional ? "?" : ""}: ${type}`;
396
- if (isAdded) {
397
- // 尝试在同一字段名下查找关联的删除行,检测类型变更
398
- const typeChange = detectTypeChangeForField(name, lines, currentIndex, consumedIndices);
399
- if (typeChange) {
400
- return {
401
- file,
402
- change_type: "field_type_changed",
403
- severity: "breaking",
404
- description: `Field type changed: ${name}`,
405
- before: typeChange.before,
406
- after: typeChange.after,
407
- };
408
- }
409
- return {
410
- file,
411
- change_type: "field_added",
412
- severity: "compatible",
413
- description: `Field added: ${fieldName}`,
414
- after: fieldName,
415
- };
416
- }
417
- if (isRemoved) {
418
- const typeChange = detectTypeChangeForField(name, lines, currentIndex, consumedIndices);
419
- if (typeChange) {
420
- return {
421
- file,
422
- change_type: "field_type_changed",
423
- severity: "breaking",
424
- description: `Field type changed: ${name}`,
425
- before: typeChange.before,
426
- after: typeChange.after,
427
- };
428
- }
429
- return {
430
- file,
431
- change_type: "field_removed",
432
- severity: "breaking",
433
- description: `Field removed: ${fieldName}`,
434
- before: fieldName,
435
- };
436
- }
437
- }
438
- return null;
439
- }
440
- /**
441
- * 检测字段的类型变更。
442
- * 在 diff 的相邻行中查找同名字段但类型不同的删除/新增行对。
443
- * 搜索范围限制为前后各 5 行,避免误匹配距离太远的无关行。
444
- * @param fieldName - 字段名称
445
- * @param lines - diff 全部行
446
- * @param currentIndex - 当前行索引
447
- * @param consumedIndices - 已消费行索引集合
448
- * @returns 类型变更信息(变更前后的类型字符串),未检测到返回 null
449
- */
450
- function detectTypeChangeForField(fieldName, lines, currentIndex, consumedIndices) {
451
- const javaRe = /^\s*(private|protected|public)\s+(?<type>[\w<>[\]]+)\s+(?<name>\w+)/;
452
- const tsRe = /^\s*(?<name>\w+)\s*(?<optional>\??):\s*(?<type>[\w<>[\]|.]+)\s*[;=]?/;
453
- const currentLine = lines[currentIndex];
454
- const isRemoved = currentLine.startsWith("-") && !currentLine.startsWith("---");
455
- const isAdded = currentLine.startsWith("+") && !currentLine.startsWith("+++");
456
- // 辅助函数:从 diff 行内容中提取类型信息(去除 +/- 前缀后)
457
- function extractTypeInfo(lineIndex) {
458
- const line = lines[lineIndex];
459
- const isPlus = line.startsWith("+") && !line.startsWith("+++");
460
- const isMinus = line.startsWith("-") && !line.startsWith("---");
461
- if (!isPlus && !isMinus)
462
- return null;
463
- const content = line.slice(1);
464
- const jMatch = content.match(javaRe);
465
- const tMatch = !jMatch ? content.match(tsRe) : null;
466
- const m = jMatch ?? tMatch;
467
- if (!m)
468
- return null;
469
- return { type: safeMatchGroups(m).type, name: safeMatchGroups(m).name };
470
- }
471
- function getCurrentTypeInfo() {
472
- return extractTypeInfo(currentIndex);
473
- }
474
- const maxLook = 5; // 最大向前/向后查找行数
475
- if (isRemoved) {
476
- // 删除行:向前查找同名字段的新增行(- 行后面紧跟 + 行)
477
- for (let j = currentIndex + 1; j < Math.min(currentIndex + maxLook, lines.length); j++) {
478
- if (consumedIndices.has(j))
479
- continue;
480
- const info = extractTypeInfo(j);
481
- if (info && info.name === fieldName) {
482
- const currentInfo = getCurrentTypeInfo();
483
- if (!currentInfo)
484
- return null;
485
- if (info.type !== currentInfo.type) {
486
- consumedIndices.add(j);
487
- return { before: `${fieldName}: ${currentInfo.type}`, after: `${fieldName}: ${info.type}` };
488
- }
489
- }
490
- }
491
- // 也在后方查找(diff 中 - 行出现在 + 行之后的情况)
492
- for (let j = currentIndex - 1; j >= Math.max(0, currentIndex - maxLook); j--) {
493
- if (consumedIndices.has(j))
494
- continue;
495
- const info = extractTypeInfo(j);
496
- if (info && info.name === fieldName) {
497
- const currentInfo = getCurrentTypeInfo();
498
- if (!currentInfo)
499
- return null;
500
- if (info.type !== currentInfo.type) {
501
- consumedIndices.add(j);
502
- return { before: `${fieldName}: ${currentInfo.type}`, after: `${fieldName}: ${info.type}` };
503
- }
504
- }
505
- }
506
- }
507
- if (isAdded) {
508
- // 新增行:向后查找同名字段的删除行(+ 行前面是 - 行)
509
- for (let j = currentIndex - 1; j >= Math.max(0, currentIndex - maxLook); j--) {
510
- if (consumedIndices.has(j))
511
- continue;
512
- const info = extractTypeInfo(j);
513
- if (info && info.name === fieldName) {
514
- const currentInfo = getCurrentTypeInfo();
515
- if (!currentInfo)
516
- return null;
517
- if (info.type !== currentInfo.type) {
518
- consumedIndices.add(j);
519
- return { before: `${fieldName}: ${info.type}`, after: `${fieldName}: ${currentInfo.type}` };
520
- }
521
- }
522
- }
523
- // 也在前方查找(diff 中 + 行出现在 - 行之前的情况)
524
- for (let j = currentIndex + 1; j < Math.min(currentIndex + maxLook, lines.length); j++) {
525
- if (consumedIndices.has(j))
526
- continue;
527
- const info = extractTypeInfo(j);
528
- if (info && info.name === fieldName) {
529
- const currentInfo = getCurrentTypeInfo();
530
- if (!currentInfo)
531
- return null;
532
- if (info.type !== currentInfo.type) {
533
- consumedIndices.add(j);
534
- return { before: `${fieldName}: ${info.type}`, after: `${fieldName}: ${currentInfo.type}` };
535
- }
536
- }
537
- }
538
- }
539
- return null;
540
- }
541
- /**
542
- * 分析破坏性变更的跨服务影响。
543
- * 仅在多仓库(多服务)场景下有效。当前版本将所有破坏性端点
544
- * 归类为对前端的潜在影响。
545
- * @param breakingChanges - 破坏性变更列表
546
- * @param config - 项目配置
547
- * @returns 受影响的服务列表及其关联端点
548
- */
549
- function analyzeCrossServiceImpact(breakingChanges, config) {
550
- const impact = [];
551
- // 仅在多仓库(微服务)场景下进行跨服务影响分析
552
- if (config.repos.length < 2)
553
- return impact;
554
- // 从破坏性变更中提取受影响的端点路径
555
- const affectedEndpoints = [];
556
- for (const change of breakingChanges) {
557
- if (change.change_type === "path_removed" ||
558
- change.change_type === "method_changed" ||
559
- change.change_type === "field_removed" ||
560
- change.change_type === "field_type_changed") {
561
- const endpoint = change.before ?? change.description;
562
- affectedEndpoints.push(endpoint);
563
- }
564
- }
565
- if (affectedEndpoints.length > 0) {
566
- impact.push({
567
- service: "frontend",
568
- endpoints: affectedEndpoints,
569
- });
570
- }
571
- return impact;
572
- }
573
- /**
574
- * 构建契约检查的人类可读摘要。
575
- * @param total - 变更总数
576
- * @param breaking - 破坏性变更数
577
- * @param compatible - 兼容性变更数
578
- * @param crossService - 跨服务影响列表
579
- * @returns 摘要文本
580
- */
581
- function buildSummary(total, breaking, compatible, crossService) {
582
- const parts = [];
583
- if (total === 0) {
584
- return "No contract changes detected.";
585
- }
586
- parts.push(`Detected ${total} contract change(s): ${breaking} breaking, ${compatible} compatible.`);
587
- if (crossService.length > 0) {
588
- const services = crossService.map((c) => `${c.service} (${c.endpoints.length} endpoint(s))`);
589
- parts.push(`Cross-service impact: ${services.join(", ")}.`);
590
- }
591
- if (breaking > 0) {
592
- parts.push("Review required due to breaking changes.");
593
- }
594
- return parts.join(" ");
595
- }
596
- /**
597
- * 创建空的契约检查结果。
598
- * @param summary - 摘要说明(通常描述为何无变更)
599
- * @returns 所有计数为零的空契约检查结果
600
- */
601
- function emptyResult(summary) {
602
- return {
603
- changes: [],
604
- breaking_count: 0,
605
- compatible_count: 0,
606
- cross_service_impact: [],
607
- requires_review: false,
608
- summary,
609
- };
610
- }
611
- //# sourceMappingURL=contract_guard.js.map