@ybotok/loam 0.1.0-beta.3 → 0.2.0-alpha.1

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 (1026) hide show
  1. package/CHANGELOG.md +2548 -86
  2. package/COMPARISON.md +80 -63
  3. package/CONTRIBUTING.md +84 -0
  4. package/MIGRATING-from-OpenSpec.md +213 -54
  5. package/QUICKSTART.md +125 -0
  6. package/README.md +450 -150
  7. package/ROADMAP.md +494 -0
  8. package/SCHEMA.md +2355 -256
  9. package/SECURITY.md +21 -3
  10. package/WORKFLOW.md +701 -0
  11. package/dist/cli.js +113 -19
  12. package/dist/cli.js.map +1 -1
  13. package/dist/commands/adopt/adopt.js +209 -0
  14. package/dist/commands/adopt/adopt.js.map +1 -0
  15. package/dist/commands/adopt/render.js +268 -0
  16. package/dist/commands/adopt/render.js.map +1 -0
  17. package/dist/commands/archive/archive.js +77 -0
  18. package/dist/commands/archive/archive.js.map +1 -0
  19. package/dist/commands/archive/plan/contracts/asyncapi.js +178 -0
  20. package/dist/commands/archive/plan/contracts/asyncapi.js.map +1 -0
  21. package/dist/commands/archive/plan/contracts/openapi.js +159 -0
  22. package/dist/commands/archive/plan/contracts/openapi.js.map +1 -0
  23. package/dist/commands/archive/plan/gate.js +317 -0
  24. package/dist/commands/archive/plan/gate.js.map +1 -0
  25. package/dist/commands/archive/plan/landscape.js +161 -0
  26. package/dist/commands/archive/plan/landscape.js.map +1 -0
  27. package/dist/commands/archive/plan/refusal.js +111 -0
  28. package/dist/commands/archive/plan/refusal.js.map +1 -0
  29. package/dist/commands/archive/plan/specs.js +237 -0
  30. package/dist/commands/archive/plan/specs.js.map +1 -0
  31. package/dist/commands/archive/plan/state.js +27 -0
  32. package/dist/commands/archive/plan/state.js.map +1 -0
  33. package/dist/commands/archive/run.js +251 -0
  34. package/dist/commands/archive/run.js.map +1 -0
  35. package/dist/commands/context/context.js +99 -0
  36. package/dist/commands/context/context.js.map +1 -0
  37. package/dist/commands/context/print.js +283 -0
  38. package/dist/commands/context/print.js.map +1 -0
  39. package/dist/commands/delta/delta.js +279 -0
  40. package/dist/commands/delta/delta.js.map +1 -0
  41. package/dist/commands/delta/print.js +205 -0
  42. package/dist/commands/delta/print.js.map +1 -0
  43. package/dist/commands/dependencies.js +9 -7
  44. package/dist/commands/dependencies.js.map +1 -1
  45. package/dist/commands/diff/diff.js +93 -0
  46. package/dist/commands/diff/diff.js.map +1 -0
  47. package/dist/commands/diff/print.js +38 -0
  48. package/dist/commands/diff/print.js.map +1 -0
  49. package/dist/commands/doctor.js +5 -4
  50. package/dist/commands/doctor.js.map +1 -1
  51. package/dist/commands/explain/explain.js +151 -0
  52. package/dist/commands/explain/explain.js.map +1 -0
  53. package/dist/commands/explore.js +29 -24
  54. package/dist/commands/explore.js.map +1 -1
  55. package/dist/commands/gate/gate.js +115 -0
  56. package/dist/commands/gate/gate.js.map +1 -0
  57. package/dist/commands/gate/print.js +54 -0
  58. package/dist/commands/gate/print.js.map +1 -0
  59. package/dist/commands/gherkin/commit.js +146 -0
  60. package/dist/commands/gherkin/commit.js.map +1 -0
  61. package/dist/commands/gherkin/gherkin.js +246 -0
  62. package/dist/commands/gherkin/gherkin.js.map +1 -0
  63. package/dist/commands/gherkin/reconcile.js +149 -0
  64. package/dist/commands/gherkin/reconcile.js.map +1 -0
  65. package/dist/commands/gherkin/render.js +77 -0
  66. package/dist/commands/gherkin/render.js.map +1 -0
  67. package/dist/commands/init/example.js +204 -0
  68. package/dist/commands/init/example.js.map +1 -0
  69. package/dist/commands/init/first-hour.js +28 -0
  70. package/dist/commands/init/first-hour.js.map +1 -0
  71. package/dist/commands/{init.js → init/init.js} +146 -71
  72. package/dist/commands/init/init.js.map +1 -0
  73. package/dist/commands/init/mcp.js +131 -0
  74. package/dist/commands/init/mcp.js.map +1 -0
  75. package/dist/commands/init/options.js +78 -0
  76. package/dist/commands/init/options.js.map +1 -0
  77. package/dist/commands/instructions.js +72 -14
  78. package/dist/commands/instructions.js.map +1 -1
  79. package/dist/commands/list/campaign/campaign.js +65 -0
  80. package/dist/commands/list/campaign/campaign.js.map +1 -0
  81. package/dist/commands/list/campaign/owners.js +65 -0
  82. package/dist/commands/list/campaign/owners.js.map +1 -0
  83. package/dist/commands/list/json.js +157 -0
  84. package/dist/commands/list/json.js.map +1 -0
  85. package/dist/commands/list/list.js +343 -0
  86. package/dist/commands/list/list.js.map +1 -0
  87. package/dist/commands/list/print.js +301 -0
  88. package/dist/commands/list/print.js.map +1 -0
  89. package/dist/commands/list/review.js +120 -0
  90. package/dist/commands/list/review.js.map +1 -0
  91. package/dist/commands/list/views.js +105 -0
  92. package/dist/commands/list/views.js.map +1 -0
  93. package/dist/commands/mcp/dispatch.js +183 -0
  94. package/dist/commands/mcp/dispatch.js.map +1 -0
  95. package/dist/commands/mcp/mcp.js +34 -0
  96. package/dist/commands/mcp/mcp.js.map +1 -0
  97. package/dist/commands/mcp/serve.js +55 -0
  98. package/dist/commands/mcp/serve.js.map +1 -0
  99. package/dist/commands/migrate-openspec/materialize/active.js +170 -0
  100. package/dist/commands/migrate-openspec/materialize/active.js.map +1 -0
  101. package/dist/commands/migrate-openspec/materialize/feature.js +41 -0
  102. package/dist/commands/migrate-openspec/materialize/feature.js.map +1 -0
  103. package/dist/commands/migrate-openspec/materialize/living.js +62 -0
  104. package/dist/commands/migrate-openspec/materialize/living.js.map +1 -0
  105. package/dist/commands/migrate-openspec/materialize/stage.js +142 -0
  106. package/dist/commands/migrate-openspec/materialize/stage.js.map +1 -0
  107. package/dist/commands/migrate-openspec/materialize/target.js +219 -0
  108. package/dist/commands/migrate-openspec/materialize/target.js.map +1 -0
  109. package/dist/commands/migrate-openspec/migrate-openspec.js +142 -0
  110. package/dist/commands/migrate-openspec/migrate-openspec.js.map +1 -0
  111. package/dist/commands/migrate-openspec/openspec/decisions.js +91 -0
  112. package/dist/commands/migrate-openspec/openspec/decisions.js.map +1 -0
  113. package/dist/commands/migrate-openspec/openspec/error.js +19 -0
  114. package/dist/commands/migrate-openspec/openspec/error.js.map +1 -0
  115. package/dist/commands/migrate-openspec/openspec/mapping.js +170 -0
  116. package/dist/commands/migrate-openspec/openspec/mapping.js.map +1 -0
  117. package/dist/commands/migrate-openspec/openspec/paths.js +43 -0
  118. package/dist/commands/migrate-openspec/openspec/paths.js.map +1 -0
  119. package/dist/commands/migrate-openspec/openspec/read.js +49 -0
  120. package/dist/commands/migrate-openspec/openspec/read.js.map +1 -0
  121. package/dist/commands/migrate-openspec/print.js +89 -0
  122. package/dist/commands/migrate-openspec/print.js.map +1 -0
  123. package/dist/commands/new/commit.js +76 -0
  124. package/dist/commands/new/commit.js.map +1 -0
  125. package/dist/commands/new/new.js +283 -0
  126. package/dist/commands/new/new.js.map +1 -0
  127. package/dist/commands/new/templates.js +355 -0
  128. package/dist/commands/new/templates.js.map +1 -0
  129. package/dist/commands/open.js +203 -0
  130. package/dist/commands/open.js.map +1 -0
  131. package/dist/commands/policy/format.js +152 -0
  132. package/dist/commands/policy/format.js.map +1 -0
  133. package/dist/commands/{docs-repo-gate.js → policy/gate.js} +11 -11
  134. package/dist/commands/policy/gate.js.map +1 -0
  135. package/dist/commands/rebase/edit.js +106 -0
  136. package/dist/commands/rebase/edit.js.map +1 -0
  137. package/dist/commands/rebase/living.js +185 -0
  138. package/dist/commands/rebase/living.js.map +1 -0
  139. package/dist/commands/rebase/plan.js +245 -0
  140. package/dist/commands/rebase/plan.js.map +1 -0
  141. package/dist/commands/rebase/rebase.js +275 -0
  142. package/dist/commands/rebase/rebase.js.map +1 -0
  143. package/dist/commands/seed/commit.js +192 -0
  144. package/dist/commands/seed/commit.js.map +1 -0
  145. package/dist/commands/seed/plan.js +133 -0
  146. package/dist/commands/seed/plan.js.map +1 -0
  147. package/dist/commands/seed/seed.js +172 -0
  148. package/dist/commands/seed/seed.js.map +1 -0
  149. package/dist/commands/show/feature.js +178 -0
  150. package/dist/commands/show/feature.js.map +1 -0
  151. package/dist/commands/show/marks.js +24 -0
  152. package/dist/commands/show/marks.js.map +1 -0
  153. package/dist/commands/{show.js → show/service.js} +63 -152
  154. package/dist/commands/show/service.js.map +1 -0
  155. package/dist/commands/show/show.js +77 -0
  156. package/dist/commands/show/show.js.map +1 -0
  157. package/dist/commands/status/json.js +45 -0
  158. package/dist/commands/status/json.js.map +1 -0
  159. package/dist/commands/status/print.js +157 -0
  160. package/dist/commands/status/print.js.map +1 -0
  161. package/dist/commands/status/status.js +119 -0
  162. package/dist/commands/status/status.js.map +1 -0
  163. package/dist/commands/steps/steps.js +189 -0
  164. package/dist/commands/steps/steps.js.map +1 -0
  165. package/dist/commands/subsystem/edit.js +192 -0
  166. package/dist/commands/subsystem/edit.js.map +1 -0
  167. package/dist/commands/subsystem/move.js +265 -0
  168. package/dist/commands/subsystem/move.js.map +1 -0
  169. package/dist/commands/subsystem/query.js +115 -0
  170. package/dist/commands/subsystem/query.js.map +1 -0
  171. package/dist/commands/subsystem/subsystem.js +101 -0
  172. package/dist/commands/subsystem/subsystem.js.map +1 -0
  173. package/dist/commands/subsystem/sync.js +103 -0
  174. package/dist/commands/subsystem/sync.js.map +1 -0
  175. package/dist/commands/subsystem/txn/txn.js +94 -0
  176. package/dist/commands/subsystem/txn/txn.js.map +1 -0
  177. package/dist/commands/subsystem/txn/views.js +70 -0
  178. package/dist/commands/subsystem/txn/views.js.map +1 -0
  179. package/dist/commands/unarchive/manifest.js +160 -0
  180. package/dist/commands/unarchive/manifest.js.map +1 -0
  181. package/dist/commands/{unarchive.js → unarchive/restore.js} +47 -160
  182. package/dist/commands/unarchive/restore.js.map +1 -0
  183. package/dist/commands/unarchive/unarchive.js +67 -0
  184. package/dist/commands/unarchive/unarchive.js.map +1 -0
  185. package/dist/commands/validate/arch-coverage.js +194 -0
  186. package/dist/commands/validate/arch-coverage.js.map +1 -0
  187. package/dist/commands/validate/checks/fleet-shape.js +296 -0
  188. package/dist/commands/validate/checks/fleet-shape.js.map +1 -0
  189. package/dist/commands/validate/checks/health-deps.js +55 -0
  190. package/dist/commands/validate/checks/health-deps.js.map +1 -0
  191. package/dist/commands/validate/checks/requirements.js +254 -0
  192. package/dist/commands/validate/checks/requirements.js.map +1 -0
  193. package/dist/commands/validate/checks/sources.js +76 -0
  194. package/dist/commands/validate/checks/sources.js.map +1 -0
  195. package/dist/commands/validate/checks/vocabulary.js +31 -0
  196. package/dist/commands/validate/checks/vocabulary.js.map +1 -0
  197. package/dist/commands/validate/feature.js +216 -0
  198. package/dist/commands/validate/feature.js.map +1 -0
  199. package/dist/commands/validate/fleet/census.js +69 -0
  200. package/dist/commands/validate/fleet/census.js.map +1 -0
  201. package/dist/commands/validate/fleet/kind-tags.js +39 -0
  202. package/dist/commands/validate/fleet/kind-tags.js.map +1 -0
  203. package/dist/commands/validate/fleet/landscape.js +353 -0
  204. package/dist/commands/validate/fleet/landscape.js.map +1 -0
  205. package/dist/commands/validate/fleet/load.js +52 -0
  206. package/dist/commands/validate/fleet/load.js.map +1 -0
  207. package/dist/commands/validate/fleet/obligations.js +236 -0
  208. package/dist/commands/validate/fleet/obligations.js.map +1 -0
  209. package/dist/commands/validate/fleet/scorecard/adoption.js +102 -0
  210. package/dist/commands/validate/fleet/scorecard/adoption.js.map +1 -0
  211. package/dist/commands/validate/fleet/scorecard/contracts.js +98 -0
  212. package/dist/commands/validate/fleet/scorecard/contracts.js.map +1 -0
  213. package/dist/commands/validate/fleet/scorecard/print.js +63 -0
  214. package/dist/commands/validate/fleet/scorecard/print.js.map +1 -0
  215. package/dist/commands/validate/fleet/scorecard/scorecard.js +156 -0
  216. package/dist/commands/validate/fleet/scorecard/scorecard.js.map +1 -0
  217. package/dist/commands/validate/fleet/usecases/capability-tag.js +94 -0
  218. package/dist/commands/validate/fleet/usecases/capability-tag.js.map +1 -0
  219. package/dist/commands/validate/fleet/usecases/place.js +13 -0
  220. package/dist/commands/validate/fleet/usecases/place.js.map +1 -0
  221. package/dist/commands/validate/fleet/usecases/requirement-tag.js +95 -0
  222. package/dist/commands/validate/fleet/usecases/requirement-tag.js.map +1 -0
  223. package/dist/commands/validate/fleet/usecases/steps.js +197 -0
  224. package/dist/commands/validate/fleet/usecases/steps.js.map +1 -0
  225. package/dist/commands/validate/fleet/usecases/usecases.js +99 -0
  226. package/dist/commands/validate/fleet/usecases/usecases.js.map +1 -0
  227. package/dist/commands/validate/fleet/views/ids.js +40 -0
  228. package/dist/commands/validate/fleet/views/ids.js.map +1 -0
  229. package/dist/commands/validate/fleet/views/stale.js +59 -0
  230. package/dist/commands/validate/fleet/views/stale.js.map +1 -0
  231. package/dist/commands/validate/links/corpus.js +92 -0
  232. package/dist/commands/validate/links/corpus.js.map +1 -0
  233. package/dist/commands/validate/links/glossary.js +75 -0
  234. package/dist/commands/validate/links/glossary.js.map +1 -0
  235. package/dist/commands/validate/report.js +269 -0
  236. package/dist/commands/validate/report.js.map +1 -0
  237. package/dist/commands/validate/service/api.js +338 -0
  238. package/dist/commands/validate/service/api.js.map +1 -0
  239. package/dist/commands/validate/service/events/events.js +219 -0
  240. package/dist/commands/validate/service/events/events.js.map +1 -0
  241. package/dist/commands/validate/service/events/message-producers.js +77 -0
  242. package/dist/commands/validate/service/events/message-producers.js.map +1 -0
  243. package/dist/commands/validate/service/evidence-pins.js +131 -0
  244. package/dist/commands/validate/service/evidence-pins.js.map +1 -0
  245. package/dist/commands/validate/service/service.js +250 -0
  246. package/dist/commands/validate/service/service.js.map +1 -0
  247. package/dist/commands/validate/service/specs.js +219 -0
  248. package/dist/commands/validate/service/specs.js.map +1 -0
  249. package/dist/commands/validate/service/spine.js +113 -0
  250. package/dist/commands/validate/service/spine.js.map +1 -0
  251. package/dist/commands/validate/validate.js +338 -0
  252. package/dist/commands/validate/validate.js.map +1 -0
  253. package/dist/commands/verify/cross/diff.js +182 -0
  254. package/dist/commands/verify/cross/diff.js.map +1 -0
  255. package/dist/commands/verify/evidence/contract.js +32 -0
  256. package/dist/commands/verify/evidence/contract.js.map +1 -0
  257. package/dist/commands/verify/evidence/pins.js +52 -0
  258. package/dist/commands/verify/evidence/pins.js.map +1 -0
  259. package/dist/commands/verify/evidence/read.js +72 -0
  260. package/dist/commands/verify/evidence/read.js.map +1 -0
  261. package/dist/commands/verify/frozen.js +241 -0
  262. package/dist/commands/verify/frozen.js.map +1 -0
  263. package/dist/commands/verify/record.js +226 -0
  264. package/dist/commands/verify/record.js.map +1 -0
  265. package/dist/commands/verify/report.js +223 -0
  266. package/dist/commands/verify/report.js.map +1 -0
  267. package/dist/commands/verify/results.js +246 -0
  268. package/dist/commands/verify/results.js.map +1 -0
  269. package/dist/commands/verify/verify.js +217 -0
  270. package/dist/commands/verify/verify.js.map +1 -0
  271. package/dist/commands/vouch/contract.js +11 -0
  272. package/dist/commands/vouch/contract.js.map +1 -0
  273. package/dist/commands/vouch/pack/contract.js +2 -0
  274. package/dist/commands/vouch/pack/contract.js.map +1 -0
  275. package/dist/commands/vouch/pack/pack.js +266 -0
  276. package/dist/commands/vouch/pack/pack.js.map +1 -0
  277. package/dist/commands/vouch/pack/print.js +271 -0
  278. package/dist/commands/vouch/pack/print.js.map +1 -0
  279. package/dist/commands/vouch/pack/sections.js +142 -0
  280. package/dist/commands/vouch/pack/sections.js.map +1 -0
  281. package/dist/commands/vouch/prompt/confirm.js +46 -0
  282. package/dist/commands/vouch/prompt/confirm.js.map +1 -0
  283. package/dist/commands/vouch/report.js +101 -0
  284. package/dist/commands/vouch/report.js.map +1 -0
  285. package/dist/commands/vouch/run.js +285 -0
  286. package/dist/commands/vouch/run.js.map +1 -0
  287. package/dist/commands/vouch/sample/plan.js +125 -0
  288. package/dist/commands/vouch/sample/plan.js.map +1 -0
  289. package/dist/commands/vouch/sample/print.js +109 -0
  290. package/dist/commands/vouch/sample/print.js.map +1 -0
  291. package/dist/commands/vouch/vet/verify.js +123 -0
  292. package/dist/commands/vouch/vet/verify.js.map +1 -0
  293. package/dist/commands/vouch/vouch.js +176 -0
  294. package/dist/commands/vouch/vouch.js.map +1 -0
  295. package/dist/core/agent/agents-md/artifacts.js +220 -0
  296. package/dist/core/agent/agents-md/artifacts.js.map +1 -0
  297. package/dist/core/agent/agents-md/command-map.js +324 -0
  298. package/dist/core/agent/agents-md/command-map.js.map +1 -0
  299. package/dist/core/agent/agents-md/cycle.js +165 -0
  300. package/dist/core/agent/agents-md/cycle.js.map +1 -0
  301. package/dist/core/agent/agents-md/map/explain.js +34 -0
  302. package/dist/core/agent/agents-md/map/explain.js.map +1 -0
  303. package/dist/core/agent/agents-md/map/lenses/context.js +41 -0
  304. package/dist/core/agent/agents-md/map/lenses/context.js.map +1 -0
  305. package/dist/core/agent/agents-md/map/lenses/diff.js +46 -0
  306. package/dist/core/agent/agents-md/map/lenses/diff.js.map +1 -0
  307. package/dist/core/agent/agents-md/map/lenses/gate.js +57 -0
  308. package/dist/core/agent/agents-md/map/lenses/gate.js.map +1 -0
  309. package/dist/core/agent/agents-md/map/mcp.js +41 -0
  310. package/dist/core/agent/agents-md/map/mcp.js.map +1 -0
  311. package/dist/core/agent/agents-md/map/status.js +62 -0
  312. package/dist/core/agent/agents-md/map/status.js.map +1 -0
  313. package/dist/core/agent/agents-md/map/subsystem.js +32 -0
  314. package/dist/core/agent/agents-md/map/subsystem.js.map +1 -0
  315. package/dist/core/agent/agents-md/map/usecases.js +60 -0
  316. package/dist/core/agent/agents-md/map/usecases.js.map +1 -0
  317. package/dist/core/agent/agents-md/refusals.js +246 -0
  318. package/dist/core/agent/agents-md/refusals.js.map +1 -0
  319. package/dist/core/agent/agents-md/shipped/archive-gate.js +98 -0
  320. package/dist/core/agent/agents-md/shipped/archive-gate.js.map +1 -0
  321. package/dist/core/agent/agents-md/spine.js +40 -0
  322. package/dist/core/agent/agents-md/spine.js.map +1 -0
  323. package/dist/core/agent/agents-md.js +170 -0
  324. package/dist/core/agent/agents-md.js.map +1 -0
  325. package/dist/core/{agents-stamp.js → agent/agents-stamp.js} +50 -0
  326. package/dist/core/agent/agents-stamp.js.map +1 -0
  327. package/dist/core/agent/contract.js +2 -0
  328. package/dist/core/agent/contract.js.map +1 -0
  329. package/dist/core/agent/protocol.js +193 -0
  330. package/dist/core/agent/protocol.js.map +1 -0
  331. package/dist/core/agent/scaffold.js +259 -0
  332. package/dist/core/agent/scaffold.js.map +1 -0
  333. package/dist/core/agent/support/report.js +103 -0
  334. package/dist/core/agent/support/report.js.map +1 -0
  335. package/dist/core/agent/tools/dialects.js +150 -0
  336. package/dist/core/agent/tools/dialects.js.map +1 -0
  337. package/dist/core/agent/tools/registry.js +228 -0
  338. package/dist/core/agent/tools/registry.js.map +1 -0
  339. package/dist/core/agent/workflows/adopt.js +133 -0
  340. package/dist/core/agent/workflows/adopt.js.map +1 -0
  341. package/dist/core/agent/workflows/check.js +334 -0
  342. package/dist/core/agent/workflows/check.js.map +1 -0
  343. package/dist/core/agent/workflows/closing.js +262 -0
  344. package/dist/core/agent/workflows/closing.js.map +1 -0
  345. package/dist/core/agent/workflows/feature.js +105 -0
  346. package/dist/core/agent/workflows/feature.js.map +1 -0
  347. package/dist/core/agent/workflows/implement.js +105 -0
  348. package/dist/core/agent/workflows/implement.js.map +1 -0
  349. package/dist/core/agent/workflows/reference/authoring.js +209 -0
  350. package/dist/core/agent/workflows/reference/authoring.js.map +1 -0
  351. package/dist/core/agent/workflows/reference/codes.js +65 -0
  352. package/dist/core/agent/workflows/reference/codes.js.map +1 -0
  353. package/dist/core/agent/workflows/reference/done-check.js +188 -0
  354. package/dist/core/agent/workflows/reference/done-check.js.map +1 -0
  355. package/dist/core/agent/workflows/reference/reference.js +16 -0
  356. package/dist/core/agent/workflows/reference/reference.js.map +1 -0
  357. package/dist/core/agent/workflows/reference/spine.js +297 -0
  358. package/dist/core/agent/workflows/reference/spine.js.map +1 -0
  359. package/dist/core/asyncapi/baseline/plan.js +110 -0
  360. package/dist/core/asyncapi/baseline/plan.js.map +1 -0
  361. package/dist/core/asyncapi/baseline/surfaces.js +54 -0
  362. package/dist/core/asyncapi/baseline/surfaces.js.map +1 -0
  363. package/dist/core/asyncapi/depth.js +164 -0
  364. package/dist/core/asyncapi/depth.js.map +1 -0
  365. package/dist/core/asyncapi/digest.js +141 -0
  366. package/dist/core/asyncapi/digest.js.map +1 -0
  367. package/dist/core/asyncapi/merge/components.js +91 -0
  368. package/dist/core/asyncapi/merge/components.js.map +1 -0
  369. package/dist/core/asyncapi/merge/error.js +33 -0
  370. package/dist/core/asyncapi/merge/error.js.map +1 -0
  371. package/dist/core/asyncapi/merge/markers.js +308 -0
  372. package/dist/core/asyncapi/merge/markers.js.map +1 -0
  373. package/dist/core/asyncapi/merge/merge.js +215 -0
  374. package/dist/core/asyncapi/merge/merge.js.map +1 -0
  375. package/dist/core/asyncapi/merge/pin.js +107 -0
  376. package/dist/core/asyncapi/merge/pin.js.map +1 -0
  377. package/dist/core/asyncapi/model.js +11 -0
  378. package/dist/core/asyncapi/model.js.map +1 -0
  379. package/dist/core/asyncapi/producers.js +50 -0
  380. package/dist/core/asyncapi/producers.js.map +1 -0
  381. package/dist/core/{asyncapi.js → asyncapi/read.js} +95 -109
  382. package/dist/core/asyncapi/read.js.map +1 -0
  383. package/dist/core/brief/brief.js +225 -0
  384. package/dist/core/brief/brief.js.map +1 -0
  385. package/dist/core/brief/checks.js +250 -0
  386. package/dist/core/brief/checks.js.map +1 -0
  387. package/dist/core/brief/landscape.js +194 -0
  388. package/dist/core/brief/landscape.js.map +1 -0
  389. package/dist/core/brief/targets.js +226 -0
  390. package/dist/core/brief/targets.js.map +1 -0
  391. package/dist/core/brief/unchecked.js +47 -0
  392. package/dist/core/brief/unchecked.js.map +1 -0
  393. package/dist/core/c4/arch.js +282 -0
  394. package/dist/core/c4/arch.js.map +1 -0
  395. package/dist/core/c4/likec4.js +88 -0
  396. package/dist/core/c4/likec4.js.map +1 -0
  397. package/dist/core/c4/parsed/dynamic-views.js +132 -0
  398. package/dist/core/c4/parsed/dynamic-views.js.map +1 -0
  399. package/dist/core/c4/parsed/specification.js +78 -0
  400. package/dist/core/c4/parsed/specification.js.map +1 -0
  401. package/dist/core/c4/parsed/values.js +57 -0
  402. package/dist/core/c4/parsed/values.js.map +1 -0
  403. package/dist/core/c4/parsed/view-ids.js +75 -0
  404. package/dist/core/c4/parsed/view-ids.js.map +1 -0
  405. package/dist/core/c4/project/architecture.js +45 -0
  406. package/dist/core/c4/project/architecture.js.map +1 -0
  407. package/dist/core/c4/project/documents.js +58 -0
  408. package/dist/core/c4/project/documents.js.map +1 -0
  409. package/dist/core/c4/project/load.js +183 -0
  410. package/dist/core/c4/project/load.js.map +1 -0
  411. package/dist/core/c4/resolve/service.js +113 -0
  412. package/dist/core/c4/resolve/service.js.map +1 -0
  413. package/dist/core/c4/seed/fleet-file.js +201 -0
  414. package/dist/core/c4/seed/fleet-file.js.map +1 -0
  415. package/dist/core/c4/seed/items.js +91 -0
  416. package/dist/core/c4/seed/items.js.map +1 -0
  417. package/dist/core/c4/seed/stamp.js +48 -0
  418. package/dist/core/c4/seed/stamp.js.map +1 -0
  419. package/dist/core/c4/seed/template.js +109 -0
  420. package/dist/core/c4/seed/template.js.map +1 -0
  421. package/dist/core/c4/source-mask.js +82 -0
  422. package/dist/core/c4/source-mask.js.map +1 -0
  423. package/dist/core/c4/source-scan.js +227 -0
  424. package/dist/core/c4/source-scan.js.map +1 -0
  425. package/dist/core/c4/splice/authored-source.js +101 -0
  426. package/dist/core/c4/splice/authored-source.js.map +1 -0
  427. package/dist/core/c4/splice/contract.js +10 -0
  428. package/dist/core/c4/splice/contract.js.map +1 -0
  429. package/dist/core/c4/splice/delta-blocks.js +126 -0
  430. package/dist/core/c4/splice/delta-blocks.js.map +1 -0
  431. package/dist/core/c4/splice/identity/edges.js +36 -0
  432. package/dist/core/c4/splice/identity/edges.js.map +1 -0
  433. package/dist/core/c4/splice/landscape-merge.js +269 -0
  434. package/dist/core/c4/splice/landscape-merge.js.map +1 -0
  435. package/dist/core/c4/splice/placement.js +194 -0
  436. package/dist/core/c4/splice/placement.js.map +1 -0
  437. package/dist/core/c4/workspace.js +172 -0
  438. package/dist/core/c4/workspace.js.map +1 -0
  439. package/dist/core/capabilities/authoring/notes.js +141 -0
  440. package/dist/core/capabilities/authoring/notes.js.map +1 -0
  441. package/dist/core/capabilities/capabilities.js +124 -0
  442. package/dist/core/capabilities/capabilities.js.map +1 -0
  443. package/dist/core/capabilities/delta/doc.js +50 -0
  444. package/dist/core/capabilities/delta/doc.js.map +1 -0
  445. package/dist/core/capabilities/delta/overlay.js +129 -0
  446. package/dist/core/capabilities/delta/overlay.js.map +1 -0
  447. package/dist/core/capabilities/delta/summary.js +57 -0
  448. package/dist/core/capabilities/delta/summary.js.map +1 -0
  449. package/dist/core/capabilities/delta/tree.js +43 -0
  450. package/dist/core/capabilities/delta/tree.js.map +1 -0
  451. package/dist/core/capabilities/delta/uncovered.js +222 -0
  452. package/dist/core/capabilities/delta/uncovered.js.map +1 -0
  453. package/dist/core/capabilities/findings.js +342 -0
  454. package/dist/core/capabilities/findings.js.map +1 -0
  455. package/dist/core/capabilities/realizes/findings.js +181 -0
  456. package/dist/core/capabilities/realizes/findings.js.map +1 -0
  457. package/dist/core/capabilities/realizes/join.js +143 -0
  458. package/dist/core/capabilities/realizes/join.js.map +1 -0
  459. package/dist/core/capabilities/rollup.js +199 -0
  460. package/dist/core/capabilities/rollup.js.map +1 -0
  461. package/dist/core/capabilities/tree.js +126 -0
  462. package/dist/core/capabilities/tree.js.map +1 -0
  463. package/dist/core/capabilities/usecase-join.js +277 -0
  464. package/dist/core/capabilities/usecase-join.js.map +1 -0
  465. package/dist/core/coherence/authoring/scaffold.js +177 -0
  466. package/dist/core/coherence/authoring/scaffold.js.map +1 -0
  467. package/dist/core/coherence/authoring/sentinels.js +74 -0
  468. package/dist/core/coherence/authoring/sentinels.js.map +1 -0
  469. package/dist/core/coherence/coherence.js +251 -0
  470. package/dist/core/coherence/coherence.js.map +1 -0
  471. package/dist/core/coherence/declared.js +269 -0
  472. package/dist/core/coherence/declared.js.map +1 -0
  473. package/dist/core/coherence/events/declared.js +206 -0
  474. package/dist/core/coherence/events/declared.js.map +1 -0
  475. package/dist/core/coherence/events/events.js +204 -0
  476. package/dist/core/coherence/events/events.js.map +1 -0
  477. package/dist/core/coherence/events/grades.js +166 -0
  478. package/dist/core/coherence/events/grades.js.map +1 -0
  479. package/dist/core/coherence/events/lookups.js +122 -0
  480. package/dist/core/coherence/events/lookups.js.map +1 -0
  481. package/dist/core/coherence/events/merged.js +40 -0
  482. package/dist/core/coherence/events/merged.js.map +1 -0
  483. package/dist/core/coherence/living.js +198 -0
  484. package/dist/core/coherence/living.js.map +1 -0
  485. package/dist/core/coherence/lookups.js +155 -0
  486. package/dist/core/coherence/lookups.js.map +1 -0
  487. package/dist/core/coherence/pending.js +39 -0
  488. package/dist/core/coherence/pending.js.map +1 -0
  489. package/dist/core/conflict-markers.js +60 -0
  490. package/dist/core/conflict-markers.js.map +1 -0
  491. package/dist/core/delta/claims.js +73 -0
  492. package/dist/core/delta/claims.js.map +1 -0
  493. package/dist/core/delta/delta.js +296 -0
  494. package/dist/core/delta/delta.js.map +1 -0
  495. package/dist/core/delta/document.js +177 -0
  496. package/dist/core/delta/document.js.map +1 -0
  497. package/dist/core/delta/scope.js +48 -0
  498. package/dist/core/delta/scope.js.map +1 -0
  499. package/dist/core/delta/select.js +237 -0
  500. package/dist/core/delta/select.js.map +1 -0
  501. package/dist/core/dependencies/dependencies.js +141 -0
  502. package/dist/core/dependencies/dependencies.js.map +1 -0
  503. package/dist/core/dependencies/facts.js +165 -0
  504. package/dist/core/dependencies/facts.js.map +1 -0
  505. package/dist/core/dependencies/fanin.js +88 -0
  506. package/dist/core/dependencies/fanin.js.map +1 -0
  507. package/dist/core/dependencies/graph.js +106 -0
  508. package/dist/core/dependencies/graph.js.map +1 -0
  509. package/dist/core/diff/base-git.js +148 -0
  510. package/dist/core/diff/base-git.js.map +1 -0
  511. package/dist/core/diff/base-state.js +209 -0
  512. package/dist/core/diff/base-state.js.map +1 -0
  513. package/dist/core/diff/current-state.js +96 -0
  514. package/dist/core/diff/current-state.js.map +1 -0
  515. package/dist/core/diff/scope/changed-paths.js +188 -0
  516. package/dist/core/diff/scope/changed-paths.js.map +1 -0
  517. package/dist/core/diff/semantic.js +243 -0
  518. package/dist/core/diff/semantic.js.map +1 -0
  519. package/dist/core/diff/victims.js +247 -0
  520. package/dist/core/diff/victims.js.map +1 -0
  521. package/dist/core/docs.js +7 -64
  522. package/dist/core/docs.js.map +1 -1
  523. package/dist/core/doctor/agents.js +222 -0
  524. package/dist/core/doctor/agents.js.map +1 -0
  525. package/dist/core/doctor/config.js +135 -0
  526. package/dist/core/doctor/config.js.map +1 -0
  527. package/dist/core/doctor/doctor.js +275 -0
  528. package/dist/core/doctor/doctor.js.map +1 -0
  529. package/dist/core/doctor/report.js +13 -0
  530. package/dist/core/doctor/report.js.map +1 -0
  531. package/dist/core/doctor/residue.js +110 -0
  532. package/dist/core/doctor/residue.js.map +1 -0
  533. package/dist/core/document/apply.js +77 -0
  534. package/dist/core/document/apply.js.map +1 -0
  535. package/dist/core/{frontmatter.js → document/frontmatter.js} +48 -2
  536. package/dist/core/document/frontmatter.js.map +1 -0
  537. package/dist/core/document/grammar/directives.js +143 -0
  538. package/dist/core/document/grammar/directives.js.map +1 -0
  539. package/dist/core/document/parse.js +263 -0
  540. package/dist/core/document/parse.js.map +1 -0
  541. package/dist/core/document/scenarios.js +221 -0
  542. package/dist/core/document/scenarios.js.map +1 -0
  543. package/dist/core/document/spec.js +241 -0
  544. package/dist/core/document/spec.js.map +1 -0
  545. package/dist/core/{config.js → envelope/config.js} +79 -18
  546. package/dist/core/envelope/config.js.map +1 -0
  547. package/dist/core/envelope/json.js +175 -0
  548. package/dist/core/envelope/json.js.map +1 -0
  549. package/dist/core/{version.js → envelope/version.js} +3 -3
  550. package/dist/core/envelope/version.js.map +1 -0
  551. package/dist/core/explain/families.js +175 -0
  552. package/dist/core/explain/families.js.map +1 -0
  553. package/dist/core/explain/fix-tables.js +178 -0
  554. package/dist/core/explain/fix-tables.js.map +1 -0
  555. package/dist/core/explain/lookup.js +181 -0
  556. package/dist/core/explain/lookup.js.map +1 -0
  557. package/dist/core/explain/refusals.js +49 -0
  558. package/dist/core/explain/refusals.js.map +1 -0
  559. package/dist/core/explain/terms.js +144 -0
  560. package/dist/core/explain/terms.js.map +1 -0
  561. package/dist/core/explore/describe.js +105 -0
  562. package/dist/core/explore/describe.js.map +1 -0
  563. package/dist/core/{explore.js → explore/explore.js} +50 -101
  564. package/dist/core/explore/explore.js.map +1 -0
  565. package/dist/core/fleet-context.js +120 -78
  566. package/dist/core/fleet-context.js.map +1 -1
  567. package/dist/core/gate/checks.js +201 -0
  568. package/dist/core/gate/checks.js.map +1 -0
  569. package/dist/core/gate/partners.js +205 -0
  570. package/dist/core/gate/partners.js.map +1 -0
  571. package/dist/core/gate/report.js +47 -0
  572. package/dist/core/gate/report.js.map +1 -0
  573. package/dist/core/gate/verification.js +113 -0
  574. package/dist/core/gate/verification.js.map +1 -0
  575. package/dist/core/gherkin/digest.js +60 -0
  576. package/dist/core/gherkin/digest.js.map +1 -0
  577. package/dist/core/gherkin/emit.js +177 -0
  578. package/dist/core/gherkin/emit.js.map +1 -0
  579. package/dist/core/gherkin/read.js +76 -0
  580. package/dist/core/gherkin/read.js.map +1 -0
  581. package/dist/core/gherkin/stale.js +234 -0
  582. package/dist/core/gherkin/stale.js.map +1 -0
  583. package/dist/core/gherkin/stamp.js +77 -0
  584. package/dist/core/gherkin/stamp.js.map +1 -0
  585. package/dist/core/gherkin/steps/catalogue.js +154 -0
  586. package/dist/core/gherkin/steps/catalogue.js.map +1 -0
  587. package/dist/core/gherkin/steps/inventory.js +98 -0
  588. package/dist/core/gherkin/steps/inventory.js.map +1 -0
  589. package/dist/core/gherkin/steps/phrase.js +72 -0
  590. package/dist/core/gherkin/steps/phrase.js.map +1 -0
  591. package/dist/core/glossary/delta.js +106 -0
  592. package/dist/core/glossary/delta.js.map +1 -0
  593. package/dist/core/glossary/tree.js +86 -0
  594. package/dist/core/glossary/tree.js.map +1 -0
  595. package/dist/core/kernel/concurrency.js.map +1 -0
  596. package/dist/core/{document-bytes.js → kernel/document-bytes.js} +1 -1
  597. package/dist/core/kernel/document-bytes.js.map +1 -0
  598. package/dist/core/kernel/fences.js +42 -0
  599. package/dist/core/kernel/fences.js.map +1 -0
  600. package/dist/core/kernel/ids/capability.js +72 -0
  601. package/dist/core/kernel/ids/capability.js.map +1 -0
  602. package/dist/core/kernel/ids/dirs.js +33 -0
  603. package/dist/core/kernel/ids/dirs.js.map +1 -0
  604. package/dist/core/kernel/ids/feature.js +75 -0
  605. package/dist/core/kernel/ids/feature.js.map +1 -0
  606. package/dist/core/kernel/ids/service.js +156 -0
  607. package/dist/core/kernel/ids/service.js.map +1 -0
  608. package/dist/core/kernel/ids/subsystem.js +63 -0
  609. package/dist/core/kernel/ids/subsystem.js.map +1 -0
  610. package/dist/core/{path-safety.js → kernel/path-safety.js} +18 -4
  611. package/dist/core/kernel/path-safety.js.map +1 -0
  612. package/dist/core/kernel/records.js.map +1 -0
  613. package/dist/core/links/backlinks.js +68 -0
  614. package/dist/core/links/backlinks.js.map +1 -0
  615. package/dist/core/links/case.js +74 -0
  616. package/dist/core/links/case.js.map +1 -0
  617. package/dist/core/links/corpus.js +104 -0
  618. package/dist/core/links/corpus.js.map +1 -0
  619. package/dist/core/links/findings.js +110 -0
  620. package/dist/core/links/findings.js.map +1 -0
  621. package/dist/core/links/parse.js +236 -0
  622. package/dist/core/links/parse.js.map +1 -0
  623. package/dist/core/mcp/argv.js +111 -0
  624. package/dist/core/mcp/argv.js.map +1 -0
  625. package/dist/core/mcp/author-tools.js +72 -0
  626. package/dist/core/mcp/author-tools.js.map +1 -0
  627. package/dist/core/mcp/framing.js +46 -0
  628. package/dist/core/mcp/framing.js.map +1 -0
  629. package/dist/core/mcp/protocol.js +280 -0
  630. package/dist/core/mcp/protocol.js.map +1 -0
  631. package/dist/core/mcp/tools.js +314 -0
  632. package/dist/core/mcp/tools.js.map +1 -0
  633. package/dist/core/obligations/obligations.js +106 -0
  634. package/dist/core/obligations/obligations.js.map +1 -0
  635. package/dist/core/openapi/baseline/gate.js +166 -0
  636. package/dist/core/openapi/baseline/gate.js.map +1 -0
  637. package/dist/core/openapi/baseline/plan.js +112 -0
  638. package/dist/core/openapi/baseline/plan.js.map +1 -0
  639. package/dist/core/openapi/baseline/record.js +175 -0
  640. package/dist/core/openapi/baseline/record.js.map +1 -0
  641. package/dist/core/openapi/depth.js +122 -0
  642. package/dist/core/openapi/depth.js.map +1 -0
  643. package/dist/core/openapi/digest.js +189 -0
  644. package/dist/core/openapi/digest.js.map +1 -0
  645. package/dist/core/{openapi.js → openapi/doc.js} +44 -106
  646. package/dist/core/openapi/doc.js.map +1 -0
  647. package/dist/core/openapi/merge/components.js +234 -0
  648. package/dist/core/openapi/merge/components.js.map +1 -0
  649. package/dist/core/openapi/merge/error.js +26 -0
  650. package/dist/core/openapi/merge/error.js.map +1 -0
  651. package/dist/core/openapi/merge/markers.js +208 -0
  652. package/dist/core/openapi/merge/markers.js.map +1 -0
  653. package/dist/core/openapi/merge/merge.js +256 -0
  654. package/dist/core/openapi/merge/merge.js.map +1 -0
  655. package/dist/core/openapi/merge/pin.js +128 -0
  656. package/dist/core/openapi/merge/pin.js.map +1 -0
  657. package/dist/core/openspec/decide/capabilities.js +244 -0
  658. package/dist/core/openspec/decide/capabilities.js.map +1 -0
  659. package/dist/core/openspec/decide/dispositions.js +63 -0
  660. package/dist/core/openspec/decide/dispositions.js.map +1 -0
  661. package/dist/core/openspec/decide/renames.js +179 -0
  662. package/dist/core/openspec/decide/renames.js.map +1 -0
  663. package/dist/core/openspec/decide/verdict.js +84 -0
  664. package/dist/core/openspec/decide/verdict.js.map +1 -0
  665. package/dist/core/openspec/inventory.js +221 -0
  666. package/dist/core/openspec/inventory.js.map +1 -0
  667. package/dist/core/openspec/model/mapping.js +76 -0
  668. package/dist/core/openspec/model/mapping.js.map +1 -0
  669. package/dist/core/openspec/model/model.js +65 -0
  670. package/dist/core/openspec/model/model.js.map +1 -0
  671. package/dist/core/openspec/scan/changes.js +235 -0
  672. package/dist/core/openspec/scan/changes.js.map +1 -0
  673. package/dist/core/openspec/scan/config.js +200 -0
  674. package/dist/core/openspec/scan/config.js.map +1 -0
  675. package/dist/core/openspec/scan/shape.js +260 -0
  676. package/dist/core/openspec/scan/shape.js.map +1 -0
  677. package/dist/core/openspec/scan/walk.js +133 -0
  678. package/dist/core/openspec/scan/walk.js.map +1 -0
  679. package/dist/core/openspec/scan/workspace.js +71 -0
  680. package/dist/core/openspec/scan/workspace.js.map +1 -0
  681. package/dist/core/owners/codeowners.js +141 -0
  682. package/dist/core/owners/codeowners.js.map +1 -0
  683. package/dist/core/pack/features.js +120 -0
  684. package/dist/core/pack/features.js.map +1 -0
  685. package/dist/core/pack/joins.js +112 -0
  686. package/dist/core/pack/joins.js.map +1 -0
  687. package/dist/core/pack/living.js +118 -0
  688. package/dist/core/pack/living.js.map +1 -0
  689. package/dist/core/pack/pack.js +76 -0
  690. package/dist/core/pack/pack.js.map +1 -0
  691. package/dist/core/permissions/permissions.js +87 -0
  692. package/dist/core/permissions/permissions.js.map +1 -0
  693. package/dist/core/projection/api.js +84 -0
  694. package/dist/core/projection/api.js.map +1 -0
  695. package/dist/core/projection/arch-slice.js +63 -0
  696. package/dist/core/projection/arch-slice.js.map +1 -0
  697. package/dist/core/projection/events.js +34 -0
  698. package/dist/core/projection/events.js.map +1 -0
  699. package/dist/core/provenance/findings.js +208 -0
  700. package/dist/core/provenance/findings.js.map +1 -0
  701. package/dist/core/provenance/git.js +225 -0
  702. package/dist/core/provenance/git.js.map +1 -0
  703. package/dist/core/provenance/gitq/moves.js +182 -0
  704. package/dist/core/provenance/gitq/moves.js.map +1 -0
  705. package/dist/core/provenance/gitq/vouched-ancestor.js +179 -0
  706. package/dist/core/provenance/gitq/vouched-ancestor.js.map +1 -0
  707. package/dist/core/provenance/sample/scope.js +238 -0
  708. package/dist/core/provenance/sample/scope.js.map +1 -0
  709. package/dist/core/provenance/sample/sections.js +61 -0
  710. package/dist/core/provenance/sample/sections.js.map +1 -0
  711. package/dist/core/provenance/sources.js +263 -0
  712. package/dist/core/provenance/sources.js.map +1 -0
  713. package/dist/core/provenance/stamp.js +232 -0
  714. package/dist/core/provenance/stamp.js.map +1 -0
  715. package/dist/core/provenance/walk.js +157 -0
  716. package/dist/core/provenance/walk.js.map +1 -0
  717. package/dist/core/repo/authored/paths.js +192 -0
  718. package/dist/core/repo/authored/paths.js.map +1 -0
  719. package/dist/core/repo/entries.js +126 -0
  720. package/dist/core/repo/entries.js.map +1 -0
  721. package/dist/core/repo/paths.js +236 -0
  722. package/dist/core/repo/paths.js.map +1 -0
  723. package/dist/core/repo/repo.js +248 -0
  724. package/dist/core/repo/repo.js.map +1 -0
  725. package/dist/core/repo/service-target.js +153 -0
  726. package/dist/core/repo/service-target.js.map +1 -0
  727. package/dist/core/repo/state.js +58 -0
  728. package/dist/core/repo/state.js.map +1 -0
  729. package/dist/core/repo/tree/find.js +52 -0
  730. package/dist/core/repo/tree/find.js.map +1 -0
  731. package/dist/core/repo/tree/fs.js +64 -0
  732. package/dist/core/repo/tree/fs.js.map +1 -0
  733. package/dist/core/repo/tree/marker.js +61 -0
  734. package/dist/core/repo/tree/marker.js.map +1 -0
  735. package/dist/core/repo/tree/views.js +172 -0
  736. package/dist/core/repo/tree/views.js.map +1 -0
  737. package/dist/core/repo/tree/walk.js +234 -0
  738. package/dist/core/repo/tree/walk.js.map +1 -0
  739. package/dist/core/results.js +99 -2
  740. package/dist/core/results.js.map +1 -1
  741. package/dist/core/scaffold/landscape.js +131 -0
  742. package/dist/core/scaffold/landscape.js.map +1 -0
  743. package/dist/core/scaffold/readme.js +84 -0
  744. package/dist/core/scaffold/readme.js.map +1 -0
  745. package/dist/core/staging/commit.js +241 -0
  746. package/dist/core/staging/commit.js.map +1 -0
  747. package/dist/core/staging/interrupted.js +96 -0
  748. package/dist/core/staging/interrupted.js.map +1 -0
  749. package/dist/core/staging/lock.js +206 -0
  750. package/dist/core/staging/lock.js.map +1 -0
  751. package/dist/core/staging/recovery/finding.js +35 -0
  752. package/dist/core/staging/recovery/finding.js.map +1 -0
  753. package/dist/core/staging/recovery/intent.js +98 -0
  754. package/dist/core/staging/recovery/intent.js.map +1 -0
  755. package/dist/core/staging/recovery/recover.js +126 -0
  756. package/dist/core/staging/recovery/recover.js.map +1 -0
  757. package/dist/core/staging/recovery/residue.js +62 -0
  758. package/dist/core/staging/recovery/residue.js.map +1 -0
  759. package/dist/core/staging/snapshot.js +202 -0
  760. package/dist/core/staging/snapshot.js.map +1 -0
  761. package/dist/core/staging/txn/forward.js +171 -0
  762. package/dist/core/staging/txn/forward.js.map +1 -0
  763. package/dist/core/staging/txn/journal.js +139 -0
  764. package/dist/core/staging/txn/journal.js.map +1 -0
  765. package/dist/core/staging/txn/transaction.js +75 -0
  766. package/dist/core/staging/txn/transaction.js.map +1 -0
  767. package/dist/core/staging/writes.js +113 -0
  768. package/dist/core/staging/writes.js.map +1 -0
  769. package/dist/core/status/actions/execution.js +49 -0
  770. package/dist/core/status/actions/execution.js.map +1 -0
  771. package/dist/core/status/contracts.js +102 -0
  772. package/dist/core/status/contracts.js.map +1 -0
  773. package/dist/core/status/feature/artifacts.js +171 -0
  774. package/dist/core/status/feature/artifacts.js.map +1 -0
  775. package/dist/core/status/feature/feature.js +207 -0
  776. package/dist/core/status/feature/feature.js.map +1 -0
  777. package/dist/core/status/feature/next.js +150 -0
  778. package/dist/core/status/feature/next.js.map +1 -0
  779. package/dist/core/status/feature/state.js +21 -0
  780. package/dist/core/status/feature/state.js.map +1 -0
  781. package/dist/core/status/fleet/fleet.js +187 -0
  782. package/dist/core/status/fleet/fleet.js.map +1 -0
  783. package/dist/core/status/fleet/next.js +207 -0
  784. package/dist/core/status/fleet/next.js.map +1 -0
  785. package/dist/core/status/interrupted.js +97 -0
  786. package/dist/core/status/interrupted.js.map +1 -0
  787. package/dist/core/status/report.js +31 -0
  788. package/dist/core/status/report.js.map +1 -0
  789. package/dist/core/status/scan.js +41 -0
  790. package/dist/core/status/scan.js.map +1 -0
  791. package/dist/core/status/verification.js +201 -0
  792. package/dist/core/status/verification.js.map +1 -0
  793. package/dist/core/usecases/capability.js +169 -0
  794. package/dist/core/usecases/capability.js.map +1 -0
  795. package/dist/core/usecases/delta/claims.js +116 -0
  796. package/dist/core/usecases/delta/claims.js.map +1 -0
  797. package/dist/core/usecases/delta/flows.js +103 -0
  798. package/dist/core/usecases/delta/flows.js.map +1 -0
  799. package/dist/core/usecases/delta/overlay.js +235 -0
  800. package/dist/core/usecases/delta/overlay.js.map +1 -0
  801. package/dist/core/usecases/fleet.js +137 -0
  802. package/dist/core/usecases/fleet.js.map +1 -0
  803. package/dist/core/usecases/operations.js +111 -0
  804. package/dist/core/usecases/operations.js.map +1 -0
  805. package/dist/core/usecases/place.js +44 -0
  806. package/dist/core/usecases/place.js.map +1 -0
  807. package/dist/core/usecases/touch.js +101 -0
  808. package/dist/core/usecases/touch.js.map +1 -0
  809. package/dist/core/verify/answers.js +173 -0
  810. package/dist/core/verify/answers.js.map +1 -0
  811. package/dist/core/verify/build.js +150 -0
  812. package/dist/core/verify/build.js.map +1 -0
  813. package/dist/core/verify/checklist.js +201 -0
  814. package/dist/core/verify/checklist.js.map +1 -0
  815. package/dist/core/verify/claims/identity.js +61 -0
  816. package/dist/core/verify/claims/identity.js.map +1 -0
  817. package/dist/core/verify/cross/diff.js +97 -0
  818. package/dist/core/verify/cross/diff.js.map +1 -0
  819. package/dist/core/verify/evidence/contract.js +169 -0
  820. package/dist/core/verify/evidence/contract.js.map +1 -0
  821. package/dist/core/verify/file.js +257 -0
  822. package/dist/core/verify/file.js.map +1 -0
  823. package/dist/core/verify/pins/lint.js +157 -0
  824. package/dist/core/verify/pins/lint.js.map +1 -0
  825. package/dist/core/verify/pins/pin.js +95 -0
  826. package/dist/core/verify/pins/pin.js.map +1 -0
  827. package/dist/core/verify/record.js +142 -0
  828. package/dist/core/verify/record.js.map +1 -0
  829. package/dist/core/verify/store/commit.js +89 -0
  830. package/dist/core/verify/store/commit.js.map +1 -0
  831. package/dist/core/verify/store/render.js +57 -0
  832. package/dist/core/verify/store/render.js.map +1 -0
  833. package/dist/core/vocabulary/health.js +91 -0
  834. package/dist/core/vocabulary/health.js.map +1 -0
  835. package/dist/core/vocabulary/issue.js +55 -0
  836. package/dist/core/vocabulary/issue.js.map +1 -0
  837. package/dist/core/vocabulary/maturity.js +145 -0
  838. package/dist/core/vocabulary/maturity.js.map +1 -0
  839. package/dist/core/{report.js → vocabulary/report.js} +30 -2
  840. package/dist/core/vocabulary/report.js.map +1 -0
  841. package/dist/core/vocabulary/steps.js +266 -0
  842. package/dist/core/vocabulary/steps.js.map +1 -0
  843. package/dist/core/workspace/discover.js +239 -0
  844. package/dist/core/workspace/discover.js.map +1 -0
  845. package/dist/core/workspace/render.js +52 -0
  846. package/dist/core/workspace/render.js.map +1 -0
  847. package/examples/README.md +189 -0
  848. package/examples/docs/architecture/adrs/0001-transactional-outbox.md +33 -0
  849. package/examples/docs/architecture/capabilities.yaml +31 -0
  850. package/examples/docs/architecture/landscape.likec4 +280 -0
  851. package/examples/docs/architecture/obligations.yaml +23 -0
  852. package/examples/docs/architecture/permissions.yaml +50 -0
  853. package/examples/docs/architecture/subsystems.likec4 +11 -0
  854. package/examples/docs/architecture/usecases/order-notification.likec4 +65 -0
  855. package/examples/docs/capabilities/checkout/spec.md +55 -0
  856. package/examples/docs/capabilities/identity/tokens/spec.md +42 -0
  857. package/examples/docs/capabilities/order-notifications/spec.md +43 -0
  858. package/examples/docs/features/FEAT-101-payment-splitting/adrs/0001-dedicated-split-service.md +18 -0
  859. package/examples/docs/features/FEAT-101-payment-splitting/delta.likec4 +94 -0
  860. package/examples/docs/features/FEAT-101-payment-splitting/intent.md +44 -0
  861. package/examples/docs/features/FEAT-101-payment-splitting/specs/checkout-web/spec.md +21 -0
  862. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-service/asyncapi.yaml +129 -0
  863. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-service/spec.md +36 -0
  864. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/arch.spec.md +40 -0
  865. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/openapi.yaml +116 -0
  866. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/spec.md +55 -0
  867. package/examples/docs/features/FEAT-112-retire-order-v1/intent.md +35 -0
  868. package/examples/docs/features/FEAT-112-retire-order-v1/specs/order-service/openapi.yaml +28 -0
  869. package/examples/docs/features/FEAT-112-retire-order-v1/specs/order-service/spec.md +17 -0
  870. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/architecture/landscape.likec4 +253 -0
  871. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/services/order-service/spec.md +121 -0
  872. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/services/payment-service/openapi.yaml +111 -0
  873. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/services/payment-service/spec.md +58 -0
  874. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/manifest.json +32 -0
  875. package/examples/docs/features/archive/FEAT-088-refunds/adrs/0001-refunds-stay-in-payment-service.md +26 -0
  876. package/examples/docs/features/archive/FEAT-088-refunds/delta.likec4 +28 -0
  877. package/examples/docs/features/archive/FEAT-088-refunds/intent.md +26 -0
  878. package/examples/docs/features/archive/FEAT-088-refunds/specs/order-service/spec.md +37 -0
  879. package/examples/docs/features/archive/FEAT-088-refunds/specs/payment-service/openapi.yaml +70 -0
  880. package/examples/docs/features/archive/FEAT-088-refunds/specs/payment-service/spec.md +23 -0
  881. package/examples/docs/features/archive/FEAT-088-refunds/verification.yaml +76 -0
  882. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/architecture/landscape.likec4 +275 -0
  883. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/payment-service/asyncapi.yaml +96 -0
  884. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/payment-service/spec.md +82 -0
  885. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/platform/notification-service/asyncapi.yaml +164 -0
  886. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/platform/notification-service/spec.md +91 -0
  887. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/manifest.json +46 -0
  888. package/examples/docs/features/archive/FEAT-120-refund-notification/delta.likec4 +36 -0
  889. package/examples/docs/features/archive/FEAT-120-refund-notification/intent.md +22 -0
  890. package/examples/docs/features/archive/FEAT-120-refund-notification/scenario-report.json +10 -0
  891. package/examples/docs/features/archive/FEAT-120-refund-notification/specs/notification-service/asyncapi.yaml +208 -0
  892. package/examples/docs/features/archive/FEAT-120-refund-notification/specs/notification-service/spec.md +24 -0
  893. package/examples/docs/features/archive/FEAT-120-refund-notification/specs/payment-service/asyncapi.yaml +137 -0
  894. package/examples/docs/features/archive/FEAT-120-refund-notification/specs/payment-service/spec.md +31 -0
  895. package/examples/docs/features/archive/FEAT-120-refund-notification/verification.yaml +84 -0
  896. package/examples/docs/glossary/order.md +15 -0
  897. package/examples/docs/glossary/payments/authorization.md +14 -0
  898. package/examples/docs/likec4.config.json +9 -0
  899. package/examples/docs/loam.json +3 -0
  900. package/examples/docs/services/checkout-web/model.likec4 +109 -0
  901. package/examples/docs/services/checkout-web/spec.md +91 -0
  902. package/examples/docs/services/checkout-web/ui/pages/checkout.page.yaml +40 -0
  903. package/examples/docs/services/checkout-web/ui/pages/order-status.page.yaml +24 -0
  904. package/examples/docs/services/checkout-web/ui/pages/split-payment.page.yaml +26 -0
  905. package/examples/docs/services/order-service/adrs/0001-orchestrated-order-lifecycle.md +52 -0
  906. package/examples/docs/services/order-service/arch.spec.md +127 -0
  907. package/examples/docs/services/order-service/asyncapi.yaml +108 -0
  908. package/examples/docs/services/order-service/health.yaml +57 -0
  909. package/examples/docs/services/order-service/model.likec4 +138 -0
  910. package/examples/docs/services/order-service/openapi.yaml +257 -0
  911. package/examples/docs/services/order-service/runbook.md +62 -0
  912. package/examples/docs/services/order-service/spec.md +134 -0
  913. package/examples/docs/services/payment-service/adrs/0001-payments-outbox.md +18 -0
  914. package/examples/docs/services/payment-service/adrs/0002-idempotency-keys-on-authorization.md +27 -0
  915. package/examples/docs/services/payment-service/arch.spec.md +73 -0
  916. package/examples/docs/services/payment-service/asyncapi.yaml +130 -0
  917. package/examples/docs/services/payment-service/health.yaml +39 -0
  918. package/examples/docs/services/payment-service/model.likec4 +67 -0
  919. package/examples/docs/services/payment-service/openapi.yaml +151 -0
  920. package/examples/docs/services/payment-service/runbook.md +37 -0
  921. package/examples/docs/services/payment-service/spec.md +88 -0
  922. package/examples/docs/services/platform/identity-service/adrs/0001-token-introspection-over-local-validation.md +60 -0
  923. package/examples/docs/services/platform/identity-service/arch.spec.md +117 -0
  924. package/examples/docs/services/platform/identity-service/health.yaml +70 -0
  925. package/examples/docs/services/platform/identity-service/model.likec4 +83 -0
  926. package/examples/docs/services/platform/identity-service/openapi.yaml +197 -0
  927. package/examples/docs/services/platform/identity-service/runbook.md +95 -0
  928. package/examples/docs/services/platform/identity-service/spec.md +119 -0
  929. package/examples/docs/services/platform/notification-service/asyncapi.yaml +199 -0
  930. package/examples/docs/services/platform/notification-service/health.yaml +35 -0
  931. package/examples/docs/services/platform/notification-service/model.likec4 +118 -0
  932. package/examples/docs/services/platform/notification-service/runbook.md +48 -0
  933. package/examples/docs/services/platform/notification-service/spec.md +112 -0
  934. package/examples/docs/services/platform/subsystem.yaml +2 -0
  935. package/examples/fleet.yaml +57 -0
  936. package/package.json +19 -6
  937. package/dist/commands/adopt.js +0 -240
  938. package/dist/commands/adopt.js.map +0 -1
  939. package/dist/commands/archive.js +0 -1313
  940. package/dist/commands/archive.js.map +0 -1
  941. package/dist/commands/delta.js +0 -388
  942. package/dist/commands/delta.js.map +0 -1
  943. package/dist/commands/docs-repo-gate.js.map +0 -1
  944. package/dist/commands/format.js +0 -17
  945. package/dist/commands/format.js.map +0 -1
  946. package/dist/commands/gherkin.js +0 -309
  947. package/dist/commands/gherkin.js.map +0 -1
  948. package/dist/commands/init.js.map +0 -1
  949. package/dist/commands/list.js +0 -295
  950. package/dist/commands/list.js.map +0 -1
  951. package/dist/commands/migrate-openspec.js +0 -950
  952. package/dist/commands/migrate-openspec.js.map +0 -1
  953. package/dist/commands/new.js +0 -413
  954. package/dist/commands/new.js.map +0 -1
  955. package/dist/commands/rebase.js +0 -356
  956. package/dist/commands/rebase.js.map +0 -1
  957. package/dist/commands/show.js.map +0 -1
  958. package/dist/commands/status.js +0 -262
  959. package/dist/commands/status.js.map +0 -1
  960. package/dist/commands/unarchive.js.map +0 -1
  961. package/dist/commands/validate.js +0 -1773
  962. package/dist/commands/validate.js.map +0 -1
  963. package/dist/commands/verify.js +0 -775
  964. package/dist/commands/verify.js.map +0 -1
  965. package/dist/commands/vouch.js +0 -421
  966. package/dist/commands/vouch.js.map +0 -1
  967. package/dist/core/agent.js +0 -2173
  968. package/dist/core/agent.js.map +0 -1
  969. package/dist/core/agents-stamp.js.map +0 -1
  970. package/dist/core/arch.js +0 -130
  971. package/dist/core/arch.js.map +0 -1
  972. package/dist/core/asyncapi.js.map +0 -1
  973. package/dist/core/brief.js +0 -755
  974. package/dist/core/brief.js.map +0 -1
  975. package/dist/core/coherence.js +0 -577
  976. package/dist/core/coherence.js.map +0 -1
  977. package/dist/core/concurrency.js.map +0 -1
  978. package/dist/core/config.js.map +0 -1
  979. package/dist/core/delta.js +0 -476
  980. package/dist/core/delta.js.map +0 -1
  981. package/dist/core/dependencies.js +0 -356
  982. package/dist/core/dependencies.js.map +0 -1
  983. package/dist/core/doctor.js +0 -596
  984. package/dist/core/doctor.js.map +0 -1
  985. package/dist/core/document-bytes.js.map +0 -1
  986. package/dist/core/explore.js.map +0 -1
  987. package/dist/core/frontmatter.js.map +0 -1
  988. package/dist/core/gherkin.js +0 -463
  989. package/dist/core/gherkin.js.map +0 -1
  990. package/dist/core/health.js +0 -67
  991. package/dist/core/health.js.map +0 -1
  992. package/dist/core/ids.js +0 -122
  993. package/dist/core/ids.js.map +0 -1
  994. package/dist/core/issue.js +0 -9
  995. package/dist/core/issue.js.map +0 -1
  996. package/dist/core/json.js +0 -74
  997. package/dist/core/json.js.map +0 -1
  998. package/dist/core/likec4.js +0 -489
  999. package/dist/core/likec4.js.map +0 -1
  1000. package/dist/core/maturity.js +0 -66
  1001. package/dist/core/maturity.js.map +0 -1
  1002. package/dist/core/openapi-merge.js +0 -552
  1003. package/dist/core/openapi-merge.js.map +0 -1
  1004. package/dist/core/openapi.js.map +0 -1
  1005. package/dist/core/openspec-inventory.js +0 -1440
  1006. package/dist/core/openspec-inventory.js.map +0 -1
  1007. package/dist/core/path-safety.js.map +0 -1
  1008. package/dist/core/provenance.js +0 -787
  1009. package/dist/core/provenance.js.map +0 -1
  1010. package/dist/core/records.js.map +0 -1
  1011. package/dist/core/repo.js +0 -438
  1012. package/dist/core/repo.js.map +0 -1
  1013. package/dist/core/report.js.map +0 -1
  1014. package/dist/core/spec.js +0 -505
  1015. package/dist/core/spec.js.map +0 -1
  1016. package/dist/core/staging.js +0 -890
  1017. package/dist/core/staging.js.map +0 -1
  1018. package/dist/core/status.js +0 -1132
  1019. package/dist/core/status.js.map +0 -1
  1020. package/dist/core/steps.js +0 -72
  1021. package/dist/core/steps.js.map +0 -1
  1022. package/dist/core/verify.js +0 -807
  1023. package/dist/core/verify.js.map +0 -1
  1024. package/dist/core/version.js.map +0 -1
  1025. /package/dist/core/{concurrency.js → kernel/concurrency.js} +0 -0
  1026. /package/dist/core/{records.js → kernel/records.js} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"declared.js","sourceRoot":"","sources":["../../../src/core/coherence/declared.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * What a feature's own delta DECLARES, per service, indexed once.\n *\n * Seven indexes over the same four files (the delta spec.md, arch.spec.md,\n * openapi.yaml, and the living contract they are graded against), built in one\n * walk because every check downstream joins on the service id and would\n * otherwise re-read the delta per question. The distinctions here are the ones\n * the checks cannot make for themselves: an operation a REMOVED requirement\n * governs is being retired, so it neither claims the contract nor governs\n * anything after the merge; a removal marker that names an id also defined\n * elsewhere in the delta is a RELOCATION, not a retirement; and a marker with\n * no `operationId` at all is a shape only this walk can see. The capability\n * gate rides the same loop: both delta spec documents are graded against the\n * fleet vocabulary here, because coherence.ts and this package's file count\n * are both at their limits and the walk already holds the parsed documents.\n */\nimport { existsSync } from \"node:fs\";\nimport { NotUtf8DocumentError } from \"../kernel/document-bytes.js\";\nimport { readFile } from \"node:fs/promises\";\nimport { type PathableService } from \"../kernel/ids/service.js\";\nimport type { Issue } from \"../vocabulary/issue.js\";\nimport { featureSpecPaths } from \"../repo/paths.js\";\nimport { locateServicePaths } from \"../repo/service-target.js\";\nimport { parseRequirements } from \"../document/parse.js\";\nimport { readCapabilityVocabulary } from \"../capabilities/capabilities.js\";\nimport { capabilityRequirementIndex } from \"../capabilities/findings.js\";\nimport { withFeatureCapabilities, withFeatureRequirements } from \"../capabilities/delta/overlay.js\";\nimport { featureCapabilityDeltas } from \"../capabilities/delta/tree.js\";\nimport { realizesUnknownIssues } from \"../capabilities/realizes/findings.js\";\nimport type { CapabilityRequirementIndex } from \"../capabilities/realizes/join.js\";\nimport { capabilityUnknownIssues } from \"../capabilities/findings.js\";\nimport type { Requirement } from \"../document/spec.js\";\nimport { openapiBaselineIssues } from \"../openapi/baseline/gate.js\";\nimport { readOpenapi } from \"../openapi/doc.js\";\nimport type { FleetContext } from \"../fleet-context.js\";\nimport type { DocsDir, FeatureDir } from \"../kernel/ids/dirs.js\";\n\n/** Everything one feature's delta says about its own services. */\nexport interface Declared {\n /** Per service: the operations its non-REMOVED requirements govern. */\n reqOps: Map<PathableService, string[]>;\n /** Per service: the operations its REMOVED requirements governed. */\n removedReqOps: Map<string, Set<string>>;\n /** Per service: operations this feature genuinely retires (markers minus relocations). */\n removingOps: Map<string, Set<string>>;\n /** Per service: every id a removal marker names, relocations included. */\n allMarkerIds: Map<string, Set<string>>;\n /** Per service: does the feature contract carry a marker with no operationId? */\n anonymousMarkers: Map<string, boolean>;\n /** The operationIds genuinely NEW to their service across the whole feature. */\n featureApiOps: Set<string>;\n /**\n * Services whose FEATURE openapi.yaml exists but does not parse. Every check\n * that joins on the feature contract must suspend itself for these — an\n * unreadable document yields the same empty op set as an absent one, and\n * grading against that emptiness produced false errors pointing everywhere\n * but at the broken file.\n */\n unreadableApis: Set<string>;\n}\n\n/** The three facts this walk needs about the feature it is reading. */\nexport interface DeltaScope {\n docsDir: DocsDir;\n featureDir: FeatureDir;\n featureId: string;\n}\n\nexport async function declaredByService(\n scope: DeltaScope,\n svcNames: PathableService[],\n issues: Issue[],\n context?: FleetContext,\n): Promise<Declared> {\n const { docsDir, featureDir, featureId } = scope;\n const reqOps = new Map<PathableService, string[]>();\n const removedReqOps = new Map<string, Set<string>>();\n /** Per service: operations this feature genuinely retires (markers minus relocations). */\n const removingOps = new Map<string, Set<string>>();\n /** Per service: every id a removal marker names, relocations included. */\n const allMarkerIds = new Map<string, Set<string>>();\n /** Per service: does the feature contract carry a marker with no operationId? */\n const anonymousMarkers = new Map<string, boolean>();\n const featureApiOps = new Set<string>();\n const unreadableApis = new Set<string>();\n // The capability gate's vocabulary, once per call. Absent or invalid stays\n // SILENT here — capability.invalid is validate --all's one finding about a\n // broken file, and an absent file means the fleet never opted in — so with\n // either, nothing new gates archive (the roadmap's own trade; the\n // /loam-check row tells agents to fix the YAML first). `grading` is that\n // silence hoisted into a guard, so a silent axis also skips the reads that\n // exist only to feed it.\n //\n // The vocabulary is the one this feature's MERGE would leave behind, not\n // the one on disk: a feature that adds a capability requirement in its own\n // capability delta and `Realizes:` it from its own service delta is the\n // flow the whole axis exists for, and graded against the living tree alone\n // it is refused with `capability.realizes-unknown` — an error, gating\n // archive, for a target the same archive creates. `capabilities/delta/\n // overlay.ts` states the whole judgement. One `existsSync` for a feature\n // that carries no capability delta, which is every feature in a fleet that\n // has not adopted the axis.\n const capabilityDeltas =\n context === undefined ? await featureCapabilityDeltas(featureDir) : await context.featureCapabilityDeltas(featureDir);\n const capabilityVocab = withFeatureCapabilities(\n context === undefined ? await readCapabilityVocabulary(docsDir) : await context.capabilities(docsDir),\n capabilityDeltas.docs.map((d) => d.id),\n );\n const grading = capabilityVocab.present && capabilityVocab.invalid === undefined;\n // The `Realizes:` index, built at most ONCE per feature and only if some\n // delta document actually reaches the grading branch. Lazy rather than\n // eager because it reads every capability document in the fleet, and a\n // feature whose deltas carry no requirement file at all must not pay for\n // that — the same \"a silent axis skips the reads that feed it\" rule\n // `grading` above states, one level deeper.\n let pendingIndex: Promise<CapabilityRequirementIndex> | null = null;\n const capabilityReqs = (): Promise<CapabilityRequirementIndex> => {\n const read = context === undefined\n ? async (p: string): Promise<Requirement[]> => parseRequirements(await readFile(p, \"utf8\"))\n : (p: string): Promise<Requirement[]> => context.readRequirements(p);\n // The living index first, then widened by what this feature's capability\n // deltas ADD or MODIFY. Both halves are inside the lazy thunk, so a\n // feature whose deltas carry no requirement file at all pays for neither.\n pendingIndex ??= capabilityRequirementIndex(capabilityVocab, read).then(async (index) =>\n withFeatureRequirements(\n index,\n await Promise.all(capabilityDeltas.docs.map(async (d) => ({ id: d.id, reqs: await read(d.spec) }))),\n ),\n );\n return pendingIndex;\n };\n for (const svc of svcNames) {\n const paths = featureSpecPaths(featureDir, svc);\n if (existsSync(paths.spec)) {\n const reqs = context === undefined\n ? parseRequirements(await readFile(paths.spec, \"utf8\"))\n : await context.readRequirements(paths.spec);\n // REMOVED requirements are being retired along with their operations — their\n // ops neither claim the contract (E1) nor govern anything after the merge.\n reqOps.set(svc, reqs.filter((r) => r.kind !== \"REMOVED\").flatMap((r) => r.operations));\n removedReqOps.set(\n svc,\n new Set(reqs.filter((r) => r.kind === \"REMOVED\").flatMap((r) => r.operations)),\n );\n if (grading) {\n const target = { where: `${svc}: spec.md`, subject: svc };\n issues.push(...capabilityUnknownIssues(reqs, target, capabilityVocab));\n issues.push(...realizesUnknownIssues(reqs, target, await capabilityReqs()));\n }\n }\n // The delta arch.spec.md carries the same grammar and merges the same\n // way, so an undeclared capability in it gates identically. Nothing else\n // in this walk needs the arch delta, so the read itself sits behind\n // `grading` — and it is NOT always cached: `validate --feature` passes a\n // context, but archive's plan gate (commands/archive/plan/gate.ts) calls\n // featureCoherence without one, so this parse is paid fresh there.\n if (grading && existsSync(paths.archSpec)) {\n const archReqs = context === undefined\n ? parseRequirements(await readFile(paths.archSpec, \"utf8\"))\n : await context.readRequirements(paths.archSpec);\n const archTarget = { where: `${svc}: arch.spec.md`, subject: svc };\n issues.push(...capabilityUnknownIssues(archReqs, archTarget, capabilityVocab));\n issues.push(...realizesUnknownIssues(archReqs, archTarget, await capabilityReqs()));\n }\n // Only operations genuinely NEW to this service count as feature-added: authors\n // restate the full living API in the delta file (it is a complete document, not a patch).\n const featDoc = await readOpenapi(paths.openapi, context);\n // A feature contract that EXISTS but does not read is a broken document,\n // not an empty one — the living-side `openapi.invalid` discipline\n // (validate/service/api.ts), applied to the delta. Before this check,\n // `validate --feature` said nothing about the file at all: the empty\n // parse silently skipped every baseline pin and removal marker in it,\n // and E1 graded requirements against a contract that was never read.\n // The rest of this service's contract-axis checks are suspended — every\n // one of them would be an opinion about a document nobody could open.\n if (featDoc.unreadable) {\n unreadableApis.add(svc);\n issues.push({\n severity: \"error\",\n code: \"openapi.invalid\",\n subject: svc,\n message: `${svc}: this feature's openapi.yaml does not parse${featDoc.error === undefined ? \"\" : ` (${featDoc.error})`} — the contract axis is unchecked and the merge would have nothing true to write. Fix the YAML first.`,\n });\n continue;\n }\n const featOps = featDoc.ops;\n const removals = featOps.filter((op) => op.remove);\n // A relocation — same operationId, removal marker on the old slot, upsert\n // on the new one — retires nothing. Every rule that asks \"is this operation\n // going away\" must therefore ask the NET set (markers this feature does not\n // redefine), while \"did the author write a marker at all\" asks the raw one.\n // Conflating them made moving an endpoint fail three checks at once for a\n // change that removes nothing.\n const redefined = new Set(featOps.filter((op) => !op.remove).map((op) => op.id));\n const markerIds = new Set(removals.map((op) => op.id));\n const netRemoved = new Set([...markerIds].filter((id) => !redefined.has(id)));\n removingOps.set(svc, netRemoved);\n allMarkerIds.set(svc, markerIds);\n anonymousMarkers.set(svc, featDoc.anonymousRemovals.length > 0);\n\n // A marker with no operationId names a slot but no operation. Every\n // id-keyed check is blind to it, so it used to travel all the way into the\n // living contract as a literal `x-loam-remove: true` — the one feature-only\n // key that must never be published.\n for (const marker of featDoc.anonymousRemovals) {\n issues.push({\n severity: \"error\",\n code: \"openapi.remove-marker-anonymous\",\n subject: svc,\n message: `${svc}: ${marker.method} ${marker.path} carries x-loam-remove: true but declares no operationId — loam cannot tell which operation it retires; name the operation the living contract has at that slot`,\n });\n }\n\n const livingDoc = await readOpenapi((await locateServicePaths(docsDir, svc, context)).openapi, context);\n const livingOps = livingDoc.ops;\n for (const id of livingDoc.duplicateIds) {\n const slots = livingOps.filter((op) => op.id === id).map((op) => `${op.method} ${op.path}`);\n issues.push({\n severity: \"warn\",\n code: \"openapi.duplicate-operationid\",\n subject: svc,\n message: `${svc}: the living OpenAPI defines operationId '${id}' at ${slots.join(\" and \")} — every join on the id (a requirement's Operations: line, an edge's metadata { op }, a removal marker) picks one of those slots arbitrarily`,\n });\n }\n // The baseline axis — operation pins, path-item keys and components —\n // graded in its own package (openapi/baseline/gate.ts), slot-keyed\n // exactly as the merge writes. Texts come through the context's memoized\n // read when there is one, mirroring the readRequirements pattern above;\n // the gate itself never touches the filesystem.\n if (existsSync(paths.openapi)) {\n const livingOpenapiPath = (await locateServicePaths(docsDir, svc, context)).openapi;\n // `context.readText` DECODES and THROWS on non-UTF-8 bytes, where the\n // no-context `readFile` substitutes U+FFFD and lets `readOpenapi`\n // flag the document unreadable. Uncaught, one service's UTF-16 living\n // contract took down the whole feature target under validate's\n // context while archive's no-context path sailed past — the exact\n // context/no-context divergence doc.ts documents as paid for once.\n // Either text failing to decode gets the same answer the gate gives\n // an unreadable parse: that side's surface checks are skipped.\n const readOr = async (p: string): Promise<string | undefined> => {\n try {\n return context === undefined ? await readFile(p, \"utf8\") : await context.readText(p);\n } catch (err) {\n if (err instanceof NotUtf8DocumentError) return undefined;\n throw err;\n }\n };\n const featureText = await readOr(paths.openapi);\n const livingText = !existsSync(livingOpenapiPath) ? undefined : await readOr(livingOpenapiPath);\n if (featureText !== undefined) {\n issues.push(\n ...openapiBaselineIssues({ featDoc, livingDoc, featureText, livingText, service: svc, featureId }),\n );\n }\n }\n\n if (featOps.length > 0) {\n const living = new Set(livingOps.filter((op) => !op.remove).map((op) => op.id));\n for (const op of featOps) {\n if (!op.remove && !living.has(op.id)) featureApiOps.add(op.id);\n }\n\n // Removal is exact: the feature names both an operationId and the\n // path+method slot it expects to delete. That catches stale deltas whose\n // target moved or was already retired before the archive planner runs.\n const justified = removedReqOps.get(svc) ?? new Set<string>();\n for (const marker of removals) {\n const target = livingOps.find((op) => op.path === marker.path && op.method === marker.method);\n if (target === undefined) {\n issues.push({\n severity: \"error\",\n code: \"openapi.remove-target-missing\",\n subject: svc,\n message: `${svc}: removal marker for '${marker.id}' addresses ${marker.method} ${marker.path}, but no living operation exists there`,\n });\n } else if (target.id !== marker.id) {\n issues.push({\n severity: \"error\",\n code: \"openapi.remove-target-mismatch\",\n subject: svc,\n message: `${svc}: removal marker names '${marker.id}' at ${marker.method} ${marker.path}, but the living operation there is '${target.id}'`,\n });\n }\n // A relocation needs no REMOVED requirement: the requirement governing\n // the operation stays, the operation only changes address.\n if (!netRemoved.has(marker.id)) continue;\n if (!justified.has(marker.id)) {\n issues.push({\n severity: \"error\",\n code: \"openapi.remove-marker-unjustified\",\n subject: svc,\n message: `${svc}: removal marker for '${marker.id}' is not governed by a REMOVED requirement's Operations: line`,\n });\n }\n }\n }\n }\n for (const [svc, required] of removedReqOps) {\n // The markers live in the unreadable file — \"no matching marker\" would\n // be a claim about a document nobody could open.\n if (unreadableApis.has(svc)) continue;\n const marked = allMarkerIds.get(svc) ?? new Set<string>();\n for (const op of required) {\n if (marked.has(op)) continue;\n // Distinguish \"no marker at all\" from \"a marker is there but loam cannot\n // read which operation it names\" — the first asks the author to write the\n // marker, the second to write the operationId, and telling somebody who\n // already wrote the marker that there is none sends them looking for a\n // file they are staring at.\n issues.push({\n severity: \"error\",\n code: \"openapi.remove-marker-missing\",\n subject: svc,\n message: anonymousMarkers.get(svc) === true\n ? `${svc}: REMOVED requirement governs '${op}', and its feature openapi.yaml carries an x-loam-remove: true marker with no operationId — name '${op}' on that marker`\n : `${svc}: REMOVED requirement governs '${op}', but its feature openapi.yaml has no matching x-loam-remove: true marker`,\n });\n }\n }\n return { reqOps, removedReqOps, removingOps, allMarkerIds, anonymousMarkers, featureApiOps, unreadableApis };\n}\n"]}
