@descryy/core 0.3.0 → 0.5.0

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 (362) hide show
  1. package/dist/budget/reply.d.ts +11 -46
  2. package/dist/budget/reply.d.ts.map +1 -1
  3. package/dist/budget/reply.js +10 -39
  4. package/dist/budget/reply.js.map +1 -1
  5. package/dist/budget/size.d.ts +2 -21
  6. package/dist/budget/size.d.ts.map +1 -1
  7. package/dist/budget/size.js +3 -24
  8. package/dist/budget/size.js.map +1 -1
  9. package/dist/capabilities/preconditions.d.ts +7 -68
  10. package/dist/capabilities/preconditions.d.ts.map +1 -1
  11. package/dist/capabilities/preconditions.js +6 -57
  12. package/dist/capabilities/preconditions.js.map +1 -1
  13. package/dist/contracts/engine.d.ts +26 -12
  14. package/dist/contracts/engine.d.ts.map +1 -1
  15. package/dist/contracts/engine.js +28 -11
  16. package/dist/contracts/engine.js.map +1 -1
  17. package/dist/contracts/index.d.ts +1 -1
  18. package/dist/contracts/index.d.ts.map +1 -1
  19. package/dist/contracts/index.js.map +1 -1
  20. package/dist/contracts/orphans.d.ts +28 -77
  21. package/dist/contracts/orphans.d.ts.map +1 -1
  22. package/dist/contracts/orphans.js +124 -94
  23. package/dist/contracts/orphans.js.map +1 -1
  24. package/dist/contracts/paths.d.ts +4 -114
  25. package/dist/contracts/paths.d.ts.map +1 -1
  26. package/dist/contracts/paths.js +7 -140
  27. package/dist/contracts/paths.js.map +1 -1
  28. package/dist/contracts/shapes.d.ts +13 -66
  29. package/dist/contracts/shapes.d.ts.map +1 -1
  30. package/dist/contracts/shapes.js +20 -91
  31. package/dist/contracts/shapes.js.map +1 -1
  32. package/dist/governance/budget.d.ts +12 -48
  33. package/dist/governance/budget.d.ts.map +1 -1
  34. package/dist/governance/budget.js +12 -48
  35. package/dist/governance/budget.js.map +1 -1
  36. package/dist/governance/candidate-boundary.d.ts +4 -32
  37. package/dist/governance/candidate-boundary.d.ts.map +1 -1
  38. package/dist/governance/candidate-boundary.js +4 -32
  39. package/dist/governance/candidate-boundary.js.map +1 -1
  40. package/dist/governance/escalation.d.ts +7 -45
  41. package/dist/governance/escalation.d.ts.map +1 -1
  42. package/dist/governance/escalation.js +7 -45
  43. package/dist/governance/escalation.js.map +1 -1
  44. package/dist/governance/fact-boundary.d.ts +7 -49
  45. package/dist/governance/fact-boundary.d.ts.map +1 -1
  46. package/dist/governance/fact-boundary.js +5 -43
  47. package/dist/governance/fact-boundary.js.map +1 -1
  48. package/dist/governance/finding-funnel.d.ts +11 -72
  49. package/dist/governance/finding-funnel.d.ts.map +1 -1
  50. package/dist/governance/finding-funnel.js +9 -68
  51. package/dist/governance/finding-funnel.js.map +1 -1
  52. package/dist/graph/build.d.ts +13 -75
  53. package/dist/graph/build.d.ts.map +1 -1
  54. package/dist/graph/build.js +0 -0
  55. package/dist/graph/build.js.map +1 -1
  56. package/dist/graph/cross-language.d.ts +4 -43
  57. package/dist/graph/cross-language.d.ts.map +1 -1
  58. package/dist/graph/cross-language.js +9 -77
  59. package/dist/graph/cross-language.js.map +1 -1
  60. package/dist/graph/index.d.ts +1 -1
  61. package/dist/graph/index.d.ts.map +1 -1
  62. package/dist/graph/merge.d.ts +8 -76
  63. package/dist/graph/merge.d.ts.map +1 -1
  64. package/dist/graph/merge.js +27 -77
  65. package/dist/graph/merge.js.map +1 -1
  66. package/dist/graph/observed-tests.d.ts +7 -68
  67. package/dist/graph/observed-tests.d.ts.map +1 -1
  68. package/dist/graph/observed-tests.js +5 -60
  69. package/dist/graph/observed-tests.js.map +1 -1
  70. package/dist/graph/persist.d.ts +2 -25
  71. package/dist/graph/persist.d.ts.map +1 -1
  72. package/dist/graph/persist.js +2 -25
  73. package/dist/graph/persist.js.map +1 -1
  74. package/dist/graph/runtime-confirmation.d.ts +14 -91
  75. package/dist/graph/runtime-confirmation.d.ts.map +1 -1
  76. package/dist/graph/runtime-confirmation.js +19 -103
  77. package/dist/graph/runtime-confirmation.js.map +1 -1
  78. package/dist/ledger/mint.d.ts +9 -43
  79. package/dist/ledger/mint.d.ts.map +1 -1
  80. package/dist/ledger/mint.js +15 -65
  81. package/dist/ledger/mint.js.map +1 -1
  82. package/dist/ledger/resolve.d.ts +13 -81
  83. package/dist/ledger/resolve.d.ts.map +1 -1
  84. package/dist/ledger/resolve.js +13 -76
  85. package/dist/ledger/resolve.js.map +1 -1
  86. package/dist/multipr/fingerprint.d.ts +5 -46
  87. package/dist/multipr/fingerprint.d.ts.map +1 -1
  88. package/dist/multipr/fingerprint.js +22 -74
  89. package/dist/multipr/fingerprint.js.map +1 -1
  90. package/dist/multipr/hidden-dependency.d.ts +13 -73
  91. package/dist/multipr/hidden-dependency.d.ts.map +1 -1
  92. package/dist/multipr/hidden-dependency.js +12 -63
  93. package/dist/multipr/hidden-dependency.js.map +1 -1
  94. package/dist/multipr/mechanical.d.ts +25 -160
  95. package/dist/multipr/mechanical.d.ts.map +1 -1
  96. package/dist/multipr/mechanical.js +21 -137
  97. package/dist/multipr/mechanical.js.map +1 -1
  98. package/dist/multipr/migration-heads.d.ts +18 -105
  99. package/dist/multipr/migration-heads.d.ts.map +1 -1
  100. package/dist/multipr/migration-heads.js +15 -84
  101. package/dist/multipr/migration-heads.js.map +1 -1
  102. package/dist/multipr/overlap.d.ts +16 -94
  103. package/dist/multipr/overlap.d.ts.map +1 -1
  104. package/dist/multipr/overlap.js +25 -105
  105. package/dist/multipr/overlap.js.map +1 -1
  106. package/dist/multipr/scope-store.d.ts +15 -80
  107. package/dist/multipr/scope-store.d.ts.map +1 -1
  108. package/dist/multipr/scope-store.js +17 -87
  109. package/dist/multipr/scope-store.js.map +1 -1
  110. package/dist/multipr/superseded.d.ts +10 -95
  111. package/dist/multipr/superseded.d.ts.map +1 -1
  112. package/dist/multipr/superseded.js +7 -60
  113. package/dist/multipr/superseded.js.map +1 -1
  114. package/dist/query/confirmed-facts.d.ts +12 -58
  115. package/dist/query/confirmed-facts.d.ts.map +1 -1
  116. package/dist/query/confirmed-facts.js +8 -47
  117. package/dist/query/confirmed-facts.js.map +1 -1
  118. package/dist/query/declared-value-closure.d.ts +13 -104
  119. package/dist/query/declared-value-closure.d.ts.map +1 -1
  120. package/dist/query/declared-value-closure.js +15 -104
  121. package/dist/query/declared-value-closure.js.map +1 -1
  122. package/dist/query/memory.d.ts +5 -9
  123. package/dist/query/memory.d.ts.map +1 -1
  124. package/dist/query/memory.js +31 -15
  125. package/dist/query/memory.js.map +1 -1
  126. package/dist/query/prominence.d.ts +6 -55
  127. package/dist/query/prominence.d.ts.map +1 -1
  128. package/dist/query/prominence.js +6 -55
  129. package/dist/query/prominence.js.map +1 -1
  130. package/dist/query/provider.d.ts +28 -81
  131. package/dist/query/provider.d.ts.map +1 -1
  132. package/dist/query/provider.js +8 -29
  133. package/dist/query/provider.js.map +1 -1
  134. package/dist/query/queries.d.ts +15 -65
  135. package/dist/query/queries.d.ts.map +1 -1
  136. package/dist/query/queries.js +43 -100
  137. package/dist/query/queries.js.map +1 -1
  138. package/dist/query/refusal-fetch.d.ts +8 -85
  139. package/dist/query/refusal-fetch.d.ts.map +1 -1
  140. package/dist/query/refusal-fetch.js +11 -93
  141. package/dist/query/refusal-fetch.js.map +1 -1
  142. package/dist/query/refusal-questions.d.ts +17 -92
  143. package/dist/query/refusal-questions.d.ts.map +1 -1
  144. package/dist/query/refusal-questions.js +14 -78
  145. package/dist/query/refusal-questions.js.map +1 -1
  146. package/dist/query/resolution-floor.d.ts +3 -23
  147. package/dist/query/resolution-floor.d.ts.map +1 -1
  148. package/dist/query/resolution-floor.js +3 -23
  149. package/dist/query/resolution-floor.js.map +1 -1
  150. package/dist/query/root-cause-score.d.ts +11 -161
  151. package/dist/query/root-cause-score.d.ts.map +1 -1
  152. package/dist/query/root-cause-score.js +6 -137
  153. package/dist/query/root-cause-score.js.map +1 -1
  154. package/dist/query/row-closure-picture.d.ts +5 -67
  155. package/dist/query/row-closure-picture.d.ts.map +1 -1
  156. package/dist/query/row-closure-picture.js +6 -67
  157. package/dist/query/row-closure-picture.js.map +1 -1
  158. package/dist/query/similar-incidents.d.ts +6 -41
  159. package/dist/query/similar-incidents.d.ts.map +1 -1
  160. package/dist/query/similar-incidents.js +15 -69
  161. package/dist/query/similar-incidents.js.map +1 -1
  162. package/dist/query/sqlite.d.ts +3 -7
  163. package/dist/query/sqlite.d.ts.map +1 -1
  164. package/dist/query/sqlite.js +13 -16
  165. package/dist/query/sqlite.js.map +1 -1
  166. package/dist/query/test-coverage.d.ts +5 -45
  167. package/dist/query/test-coverage.d.ts.map +1 -1
  168. package/dist/query/test-coverage.js +10 -53
  169. package/dist/query/test-coverage.js.map +1 -1
  170. package/dist/query/traverse.d.ts +22 -126
  171. package/dist/query/traverse.d.ts.map +1 -1
  172. package/dist/query/traverse.js +0 -0
  173. package/dist/query/traverse.js.map +1 -1
  174. package/dist/query/unresolved.d.ts +19 -164
  175. package/dist/query/unresolved.d.ts.map +1 -1
  176. package/dist/query/unresolved.js +11 -138
  177. package/dist/query/unresolved.js.map +1 -1
  178. package/dist/query/verification-status.d.ts +12 -109
  179. package/dist/query/verification-status.d.ts.map +1 -1
  180. package/dist/query/verification-status.js +9 -99
  181. package/dist/query/verification-status.js.map +1 -1
  182. package/dist/recording/migrate.d.ts +4 -10
  183. package/dist/recording/migrate.d.ts.map +1 -1
  184. package/dist/recording/migrate.js +4 -10
  185. package/dist/recording/migrate.js.map +1 -1
  186. package/dist/recording/reader.d.ts +2 -7
  187. package/dist/recording/reader.d.ts.map +1 -1
  188. package/dist/recording/reader.js +2 -7
  189. package/dist/recording/reader.js.map +1 -1
  190. package/dist/recording/redact.d.ts +6 -57
  191. package/dist/recording/redact.d.ts.map +1 -1
  192. package/dist/recording/redact.js +8 -64
  193. package/dist/recording/redact.js.map +1 -1
  194. package/dist/recording/schema.d.ts +3 -38
  195. package/dist/recording/schema.d.ts.map +1 -1
  196. package/dist/recording/schema.js +3 -38
  197. package/dist/recording/schema.js.map +1 -1
  198. package/dist/recording/writer.d.ts +11 -74
  199. package/dist/recording/writer.d.ts.map +1 -1
  200. package/dist/recording/writer.js +3 -43
  201. package/dist/recording/writer.js.map +1 -1
  202. package/dist/scoping/fanout.d.ts +6 -68
  203. package/dist/scoping/fanout.d.ts.map +1 -1
  204. package/dist/scoping/fanout.js +6 -68
  205. package/dist/scoping/fanout.js.map +1 -1
  206. package/dist/scoping/score.d.ts +20 -70
  207. package/dist/scoping/score.d.ts.map +1 -1
  208. package/dist/scoping/score.js +20 -70
  209. package/dist/scoping/score.js.map +1 -1
  210. package/dist/scoping/tiers.d.ts +4 -16
  211. package/dist/scoping/tiers.d.ts.map +1 -1
  212. package/dist/scoping/tiers.js +4 -16
  213. package/dist/scoping/tiers.js.map +1 -1
  214. package/dist/scoping/traverse.d.ts +3 -25
  215. package/dist/scoping/traverse.d.ts.map +1 -1
  216. package/dist/scoping/traverse.js +14 -49
  217. package/dist/scoping/traverse.js.map +1 -1
  218. package/dist/scoping/weights.d.ts +10 -74
  219. package/dist/scoping/weights.d.ts.map +1 -1
  220. package/dist/scoping/weights.js +14 -86
  221. package/dist/scoping/weights.js.map +1 -1
  222. package/dist/sources/confirmed/incidents.d.ts +5 -35
  223. package/dist/sources/confirmed/incidents.d.ts.map +1 -1
  224. package/dist/sources/confirmed/incidents.js +14 -48
  225. package/dist/sources/confirmed/incidents.js.map +1 -1
  226. package/dist/sources/git/diff.d.ts +71 -65
  227. package/dist/sources/git/diff.d.ts.map +1 -1
  228. package/dist/sources/git/diff.js +136 -83
  229. package/dist/sources/git/diff.js.map +1 -1
  230. package/dist/sources/git/env.d.ts +7 -0
  231. package/dist/sources/git/env.d.ts.map +1 -1
  232. package/dist/sources/git/env.js +10 -11
  233. package/dist/sources/git/env.js.map +1 -1
  234. package/dist/sources/git/history.d.ts +64 -84
  235. package/dist/sources/git/history.d.ts.map +1 -1
  236. package/dist/sources/git/history.js +141 -112
  237. package/dist/sources/git/history.js.map +1 -1
  238. package/dist/sources/git/incidents.d.ts +13 -75
  239. package/dist/sources/git/incidents.d.ts.map +1 -1
  240. package/dist/sources/git/incidents.js +21 -91
  241. package/dist/sources/git/incidents.js.map +1 -1
  242. package/dist/sources/git/index.d.ts +5 -3
  243. package/dist/sources/git/index.d.ts.map +1 -1
  244. package/dist/sources/git/index.js +3 -2
  245. package/dist/sources/git/index.js.map +1 -1
  246. package/dist/sources/git/source.d.ts +9 -79
  247. package/dist/sources/git/source.d.ts.map +1 -1
  248. package/dist/sources/git/source.js +0 -0
  249. package/dist/sources/git/source.js.map +1 -1
  250. package/dist/sources/migrations/across-change.d.ts +94 -0
  251. package/dist/sources/migrations/across-change.d.ts.map +1 -0
  252. package/dist/sources/migrations/across-change.js +278 -0
  253. package/dist/sources/migrations/across-change.js.map +1 -0
  254. package/dist/sources/migrations/dialects.d.ts +20 -36
  255. package/dist/sources/migrations/dialects.d.ts.map +1 -1
  256. package/dist/sources/migrations/dialects.js +11 -36
  257. package/dist/sources/migrations/dialects.js.map +1 -1
  258. package/dist/sources/migrations/index.d.ts +3 -1
  259. package/dist/sources/migrations/index.d.ts.map +1 -1
  260. package/dist/sources/migrations/index.js +2 -1
  261. package/dist/sources/migrations/index.js.map +1 -1
  262. package/dist/sources/migrations/read.d.ts +14 -79
  263. package/dist/sources/migrations/read.d.ts.map +1 -1
  264. package/dist/sources/migrations/read.js +14 -89
  265. package/dist/sources/migrations/read.js.map +1 -1
  266. package/dist/sources/workspace/workspace.d.ts +6 -42
  267. package/dist/sources/workspace/workspace.d.ts.map +1 -1
  268. package/dist/sources/workspace/workspace.js +10 -53
  269. package/dist/sources/workspace/workspace.js.map +1 -1
  270. package/dist/store/driver/driver.d.ts +9 -38
  271. package/dist/store/driver/driver.d.ts.map +1 -1
  272. package/dist/store/driver/driver.js +4 -22
  273. package/dist/store/driver/driver.js.map +1 -1
  274. package/dist/store/driver/node-sqlite.d.ts +3 -12
  275. package/dist/store/driver/node-sqlite.d.ts.map +1 -1
  276. package/dist/store/driver/node-sqlite.js +4 -18
  277. package/dist/store/driver/node-sqlite.js.map +1 -1
  278. package/dist/store/index.d.ts +2 -7
  279. package/dist/store/index.d.ts.map +1 -1
  280. package/dist/store/index.js +4 -10
  281. package/dist/store/index.js.map +1 -1
  282. package/dist/store/migrate.d.ts +14 -50
  283. package/dist/store/migrate.d.ts.map +1 -1
  284. package/dist/store/migrate.js +15 -52
  285. package/dist/store/migrate.js.map +1 -1
  286. package/dist/store/reader.d.ts +19 -84
  287. package/dist/store/reader.d.ts.map +1 -1
  288. package/dist/store/reader.js +25 -92
  289. package/dist/store/reader.js.map +1 -1
  290. package/dist/store/schema.d.ts +14 -76
  291. package/dist/store/schema.d.ts.map +1 -1
  292. package/dist/store/schema.js +14 -76
  293. package/dist/store/schema.js.map +1 -1
  294. package/dist/store/writer.d.ts +14 -88
  295. package/dist/store/writer.d.ts.map +1 -1
  296. package/dist/store/writer.js +29 -123
  297. package/dist/store/writer.js.map +1 -1
  298. package/dist/tiers/certify.d.ts +46 -281
  299. package/dist/tiers/certify.d.ts.map +1 -1
  300. package/dist/tiers/certify.js +46 -226
  301. package/dist/tiers/certify.js.map +1 -1
  302. package/dist/tiers/ladder.d.ts +7 -51
  303. package/dist/tiers/ladder.d.ts.map +1 -1
  304. package/dist/tiers/ladder.js +13 -89
  305. package/dist/tiers/ladder.js.map +1 -1
  306. package/dist/validation/attributes.d.ts +47 -0
  307. package/dist/validation/attributes.d.ts.map +1 -0
  308. package/dist/validation/attributes.js +130 -0
  309. package/dist/validation/attributes.js.map +1 -0
  310. package/dist/validation/config-graph.d.ts +7 -56
  311. package/dist/validation/config-graph.d.ts.map +1 -1
  312. package/dist/validation/config-graph.js +15 -61
  313. package/dist/validation/config-graph.js.map +1 -1
  314. package/dist/validation/env.d.ts +53 -2
  315. package/dist/validation/env.d.ts.map +1 -1
  316. package/dist/validation/env.js +99 -4
  317. package/dist/validation/env.js.map +1 -1
  318. package/dist/validation/index.d.ts +5 -1
  319. package/dist/validation/index.d.ts.map +1 -1
  320. package/dist/validation/index.js +3 -1
  321. package/dist/validation/index.js.map +1 -1
  322. package/dist/validation/join-substitution.d.ts +22 -120
  323. package/dist/validation/join-substitution.d.ts.map +1 -1
  324. package/dist/validation/join-substitution.js +13 -90
  325. package/dist/validation/join-substitution.js.map +1 -1
  326. package/dist/validation/migration-integrity.d.ts +72 -0
  327. package/dist/validation/migration-integrity.d.ts.map +1 -0
  328. package/dist/validation/migration-integrity.js +238 -0
  329. package/dist/validation/migration-integrity.js.map +1 -0
  330. package/dist/validation/migrations.d.ts +23 -88
  331. package/dist/validation/migrations.d.ts.map +1 -1
  332. package/dist/validation/migrations.js +20 -79
  333. package/dist/validation/migrations.js.map +1 -1
  334. package/dist/validation/nodes.d.ts +3 -1
  335. package/dist/validation/nodes.d.ts.map +1 -1
  336. package/dist/validation/nodes.js +3 -1
  337. package/dist/validation/nodes.js.map +1 -1
  338. package/dist/validation/rollback.d.ts +10 -73
  339. package/dist/validation/rollback.d.ts.map +1 -1
  340. package/dist/validation/rollback.js +23 -81
  341. package/dist/validation/rollback.js.map +1 -1
  342. package/dist/validation/route-drift.d.ts +9 -62
  343. package/dist/validation/route-drift.d.ts.map +1 -1
  344. package/dist/validation/route-drift.js +7 -52
  345. package/dist/validation/route-drift.js.map +1 -1
  346. package/dist/validation/sources.d.ts +16 -94
  347. package/dist/validation/sources.d.ts.map +1 -1
  348. package/dist/validation/sources.js +51 -147
  349. package/dist/validation/sources.js.map +1 -1
  350. package/dist/worker/pool.d.ts +6 -45
  351. package/dist/worker/pool.d.ts.map +1 -1
  352. package/dist/worker/pool.js +5 -42
  353. package/dist/worker/pool.js.map +1 -1
  354. package/dist/worker/protocol.d.ts +7 -20
  355. package/dist/worker/protocol.d.ts.map +1 -1
  356. package/dist/worker/protocol.js +3 -10
  357. package/dist/worker/protocol.js.map +1 -1
  358. package/dist/worker/traversal.worker.d.ts +2 -21
  359. package/dist/worker/traversal.worker.d.ts.map +1 -1
  360. package/dist/worker/traversal.worker.js +4 -23
  361. package/dist/worker/traversal.worker.js.map +1 -1
  362. package/package.json +11 -2
