@ybotok/loam 0.2.0-alpha.1 → 0.2.0-alpha.13

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 (901) hide show
  1. package/CHANGELOG.md +3448 -0
  2. package/COMPARISON.md +91 -3
  3. package/CONTRIBUTING.md +37 -0
  4. package/MIGRATING-from-OpenSpec.md +47 -23
  5. package/QUICKSTART.md +189 -12
  6. package/README.md +274 -65
  7. package/ROADMAP.md +572 -31
  8. package/SCHEMA.md +1709 -155
  9. package/WORKFLOW.md +298 -72
  10. package/dist/cli.js +26 -8
  11. package/dist/cli.js.map +1 -1
  12. package/dist/commands/adopt/adopt.js +5 -10
  13. package/dist/commands/adopt/adopt.js.map +1 -1
  14. package/dist/commands/adopt/render.js +50 -9
  15. package/dist/commands/adopt/render.js.map +1 -1
  16. package/dist/commands/archive/archive.js +16 -19
  17. package/dist/commands/archive/archive.js.map +1 -1
  18. package/dist/commands/archive/closing.js +42 -0
  19. package/dist/commands/archive/closing.js.map +1 -0
  20. package/dist/commands/archive/plan/contracts/asyncapi.js +36 -42
  21. package/dist/commands/archive/plan/contracts/asyncapi.js.map +1 -1
  22. package/dist/commands/archive/plan/contracts/consumers.js +56 -0
  23. package/dist/commands/archive/plan/contracts/consumers.js.map +1 -0
  24. package/dist/commands/archive/plan/contracts/openapi.js +77 -43
  25. package/dist/commands/archive/plan/contracts/openapi.js.map +1 -1
  26. package/dist/commands/archive/plan/contracts/verdict-lines.js +103 -0
  27. package/dist/commands/archive/plan/contracts/verdict-lines.js.map +1 -0
  28. package/dist/commands/archive/plan/document/head.js +151 -0
  29. package/dist/commands/archive/plan/document/head.js.map +1 -0
  30. package/dist/commands/archive/plan/document/links.js +284 -0
  31. package/dist/commands/archive/plan/document/links.js.map +1 -0
  32. package/dist/commands/archive/plan/document/run.js +136 -0
  33. package/dist/commands/archive/plan/document/run.js.map +1 -0
  34. package/dist/commands/archive/plan/gate.js +21 -19
  35. package/dist/commands/archive/plan/gate.js.map +1 -1
  36. package/dist/commands/archive/plan/landscape.js +167 -30
  37. package/dist/commands/archive/plan/landscape.js.map +1 -1
  38. package/dist/commands/archive/plan/model/extending.js +85 -0
  39. package/dist/commands/archive/plan/model/extending.js.map +1 -0
  40. package/dist/commands/archive/plan/refusal.js +14 -19
  41. package/dist/commands/archive/plan/refusal.js.map +1 -1
  42. package/dist/commands/archive/plan/specs.js +137 -56
  43. package/dist/commands/archive/plan/specs.js.map +1 -1
  44. package/dist/commands/archive/plan/state.js +3 -0
  45. package/dist/commands/archive/plan/state.js.map +1 -1
  46. package/dist/commands/archive/run.js +134 -30
  47. package/dist/commands/archive/run.js.map +1 -1
  48. package/dist/commands/archive/shipped.js +49 -0
  49. package/dist/commands/archive/shipped.js.map +1 -0
  50. package/dist/commands/context/context.js +85 -18
  51. package/dist/commands/context/context.js.map +1 -1
  52. package/dist/commands/context/print.js +29 -7
  53. package/dist/commands/context/print.js.map +1 -1
  54. package/dist/commands/delta/delta.js +102 -14
  55. package/dist/commands/delta/delta.js.map +1 -1
  56. package/dist/commands/delta/print.js +17 -1
  57. package/dist/commands/delta/print.js.map +1 -1
  58. package/dist/commands/dependencies.js +3 -7
  59. package/dist/commands/dependencies.js.map +1 -1
  60. package/dist/commands/diff/diff.js +20 -27
  61. package/dist/commands/diff/diff.js.map +1 -1
  62. package/dist/commands/doctor.js +60 -1
  63. package/dist/commands/doctor.js.map +1 -1
  64. package/dist/commands/explain/explain.js +89 -13
  65. package/dist/commands/explain/explain.js.map +1 -1
  66. package/dist/commands/explore.js +16 -10
  67. package/dist/commands/explore.js.map +1 -1
  68. package/dist/commands/gate/gate.js +45 -8
  69. package/dist/commands/gate/gate.js.map +1 -1
  70. package/dist/commands/gate/print.js +15 -3
  71. package/dist/commands/gate/print.js.map +1 -1
  72. package/dist/commands/gherkin/commit.js +13 -54
  73. package/dist/commands/gherkin/commit.js.map +1 -1
  74. package/dist/commands/gherkin/gherkin.js +36 -20
  75. package/dist/commands/gherkin/gherkin.js.map +1 -1
  76. package/dist/commands/gherkin/reconcile.js +10 -13
  77. package/dist/commands/gherkin/reconcile.js.map +1 -1
  78. package/dist/commands/init/first-hour.js +44 -0
  79. package/dist/commands/init/first-hour.js.map +1 -1
  80. package/dist/commands/init/init.js +18 -22
  81. package/dist/commands/init/init.js.map +1 -1
  82. package/dist/commands/list/campaign/campaign.js +4 -6
  83. package/dist/commands/list/campaign/campaign.js.map +1 -1
  84. package/dist/commands/list/json.js +5 -7
  85. package/dist/commands/list/json.js.map +1 -1
  86. package/dist/commands/list/list.js +44 -29
  87. package/dist/commands/list/list.js.map +1 -1
  88. package/dist/commands/list/print.js +52 -9
  89. package/dist/commands/list/print.js.map +1 -1
  90. package/dist/commands/list/suites/suites.js +140 -0
  91. package/dist/commands/list/suites/suites.js.map +1 -0
  92. package/dist/commands/list/views.js +37 -34
  93. package/dist/commands/list/views.js.map +1 -1
  94. package/dist/commands/mcp/dispatch.js +91 -36
  95. package/dist/commands/mcp/dispatch.js.map +1 -1
  96. package/dist/commands/mcp/mcp.js +56 -15
  97. package/dist/commands/mcp/mcp.js.map +1 -1
  98. package/dist/commands/mcp/serve.js.map +1 -1
  99. package/dist/commands/migrate-openspec/materialize/active.js +27 -22
  100. package/dist/commands/migrate-openspec/materialize/active.js.map +1 -1
  101. package/dist/commands/migrate-openspec/materialize/stage.js +4 -3
  102. package/dist/commands/migrate-openspec/materialize/stage.js.map +1 -1
  103. package/dist/commands/migrate-openspec/materialize/target.js +2 -2
  104. package/dist/commands/migrate-openspec/materialize/target.js.map +1 -1
  105. package/dist/commands/migrate-openspec/openspec/decisions.js +9 -14
  106. package/dist/commands/migrate-openspec/openspec/decisions.js.map +1 -1
  107. package/dist/commands/migrate-openspec/openspec/error.js +7 -8
  108. package/dist/commands/migrate-openspec/openspec/error.js.map +1 -1
  109. package/dist/commands/migrate-openspec/openspec/mapping.js +1 -9
  110. package/dist/commands/migrate-openspec/openspec/mapping.js.map +1 -1
  111. package/dist/commands/migrate-openspec/openspec/paths.js +3 -6
  112. package/dist/commands/migrate-openspec/openspec/paths.js.map +1 -1
  113. package/dist/commands/new/capability-template.js +118 -0
  114. package/dist/commands/new/capability-template.js.map +1 -0
  115. package/dist/commands/new/commit.js +8 -22
  116. package/dist/commands/new/commit.js.map +1 -1
  117. package/dist/commands/new/modifies.js +206 -0
  118. package/dist/commands/new/modifies.js.map +1 -0
  119. package/dist/commands/new/new.js +59 -14
  120. package/dist/commands/new/new.js.map +1 -1
  121. package/dist/commands/new/templates.js +48 -124
  122. package/dist/commands/new/templates.js.map +1 -1
  123. package/dist/commands/open.js +3 -7
  124. package/dist/commands/open.js.map +1 -1
  125. package/dist/commands/policy/gate.js +27 -0
  126. package/dist/commands/policy/gate.js.map +1 -1
  127. package/dist/commands/rebase/plan.js +2 -2
  128. package/dist/commands/rebase/plan.js.map +1 -1
  129. package/dist/commands/rebase/rebase.js +60 -35
  130. package/dist/commands/rebase/rebase.js.map +1 -1
  131. package/dist/commands/seed/commit.js +55 -26
  132. package/dist/commands/seed/commit.js.map +1 -1
  133. package/dist/commands/seed/plan.js +158 -13
  134. package/dist/commands/seed/plan.js.map +1 -1
  135. package/dist/commands/seed/seed.js +13 -11
  136. package/dist/commands/seed/seed.js.map +1 -1
  137. package/dist/commands/show/feature.js +9 -5
  138. package/dist/commands/show/feature.js.map +1 -1
  139. package/dist/commands/show/introduced.js +157 -0
  140. package/dist/commands/show/introduced.js.map +1 -0
  141. package/dist/commands/show/marks.js +35 -6
  142. package/dist/commands/show/marks.js.map +1 -1
  143. package/dist/commands/show/service.js +41 -33
  144. package/dist/commands/show/service.js.map +1 -1
  145. package/dist/commands/show/show.js +17 -7
  146. package/dist/commands/show/show.js.map +1 -1
  147. package/dist/commands/status/fleet-next.js +90 -0
  148. package/dist/commands/status/fleet-next.js.map +1 -0
  149. package/dist/commands/status/json.js +2 -0
  150. package/dist/commands/status/json.js.map +1 -1
  151. package/dist/commands/status/print.js +89 -37
  152. package/dist/commands/status/print.js.map +1 -1
  153. package/dist/commands/status/status.js +3 -7
  154. package/dist/commands/status/status.js.map +1 -1
  155. package/dist/commands/steps/steps.js +103 -23
  156. package/dist/commands/steps/steps.js.map +1 -1
  157. package/dist/commands/subsystem/edit.js +7 -7
  158. package/dist/commands/subsystem/edit.js.map +1 -1
  159. package/dist/commands/subsystem/move.js +106 -46
  160. package/dist/commands/subsystem/move.js.map +1 -1
  161. package/dist/commands/subsystem/query.js +2 -4
  162. package/dist/commands/subsystem/query.js.map +1 -1
  163. package/dist/commands/subsystem/subsystem.js +4 -7
  164. package/dist/commands/subsystem/subsystem.js.map +1 -1
  165. package/dist/commands/subsystem/sync.js +289 -74
  166. package/dist/commands/subsystem/sync.js.map +1 -1
  167. package/dist/commands/subsystem/txn/exclude.js +132 -0
  168. package/dist/commands/subsystem/txn/exclude.js.map +1 -0
  169. package/dist/commands/subsystem/txn/links.js +128 -0
  170. package/dist/commands/subsystem/txn/links.js.map +1 -0
  171. package/dist/commands/subsystem/txn/report.js +174 -0
  172. package/dist/commands/subsystem/txn/report.js.map +1 -0
  173. package/dist/commands/subsystem/txn/txn.js +147 -45
  174. package/dist/commands/subsystem/txn/txn.js.map +1 -1
  175. package/dist/commands/subsystem/txn/views.js +200 -21
  176. package/dist/commands/subsystem/txn/views.js.map +1 -1
  177. package/dist/commands/tasks/actions.js +107 -0
  178. package/dist/commands/tasks/actions.js.map +1 -0
  179. package/dist/commands/tasks/render.js +253 -0
  180. package/dist/commands/tasks/render.js.map +1 -0
  181. package/dist/commands/tasks/tasks.js +119 -0
  182. package/dist/commands/tasks/tasks.js.map +1 -0
  183. package/dist/commands/unarchive/manifest.js +42 -26
  184. package/dist/commands/unarchive/manifest.js.map +1 -1
  185. package/dist/commands/unarchive/restore.js +83 -33
  186. package/dist/commands/unarchive/restore.js.map +1 -1
  187. package/dist/commands/unarchive/unarchive.js +22 -30
  188. package/dist/commands/unarchive/unarchive.js.map +1 -1
  189. package/dist/commands/validate/arch-coverage.js +78 -27
  190. package/dist/commands/validate/arch-coverage.js.map +1 -1
  191. package/dist/commands/validate/checks/fleet-shape.js +34 -126
  192. package/dist/commands/validate/checks/fleet-shape.js.map +1 -1
  193. package/dist/commands/validate/checks/health-deps.js +9 -6
  194. package/dist/commands/validate/checks/health-deps.js.map +1 -1
  195. package/dist/commands/validate/checks/introduced.js +102 -0
  196. package/dist/commands/validate/checks/introduced.js.map +1 -0
  197. package/dist/commands/validate/checks/requirements.js +18 -8
  198. package/dist/commands/validate/checks/requirements.js.map +1 -1
  199. package/dist/commands/validate/checks/sources.js +11 -2
  200. package/dist/commands/validate/checks/sources.js.map +1 -1
  201. package/dist/commands/validate/coverage/covers-after.js +105 -0
  202. package/dist/commands/validate/coverage/covers-after.js.map +1 -0
  203. package/dist/commands/validate/feature.js +26 -20
  204. package/dist/commands/validate/feature.js.map +1 -1
  205. package/dist/commands/validate/fleet/census.js +37 -13
  206. package/dist/commands/validate/fleet/census.js.map +1 -1
  207. package/dist/commands/validate/fleet/landscape.js +144 -126
  208. package/dist/commands/validate/fleet/landscape.js.map +1 -1
  209. package/dist/commands/validate/fleet/load.js +66 -0
  210. package/dist/commands/validate/fleet/load.js.map +1 -1
  211. package/dist/commands/validate/fleet/map/attest.js +98 -0
  212. package/dist/commands/validate/fleet/map/attest.js.map +1 -0
  213. package/dist/commands/validate/fleet/map/bindings.js +107 -0
  214. package/dist/commands/validate/fleet/map/bindings.js.map +1 -0
  215. package/dist/commands/validate/fleet/map/consumers.js +244 -0
  216. package/dist/commands/validate/fleet/map/consumers.js.map +1 -0
  217. package/dist/commands/validate/fleet/map/isolation.js +116 -0
  218. package/dist/commands/validate/fleet/map/isolation.js.map +1 -0
  219. package/dist/commands/validate/fleet/map/usecases.js +54 -0
  220. package/dist/commands/validate/fleet/map/usecases.js.map +1 -0
  221. package/dist/commands/validate/fleet/obligations.js +44 -14
  222. package/dist/commands/validate/fleet/obligations.js.map +1 -1
  223. package/dist/commands/validate/fleet/scorecard/print.js +10 -2
  224. package/dist/commands/validate/fleet/scorecard/print.js.map +1 -1
  225. package/dist/commands/validate/fleet/scorecard/scorecard.js +17 -11
  226. package/dist/commands/validate/fleet/scorecard/scorecard.js.map +1 -1
  227. package/dist/commands/validate/fleet/usecases/place.js.map +1 -1
  228. package/dist/commands/validate/fleet/views/fleet-project.js +217 -0
  229. package/dist/commands/validate/fleet/views/fleet-project.js.map +1 -0
  230. package/dist/commands/validate/fleet/views/ids.js +50 -15
  231. package/dist/commands/validate/fleet/views/ids.js.map +1 -1
  232. package/dist/commands/validate/fleet/views/projects.js +278 -0
  233. package/dist/commands/validate/fleet/views/projects.js.map +1 -0
  234. package/dist/commands/validate/fleet/views/root-documents.js +83 -0
  235. package/dist/commands/validate/fleet/views/root-documents.js.map +1 -0
  236. package/dist/commands/validate/fleet/views/stale.js +40 -47
  237. package/dist/commands/validate/fleet/views/stale.js.map +1 -1
  238. package/dist/commands/validate/links/corpus.js +1 -4
  239. package/dist/commands/validate/links/corpus.js.map +1 -1
  240. package/dist/commands/validate/links/glossary.js.map +1 -1
  241. package/dist/commands/validate/render/repeats.js +63 -0
  242. package/dist/commands/validate/render/repeats.js.map +1 -0
  243. package/dist/commands/validate/render/rollups.js +115 -0
  244. package/dist/commands/validate/render/rollups.js.map +1 -0
  245. package/dist/commands/validate/render/text.js +199 -0
  246. package/dist/commands/validate/render/text.js.map +1 -0
  247. package/dist/commands/validate/report.js +36 -160
  248. package/dist/commands/validate/report.js.map +1 -1
  249. package/dist/commands/validate/scope.js +113 -0
  250. package/dist/commands/validate/scope.js.map +1 -0
  251. package/dist/commands/validate/service/api.js +21 -107
  252. package/dist/commands/validate/service/api.js.map +1 -1
  253. package/dist/commands/validate/service/contracts/generated.js +134 -0
  254. package/dist/commands/validate/service/contracts/generated.js.map +1 -0
  255. package/dist/commands/validate/service/events/events.js +36 -14
  256. package/dist/commands/validate/service/events/events.js.map +1 -1
  257. package/dist/commands/validate/service/events/message-producers.js +1 -1
  258. package/dist/commands/validate/service/events/message-producers.js.map +1 -1
  259. package/dist/commands/validate/service/evidence-pins.js +56 -10
  260. package/dist/commands/validate/service/evidence-pins.js.map +1 -1
  261. package/dist/commands/validate/service/model/diverged.js +226 -0
  262. package/dist/commands/validate/service/model/diverged.js.map +1 -0
  263. package/dist/commands/validate/service/model/grade.js +163 -0
  264. package/dist/commands/validate/service/model/grade.js.map +1 -0
  265. package/dist/commands/validate/service/service.js +121 -61
  266. package/dist/commands/validate/service/service.js.map +1 -1
  267. package/dist/commands/validate/service/specs.js +88 -28
  268. package/dist/commands/validate/service/specs.js.map +1 -1
  269. package/dist/commands/validate/service/spine.js +38 -3
  270. package/dist/commands/validate/service/spine.js.map +1 -1
  271. package/dist/commands/validate/service/usecases/tags.js +113 -0
  272. package/dist/commands/validate/service/usecases/tags.js.map +1 -0
  273. package/dist/commands/validate/service/usecases/usecases.js +209 -0
  274. package/dist/commands/validate/service/usecases/usecases.js.map +1 -0
  275. package/dist/commands/validate/validate.js +85 -60
  276. package/dist/commands/validate/validate.js.map +1 -1
  277. package/dist/commands/verify/cross/diff.js +2 -6
  278. package/dist/commands/verify/cross/diff.js.map +1 -1
  279. package/dist/commands/verify/evidence/contract.js +1 -1
  280. package/dist/commands/verify/evidence/contract.js.map +1 -1
  281. package/dist/commands/verify/evidence/read.js +12 -3
  282. package/dist/commands/verify/evidence/read.js.map +1 -1
  283. package/dist/commands/verify/frozen.js +45 -23
  284. package/dist/commands/verify/frozen.js.map +1 -1
  285. package/dist/commands/verify/record.js +69 -17
  286. package/dist/commands/verify/record.js.map +1 -1
  287. package/dist/commands/verify/report.js +27 -44
  288. package/dist/commands/verify/report.js.map +1 -1
  289. package/dist/commands/verify/results.js +112 -30
  290. package/dist/commands/verify/results.js.map +1 -1
  291. package/dist/commands/verify/verify.js +55 -52
  292. package/dist/commands/verify/verify.js.map +1 -1
  293. package/dist/commands/vouch/pack/pack.js +2 -2
  294. package/dist/commands/vouch/pack/pack.js.map +1 -1
  295. package/dist/commands/vouch/pack/print.js +1 -6
  296. package/dist/commands/vouch/pack/print.js.map +1 -1
  297. package/dist/commands/vouch/pack/sections.js +1 -2
  298. package/dist/commands/vouch/pack/sections.js.map +1 -1
  299. package/dist/commands/vouch/run.js +26 -81
  300. package/dist/commands/vouch/run.js.map +1 -1
  301. package/dist/commands/vouch/sample/plan.js +20 -34
  302. package/dist/commands/vouch/sample/plan.js.map +1 -1
  303. package/dist/commands/vouch/vet/verify.js +39 -7
  304. package/dist/commands/vouch/vet/verify.js.map +1 -1
  305. package/dist/commands/vouch/vouch.js +10 -17
  306. package/dist/commands/vouch/vouch.js.map +1 -1
  307. package/dist/core/agent/agents-md/command-map.js +81 -106
  308. package/dist/core/agent/agents-md/command-map.js.map +1 -1
  309. package/dist/core/agent/agents-md/map/explain.js +21 -9
  310. package/dist/core/agent/agents-md/map/explain.js.map +1 -1
  311. package/dist/core/agent/agents-md/map/lenses/context.js +17 -8
  312. package/dist/core/agent/agents-md/map/lenses/context.js.map +1 -1
  313. package/dist/core/agent/agents-md/map/lenses/diff.js +33 -20
  314. package/dist/core/agent/agents-md/map/lenses/diff.js.map +1 -1
  315. package/dist/core/agent/agents-md/map/lenses/gate.js +13 -5
  316. package/dist/core/agent/agents-md/map/lenses/gate.js.map +1 -1
  317. package/dist/core/agent/agents-md/map/mcp.js +10 -7
  318. package/dist/core/agent/agents-md/map/mcp.js.map +1 -1
  319. package/dist/core/agent/agents-md/map/status.js +24 -8
  320. package/dist/core/agent/agents-md/map/status.js.map +1 -1
  321. package/dist/core/agent/agents-md/map/subsystem.js +80 -8
  322. package/dist/core/agent/agents-md/map/subsystem.js.map +1 -1
  323. package/dist/core/agent/agents-md/map/usecases.js +88 -10
  324. package/dist/core/agent/agents-md/map/usecases.js.map +1 -1
  325. package/dist/core/agent/agents-md/refusals.js +49 -22
  326. package/dist/core/agent/agents-md/refusals.js.map +1 -1
  327. package/dist/core/agent/agents-md.js +39 -6
  328. package/dist/core/agent/agents-md.js.map +1 -1
  329. package/dist/core/agent/agents-stamp.js +10 -0
  330. package/dist/core/agent/agents-stamp.js.map +1 -1
  331. package/dist/core/agent/protocol.js +1 -1
  332. package/dist/core/agent/protocol.js.map +1 -1
  333. package/dist/core/agent/scaffold.js +10 -15
  334. package/dist/core/agent/scaffold.js.map +1 -1
  335. package/dist/core/agent/support/report.js +46 -5
  336. package/dist/core/agent/support/report.js.map +1 -1
  337. package/dist/core/agent/tools/dialects.js +1 -0
  338. package/dist/core/agent/tools/dialects.js.map +1 -1
  339. package/dist/core/agent/tools/registry.js +41 -76
  340. package/dist/core/agent/tools/registry.js.map +1 -1
  341. package/dist/core/agent/workflows/adopt.js +158 -11
  342. package/dist/core/agent/workflows/adopt.js.map +1 -1
  343. package/dist/core/agent/workflows/check.js +78 -39
  344. package/dist/core/agent/workflows/check.js.map +1 -1
  345. package/dist/core/agent/workflows/closing.js +88 -27
  346. package/dist/core/agent/workflows/closing.js.map +1 -1
  347. package/dist/core/agent/workflows/feature.js +128 -13
  348. package/dist/core/agent/workflows/feature.js.map +1 -1
  349. package/dist/core/agent/workflows/implement.js +96 -13
  350. package/dist/core/agent/workflows/implement.js.map +1 -1
  351. package/dist/core/agent/workflows/reference/authoring.js +106 -4
  352. package/dist/core/agent/workflows/reference/authoring.js.map +1 -1
  353. package/dist/core/agent/workflows/reference/codes.js +8 -6
  354. package/dist/core/agent/workflows/reference/codes.js.map +1 -1
  355. package/dist/core/agent/workflows/reference/done-check.js +37 -15
  356. package/dist/core/agent/workflows/reference/done-check.js.map +1 -1
  357. package/dist/core/agent/workflows/reference/drawing/drawing.js +253 -0
  358. package/dist/core/agent/workflows/reference/drawing/drawing.js.map +1 -0
  359. package/dist/core/agent/workflows/reference/reference.js +6 -3
  360. package/dist/core/agent/workflows/reference/reference.js.map +1 -1
  361. package/dist/core/agent/workflows/reference/spine.js +68 -27
  362. package/dist/core/agent/workflows/reference/spine.js.map +1 -1
  363. package/dist/core/asyncapi/baseline/plan.js +14 -81
  364. package/dist/core/asyncapi/baseline/plan.js.map +1 -1
  365. package/dist/core/asyncapi/digest.js +30 -25
  366. package/dist/core/asyncapi/digest.js.map +1 -1
  367. package/dist/core/asyncapi/merge/components.js +5 -4
  368. package/dist/core/asyncapi/merge/components.js.map +1 -1
  369. package/dist/core/asyncapi/merge/error.js +7 -2
  370. package/dist/core/asyncapi/merge/error.js.map +1 -1
  371. package/dist/core/asyncapi/merge/markers.js +32 -50
  372. package/dist/core/asyncapi/merge/markers.js.map +1 -1
  373. package/dist/core/asyncapi/merge/merge.js +33 -53
  374. package/dist/core/asyncapi/merge/merge.js.map +1 -1
  375. package/dist/core/asyncapi/merge/pin.js +12 -36
  376. package/dist/core/asyncapi/merge/pin.js.map +1 -1
  377. package/dist/core/asyncapi/model.js.map +1 -1
  378. package/dist/core/asyncapi/read.js +36 -12
  379. package/dist/core/asyncapi/read.js.map +1 -1
  380. package/dist/core/brief/brief.js +96 -36
  381. package/dist/core/brief/brief.js.map +1 -1
  382. package/dist/core/brief/checks.js +138 -3
  383. package/dist/core/brief/checks.js.map +1 -1
  384. package/dist/core/brief/landscape.js +209 -130
  385. package/dist/core/brief/landscape.js.map +1 -1
  386. package/dist/core/brief/map/extend.js +84 -0
  387. package/dist/core/brief/map/extend.js.map +1 -0
  388. package/dist/core/brief/map/owed.js +266 -0
  389. package/dist/core/brief/map/owed.js.map +1 -0
  390. package/dist/core/brief/targets.js +109 -31
  391. package/dist/core/brief/targets.js.map +1 -1
  392. package/dist/core/brief/unchecked.js +14 -3
  393. package/dist/core/brief/unchecked.js.map +1 -1
  394. package/dist/core/c4/arch.js +90 -182
  395. package/dist/core/c4/arch.js.map +1 -1
  396. package/dist/core/c4/direction/direction.js +114 -0
  397. package/dist/core/c4/direction/direction.js.map +1 -0
  398. package/dist/core/c4/likec4.js +169 -14
  399. package/dist/core/c4/likec4.js.map +1 -1
  400. package/dist/core/c4/locate/unlocated.js +150 -0
  401. package/dist/core/c4/locate/unlocated.js.map +1 -0
  402. package/dist/core/c4/parsed/deployment.js +160 -0
  403. package/dist/core/c4/parsed/deployment.js.map +1 -0
  404. package/dist/core/c4/parsed/dynamic-views.js.map +1 -1
  405. package/dist/core/c4/parsed/values.js +54 -1
  406. package/dist/core/c4/parsed/values.js.map +1 -1
  407. package/dist/core/c4/parsed/view-ids.js +39 -1
  408. package/dist/core/c4/parsed/view-ids.js.map +1 -1
  409. package/dist/core/c4/prefetch/fleet.js +134 -0
  410. package/dist/core/c4/prefetch/fleet.js.map +1 -0
  411. package/dist/core/c4/project/architecture.js +123 -7
  412. package/dist/core/c4/project/architecture.js.map +1 -1
  413. package/dist/core/c4/project/batch.js +140 -0
  414. package/dist/core/c4/project/batch.js.map +1 -0
  415. package/dist/core/c4/project/documents.js +43 -12
  416. package/dist/core/c4/project/documents.js.map +1 -1
  417. package/dist/core/c4/project/load.js +79 -43
  418. package/dist/core/c4/project/load.js.map +1 -1
  419. package/dist/core/c4/project/staged.js +277 -0
  420. package/dist/core/c4/project/staged.js.map +1 -0
  421. package/dist/core/c4/resolve/attested.js +0 -0
  422. package/dist/core/c4/resolve/attested.js.map +1 -0
  423. package/dist/core/c4/resolve/external.js +51 -0
  424. package/dist/core/c4/resolve/external.js.map +1 -0
  425. package/dist/core/c4/resolve/service.js +78 -17
  426. package/dist/core/c4/resolve/service.js.map +1 -1
  427. package/dist/core/c4/resolve/steps.js +290 -0
  428. package/dist/core/c4/resolve/steps.js.map +1 -0
  429. package/dist/core/c4/resolve/systems.js +154 -0
  430. package/dist/core/c4/resolve/systems.js.map +1 -0
  431. package/dist/core/c4/root-project/exclude.js +352 -0
  432. package/dist/core/c4/root-project/exclude.js.map +1 -0
  433. package/dist/core/c4/seed/template.js +65 -1
  434. package/dist/core/c4/seed/template.js.map +1 -1
  435. package/dist/core/c4/service-model/created/models.js +96 -0
  436. package/dist/core/c4/service-model/created/models.js.map +1 -0
  437. package/dist/core/c4/service-model/documents.js +47 -0
  438. package/dist/core/c4/service-model/documents.js.map +1 -0
  439. package/dist/core/c4/service-model/fleet/extending.js +82 -0
  440. package/dist/core/c4/service-model/fleet/extending.js.map +1 -0
  441. package/dist/core/c4/service-model/load.js +165 -0
  442. package/dist/core/c4/service-model/load.js.map +1 -0
  443. package/dist/core/c4/service-model/renderer.js +128 -0
  444. package/dist/core/c4/service-model/renderer.js.map +1 -0
  445. package/dist/core/c4/service-model/shape.js +106 -0
  446. package/dist/core/c4/service-model/shape.js.map +1 -0
  447. package/dist/core/c4/service-model/slice.js +188 -0
  448. package/dist/core/c4/service-model/slice.js.map +1 -0
  449. package/dist/core/c4/source-mask.js +297 -10
  450. package/dist/core/c4/source-mask.js.map +1 -1
  451. package/dist/core/c4/source-scan.js +222 -141
  452. package/dist/core/c4/source-scan.js.map +1 -1
  453. package/dist/core/c4/splice/authored-source.js +79 -13
  454. package/dist/core/c4/splice/authored-source.js.map +1 -1
  455. package/dist/core/c4/splice/contract.js +20 -0
  456. package/dist/core/c4/splice/contract.js.map +1 -1
  457. package/dist/core/c4/splice/delta-blocks.js +20 -20
  458. package/dist/core/c4/splice/delta-blocks.js.map +1 -1
  459. package/dist/core/c4/splice/identity/declared.js +87 -0
  460. package/dist/core/c4/splice/identity/declared.js.map +1 -0
  461. package/dist/core/c4/splice/identity/edges.js +37 -0
  462. package/dist/core/c4/splice/identity/edges.js.map +1 -1
  463. package/dist/core/c4/splice/identity/existing.js +80 -0
  464. package/dist/core/c4/splice/identity/existing.js.map +1 -0
  465. package/dist/core/c4/splice/identity/interior.js +80 -0
  466. package/dist/core/c4/splice/identity/interior.js.map +1 -0
  467. package/dist/core/c4/splice/identity/owner.js +50 -0
  468. package/dist/core/c4/splice/identity/owner.js.map +1 -0
  469. package/dist/core/c4/splice/landscape-merge.js +182 -114
  470. package/dist/core/c4/splice/landscape-merge.js.map +1 -1
  471. package/dist/core/c4/splice/model/merge.js +151 -0
  472. package/dist/core/c4/splice/model/merge.js.map +1 -0
  473. package/dist/core/c4/splice/placement.js +160 -56
  474. package/dist/core/c4/splice/placement.js.map +1 -1
  475. package/dist/core/c4/splice/text/spot.js +131 -0
  476. package/dist/core/c4/splice/text/spot.js.map +1 -0
  477. package/dist/core/c4/workspace.js +13 -19
  478. package/dist/core/c4/workspace.js.map +1 -1
  479. package/dist/core/capabilities/capabilities.js +6 -6
  480. package/dist/core/capabilities/capabilities.js.map +1 -1
  481. package/dist/core/capabilities/delta/doc.js +7 -10
  482. package/dist/core/capabilities/delta/doc.js.map +1 -1
  483. package/dist/core/capabilities/delta/uncovered.js +2 -2
  484. package/dist/core/capabilities/delta/uncovered.js.map +1 -1
  485. package/dist/core/capabilities/findings.js +18 -22
  486. package/dist/core/capabilities/findings.js.map +1 -1
  487. package/dist/core/capabilities/realizes/findings.js +12 -19
  488. package/dist/core/capabilities/realizes/findings.js.map +1 -1
  489. package/dist/core/capabilities/realizes/join.js +0 -20
  490. package/dist/core/capabilities/realizes/join.js.map +1 -1
  491. package/dist/core/capabilities/rollup.js +6 -0
  492. package/dist/core/capabilities/rollup.js.map +1 -1
  493. package/dist/core/capabilities/tree.js +6 -28
  494. package/dist/core/capabilities/tree.js.map +1 -1
  495. package/dist/core/capabilities/usecase-join.js +3 -13
  496. package/dist/core/capabilities/usecase-join.js.map +1 -1
  497. package/dist/core/coherence/authoring/scaffold.js +11 -3
  498. package/dist/core/coherence/authoring/scaffold.js.map +1 -1
  499. package/dist/core/coherence/authoring/sentinels.js +2 -1
  500. package/dist/core/coherence/authoring/sentinels.js.map +1 -1
  501. package/dist/core/coherence/calls/called.js +52 -0
  502. package/dist/core/coherence/calls/called.js.map +1 -0
  503. package/dist/core/coherence/coherence.js +103 -22
  504. package/dist/core/coherence/coherence.js.map +1 -1
  505. package/dist/core/coherence/consumed/operations.js +70 -0
  506. package/dist/core/coherence/consumed/operations.js.map +1 -0
  507. package/dist/core/coherence/consumed/refusal.js +38 -0
  508. package/dist/core/coherence/consumed/refusal.js.map +1 -0
  509. package/dist/core/coherence/covers/health.js +85 -0
  510. package/dist/core/coherence/covers/health.js.map +1 -0
  511. package/dist/core/coherence/declared.js +60 -34
  512. package/dist/core/coherence/declared.js.map +1 -1
  513. package/dist/core/coherence/events/declared.js +44 -59
  514. package/dist/core/coherence/events/declared.js.map +1 -1
  515. package/dist/core/coherence/events/events.js +147 -16
  516. package/dist/core/coherence/events/events.js.map +1 -1
  517. package/dist/core/coherence/events/grades.js +31 -8
  518. package/dist/core/coherence/events/grades.js.map +1 -1
  519. package/dist/core/coherence/events/lookups.js +28 -87
  520. package/dist/core/coherence/events/lookups.js.map +1 -1
  521. package/dist/core/coherence/events/produced.js +100 -0
  522. package/dist/core/coherence/events/produced.js.map +1 -0
  523. package/dist/core/coherence/lookups.js +18 -78
  524. package/dist/core/coherence/lookups.js.map +1 -1
  525. package/dist/core/coherence/retired/archived.js +285 -0
  526. package/dist/core/coherence/retired/archived.js.map +1 -0
  527. package/dist/core/coherence/retired/event-pair.js +62 -0
  528. package/dist/core/coherence/retired/event-pair.js.map +1 -0
  529. package/dist/core/coherence/retired/merged.js +79 -0
  530. package/dist/core/coherence/retired/merged.js.map +1 -0
  531. package/dist/core/coherence/retired/retirement.js +49 -0
  532. package/dist/core/coherence/retired/retirement.js.map +1 -0
  533. package/dist/core/coherence/retired/revival/arrivals.js +131 -0
  534. package/dist/core/coherence/retired/revival/arrivals.js.map +1 -0
  535. package/dist/core/coherence/retired/revival/revived.js +297 -0
  536. package/dist/core/coherence/retired/revival/revived.js.map +1 -0
  537. package/dist/core/consumers/after.js +113 -0
  538. package/dist/core/consumers/after.js.map +1 -0
  539. package/dist/core/consumers/consumers.js +296 -0
  540. package/dist/core/consumers/consumers.js.map +1 -0
  541. package/dist/core/consumers/current.js +211 -0
  542. package/dist/core/consumers/current.js.map +1 -0
  543. package/dist/core/consumers/scan.js +46 -0
  544. package/dist/core/consumers/scan.js.map +1 -0
  545. package/dist/core/consumers/state.js +27 -0
  546. package/dist/core/consumers/state.js.map +1 -0
  547. package/dist/core/delta/delta.js +51 -6
  548. package/dist/core/delta/delta.js.map +1 -1
  549. package/dist/core/dependencies/fanin.js +2 -2
  550. package/dist/core/dependencies/fanin.js.map +1 -1
  551. package/dist/core/deployment/delta.js +191 -0
  552. package/dist/core/deployment/delta.js.map +1 -0
  553. package/dist/core/deployment/objects.js +145 -0
  554. package/dist/core/deployment/objects.js.map +1 -0
  555. package/dist/core/diff/base-git.js +94 -12
  556. package/dist/core/diff/base-git.js.map +1 -1
  557. package/dist/core/diff/base-state.js +49 -21
  558. package/dist/core/diff/base-state.js.map +1 -1
  559. package/dist/core/diff/joins.js +136 -0
  560. package/dist/core/diff/joins.js.map +1 -0
  561. package/dist/core/diff/scope/changed-paths.js +22 -6
  562. package/dist/core/diff/scope/changed-paths.js.map +1 -1
  563. package/dist/core/diff/scope/edges.js +82 -0
  564. package/dist/core/diff/scope/edges.js.map +1 -0
  565. package/dist/core/diff/semantic.js +100 -31
  566. package/dist/core/diff/semantic.js.map +1 -1
  567. package/dist/core/docs.js +31 -22
  568. package/dist/core/docs.js.map +1 -1
  569. package/dist/core/doctor/agents.js +34 -18
  570. package/dist/core/doctor/agents.js.map +1 -1
  571. package/dist/core/doctor/config.js +7 -3
  572. package/dist/core/doctor/config.js.map +1 -1
  573. package/dist/core/doctor/doctor.js +91 -11
  574. package/dist/core/doctor/doctor.js.map +1 -1
  575. package/dist/core/doctor/report.js.map +1 -1
  576. package/dist/core/doctor/reports/scan.js +242 -0
  577. package/dist/core/doctor/reports/scan.js.map +1 -0
  578. package/dist/core/document/apply.js +158 -11
  579. package/dist/core/document/apply.js.map +1 -1
  580. package/dist/core/document/frontmatter.js +55 -0
  581. package/dist/core/document/frontmatter.js.map +1 -1
  582. package/dist/core/document/parse.js +29 -6
  583. package/dist/core/document/parse.js.map +1 -1
  584. package/dist/core/document/scenarios.js +17 -0
  585. package/dist/core/document/scenarios.js.map +1 -1
  586. package/dist/core/document/spec.js +4 -11
  587. package/dist/core/document/spec.js.map +1 -1
  588. package/dist/core/envelope/config.js +10 -0
  589. package/dist/core/envelope/config.js.map +1 -1
  590. package/dist/core/envelope/json.js +34 -0
  591. package/dist/core/envelope/json.js.map +1 -1
  592. package/dist/core/explain/families.js +26 -21
  593. package/dist/core/explain/families.js.map +1 -1
  594. package/dist/core/explain/lookup.js +14 -1
  595. package/dist/core/explain/lookup.js.map +1 -1
  596. package/dist/core/explain/refusals.js +5 -5
  597. package/dist/core/explain/refusals.js.map +1 -1
  598. package/dist/core/explain/terms/documents.js +227 -0
  599. package/dist/core/explain/terms/documents.js.map +1 -0
  600. package/dist/core/explain/terms/done-check.js +144 -0
  601. package/dist/core/explain/terms/done-check.js.map +1 -0
  602. package/dist/core/explain/terms/entry.js +14 -0
  603. package/dist/core/explain/terms/entry.js.map +1 -0
  604. package/dist/core/explain/terms/stages.js +71 -0
  605. package/dist/core/explain/terms/stages.js.map +1 -0
  606. package/dist/core/explain/terms/tasks.js +97 -0
  607. package/dist/core/explain/terms/tasks.js.map +1 -0
  608. package/dist/core/explain/terms.js +68 -109
  609. package/dist/core/explain/terms.js.map +1 -1
  610. package/dist/core/explore/explore.js +40 -10
  611. package/dist/core/explore/explore.js.map +1 -1
  612. package/dist/core/fleet-context.js +81 -95
  613. package/dist/core/fleet-context.js.map +1 -1
  614. package/dist/core/gate/checks.js +11 -4
  615. package/dist/core/gate/checks.js.map +1 -1
  616. package/dist/core/gate/partners.js +69 -28
  617. package/dist/core/gate/partners.js.map +1 -1
  618. package/dist/core/gate/report.js.map +1 -1
  619. package/dist/core/gate/verification.js +75 -12
  620. package/dist/core/gate/verification.js.map +1 -1
  621. package/dist/core/gherkin/stale.js +13 -37
  622. package/dist/core/gherkin/stale.js.map +1 -1
  623. package/dist/core/glossary/delta.js +10 -7
  624. package/dist/core/glossary/delta.js.map +1 -1
  625. package/dist/core/glossary/tree.js +6 -19
  626. package/dist/core/glossary/tree.js.map +1 -1
  627. package/dist/core/kernel/concurrency.js +19 -0
  628. package/dist/core/kernel/concurrency.js.map +1 -1
  629. package/dist/core/kernel/ids/fqn/ancestors.js +65 -0
  630. package/dist/core/kernel/ids/fqn/ancestors.js.map +1 -0
  631. package/dist/core/kernel/path-safety.js +38 -0
  632. package/dist/core/kernel/path-safety.js.map +1 -1
  633. package/dist/core/kernel/records.js +11 -0
  634. package/dist/core/kernel/records.js.map +1 -1
  635. package/dist/core/links/backlinks.js +1 -3
  636. package/dist/core/links/backlinks.js.map +1 -1
  637. package/dist/core/links/corpus.js +51 -37
  638. package/dist/core/links/corpus.js.map +1 -1
  639. package/dist/core/links/findings.js.map +1 -1
  640. package/dist/core/links/parse.js +38 -9
  641. package/dist/core/links/parse.js.map +1 -1
  642. package/dist/core/mcp/argv.js +101 -0
  643. package/dist/core/mcp/argv.js.map +1 -1
  644. package/dist/core/mcp/author-tools.js +2 -1
  645. package/dist/core/mcp/author-tools.js.map +1 -1
  646. package/dist/core/mcp/protocol.js +2 -2
  647. package/dist/core/mcp/protocol.js.map +1 -1
  648. package/dist/core/mcp/tools.js +43 -33
  649. package/dist/core/mcp/tools.js.map +1 -1
  650. package/dist/core/openapi/baseline/gate.js +53 -12
  651. package/dist/core/openapi/baseline/gate.js.map +1 -1
  652. package/dist/core/openapi/baseline/plan.js +40 -10
  653. package/dist/core/openapi/baseline/plan.js.map +1 -1
  654. package/dist/core/openapi/baseline/record.js +0 -1
  655. package/dist/core/openapi/baseline/record.js.map +1 -1
  656. package/dist/core/openapi/contract-text.js +33 -0
  657. package/dist/core/openapi/contract-text.js.map +1 -0
  658. package/dist/core/openapi/contract-tree.js +301 -0
  659. package/dist/core/openapi/contract-tree.js.map +1 -0
  660. package/dist/core/openapi/depth.js +38 -24
  661. package/dist/core/openapi/depth.js.map +1 -1
  662. package/dist/core/openapi/digest.js +52 -2
  663. package/dist/core/openapi/digest.js.map +1 -1
  664. package/dist/core/openapi/doc.js +12 -4
  665. package/dist/core/openapi/doc.js.map +1 -1
  666. package/dist/core/openapi/merge/components.js +25 -60
  667. package/dist/core/openapi/merge/components.js.map +1 -1
  668. package/dist/core/openapi/merge/error.js +3 -13
  669. package/dist/core/openapi/merge/error.js.map +1 -1
  670. package/dist/core/openapi/merge/markers.js +26 -30
  671. package/dist/core/openapi/merge/markers.js.map +1 -1
  672. package/dist/core/openapi/merge/merge.js +28 -52
  673. package/dist/core/openapi/merge/merge.js.map +1 -1
  674. package/dist/core/openapi/merge/pin.js +17 -35
  675. package/dist/core/openapi/merge/pin.js.map +1 -1
  676. package/dist/core/openspec/decide/verdict.js.map +1 -1
  677. package/dist/core/openspec/inventory.js +4 -5
  678. package/dist/core/openspec/inventory.js.map +1 -1
  679. package/dist/core/openspec/model/mapping.js +30 -28
  680. package/dist/core/openspec/model/mapping.js.map +1 -1
  681. package/dist/core/openspec/model/model.js +12 -7
  682. package/dist/core/openspec/model/model.js.map +1 -1
  683. package/dist/core/openspec/scan/changes.js +10 -4
  684. package/dist/core/openspec/scan/changes.js.map +1 -1
  685. package/dist/core/openspec/scan/config.js +7 -16
  686. package/dist/core/openspec/scan/config.js.map +1 -1
  687. package/dist/core/openspec/scan/shape.js +63 -19
  688. package/dist/core/openspec/scan/shape.js.map +1 -1
  689. package/dist/core/openspec/scan/walk.js +21 -38
  690. package/dist/core/openspec/scan/walk.js.map +1 -1
  691. package/dist/core/pack/living.js +43 -4
  692. package/dist/core/pack/living.js.map +1 -1
  693. package/dist/core/pack/pack.js +50 -6
  694. package/dist/core/pack/pack.js.map +1 -1
  695. package/dist/core/projection/arch-slice.js +2 -2
  696. package/dist/core/projection/arch-slice.js.map +1 -1
  697. package/dist/core/projection/introduced.js +14 -0
  698. package/dist/core/projection/introduced.js.map +1 -0
  699. package/dist/core/provenance/findings.js +48 -12
  700. package/dist/core/provenance/findings.js.map +1 -1
  701. package/dist/core/provenance/git.js +33 -57
  702. package/dist/core/provenance/git.js.map +1 -1
  703. package/dist/core/provenance/gitq/moves.js +71 -114
  704. package/dist/core/provenance/gitq/moves.js.map +1 -1
  705. package/dist/core/provenance/gitq/vouched-ancestor.js +2 -2
  706. package/dist/core/provenance/gitq/vouched-ancestor.js.map +1 -1
  707. package/dist/core/provenance/sources.js +23 -6
  708. package/dist/core/provenance/sources.js.map +1 -1
  709. package/dist/core/provenance/stamp.js +5 -17
  710. package/dist/core/provenance/stamp.js.map +1 -1
  711. package/dist/core/repo/authored/paths.js +18 -0
  712. package/dist/core/repo/authored/paths.js.map +1 -1
  713. package/dist/core/repo/entries.js.map +1 -1
  714. package/dist/core/repo/paths.js +92 -6
  715. package/dist/core/repo/paths.js.map +1 -1
  716. package/dist/core/repo/repo.js +74 -14
  717. package/dist/core/repo/repo.js.map +1 -1
  718. package/dist/core/repo/tree/find.js +12 -3
  719. package/dist/core/repo/tree/find.js.map +1 -1
  720. package/dist/core/repo/tree/fs.js +27 -1
  721. package/dist/core/repo/tree/fs.js.map +1 -1
  722. package/dist/core/repo/tree/render/body.js +258 -0
  723. package/dist/core/repo/tree/render/body.js.map +1 -0
  724. package/dist/core/repo/tree/render/projects.js +182 -0
  725. package/dist/core/repo/tree/render/projects.js.map +1 -0
  726. package/dist/core/repo/tree/render/service/header.js +125 -0
  727. package/dist/core/repo/tree/render/service/header.js.map +1 -0
  728. package/dist/core/repo/tree/render/service/peers.js +28 -0
  729. package/dist/core/repo/tree/render/service/peers.js.map +1 -0
  730. package/dist/core/repo/tree/render/service/view-id.js +67 -0
  731. package/dist/core/repo/tree/render/service/view-id.js.map +1 -0
  732. package/dist/core/repo/tree/render/service/views.js +78 -0
  733. package/dist/core/repo/tree/render/service/views.js.map +1 -0
  734. package/dist/core/repo/tree/render/stale.js +42 -0
  735. package/dist/core/repo/tree/render/stale.js.map +1 -0
  736. package/dist/core/repo/tree/render/text.js +84 -0
  737. package/dist/core/repo/tree/render/text.js.map +1 -0
  738. package/dist/core/repo/tree/render/views.js +293 -0
  739. package/dist/core/repo/tree/render/views.js.map +1 -0
  740. package/dist/core/repo/tree/walk.js +53 -32
  741. package/dist/core/repo/tree/walk.js.map +1 -1
  742. package/dist/core/results.js +47 -12
  743. package/dist/core/results.js.map +1 -1
  744. package/dist/core/scaffold/landscape.js +121 -13
  745. package/dist/core/scaffold/landscape.js.map +1 -1
  746. package/dist/core/scaffold/legacy.js +271 -0
  747. package/dist/core/scaffold/legacy.js.map +1 -0
  748. package/dist/core/staging/commit.js +26 -15
  749. package/dist/core/staging/commit.js.map +1 -1
  750. package/dist/core/staging/lock.js +74 -12
  751. package/dist/core/staging/lock.js.map +1 -1
  752. package/dist/core/staging/recovery/intent.js +2 -5
  753. package/dist/core/staging/recovery/intent.js.map +1 -1
  754. package/dist/core/staging/recovery/recover.js +84 -6
  755. package/dist/core/staging/recovery/recover.js.map +1 -1
  756. package/dist/core/staging/snapshot/manifest.js +188 -0
  757. package/dist/core/staging/snapshot/manifest.js.map +1 -0
  758. package/dist/core/staging/{snapshot.js → snapshot/snapshot.js} +39 -45
  759. package/dist/core/staging/snapshot/snapshot.js.map +1 -0
  760. package/dist/core/staging/txn/forward.js +24 -14
  761. package/dist/core/staging/txn/forward.js.map +1 -1
  762. package/dist/core/staging/writes.js.map +1 -1
  763. package/dist/core/status/actions/execution.js +11 -0
  764. package/dist/core/status/actions/execution.js.map +1 -1
  765. package/dist/core/status/contracts.js +39 -15
  766. package/dist/core/status/contracts.js.map +1 -1
  767. package/dist/core/status/feature/artifacts.js +33 -8
  768. package/dist/core/status/feature/artifacts.js.map +1 -1
  769. package/dist/core/status/feature/feature.js +24 -17
  770. package/dist/core/status/feature/feature.js.map +1 -1
  771. package/dist/core/status/feature/next.js +20 -7
  772. package/dist/core/status/feature/next.js.map +1 -1
  773. package/dist/core/status/feature/words.js +96 -0
  774. package/dist/core/status/feature/words.js.map +1 -0
  775. package/dist/core/status/fleet/fleet.js +43 -14
  776. package/dist/core/status/fleet/fleet.js.map +1 -1
  777. package/dist/core/status/fleet/next.js +153 -58
  778. package/dist/core/status/fleet/next.js.map +1 -1
  779. package/dist/core/status/report.js.map +1 -1
  780. package/dist/core/status/scan.js.map +1 -1
  781. package/dist/core/status/verification.js +30 -15
  782. package/dist/core/status/verification.js.map +1 -1
  783. package/dist/core/tasks/packet.js +199 -0
  784. package/dist/core/tasks/packet.js.map +1 -0
  785. package/dist/core/tasks/record.js +43 -0
  786. package/dist/core/tasks/record.js.map +1 -0
  787. package/dist/core/tasks/sources.js +181 -0
  788. package/dist/core/tasks/sources.js.map +1 -0
  789. package/dist/core/tasks/stamps.js +76 -0
  790. package/dist/core/tasks/stamps.js.map +1 -0
  791. package/dist/core/tasks/unit.js +0 -0
  792. package/dist/core/tasks/unit.js.map +1 -0
  793. package/dist/core/usecases/capability.js +11 -14
  794. package/dist/core/usecases/capability.js.map +1 -1
  795. package/dist/core/usecases/delta/claims.js +31 -7
  796. package/dist/core/usecases/delta/claims.js.map +1 -1
  797. package/dist/core/usecases/delta/flows.js +5 -7
  798. package/dist/core/usecases/delta/flows.js.map +1 -1
  799. package/dist/core/usecases/delta/modified.js +315 -0
  800. package/dist/core/usecases/delta/modified.js.map +1 -0
  801. package/dist/core/usecases/delta/overlay.js +32 -191
  802. package/dist/core/usecases/delta/overlay.js.map +1 -1
  803. package/dist/core/usecases/fleet.js +195 -36
  804. package/dist/core/usecases/fleet.js.map +1 -1
  805. package/dist/{commands/validate/fleet/usecases → core/usecases/grade}/capability-tag.js +8 -9
  806. package/dist/core/usecases/grade/capability-tag.js.map +1 -0
  807. package/dist/core/usecases/grade/feature.js +88 -0
  808. package/dist/core/usecases/grade/feature.js.map +1 -0
  809. package/dist/{commands/validate/fleet/usecases → core/usecases/grade}/requirement-tag.js +3 -4
  810. package/dist/core/usecases/grade/requirement-tag.js.map +1 -0
  811. package/dist/{commands/validate/fleet/usecases → core/usecases/grade}/steps.js +102 -33
  812. package/dist/core/usecases/grade/steps.js.map +1 -0
  813. package/dist/{commands/validate/fleet/usecases → core/usecases/grade}/usecases.js +23 -10
  814. package/dist/core/usecases/grade/usecases.js.map +1 -0
  815. package/dist/core/usecases/operations.js +26 -14
  816. package/dist/core/usecases/operations.js.map +1 -1
  817. package/dist/core/usecases/place.js.map +1 -1
  818. package/dist/core/usecases/service/exclude.js +119 -0
  819. package/dist/core/usecases/service/exclude.js.map +1 -0
  820. package/dist/core/usecases/service/flows.js +164 -0
  821. package/dist/core/usecases/service/flows.js.map +1 -0
  822. package/dist/core/usecases/suites/participants.js +83 -0
  823. package/dist/core/usecases/suites/participants.js.map +1 -0
  824. package/dist/core/usecases/suites/suites.js +45 -0
  825. package/dist/core/usecases/suites/suites.js.map +1 -0
  826. package/dist/core/verify/answers.js +12 -5
  827. package/dist/core/verify/answers.js.map +1 -1
  828. package/dist/core/verify/build.js +102 -82
  829. package/dist/core/verify/build.js.map +1 -1
  830. package/dist/core/verify/checklist.js +70 -12
  831. package/dist/core/verify/checklist.js.map +1 -1
  832. package/dist/core/verify/location.js +67 -0
  833. package/dist/core/verify/location.js.map +1 -0
  834. package/dist/core/verify/pins/lint.js +3 -2
  835. package/dist/core/verify/pins/lint.js.map +1 -1
  836. package/dist/core/verify/pins/pin.js +1 -1
  837. package/dist/core/verify/pins/pin.js.map +1 -1
  838. package/dist/core/verify/read/file.js +224 -0
  839. package/dist/core/verify/read/file.js.map +1 -0
  840. package/dist/core/verify/{file.js → read/shape.js} +16 -104
  841. package/dist/core/verify/read/shape.js.map +1 -0
  842. package/dist/core/verify/read/union.js +105 -0
  843. package/dist/core/verify/read/union.js.map +1 -0
  844. package/dist/core/verify/record.js +35 -12
  845. package/dist/core/verify/record.js.map +1 -1
  846. package/dist/core/verify/store/commit.js +40 -30
  847. package/dist/core/verify/store/commit.js.map +1 -1
  848. package/dist/core/verify/store/render.js +8 -4
  849. package/dist/core/verify/store/render.js.map +1 -1
  850. package/dist/core/vocabulary/issue.js +4 -0
  851. package/dist/core/vocabulary/issue.js.map +1 -1
  852. package/dist/core/vocabulary/maturity.js +75 -4
  853. package/dist/core/vocabulary/maturity.js.map +1 -1
  854. package/dist/core/vocabulary/report.js +16 -1
  855. package/dist/core/vocabulary/report.js.map +1 -1
  856. package/examples/README.md +54 -11
  857. package/examples/docs/architecture/landscape.likec4 +62 -6
  858. package/examples/docs/architecture/services.likec4 +70 -0
  859. package/examples/docs/architecture/subsystems.likec4 +7 -0
  860. package/examples/docs/architecture/usecases/order-notification.likec4 +16 -7
  861. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-service/asyncapi.yaml +11 -8
  862. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/openapi.yaml +6 -6
  863. package/examples/docs/features/FEAT-112-retire-order-v1/specs/order-service/openapi.yaml +4 -1
  864. package/examples/docs/features/archive/FEAT-088-refunds/specs/payment-service/openapi.yaml +13 -10
  865. package/examples/docs/likec4.config.json +0 -1
  866. package/examples/docs/services/checkout-web/model.likec4 +39 -56
  867. package/examples/docs/services/order-service/arch.spec.md +13 -6
  868. package/examples/docs/services/order-service/asyncapi.yaml +3 -2
  869. package/examples/docs/services/order-service/model.likec4 +58 -70
  870. package/examples/docs/services/payment-service/arch.spec.md +7 -4
  871. package/examples/docs/services/payment-service/model.likec4 +38 -37
  872. package/examples/docs/services/platform/identity-service/arch.spec.md +7 -4
  873. package/examples/docs/services/platform/identity-service/model.likec4 +35 -37
  874. package/examples/docs/services/platform/notification-service/asyncapi.yaml +2 -1
  875. package/examples/docs/services/platform/notification-service/health.yaml +8 -3
  876. package/examples/docs/services/platform/notification-service/model.likec4 +43 -64
  877. package/package.json +1 -1
  878. package/dist/commands/validate/checks/vocabulary.js +0 -31
  879. package/dist/commands/validate/checks/vocabulary.js.map +0 -1
  880. package/dist/commands/validate/fleet/usecases/capability-tag.js.map +0 -1
  881. package/dist/commands/validate/fleet/usecases/requirement-tag.js.map +0 -1
  882. package/dist/commands/validate/fleet/usecases/steps.js.map +0 -1
  883. package/dist/commands/validate/fleet/usecases/usecases.js.map +0 -1
  884. package/dist/core/agent/agents-md/artifacts.js +0 -220
  885. package/dist/core/agent/agents-md/artifacts.js.map +0 -1
  886. package/dist/core/agent/agents-md/cycle.js +0 -165
  887. package/dist/core/agent/agents-md/cycle.js.map +0 -1
  888. package/dist/core/agent/agents-md/shipped/archive-gate.js +0 -98
  889. package/dist/core/agent/agents-md/shipped/archive-gate.js.map +0 -1
  890. package/dist/core/agent/agents-md/spine.js +0 -40
  891. package/dist/core/agent/agents-md/spine.js.map +0 -1
  892. package/dist/core/coherence/events/merged.js +0 -40
  893. package/dist/core/coherence/events/merged.js.map +0 -1
  894. package/dist/core/diff/current-state.js +0 -96
  895. package/dist/core/diff/current-state.js.map +0 -1
  896. package/dist/core/diff/victims.js +0 -247
  897. package/dist/core/diff/victims.js.map +0 -1
  898. package/dist/core/repo/tree/views.js +0 -172
  899. package/dist/core/repo/tree/views.js.map +0 -1
  900. package/dist/core/staging/snapshot.js.map +0 -1
  901. package/dist/core/verify/file.js.map +0 -1