@@ -0,0 +1,206 @@
1
+ /**
2
+ * What a feature's asyncapi deltas DECLARE, per service — ../declared.ts's
3
+ * mirror on the event axis, indexed in one walk and graded as it goes.
4
+ *
5
+ * The walk owns every check that reads ONE service's pair of contracts: the
6
+ * feature document's readability (`asyncapi.invalid` suspends the rest, the
7
+ * unreadableApis discipline), the baseline pins and removal-marker exactness
8
+ * (./grades.ts, slot-keyed), the removal↔REMOVED-requirement justification
9
+ * join, and the merge simulation (./merged.ts) the cross-axis checks grade
10
+ * against. What it cannot answer alone — who still consumes a message, what
11
+ * other features are adding — lives in ./lookups.ts, and the cross-axis
12
+ * grading of edges and requirement lines in ./events.ts.
13
+ *
14
+ * Slot identity is core/asyncapi/digest.ts's: three sections, and an inline
15
+ * channel message is channel-slot interior — a marker NESTED on one makes
16
+ * the channel an EDIT against the channel's pin, never a message removal,
17
+ * so nothing here reads it as one. A CHANNEL-slot removal, by contrast,
18
+ * takes its living inline interior with it (SCHEMA.md's decision), so the
19
+ * justification join counts those inline names as marked: without that, a
20
+ * message declared only inline was a deadlock — the sanctioned channel
21
+ * marker graded remove-marker-missing, and the components.messages marker
22
+ * the error suggested graded remove-target-missing.
23
+ */
24
+ import { existsSync } from "node:fs";
25
+ import { readFile } from "node:fs/promises";
26
+ import { parse } from "yaml";
27
+ import { NotUtf8DocumentError } from "../../kernel/document-bytes.js";
28
+ import {} from "../../kernel/ids/service.js";
29
+ import { featureSpecPaths, SPEC_AXES } from "../../repo/paths.js";
30
+ import { locateServicePaths } from "../../repo/service-target.js";
31
+ import { parseRequirements } from "../../document/parse.js";
32
+ import { asyncapiSlots } from "../../asyncapi/digest.js";
33
+ import { readAsyncapi } from "../../asyncapi/read.js";
34
+ import { gradeBaselines, gradeMarkers } from "./grades.js";
35
+ import { mergedAsyncapiDoc } from "./merged.js";
36
+ /**
37
+ * The delta's `Publishes:`/`Consumes:` lines for one service, split by
38
+ * requirement fate — read from BOTH spec files, because the outbox
39
+ * requirement in arch.spec.md is the canonical home of an event line. A
40
+ * REMOVED requirement's lines justify removals; everything else's are
41
+ * claims ./events.ts grades against the contract.
42
+ */
43
+ export async function deltaEventLines(scope, service, context) {
44
+ const removed = new Set();
45
+ const links = [];
46
+ for (const axis of SPEC_AXES) {
47
+ const p = featureSpecPaths(scope.featureDir, service)[axis.key];
48
+ if (!existsSync(p))
49
+ continue;
50
+ const reqs = context === undefined
51
+ ? parseRequirements(await readFile(p, "utf8"))
52
+ : await context.readRequirements(p);
53
+ for (const r of reqs) {
54
+ if (r.kind === "REMOVED") {
55
+ for (const m of [...r.publishes, ...r.consumes])
56
+ removed.add(m);
57
+ continue;
58
+ }
59
+ links.push(...r.publishes.map((m) => ({ direction: "publishes", message: m, requirement: r.name })));
60
+ links.push(...r.consumes.map((m) => ({ direction: "consumes", message: m, requirement: r.name })));
61
+ }
62
+ }
63
+ return { removed, links };
64
+ }
65
+ /** Read a document's text, answering undefined for bytes that do not decode — ../declared.ts's guard. */
66
+ async function readOr(p, context) {
67
+ try {
68
+ return context === undefined ? await readFile(p, "utf8") : await context.readText(p);
69
+ }
70
+ catch (err) {
71
+ if (err instanceof NotUtf8DocumentError)
72
+ return undefined;
73
+ throw err;
74
+ }
75
+ }
76
+ export async function declaredEvents(scope, svcNames, issues, context) {
77
+ const { docsDir, featureDir, featureId } = scope;
78
+ const featureDocs = new Map();
79
+ const mergedDocs = new Map();
80
+ const netRemoved = new Map();
81
+ const stoppedSending = new Map();
82
+ const links = new Map();
83
+ const unreadable = new Set();
84
+ for (const svc of svcNames) {
85
+ const featPath = featureSpecPaths(featureDir, svc).asyncapi;
86
+ const { removed: justifiedMsgs, links: svcLinks } = await deltaEventLines(scope, svc, context);
87
+ links.set(svc, svcLinks);
88
+ // The living contract is read only where a question will be asked of it:
89
+ // no event delta and no REMOVED line means no marker debt and no slot to
90
+ // grade. The unguarded read was an eager parse per touched service —
91
+ // paid on every archive, whose gate runs without a FleetContext — for an
92
+ // answer nothing consumed.
93
+ if (!existsSync(featPath) && justifiedMsgs.size === 0)
94
+ continue;
95
+ const livingPath = (await locateServicePaths(docsDir, svc, context)).asyncapi;
96
+ const livingDoc = await readAsyncapi(livingPath, context);
97
+ if (!existsSync(featPath)) {
98
+ // No event delta — but a REMOVED requirement may still be walking away
99
+ // from a message the LIVING contract declares, and the marker that
100
+ // retires the declaration has to ride in the same feature. Only
101
+ // messages the living contract actually carries are owed one: an event
102
+ // contract is optional, and a fleet retiring a requirement over a
103
+ // message no contract declares owes no file.
104
+ for (const m of justifiedMsgs) {
105
+ if (livingDoc.unreadable || !livingDoc.messages.some((msg) => msg.name === m))
106
+ continue;
107
+ issues.push({
108
+ severity: "error",
109
+ code: "asyncapi.remove-marker-missing",
110
+ subject: svc,
111
+ message: `${svc}: a REMOVED requirement's Publishes:/Consumes: line names '${m}', which the living asyncapi.yaml still declares, but this feature carries no matching x-loam-remove: true marker in specs/${svc}/asyncapi.yaml`,
112
+ });
113
+ }
114
+ continue;
115
+ }
116
+ const featDoc = await readAsyncapi(featPath, context);
117
+ // A feature contract that EXISTS but does not read is a broken document,
118
+ // not an empty one — openapi.invalid's discipline (../declared.ts),
119
+ // applied to the event axis: the rest of this service's event checks are
120
+ // suspended, because every one of them would be an opinion about a
121
+ // document nobody could open.
122
+ if (featDoc.unreadable) {
123
+ unreadable.add(svc);
124
+ issues.push({
125
+ severity: "error",
126
+ code: "asyncapi.invalid",
127
+ subject: svc,
128
+ message: `${svc}: this feature's asyncapi.yaml does not parse${featDoc.error === undefined ? "" : ` (${featDoc.error})`} — the event axis is unchecked and the merge would have nothing true to write. Fix the YAML first.`,
129
+ });
130
+ continue;
131
+ }
132
+ featureDocs.set(svc, featDoc);
133
+ const featText = await readOr(featPath, context);
134
+ // Parsed ONCE and kept: the slot walk and the surface half of the baseline
135
+ // grade read the same resolved tree, and a second `parse` of the same
136
+ // bytes is a second chance for the two halves to disagree about what the
137
+ // delta declares.
138
+ const featPlain = featText === undefined ? {} : parse(featText);
139
+ const featSlots = asyncapiSlots(featPlain);
140
+ // The living side of every slot judgement. Absent is a real answer —
141
+ // everything the delta spells is new, and a baseline only means
142
+ // something for a slot that already exists. Unreadable is NOT an
143
+ // answer: grading pins or markers against an empty parse would call
144
+ // every restatement new and every marker stale, so both checks stand
145
+ // down and the (later) merge refuses the unreadable side by name.
146
+ const livingText = !existsSync(livingPath) || livingDoc.unreadable ? undefined : await readOr(livingPath, context);
147
+ const livingPlain = livingText === undefined ? {} : parse(livingText);
148
+ const livingSlots = new Map(asyncapiSlots(livingPlain).map((s) => [`${s.section}\0${s.key}`, s]));
149
+ if (livingText !== undefined) {
150
+ gradeBaselines({ featSlots, livingSlots, featPlain, livingPlain, svc, featureId }, issues);
151
+ gradeMarkers({ featDoc, livingDoc, featSlots, livingSlots }, svc, issues);
152
+ if (featText !== undefined) {
153
+ const merged = mergedAsyncapiDoc({ livingText, livingDoc, featureText: featText, service: svc });
154
+ if (merged !== undefined) {
155
+ mergedDocs.set(svc, merged);
156
+ stoppedSending.set(svc, livingDoc.sent.filter((m) => !merged.sent.includes(m)));
157
+ }
158
+ }
159
+ }
160
+ // A relocation — same message name, marker on the old key, declaration
161
+ // at a new one — retires nothing. "Is this message going away" asks the
162
+ // NET set; "did the author write a marker" asks the raw one,
163
+ // ../declared.ts's distinction verbatim. Two raw sets, because the two
164
+ // marker shapes carry different debts: a message-slot marker must be
165
+ // justified by a REMOVED requirement, while a channel-slot removal needs
166
+ // exactness only (requirements join on message names, never channel
167
+ // keys — SCHEMA.md) and its living inline interior leaves with it.
168
+ const markerNames = new Set(featDoc.messages.filter((m) => m.remove === true && m.slot.startsWith("components.messages.")).map((m) => m.name));
169
+ const channelRemovals = featSlots.filter((s) => s.section === "channels" && s.remove).map((s) => s.key);
170
+ const inlineRetired = new Set(livingDoc.messages
171
+ .filter((m) => channelRemovals.some((ck) => m.slot.startsWith(`channels.${ck}.messages.`)))
172
+ .map((m) => m.name));
173
+ const redeclared = new Set(featDoc.messages.filter((m) => m.remove !== true).map((m) => m.name));
174
+ const net = new Set([...markerNames, ...inlineRetired].filter((name) => !redeclared.has(name)));
175
+ netRemoved.set(svc, net);
176
+ for (const name of markerNames) {
177
+ if (redeclared.has(name) || justifiedMsgs.has(name))
178
+ continue;
179
+ issues.push({
180
+ severity: "error",
181
+ code: "asyncapi.remove-marker-unjustified",
182
+ subject: svc,
183
+ message: `${svc}: removal marker for message '${name}' is not justified by a REMOVED requirement's Publishes:/Consumes: line`,
184
+ });
185
+ }
186
+ for (const m of justifiedMsgs) {
187
+ // Owed only while the living contract still declares the message —
188
+ // and satisfied by ANY marker taking it out, relocation included: a
189
+ // message-slot marker naming it, or a channel-slot removal whose
190
+ // living inline interior declares it (the SCHEMA-sanctioned way to
191
+ // retire an inline declaration).
192
+ if (markerNames.has(m) || inlineRetired.has(m))
193
+ continue;
194
+ if (livingDoc.unreadable || !livingDoc.messages.some((msg) => msg.name === m))
195
+ continue;
196
+ issues.push({
197
+ severity: "error",
198
+ code: "asyncapi.remove-marker-missing",
199
+ subject: svc,
200
+ message: `${svc}: a REMOVED requirement's Publishes:/Consumes: line names '${m}', which the living asyncapi.yaml still declares, but this feature's asyncapi.yaml has no matching x-loam-remove: true marker`,
201
+ });
202
+ }
203
+ }
204
+ return { featureDocs, mergedDocs, netRemoved, stoppedSending, links, unreadable };
205
+ }
206
+ //# sourceMappingURL=declared.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"declared.js","sourceRoot":"","sources":["../../../../src/core/coherence/events/declared.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * What a feature's asyncapi deltas DECLARE, per service — ../declared.ts's\n * mirror on the event axis, indexed in one walk and graded as it goes.\n *\n * The walk owns every check that reads ONE service's pair of contracts: the\n * feature document's readability (`asyncapi.invalid` suspends the rest, the\n * unreadableApis discipline), the baseline pins and removal-marker exactness\n * (./grades.ts, slot-keyed), the removal↔REMOVED-requirement justification\n * join, and the merge simulation (./merged.ts) the cross-axis checks grade\n * against. What it cannot answer alone — who still consumes a message, what\n * other features are adding — lives in ./lookups.ts, and the cross-axis\n * grading of edges and requirement lines in ./events.ts.\n *\n * Slot identity is core/asyncapi/digest.ts's: three sections, and an inline\n * channel message is channel-slot interior — a marker NESTED on one makes\n * the channel an EDIT against the channel's pin, never a message removal,\n * so nothing here reads it as one. A CHANNEL-slot removal, by contrast,\n * takes its living inline interior with it (SCHEMA.md's decision), so the\n * justification join counts those inline names as marked: without that, a\n * message declared only inline was a deadlock — the sanctioned channel\n * marker graded remove-marker-missing, and the components.messages marker\n * the error suggested graded remove-target-missing.\n */\nimport { existsSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport { parse } from \"yaml\";\nimport { NotUtf8DocumentError } from \"../../kernel/document-bytes.js\";\nimport { type PathableService } from \"../../kernel/ids/service.js\";\nimport type { Issue } from \"../../vocabulary/issue.js\";\nimport { featureSpecPaths, SPEC_AXES } from \"../../repo/paths.js\";\nimport { locateServicePaths } from \"../../repo/service-target.js\";\nimport { parseRequirements } from \"../../document/parse.js\";\nimport { asyncapiSlots, type AsyncapiSlot } from \"../../asyncapi/digest.js\";\nimport { readAsyncapi } from \"../../asyncapi/read.js\";\nimport type { AsyncapiDoc } from \"../../asyncapi/model.js\";\nimport type { FleetContext } from \"../../fleet-context.js\";\nimport type { DocsDir, FeatureDir } from \"../../kernel/ids/dirs.js\";\nimport { gradeBaselines, gradeMarkers } from \"./grades.js\";\nimport { mergedAsyncapiDoc } from \"./merged.js\";\n\n/** The three facts this walk needs about the feature it is reading. */\nexport interface EventDeltaScope {\n docsDir: DocsDir;\n featureDir: FeatureDir;\n featureId: string;\n}\n\n/** One delta requirement's `Publishes:`/`Consumes:` claim — what ./events.ts grades against the contract. */\nexport interface EventLink {\n direction: \"publishes\" | \"consumes\";\n message: string;\n requirement: string;\n}\n\n/** Everything one feature's asyncapi deltas say about their own services. */\nexport interface DeclaredEvents {\n /** Per touched service: the feature delta's parse — present only where the file exists and reads. */\n featureDocs: Map<PathableService, AsyncapiDoc>;\n /**\n * Per touched service: the living contract as the MERGE would leave it\n * (./merged.ts) — present where a feature delta sits over a readable\n * living contract and the simulation had an answer. What `declares()` and\n * the consumer gate's wire half read, so the gate grades the post-archive\n * contract rather than the union of two documents one of which is leaving.\n */\n mergedDocs: Map<PathableService, AsyncapiDoc>;\n /**\n * Per service: message names this feature genuinely retires — message-slot\n * markers plus a removed channel's living INLINE interior (SCHEMA.md:\n * retiring a whole channel retires its inline messages with it), minus\n * redeclarations.\n */\n netRemoved: Map<string, Set<string>>;\n /**\n * Per service: messages the living contract SENDS that the merged one\n * would not — a channel or operation removal, or an edit, stopping\n * production while the declaration may well survive. The wire half of the\n * consumer question (./events.ts); empty where no simulation ran.\n */\n stoppedSending: Map<string, string[]>;\n /**\n * Per service in the walk: the delta's non-REMOVED `Publishes:`/`Consumes:`\n * lines — read once HERE and graded in ./events.ts, the indexed-in-one-walk\n * rule this record exists for (the same lines used to be re-read and\n * re-parsed per question on the context-less archive-gate path).\n */\n links: Map<PathableService, EventLink[]>;\n /** Services whose FEATURE asyncapi.yaml exists but does not parse — every event check suspends for them. */\n unreadable: Set<string>;\n}\n\n/**\n * The delta's `Publishes:`/`Consumes:` lines for one service, split by\n * requirement fate — read from BOTH spec files, because the outbox\n * requirement in arch.spec.md is the canonical home of an event line. A\n * REMOVED requirement's lines justify removals; everything else's are\n * claims ./events.ts grades against the contract.\n */\nexport async function deltaEventLines(\n scope: EventDeltaScope,\n service: PathableService,\n context?: FleetContext,\n): Promise<{ removed: Set<string>; links: EventLink[] }> {\n const removed = new Set<string>();\n const links: EventLink[] = [];\n for (const axis of SPEC_AXES) {\n const p = featureSpecPaths(scope.featureDir, service)[axis.key];\n if (!existsSync(p)) continue;\n const reqs = context === undefined\n ? parseRequirements(await readFile(p, \"utf8\"))\n : await context.readRequirements(p);\n for (const r of reqs) {\n if (r.kind === \"REMOVED\") {\n for (const m of [...r.publishes, ...r.consumes]) removed.add(m);\n continue;\n }\n links.push(...r.publishes.map((m) => ({ direction: \"publishes\" as const, message: m, requirement: r.name })));\n links.push(...r.consumes.map((m) => ({ direction: \"consumes\" as const, message: m, requirement: r.name })));\n }\n }\n return { removed, links };\n}\n\n/** Read a document's text, answering undefined for bytes that do not decode — ../declared.ts's guard. */\nasync function readOr(p: string, context?: FleetContext): Promise<string | undefined> {\n try {\n return context === undefined ? await readFile(p, \"utf8\") : await context.readText(p);\n } catch (err) {\n if (err instanceof NotUtf8DocumentError) return undefined;\n throw err;\n }\n}\n\nexport async function declaredEvents(\n scope: EventDeltaScope,\n svcNames: PathableService[],\n issues: Issue[],\n context?: FleetContext,\n): Promise<DeclaredEvents> {\n const { docsDir, featureDir, featureId } = scope;\n const featureDocs = new Map<PathableService, AsyncapiDoc>();\n const mergedDocs = new Map<PathableService, AsyncapiDoc>();\n const netRemoved = new Map<string, Set<string>>();\n const stoppedSending = new Map<string, string[]>();\n const links = new Map<PathableService, EventLink[]>();\n const unreadable = new Set<string>();\n for (const svc of svcNames) {\n const featPath = featureSpecPaths(featureDir, svc).asyncapi;\n const { removed: justifiedMsgs, links: svcLinks } = await deltaEventLines(scope, svc, context);\n links.set(svc, svcLinks);\n // The living contract is read only where a question will be asked of it:\n // no event delta and no REMOVED line means no marker debt and no slot to\n // grade. The unguarded read was an eager parse per touched service —\n // paid on every archive, whose gate runs without a FleetContext — for an\n // answer nothing consumed.\n if (!existsSync(featPath) && justifiedMsgs.size === 0) continue;\n const livingPath = (await locateServicePaths(docsDir, svc, context)).asyncapi;\n const livingDoc = await readAsyncapi(livingPath, context);\n if (!existsSync(featPath)) {\n // No event delta — but a REMOVED requirement may still be walking away\n // from a message the LIVING contract declares, and the marker that\n // retires the declaration has to ride in the same feature. Only\n // messages the living contract actually carries are owed one: an event\n // contract is optional, and a fleet retiring a requirement over a\n // message no contract declares owes no file.\n for (const m of justifiedMsgs) {\n if (livingDoc.unreadable || !livingDoc.messages.some((msg) => msg.name === m)) continue;\n issues.push({\n severity: \"error\",\n code: \"asyncapi.remove-marker-missing\",\n subject: svc,\n message: `${svc}: a REMOVED requirement's Publishes:/Consumes: line names '${m}', which the living asyncapi.yaml still declares, but this feature carries no matching x-loam-remove: true marker in specs/${svc}/asyncapi.yaml`,\n });\n }\n continue;\n }\n const featDoc = await readAsyncapi(featPath, context);\n // A feature contract that EXISTS but does not read is a broken document,\n // not an empty one — openapi.invalid's discipline (../declared.ts),\n // applied to the event axis: the rest of this service's event checks are\n // suspended, because every one of them would be an opinion about a\n // document nobody could open.\n if (featDoc.unreadable) {\n unreadable.add(svc);\n issues.push({\n severity: \"error\",\n code: \"asyncapi.invalid\",\n subject: svc,\n message: `${svc}: this feature's asyncapi.yaml does not parse${featDoc.error === undefined ? \"\" : ` (${featDoc.error})`} — the event axis is unchecked and the merge would have nothing true to write. Fix the YAML first.`,\n });\n continue;\n }\n featureDocs.set(svc, featDoc);\n\n const featText = await readOr(featPath, context);\n // Parsed ONCE and kept: the slot walk and the surface half of the baseline\n // grade read the same resolved tree, and a second `parse` of the same\n // bytes is a second chance for the two halves to disagree about what the\n // delta declares.\n const featPlain: unknown = featText === undefined ? {} : parse(featText);\n const featSlots = asyncapiSlots(featPlain);\n // The living side of every slot judgement. Absent is a real answer —\n // everything the delta spells is new, and a baseline only means\n // something for a slot that already exists. Unreadable is NOT an\n // answer: grading pins or markers against an empty parse would call\n // every restatement new and every marker stale, so both checks stand\n // down and the (later) merge refuses the unreadable side by name.\n const livingText = !existsSync(livingPath) || livingDoc.unreadable ? undefined : await readOr(livingPath, context);\n const livingPlain: unknown = livingText === undefined ? {} : parse(livingText);\n const livingSlots = new Map<string, AsyncapiSlot>(\n asyncapiSlots(livingPlain).map((s) => [`${s.section}\\0${s.key}`, s]),\n );\n\n if (livingText !== undefined) {\n gradeBaselines({ featSlots, livingSlots, featPlain, livingPlain, svc, featureId }, issues);\n gradeMarkers({ featDoc, livingDoc, featSlots, livingSlots }, svc, issues);\n if (featText !== undefined) {\n const merged = mergedAsyncapiDoc({ livingText, livingDoc, featureText: featText, service: svc });\n if (merged !== undefined) {\n mergedDocs.set(svc, merged);\n stoppedSending.set(svc, livingDoc.sent.filter((m) => !merged.sent.includes(m)));\n }\n }\n }\n\n // A relocation — same message name, marker on the old key, declaration\n // at a new one — retires nothing. \"Is this message going away\" asks the\n // NET set; \"did the author write a marker\" asks the raw one,\n // ../declared.ts's distinction verbatim. Two raw sets, because the two\n // marker shapes carry different debts: a message-slot marker must be\n // justified by a REMOVED requirement, while a channel-slot removal needs\n // exactness only (requirements join on message names, never channel\n // keys — SCHEMA.md) and its living inline interior leaves with it.\n const markerNames = new Set(\n featDoc.messages.filter((m) => m.remove === true && m.slot.startsWith(\"components.messages.\")).map((m) => m.name),\n );\n const channelRemovals = featSlots.filter((s) => s.section === \"channels\" && s.remove).map((s) => s.key);\n const inlineRetired = new Set(\n livingDoc.messages\n .filter((m) => channelRemovals.some((ck) => m.slot.startsWith(`channels.${ck}.messages.`)))\n .map((m) => m.name),\n );\n const redeclared = new Set(featDoc.messages.filter((m) => m.remove !== true).map((m) => m.name));\n const net = new Set([...markerNames, ...inlineRetired].filter((name) => !redeclared.has(name)));\n netRemoved.set(svc, net);\n\n for (const name of markerNames) {\n if (redeclared.has(name) || justifiedMsgs.has(name)) continue;\n issues.push({\n severity: \"error\",\n code: \"asyncapi.remove-marker-unjustified\",\n subject: svc,\n message: `${svc}: removal marker for message '${name}' is not justified by a REMOVED requirement's Publishes:/Consumes: line`,\n });\n }\n for (const m of justifiedMsgs) {\n // Owed only while the living contract still declares the message —\n // and satisfied by ANY marker taking it out, relocation included: a\n // message-slot marker naming it, or a channel-slot removal whose\n // living inline interior declares it (the SCHEMA-sanctioned way to\n // retire an inline declaration).\n if (markerNames.has(m) || inlineRetired.has(m)) continue;\n if (livingDoc.unreadable || !livingDoc.messages.some((msg) => msg.name === m)) continue;\n issues.push({\n severity: \"error\",\n code: \"asyncapi.remove-marker-missing\",\n subject: svc,\n message: `${svc}: a REMOVED requirement's Publishes:/Consumes: line names '${m}', which the living asyncapi.yaml still declares, but this feature's asyncapi.yaml has no matching x-loam-remove: true marker`,\n });\n }\n }\n return { featureDocs, mergedDocs, netRemoved, stoppedSending, links, unreadable };\n}\n"]}
@@ -0,0 +1,204 @@
1
+ /**
2
+ * The event axis of the feature gate: do the C4 delta's tagged edges, the
3
+ * requirement deltas' `Publishes:`/`Consumes:` lines, and the asyncapi
4
+ * contracts agree about what each service puts on the wire?
5
+ *
6
+ * The package's orchestrator, called once from featureCoherence with the
7
+ * delta facts it already holds (tagged relationships and the element
8
+ * resolver): ./declared.ts walks the feature's own contracts and grades
9
+ * what one service's pair of documents can settle; ./lookups.ts answers the
10
+ * fleet questions lazily; this module joins the three axes — the exact
11
+ * shape coherence.ts gives the operation join, on the message name.
12
+ *
13
+ * A package of its own rather than lines in coherence.ts because that file
14
+ * ran at its 300-line limit before the event axis existed; the seam is
15
+ * real, not cosmetic — everything here joins on a message name, nothing
16
+ * there does.
17
+ */
18
+ import {} from "../../c4/likec4.js";
19
+ import {} from "../../kernel/ids/service.js";
20
+ import { locateServicePaths } from "../../repo/service-target.js";
21
+ import { enumeratedServiceIndex } from "../../repo/service-target.js";
22
+ import { readAsyncapi } from "../../asyncapi/read.js";
23
+ import { declaredEvents } from "./declared.js";
24
+ import { eventLookups } from "./lookups.js";
25
+ export async function eventCoherence(request) {
26
+ const { scope, svcNames, taggedRels, svcOf, context } = request;
27
+ const issues = [];
28
+ const declared = await declaredEvents(scope, svcNames, issues, context);
29
+ const lookups = eventLookups({ docsDir: scope.docsDir, featureId: scope.featureId }, context);
30
+ // Retiring a message the fleet still consumes — openapi.remove-op-consumed's
31
+ // twin, and like it a question neither exactness nor justification asks:
32
+ // the merge deletes the declaration while the consumes edge and the other
33
+ // repo's requirement stay, so the next `validate --all` breaks on a
34
+ // repository whose author was never in this feature.
35
+ for (const [svc, net] of declared.netRemoved) {
36
+ for (const message of net) {
37
+ const consumers = await lookups.messageConsumers(svc, message);
38
+ if (consumers.length === 0)
39
+ continue;
40
+ issues.push({
41
+ severity: "error",
42
+ code: "asyncapi.remove-message-consumed",
43
+ subject: svc,
44
+ message: `${svc}: this feature retires message '${message}', but the living fleet still consumes it — ${consumers.join("; ")}. Retire the consumer in the same feature (drop the consumes edge from architecture/landscape.likec4, or the requirement that names it), or archive with --approve to break it deliberately.`,
45
+ });
46
+ }
47
+ }
48
+ // The WIRE half of the same question: a channel or operation removal (or
49
+ // an edit) can stop the service SENDING a message whose declaration
50
+ // survives — the merge applies cleanly, and the next `validate --all`
51
+ // breaks on the consumer's repository (spine.message-unproduced) exactly
52
+ // as a deleted declaration would. Asked of the simulated merge's sent-set
53
+ // diff; a name the net-removal loop above already asked keeps one finding.
54
+ for (const [svc, stopped] of declared.stoppedSending) {
55
+ const net = declared.netRemoved.get(svc);
56
+ for (const message of stopped) {
57
+ if (net?.has(message) === true)
58
+ continue;
59
+ const consumers = await lookups.messageConsumers(svc, message);
60
+ if (consumers.length === 0)
61
+ continue;
62
+ issues.push({
63
+ severity: "error",
64
+ code: "asyncapi.remove-message-consumed",
65
+ subject: svc,
66
+ message: `${svc}: after this feature's merge, ${svc}'s asyncapi.yaml would no longer declare an action: send operation for '${message}', but the living fleet still consumes it — ${consumers.join("; ")}. Keep an operation sending it, retire the consumer in the same feature, or archive with --approve to break it deliberately.`,
67
+ });
68
+ }
69
+ }
70
+ // Two features declaring one (service, message): both deltas apply
71
+ // cleanly, so whichever archives second replaces the other's declaration
72
+ // wholesale — delta.added-conflict's shape on the message join.
73
+ for (const [svc, doc] of declared.featureDocs) {
74
+ for (const m of doc.messages) {
75
+ if (m.remove === true)
76
+ continue;
77
+ const other = await lookups.messageDefinedElsewhere(svc, m.name);
78
+ if (other === undefined)
79
+ continue;
80
+ issues.push({
81
+ severity: "warn",
82
+ code: "asyncapi.message-conflict",
83
+ subject: svc,
84
+ message: `${svc}: this feature declares message '${m.name}', which in-flight ${other} also adds or edits — whichever archives second replaces the other's declaration wholesale; coordinate before either ships`,
85
+ });
86
+ }
87
+ }
88
+ // The bound service's contract as the feature would leave it. Where the
89
+ // feature carries a delta over a readable living contract, that is the
90
+ // SIMULATED merge (declared.mergedDocs): a slot the delta retires or edits
91
+ // away stops answering here BEFORE archive — a leftover Publishes: line on
92
+ // a surviving requirement used to pass this gate on living's say-so, then
93
+ // break `validate --all` on the post-archive docs. Everywhere the
94
+ // simulation has no answer — no delta for the service, a side that does
95
+ // not read, a document the merge refuses — the feature ∪ living union
96
+ // stands in, which can only be too lenient, never wrongly red; the living
97
+ // side is read lazily per service, since an edge may bind a service the
98
+ // feature carries no specs/ directory for.
99
+ const livingDocs = new Map();
100
+ const livingOf = async (svc) => {
101
+ let doc = livingDocs.get(svc);
102
+ if (doc === undefined) {
103
+ doc = await readAsyncapi((await locateServicePaths(scope.docsDir, svc, context)).asyncapi, context);
104
+ livingDocs.set(svc, doc);
105
+ }
106
+ return doc;
107
+ };
108
+ // undefined = no verdict: an unreadable LIVING contract proves nothing
109
+ // about the message (validate's asyncapi.invalid owns that file), and
110
+ // grading against its empty parse would blame every edge for one broken
111
+ // document.
112
+ const declares = async (svc, direction, message) => {
113
+ const merged = declared.mergedDocs.get(svc);
114
+ if (merged !== undefined) {
115
+ return direction === "publishes" ? merged.sent.includes(message) : merged.received.includes(message);
116
+ }
117
+ const living = await livingOf(svc);
118
+ if (living.unreadable)
119
+ return undefined;
120
+ const feat = declared.featureDocs.get(svc);
121
+ return direction === "publishes"
122
+ ? living.sent.includes(message) || (feat?.sent.includes(message) ?? false)
123
+ : living.received.includes(message) || (feat?.received.includes(message) ?? false);
124
+ };
125
+ const action = (direction) => (direction === "publishes" ? "send" : "receive");
126
+ // The declared→enumerated bridge coherence.ts uses for op edges, for the
127
+ // same reason: every lookup below joins into services/<id>/ or the
128
+ // feature's own specs/. A bound element NEITHER knows is skipped rather
129
+ // than graded — an #external producer is the documented shape for a
130
+ // message produced outside the fleet (spine.message-external), so grading
131
+ // its edge against an absent service directory would turn the worked
132
+ // example red.
133
+ const enumeratedTarget = enumeratedServiceIndex(scope.docsDir, svcNames, context);
134
+ // Tagged edges: `publishes` binds the edge's SOURCE, `consumes` its
135
+ // TARGET — the same reading validate's event spine takes of the living
136
+ // landscape, applied to the delta.
137
+ for (const r of taggedRels) {
138
+ const bound = [];
139
+ const edge = `${svcOf(r.source)} → ${svcOf(r.target)}`;
140
+ if (r.publishes !== undefined)
141
+ bound.push({ direction: "publishes", message: r.publishes, name: svcOf(r.source), edge });
142
+ if (r.consumes !== undefined)
143
+ bound.push({ direction: "consumes", message: r.consumes, name: svcOf(r.target), edge });
144
+ for (const b of bound) {
145
+ const pathable = await enumeratedTarget(b.name);
146
+ if (pathable === undefined)
147
+ continue;
148
+ // asyncapi.invalid already gates; one breach, one finding.
149
+ if (declared.unreadable.has(pathable))
150
+ continue;
151
+ const ok = await declares(pathable, b.direction, b.message);
152
+ if (ok !== false)
153
+ continue;
154
+ const other = await lookups.messageDefinedElsewhere(pathable, b.message);
155
+ if (other !== undefined) {
156
+ issues.push({
157
+ severity: "warn",
158
+ code: "c4-event.message-pending",
159
+ message: `edge ${b.edge} ${b.direction} '${b.message}', defined by in-flight ${other} — archive it first`,
160
+ });
161
+ }
162
+ else {
163
+ issues.push({
164
+ severity: "error",
165
+ code: "c4-event.message-undefined",
166
+ message: `edge ${b.edge} ${b.direction} '${b.message}', but ${b.name}'s asyncapi contract (feature and living alike) declares no operation with action: ${action(b.direction)} for it`,
167
+ });
168
+ }
169
+ }
170
+ }
171
+ // The requirement deltas' own lines, graded the same way — the same
172
+ // sentence validate gives the living-side breach, under the same code, so
173
+ // one breach keeps one name across scopes. The lines were read once by
174
+ // ./declared.ts's walk (declared.links); re-reading them here per service
175
+ // was a second parse of both spec files on the context-less archive path.
176
+ for (const svc of svcNames) {
177
+ if (declared.unreadable.has(svc))
178
+ continue;
179
+ for (const link of declared.links.get(svc) ?? []) {
180
+ const ok = await declares(svc, link.direction, link.message);
181
+ if (ok !== false)
182
+ continue;
183
+ const other = await lookups.messageDefinedElsewhere(svc, link.message);
184
+ if (other !== undefined) {
185
+ issues.push({
186
+ severity: "warn",
187
+ code: "spec-event.message-pending",
188
+ subject: svc,
189
+ message: `${svc}: requirement '${link.requirement}' ${link.direction} '${link.message}', defined by in-flight ${other} — archive it first`,
190
+ });
191
+ }
192
+ else {
193
+ issues.push({
194
+ severity: "error",
195
+ code: "spec-event.message-undefined",
196
+ subject: svc,
197
+ message: `${svc}: requirement '${link.requirement}' ${link.direction} '${link.message}', but ${svc}'s asyncapi.yaml declares no operation with action: ${action(link.direction)} for it`,
198
+ });
199
+ }
200
+ }
201
+ }
202
+ return issues;
203
+ }
204
+ //# sourceMappingURL=events.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.js","sourceRoot":"","sources":["../../../../src/core/coherence/events/events.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The event axis of the feature gate: do the C4 delta's tagged edges, the\n * requirement deltas' `Publishes:`/`Consumes:` lines, and the asyncapi\n * contracts agree about what each service puts on the wire?\n *\n * The package's orchestrator, called once from featureCoherence with the\n * delta facts it already holds (tagged relationships and the element\n * resolver): ./declared.ts walks the feature's own contracts and grades\n * what one service's pair of documents can settle; ./lookups.ts answers the\n * fleet questions lazily; this module joins the three axes — the exact\n * shape coherence.ts gives the operation join, on the message name.\n *\n * A package of its own rather than lines in coherence.ts because that file\n * ran at its 300-line limit before the event axis existed; the seam is\n * real, not cosmetic — everything here joins on a message name, nothing\n * there does.\n */\nimport { type Rel } from \"../../c4/likec4.js\";\nimport { type PathableService } from \"../../kernel/ids/service.js\";\nimport type { Issue } from \"../../vocabulary/issue.js\";\nimport { locateServicePaths } from \"../../repo/service-target.js\";\nimport { enumeratedServiceIndex } from \"../../repo/service-target.js\";\nimport { readAsyncapi } from \"../../asyncapi/read.js\";\nimport type { AsyncapiDoc } from \"../../asyncapi/model.js\";\nimport type { FleetContext } from \"../../fleet-context.js\";\nimport { declaredEvents, type EventDeltaScope } from \"./declared.js\";\nimport { eventLookups } from \"./lookups.js\";\n\n/** What featureCoherence hands the event axis — the delta facts it already computed. */\nexport interface EventCoherenceRequest {\n scope: EventDeltaScope;\n /** The services this feature's specs/ touch — the walk's subjects. */\n svcNames: PathableService[];\n /** The delta's tagged relationships — the edges the landscape merge would splice. */\n taggedRels: Rel[];\n /** The element→service resolver over the delta's elements plus the enumerated fleet. */\n svcOf: (id: string) => string;\n context?: FleetContext;\n}\n\nexport async function eventCoherence(request: EventCoherenceRequest): Promise<Issue[]> {\n const { scope, svcNames, taggedRels, svcOf, context } = request;\n const issues: Issue[] = [];\n const declared = await declaredEvents(scope, svcNames, issues, context);\n const lookups = eventLookups({ docsDir: scope.docsDir, featureId: scope.featureId }, context);\n\n // Retiring a message the fleet still consumes — openapi.remove-op-consumed's\n // twin, and like it a question neither exactness nor justification asks:\n // the merge deletes the declaration while the consumes edge and the other\n // repo's requirement stay, so the next `validate --all` breaks on a\n // repository whose author was never in this feature.\n for (const [svc, net] of declared.netRemoved) {\n for (const message of net) {\n const consumers = await lookups.messageConsumers(svc, message);\n if (consumers.length === 0) continue;\n issues.push({\n severity: \"error\",\n code: \"asyncapi.remove-message-consumed\",\n subject: svc,\n message: `${svc}: this feature retires message '${message}', but the living fleet still consumes it — ${consumers.join(\"; \")}. Retire the consumer in the same feature (drop the consumes edge from architecture/landscape.likec4, or the requirement that names it), or archive with --approve to break it deliberately.`,\n });\n }\n }\n\n // The WIRE half of the same question: a channel or operation removal (or\n // an edit) can stop the service SENDING a message whose declaration\n // survives — the merge applies cleanly, and the next `validate --all`\n // breaks on the consumer's repository (spine.message-unproduced) exactly\n // as a deleted declaration would. Asked of the simulated merge's sent-set\n // diff; a name the net-removal loop above already asked keeps one finding.\n for (const [svc, stopped] of declared.stoppedSending) {\n const net = declared.netRemoved.get(svc);\n for (const message of stopped) {\n if (net?.has(message) === true) continue;\n const consumers = await lookups.messageConsumers(svc, message);\n if (consumers.length === 0) continue;\n issues.push({\n severity: \"error\",\n code: \"asyncapi.remove-message-consumed\",\n subject: svc,\n message: `${svc}: after this feature's merge, ${svc}'s asyncapi.yaml would no longer declare an action: send operation for '${message}', but the living fleet still consumes it — ${consumers.join(\"; \")}. Keep an operation sending it, retire the consumer in the same feature, or archive with --approve to break it deliberately.`,\n });\n }\n }\n\n // Two features declaring one (service, message): both deltas apply\n // cleanly, so whichever archives second replaces the other's declaration\n // wholesale — delta.added-conflict's shape on the message join.\n for (const [svc, doc] of declared.featureDocs) {\n for (const m of doc.messages) {\n if (m.remove === true) continue;\n const other = await lookups.messageDefinedElsewhere(svc, m.name);\n if (other === undefined) continue;\n issues.push({\n severity: \"warn\",\n code: \"asyncapi.message-conflict\",\n subject: svc,\n message: `${svc}: this feature declares message '${m.name}', which in-flight ${other} also adds or edits — whichever archives second replaces the other's declaration wholesale; coordinate before either ships`,\n });\n }\n }\n\n // The bound service's contract as the feature would leave it. Where the\n // feature carries a delta over a readable living contract, that is the\n // SIMULATED merge (declared.mergedDocs): a slot the delta retires or edits\n // away stops answering here BEFORE archive — a leftover Publishes: line on\n // a surviving requirement used to pass this gate on living's say-so, then\n // break `validate --all` on the post-archive docs. Everywhere the\n // simulation has no answer — no delta for the service, a side that does\n // not read, a document the merge refuses — the feature ∪ living union\n // stands in, which can only be too lenient, never wrongly red; the living\n // side is read lazily per service, since an edge may bind a service the\n // feature carries no specs/ directory for.\n const livingDocs = new Map<PathableService, AsyncapiDoc>();\n const livingOf = async (svc: PathableService): Promise<AsyncapiDoc> => {\n let doc = livingDocs.get(svc);\n if (doc === undefined) {\n doc = await readAsyncapi((await locateServicePaths(scope.docsDir, svc, context)).asyncapi, context);\n livingDocs.set(svc, doc);\n }\n return doc;\n };\n // undefined = no verdict: an unreadable LIVING contract proves nothing\n // about the message (validate's asyncapi.invalid owns that file), and\n // grading against its empty parse would blame every edge for one broken\n // document.\n const declares = async (\n svc: PathableService,\n direction: \"publishes\" | \"consumes\",\n message: string,\n ): Promise<boolean | undefined> => {\n const merged = declared.mergedDocs.get(svc);\n if (merged !== undefined) {\n return direction === \"publishes\" ? merged.sent.includes(message) : merged.received.includes(message);\n }\n const living = await livingOf(svc);\n if (living.unreadable) return undefined;\n const feat = declared.featureDocs.get(svc);\n return direction === \"publishes\"\n ? living.sent.includes(message) || (feat?.sent.includes(message) ?? false)\n : living.received.includes(message) || (feat?.received.includes(message) ?? false);\n };\n const action = (direction: \"publishes\" | \"consumes\"): string => (direction === \"publishes\" ? \"send\" : \"receive\");\n\n // The declared→enumerated bridge coherence.ts uses for op edges, for the\n // same reason: every lookup below joins into services/<id>/ or the\n // feature's own specs/. A bound element NEITHER knows is skipped rather\n // than graded — an #external producer is the documented shape for a\n // message produced outside the fleet (spine.message-external), so grading\n // its edge against an absent service directory would turn the worked\n // example red.\n const enumeratedTarget = enumeratedServiceIndex(scope.docsDir, svcNames, context);\n\n // Tagged edges: `publishes` binds the edge's SOURCE, `consumes` its\n // TARGET — the same reading validate's event spine takes of the living\n // landscape, applied to the delta.\n for (const r of taggedRels) {\n const bound: { direction: \"publishes\" | \"consumes\"; message: string; name: string; edge: string }[] = [];\n const edge = `${svcOf(r.source)} → ${svcOf(r.target)}`;\n if (r.publishes !== undefined) bound.push({ direction: \"publishes\", message: r.publishes, name: svcOf(r.source), edge });\n if (r.consumes !== undefined) bound.push({ direction: \"consumes\", message: r.consumes, name: svcOf(r.target), edge });\n for (const b of bound) {\n const pathable = await enumeratedTarget(b.name);\n if (pathable === undefined) continue;\n // asyncapi.invalid already gates; one breach, one finding.\n if (declared.unreadable.has(pathable)) continue;\n const ok = await declares(pathable, b.direction, b.message);\n if (ok !== false) continue;\n const other = await lookups.messageDefinedElsewhere(pathable, b.message);\n if (other !== undefined) {\n issues.push({\n severity: \"warn\",\n code: \"c4-event.message-pending\",\n message: `edge ${b.edge} ${b.direction} '${b.message}', defined by in-flight ${other} — archive it first`,\n });\n } else {\n issues.push({\n severity: \"error\",\n code: \"c4-event.message-undefined\",\n message: `edge ${b.edge} ${b.direction} '${b.message}', but ${b.name}'s asyncapi contract (feature and living alike) declares no operation with action: ${action(b.direction)} for it`,\n });\n }\n }\n }\n\n // The requirement deltas' own lines, graded the same way — the same\n // sentence validate gives the living-side breach, under the same code, so\n // one breach keeps one name across scopes. The lines were read once by\n // ./declared.ts's walk (declared.links); re-reading them here per service\n // was a second parse of both spec files on the context-less archive path.\n for (const svc of svcNames) {\n if (declared.unreadable.has(svc)) continue;\n for (const link of declared.links.get(svc) ?? []) {\n const ok = await declares(svc, link.direction, link.message);\n if (ok !== false) continue;\n const other = await lookups.messageDefinedElsewhere(svc, link.message);\n if (other !== undefined) {\n issues.push({\n severity: \"warn\",\n code: \"spec-event.message-pending\",\n subject: svc,\n message: `${svc}: requirement '${link.requirement}' ${link.direction} '${link.message}', defined by in-flight ${other} — archive it first`,\n });\n } else {\n issues.push({\n severity: \"error\",\n code: \"spec-event.message-undefined\",\n subject: svc,\n message: `${svc}: requirement '${link.requirement}' ${link.direction} '${link.message}', but ${svc}'s asyncapi.yaml declares no operation with action: ${action(link.direction)} for it`,\n });\n }\n }\n }\n\n return issues;\n}\n"]}