@@ -1,110 +1,7 @@
1
1
  /**
2
- * Comparing two endpoint paths, and knowing when not to.
3
- *
4
- * This file is small and is the most dangerous part of the contract engine, so
5
- * it is separate and tested on its own.
6
- *
7
- * ## The problem it exists to solve
8
- *
9
- * A caller reaching an endpoint no route serves is *sometimes* a bug and
10
- * *usually* not. Measured on two real repositories: 117 callers, 24 routes, 16
11
- * joined. The other 101 are overwhelmingly calls to services that are simply not
12
- * in this graph — a third-party API, a backend nobody has analysed. Reporting
13
- * all 101 as "no route serves this" would be 101 confident wrong statements, and
14
- * would bury the handful that are real.
15
- *
16
- * So an unmatched caller is only a **finding** when a served route exists that
17
- * it nearly matches. Nothing similar on the provider side means the provider was
18
- * probably never analysed, which belongs in §20.2's *not analysable* category
19
- * and is disclosed as a count rather than enumerated as defects.
20
- *
21
- * ## The near-miss rules are deliberately narrow
22
- *
23
- * Each one describes a specific, common, *mechanical* mistake. None of them is a
24
- * similarity score, because a threshold on a score is a knob that turns "is this
25
- * a bug" into "how high did we set it".
26
- *
27
- * | rule | example | why it is a real mistake |
28
- * | --- | --- | --- |
29
- * | method differs, path identical | `POST /orders` vs `GET /orders` | someone changed the verb on one side |
30
- * | exactly one **literal** segment differs, **and the two differ by a typo's worth of characters** | `/order/{param}/items` vs `/orders/{param}/items` | a typo or a rename applied on one side |
31
- *
32
- * ## Rule 2's similarity floor, and the measurement that set it
33
- *
34
- * That second clause was missing for the whole life of this file, and its
35
- * absence was not a small thing. "Exactly one segment differs" says nothing at
36
- * all about *how* it differs: `/api/hmac` and `/api/novu-agent` differ in
37
- * exactly one segment, share a method and share arity. Precision came only
38
- * incidentally, from `{param}` segments happening to sit where the paths
39
- * diverge.
40
- *
41
- * `DEC-317` found this from the GraphQL side — every operation path is arity-2
42
- * with no `{param}` and a first segment drawn from a set of size three, so the
43
- * whole GraphQL surface of a repository collapsed into three buckets in which
44
- * every member near-missed every other — and gated it rather than fixing it,
45
- * because a threshold chosen carelessly costs the near-typo detections this
46
- * rule exists for, and costs them invisibly.
47
- *
48
- * So it was measured, against 3,524 routes from 27 real repositories, by
49
- * `bench/near-miss-similarity.mjs` — which pre-registers the metric, the
50
- * candidate thresholds and the decision rule in its header, and was committed
51
- * before it was run. What it found:
52
- *
53
- * - **The rule was not a precision rule.** Treating each real route as an
54
- * unmatched caller against the rest of its own application's table, it
55
- * reported a `ONE_SEGMENT` near miss for **1,796 of 3,524 routes — 51%.**
56
- * Every one is a false positive by construction: both sides are real,
57
- * deliberately distinct routes of the same service.
58
- * - **On the genuinely reachable population it was worse.** Across every
59
- * unmatched `USES_API` caller in the corpus, the rule emitted **18 findings,
60
- * and all 18 were nonsense** — 15 of them naming the same `/api/novu-agent`
61
- * route from callers like `/api/hmac` and `/api/send-email`. There were no
62
- * true positives to lose.
63
- *
64
- * The floor is `1 - distance / max(len) >= 0.4`, with any distance of 1 or less
65
- * admitted outright so that a one-character mistake in a short segment (`/v1`
66
- * against `/v2`) is not scored away. It rejects **87.4%** of those 1,796 and
67
- * retains **100%** of a seeded near-typo population of 49,405 — real route
68
- * segments mutated by transposition, deletion, insertion, substitution,
69
- * singular/plural and separator variance. Not one seeded typo is lost, in any
70
- * class.
71
- *
72
- * **The distance counts an adjacent transposition as one edit, not two, and
73
- * that is load-bearing.** With plain Levenshtein a swap costs two, so `api` →
74
- * `aip` scores `1 - 2/3 = 0.33` and every candidate threshold silently deleted
75
- * the entire transposition class — 2,916 real detections, all on segments of
76
- * three characters. The first measurement pass rejected every threshold for
77
- * exactly this reason, and the reason was a defect in the metric rather than a
78
- * fact about the corpus.
79
- *
80
- * **What the floor is not.** It is a similarity test, not an oracle. `activate`
81
- * and `deactivate` are two real routes in one API and score 0.80, so they are
82
- * still reported. Nothing here can distinguish a two-character prefix from a
83
- * typo, and this does not claim to — it buys precision against *unrelated*
84
- * words, which is what the corpus says the problem was.
85
- *
86
- * **A trailing-slash rule was written and then deleted, and the reason is worth
87
- * keeping.** `/orders/` and `/orders` look like the classic contract mismatch,
88
- * but `normaliseEndpointPath` strips the trailing slash *before hashing*, so the
89
- * two sides mint the **same `API_ENDPOINT` id** and join correctly. The rule
90
- * could never fire. It was caught by a test that asserted it would.
91
- *
92
- * That unification is the right default — the two paths mean the same endpoint
93
- * to everyone who writes them — but it does make one real class of bug
94
- * invisible here: a framework configured for strict routing genuinely serves
95
- * only one of them. Whether it does depends on router configuration this graph
96
- * does not read, so the limit is stated rather than papered over with a rule
97
- * that fires on nothing.
98
- *
99
- * **Deliberately not a rule: a parameter where the other side has a literal.**
100
- * `/orders/{param}` and `/orders/recent` legitimately coexist in every routing
101
- * framework on earth — the literal is matched first and the parameter catches
102
- * the rest. Treating that as a near miss would report the single most common
103
- * correct pattern in REST routing as a defect.
104
- *
105
- * Segment counts must be equal for the segment rule. `/orders` and
106
- * `/orders/{param}` are two different endpoints, not a near miss, and a rule
107
- * that ignored length would pair every collection route with its item route.
2
+ * A near-miss caller is a finding only when genuinely close to a served route (DEC-317: "one segment
3
+ * differs" alone was 51% false positives on 3,524 routes). Floor `1 - distance/max(len) >= 0.4` (transposition
4
+ * = 1 edit not 2) rejects 87.4% of those, keeps 100% of a 49,405-case seeded typo set. Not an oracle.
108
5
  */