@@ -0,0 +1,301 @@
1
+ /**
2
+ * The one way both contract axes read and write a contract document: parse it,
3
+ * refuse its first parse error, resolve it, and hand it back as text.
4
+ *
5
+ * The helpers are axis-neutral and take the refusal to raise as a `fail`
6
+ * callback, because the event axis's six entry points spelled the same parse,
7
+ * first-error, resolve and serialize sequence the OpenAPI axis's did, against
8
+ * its own error class (../asyncapi/merge/error.ts, beside ./merge/error.ts). A
9
+ * leaf of its own, named for what it holds, at the lowest package both merge
10
+ * packages already import — not inside either axis's refusal module, where the
11
+ * event axis would read its contracts through a file named for an error.
12
+ * Import direction is asyncapi → openapi, as everywhere else on the contract
13
+ * axes. `writeTreeOver` is the write an EDIT takes — a merge into a living
14
+ * contract, a strip of a feature's markers, the pins and baseline record
15
+ * `loam rebase` stamps into one — so that only what changed is re-printed.
16
+ */
17
+ import { isDeepStrictEqual } from "node:util";
18
+ import { Document, Pair, Scalar, YAMLMap, isMap, isScalar, parseDocument } from "yaml";
19
+ function errorMessage(error) {
20
+ return error instanceof Error ? error.message : String(error);
21
+ }
22
+ /**
23
+ * Parse a contract, refuse its first parse error, and resolve it. `check` runs
24
+ * between the two, on the AST: the event axis refuses an ambiguous slot key
25
+ * there, BEFORE resolution, so a document that is both ambiguous and carries
26
+ * an unresolvable alias is refused for the ambiguity, exactly as it was when
27
+ * each entry point spelled the sequence out.
28
+ */
29
+ export function readTree(text, fail, check) {
30
+ const doc = parseDocument(text);
31
+ if (doc.errors.length > 0)
32
+ throw fail(doc.errors[0].message);
33
+ check?.(doc);
34
+ return { doc, plain: resolveTree(doc, fail) };
35
+ }
36
+ /**
37
+ * Resolve aliases once with the document's own anchor context. Calling an
38
+ * individual AST node's toJSON() loses that context and can silently turn an
39
+ * aliased operation, slot or component into the wrong value. An alias that
40
+ * cannot be resolved at all is a document loam cannot read, and says so.
41
+ */
42
+ export function resolveTree(doc, fail) {
43
+ try {
44
+ return doc.toJS() ?? {};
45
+ }
46
+ catch (error) {
47
+ throw fail(errorMessage(error));
48
+ }
49
+ }
50
+ /**
51
+ * Hand the whole document back through the printer. Not exported: it is
52
+ * `writeTreeOver`'s first step and its fallback, and a writer calling it
53
+ * directly would re-print the author's whole contract — the cost
54
+ * `writeTreeOver` exists to avoid.
55
+ */
56
+ function writeTree(doc, fail) {
57
+ try {
58
+ return doc.toString();
59
+ }
60
+ catch (error) {
61
+ throw fail(errorMessage(error));
62
+ }
63
+ }
64
+ /**
65
+ * Hand an EDITED document back over the text it was parsed from: every map
66
+ * entry the edit did not change keeps its original bytes, and only the entries
67
+ * it added, replaced or removed are written fresh.
68
+ *
69
+ * WHY THE WHOLE-DOCUMENT WRITE WAS NOT ENOUGH. `writeTree` re-serializes every
70
+ * node, and the `yaml` library's printer has opinions the author never asked
71
+ * for: it re-folds every plain or quoted scalar at 80 columns, re-pads every
72
+ * flow sequence (`[a, b]` becomes `[ a, b ]`), and turns CRLF into LF. So an
73
+ * archive that added one channel to a living contract rewrote a long
74
+ * `description` three sections away, and the merge's diff — the thing a
75
+ * reviewer reads to learn what the feature changed — carried lines nobody
76
+ * touched. `lineWidth: 0` is not the fix, and was measured not to be: it stops
77
+ * the folding by JOINING every scalar the author folded by hand onto one line,
78
+ * which on loam's own `examples/docs` rewrote 38 lines of a contract the
79
+ * default printer had left alone. No printer setting reproduces an author's
80
+ * layout; only the author's bytes do.
81
+ *
82
+ * HOW. Both trees are walked in step, block map by block map, keyed on the
83
+ * entry key: an entry whose resolved value is unchanged is left exactly where it
84
+ * is, an entry that changed is either descended into (both sides are block
85
+ * maps) or replaced by the printer's spelling of its new value, a new entry is
86
+ * printed after the entry the edit placed it behind, and a removed one is cut
87
+ * out with the comment lines directly above it — which is where the `yaml`
88
+ * library attaches such a comment, and so what the whole-document write would
89
+ * have removed with it.
90
+ *
91
+ * VERIFIED, OR NOT USED. The spliced text is parsed back and compared, resolved
92
+ * value against resolved value, with the edited tree. Anything the walk does
93
+ * not understand — a key that is not a scalar, a key spelled twice, an entry
94
+ * not on a line of its own, a reorder, an alias it cannot print alone — makes
95
+ * it answer nothing, and so does a splice that would read back as a different
96
+ * document: the fallback is `writeTree`, the old behaviour exactly, so this can
97
+ * only ever narrow a diff and never change what a contract says. The
98
+ * whole-document write also runs first, every time, so a document it cannot
99
+ * print fails the way it always failed.
100
+ */
101
+ export function writeTreeOver(doc, source, fail) {
102
+ const whole = writeTree(doc, fail);
103
+ const spliced = splicedText(doc, source);
104
+ return spliced !== null && readsAs(spliced, doc) ? spliced : whole;
105
+ }
106
+ function splicedText(doc, source) {
107
+ const original = parseDocument(source);
108
+ if (original.errors.length > 0)
109
+ return null;
110
+ const run = { source, eol: source.includes("\r\n") ? "\r\n" : "\n", edits: [] };
111
+ try {
112
+ // Resolved through each document's own anchors, once — what "unchanged"
113
+ // means is decided on these, never on the nodes.
114
+ const before = { node: original.contents, plain: original.toJS() };
115
+ const after = { node: doc.contents, plain: doc.toJS() };
116
+ if (!spliceMap(run, before, after))
117
+ return null;
118
+ }
119
+ catch {
120
+ // A node the printer cannot print alone — an alias whose anchor sits
121
+ // outside the entry being written — is a document this walk does not
122
+ // understand, and the answer for those is the whole-document write.
123
+ return null;
124
+ }
125
+ // Stable by position, so two insertions at one point keep the order the
126
+ // walk emitted them in — which is the edited tree's order.
127
+ const edits = [...run.edits].sort((a, b) => a.from - b.from);
128
+ let out = "";
129
+ let cursor = 0;
130
+ for (const edit of edits) {
131
+ if (edit.from < cursor)
132
+ return null;
133
+ out += source.slice(cursor, edit.from) + edit.text;
134
+ cursor = edit.to;
135
+ }
136
+ return out + source.slice(cursor);
137
+ }
138
+ /** Does the spliced text read back as exactly the edited document? */
139
+ function readsAs(text, doc) {
140
+ try {
141
+ const back = parseDocument(text);
142
+ return back.errors.length === 0 && isDeepStrictEqual(back.toJS(), doc.toJS());
143
+ }
144
+ catch {
145
+ return false;
146
+ }
147
+ }
148
+ function blockMap(node) {
149
+ return isMap(node) && node.flow !== true;
150
+ }
151
+ /**
152
+ * An entry's key as the resolved tree spells it, or null for a key this walk
153
+ * will not match on. A key the edit SET arrives as the raw value rather than a
154
+ * node — `setIn` builds the pair from what it was handed — and is the same key.
155
+ */
156
+ function keyOf(pair) {
157
+ const value = isScalar(pair.key) ? pair.key.value : pair.key;
158
+ return typeof value === "string" || typeof value === "number" || typeof value === "boolean" ? String(value) : null;
159
+ }
160
+ function child(plain, key) {
161
+ return plain !== null && typeof plain === "object" ? plain[key] : undefined;
162
+ }
163
+ /**
164
+ * Splice one block map. Answers false — and the whole splice is abandoned — on
165
+ * any shape it does not understand; see `writeTreeOver`.
166
+ */
167
+ function spliceMap(run, before, after) {
168
+ if (!blockMap(before.node) || !blockMap(after.node) || before.node.items.length === 0)
169
+ return false;
170
+ const located = locateEntries(run.source, before.node.items);
171
+ if (located === null)
172
+ return false;
173
+ const { entries, column: indent } = located;
174
+ const byKey = new Map();
175
+ for (const [at, entry] of entries.entries()) {
176
+ const key = keyOf(entry.pair);
177
+ if (key === null || byKey.has(key))
178
+ return false;
179
+ byKey.set(key, { at, entry });
180
+ }
181
+ const kept = new Set();
182
+ let insertAt = entries[0].lead;
183
+ let lastAt = -1;
184
+ for (const pair of after.node.items) {
185
+ const key = keyOf(pair);
186
+ if (key === null || kept.has(key))
187
+ return false;
188
+ kept.add(key);
189
+ const was = byKey.get(key);
190
+ if (was === undefined) {
191
+ run.edits.push({ from: insertAt, to: insertAt, text: printed(run, pair, indent, insertAt) });
192
+ continue;
193
+ }
194
+ // A reorder is a change this walk cannot express by keeping bytes where
195
+ // they are, and the whole-document write expresses it exactly.
196
+ if (was.at < lastAt)
197
+ return false;
198
+ lastAt = was.at;
199
+ insertAt = was.entry.end;
200
+ const old = { node: was.entry.pair.value, plain: child(before.plain, key) };
201
+ const now = { node: pair.value, plain: child(after.plain, key) };
202
+ if (isDeepStrictEqual(old.plain, now.plain))
203
+ continue;
204
+ const mark = run.edits.length;
205
+ if (blockMap(old.node) && blockMap(now.node) && spliceMap(run, old, now))
206
+ continue;
207
+ // Not descended into, or the descent failed: drop whatever it collected
208
+ // and write the entry whole, from its key line to its end. The comment
209
+ // lines above it stay — they are outside the range, and the key printed
210
+ // here carries none of its own.
211
+ run.edits.length = mark;
212
+ run.edits.push({ from: was.entry.line, to: was.entry.end, text: printed(run, pair, indent, was.entry.line) });
213
+ }
214
+ for (const [key, { entry }] of byKey) {
215
+ if (!kept.has(key))
216
+ run.edits.push({ from: entry.lead, to: entry.end, text: "" });
217
+ }
218
+ return true;
219
+ }
220
+ /** Each entry's line, comment lead and end — or null when one is not on a line of its own at one indentation. */
221
+ function locateEntries(source, items) {
222
+ const entries = [];
223
+ let column = null;
224
+ let bound = 0;
225
+ for (const pair of items) {
226
+ const key = pair.key;
227
+ const value = pair.value;
228
+ if (!key?.range || !value?.range)
229
+ return null;
230
+ const start = key.range[0];
231
+ const line = source.lastIndexOf("\n", start - 1) + 1;
232
+ if (line < bound || !/^ *$/.test(source.slice(line, start)))
233
+ return null;
234
+ if (column !== null && start - line !== column)
235
+ return null;
236
+ column = start - line;
237
+ const lead = commentLead(source, { line, bound, attached: isScalar(key) && key.commentBefore !== undefined });
238
+ // An EMPTY value — `a:`, `a: !tag`, `a: &x` — ends AT its line break rather
239
+ // than past it, measured on both line endings; without the step a cut
240
+ // leaves a stray blank line, and an insert after it joins the next line.
241
+ let end = value.range[2];
242
+ if (end > 0 && source[end - 1] !== "\n") {
243
+ if (source.startsWith("\r\n", end))
244
+ end += 2;
245
+ else if (source[end] === "\n")
246
+ end += 1;
247
+ }
248
+ entries.push({ pair, line, lead, end });
249
+ bound = end;
250
+ }
251
+ return column === null ? null : { entries, column };
252
+ }
253
+ /**
254
+ * Where the comment block above an entry's key line starts — the lines the
255
+ * `yaml` library attaches to the key, which a removed entry takes with it, as
256
+ * the whole-document write would. Contiguous comment lines always; across blank
257
+ * lines too when the key carries an attached comment, because the library
258
+ * attaches one separated by a blank line as well. Never above `bound`, the end
259
+ * of the entry before, and never onto a blank line ABOVE the block: those
260
+ * separate this entry from the previous one and stay.
261
+ */
262
+ function commentLead(source, at) {
263
+ let lead = at.line;
264
+ for (let cursor = at.line; cursor > at.bound;) {
265
+ const previous = source.lastIndexOf("\n", cursor - 2) + 1;
266
+ if (previous < at.bound)
267
+ break;
268
+ const text = source.slice(previous, cursor).trim();
269
+ if (text.startsWith("#"))
270
+ lead = previous;
271
+ else if (text !== "" || !at.attached)
272
+ break;
273
+ cursor = previous;
274
+ }
275
+ return lead;
276
+ }
277
+ /**
278
+ * One entry as the printer spells it, indented to its map's column, in the
279
+ * original's line break. The key is printed BARE — a fresh scalar with the
280
+ * original's quoting style and none of its comments — because the comment
281
+ * lines above an entry stay in place outside the range being replaced, and the
282
+ * printer would otherwise write them a second time.
283
+ */
284
+ function printed(run, pair, indent, at) {
285
+ const key = new Scalar(isScalar(pair.key) ? pair.key.value : pair.key);
286
+ if (isScalar(pair.key) && pair.key.type !== undefined)
287
+ key.type = pair.key.type;
288
+ const map = new YAMLMap();
289
+ map.items.push(new Pair(key, pair.value));
290
+ const single = new Document();
291
+ single.contents = map;
292
+ const text = single
293
+ .toString()
294
+ .split("\n")
295
+ .map((line) => (line === "" ? line : " ".repeat(indent) + line))
296
+ .join(run.eol);
297
+ // Written where the original stopped without a final line break, the entry
298
+ // needs one in front of it, or it would join the line it follows.
299
+ return at === run.source.length && at > 0 && !run.source.endsWith("\n") ? run.eol + text : text;
300
+ }
301
+ //# sourceMappingURL=contract-tree.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contract-tree.js","sourceRoot":"","sources":["../../../src/core/openapi/contract-tree.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The one way both contract axes read and write a contract document: parse it,\n * refuse its first parse error, resolve it, and hand it back as text.\n *\n * The helpers are axis-neutral and take the refusal to raise as a `fail`\n * callback, because the event axis's six entry points spelled the same parse,\n * first-error, resolve and serialize sequence the OpenAPI axis's did, against\n * its own error class (../asyncapi/merge/error.ts, beside ./merge/error.ts). A\n * leaf of its own, named for what it holds, at the lowest package both merge\n * packages already import — not inside either axis's refusal module, where the\n * event axis would read its contracts through a file named for an error.\n * Import direction is asyncapi → openapi, as everywhere else on the contract\n * axes. `writeTreeOver` is the write an EDIT takes — a merge into a living\n * contract, a strip of a feature's markers, the pins and baseline record\n * `loam rebase` stamps into one — so that only what changed is re-printed.\n */\nimport { isDeepStrictEqual } from \"node:util\";\nimport { Document, Pair, Scalar, YAMLMap, isMap, isScalar, parseDocument, type Node } from \"yaml\";\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\n/** A contract's AST, for the writes, and its resolved plain tree, for every shape question. */\nexport interface ContractTree {\n doc: Document.Parsed;\n plain: unknown;\n}\n\n/**\n * Parse a contract, refuse its first parse error, and resolve it. `check` runs\n * between the two, on the AST: the event axis refuses an ambiguous slot key\n * there, BEFORE resolution, so a document that is both ambiguous and carries\n * an unresolvable alias is refused for the ambiguity, exactly as it was when\n * each entry point spelled the sequence out.\n */\nexport function readTree(text: string, fail: (detail: string) => Error, check?: (doc: Document) => void): ContractTree {\n const doc = parseDocument(text);\n if (doc.errors.length > 0) throw fail(doc.errors[0]!.message);\n check?.(doc);\n return { doc, plain: resolveTree(doc, fail) };\n}\n\n/**\n * Resolve aliases once with the document's own anchor context. Calling an\n * individual AST node's toJSON() loses that context and can silently turn an\n * aliased operation, slot or component into the wrong value. An alias that\n * cannot be resolved at all is a document loam cannot read, and says so.\n */\nexport function resolveTree(doc: Document, fail: (detail: string) => Error): unknown {\n try {\n return doc.toJS() ?? {};\n } catch (error) {\n throw fail(errorMessage(error));\n }\n}\n\n/**\n * Hand the whole document back through the printer. Not exported: it is\n * `writeTreeOver`'s first step and its fallback, and a writer calling it\n * directly would re-print the author's whole contract — the cost\n * `writeTreeOver` exists to avoid.\n */\nfunction writeTree(doc: Document, fail: (detail: string) => Error): string {\n try {\n return doc.toString();\n } catch (error) {\n throw fail(errorMessage(error));\n }\n}\n\n/**\n * Hand an EDITED document back over the text it was parsed from: every map\n * entry the edit did not change keeps its original bytes, and only the entries\n * it added, replaced or removed are written fresh.\n *\n * WHY THE WHOLE-DOCUMENT WRITE WAS NOT ENOUGH. `writeTree` re-serializes every\n * node, and the `yaml` library's printer has opinions the author never asked\n * for: it re-folds every plain or quoted scalar at 80 columns, re-pads every\n * flow sequence (`[a, b]` becomes `[ a, b ]`), and turns CRLF into LF. So an\n * archive that added one channel to a living contract rewrote a long\n * `description` three sections away, and the merge's diff — the thing a\n * reviewer reads to learn what the feature changed — carried lines nobody\n * touched. `lineWidth: 0` is not the fix, and was measured not to be: it stops\n * the folding by JOINING every scalar the author folded by hand onto one line,\n * which on loam's own `examples/docs` rewrote 38 lines of a contract the\n * default printer had left alone. No printer setting reproduces an author's\n * layout; only the author's bytes do.\n *\n * HOW. Both trees are walked in step, block map by block map, keyed on the\n * entry key: an entry whose resolved value is unchanged is left exactly where it\n * is, an entry that changed is either descended into (both sides are block\n * maps) or replaced by the printer's spelling of its new value, a new entry is\n * printed after the entry the edit placed it behind, and a removed one is cut\n * out with the comment lines directly above it — which is where the `yaml`\n * library attaches such a comment, and so what the whole-document write would\n * have removed with it.\n *\n * VERIFIED, OR NOT USED. The spliced text is parsed back and compared, resolved\n * value against resolved value, with the edited tree. Anything the walk does\n * not understand — a key that is not a scalar, a key spelled twice, an entry\n * not on a line of its own, a reorder, an alias it cannot print alone — makes\n * it answer nothing, and so does a splice that would read back as a different\n * document: the fallback is `writeTree`, the old behaviour exactly, so this can\n * only ever narrow a diff and never change what a contract says. The\n * whole-document write also runs first, every time, so a document it cannot\n * print fails the way it always failed.\n */\nexport function writeTreeOver(doc: Document, source: string, fail: (detail: string) => Error): string {\n const whole = writeTree(doc, fail);\n const spliced = splicedText(doc, source);\n return spliced !== null && readsAs(spliced, doc) ? spliced : whole;\n}\n\n/** One replacement of `source[from, to)`. An insertion is `from === to`. */\ninterface Edit {\n from: number;\n to: number;\n text: string;\n}\n\n/** What one walk shares: the original text, its line break, and the edits collected so far. */\ninterface SpliceRun {\n source: string;\n eol: string;\n edits: Edit[];\n}\n\n/** One original entry, located: where its key line starts, where its comments start, where it ends. */\ninterface Located {\n pair: Pair;\n /** Start of the line the key is on. */\n line: number;\n /** Start of the contiguous comment lines directly above that line, or `line` when there are none. */\n lead: number;\n /** End of the entry, past its line break. */\n end: number;\n}\n\n\n/** One side of the walk: a node, and the value it resolves to through its own document. */\ninterface Side {\n node: unknown;\n plain: unknown;\n}\n\nfunction splicedText(doc: Document, source: string): string | null {\n const original = parseDocument(source);\n if (original.errors.length > 0) return null;\n const run: SpliceRun = { source, eol: source.includes(\"\\r\\n\") ? \"\\r\\n\" : \"\\n\", edits: [] };\n try {\n // Resolved through each document's own anchors, once — what \"unchanged\"\n // means is decided on these, never on the nodes.\n const before: Side = { node: original.contents, plain: original.toJS() };\n const after: Side = { node: doc.contents, plain: doc.toJS() };\n if (!spliceMap(run, before, after)) return null;\n } catch {\n // A node the printer cannot print alone — an alias whose anchor sits\n // outside the entry being written — is a document this walk does not\n // understand, and the answer for those is the whole-document write.\n return null;\n }\n // Stable by position, so two insertions at one point keep the order the\n // walk emitted them in — which is the edited tree's order.\n const edits = [...run.edits].sort((a, b) => a.from - b.from);\n let out = \"\";\n let cursor = 0;\n for (const edit of edits) {\n if (edit.from < cursor) return null;\n out += source.slice(cursor, edit.from) + edit.text;\n cursor = edit.to;\n }\n return out + source.slice(cursor);\n}\n\n/** Does the spliced text read back as exactly the edited document? */\nfunction readsAs(text: string, doc: Document): boolean {\n try {\n const back = parseDocument(text);\n return back.errors.length === 0 && isDeepStrictEqual(back.toJS(), doc.toJS());\n } catch {\n return false;\n }\n}\n\nfunction blockMap(node: unknown): node is YAMLMap {\n return isMap(node) && node.flow !== true;\n}\n\n/**\n * An entry's key as the resolved tree spells it, or null for a key this walk\n * will not match on. A key the edit SET arrives as the raw value rather than a\n * node — `setIn` builds the pair from what it was handed — and is the same key.\n */\nfunction keyOf(pair: Pair): string | null {\n const value: unknown = isScalar(pair.key) ? pair.key.value : pair.key;\n return typeof value === \"string\" || typeof value === \"number\" || typeof value === \"boolean\" ? String(value) : null;\n}\n\nfunction child(plain: unknown, key: string): unknown {\n return plain !== null && typeof plain === \"object\" ? (plain as Record<string, unknown>)[key] : undefined;\n}\n\n/**\n * Splice one block map. Answers false — and the whole splice is abandoned — on\n * any shape it does not understand; see `writeTreeOver`.\n */\nfunction spliceMap(run: SpliceRun, before: Side, after: Side): boolean {\n if (!blockMap(before.node) || !blockMap(after.node) || before.node.items.length === 0) return false;\n const located = locateEntries(run.source, before.node.items);\n if (located === null) return false;\n const { entries, column: indent } = located;\n const byKey = new Map<string, { at: number; entry: Located }>();\n for (const [at, entry] of entries.entries()) {\n const key = keyOf(entry.pair);\n if (key === null || byKey.has(key)) return false;\n byKey.set(key, { at, entry });\n }\n const kept = new Set<string>();\n let insertAt = entries[0]!.lead;\n let lastAt = -1;\n for (const pair of after.node.items) {\n const key = keyOf(pair);\n if (key === null || kept.has(key)) return false;\n kept.add(key);\n const was = byKey.get(key);\n if (was === undefined) {\n run.edits.push({ from: insertAt, to: insertAt, text: printed(run, pair, indent, insertAt) });\n continue;\n }\n // A reorder is a change this walk cannot express by keeping bytes where\n // they are, and the whole-document write expresses it exactly.\n if (was.at < lastAt) return false;\n lastAt = was.at;\n insertAt = was.entry.end;\n const old: Side = { node: was.entry.pair.value, plain: child(before.plain, key) };\n const now: Side = { node: pair.value, plain: child(after.plain, key) };\n if (isDeepStrictEqual(old.plain, now.plain)) continue;\n const mark = run.edits.length;\n if (blockMap(old.node) && blockMap(now.node) && spliceMap(run, old, now)) continue;\n // Not descended into, or the descent failed: drop whatever it collected\n // and write the entry whole, from its key line to its end. The comment\n // lines above it stay — they are outside the range, and the key printed\n // here carries none of its own.\n run.edits.length = mark;\n run.edits.push({ from: was.entry.line, to: was.entry.end, text: printed(run, pair, indent, was.entry.line) });\n }\n for (const [key, { entry }] of byKey) {\n if (!kept.has(key)) run.edits.push({ from: entry.lead, to: entry.end, text: \"\" });\n }\n return true;\n}\n\n/** A block map's entries, located, and the one column every key in it starts at. */\ninterface LocatedMap {\n entries: Located[];\n column: number;\n}\n\n/** Each entry's line, comment lead and end — or null when one is not on a line of its own at one indentation. */\nfunction locateEntries(source: string, items: readonly Pair[]): LocatedMap | null {\n const entries: Located[] = [];\n let column: number | null = null;\n let bound = 0;\n for (const pair of items) {\n const key = pair.key as Node | null;\n const value = pair.value as Node | null;\n if (!key?.range || !value?.range) return null;\n const start = key.range[0];\n const line = source.lastIndexOf(\"\\n\", start - 1) + 1;\n if (line < bound || !/^ *$/.test(source.slice(line, start))) return null;\n if (column !== null && start - line !== column) return null;\n column = start - line;\n const lead = commentLead(source, { line, bound, attached: isScalar(key) && key.commentBefore !== undefined });\n // An EMPTY value — `a:`, `a: !tag`, `a: &x` — ends AT its line break rather\n // than past it, measured on both line endings; without the step a cut\n // leaves a stray blank line, and an insert after it joins the next line.\n let end = value.range[2];\n if (end > 0 && source[end - 1] !== \"\\n\") {\n if (source.startsWith(\"\\r\\n\", end)) end += 2;\n else if (source[end] === \"\\n\") end += 1;\n }\n entries.push({ pair, line, lead, end });\n bound = end;\n }\n return column === null ? null : { entries, column };\n}\n\n/**\n * Where the comment block above an entry's key line starts — the lines the\n * `yaml` library attaches to the key, which a removed entry takes with it, as\n * the whole-document write would. Contiguous comment lines always; across blank\n * lines too when the key carries an attached comment, because the library\n * attaches one separated by a blank line as well. Never above `bound`, the end\n * of the entry before, and never onto a blank line ABOVE the block: those\n * separate this entry from the previous one and stay.\n */\nfunction commentLead(source: string, at: { line: number; bound: number; attached: boolean }): number {\n let lead = at.line;\n for (let cursor = at.line; cursor > at.bound; ) {\n const previous = source.lastIndexOf(\"\\n\", cursor - 2) + 1;\n if (previous < at.bound) break;\n const text = source.slice(previous, cursor).trim();\n if (text.startsWith(\"#\")) lead = previous;\n else if (text !== \"\" || !at.attached) break;\n cursor = previous;\n }\n return lead;\n}\n\n/**\n * One entry as the printer spells it, indented to its map's column, in the\n * original's line break. The key is printed BARE — a fresh scalar with the\n * original's quoting style and none of its comments — because the comment\n * lines above an entry stay in place outside the range being replaced, and the\n * printer would otherwise write them a second time.\n */\nfunction printed(run: SpliceRun, pair: Pair, indent: number, at: number): string {\n const key = new Scalar(isScalar(pair.key) ? pair.key.value : pair.key);\n if (isScalar(pair.key) && pair.key.type !== undefined) key.type = pair.key.type;\n const map = new YAMLMap();\n map.items.push(new Pair(key, pair.value));\n const single = new Document();\n single.contents = map;\n const text = single\n .toString()\n .split(\"\\n\")\n .map((line) => (line === \"\" ? line : \" \".repeat(indent) + line))\n .join(run.eol);\n // Written where the original stopped without a final line break, the entry\n // needs one in front of it, or it would join the line it follows.\n return at === run.source.length && at > 0 && !run.source.endsWith(\"\\n\") ? run.eol + text : text;\n}\n"]}
@@ -10,10 +10,14 @@
10
10
  * says, only whether one was declared at all, so the reader's structure-only