109
6
  export interface EndpointKey {
110
7
  readonly method: string;
@@ -120,13 +17,6 @@ export interface NearMiss {
120
17
  readonly detail: string;
121
18
  }
122
19
  export declare function sameEndpoint(a: EndpointKey, b: EndpointKey): boolean;
123
- /**
124
- * The closest served endpoint to `wanted`, or null if nothing is close enough.
125
- *
126
- * Rules are tried in order of how certain they are, and the first hit wins —
127
- * a method mismatch on an otherwise identical path is a better explanation than
128
- * a one-segment difference somewhere else, and reporting both would be reporting
129
- * one mistake twice.
130
- */
20
+ /** Closest served endpoint to `wanted`, or null. Rules tried in order of certainty; first hit wins. */
131
21
  export declare function nearestMiss(wanted: EndpointKey, served: readonly EndpointKey[]): NearMiss | null;
132
22
  //# sourceMappingURL=paths.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/contracts/paths.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2GG;AAkEH,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,0EAA0E;IAC1E,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,aAAa,CAAC;AAEpD,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B,mDAAmD;IACnD,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAC9B,+EAA+E;IAC/E,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAWD,wBAAgB,YAAY,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,WAAW,GAAG,OAAO,CAEpE;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CACzB,MAAM,EAAE,WAAW,EACnB,MAAM,EAAE,SAAS,WAAW,EAAE,GAC7B,QAAQ,GAAG,IAAI,CA0DjB"}
1
+ {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/contracts/paths.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AA2CH,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,0EAA0E;IAC1E,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,aAAa,CAAC;AAEpD,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B,mDAAmD;IACnD,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAC9B,+EAA+E;IAC/E,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAWD,wBAAgB,YAAY,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,WAAW,GAAG,OAAO,CAEpE;AAED,uGAAuG;AACvG,wBAAgB,WAAW,CACzB,MAAM,EAAE,WAAW,EACnB,MAAM,EAAE,SAAS,WAAW,EAAE,GAC7B,QAAQ,GAAG,IAAI,CA0DjB"}
@@ -1,131 +1,13 @@
1
1
  /**
2
- * Comparing two endpoint paths, and knowing when not to.
3
- *
4
- * This file is small and is the most dangerous part of the contract engine, so
5
- * it is separate and tested on its own.
6
- *
7
- * ## The problem it exists to solve
8
- *
9
- * A caller reaching an endpoint no route serves is *sometimes* a bug and
10
- * *usually* not. Measured on two real repositories: 117 callers, 24 routes, 16
11
- * joined. The other 101 are overwhelmingly calls to services that are simply not
12
- * in this graph — a third-party API, a backend nobody has analysed. Reporting
13
- * all 101 as "no route serves this" would be 101 confident wrong statements, and
14
- * would bury the handful that are real.
15
- *
16
- * So an unmatched caller is only a **finding** when a served route exists that
17
- * it nearly matches. Nothing similar on the provider side means the provider was
18
- * probably never analysed, which belongs in §20.2's *not analysable* category
19
- * and is disclosed as a count rather than enumerated as defects.
20
- *
21
- * ## The near-miss rules are deliberately narrow
22
- *
23
- * Each one describes a specific, common, *mechanical* mistake. None of them is a
24
- * similarity score, because a threshold on a score is a knob that turns "is this
25
- * a bug" into "how high did we set it".
26
- *
27
- * | rule | example | why it is a real mistake |
28
- * | --- | --- | --- |
29
- * | method differs, path identical | `POST /orders` vs `GET /orders` | someone changed the verb on one side |
30
- * | exactly one **literal** segment differs, **and the two differ by a typo's worth of characters** | `/order/{param}/items` vs `/orders/{param}/items` | a typo or a rename applied on one side |
31
- *
32
- * ## Rule 2's similarity floor, and the measurement that set it
33
- *
34
- * That second clause was missing for the whole life of this file, and its
35
- * absence was not a small thing. "Exactly one segment differs" says nothing at
36
- * all about *how* it differs: `/api/hmac` and `/api/novu-agent` differ in
37
- * exactly one segment, share a method and share arity. Precision came only
38
- * incidentally, from `{param}` segments happening to sit where the paths
39
- * diverge.
40
- *
41
- * `DEC-317` found this from the GraphQL side — every operation path is arity-2
42
- * with no `{param}` and a first segment drawn from a set of size three, so the
43
- * whole GraphQL surface of a repository collapsed into three buckets in which
44
- * every member near-missed every other — and gated it rather than fixing it,
45
- * because a threshold chosen carelessly costs the near-typo detections this
46
- * rule exists for, and costs them invisibly.
47
- *
48
- * So it was measured, against 3,524 routes from 27 real repositories, by
49
- * `bench/near-miss-similarity.mjs` — which pre-registers the metric, the
50
- * candidate thresholds and the decision rule in its header, and was committed
51
- * before it was run. What it found:
52
- *
53
- * - **The rule was not a precision rule.** Treating each real route as an
54
- * unmatched caller against the rest of its own application's table, it
55
- * reported a `ONE_SEGMENT` near miss for **1,796 of 3,524 routes — 51%.**
56
- * Every one is a false positive by construction: both sides are real,
57
- * deliberately distinct routes of the same service.
58
- * - **On the genuinely reachable population it was worse.** Across every
59
- * unmatched `USES_API` caller in the corpus, the rule emitted **18 findings,
60
- * and all 18 were nonsense** — 15 of them naming the same `/api/novu-agent`
61
- * route from callers like `/api/hmac` and `/api/send-email`. There were no
62
- * true positives to lose.
63
- *
64
- * The floor is `1 - distance / max(len) >= 0.4`, with any distance of 1 or less
65
- * admitted outright so that a one-character mistake in a short segment (`/v1`
66
- * against `/v2`) is not scored away. It rejects **87.4%** of those 1,796 and
67
- * retains **100%** of a seeded near-typo population of 49,405 — real route
68
- * segments mutated by transposition, deletion, insertion, substitution,
69
- * singular/plural and separator variance. Not one seeded typo is lost, in any
70
- * class.
71
- *
72
- * **The distance counts an adjacent transposition as one edit, not two, and
73
- * that is load-bearing.** With plain Levenshtein a swap costs two, so `api` →
74
- * `aip` scores `1 - 2/3 = 0.33` and every candidate threshold silently deleted
75
- * the entire transposition class — 2,916 real detections, all on segments of
76
- * three characters. The first measurement pass rejected every threshold for
77
- * exactly this reason, and the reason was a defect in the metric rather than a
78
- * fact about the corpus.
79
- *
80
- * **What the floor is not.** It is a similarity test, not an oracle. `activate`
81
- * and `deactivate` are two real routes in one API and score 0.80, so they are
82
- * still reported. Nothing here can distinguish a two-character prefix from a
83
- * typo, and this does not claim to — it buys precision against *unrelated*
84
- * words, which is what the corpus says the problem was.
85
- *
86
- * **A trailing-slash rule was written and then deleted, and the reason is worth
87
- * keeping.** `/orders/` and `/orders` look like the classic contract mismatch,
88
- * but `normaliseEndpointPath` strips the trailing slash *before hashing*, so the
89
- * two sides mint the **same `API_ENDPOINT` id** and join correctly. The rule
90
- * could never fire. It was caught by a test that asserted it would.
91
- *
92
- * That unification is the right default — the two paths mean the same endpoint
93
- * to everyone who writes them — but it does make one real class of bug
94
- * invisible here: a framework configured for strict routing genuinely serves
95
- * only one of them. Whether it does depends on router configuration this graph
96
- * does not read, so the limit is stated rather than papered over with a rule
97
- * that fires on nothing.
98
- *
99
- * **Deliberately not a rule: a parameter where the other side has a literal.**
100
- * `/orders/{param}` and `/orders/recent` legitimately coexist in every routing
101
- * framework on earth — the literal is matched first and the parameter catches
102
- * the rest. Treating that as a near miss would report the single most common
103
- * correct pattern in REST routing as a defect.
104
- *
105
- * Segment counts must be equal for the segment rule. `/orders` and
106
- * `/orders/{param}` are two different endpoints, not a near miss, and a rule
107
- * that ignored length would pair every collection route with its item route.
2
+ * A near-miss caller is a finding only when genuinely close to a served route (DEC-317: "one segment
3
+ * differs" alone was 51% false positives on 3,524 routes). Floor `1 - distance/max(len) >= 0.4` (transposition
4
+ * = 1 edit not 2) rejects 87.4% of those, keeps 100% of a 49,405-case seeded typo set. Not an oracle.
108
5
  */
109
6
  /** The normalised placeholder every adapter writes. See `normaliseEndpointPath`. */
110
7
  const PARAM = "{param}";
111
- /**
112
- * How alike rule 2's two differing segments must be, as a fraction of the
113
- * longer one's length. **Measured, not chosen** — see the module header, and
114
- * `bench/near-miss-similarity.mjs` for the pre-registered decision rule that
115
- * selected it: the lowest candidate that keeps 100% of a 49,405-case seeded
116
- * near-typo population, which it does while rejecting 87.4% of the false
117
- * positives the unguarded rule produced on 3,524 real routes.
118
- */
8
+ /** How alike rule 2's two differing segments must be. Measured, not chosen — see module header. */
119
9
  const SEGMENT_SIMILARITY_FLOOR = 0.4;
120
- /**
121
- * Damerau-Levenshtein distance, optimal string alignment.
122
- *
123
- * **An adjacent transposition costs one edit, not two**, and that is the whole
124
- * reason this is not the three-line Levenshtein. A swapped pair of characters
125
- * is a single keystroke mistake and the single most common way a path is
126
- * typo'd; charging it two edits puts `api`/`aip` at 0.33 and deletes the entire
127
- * class from what rule 2 can report.
128
- */
10
+ /** Damerau-Levenshtein distance. Adjacent transposition costs 1 edit, not 2 — else `api`/`aip` scores 0.33. */
129
11
  function editDistance(a, b) {
130
12
  if (a === b)
131
13
  return 0;
@@ -152,15 +34,7 @@ function editDistance(a, b) {
152
34
  }
153
35
  return rows[a.length][b.length];
154
36
  }
155
- /**
156
- * Are these two segments close enough that one could be a mistyping of the
157
- * other, rather than simply a different word?
158
- *
159
- * A distance of one is admitted whatever the lengths, because on a short
160
- * segment a single edit is a large fraction of the string and normalising it
161
- * away would reject `/v1` against `/v2` — the most mechanical mismatch there
162
- * is.
163
- */
37
+ /** Close enough to be a mistyping, not just a different word? Distance-1 always admitted, so `/v1`/`/v2` isn't scored away. */
164
38
  function nearlyTheSameWord(a, b) {
165
39
  const distance = editDistance(a, b);
166
40
  if (distance <= 1)
@@ -177,14 +51,7 @@ function trimmed(path) {
177
51
  export function sameEndpoint(a, b) {
178
52
  return a.method === b.method && a.pathTemplate === b.pathTemplate;
179
53
  }
180
- /**
181
- * The closest served endpoint to `wanted`, or null if nothing is close enough.
182
- *
183
- * Rules are tried in order of how certain they are, and the first hit wins —
184
- * a method mismatch on an otherwise identical path is a better explanation than
185
- * a one-segment difference somewhere else, and reporting both would be reporting
186
- * one mistake twice.
187
- */
54
+ /** Closest served endpoint to `wanted`, or null. Rules tried in order of certainty; first hit wins. */
188
55
  export function nearestMiss(wanted, served) {
189
56
  const wantedPath = trimmed(wanted.pathTemplate);
190
57
  const wantedSegments = segments(wantedPath);
@@ -1 +1 @@
1
- {"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/contracts/paths.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/contracts/paths.ts"],"names":[],"mappings":"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"}
@@ -1,56 +1,15 @@
1
- /**
2
- * Comparing two declared shapes — the R3 half of §13.
3
- *
4
- * Everything here is a pure function over `attrs`, and that is the design rather
5
- * than an accident. §13.2's mechanism is **shape comparison, not identifier
6
- * matching**, and a shape reaches this file as a list of fields with optional
7
- * per-field detail. No type here names a language, and nothing branches on one:
8
- * a Pydantic model, an OpenAPI schema and a TypeScript interface arrive
9
- * identically or they do not arrive at all.
10
- *
11
- * ## Direction is not symmetric, and getting that wrong produces noise
12
- *
13
- * A consumer that ignores a field the provider sends is **fine** — that is how
14
- * every API client on earth works. A consumer that reads a field the provider
15
- * does not send is **broken**. So the comparison takes an *expected* side and a
16
- * *provided* side, and a field present only in `provided` is not a finding.
17
- *
18
- * A symmetric diff would report every unused response field in every codebase,
19
- * which is both enormous and wrong.
20
- *
21
- * ## Detail is compared only when both sides have it
22
- *
23
- * A shape read from `attrs.fields` is a list of names — R2-grade evidence, good
24
- * enough to say *this field is missing* and nothing else. A shape read from
25
- * `attrs.fieldDetail` carries type, nullability and requiredness, which is what
26
- * a type checker buys.
27
- *
28
- * When either side lacks detail, `comparedDetail` comes back false and **no type
29
- * or nullability differences are emitted**. That flag is load-bearing: an empty
30
- * difference list is otherwise indistinguishable from "the types agree", and
31
- * reporting "no type mismatches" after comparing two lists of names is exactly
32
- * the overstatement principle 3 exists to stop.
33
- */
1
+ /** R3 half of §13: comparing two declared shapes, pure over `attrs`, no language named (IR
2
+ * boundary). Asymmetric by design — a field only in `provided` is fine; one only in `expected`
3
+ * is broken. `comparedDetail` false means "no detail to compare," never "types agree" (rule 3). */
34
4
  import type { IRNode } from "@descryy/ir";
35
5
  export interface ShapeField {
36
6
  readonly name: string;
37
7
  readonly type?: string | undefined;
38
8
  readonly nullable?: boolean | undefined;
39
9
  readonly required?: boolean | undefined;
40
- /**
41
- * The field holds *many* of `type`, not one.
42
- *
43
- * **A separate flag rather than part of the type string, and that is rule 1.**
44
- * The same field is written `Foo[]` by one producer, `List[Foo]` by another and
45
- * `array` with an `items` schema by a third. Comparing those as strings is an
46
- * engine above the IR deciding what a language's array syntax looks like, which
47
- * is the leak the boundary exists to stop — and it fails in both directions at
48
- * once: `Foo[]` vs `List[Foo]` reports a mismatch that is not there, while
49
- * `Foo` vs `Foo` with one side an array reports nothing when the consumer is
50
- * about to iterate an object.
51
- *
52
- * Producers put the **element** type in `type` and the cardinality here.
53
- */
10
+ /** True when the field holds MANY of `type` (rule 1: separate flag, not baked into the type
11
+ * string — `Foo[]` vs `List[Foo]` vs OpenAPI's `array`+items would otherwise need this engine
12
+ * to parse a language's array syntax). Producers put the element type in `type`, cardinality here. */
54
13
  readonly list?: boolean | undefined;
55
14
  }
56
15
  export interface Shape {
@@ -60,13 +19,9 @@ export interface Shape {
60
19
  /** True when per-field type/nullability/requiredness is present — R3-grade. */
61
20
  readonly detailed: boolean;
62
21
  }
63
- /**
64
- * Read a shape out of a node's `attrs`, or return null if it declares none.
65
- *
66
- * Two forms, in order of richness. `fieldDetail` is what a producer emits when a
67
- * type checker or a schema gave it per-field facts; `fields` is the name-level
68
- * fallback. Anything else is not a shape and is not guessed at.
69
- */
22
+ /** Reads a shape from `attrs`, or null if none declared. Two forms: `fieldDetail` (per-field
23
+ * facts from a type checker/schema) is preferred, `fields` is the name-level fallback.
24
+ * Anything else is not a shape and is not guessed at. */
70
25
  export declare function readShape(node: IRNode): Shape | null;
71
26
  export type ShapeDifferenceKind = "FIELD_MISSING" | "TYPE_DIFFERS" | "NULLABILITY_DIFFERS" | "REQUIREDNESS_DIFFERS" | "LIST_DIFFERS";
72
27
  export interface ShapeDifference {
@@ -80,20 +35,12 @@ export interface ShapeDifference {
80
35
  }
81
36
  export interface ShapeComparison {
82
37
  readonly differences: readonly ShapeDifference[];
83
- /**
84
- * True only when **both** sides carried per-field detail.
85
- *
86
- * When false, an empty `differences` means "no field is missing", not "the
87
- * types agree" — and every consumer of this result has to say so.
88
- */
38
+ /** True only when both sides carried per-field detail. False means an empty `differences`
39
+ * reads as "no field is missing," never "the types agree" — every consumer must say so. */
89
40
  readonly comparedDetail: boolean;
90
41
  readonly fieldsCompared: number;
91
42
  }
92
- /**
93
- * What the consuming side asks for that the providing side does not deliver.
94
- *
95
- * @param expected the shape the consumer reads
96
- * @param provided the shape the producer declares
97
- */
43
+ /** What the consumer expects that the provider doesn't deliver. `expected`: what the consumer
44
+ * reads. `provided`: what the producer declares. */
98
45
  export declare function compareShapes(expected: Shape, provided: Shape): ShapeComparison;
99
46
  //# sourceMappingURL=shapes.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"shapes.d.ts","sourceRoot":"","sources":["../../src/contracts/shapes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACxC,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACxC;;;;;;;;;;;;;OAaG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CACrC;AAED,MAAM,WAAW,KAAK;IACpB,gFAAgF;IAChF,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE,CAAC;IACvC,+EAA+E;IAC/E,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC5B;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK,GAAG,IAAI,CAUpD;AAwDD,MAAM,MAAM,mBAAmB,GAC3B,eAAe,GACf,cAAc,GACd,qBAAqB,GACrB,sBAAsB,GACtB,cAAc,CAAC;AAEnB,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,mBAAmB,CAAC;IACnC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,uCAAuC;IACvC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,wCAAwC;IACxC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,WAAW,EAAE,SAAS,eAAe,EAAE,CAAC;IACjD;;;;;OAKG;IACH,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;IACjC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;CACjC;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,GAAG,eAAe,CAoG/E"}
1
+ {"version":3,"file":"shapes.d.ts","sourceRoot":"","sources":["../../src/contracts/shapes.ts"],"names":[],"mappings":"AAAA;;oGAEoG;AAEpG,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACxC,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACxC;;2GAEuG;IACvG,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CACrC;AAED,MAAM,WAAW,KAAK;IACpB,gFAAgF;IAChF,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE,CAAC;IACvC,+EAA+E;IAC/E,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC5B;AAED;;0DAE0D;AAC1D,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK,GAAG,IAAI,CAUpD;AAoCD,MAAM,MAAM,mBAAmB,GAC3B,eAAe,GACf,cAAc,GACd,qBAAqB,GACrB,sBAAsB,GACtB,cAAc,CAAC;AAEnB,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,mBAAmB,CAAC;IACnC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,uCAAuC;IACvC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,wCAAwC;IACxC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,WAAW,EAAE,SAAS,eAAe,EAAE,CAAC;IACjD;gGAC4F;IAC5F,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;IACjC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;CACjC;AAED;qDACqD;AACrD,wBAAgB,aAAa,CAAC,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,GAAG,eAAe,CAuF/E"}
@@ -1,43 +1,9 @@
1
- /**
2
- * Comparing two declared shapes — the R3 half of §13.
3
- *
4
- * Everything here is a pure function over `attrs`, and that is the design rather
5
- * than an accident. §13.2's mechanism is **shape comparison, not identifier
6
- * matching**, and a shape reaches this file as a list of fields with optional
7
- * per-field detail. No type here names a language, and nothing branches on one:
8
- * a Pydantic model, an OpenAPI schema and a TypeScript interface arrive
9
- * identically or they do not arrive at all.
10
- *
11
- * ## Direction is not symmetric, and getting that wrong produces noise
12
- *
13
- * A consumer that ignores a field the provider sends is **fine** — that is how
14
- * every API client on earth works. A consumer that reads a field the provider
15
- * does not send is **broken**. So the comparison takes an *expected* side and a
16
- * *provided* side, and a field present only in `provided` is not a finding.
17
- *
18
- * A symmetric diff would report every unused response field in every codebase,
19
- * which is both enormous and wrong.
20
- *
21
- * ## Detail is compared only when both sides have it
22
- *
23
- * A shape read from `attrs.fields` is a list of names — R2-grade evidence, good
24
- * enough to say *this field is missing* and nothing else. A shape read from
25
- * `attrs.fieldDetail` carries type, nullability and requiredness, which is what
26
- * a type checker buys.
27
- *
28
- * When either side lacks detail, `comparedDetail` comes back false and **no type
29
- * or nullability differences are emitted**. That flag is load-bearing: an empty
30
- * difference list is otherwise indistinguishable from "the types agree", and
31
- * reporting "no type mismatches" after comparing two lists of names is exactly
32
- * the overstatement principle 3 exists to stop.
33
- */
34
- /**
35
- * Read a shape out of a node's `attrs`, or return null if it declares none.
36
- *
37
- * Two forms, in order of richness. `fieldDetail` is what a producer emits when a
38
- * type checker or a schema gave it per-field facts; `fields` is the name-level
39
- * fallback. Anything else is not a shape and is not guessed at.
40
- */
1
+ /** R3 half of §13: comparing two declared shapes, pure over `attrs`, no language named (IR
2
+ * boundary). Asymmetric by design — a field only in `provided` is fine; one only in `expected`
3
+ * is broken. `comparedDetail` false means "no detail to compare," never "types agree" (rule 3). */
4
+ /** Reads a shape from `attrs`, or null if none declared. Two forms: `fieldDetail` (per-field
5
+ * facts from a type checker/schema) is preferred, `fields` is the name-level fallback.
6
+ * Anything else is not a shape and is not guessed at. */
41
7
  export function readShape(node) {
42
8
  const detail = readEntries(node.attrs["fieldDetail"]);
43
9
  if (detail !== null && detail.fields.length > 0) {
@@ -49,29 +15,9 @@ export function readShape(node) {
49
15
  }
50
16
  return null;
51
17
  }
52
- /**
53
- * Read a field list in either spelling a producer actually uses.
54
- *
55
- * **Measured, not anticipated.** Two shipped adapters both write
56
- * `attrs.fields` and disagree on what it holds: the contract reader writes a
57
- * list of **names** with per-field detail alongside in `fieldDetail`, and the
58
- * TypeScript adapter writes a list of **objects** (`{ name, nullable }`) under
59
- * the same key. On real repositories, **77 of 77** shape pointers resolved to a
60
- * node that plainly declared its fields, and every one read as *no shape at
61
- * all*, because the reader filtered for strings and found none.
62
- *
63
- * The silence is the part worth fixing: a reader that cannot read a node which
64
- * visibly declares fields, and says nothing, answers "no" where it should
65
- * answer "I could not tell".
66
- *
67
- * Reading both beats forcing one spelling on two adapters. `attrs` is where
68
- * language-specific detail lives and nothing above the IR may demand a single
69
- * form of it. Neither adapter changed.
70
- *
71
- * `detailed` is derived rather than declared: an entry carrying anything beyond
72
- * a name is per-field evidence. A producer emitting `{ name, nullable }` gets
73
- * nullability compared and nothing else — exactly what it supplied.
74
- */
18
+ /** Reads either spelling a producer uses for `attrs.fields` — measured: the contract reader
19
+ * writes names, the TS adapter writes objects under the same key, and before this read both,
20
+ * all 77/77 real shape pointers silently read as "no shape" instead of "could not tell". */
75
21
  function readEntries(raw) {
76
22
  if (!Array.isArray(raw))
77
23
  return null;
@@ -101,12 +47,8 @@ function readEntries(raw) {
101
47
  }
102
48
  return { fields, detailed };
103
49
  }
104
- /**
105
- * What the consuming side asks for that the providing side does not deliver.
106
- *
107
- * @param expected the shape the consumer reads
108
- * @param provided the shape the producer declares
109
- */
50
+ /** What the consumer expects that the provider doesn't deliver. `expected`: what the consumer
51
+ * reads. `provided`: what the producer declares. */
110
52
  export function compareShapes(expected, provided) {
111
53
  const byName = new Map(provided.fields.map((f) => [f.name, f]));
112
54
  const comparedDetail = expected.detailed && provided.detailed;
@@ -124,10 +66,8 @@ export function compareShapes(expected, provided) {
124
66
  });
125
67
  continue;
126
68
  }
127
- // Below here every claim is about a *shape*, which no amount of name
128
- // resolution establishes. Skipped entirely rather than compared against
129
- // undefined — `undefined !== "string"` would report a type mismatch on every
130
- // field of every name-level shape.
69
+ // Below here every claim is about a *shape* — name resolution alone can't establish it.
70
+ // Skipped rather than compared against undefined, which would type-mismatch every name-level shape.
131
71
  if (!comparedDetail)
132
72
  continue;
133
73
  if (want.type !== undefined && have.type !== undefined && want.type !== have.type) {
@@ -139,18 +79,9 @@ export function compareShapes(expected, provided) {
139
79
  detail: `"${want.name}" is read as ${want.type} and declared as ${have.type}.`,
140
80
  });
141
81
  }
142
- // Cardinality, and **unlike nullability this one is symmetric**. A consumer
143
- // that iterates what the provider sends as a single object breaks, and a
144
- // consumer that reads fields off what the provider sends as an array breaks
145
- // too. Neither direction is the safe one, so both are reported.
146
- //
147
- // Compared only when **both sides say**. An absent `list` is *unknown*, not
148
- // `false`. A producer that never emits the flag would otherwise read as
149
- // declaring every field singular, and every array field on the other side
150
- // would come back as a finding — the 77-of-77 conflation running the other
151
- // way. There the reader saw no shape and answered "no fields"; here it
152
- // would see no flag and answer "not a list". Absence of evidence is allowed
153
- // to stay absence of evidence.
82
+ // Cardinality is symmetric (unlike nullability) — a consumer iterating a single object, or
83
+ // reading fields off an array, both break, so both directions are reported. Compared only
84
+ // when both sides say: absent `list` is unknown, not false — same 77-of-77 absence-of-evidence rule.
154
85
  if (want.list !== undefined && have.list !== undefined && want.list !== have.list) {
155
86
  const asRead = want.list ? "a list" : "a single value";
156
87
  const asDeclared = have.list ? "a list" : "a single value";
@@ -163,9 +94,8 @@ export function compareShapes(expected, provided) {
163
94
  `${provided.source.name} as ${asDeclared}.`,
164
95
  });
165
96
  }
166
- // A field the provider may return as null and the consumer does not expect
167
- // to be null. The reverse — consumer tolerates null, provider never sends it
168
- // — is safe and is not reported.
97
+ // Provider may return null, consumer doesn't expect it. The reverse (consumer tolerates
98
+ // null, provider never sends it) is safe and not reported.
169
99
  if (want.nullable === false && have.nullable === true) {
170
100
  differences.push({
171
101
  kind: "NULLABILITY_DIFFERS",
@@ -176,9 +106,8 @@ export function compareShapes(expected, provided) {
176
106
  `${expected.source.name} reads it as though it never is.`,
177
107
  });
178
108
  }
179
- // A field the consumer requires and the provider may omit. `required` and
180
- // `nullable` assert different things — a field absent from `required` may be
181
- // *omitted*, not set to null — so they are checked apart.
109
+ // Consumer requires it, provider may omit it. `required` and `nullable` assert different
110
+ // things — absent-from-required means omitted, not null — so checked separately.
182
111
  if (want.required === true && have.required === false) {
183
112
  differences.push({
184
113
  kind: "REQUIREDNESS_DIFFERS",
@@ -1 +1 @@
1
- {"version":3,"file":"shapes.js","sourceRoot":"","sources":["../../src/contracts/shapes.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"shapes.js","sourceRoot":"","sources":["../../src/contracts/shapes.ts"],"names":[],"mappings":"AAAA;;oGAEoG;AAuBpG;;0DAE0D;AAC1D,MAAM,UAAU,SAAS,CAAC,IAAY;IACpC,MAAM,MAAM,GAAG,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC;IACtD,IAAI,MAAM,KAAK,IAAI,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAChD,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IACjE,CAAC;IACD,MAAM,MAAM,GAAG,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC;IACjD,IAAI,MAAM,KAAK,IAAI,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAChD,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC;IAC5E,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;6FAE6F;AAC7F,SAAS,WAAW,CAClB,GAAY;IAEZ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IACrC,MAAM,MAAM,GAAiB,EAAE,CAAC;IAChC,IAAI,QAAQ,GAAG,KAAK,CAAC;IAErB,KAAK,MAAM,KAAK,IAAI,GAAG,EAAE,CAAC;QACxB,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC9B,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;YAC7B,SAAS;QACX,CAAC;QACD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;YAAE,SAAS;QAC1D,MAAM,MAAM,GAAG,KAAgC,CAAC;QAChD,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;QAC5B,IAAI,OAAO,IAAI,KAAK,QAAQ;YAAE,SAAS;QAEvC,MAAM,KAAK,GAAe;YACxB,IAAI;YACJ,GAAG,CAAC,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACvE,GAAG,CAAC,OAAO,MAAM,CAAC,UAAU,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACpF,GAAG,CAAC,OAAO,MAAM,CAAC,UAAU,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACpF,GAAG,CAAC,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACzE,CAAC;QACF,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,GAAG,CAAC;YAAE,QAAQ,GAAG,IAAI,CAAC;QACnD,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACrB,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;AAC9B,CAAC;AA2BD;qDACqD;AACrD,MAAM,UAAU,aAAa,CAAC,QAAe,EAAE,QAAe;IAC5D,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAChE,MAAM,cAAc,GAAG,QAAQ,CAAC,QAAQ,IAAI,QAAQ,CAAC,QAAQ,CAAC;IAC9D,MAAM,WAAW,GAAsB,EAAE,CAAC;IAE1C,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;QACnC,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAEnC,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YACvB,WAAW,CAAC,IAAI,CAAC;gBACf,IAAI,EAAE,eAAe;gBACrB,KAAK,EAAE,IAAI,CAAC,IAAI;gBAChB,QAAQ,EAAE,SAAS;gBACnB,QAAQ,EAAE,QAAQ;gBAClB,MAAM,EACJ,IAAI,IAAI,CAAC,IAAI,kBAAkB,QAAQ,CAAC,MAAM,CAAC,IAAI,0BAA0B;oBAC7E,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,GAAG;aAC7B,CAAC,CAAC;YACH,SAAS;QACX,CAAC;QAED,wFAAwF;QACxF,oGAAoG;QACpG,IAAI,CAAC,cAAc;YAAE,SAAS;QAE9B,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,EAAE,CAAC;YAClF,WAAW,CAAC,IAAI,CAAC;gBACf,IAAI,EAAE,cAAc;gBACpB,KAAK,EAAE,IAAI,CAAC,IAAI;gBAChB,QAAQ,EAAE,IAAI,CAAC,IAAI;gBACnB,QAAQ,EAAE,IAAI,CAAC,IAAI;gBACnB,MAAM,EACJ,IAAI,IAAI,CAAC,IAAI,gBAAgB,IAAI,CAAC,IAAI,oBAAoB,IAAI,CAAC,IAAI,GAAG;aACzE,CAAC,CAAC;QACL,CAAC;QAED,2FAA2F;QAC3F,0FAA0F;QAC1F,qGAAqG;QACrG,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,EAAE,CAAC;YAClF,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,gBAAgB,CAAC;YACvD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,gBAAgB,CAAC;YAC3D,WAAW,CAAC,IAAI,CAAC;gBACf,IAAI,EAAE,cAAc;gBACpB,KAAK,EAAE,IAAI,CAAC,IAAI;gBAChB,QAAQ,EAAE,MAAM;gBAChB,QAAQ,EAAE,UAAU;gBACpB,MAAM,EACJ,IAAI,IAAI,CAAC,IAAI,kBAAkB,QAAQ,CAAC,MAAM,CAAC,IAAI,OAAO,MAAM,mBAAmB;oBACnF,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,OAAO,UAAU,GAAG;aAC9C,CAAC,CAAC;QACL,CAAC;QAED,wFAAwF;QACxF,2DAA2D;QAC3D,IAAI,IAAI,CAAC,QAAQ,KAAK,KAAK,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;YACtD,WAAW,CAAC,IAAI,CAAC;gBACf,IAAI,EAAE,qBAAqB;gBAC3B,KAAK,EAAE,IAAI,CAAC,IAAI;gBAChB,QAAQ,EAAE,UAAU;gBACpB,QAAQ,EAAE,UAAU;gBACpB,MAAM,EACJ,IAAI,IAAI,CAAC,IAAI,8BAA8B,QAAQ,CAAC,MAAM,CAAC,IAAI,QAAQ;oBACvE,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,kCAAkC;aAC5D,CAAC,CAAC;QACL,CAAC;QAED,yFAAyF;QACzF,iFAAiF;QACjF,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI,IAAI,IAAI,CAAC,QAAQ,KAAK,KAAK,EAAE,CAAC;YACtD,WAAW,CAAC,IAAI,CAAC;gBACf,IAAI,EAAE,sBAAsB;gBAC5B,KAAK,EAAE,IAAI,CAAC,IAAI;gBAChB,QAAQ,EAAE,gBAAgB;gBAC1B,QAAQ,EAAE,UAAU;gBACpB,MAAM,EACJ,IAAI,IAAI,CAAC,IAAI,oBAAoB,QAAQ,CAAC,MAAM,CAAC,IAAI,mBAAmB;oBACxE,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,iCAAiC;aAC3D,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,WAAW,CAAC,IAAI,CACd,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CACzE,CAAC;IAEF,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,cAAc,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;AACjF,CAAC"}