11
11
  * stance holds.
12
12
  *
13
- * A local pointer walk rather than an import from `merge/components.ts`: the merge
14
- * package already imports this package (`HTTP_METHODS` from doc.ts), so the
15
- * reverse import would be a package cycle — the same reason read-side
16
- * `resolvePointer` copies exist on the asyncapi axis.
13
+ * This module used to keep a private pointer walk rather than import the
14
+ * merge's: the merge package already imports this package (`HTTP_METHODS` from
15
+ * doc.ts), so the reverse import would have been a package cycle — the same
16
+ * reason read-side `resolvePointer` copies exist on the asyncapi axis. The two
17
+ * plain `$ref` questions now live HERE, at the axis root (`collectRefs` and
18
+ * `resolvePointer`, at the bottom), so the private copy went: the dangling-ref
19
+ * probe below, the merge's component closure and the reader's closure digest
20
+ * (`closureDigester`, ./digest.ts) all ask the same two questions.
17
21
  */
18
22
  /** Status codes whose response legitimately carries no body. */
19
23
  const NO_CONTENT = new Set(["204", "304"]);
@@ -78,45 +82,55 @@ export function failureCodesOf(op) {
78
82
  * scope and never graded, matching the merge's documented stance.
79
83
  */
80
84
  export function danglingRefs(root) {
81
- const out = new Set();
82
- const walk = (node) => {
83
- if (Array.isArray(node)) {
84
- for (const value of node)
85
+ // A Set keeps first-insertion order, so dedup and document order both hold.
86
+ return [...new Set(collectRefs(root).filter((ref) => ref.startsWith("#/") && !resolvePointer(root, ref).found))];
87
+ }
88
+ /*
89
+ * `$ref` as a pair of plain questions — which ones does this tree contain, and
90
+ * what does one point at. Both lived in `./merge/components.ts`, beside the
91
+ * component closure that was their only caller, until the reader needed the same
92
+ * walk; the header says why the root and not there.
93
+ */
94
+ /** Every `$ref` string in a tree, in document order — duplicates kept, external refs included. */
95
+ export function collectRefs(node) {
96
+ const out = [];
97
+ const walk = (current) => {
98
+ if (Array.isArray(current)) {
99
+ for (const value of current)
85
100
  walk(value);
86
101
  return;
87
102
  }
88
- if (node === null || typeof node !== "object")
89
- return;
90
- for (const [key, value] of Object.entries(node)) {
91
- if (key === "$ref" && typeof value === "string") {
92
- if (value.startsWith("#/") && !resolves(root, value))
93
- out.add(value);
94
- continue;
103
+ if (current !== null && typeof current === "object") {
104
+ for (const [key, value] of Object.entries(current)) {
105
+ if (key === "$ref" && typeof value === "string")
106
+ out.push(value);
107
+ else
108
+ walk(value);
95
109
  }
96
- walk(value);
97
110
  }
98
111
  };
99
- walk(root);
100
- return [...out];
112
+ walk(node);
113
+ return out;
101
114
  }
102
- /** Does a local JSON pointer (`#/a/b~1c`) reach a node in this tree? */
103
- function resolves(root, ref) {
115
+ /** Resolve a local JSON pointer (`#/a/b~1c`) against a plain JS tree. */
116
+ export function resolvePointer(root, ref) {
104
117
  let current = root;
105
118
  for (const raw of ref.slice(2).split("/")) {
106
119
  const segment = raw.replace(/~1/g, "/").replace(/~0/g, "~");
107
120
  if (Array.isArray(current)) {
108
121
  const index = Number(segment);
109
- if (!Number.isInteger(index) || index < 0 || index >= current.length)
110
- return false;
122
+ if (!Number.isInteger(index) || index < 0 || index >= current.length) {
123
+ return { found: false, value: undefined };
124
+ }
111
125
  current = current[index];
112
126
  }
113
127
  else if (current !== null && typeof current === "object" && segment in current) {
114
128
  current = current[segment];
115
129
  }
116
130
  else {
117
- return false;
131
+ return { found: false, value: undefined };
118
132
  }
119
133
  }
120
- return true;
134
+ return { found: true, value: current };
121
135
  }
122
136
  //# sourceMappingURL=depth.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"depth.js","sourceRoot":"","sources":["../../../src/core/openapi/depth.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The contract-depth probes: does an operation say anything about what it\n * returns, and does every internal `$ref` point at something.\n *\n * Form validated and depth did not, and that was invisible from the output:\n * an operation whose one response is `description: OK`, and a `$ref` to a\n * schema nobody ever wrote, both validate exactly as cleanly as a complete\n * contract even though a reader still needs the code. Everything here is a\n * PRESENCE probe over the document's own keys: nothing reads what a schema\n * says, only whether one was declared at all, so the reader's structure-only\n * stance holds.\n *\n * A local pointer walk rather than an import from `merge/components.ts`: the merge\n * package already imports this package (`HTTP_METHODS` from doc.ts), so the\n * reverse import would be a package cycle — the same reason read-side\n * `resolvePointer` copies exist on the asyncapi axis.\n */\n\n/** Status codes whose response legitimately carries no body. */\nconst NO_CONTENT = new Set([\"204\", \"304\"]);\n\n/**\n * True when no response declares content with a schema while at least one\n * response should carry a body — an operation with no `responses` at all\n * counts, one whose only responses are 204/304 does not. A response that is\n * itself a `$ref` counts as described: somebody wrote the shape down, and the\n * dangling case is the ref probe's finding, not this one's.\n */\nexport function responseUndescribed(op: unknown): boolean {\n if (op === null || typeof op !== \"object\") return true;\n const responses = (op as Record<string, unknown>)[\"responses\"];\n if (responses === null || responses === undefined || typeof responses !== \"object\" || Array.isArray(responses)) {\n return true;\n }\n const entries = Object.entries(responses as Record<string, unknown>);\n if (entries.length === 0) return true;\n let owesBody = false;\n for (const [code, resp] of entries) {\n if (NO_CONTENT.has(code)) continue;\n owesBody = true;\n if (resp === null || typeof resp !== \"object\" || Array.isArray(resp)) continue;\n const rec = resp as Record<string, unknown>;\n if (\"$ref\" in rec) return false;\n const content = rec[\"content\"];\n if (content === null || typeof content !== \"object\" || Array.isArray(content)) continue;\n for (const media of Object.values(content as Record<string, unknown>)) {\n if (media !== null && typeof media === \"object\" && \"schema\" in (media as Record<string, unknown>)) {\n return false;\n }\n }\n }\n return owesBody;\n}\n\n/**\n * The non-2xx response codes an operation declares, in document order.\n *\n * Exact three-digit codes only. `default` names no case — it is whatever else\n * happens — and the `4XX`/`5XX` wildcards name a class rather than a refusal,\n * so no scenario could be written for either and demanding one would teach an\n * author to write a scenario about nothing. 1xx and 3xx are excluded with 2xx:\n * a redirect or a continue is not the service saying no.\n */\nexport function failureCodesOf(op: unknown): string[] {\n if (op === null || typeof op !== \"object\") return [];\n const responses = (op as Record<string, unknown>)[\"responses\"];\n if (responses === null || typeof responses !== \"object\" || Array.isArray(responses)) return [];\n return Object.keys(responses as Record<string, unknown>).filter((code) => /^[45]\\d\\d$/.test(code));\n}\n\n/**\n * Every internal `#/` reference in the document that resolves to nothing —\n * deduped, document order. External references (URLs, file paths) are out of\n * scope and never graded, matching the merge's documented stance.\n */\nexport function danglingRefs(root: unknown): string[] {\n const out = new Set<string>();\n const walk = (node: unknown): void => {\n if (Array.isArray(node)) {\n for (const value of node) walk(value);\n return;\n }\n if (node === null || typeof node !== \"object\") return;\n for (const [key, value] of Object.entries(node as Record<string, unknown>)) {\n if (key === \"$ref\" && typeof value === \"string\") {\n if (value.startsWith(\"#/\") && !resolves(root, value)) out.add(value);\n continue;\n }\n walk(value);\n }\n };\n walk(root);\n return [...out];\n}\n\n/** Does a local JSON pointer (`#/a/b~1c`) reach a node in this tree? */\nfunction resolves(root: unknown, ref: string): boolean {\n let current: unknown = root;\n for (const raw of ref.slice(2).split(\"/\")) {\n const segment = raw.replace(/~1/g, \"/\").replace(/~0/g, \"~\");\n if (Array.isArray(current)) {\n const index = Number(segment);\n if (!Number.isInteger(index) || index < 0 || index >= current.length) return false;\n current = current[index];\n } else if (current !== null && typeof current === \"object\" && segment in (current as Record<string, unknown>)) {\n current = (current as Record<string, unknown>)[segment];\n } else {\n return false;\n }\n }\n return true;\n}\n"]}
1
+ {"version":3,"file":"depth.js","sourceRoot":"","sources":["../../../src/core/openapi/depth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,gEAAgE;AAChE,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;AAE3C;;;;;;GAMG;AACH,MAAM,UAAU,mBAAmB,CAAC,EAAW;IAC7C,IAAI,EAAE,KAAK,IAAI,IAAI,OAAO,EAAE,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IACvD,MAAM,SAAS,GAAI,EAA8B,CAAC,WAAW,CAAC,CAAC;IAC/D,IAAI,SAAS,KAAK,IAAI,IAAI,SAAS,KAAK,SAAS,IAAI,OAAO,SAAS,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;QAC/G,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,SAAoC,CAAC,CAAC;IACrE,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACtC,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,KAAK,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,OAAO,EAAE,CAAC;QACnC,IAAI,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,SAAS;QACnC,QAAQ,GAAG,IAAI,CAAC;QAChB,IAAI,IAAI,KAAK,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC;YAAE,SAAS;QAC/E,MAAM,GAAG,GAAG,IAA+B,CAAC;QAC5C,IAAI,MAAM,IAAI,GAAG;YAAE,OAAO,KAAK,CAAC;QAChC,MAAM,OAAO,GAAG,GAAG,CAAC,SAAS,CAAC,CAAC;QAC/B,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;YAAE,SAAS;QACxF,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,CAAC,OAAkC,CAAC,EAAE,CAAC;YACtE,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,QAAQ,IAAK,KAAiC,EAAE,CAAC;gBAClG,OAAO,KAAK,CAAC;YACf,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,cAAc,CAAC,EAAW;IACxC,IAAI,EAAE,KAAK,IAAI,IAAI,OAAO,EAAE,KAAK,QAAQ;QAAE,OAAO,EAAE,CAAC;IACrD,MAAM,SAAS,GAAI,EAA8B,CAAC,WAAW,CAAC,CAAC;IAC/D,IAAI,SAAS,KAAK,IAAI,IAAI,OAAO,SAAS,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC;QAAE,OAAO,EAAE,CAAC;IAC/F,OAAO,MAAM,CAAC,IAAI,CAAC,SAAoC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;AACrG,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,IAAa;IACxC,4EAA4E;IAC5E,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACnH,CAAC;AAED;;;;;GAKG;AAEH,kGAAkG;AAClG,MAAM,UAAU,WAAW,CAAC,IAAa;IACvC,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,MAAM,IAAI,GAAG,CAAC,OAAgB,EAAQ,EAAE;QACtC,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;YAC3B,KAAK,MAAM,KAAK,IAAI,OAAO;gBAAE,IAAI,CAAC,KAAK,CAAC,CAAC;YACzC,OAAO;QACT,CAAC;QACD,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;YACpD,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;gBACnD,IAAI,GAAG,KAAK,MAAM,IAAI,OAAO,KAAK,KAAK,QAAQ;oBAAE,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;;oBAC5D,IAAI,CAAC,KAAK,CAAC,CAAC;YACnB,CAAC;QACH,CAAC;IACH,CAAC,CAAC;IACF,IAAI,CAAC,IAAI,CAAC,CAAC;IACX,OAAO,GAAG,CAAC;AACb,CAAC;AAED,yEAAyE;AACzE,MAAM,UAAU,cAAc,CAAC,IAAa,EAAE,GAAW;IACvD,IAAI,OAAO,GAAY,IAAI,CAAC;IAC5B,KAAK,MAAM,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QAC1C,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAC5D,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;YAC3B,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;YAC9B,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,IAAI,KAAK,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;gBACrE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;YAC5C,CAAC;YACD,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;QAC3B,CAAC;aAAM,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,IAAK,OAAmC,EAAE,CAAC;YAC9G,OAAO,GAAI,OAAmC,CAAC,OAAO,CAAC,CAAC;QAC1D,CAAC;aAAM,CAAC;YACN,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;QAC5C,CAAC;IACH,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;AACzC,CAAC","sourcesContent":["/**\n * The contract-depth probes: does an operation say anything about what it\n * returns, and does every internal `$ref` point at something.\n *\n * Form validated and depth did not, and that was invisible from the output:\n * an operation whose one response is `description: OK`, and a `$ref` to a\n * schema nobody ever wrote, both validate exactly as cleanly as a complete\n * contract even though a reader still needs the code. Everything here is a\n * PRESENCE probe over the document's own keys: nothing reads what a schema\n * says, only whether one was declared at all, so the reader's structure-only\n * stance holds.\n *\n * This module used to keep a private pointer walk rather than import the\n * merge's: the merge package already imports this package (`HTTP_METHODS` from\n * doc.ts), so the reverse import would have been a package cycle — the same\n * reason read-side `resolvePointer` copies exist on the asyncapi axis. The two\n * plain `$ref` questions now live HERE, at the axis root (`collectRefs` and\n * `resolvePointer`, at the bottom), so the private copy went: the dangling-ref\n * probe below, the merge's component closure and the reader's closure digest\n * (`closureDigester`, ./digest.ts) all ask the same two questions.\n */\n\n/** Status codes whose response legitimately carries no body. */\nconst NO_CONTENT = new Set([\"204\", \"304\"]);\n\n/**\n * True when no response declares content with a schema while at least one\n * response should carry a body — an operation with no `responses` at all\n * counts, one whose only responses are 204/304 does not. A response that is\n * itself a `$ref` counts as described: somebody wrote the shape down, and the\n * dangling case is the ref probe's finding, not this one's.\n */\nexport function responseUndescribed(op: unknown): boolean {\n if (op === null || typeof op !== \"object\") return true;\n const responses = (op as Record<string, unknown>)[\"responses\"];\n if (responses === null || responses === undefined || typeof responses !== \"object\" || Array.isArray(responses)) {\n return true;\n }\n const entries = Object.entries(responses as Record<string, unknown>);\n if (entries.length === 0) return true;\n let owesBody = false;\n for (const [code, resp] of entries) {\n if (NO_CONTENT.has(code)) continue;\n owesBody = true;\n if (resp === null || typeof resp !== \"object\" || Array.isArray(resp)) continue;\n const rec = resp as Record<string, unknown>;\n if (\"$ref\" in rec) return false;\n const content = rec[\"content\"];\n if (content === null || typeof content !== \"object\" || Array.isArray(content)) continue;\n for (const media of Object.values(content as Record<string, unknown>)) {\n if (media !== null && typeof media === \"object\" && \"schema\" in (media as Record<string, unknown>)) {\n return false;\n }\n }\n }\n return owesBody;\n}\n\n/**\n * The non-2xx response codes an operation declares, in document order.\n *\n * Exact three-digit codes only. `default` names no case — it is whatever else\n * happens — and the `4XX`/`5XX` wildcards name a class rather than a refusal,\n * so no scenario could be written for either and demanding one would teach an\n * author to write a scenario about nothing. 1xx and 3xx are excluded with 2xx:\n * a redirect or a continue is not the service saying no.\n */\nexport function failureCodesOf(op: unknown): string[] {\n if (op === null || typeof op !== \"object\") return [];\n const responses = (op as Record<string, unknown>)[\"responses\"];\n if (responses === null || typeof responses !== \"object\" || Array.isArray(responses)) return [];\n return Object.keys(responses as Record<string, unknown>).filter((code) => /^[45]\\d\\d$/.test(code));\n}\n\n/**\n * Every internal `#/` reference in the document that resolves to nothing —\n * deduped, document order. External references (URLs, file paths) are out of\n * scope and never graded, matching the merge's documented stance.\n */\nexport function danglingRefs(root: unknown): string[] {\n // A Set keeps first-insertion order, so dedup and document order both hold.\n return [...new Set(collectRefs(root).filter((ref) => ref.startsWith(\"#/\") && !resolvePointer(root, ref).found))];\n}\n\n/*\n * `$ref` as a pair of plain questions — which ones does this tree contain, and\n * what does one point at. Both lived in `./merge/components.ts`, beside the\n * component closure that was their only caller, until the reader needed the same\n * walk; the header says why the root and not there.\n */\n\n/** Every `$ref` string in a tree, in document order — duplicates kept, external refs included. */\nexport function collectRefs(node: unknown): string[] {\n const out: string[] = [];\n const walk = (current: unknown): void => {\n if (Array.isArray(current)) {\n for (const value of current) walk(value);\n return;\n }\n if (current !== null && typeof current === \"object\") {\n for (const [key, value] of Object.entries(current)) {\n if (key === \"$ref\" && typeof value === \"string\") out.push(value);\n else walk(value);\n }\n }\n };\n walk(node);\n return out;\n}\n\n/** Resolve a local JSON pointer (`#/a/b~1c`) against a plain JS tree. */\nexport function resolvePointer(root: unknown, ref: string): { found: boolean; value: unknown } {\n let current: unknown = root;\n for (const raw of ref.slice(2).split(\"/\")) {\n const segment = raw.replace(/~1/g, \"/\").replace(/~0/g, \"~\");\n if (Array.isArray(current)) {\n const index = Number(segment);\n if (!Number.isInteger(index) || index < 0 || index >= current.length) {\n return { found: false, value: undefined };\n }\n current = current[index];\n } else if (current !== null && typeof current === \"object\" && segment in (current as Record<string, unknown>)) {\n current = (current as Record<string, unknown>)[segment];\n } else {\n return { found: false, value: undefined };\n }\n }\n return { found: true, value: current };\n}\n"]}
@@ -10,14 +10,17 @@
10
10
  * is that it fires only for real ones.
11
11
  */
12
12
  import { createHash } from "node:crypto";
13
+ import { collectRefs, resolvePointer } from "./depth.js";
13
14
  /**
14
15
  * The baseline marker: which living version of this operation a FEATURE delta
15
16
  * was written against. Same idea as a requirement's `Based-On:` (core/document/spec.ts),
16
17
  * in the vendor-extension shape this axis already uses for `x-loam-remove`.
17
18
  *
18
19
  * This axis needs it MORE than the requirement axis does, because a feature's
19
- * openapi.yaml is a COMPLETE document rather than a patch: authors restate the
20
- * living contract around the slot they are changing, and the merge upserts every
20
+ * openapi.yaml may spell operations it does not change: it needs only what it
21
+ * adds, changes or removes (the merge leaves everything else to the living
22
+ * contract), but restating more is legal — for context, or a contract pasted
23
+ * whole, which is what loam's own docs once taught — and the merge upserts every
21
24
  * operation the document spells. So a feature that never meant to touch
22
25
  * `refundOrder` — it merely quoted it — pushes its authoring-time copy back over
23
26
  * whatever landed in between, reverting another team's shipped change without
@@ -154,6 +157,53 @@ export function valueDigest(node) {
154
157
  export function operationDigest(node) {
155
158
  return valueDigest(withoutOperationBaseline(node));
156
159
  }
160
+ /**
161
+ * The identity of what a node PROMISES rather than of its own bytes: the
162
+ * `operationDigest` input plus every internal `$ref` it reaches, transitively,
163
+ * each paired with the digest of what it resolves to in `root`. One digester per
164
+ * document; call it once per operation or message.
165
+ *
166
+ * `operationDigest` stops at the node on purpose — a pin says which version of
167
+ * THIS slot a delta was written against, and components carry their own pins.
168
+ * But a reviewer asking "did this operation change?" means the contract a
169
+ * consumer codes against, and in a factored document that is mostly somewhere
170
+ * else: renaming a required field of `#/components/schemas/Payment` leaves every
171
+ * operation returning it byte-identical, and `loam diff` reported exactly that
172
+ * PR as "no fleet-meaningful changes". This digest is what diff compares.
173
+ *
174
+ * The memo is per document and per ref, so a schema twenty operations reference
175
+ * is resolved, walked and hashed once. A ref that resolves to nothing still
176
+ * contributes — as a marker no 16-hex digest can equal — so a dangling ref that
177
+ * starts resolving reads as a change. External refs (anything not `#/`) are not
178
+ * followed, matching every other reader here; the ref string itself is part of
179
+ * the node's own bytes, so re-pointing one still moves the digest.
180
+ */
181
+ export function closureDigester(root) {
182
+ const targets = new Map();
183
+ const target = (ref) => {
184
+ let hit = targets.get(ref);
185
+ if (hit === undefined) {
186
+ const resolved = resolvePointer(root, ref);
187
+ hit = resolved.found ? { digest: valueDigest(resolved.value), refs: collectRefs(resolved.value) } : { digest: "unresolved", refs: [] };
188
+ targets.set(ref, hit);
189
+ }
190
+ return hit;
191
+ };
192
+ return (node) => {
193
+ const reached = new Map();
194
+ const queue = collectRefs(node);
195
+ while (queue.length > 0) {
196
+ const ref = queue.pop();
197
+ if (!ref.startsWith("#/") || reached.has(ref))
198
+ continue;
199
+ const hit = target(ref);
200
+ reached.set(ref, hit.digest);
201
+ queue.push(...hit.refs);
202
+ }
203
+ // canonicalJson sorts keys, so the walk order above never reaches the digest.
204
+ return valueDigest({ node: withoutOperationBaseline(node), refs: Object.fromEntries(reached) });
205
+ };
206
+ }
157
207
  /**
158
208
  * What a pin says, from digests alone — the one definition every decider
159
209
  * shares: the gate (./baseline/gate.ts) and the merge