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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1256) hide show
  1. package/CHANGELOG.md +5992 -82
  2. package/COMPARISON.md +168 -63
  3. package/CONTRIBUTING.md +121 -0
  4. package/MIGRATING-from-OpenSpec.md +238 -55
  5. package/QUICKSTART.md +302 -0
  6. package/README.md +653 -144
  7. package/ROADMAP.md +1035 -0
  8. package/SCHEMA.md +3916 -263
  9. package/SECURITY.md +21 -3
  10. package/WORKFLOW.md +927 -0
  11. package/dist/cli.js +133 -21
  12. package/dist/cli.js.map +1 -1
  13. package/dist/commands/adopt/adopt.js +204 -0
  14. package/dist/commands/adopt/adopt.js.map +1 -0
  15. package/dist/commands/adopt/render.js +309 -0
  16. package/dist/commands/adopt/render.js.map +1 -0
  17. package/dist/commands/archive/archive.js +74 -0
  18. package/dist/commands/archive/archive.js.map +1 -0
  19. package/dist/commands/archive/closing.js +42 -0
  20. package/dist/commands/archive/closing.js.map +1 -0
  21. package/dist/commands/archive/plan/contracts/asyncapi.js +172 -0
  22. package/dist/commands/archive/plan/contracts/asyncapi.js.map +1 -0
  23. package/dist/commands/archive/plan/contracts/consumers.js +56 -0
  24. package/dist/commands/archive/plan/contracts/consumers.js.map +1 -0
  25. package/dist/commands/archive/plan/contracts/openapi.js +193 -0
  26. package/dist/commands/archive/plan/contracts/openapi.js.map +1 -0
  27. package/dist/commands/archive/plan/contracts/verdict-lines.js +103 -0
  28. package/dist/commands/archive/plan/contracts/verdict-lines.js.map +1 -0
  29. package/dist/commands/archive/plan/document/head.js +151 -0
  30. package/dist/commands/archive/plan/document/head.js.map +1 -0
  31. package/dist/commands/archive/plan/document/links.js +284 -0
  32. package/dist/commands/archive/plan/document/links.js.map +1 -0
  33. package/dist/commands/archive/plan/document/run.js +136 -0
  34. package/dist/commands/archive/plan/document/run.js.map +1 -0
  35. package/dist/commands/archive/plan/gate.js +319 -0
  36. package/dist/commands/archive/plan/gate.js.map +1 -0
  37. package/dist/commands/archive/plan/landscape.js +298 -0
  38. package/dist/commands/archive/plan/landscape.js.map +1 -0
  39. package/dist/commands/archive/plan/model/extending.js +85 -0
  40. package/dist/commands/archive/plan/model/extending.js.map +1 -0
  41. package/dist/commands/archive/plan/refusal.js +106 -0
  42. package/dist/commands/archive/plan/refusal.js.map +1 -0
  43. package/dist/commands/archive/plan/specs.js +318 -0
  44. package/dist/commands/archive/plan/specs.js.map +1 -0
  45. package/dist/commands/archive/plan/state.js +30 -0
  46. package/dist/commands/archive/plan/state.js.map +1 -0
  47. package/dist/commands/archive/run.js +355 -0
  48. package/dist/commands/archive/run.js.map +1 -0
  49. package/dist/commands/archive/shipped.js +49 -0
  50. package/dist/commands/archive/shipped.js.map +1 -0
  51. package/dist/commands/context/context.js +166 -0
  52. package/dist/commands/context/context.js.map +1 -0
  53. package/dist/commands/context/print.js +305 -0
  54. package/dist/commands/context/print.js.map +1 -0
  55. package/dist/commands/delta/delta.js +367 -0
  56. package/dist/commands/delta/delta.js.map +1 -0
  57. package/dist/commands/delta/print.js +221 -0
  58. package/dist/commands/delta/print.js.map +1 -0
  59. package/dist/commands/dependencies.js +6 -8
  60. package/dist/commands/dependencies.js.map +1 -1
  61. package/dist/commands/diff/diff.js +86 -0
  62. package/dist/commands/diff/diff.js.map +1 -0
  63. package/dist/commands/diff/print.js +38 -0
  64. package/dist/commands/diff/print.js.map +1 -0
  65. package/dist/commands/doctor.js +65 -5
  66. package/dist/commands/doctor.js.map +1 -1
  67. package/dist/commands/explain/explain.js +227 -0
  68. package/dist/commands/explain/explain.js.map +1 -0
  69. package/dist/commands/explore.js +39 -28
  70. package/dist/commands/explore.js.map +1 -1
  71. package/dist/commands/gate/gate.js +152 -0
  72. package/dist/commands/gate/gate.js.map +1 -0
  73. package/dist/commands/gate/print.js +66 -0
  74. package/dist/commands/gate/print.js.map +1 -0
  75. package/dist/commands/gherkin/commit.js +105 -0
  76. package/dist/commands/gherkin/commit.js.map +1 -0
  77. package/dist/commands/gherkin/gherkin.js +262 -0
  78. package/dist/commands/gherkin/gherkin.js.map +1 -0
  79. package/dist/commands/gherkin/reconcile.js +146 -0
  80. package/dist/commands/gherkin/reconcile.js.map +1 -0
  81. package/dist/commands/gherkin/render.js +77 -0
  82. package/dist/commands/gherkin/render.js.map +1 -0
  83. package/dist/commands/init/example.js +204 -0
  84. package/dist/commands/init/example.js.map +1 -0
  85. package/dist/commands/init/first-hour.js +72 -0
  86. package/dist/commands/init/first-hour.js.map +1 -0
  87. package/dist/commands/{init.js → init/init.js} +142 -71
  88. package/dist/commands/init/init.js.map +1 -0
  89. package/dist/commands/init/mcp.js +131 -0
  90. package/dist/commands/init/mcp.js.map +1 -0
  91. package/dist/commands/init/options.js +78 -0
  92. package/dist/commands/init/options.js.map +1 -0
  93. package/dist/commands/instructions.js +72 -14
  94. package/dist/commands/instructions.js.map +1 -1
  95. package/dist/commands/list/campaign/campaign.js +63 -0
  96. package/dist/commands/list/campaign/campaign.js.map +1 -0
  97. package/dist/commands/list/campaign/owners.js +65 -0
  98. package/dist/commands/list/campaign/owners.js.map +1 -0
  99. package/dist/commands/list/json.js +155 -0
  100. package/dist/commands/list/json.js.map +1 -0
  101. package/dist/commands/list/list.js +358 -0
  102. package/dist/commands/list/list.js.map +1 -0
  103. package/dist/commands/list/print.js +344 -0
  104. package/dist/commands/list/print.js.map +1 -0
  105. package/dist/commands/list/review.js +120 -0
  106. package/dist/commands/list/review.js.map +1 -0
  107. package/dist/commands/list/suites/suites.js +140 -0
  108. package/dist/commands/list/suites/suites.js.map +1 -0
  109. package/dist/commands/list/views.js +108 -0
  110. package/dist/commands/list/views.js.map +1 -0
  111. package/dist/commands/mcp/dispatch.js +238 -0
  112. package/dist/commands/mcp/dispatch.js.map +1 -0
  113. package/dist/commands/mcp/mcp.js +75 -0
  114. package/dist/commands/mcp/mcp.js.map +1 -0
  115. package/dist/commands/mcp/serve.js +55 -0
  116. package/dist/commands/mcp/serve.js.map +1 -0
  117. package/dist/commands/migrate-openspec/materialize/active.js +175 -0
  118. package/dist/commands/migrate-openspec/materialize/active.js.map +1 -0
  119. package/dist/commands/migrate-openspec/materialize/feature.js +41 -0
  120. package/dist/commands/migrate-openspec/materialize/feature.js.map +1 -0
  121. package/dist/commands/migrate-openspec/materialize/living.js +62 -0
  122. package/dist/commands/migrate-openspec/materialize/living.js.map +1 -0
  123. package/dist/commands/migrate-openspec/materialize/stage.js +143 -0
  124. package/dist/commands/migrate-openspec/materialize/stage.js.map +1 -0
  125. package/dist/commands/migrate-openspec/materialize/target.js +219 -0
  126. package/dist/commands/migrate-openspec/materialize/target.js.map +1 -0
  127. package/dist/commands/migrate-openspec/migrate-openspec.js +142 -0
  128. package/dist/commands/migrate-openspec/migrate-openspec.js.map +1 -0
  129. package/dist/commands/migrate-openspec/openspec/decisions.js +86 -0
  130. package/dist/commands/migrate-openspec/openspec/decisions.js.map +1 -0
  131. package/dist/commands/migrate-openspec/openspec/error.js +18 -0
  132. package/dist/commands/migrate-openspec/openspec/error.js.map +1 -0
  133. package/dist/commands/migrate-openspec/openspec/mapping.js +162 -0
  134. package/dist/commands/migrate-openspec/openspec/mapping.js.map +1 -0
  135. package/dist/commands/migrate-openspec/openspec/paths.js +40 -0
  136. package/dist/commands/migrate-openspec/openspec/paths.js.map +1 -0
  137. package/dist/commands/migrate-openspec/openspec/read.js +49 -0
  138. package/dist/commands/migrate-openspec/openspec/read.js.map +1 -0
  139. package/dist/commands/migrate-openspec/print.js +89 -0
  140. package/dist/commands/migrate-openspec/print.js.map +1 -0
  141. package/dist/commands/new/capability-template.js +118 -0
  142. package/dist/commands/new/capability-template.js.map +1 -0
  143. package/dist/commands/new/commit.js +62 -0
  144. package/dist/commands/new/commit.js.map +1 -0
  145. package/dist/commands/new/modifies.js +206 -0
  146. package/dist/commands/new/modifies.js.map +1 -0
  147. package/dist/commands/new/new.js +328 -0
  148. package/dist/commands/new/new.js.map +1 -0
  149. package/dist/commands/new/templates.js +279 -0
  150. package/dist/commands/new/templates.js.map +1 -0
  151. package/dist/commands/open.js +199 -0
  152. package/dist/commands/open.js.map +1 -0
  153. package/dist/commands/policy/format.js +152 -0
  154. package/dist/commands/policy/format.js.map +1 -0
  155. package/dist/commands/{docs-repo-gate.js → policy/gate.js} +38 -11
  156. package/dist/commands/policy/gate.js.map +1 -0
  157. package/dist/commands/rebase/edit.js +106 -0
  158. package/dist/commands/rebase/edit.js.map +1 -0
  159. package/dist/commands/rebase/living.js +185 -0
  160. package/dist/commands/rebase/living.js.map +1 -0
  161. package/dist/commands/rebase/plan.js +245 -0
  162. package/dist/commands/rebase/plan.js.map +1 -0
  163. package/dist/commands/rebase/rebase.js +300 -0
  164. package/dist/commands/rebase/rebase.js.map +1 -0
  165. package/dist/commands/seed/commit.js +221 -0
  166. package/dist/commands/seed/commit.js.map +1 -0
  167. package/dist/commands/seed/plan.js +278 -0
  168. package/dist/commands/seed/plan.js.map +1 -0
  169. package/dist/commands/seed/seed.js +174 -0
  170. package/dist/commands/seed/seed.js.map +1 -0
  171. package/dist/commands/show/feature.js +182 -0
  172. package/dist/commands/show/feature.js.map +1 -0
  173. package/dist/commands/show/introduced.js +157 -0
  174. package/dist/commands/show/introduced.js.map +1 -0
  175. package/dist/commands/show/marks.js +53 -0
  176. package/dist/commands/show/marks.js.map +1 -0
  177. package/dist/commands/show/service.js +239 -0
  178. package/dist/commands/show/service.js.map +1 -0
  179. package/dist/commands/show/show.js +87 -0
  180. package/dist/commands/show/show.js.map +1 -0
  181. package/dist/commands/status/fleet-next.js +90 -0
  182. package/dist/commands/status/fleet-next.js.map +1 -0
  183. package/dist/commands/status/json.js +47 -0
  184. package/dist/commands/status/json.js.map +1 -0
  185. package/dist/commands/status/print.js +209 -0
  186. package/dist/commands/status/print.js.map +1 -0
  187. package/dist/commands/status/status.js +115 -0
  188. package/dist/commands/status/status.js.map +1 -0
  189. package/dist/commands/steps/steps.js +269 -0
  190. package/dist/commands/steps/steps.js.map +1 -0
  191. package/dist/commands/subsystem/edit.js +192 -0
  192. package/dist/commands/subsystem/edit.js.map +1 -0
  193. package/dist/commands/subsystem/move.js +325 -0
  194. package/dist/commands/subsystem/move.js.map +1 -0
  195. package/dist/commands/subsystem/query.js +113 -0
  196. package/dist/commands/subsystem/query.js.map +1 -0
  197. package/dist/commands/subsystem/subsystem.js +98 -0
  198. package/dist/commands/subsystem/subsystem.js.map +1 -0
  199. package/dist/commands/subsystem/sync.js +318 -0
  200. package/dist/commands/subsystem/sync.js.map +1 -0
  201. package/dist/commands/subsystem/txn/exclude.js +132 -0
  202. package/dist/commands/subsystem/txn/exclude.js.map +1 -0
  203. package/dist/commands/subsystem/txn/links.js +128 -0
  204. package/dist/commands/subsystem/txn/links.js.map +1 -0
  205. package/dist/commands/subsystem/txn/report.js +174 -0
  206. package/dist/commands/subsystem/txn/report.js.map +1 -0
  207. package/dist/commands/subsystem/txn/txn.js +196 -0
  208. package/dist/commands/subsystem/txn/txn.js.map +1 -0
  209. package/dist/commands/subsystem/txn/views.js +249 -0
  210. package/dist/commands/subsystem/txn/views.js.map +1 -0
  211. package/dist/commands/tasks/actions.js +107 -0
  212. package/dist/commands/tasks/actions.js.map +1 -0
  213. package/dist/commands/tasks/render.js +253 -0
  214. package/dist/commands/tasks/render.js.map +1 -0
  215. package/dist/commands/tasks/tasks.js +119 -0
  216. package/dist/commands/tasks/tasks.js.map +1 -0
  217. package/dist/commands/unarchive/manifest.js +176 -0
  218. package/dist/commands/unarchive/manifest.js.map +1 -0
  219. package/dist/commands/unarchive/restore.js +254 -0
  220. package/dist/commands/unarchive/restore.js.map +1 -0
  221. package/dist/commands/unarchive/unarchive.js +59 -0
  222. package/dist/commands/unarchive/unarchive.js.map +1 -0
  223. package/dist/commands/validate/arch-coverage.js +245 -0
  224. package/dist/commands/validate/arch-coverage.js.map +1 -0
  225. package/dist/commands/validate/checks/fleet-shape.js +204 -0
  226. package/dist/commands/validate/checks/fleet-shape.js.map +1 -0
  227. package/dist/commands/validate/checks/health-deps.js +58 -0
  228. package/dist/commands/validate/checks/health-deps.js.map +1 -0
  229. package/dist/commands/validate/checks/introduced.js +102 -0
  230. package/dist/commands/validate/checks/introduced.js.map +1 -0
  231. package/dist/commands/validate/checks/requirements.js +264 -0
  232. package/dist/commands/validate/checks/requirements.js.map +1 -0
  233. package/dist/commands/validate/checks/sources.js +85 -0
  234. package/dist/commands/validate/checks/sources.js.map +1 -0
  235. package/dist/commands/validate/coverage/covers-after.js +105 -0
  236. package/dist/commands/validate/coverage/covers-after.js.map +1 -0
  237. package/dist/commands/validate/feature.js +222 -0
  238. package/dist/commands/validate/feature.js.map +1 -0
  239. package/dist/commands/validate/fleet/census.js +93 -0
  240. package/dist/commands/validate/fleet/census.js.map +1 -0
  241. package/dist/commands/validate/fleet/kind-tags.js +39 -0
  242. package/dist/commands/validate/fleet/kind-tags.js.map +1 -0
  243. package/dist/commands/validate/fleet/landscape.js +371 -0
  244. package/dist/commands/validate/fleet/landscape.js.map +1 -0
  245. package/dist/commands/validate/fleet/load.js +118 -0
  246. package/dist/commands/validate/fleet/load.js.map +1 -0
  247. package/dist/commands/validate/fleet/map/attest.js +98 -0
  248. package/dist/commands/validate/fleet/map/attest.js.map +1 -0
  249. package/dist/commands/validate/fleet/map/bindings.js +107 -0
  250. package/dist/commands/validate/fleet/map/bindings.js.map +1 -0
  251. package/dist/commands/validate/fleet/map/consumers.js +244 -0
  252. package/dist/commands/validate/fleet/map/consumers.js.map +1 -0
  253. package/dist/commands/validate/fleet/map/isolation.js +116 -0
  254. package/dist/commands/validate/fleet/map/isolation.js.map +1 -0
  255. package/dist/commands/validate/fleet/map/usecases.js +54 -0
  256. package/dist/commands/validate/fleet/map/usecases.js.map +1 -0
  257. package/dist/commands/validate/fleet/obligations.js +266 -0
  258. package/dist/commands/validate/fleet/obligations.js.map +1 -0
  259. package/dist/commands/validate/fleet/scorecard/adoption.js +102 -0
  260. package/dist/commands/validate/fleet/scorecard/adoption.js.map +1 -0
  261. package/dist/commands/validate/fleet/scorecard/contracts.js +98 -0
  262. package/dist/commands/validate/fleet/scorecard/contracts.js.map +1 -0
  263. package/dist/commands/validate/fleet/scorecard/print.js +71 -0
  264. package/dist/commands/validate/fleet/scorecard/print.js.map +1 -0
  265. package/dist/commands/validate/fleet/scorecard/scorecard.js +162 -0
  266. package/dist/commands/validate/fleet/scorecard/scorecard.js.map +1 -0
  267. package/dist/commands/validate/fleet/usecases/place.js +13 -0
  268. package/dist/commands/validate/fleet/usecases/place.js.map +1 -0
  269. package/dist/commands/validate/fleet/views/fleet-project.js +217 -0
  270. package/dist/commands/validate/fleet/views/fleet-project.js.map +1 -0
  271. package/dist/commands/validate/fleet/views/ids.js +75 -0
  272. package/dist/commands/validate/fleet/views/ids.js.map +1 -0
  273. package/dist/commands/validate/fleet/views/projects.js +278 -0
  274. package/dist/commands/validate/fleet/views/projects.js.map +1 -0
  275. package/dist/commands/validate/fleet/views/root-documents.js +83 -0
  276. package/dist/commands/validate/fleet/views/root-documents.js.map +1 -0
  277. package/dist/commands/validate/fleet/views/stale.js +52 -0
  278. package/dist/commands/validate/fleet/views/stale.js.map +1 -0
  279. package/dist/commands/validate/links/corpus.js +89 -0
  280. package/dist/commands/validate/links/corpus.js.map +1 -0
  281. package/dist/commands/validate/links/glossary.js +75 -0
  282. package/dist/commands/validate/links/glossary.js.map +1 -0
  283. package/dist/commands/validate/render/repeats.js +63 -0
  284. package/dist/commands/validate/render/repeats.js.map +1 -0
  285. package/dist/commands/validate/render/rollups.js +115 -0
  286. package/dist/commands/validate/render/rollups.js.map +1 -0
  287. package/dist/commands/validate/render/text.js +199 -0
  288. package/dist/commands/validate/render/text.js.map +1 -0
  289. package/dist/commands/validate/report.js +145 -0
  290. package/dist/commands/validate/report.js.map +1 -0
  291. package/dist/commands/validate/scope.js +113 -0
  292. package/dist/commands/validate/scope.js.map +1 -0
  293. package/dist/commands/validate/service/api.js +252 -0
  294. package/dist/commands/validate/service/api.js.map +1 -0
  295. package/dist/commands/validate/service/contracts/generated.js +134 -0
  296. package/dist/commands/validate/service/contracts/generated.js.map +1 -0
  297. package/dist/commands/validate/service/events/events.js +241 -0
  298. package/dist/commands/validate/service/events/events.js.map +1 -0
  299. package/dist/commands/validate/service/events/message-producers.js +77 -0
  300. package/dist/commands/validate/service/events/message-producers.js.map +1 -0
  301. package/dist/commands/validate/service/evidence-pins.js +177 -0
  302. package/dist/commands/validate/service/evidence-pins.js.map +1 -0
  303. package/dist/commands/validate/service/model/diverged.js +226 -0
  304. package/dist/commands/validate/service/model/diverged.js.map +1 -0
  305. package/dist/commands/validate/service/model/grade.js +163 -0
  306. package/dist/commands/validate/service/model/grade.js.map +1 -0
  307. package/dist/commands/validate/service/service.js +310 -0
  308. package/dist/commands/validate/service/service.js.map +1 -0
  309. package/dist/commands/validate/service/specs.js +279 -0
  310. package/dist/commands/validate/service/specs.js.map +1 -0
  311. package/dist/commands/validate/service/spine.js +148 -0
  312. package/dist/commands/validate/service/spine.js.map +1 -0
  313. package/dist/commands/validate/service/usecases/tags.js +113 -0
  314. package/dist/commands/validate/service/usecases/tags.js.map +1 -0
  315. package/dist/commands/validate/service/usecases/usecases.js +209 -0
  316. package/dist/commands/validate/service/usecases/usecases.js.map +1 -0
  317. package/dist/commands/validate/validate.js +363 -0
  318. package/dist/commands/validate/validate.js.map +1 -0
  319. package/dist/commands/verify/cross/diff.js +178 -0
  320. package/dist/commands/verify/cross/diff.js.map +1 -0
  321. package/dist/commands/verify/evidence/contract.js +32 -0
  322. package/dist/commands/verify/evidence/contract.js.map +1 -0
  323. package/dist/commands/verify/evidence/pins.js +52 -0
  324. package/dist/commands/verify/evidence/pins.js.map +1 -0
  325. package/dist/commands/verify/evidence/read.js +81 -0
  326. package/dist/commands/verify/evidence/read.js.map +1 -0
  327. package/dist/commands/verify/frozen.js +263 -0
  328. package/dist/commands/verify/frozen.js.map +1 -0
  329. package/dist/commands/verify/record.js +278 -0
  330. package/dist/commands/verify/record.js.map +1 -0
  331. package/dist/commands/verify/report.js +206 -0
  332. package/dist/commands/verify/report.js.map +1 -0
  333. package/dist/commands/verify/results.js +328 -0
  334. package/dist/commands/verify/results.js.map +1 -0
  335. package/dist/commands/verify/verify.js +220 -0
  336. package/dist/commands/verify/verify.js.map +1 -0
  337. package/dist/commands/vouch/contract.js +11 -0
  338. package/dist/commands/vouch/contract.js.map +1 -0
  339. package/dist/commands/vouch/pack/contract.js +2 -0
  340. package/dist/commands/vouch/pack/contract.js.map +1 -0
  341. package/dist/commands/vouch/pack/pack.js +266 -0
  342. package/dist/commands/vouch/pack/pack.js.map +1 -0
  343. package/dist/commands/vouch/pack/print.js +266 -0
  344. package/dist/commands/vouch/pack/print.js.map +1 -0
  345. package/dist/commands/vouch/pack/sections.js +141 -0
  346. package/dist/commands/vouch/pack/sections.js.map +1 -0
  347. package/dist/commands/vouch/prompt/confirm.js +46 -0
  348. package/dist/commands/vouch/prompt/confirm.js.map +1 -0
  349. package/dist/commands/vouch/report.js +101 -0
  350. package/dist/commands/vouch/report.js.map +1 -0
  351. package/dist/commands/vouch/run.js +230 -0
  352. package/dist/commands/vouch/run.js.map +1 -0
  353. package/dist/commands/vouch/sample/plan.js +111 -0
  354. package/dist/commands/vouch/sample/plan.js.map +1 -0
  355. package/dist/commands/vouch/sample/print.js +109 -0
  356. package/dist/commands/vouch/sample/print.js.map +1 -0
  357. package/dist/commands/vouch/vet/verify.js +155 -0
  358. package/dist/commands/vouch/vet/verify.js.map +1 -0
  359. package/dist/commands/vouch/vouch.js +169 -0
  360. package/dist/commands/vouch/vouch.js.map +1 -0
  361. package/dist/core/agent/agents-md/command-map.js +299 -0
  362. package/dist/core/agent/agents-md/command-map.js.map +1 -0
  363. package/dist/core/agent/agents-md/map/explain.js +46 -0
  364. package/dist/core/agent/agents-md/map/explain.js.map +1 -0
  365. package/dist/core/agent/agents-md/map/lenses/context.js +50 -0
  366. package/dist/core/agent/agents-md/map/lenses/context.js.map +1 -0
  367. package/dist/core/agent/agents-md/map/lenses/diff.js +59 -0
  368. package/dist/core/agent/agents-md/map/lenses/diff.js.map +1 -0
  369. package/dist/core/agent/agents-md/map/lenses/gate.js +65 -0
  370. package/dist/core/agent/agents-md/map/lenses/gate.js.map +1 -0
  371. package/dist/core/agent/agents-md/map/mcp.js +44 -0
  372. package/dist/core/agent/agents-md/map/mcp.js.map +1 -0
  373. package/dist/core/agent/agents-md/map/status.js +78 -0
  374. package/dist/core/agent/agents-md/map/status.js.map +1 -0
  375. package/dist/core/agent/agents-md/map/subsystem.js +104 -0
  376. package/dist/core/agent/agents-md/map/subsystem.js.map +1 -0
  377. package/dist/core/agent/agents-md/map/usecases.js +138 -0
  378. package/dist/core/agent/agents-md/map/usecases.js.map +1 -0
  379. package/dist/core/agent/agents-md/refusals.js +273 -0
  380. package/dist/core/agent/agents-md/refusals.js.map +1 -0
  381. package/dist/core/agent/agents-md.js +203 -0
  382. package/dist/core/agent/agents-md.js.map +1 -0
  383. package/dist/core/{agents-stamp.js → agent/agents-stamp.js} +60 -0
  384. package/dist/core/agent/agents-stamp.js.map +1 -0
  385. package/dist/core/agent/contract.js +2 -0
  386. package/dist/core/agent/contract.js.map +1 -0
  387. package/dist/core/agent/protocol.js +193 -0
  388. package/dist/core/agent/protocol.js.map +1 -0
  389. package/dist/core/agent/scaffold.js +254 -0
  390. package/dist/core/agent/scaffold.js.map +1 -0
  391. package/dist/core/agent/support/report.js +144 -0
  392. package/dist/core/agent/support/report.js.map +1 -0
  393. package/dist/core/agent/tools/dialects.js +151 -0
  394. package/dist/core/agent/tools/dialects.js.map +1 -0
  395. package/dist/core/agent/tools/registry.js +193 -0
  396. package/dist/core/agent/tools/registry.js.map +1 -0
  397. package/dist/core/agent/workflows/adopt.js +280 -0
  398. package/dist/core/agent/workflows/adopt.js.map +1 -0
  399. package/dist/core/agent/workflows/check.js +373 -0
  400. package/dist/core/agent/workflows/check.js.map +1 -0
  401. package/dist/core/agent/workflows/closing.js +323 -0
  402. package/dist/core/agent/workflows/closing.js.map +1 -0
  403. package/dist/core/agent/workflows/feature.js +220 -0
  404. package/dist/core/agent/workflows/feature.js.map +1 -0
  405. package/dist/core/agent/workflows/implement.js +188 -0
  406. package/dist/core/agent/workflows/implement.js.map +1 -0
  407. package/dist/core/agent/workflows/reference/authoring.js +311 -0
  408. package/dist/core/agent/workflows/reference/authoring.js.map +1 -0
  409. package/dist/core/agent/workflows/reference/codes.js +67 -0
  410. package/dist/core/agent/workflows/reference/codes.js.map +1 -0
  411. package/dist/core/agent/workflows/reference/done-check.js +210 -0
  412. package/dist/core/agent/workflows/reference/done-check.js.map +1 -0
  413. package/dist/core/agent/workflows/reference/drawing/drawing.js +253 -0
  414. package/dist/core/agent/workflows/reference/drawing/drawing.js.map +1 -0
  415. package/dist/core/agent/workflows/reference/reference.js +19 -0
  416. package/dist/core/agent/workflows/reference/reference.js.map +1 -0
  417. package/dist/core/agent/workflows/reference/spine.js +338 -0
  418. package/dist/core/agent/workflows/reference/spine.js.map +1 -0
  419. package/dist/core/asyncapi/baseline/plan.js +43 -0
  420. package/dist/core/asyncapi/baseline/plan.js.map +1 -0
  421. package/dist/core/asyncapi/baseline/surfaces.js +54 -0
  422. package/dist/core/asyncapi/baseline/surfaces.js.map +1 -0
  423. package/dist/core/asyncapi/depth.js +164 -0
  424. package/dist/core/asyncapi/depth.js.map +1 -0
  425. package/dist/core/asyncapi/digest.js +146 -0
  426. package/dist/core/asyncapi/digest.js.map +1 -0
  427. package/dist/core/asyncapi/merge/components.js +92 -0
  428. package/dist/core/asyncapi/merge/components.js.map +1 -0
  429. package/dist/core/asyncapi/merge/error.js +38 -0
  430. package/dist/core/asyncapi/merge/error.js.map +1 -0
  431. package/dist/core/asyncapi/merge/markers.js +290 -0
  432. package/dist/core/asyncapi/merge/markers.js.map +1 -0
  433. package/dist/core/asyncapi/merge/merge.js +195 -0
  434. package/dist/core/asyncapi/merge/merge.js.map +1 -0
  435. package/dist/core/asyncapi/merge/pin.js +83 -0
  436. package/dist/core/asyncapi/merge/pin.js.map +1 -0
  437. package/dist/core/asyncapi/model.js +11 -0
  438. package/dist/core/asyncapi/model.js.map +1 -0
  439. package/dist/core/asyncapi/producers.js +50 -0
  440. package/dist/core/asyncapi/producers.js.map +1 -0
  441. package/dist/core/asyncapi/read.js +263 -0
  442. package/dist/core/asyncapi/read.js.map +1 -0
  443. package/dist/core/brief/brief.js +285 -0
  444. package/dist/core/brief/brief.js.map +1 -0
  445. package/dist/core/brief/checks.js +385 -0
  446. package/dist/core/brief/checks.js.map +1 -0
  447. package/dist/core/brief/landscape.js +273 -0
  448. package/dist/core/brief/landscape.js.map +1 -0
  449. package/dist/core/brief/map/extend.js +84 -0
  450. package/dist/core/brief/map/extend.js.map +1 -0
  451. package/dist/core/brief/map/owed.js +266 -0
  452. package/dist/core/brief/map/owed.js.map +1 -0
  453. package/dist/core/brief/targets.js +304 -0
  454. package/dist/core/brief/targets.js.map +1 -0
  455. package/dist/core/brief/unchecked.js +58 -0
  456. package/dist/core/brief/unchecked.js.map +1 -0
  457. package/dist/core/c4/arch.js +190 -0
  458. package/dist/core/c4/arch.js.map +1 -0
  459. package/dist/core/c4/direction/direction.js +114 -0
  460. package/dist/core/c4/direction/direction.js.map +1 -0
  461. package/dist/core/c4/likec4.js +243 -0
  462. package/dist/core/c4/likec4.js.map +1 -0
  463. package/dist/core/c4/locate/unlocated.js +150 -0
  464. package/dist/core/c4/locate/unlocated.js.map +1 -0
  465. package/dist/core/c4/parsed/deployment.js +160 -0
  466. package/dist/core/c4/parsed/deployment.js.map +1 -0
  467. package/dist/core/c4/parsed/dynamic-views.js +132 -0
  468. package/dist/core/c4/parsed/dynamic-views.js.map +1 -0
  469. package/dist/core/c4/parsed/specification.js +78 -0
  470. package/dist/core/c4/parsed/specification.js.map +1 -0
  471. package/dist/core/c4/parsed/values.js +110 -0
  472. package/dist/core/c4/parsed/values.js.map +1 -0
  473. package/dist/core/c4/parsed/view-ids.js +113 -0
  474. package/dist/core/c4/parsed/view-ids.js.map +1 -0
  475. package/dist/core/c4/prefetch/fleet.js +134 -0
  476. package/dist/core/c4/prefetch/fleet.js.map +1 -0
  477. package/dist/core/c4/project/architecture.js +161 -0
  478. package/dist/core/c4/project/architecture.js.map +1 -0
  479. package/dist/core/c4/project/batch.js +140 -0
  480. package/dist/core/c4/project/batch.js.map +1 -0
  481. package/dist/core/c4/project/documents.js +89 -0
  482. package/dist/core/c4/project/documents.js.map +1 -0
  483. package/dist/core/c4/project/load.js +219 -0
  484. package/dist/core/c4/project/load.js.map +1 -0
  485. package/dist/core/c4/project/staged.js +277 -0
  486. package/dist/core/c4/project/staged.js.map +1 -0
  487. package/dist/core/c4/resolve/attested.js +0 -0
  488. package/dist/core/c4/resolve/attested.js.map +1 -0
  489. package/dist/core/c4/resolve/external.js +51 -0
  490. package/dist/core/c4/resolve/external.js.map +1 -0
  491. package/dist/core/c4/resolve/service.js +174 -0
  492. package/dist/core/c4/resolve/service.js.map +1 -0
  493. package/dist/core/c4/resolve/steps.js +290 -0
  494. package/dist/core/c4/resolve/steps.js.map +1 -0
  495. package/dist/core/c4/resolve/systems.js +154 -0
  496. package/dist/core/c4/resolve/systems.js.map +1 -0
  497. package/dist/core/c4/root-project/exclude.js +352 -0
  498. package/dist/core/c4/root-project/exclude.js.map +1 -0
  499. package/dist/core/c4/seed/fleet-file.js +201 -0
  500. package/dist/core/c4/seed/fleet-file.js.map +1 -0
  501. package/dist/core/c4/seed/items.js +91 -0
  502. package/dist/core/c4/seed/items.js.map +1 -0
  503. package/dist/core/c4/seed/stamp.js +48 -0
  504. package/dist/core/c4/seed/stamp.js.map +1 -0
  505. package/dist/core/c4/seed/template.js +173 -0
  506. package/dist/core/c4/seed/template.js.map +1 -0
  507. package/dist/core/c4/service-model/created/models.js +96 -0
  508. package/dist/core/c4/service-model/created/models.js.map +1 -0
  509. package/dist/core/c4/service-model/documents.js +47 -0
  510. package/dist/core/c4/service-model/documents.js.map +1 -0
  511. package/dist/core/c4/service-model/fleet/extending.js +82 -0
  512. package/dist/core/c4/service-model/fleet/extending.js.map +1 -0
  513. package/dist/core/c4/service-model/load.js +165 -0
  514. package/dist/core/c4/service-model/load.js.map +1 -0
  515. package/dist/core/c4/service-model/renderer.js +128 -0
  516. package/dist/core/c4/service-model/renderer.js.map +1 -0
  517. package/dist/core/c4/service-model/shape.js +106 -0
  518. package/dist/core/c4/service-model/shape.js.map +1 -0
  519. package/dist/core/c4/service-model/slice.js +188 -0
  520. package/dist/core/c4/service-model/slice.js.map +1 -0
  521. package/dist/core/c4/source-mask.js +369 -0
  522. package/dist/core/c4/source-mask.js.map +1 -0
  523. package/dist/core/c4/source-scan.js +308 -0
  524. package/dist/core/c4/source-scan.js.map +1 -0
  525. package/dist/core/c4/splice/authored-source.js +167 -0
  526. package/dist/core/c4/splice/authored-source.js.map +1 -0
  527. package/dist/core/c4/splice/contract.js +30 -0
  528. package/dist/core/c4/splice/contract.js.map +1 -0
  529. package/dist/core/c4/splice/delta-blocks.js +126 -0
  530. package/dist/core/c4/splice/delta-blocks.js.map +1 -0
  531. package/dist/core/c4/splice/identity/declared.js +87 -0
  532. package/dist/core/c4/splice/identity/declared.js.map +1 -0
  533. package/dist/core/c4/splice/identity/edges.js +73 -0
  534. package/dist/core/c4/splice/identity/edges.js.map +1 -0
  535. package/dist/core/c4/splice/identity/existing.js +80 -0
  536. package/dist/core/c4/splice/identity/existing.js.map +1 -0
  537. package/dist/core/c4/splice/identity/interior.js +80 -0
  538. package/dist/core/c4/splice/identity/interior.js.map +1 -0
  539. package/dist/core/c4/splice/identity/owner.js +50 -0
  540. package/dist/core/c4/splice/identity/owner.js.map +1 -0
  541. package/dist/core/c4/splice/landscape-merge.js +337 -0
  542. package/dist/core/c4/splice/landscape-merge.js.map +1 -0
  543. package/dist/core/c4/splice/model/merge.js +151 -0
  544. package/dist/core/c4/splice/model/merge.js.map +1 -0
  545. package/dist/core/c4/splice/placement.js +298 -0
  546. package/dist/core/c4/splice/placement.js.map +1 -0
  547. package/dist/core/c4/splice/text/spot.js +131 -0
  548. package/dist/core/c4/splice/text/spot.js.map +1 -0
  549. package/dist/core/c4/workspace.js +166 -0
  550. package/dist/core/c4/workspace.js.map +1 -0
  551. package/dist/core/capabilities/authoring/notes.js +141 -0
  552. package/dist/core/capabilities/authoring/notes.js.map +1 -0
  553. package/dist/core/capabilities/capabilities.js +124 -0
  554. package/dist/core/capabilities/capabilities.js.map +1 -0
  555. package/dist/core/capabilities/delta/doc.js +47 -0
  556. package/dist/core/capabilities/delta/doc.js.map +1 -0
  557. package/dist/core/capabilities/delta/overlay.js +129 -0
  558. package/dist/core/capabilities/delta/overlay.js.map +1 -0
  559. package/dist/core/capabilities/delta/summary.js +57 -0
  560. package/dist/core/capabilities/delta/summary.js.map +1 -0
  561. package/dist/core/capabilities/delta/tree.js +43 -0
  562. package/dist/core/capabilities/delta/tree.js.map +1 -0
  563. package/dist/core/capabilities/delta/uncovered.js +222 -0
  564. package/dist/core/capabilities/delta/uncovered.js.map +1 -0
  565. package/dist/core/capabilities/findings.js +338 -0
  566. package/dist/core/capabilities/findings.js.map +1 -0
  567. package/dist/core/capabilities/realizes/findings.js +174 -0
  568. package/dist/core/capabilities/realizes/findings.js.map +1 -0
  569. package/dist/core/capabilities/realizes/join.js +123 -0
  570. package/dist/core/capabilities/realizes/join.js.map +1 -0
  571. package/dist/core/capabilities/rollup.js +205 -0
  572. package/dist/core/capabilities/rollup.js.map +1 -0
  573. package/dist/core/capabilities/tree.js +104 -0
  574. package/dist/core/capabilities/tree.js.map +1 -0
  575. package/dist/core/capabilities/usecase-join.js +267 -0
  576. package/dist/core/capabilities/usecase-join.js.map +1 -0
  577. package/dist/core/coherence/authoring/scaffold.js +185 -0
  578. package/dist/core/coherence/authoring/scaffold.js.map +1 -0
  579. package/dist/core/coherence/authoring/sentinels.js +75 -0
  580. package/dist/core/coherence/authoring/sentinels.js.map +1 -0
  581. package/dist/core/coherence/calls/called.js +52 -0
  582. package/dist/core/coherence/calls/called.js.map +1 -0
  583. package/dist/core/coherence/coherence.js +332 -0
  584. package/dist/core/coherence/coherence.js.map +1 -0
  585. package/dist/core/coherence/consumed/operations.js +70 -0
  586. package/dist/core/coherence/consumed/operations.js.map +1 -0
  587. package/dist/core/coherence/consumed/refusal.js +38 -0
  588. package/dist/core/coherence/consumed/refusal.js.map +1 -0
  589. package/dist/core/coherence/covers/health.js +85 -0
  590. package/dist/core/coherence/covers/health.js.map +1 -0
  591. package/dist/core/coherence/declared.js +295 -0
  592. package/dist/core/coherence/declared.js.map +1 -0
  593. package/dist/core/coherence/events/declared.js +191 -0
  594. package/dist/core/coherence/events/declared.js.map +1 -0
  595. package/dist/core/coherence/events/events.js +335 -0
  596. package/dist/core/coherence/events/events.js.map +1 -0
  597. package/dist/core/coherence/events/grades.js +189 -0
  598. package/dist/core/coherence/events/grades.js.map +1 -0
  599. package/dist/core/coherence/events/lookups.js +63 -0
  600. package/dist/core/coherence/events/lookups.js.map +1 -0
  601. package/dist/core/coherence/events/produced.js +100 -0
  602. package/dist/core/coherence/events/produced.js.map +1 -0
  603. package/dist/core/coherence/living.js +198 -0
  604. package/dist/core/coherence/living.js.map +1 -0
  605. package/dist/core/coherence/lookups.js +95 -0
  606. package/dist/core/coherence/lookups.js.map +1 -0
  607. package/dist/core/coherence/pending.js +39 -0
  608. package/dist/core/coherence/pending.js.map +1 -0
  609. package/dist/core/coherence/retired/archived.js +285 -0
  610. package/dist/core/coherence/retired/archived.js.map +1 -0
  611. package/dist/core/coherence/retired/event-pair.js +62 -0
  612. package/dist/core/coherence/retired/event-pair.js.map +1 -0
  613. package/dist/core/coherence/retired/merged.js +79 -0
  614. package/dist/core/coherence/retired/merged.js.map +1 -0
  615. package/dist/core/coherence/retired/retirement.js +49 -0
  616. package/dist/core/coherence/retired/retirement.js.map +1 -0
  617. package/dist/core/coherence/retired/revival/arrivals.js +131 -0
  618. package/dist/core/coherence/retired/revival/arrivals.js.map +1 -0
  619. package/dist/core/coherence/retired/revival/revived.js +297 -0
  620. package/dist/core/coherence/retired/revival/revived.js.map +1 -0
  621. package/dist/core/conflict-markers.js +60 -0
  622. package/dist/core/conflict-markers.js.map +1 -0
  623. package/dist/core/consumers/after.js +113 -0
  624. package/dist/core/consumers/after.js.map +1 -0
  625. package/dist/core/consumers/consumers.js +296 -0
  626. package/dist/core/consumers/consumers.js.map +1 -0
  627. package/dist/core/consumers/current.js +211 -0
  628. package/dist/core/consumers/current.js.map +1 -0
  629. package/dist/core/consumers/scan.js +46 -0
  630. package/dist/core/consumers/scan.js.map +1 -0
  631. package/dist/core/consumers/state.js +27 -0
  632. package/dist/core/consumers/state.js.map +1 -0
  633. package/dist/core/delta/claims.js +73 -0
  634. package/dist/core/delta/claims.js.map +1 -0
  635. package/dist/core/delta/delta.js +341 -0
  636. package/dist/core/delta/delta.js.map +1 -0
  637. package/dist/core/delta/document.js +177 -0
  638. package/dist/core/delta/document.js.map +1 -0
  639. package/dist/core/delta/scope.js +48 -0
  640. package/dist/core/delta/scope.js.map +1 -0
  641. package/dist/core/delta/select.js +237 -0
  642. package/dist/core/delta/select.js.map +1 -0
  643. package/dist/core/dependencies/dependencies.js +141 -0
  644. package/dist/core/dependencies/dependencies.js.map +1 -0
  645. package/dist/core/dependencies/facts.js +165 -0
  646. package/dist/core/dependencies/facts.js.map +1 -0
  647. package/dist/core/dependencies/fanin.js +88 -0
  648. package/dist/core/dependencies/fanin.js.map +1 -0
  649. package/dist/core/dependencies/graph.js +106 -0
  650. package/dist/core/dependencies/graph.js.map +1 -0
  651. package/dist/core/deployment/delta.js +191 -0
  652. package/dist/core/deployment/delta.js.map +1 -0
  653. package/dist/core/deployment/objects.js +145 -0
  654. package/dist/core/deployment/objects.js.map +1 -0
  655. package/dist/core/diff/base-git.js +230 -0
  656. package/dist/core/diff/base-git.js.map +1 -0
  657. package/dist/core/diff/base-state.js +237 -0
  658. package/dist/core/diff/base-state.js.map +1 -0
  659. package/dist/core/diff/joins.js +136 -0
  660. package/dist/core/diff/joins.js.map +1 -0
  661. package/dist/core/diff/scope/changed-paths.js +204 -0
  662. package/dist/core/diff/scope/changed-paths.js.map +1 -0
  663. package/dist/core/diff/scope/edges.js +82 -0
  664. package/dist/core/diff/scope/edges.js.map +1 -0
  665. package/dist/core/diff/semantic.js +312 -0
  666. package/dist/core/diff/semantic.js.map +1 -0
  667. package/dist/core/docs.js +37 -85
  668. package/dist/core/docs.js.map +1 -1
  669. package/dist/core/doctor/agents.js +238 -0
  670. package/dist/core/doctor/agents.js.map +1 -0
  671. package/dist/core/doctor/config.js +139 -0
  672. package/dist/core/doctor/config.js.map +1 -0
  673. package/dist/core/doctor/doctor.js +355 -0
  674. package/dist/core/doctor/doctor.js.map +1 -0
  675. package/dist/core/doctor/report.js +13 -0
  676. package/dist/core/doctor/report.js.map +1 -0
  677. package/dist/core/doctor/reports/scan.js +242 -0
  678. package/dist/core/doctor/reports/scan.js.map +1 -0
  679. package/dist/core/doctor/residue.js +110 -0
  680. package/dist/core/doctor/residue.js.map +1 -0
  681. package/dist/core/document/apply.js +224 -0
  682. package/dist/core/document/apply.js.map +1 -0
  683. package/dist/core/{frontmatter.js → document/frontmatter.js} +103 -2
  684. package/dist/core/document/frontmatter.js.map +1 -0
  685. package/dist/core/document/grammar/directives.js +143 -0
  686. package/dist/core/document/grammar/directives.js.map +1 -0
  687. package/dist/core/document/parse.js +286 -0
  688. package/dist/core/document/parse.js.map +1 -0
  689. package/dist/core/document/scenarios.js +238 -0
  690. package/dist/core/document/scenarios.js.map +1 -0
  691. package/dist/core/document/spec.js +234 -0
  692. package/dist/core/document/spec.js.map +1 -0
  693. package/dist/core/{config.js → envelope/config.js} +89 -18
  694. package/dist/core/envelope/config.js.map +1 -0
  695. package/dist/core/envelope/json.js +209 -0
  696. package/dist/core/envelope/json.js.map +1 -0
  697. package/dist/core/{version.js → envelope/version.js} +3 -3
  698. package/dist/core/envelope/version.js.map +1 -0
  699. package/dist/core/explain/families.js +180 -0
  700. package/dist/core/explain/families.js.map +1 -0
  701. package/dist/core/explain/fix-tables.js +178 -0
  702. package/dist/core/explain/fix-tables.js.map +1 -0
  703. package/dist/core/explain/lookup.js +194 -0
  704. package/dist/core/explain/lookup.js.map +1 -0
  705. package/dist/core/explain/refusals.js +49 -0
  706. package/dist/core/explain/refusals.js.map +1 -0
  707. package/dist/core/explain/terms/documents.js +227 -0
  708. package/dist/core/explain/terms/documents.js.map +1 -0
  709. package/dist/core/explain/terms/done-check.js +144 -0
  710. package/dist/core/explain/terms/done-check.js.map +1 -0
  711. package/dist/core/explain/terms/entry.js +14 -0
  712. package/dist/core/explain/terms/entry.js.map +1 -0
  713. package/dist/core/explain/terms/stages.js +71 -0
  714. package/dist/core/explain/terms/stages.js.map +1 -0
  715. package/dist/core/explain/terms/tasks.js +97 -0
  716. package/dist/core/explain/terms/tasks.js.map +1 -0
  717. package/dist/core/explain/terms.js +103 -0
  718. package/dist/core/explain/terms.js.map +1 -0
  719. package/dist/core/explore/describe.js +105 -0
  720. package/dist/core/explore/describe.js.map +1 -0
  721. package/dist/core/explore/explore.js +204 -0
  722. package/dist/core/explore/explore.js.map +1 -0
  723. package/dist/core/fleet-context.js +174 -146
  724. package/dist/core/fleet-context.js.map +1 -1
  725. package/dist/core/gate/checks.js +208 -0
  726. package/dist/core/gate/checks.js.map +1 -0
  727. package/dist/core/gate/partners.js +246 -0
  728. package/dist/core/gate/partners.js.map +1 -0
  729. package/dist/core/gate/report.js +47 -0
  730. package/dist/core/gate/report.js.map +1 -0
  731. package/dist/core/gate/verification.js +176 -0
  732. package/dist/core/gate/verification.js.map +1 -0
  733. package/dist/core/gherkin/digest.js +60 -0
  734. package/dist/core/gherkin/digest.js.map +1 -0
  735. package/dist/core/gherkin/emit.js +177 -0
  736. package/dist/core/gherkin/emit.js.map +1 -0
  737. package/dist/core/gherkin/read.js +76 -0
  738. package/dist/core/gherkin/read.js.map +1 -0
  739. package/dist/core/gherkin/stale.js +210 -0
  740. package/dist/core/gherkin/stale.js.map +1 -0
  741. package/dist/core/gherkin/stamp.js +77 -0
  742. package/dist/core/gherkin/stamp.js.map +1 -0
  743. package/dist/core/gherkin/steps/catalogue.js +154 -0
  744. package/dist/core/gherkin/steps/catalogue.js.map +1 -0
  745. package/dist/core/gherkin/steps/inventory.js +98 -0
  746. package/dist/core/gherkin/steps/inventory.js.map +1 -0
  747. package/dist/core/gherkin/steps/phrase.js +72 -0
  748. package/dist/core/gherkin/steps/phrase.js.map +1 -0
  749. package/dist/core/glossary/delta.js +109 -0
  750. package/dist/core/glossary/delta.js.map +1 -0
  751. package/dist/core/glossary/tree.js +73 -0
  752. package/dist/core/glossary/tree.js.map +1 -0
  753. package/dist/core/{concurrency.js → kernel/concurrency.js} +19 -0
  754. package/dist/core/kernel/concurrency.js.map +1 -0
  755. package/dist/core/{document-bytes.js → kernel/document-bytes.js} +1 -1
  756. package/dist/core/kernel/document-bytes.js.map +1 -0
  757. package/dist/core/kernel/fences.js +42 -0
  758. package/dist/core/kernel/fences.js.map +1 -0
  759. package/dist/core/kernel/ids/capability.js +72 -0
  760. package/dist/core/kernel/ids/capability.js.map +1 -0
  761. package/dist/core/kernel/ids/dirs.js +33 -0
  762. package/dist/core/kernel/ids/dirs.js.map +1 -0
  763. package/dist/core/kernel/ids/feature.js +75 -0
  764. package/dist/core/kernel/ids/feature.js.map +1 -0
  765. package/dist/core/kernel/ids/fqn/ancestors.js +65 -0
  766. package/dist/core/kernel/ids/fqn/ancestors.js.map +1 -0
  767. package/dist/core/kernel/ids/service.js +156 -0
  768. package/dist/core/kernel/ids/service.js.map +1 -0
  769. package/dist/core/kernel/ids/subsystem.js +63 -0
  770. package/dist/core/kernel/ids/subsystem.js.map +1 -0
  771. package/dist/core/{path-safety.js → kernel/path-safety.js} +56 -4
  772. package/dist/core/kernel/path-safety.js.map +1 -0
  773. package/dist/core/{records.js → kernel/records.js} +11 -0
  774. package/dist/core/kernel/records.js.map +1 -0
  775. package/dist/core/links/backlinks.js +66 -0
  776. package/dist/core/links/backlinks.js.map +1 -0
  777. package/dist/core/links/case.js +74 -0
  778. package/dist/core/links/case.js.map +1 -0
  779. package/dist/core/links/corpus.js +118 -0
  780. package/dist/core/links/corpus.js.map +1 -0
  781. package/dist/core/links/findings.js +110 -0
  782. package/dist/core/links/findings.js.map +1 -0
  783. package/dist/core/links/parse.js +265 -0
  784. package/dist/core/links/parse.js.map +1 -0
  785. package/dist/core/mcp/argv.js +212 -0
  786. package/dist/core/mcp/argv.js.map +1 -0
  787. package/dist/core/mcp/author-tools.js +73 -0
  788. package/dist/core/mcp/author-tools.js.map +1 -0
  789. package/dist/core/mcp/framing.js +46 -0
  790. package/dist/core/mcp/framing.js.map +1 -0
  791. package/dist/core/mcp/protocol.js +280 -0
  792. package/dist/core/mcp/protocol.js.map +1 -0
  793. package/dist/core/mcp/tools.js +324 -0
  794. package/dist/core/mcp/tools.js.map +1 -0
  795. package/dist/core/obligations/obligations.js +106 -0
  796. package/dist/core/obligations/obligations.js.map +1 -0
  797. package/dist/core/openapi/baseline/gate.js +207 -0
  798. package/dist/core/openapi/baseline/gate.js.map +1 -0
  799. package/dist/core/openapi/baseline/plan.js +142 -0
  800. package/dist/core/openapi/baseline/plan.js.map +1 -0
  801. package/dist/core/openapi/baseline/record.js +174 -0
  802. package/dist/core/openapi/baseline/record.js.map +1 -0
  803. package/dist/core/openapi/contract-text.js +33 -0
  804. package/dist/core/openapi/contract-text.js.map +1 -0
  805. package/dist/core/openapi/contract-tree.js +301 -0
  806. package/dist/core/openapi/contract-tree.js.map +1 -0
  807. package/dist/core/openapi/depth.js +136 -0
  808. package/dist/core/openapi/depth.js.map +1 -0
  809. package/dist/core/openapi/digest.js +239 -0
  810. package/dist/core/openapi/digest.js.map +1 -0
  811. package/dist/core/{openapi.js → openapi/doc.js} +54 -108
  812. package/dist/core/openapi/doc.js.map +1 -0
  813. package/dist/core/openapi/merge/components.js +199 -0
  814. package/dist/core/openapi/merge/components.js.map +1 -0
  815. package/dist/core/openapi/merge/error.js +16 -0
  816. package/dist/core/openapi/merge/error.js.map +1 -0
  817. package/dist/core/openapi/merge/markers.js +204 -0
  818. package/dist/core/openapi/merge/markers.js.map +1 -0
  819. package/dist/core/openapi/merge/merge.js +232 -0
  820. package/dist/core/openapi/merge/merge.js.map +1 -0
  821. package/dist/core/openapi/merge/pin.js +110 -0
  822. package/dist/core/openapi/merge/pin.js.map +1 -0
  823. package/dist/core/openspec/decide/capabilities.js +244 -0
  824. package/dist/core/openspec/decide/capabilities.js.map +1 -0
  825. package/dist/core/openspec/decide/dispositions.js +63 -0
  826. package/dist/core/openspec/decide/dispositions.js.map +1 -0
  827. package/dist/core/openspec/decide/renames.js +179 -0
  828. package/dist/core/openspec/decide/renames.js.map +1 -0
  829. package/dist/core/openspec/decide/verdict.js +84 -0
  830. package/dist/core/openspec/decide/verdict.js.map +1 -0
  831. package/dist/core/openspec/inventory.js +220 -0
  832. package/dist/core/openspec/inventory.js.map +1 -0
  833. package/dist/core/openspec/model/mapping.js +78 -0
  834. package/dist/core/openspec/model/mapping.js.map +1 -0
  835. package/dist/core/openspec/model/model.js +70 -0
  836. package/dist/core/openspec/model/model.js.map +1 -0
  837. package/dist/core/openspec/scan/changes.js +241 -0
  838. package/dist/core/openspec/scan/changes.js.map +1 -0
  839. package/dist/core/openspec/scan/config.js +191 -0
  840. package/dist/core/openspec/scan/config.js.map +1 -0
  841. package/dist/core/openspec/scan/shape.js +304 -0
  842. package/dist/core/openspec/scan/shape.js.map +1 -0
  843. package/dist/core/openspec/scan/walk.js +116 -0
  844. package/dist/core/openspec/scan/walk.js.map +1 -0
  845. package/dist/core/openspec/scan/workspace.js +71 -0
  846. package/dist/core/openspec/scan/workspace.js.map +1 -0
  847. package/dist/core/owners/codeowners.js +141 -0
  848. package/dist/core/owners/codeowners.js.map +1 -0
  849. package/dist/core/pack/features.js +120 -0
  850. package/dist/core/pack/features.js.map +1 -0
  851. package/dist/core/pack/joins.js +112 -0
  852. package/dist/core/pack/joins.js.map +1 -0
  853. package/dist/core/pack/living.js +157 -0
  854. package/dist/core/pack/living.js.map +1 -0
  855. package/dist/core/pack/pack.js +120 -0
  856. package/dist/core/pack/pack.js.map +1 -0
  857. package/dist/core/permissions/permissions.js +87 -0
  858. package/dist/core/permissions/permissions.js.map +1 -0
  859. package/dist/core/projection/api.js +84 -0
  860. package/dist/core/projection/api.js.map +1 -0
  861. package/dist/core/projection/arch-slice.js +63 -0
  862. package/dist/core/projection/arch-slice.js.map +1 -0
  863. package/dist/core/projection/events.js +34 -0
  864. package/dist/core/projection/events.js.map +1 -0
  865. package/dist/core/projection/introduced.js +14 -0
  866. package/dist/core/projection/introduced.js.map +1 -0
  867. package/dist/core/provenance/findings.js +244 -0
  868. package/dist/core/provenance/findings.js.map +1 -0
  869. package/dist/core/provenance/git.js +201 -0
  870. package/dist/core/provenance/git.js.map +1 -0
  871. package/dist/core/provenance/gitq/moves.js +139 -0
  872. package/dist/core/provenance/gitq/moves.js.map +1 -0
  873. package/dist/core/provenance/gitq/vouched-ancestor.js +179 -0
  874. package/dist/core/provenance/gitq/vouched-ancestor.js.map +1 -0
  875. package/dist/core/provenance/sample/scope.js +238 -0
  876. package/dist/core/provenance/sample/scope.js.map +1 -0
  877. package/dist/core/provenance/sample/sections.js +61 -0
  878. package/dist/core/provenance/sample/sections.js.map +1 -0
  879. package/dist/core/provenance/sources.js +280 -0
  880. package/dist/core/provenance/sources.js.map +1 -0
  881. package/dist/core/provenance/stamp.js +220 -0
  882. package/dist/core/provenance/stamp.js.map +1 -0
  883. package/dist/core/provenance/walk.js +157 -0
  884. package/dist/core/provenance/walk.js.map +1 -0
  885. package/dist/core/repo/authored/paths.js +210 -0
  886. package/dist/core/repo/authored/paths.js.map +1 -0
  887. package/dist/core/repo/entries.js +126 -0
  888. package/dist/core/repo/entries.js.map +1 -0
  889. package/dist/core/repo/paths.js +322 -0
  890. package/dist/core/repo/paths.js.map +1 -0
  891. package/dist/core/repo/repo.js +308 -0
  892. package/dist/core/repo/repo.js.map +1 -0
  893. package/dist/core/repo/service-target.js +153 -0
  894. package/dist/core/repo/service-target.js.map +1 -0
  895. package/dist/core/repo/state.js +58 -0
  896. package/dist/core/repo/state.js.map +1 -0
  897. package/dist/core/repo/tree/find.js +61 -0
  898. package/dist/core/repo/tree/find.js.map +1 -0
  899. package/dist/core/repo/tree/fs.js +90 -0
  900. package/dist/core/repo/tree/fs.js.map +1 -0
  901. package/dist/core/repo/tree/marker.js +61 -0
  902. package/dist/core/repo/tree/marker.js.map +1 -0
  903. package/dist/core/repo/tree/render/body.js +258 -0
  904. package/dist/core/repo/tree/render/body.js.map +1 -0
  905. package/dist/core/repo/tree/render/projects.js +182 -0
  906. package/dist/core/repo/tree/render/projects.js.map +1 -0
  907. package/dist/core/repo/tree/render/service/header.js +125 -0
  908. package/dist/core/repo/tree/render/service/header.js.map +1 -0
  909. package/dist/core/repo/tree/render/service/peers.js +28 -0
  910. package/dist/core/repo/tree/render/service/peers.js.map +1 -0
  911. package/dist/core/repo/tree/render/service/view-id.js +67 -0
  912. package/dist/core/repo/tree/render/service/view-id.js.map +1 -0
  913. package/dist/core/repo/tree/render/service/views.js +78 -0
  914. package/dist/core/repo/tree/render/service/views.js.map +1 -0
  915. package/dist/core/repo/tree/render/stale.js +42 -0
  916. package/dist/core/repo/tree/render/stale.js.map +1 -0
  917. package/dist/core/repo/tree/render/text.js +84 -0
  918. package/dist/core/repo/tree/render/text.js.map +1 -0
  919. package/dist/core/repo/tree/render/views.js +293 -0
  920. package/dist/core/repo/tree/render/views.js.map +1 -0
  921. package/dist/core/repo/tree/walk.js +255 -0
  922. package/dist/core/repo/tree/walk.js.map +1 -0
  923. package/dist/core/results.js +146 -14
  924. package/dist/core/results.js.map +1 -1
  925. package/dist/core/scaffold/landscape.js +239 -0
  926. package/dist/core/scaffold/landscape.js.map +1 -0
  927. package/dist/core/scaffold/legacy.js +271 -0
  928. package/dist/core/scaffold/legacy.js.map +1 -0
  929. package/dist/core/scaffold/readme.js +84 -0
  930. package/dist/core/scaffold/readme.js.map +1 -0
  931. package/dist/core/staging/commit.js +252 -0
  932. package/dist/core/staging/commit.js.map +1 -0
  933. package/dist/core/staging/interrupted.js +96 -0
  934. package/dist/core/staging/interrupted.js.map +1 -0
  935. package/dist/core/staging/lock.js +268 -0
  936. package/dist/core/staging/lock.js.map +1 -0
  937. package/dist/core/staging/recovery/finding.js +35 -0
  938. package/dist/core/staging/recovery/finding.js.map +1 -0
  939. package/dist/core/staging/recovery/intent.js +95 -0
  940. package/dist/core/staging/recovery/intent.js.map +1 -0
  941. package/dist/core/staging/recovery/recover.js +204 -0
  942. package/dist/core/staging/recovery/recover.js.map +1 -0
  943. package/dist/core/staging/recovery/residue.js +62 -0
  944. package/dist/core/staging/recovery/residue.js.map +1 -0
  945. package/dist/core/staging/snapshot/manifest.js +188 -0
  946. package/dist/core/staging/snapshot/manifest.js.map +1 -0
  947. package/dist/core/staging/snapshot/snapshot.js +196 -0
  948. package/dist/core/staging/snapshot/snapshot.js.map +1 -0
  949. package/dist/core/staging/txn/forward.js +181 -0
  950. package/dist/core/staging/txn/forward.js.map +1 -0
  951. package/dist/core/staging/txn/journal.js +139 -0
  952. package/dist/core/staging/txn/journal.js.map +1 -0
  953. package/dist/core/staging/txn/transaction.js +75 -0
  954. package/dist/core/staging/txn/transaction.js.map +1 -0
  955. package/dist/core/staging/writes.js +113 -0
  956. package/dist/core/staging/writes.js.map +1 -0
  957. package/dist/core/status/actions/execution.js +60 -0
  958. package/dist/core/status/actions/execution.js.map +1 -0
  959. package/dist/core/status/contracts.js +126 -0
  960. package/dist/core/status/contracts.js.map +1 -0
  961. package/dist/core/status/feature/artifacts.js +196 -0
  962. package/dist/core/status/feature/artifacts.js.map +1 -0
  963. package/dist/core/status/feature/feature.js +214 -0
  964. package/dist/core/status/feature/feature.js.map +1 -0
  965. package/dist/core/status/feature/next.js +163 -0
  966. package/dist/core/status/feature/next.js.map +1 -0
  967. package/dist/core/status/feature/state.js +21 -0
  968. package/dist/core/status/feature/state.js.map +1 -0
  969. package/dist/core/status/feature/words.js +96 -0
  970. package/dist/core/status/feature/words.js.map +1 -0
  971. package/dist/core/status/fleet/fleet.js +216 -0
  972. package/dist/core/status/fleet/fleet.js.map +1 -0
  973. package/dist/core/status/fleet/next.js +302 -0
  974. package/dist/core/status/fleet/next.js.map +1 -0
  975. package/dist/core/status/interrupted.js +97 -0
  976. package/dist/core/status/interrupted.js.map +1 -0
  977. package/dist/core/status/report.js +31 -0
  978. package/dist/core/status/report.js.map +1 -0
  979. package/dist/core/status/scan.js +41 -0
  980. package/dist/core/status/scan.js.map +1 -0
  981. package/dist/core/status/verification.js +216 -0
  982. package/dist/core/status/verification.js.map +1 -0
  983. package/dist/core/tasks/packet.js +199 -0
  984. package/dist/core/tasks/packet.js.map +1 -0
  985. package/dist/core/tasks/record.js +43 -0
  986. package/dist/core/tasks/record.js.map +1 -0
  987. package/dist/core/tasks/sources.js +181 -0
  988. package/dist/core/tasks/sources.js.map +1 -0
  989. package/dist/core/tasks/stamps.js +76 -0
  990. package/dist/core/tasks/stamps.js.map +1 -0
  991. package/dist/core/tasks/unit.js +0 -0
  992. package/dist/core/tasks/unit.js.map +1 -0
  993. package/dist/core/usecases/capability.js +166 -0
  994. package/dist/core/usecases/capability.js.map +1 -0
  995. package/dist/core/usecases/delta/claims.js +140 -0
  996. package/dist/core/usecases/delta/claims.js.map +1 -0
  997. package/dist/core/usecases/delta/flows.js +101 -0
  998. package/dist/core/usecases/delta/flows.js.map +1 -0
  999. package/dist/core/usecases/delta/modified.js +315 -0
  1000. package/dist/core/usecases/delta/modified.js.map +1 -0
  1001. package/dist/core/usecases/delta/overlay.js +76 -0
  1002. package/dist/core/usecases/delta/overlay.js.map +1 -0
  1003. package/dist/core/usecases/fleet.js +296 -0
  1004. package/dist/core/usecases/fleet.js.map +1 -0
  1005. package/dist/core/usecases/grade/capability-tag.js +93 -0
  1006. package/dist/core/usecases/grade/capability-tag.js.map +1 -0
  1007. package/dist/core/usecases/grade/feature.js +88 -0
  1008. package/dist/core/usecases/grade/feature.js.map +1 -0
  1009. package/dist/core/usecases/grade/requirement-tag.js +94 -0
  1010. package/dist/core/usecases/grade/requirement-tag.js.map +1 -0
  1011. package/dist/core/usecases/grade/steps.js +266 -0
  1012. package/dist/core/usecases/grade/steps.js.map +1 -0
  1013. package/dist/core/usecases/grade/usecases.js +112 -0
  1014. package/dist/core/usecases/grade/usecases.js.map +1 -0
  1015. package/dist/core/usecases/operations.js +123 -0
  1016. package/dist/core/usecases/operations.js.map +1 -0
  1017. package/dist/core/usecases/place.js +44 -0
  1018. package/dist/core/usecases/place.js.map +1 -0
  1019. package/dist/core/usecases/service/exclude.js +119 -0
  1020. package/dist/core/usecases/service/exclude.js.map +1 -0
  1021. package/dist/core/usecases/service/flows.js +164 -0
  1022. package/dist/core/usecases/service/flows.js.map +1 -0
  1023. package/dist/core/usecases/suites/participants.js +83 -0
  1024. package/dist/core/usecases/suites/participants.js.map +1 -0
  1025. package/dist/core/usecases/suites/suites.js +45 -0
  1026. package/dist/core/usecases/suites/suites.js.map +1 -0
  1027. package/dist/core/usecases/touch.js +101 -0
  1028. package/dist/core/usecases/touch.js.map +1 -0
  1029. package/dist/core/verify/answers.js +180 -0
  1030. package/dist/core/verify/answers.js.map +1 -0
  1031. package/dist/core/verify/build.js +170 -0
  1032. package/dist/core/verify/build.js.map +1 -0
  1033. package/dist/core/verify/checklist.js +259 -0
  1034. package/dist/core/verify/checklist.js.map +1 -0
  1035. package/dist/core/verify/claims/identity.js +61 -0
  1036. package/dist/core/verify/claims/identity.js.map +1 -0
  1037. package/dist/core/verify/cross/diff.js +97 -0
  1038. package/dist/core/verify/cross/diff.js.map +1 -0
  1039. package/dist/core/verify/evidence/contract.js +169 -0
  1040. package/dist/core/verify/evidence/contract.js.map +1 -0
  1041. package/dist/core/verify/location.js +67 -0
  1042. package/dist/core/verify/location.js.map +1 -0
  1043. package/dist/core/verify/pins/lint.js +158 -0
  1044. package/dist/core/verify/pins/lint.js.map +1 -0
  1045. package/dist/core/verify/pins/pin.js +95 -0
  1046. package/dist/core/verify/pins/pin.js.map +1 -0
  1047. package/dist/core/verify/read/file.js +224 -0
  1048. package/dist/core/verify/read/file.js.map +1 -0
  1049. package/dist/core/verify/read/shape.js +169 -0
  1050. package/dist/core/verify/read/shape.js.map +1 -0
  1051. package/dist/core/verify/read/union.js +105 -0
  1052. package/dist/core/verify/read/union.js.map +1 -0
  1053. package/dist/core/verify/record.js +165 -0
  1054. package/dist/core/verify/record.js.map +1 -0
  1055. package/dist/core/verify/store/commit.js +99 -0
  1056. package/dist/core/verify/store/commit.js.map +1 -0
  1057. package/dist/core/verify/store/render.js +61 -0
  1058. package/dist/core/verify/store/render.js.map +1 -0
  1059. package/dist/core/vocabulary/health.js +91 -0
  1060. package/dist/core/vocabulary/health.js.map +1 -0
  1061. package/dist/core/vocabulary/issue.js +59 -0
  1062. package/dist/core/vocabulary/issue.js.map +1 -0
  1063. package/dist/core/vocabulary/maturity.js +216 -0
  1064. package/dist/core/vocabulary/maturity.js.map +1 -0
  1065. package/dist/core/vocabulary/report.js +90 -0
  1066. package/dist/core/vocabulary/report.js.map +1 -0
  1067. package/dist/core/vocabulary/steps.js +266 -0
  1068. package/dist/core/vocabulary/steps.js.map +1 -0
  1069. package/dist/core/workspace/discover.js +239 -0
  1070. package/dist/core/workspace/discover.js.map +1 -0
  1071. package/dist/core/workspace/render.js +52 -0
  1072. package/dist/core/workspace/render.js.map +1 -0
  1073. package/examples/README.md +232 -0
  1074. package/examples/docs/architecture/adrs/0001-transactional-outbox.md +33 -0
  1075. package/examples/docs/architecture/capabilities.yaml +31 -0
  1076. package/examples/docs/architecture/landscape.likec4 +336 -0
  1077. package/examples/docs/architecture/obligations.yaml +23 -0
  1078. package/examples/docs/architecture/permissions.yaml +50 -0
  1079. package/examples/docs/architecture/services.likec4 +70 -0
  1080. package/examples/docs/architecture/subsystems.likec4 +18 -0
  1081. package/examples/docs/architecture/usecases/order-notification.likec4 +74 -0
  1082. package/examples/docs/capabilities/checkout/spec.md +55 -0
  1083. package/examples/docs/capabilities/identity/tokens/spec.md +42 -0
  1084. package/examples/docs/capabilities/order-notifications/spec.md +43 -0
  1085. package/examples/docs/features/FEAT-101-payment-splitting/adrs/0001-dedicated-split-service.md +18 -0
  1086. package/examples/docs/features/FEAT-101-payment-splitting/delta.likec4 +94 -0
  1087. package/examples/docs/features/FEAT-101-payment-splitting/intent.md +44 -0
  1088. package/examples/docs/features/FEAT-101-payment-splitting/specs/checkout-web/spec.md +21 -0
  1089. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-service/asyncapi.yaml +132 -0
  1090. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-service/spec.md +36 -0
  1091. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/arch.spec.md +40 -0
  1092. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/openapi.yaml +116 -0
  1093. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/spec.md +55 -0
  1094. package/examples/docs/features/FEAT-112-retire-order-v1/intent.md +35 -0
  1095. package/examples/docs/features/FEAT-112-retire-order-v1/specs/order-service/openapi.yaml +31 -0
  1096. package/examples/docs/features/FEAT-112-retire-order-v1/specs/order-service/spec.md +17 -0
  1097. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/architecture/landscape.likec4 +253 -0
  1098. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/services/order-service/spec.md +121 -0
  1099. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/services/payment-service/openapi.yaml +111 -0
  1100. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/services/payment-service/spec.md +58 -0
  1101. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/manifest.json +32 -0
  1102. package/examples/docs/features/archive/FEAT-088-refunds/adrs/0001-refunds-stay-in-payment-service.md +26 -0
  1103. package/examples/docs/features/archive/FEAT-088-refunds/delta.likec4 +28 -0
  1104. package/examples/docs/features/archive/FEAT-088-refunds/intent.md +26 -0
  1105. package/examples/docs/features/archive/FEAT-088-refunds/specs/order-service/spec.md +37 -0
  1106. package/examples/docs/features/archive/FEAT-088-refunds/specs/payment-service/openapi.yaml +73 -0
  1107. package/examples/docs/features/archive/FEAT-088-refunds/specs/payment-service/spec.md +23 -0
  1108. package/examples/docs/features/archive/FEAT-088-refunds/verification.yaml +76 -0
  1109. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/architecture/landscape.likec4 +275 -0
  1110. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/payment-service/asyncapi.yaml +96 -0
  1111. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/payment-service/spec.md +82 -0
  1112. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/platform/notification-service/asyncapi.yaml +164 -0
  1113. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/platform/notification-service/spec.md +91 -0
  1114. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/manifest.json +46 -0
  1115. package/examples/docs/features/archive/FEAT-120-refund-notification/delta.likec4 +36 -0
  1116. package/examples/docs/features/archive/FEAT-120-refund-notification/intent.md +22 -0
  1117. package/examples/docs/features/archive/FEAT-120-refund-notification/scenario-report.json +10 -0
  1118. package/examples/docs/features/archive/FEAT-120-refund-notification/specs/notification-service/asyncapi.yaml +208 -0
  1119. package/examples/docs/features/archive/FEAT-120-refund-notification/specs/notification-service/spec.md +24 -0
  1120. package/examples/docs/features/archive/FEAT-120-refund-notification/specs/payment-service/asyncapi.yaml +137 -0
  1121. package/examples/docs/features/archive/FEAT-120-refund-notification/specs/payment-service/spec.md +31 -0
  1122. package/examples/docs/features/archive/FEAT-120-refund-notification/verification.yaml +84 -0
  1123. package/examples/docs/glossary/order.md +15 -0
  1124. package/examples/docs/glossary/payments/authorization.md +14 -0
  1125. package/examples/docs/likec4.config.json +8 -0
  1126. package/examples/docs/loam.json +3 -0
  1127. package/examples/docs/services/checkout-web/model.likec4 +92 -0
  1128. package/examples/docs/services/checkout-web/spec.md +91 -0
  1129. package/examples/docs/services/checkout-web/ui/pages/checkout.page.yaml +40 -0
  1130. package/examples/docs/services/checkout-web/ui/pages/order-status.page.yaml +24 -0
  1131. package/examples/docs/services/checkout-web/ui/pages/split-payment.page.yaml +26 -0
  1132. package/examples/docs/services/order-service/adrs/0001-orchestrated-order-lifecycle.md +52 -0
  1133. package/examples/docs/services/order-service/arch.spec.md +134 -0
  1134. package/examples/docs/services/order-service/asyncapi.yaml +109 -0
  1135. package/examples/docs/services/order-service/health.yaml +57 -0
  1136. package/examples/docs/services/order-service/model.likec4 +126 -0
  1137. package/examples/docs/services/order-service/openapi.yaml +257 -0
  1138. package/examples/docs/services/order-service/runbook.md +62 -0
  1139. package/examples/docs/services/order-service/spec.md +134 -0
  1140. package/examples/docs/services/payment-service/adrs/0001-payments-outbox.md +18 -0
  1141. package/examples/docs/services/payment-service/adrs/0002-idempotency-keys-on-authorization.md +27 -0
  1142. package/examples/docs/services/payment-service/arch.spec.md +76 -0
  1143. package/examples/docs/services/payment-service/asyncapi.yaml +130 -0
  1144. package/examples/docs/services/payment-service/health.yaml +39 -0
  1145. package/examples/docs/services/payment-service/model.likec4 +68 -0
  1146. package/examples/docs/services/payment-service/openapi.yaml +151 -0
  1147. package/examples/docs/services/payment-service/runbook.md +37 -0
  1148. package/examples/docs/services/payment-service/spec.md +88 -0
  1149. package/examples/docs/services/platform/identity-service/adrs/0001-token-introspection-over-local-validation.md +60 -0
  1150. package/examples/docs/services/platform/identity-service/arch.spec.md +120 -0
  1151. package/examples/docs/services/platform/identity-service/health.yaml +70 -0
  1152. package/examples/docs/services/platform/identity-service/model.likec4 +81 -0
  1153. package/examples/docs/services/platform/identity-service/openapi.yaml +197 -0
  1154. package/examples/docs/services/platform/identity-service/runbook.md +95 -0
  1155. package/examples/docs/services/platform/identity-service/spec.md +119 -0
  1156. package/examples/docs/services/platform/notification-service/asyncapi.yaml +200 -0
  1157. package/examples/docs/services/platform/notification-service/health.yaml +40 -0
  1158. package/examples/docs/services/platform/notification-service/model.likec4 +97 -0
  1159. package/examples/docs/services/platform/notification-service/runbook.md +48 -0
  1160. package/examples/docs/services/platform/notification-service/spec.md +112 -0
  1161. package/examples/docs/services/platform/subsystem.yaml +2 -0
  1162. package/examples/fleet.yaml +57 -0
  1163. package/package.json +19 -6
  1164. package/dist/commands/adopt.js +0 -240
  1165. package/dist/commands/adopt.js.map +0 -1
  1166. package/dist/commands/archive.js +0 -1313
  1167. package/dist/commands/archive.js.map +0 -1
  1168. package/dist/commands/delta.js +0 -388
  1169. package/dist/commands/delta.js.map +0 -1
  1170. package/dist/commands/docs-repo-gate.js.map +0 -1
  1171. package/dist/commands/format.js +0 -17
  1172. package/dist/commands/format.js.map +0 -1
  1173. package/dist/commands/gherkin.js +0 -309
  1174. package/dist/commands/gherkin.js.map +0 -1
  1175. package/dist/commands/init.js.map +0 -1
  1176. package/dist/commands/list.js +0 -295
  1177. package/dist/commands/list.js.map +0 -1
  1178. package/dist/commands/migrate-openspec.js +0 -950
  1179. package/dist/commands/migrate-openspec.js.map +0 -1
  1180. package/dist/commands/new.js +0 -413
  1181. package/dist/commands/new.js.map +0 -1
  1182. package/dist/commands/rebase.js +0 -356
  1183. package/dist/commands/rebase.js.map +0 -1
  1184. package/dist/commands/show.js +0 -320
  1185. package/dist/commands/show.js.map +0 -1
  1186. package/dist/commands/status.js +0 -262
  1187. package/dist/commands/status.js.map +0 -1
  1188. package/dist/commands/unarchive.js +0 -317
  1189. package/dist/commands/unarchive.js.map +0 -1
  1190. package/dist/commands/validate.js +0 -1773
  1191. package/dist/commands/validate.js.map +0 -1
  1192. package/dist/commands/verify.js +0 -775
  1193. package/dist/commands/verify.js.map +0 -1
  1194. package/dist/commands/vouch.js +0 -421
  1195. package/dist/commands/vouch.js.map +0 -1
  1196. package/dist/core/agent.js +0 -2173
  1197. package/dist/core/agent.js.map +0 -1
  1198. package/dist/core/agents-stamp.js.map +0 -1
  1199. package/dist/core/arch.js +0 -130
  1200. package/dist/core/arch.js.map +0 -1
  1201. package/dist/core/asyncapi.js +0 -253
  1202. package/dist/core/asyncapi.js.map +0 -1
  1203. package/dist/core/brief.js +0 -755
  1204. package/dist/core/brief.js.map +0 -1
  1205. package/dist/core/coherence.js +0 -577
  1206. package/dist/core/coherence.js.map +0 -1
  1207. package/dist/core/concurrency.js.map +0 -1
  1208. package/dist/core/config.js.map +0 -1
  1209. package/dist/core/delta.js +0 -476
  1210. package/dist/core/delta.js.map +0 -1
  1211. package/dist/core/dependencies.js +0 -356
  1212. package/dist/core/dependencies.js.map +0 -1
  1213. package/dist/core/doctor.js +0 -596
  1214. package/dist/core/doctor.js.map +0 -1
  1215. package/dist/core/document-bytes.js.map +0 -1
  1216. package/dist/core/explore.js +0 -225
  1217. package/dist/core/explore.js.map +0 -1
  1218. package/dist/core/frontmatter.js.map +0 -1
  1219. package/dist/core/gherkin.js +0 -463
  1220. package/dist/core/gherkin.js.map +0 -1
  1221. package/dist/core/health.js +0 -67
  1222. package/dist/core/health.js.map +0 -1
  1223. package/dist/core/ids.js +0 -122
  1224. package/dist/core/ids.js.map +0 -1
  1225. package/dist/core/issue.js +0 -9
  1226. package/dist/core/issue.js.map +0 -1
  1227. package/dist/core/json.js +0 -74
  1228. package/dist/core/json.js.map +0 -1
  1229. package/dist/core/likec4.js +0 -489
  1230. package/dist/core/likec4.js.map +0 -1
  1231. package/dist/core/maturity.js +0 -66
  1232. package/dist/core/maturity.js.map +0 -1
  1233. package/dist/core/openapi-merge.js +0 -552
  1234. package/dist/core/openapi-merge.js.map +0 -1
  1235. package/dist/core/openapi.js.map +0 -1
  1236. package/dist/core/openspec-inventory.js +0 -1440
  1237. package/dist/core/openspec-inventory.js.map +0 -1
  1238. package/dist/core/path-safety.js.map +0 -1
  1239. package/dist/core/provenance.js +0 -787
  1240. package/dist/core/provenance.js.map +0 -1
  1241. package/dist/core/records.js.map +0 -1
  1242. package/dist/core/repo.js +0 -438
  1243. package/dist/core/repo.js.map +0 -1
  1244. package/dist/core/report.js +0 -47
  1245. package/dist/core/report.js.map +0 -1
  1246. package/dist/core/spec.js +0 -505
  1247. package/dist/core/spec.js.map +0 -1
  1248. package/dist/core/staging.js +0 -890
  1249. package/dist/core/staging.js.map +0 -1
  1250. package/dist/core/status.js +0 -1132
  1251. package/dist/core/status.js.map +0 -1
  1252. package/dist/core/steps.js +0 -72
  1253. package/dist/core/steps.js.map +0 -1
  1254. package/dist/core/verify.js +0 -807
  1255. package/dist/core/verify.js.map +0 -1
  1256. package/dist/core/version.js.map +0 -1
@@ -0,0 +1,131 @@
1
+ /**
2
+ * The revival candidates: every identity — an operationId, or a message
3
+ * name — that the contract the archive would WRITE answers at an address
4
+ * the living contract does not. Split from ./revived.ts, which grades them,
5
+ * along the seam between the two questions: what the merge would leave, and
6
+ * which of it an archived feature took out.
7
+ *
8
+ * The question is asked of the contract the archive would WRITE: the
9
+ * archive's own merge runs over the two texts (../merged.ts), and where the
10
+ * result answers each operationId and message name is compared with where
11
+ * the living contract answers it now. This once re-derived the merge from
12
+ * the delta, case by case — any removal marker naming the id excused a quote,
13
+ * another NAMED operation at the id's address made a swap — and every review
14
+ * found a shape the derivation got wrong: a marker at an address the id never
15
+ * lived at (it deletes nothing, so the second address stays), a replacement
16
+ * with no operationId (it replaces all the same, so there is no second
17
+ * address), a retirement whose address became a second one when a later
18
+ * feature re-added the id elsewhere. The merged contract answers each of
19
+ * them by construction.
20
+ *
21
+ * The same comparison read the other way round answers the removal gate's
22
+ * blind spot: a living operationId the merged contract answers nowhere,
23
+ * with no marker naming it, was taken out by an overwrite (`Displacement`).
24
+ */
25
+ import { existsSync } from "node:fs";
26
+ import { readOr } from "../../../openapi/contract-text.js";
27
+ import { slotKey } from "../../../asyncapi/digest.js";
28
+ import { operationAddress } from "../archived.js";
29
+ import { mergedOpenapiDoc } from "../merged.js";
30
+ const opsPlaced = (ops) => ops.filter((op) => !op.remove).map((op) => [op.id, operationAddress(op)]);
31
+ const messagesPlaced = (all) => all.filter((m) => m.remove !== true).map((m) => [m.name, m.slot]);
32
+ /**
33
+ * Every (identity, address) the merged contract has and the living one lacks,
34
+ * in the merged contract's order. `unnamed` holds the living addresses an
35
+ * entry with no identity stands at — an operation with no operationId; the
36
+ * event axis has none.
37
+ */
38
+ function arrivals(living, merged, markable, unnamed = new Set()) {
39
+ const where = (all, id) => all.filter(([i]) => i === id).map(([, at]) => at);
40
+ return merged.flatMap(([id, at]) => {
41
+ const livesAt = where(living, id);
42
+ if (livesAt.includes(at))
43
+ return [];
44
+ const besides = where(merged, id).filter((b) => b !== at);
45
+ const replaces = living.find(([, address]) => address === at)?.[0];
46
+ const occupant = replaces !== undefined ? { replaces } : unnamed.has(at) ? { replacesUnnamed: true } : {};
47
+ return [{ id, at, livesAt, besides, markable: besides.every((b) => markable(b, livesAt)), ...occupant }];
48
+ });
49
+ }
50
+ /**
51
+ * The OpenAPI candidates: the merged contract against the living one. An
52
+ * unreadable side proves nothing (`openapi.invalid` owns it), nor does a text
53
+ * that does not decode, so either yields none; neither does a merge the
54
+ * archive refuses (`merge-failed`, which `--approve` cannot pass). The merge
55
+ * runs only when some definition in the delta is not living at its own
56
+ * address already: nothing else the merge writes can be new, so a delta that
57
+ * only restates what stands has nothing to compare and never pays for it.
58
+ * The displacements ride the same run, and need one more trigger: a named
59
+ * operation replacing a living one is itself a definition not living there,
60
+ * but one written with no operationId at a living operation's address is
61
+ * not, and it replaces that operation all the same.
62
+ */
63
+ export async function operationArrivals(sides, context) {
64
+ const none = { operations: [], displaced: [] };
65
+ const { featPath, featDoc, livingPath, livingDoc, service } = sides;
66
+ if (featDoc.unreadable || livingDoc.unreadable)
67
+ return none;
68
+ const living = opsPlaced(livingDoc.ops);
69
+ const named = new Set(living.map(([, at]) => at));
70
+ const overNamed = featDoc.anonymousOps.some((op) => named.has(operationAddress(op)));
71
+ if (arrivals(living, opsPlaced(featDoc.ops), () => true).length === 0 && !overNamed)
72
+ return none;
73
+ const featureText = sides.featText ?? (await readOr(featPath, context));
74
+ const livingExists = existsSync(livingPath);
75
+ const livingText = livingExists ? await readOr(livingPath, context) : undefined;
76
+ if (featureText === undefined || (livingExists && livingText === undefined))
77
+ return none;
78
+ const merged = mergedOpenapiDoc({ livingText, livingDoc, featureText, service });
79
+ if (merged === undefined)
80
+ return none;
81
+ // Every address the delta spells — a removal marker, an operation, named
82
+ // or not — holds what the delta spells there, so no marker can stand
83
+ // beside it.
84
+ const spelled = new Set([...featDoc.ops, ...featDoc.anonymousRemovals, ...featDoc.anonymousOps].map(operationAddress));
85
+ const placed = opsPlaced(merged.ops);
86
+ const unnamed = new Set(livingDoc.anonymousOps.map(operationAddress));
87
+ return {
88
+ operations: arrivals(living, placed, (b, livesAt) => livesAt.includes(b) && !spelled.has(b), unnamed),
89
+ displaced: displacements(living, placed, new Set(featDoc.ops.filter((op) => op.remove).map((op) => op.id))),
90
+ };
91
+ }
92
+ /**
93
+ * The living identities the merged contract answers nowhere, minus every one
94
+ * a removal marker names: those are the removal gate's already — retired,
95
+ * relocated, or a marker the exactness checks refuse — and grading them here
96
+ * too would file one loss under two findings.
97
+ */
98
+ function displacements(living, merged, marked) {
99
+ const answered = new Set(merged.map(([id]) => id));
100
+ const gone = [...new Set(living.map(([id]) => id))].filter((id) => !answered.has(id) && !marked.has(id));
101
+ return gone.map((id) => ({
102
+ id,
103
+ at: living.filter(([i]) => i === id).map(([, address]) => {
104
+ const by = merged.find(([, at]) => at === address)?.[0];
105
+ return by === undefined ? { address } : { address, by };
106
+ }),
107
+ }));
108
+ }
109
+ /**
110
+ * The event axis's candidates. A message is graded by its NAME, not by its
111
+ * key: the name is what every join reads, so a retired message redeclared
112
+ * under a new key is the same message back, and a new message reusing a dead
113
+ * key is not. A living side that does not answer (./event-pair.ts) proves
114
+ * nothing, so it yields none; a merge the pair refuses grades no message.
115
+ * The slots are read off the delta, and they are the merged contract's new
116
+ * slots exactly: the merge writes every slot the delta declares, bar a quote,
117
+ * which has a living counterpart.
118
+ */
119
+ export function eventArrivals(read) {
120
+ const { featDoc, featSlots, livingDoc, livingSlots } = read;
121
+ if (!read.livingAnswers || featDoc.unreadable || livingDoc.unreadable)
122
+ return { slots: [], messages: [] };
123
+ const slots = featSlots.filter((s) => !s.remove && s.section !== "components.messages" && !livingSlots.has(slotKey(s)));
124
+ const merged = read.merged();
125
+ if (merged === undefined)
126
+ return { slots, messages: [] };
127
+ const spelled = new Set(featSlots.filter((s) => s.section === "components.messages").map((s) => `${s.section}.${s.key}`));
128
+ const markable = (b, livesAt) => b.startsWith("channels.") || (livesAt.includes(b) && !spelled.has(b));
129
+ return { slots, messages: arrivals(messagesPlaced(livingDoc.messages), messagesPlaced(merged.doc.messages), markable), mergedRoot: merged.root };
130
+ }
131
+ //# sourceMappingURL=arrivals.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"arrivals.js","sourceRoot":"","sources":["../../../../../src/core/coherence/retired/revival/arrivals.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The revival candidates: every identity — an operationId, or a message\n * name — that the contract the archive would WRITE answers at an address\n * the living contract does not. Split from ./revived.ts, which grades them,\n * along the seam between the two questions: what the merge would leave, and\n * which of it an archived feature took out.\n *\n * The question is asked of the contract the archive would WRITE: the\n * archive's own merge runs over the two texts (../merged.ts), and where the\n * result answers each operationId and message name is compared with where\n * the living contract answers it now. This once re-derived the merge from\n * the delta, case by case — any removal marker naming the id excused a quote,\n * another NAMED operation at the id's address made a swap — and every review\n * found a shape the derivation got wrong: a marker at an address the id never\n * lived at (it deletes nothing, so the second address stays), a replacement\n * with no operationId (it replaces all the same, so there is no second\n * address), a retirement whose address became a second one when a later\n * feature re-added the id elsewhere. The merged contract answers each of\n * them by construction.\n *\n * The same comparison read the other way round answers the removal gate's\n * blind spot: a living operationId the merged contract answers nowhere,\n * with no marker naming it, was taken out by an overwrite (`Displacement`).\n */\nimport { existsSync } from \"node:fs\";\nimport type { OpenapiDoc, Operation } from \"../../../openapi/doc.js\";\nimport { readOr } from \"../../../openapi/contract-text.js\";\nimport { slotKey, type AsyncapiSlot } from \"../../../asyncapi/digest.js\";\nimport type { EventMessage } from \"../../../asyncapi/model.js\";\nimport type { FleetContext } from \"../../../fleet-context.js\";\nimport { operationAddress } from \"../archived.js\";\nimport type { EventPairRead, PairSides } from \"../event-pair.js\";\nimport { mergedOpenapiDoc } from \"../merged.js\";\n\n/**\n * One identity — an operationId, or a message name — that the merged\n * contract answers at an address the living contract does not. The only\n * shape a revival can take: everything else the merge writes is already\n * living where it stands.\n */\nexport interface Arrival {\n id: string;\n /** The new address: `METHOD /path`, or the slot a message is declared in. */\n at: string;\n /** Where the living contract answers the identity now — empty for nowhere. */\n livesAt: string[];\n /** Every OTHER address the merged contract answers it at. */\n besides: string[];\n /**\n * What the living contract answers at `at` now — another operationId, or\n * another message name — which the merge replaces there: a slot holds one\n * entry. Absent where nothing does. A finding that called such an address\n * one \"the living contract no longer has\" sent its reader to a remedy that\n * deleted the other entry with nothing naming it.\n */\n replaces?: string;\n /**\n * Set where what the living contract answers at `at` is an operation\n * written with NO operationId: the merge replaces it there all the same,\n * and no id can name it, so `replaces` stays absent. The reader dropped\n * such operations outright once, and the finding called their address one\n * \"the living contract no longer has\" — the very defect `replaces` was\n * added for, through the one door it left open.\n */\n replacesUnnamed?: true;\n /**\n * Can this same delta take it out of every one of `besides`? A living\n * address the delta spells nothing at takes a removal marker; a declaration\n * inline under a channel is taken out by restating or retiring the channel\n * (`moveBackRemedy`). A key the delta already spells holds what it spells,\n * and a marker cannot be written beside it — the remedy that once named\n * one there could not be followed.\n */\n markable: boolean;\n}\n\n/**\n * A living operationId the merged contract answers NOWHERE although no\n * removal marker in the delta names it: another operation now stands at\n * every address it held, so the merge — which writes per method and path —\n * replaced it there. The removal gate's own question\n * (`openapi.remove-op-consumed`, ../../consumed/operations.ts) asked of the one way to\n * take an operation out of a contract that carries no marker for it to read:\n * a delta defining\n * `fetchOrder` where `getOrder` lives archived at exit 0 while a landscape\n * edge still called `getOrder`, and the next `validate` reported the\n * contract broken (`spine.op-undefined`) on a repository nobody in the\n * feature touched. Read off the merged contract, never re-derived from the\n * delta, for this module's reason.\n */\nexport interface Displacement {\n /** The living operationId the contract the archive would write no longer defines. */\n id: string;\n /**\n * Every address it lives at now, with what the merged contract answers\n * there — the operationId that replaces it, or nothing for an operation\n * written without one, which the reader cannot name.\n */\n at: ReadonlyArray<{ address: string; by?: string }>;\n}\n\n/** What the merged contract answers that the living one does not, and what it stops answering. */\nexport interface OperationArrivals {\n /** Every (operationId, address) the merged contract has and the living one lacks — the revival candidates. */\n operations: Arrival[];\n /** Every living operationId the merged contract answers nowhere, no removal marker naming it. */\n displaced: Displacement[];\n}\n\n/** An identity and one address a contract answers it at. */\ntype Placed = readonly [id: string, at: string];\n\nconst opsPlaced = (ops: readonly Operation[]): Placed[] => ops.filter((op) => !op.remove).map((op) => [op.id, operationAddress(op)]);\nconst messagesPlaced = (all: readonly EventMessage[]): Placed[] => all.filter((m) => m.remove !== true).map((m) => [m.name, m.slot]);\n\n/**\n * Every (identity, address) the merged contract has and the living one lacks,\n * in the merged contract's order. `unnamed` holds the living addresses an\n * entry with no identity stands at — an operation with no operationId; the\n * event axis has none.\n */\nfunction arrivals(\n living: readonly Placed[],\n merged: readonly Placed[],\n markable: (address: string, livesAt: readonly string[]) => boolean,\n unnamed: ReadonlySet<string> = new Set(),\n): Arrival[] {\n const where = (all: readonly Placed[], id: string): string[] => all.filter(([i]) => i === id).map(([, at]) => at);\n return merged.flatMap(([id, at]) => {\n const livesAt = where(living, id);\n if (livesAt.includes(at)) return [];\n const besides = where(merged, id).filter((b) => b !== at);\n const replaces = living.find(([, address]) => address === at)?.[0];\n const occupant = replaces !== undefined ? { replaces } : unnamed.has(at) ? { replacesUnnamed: true as const } : {};\n return [{ id, at, livesAt, besides, markable: besides.every((b) => markable(b, livesAt)), ...occupant }];\n });\n}\n\n/**\n * The OpenAPI candidates: the merged contract against the living one. An\n * unreadable side proves nothing (`openapi.invalid` owns it), nor does a text\n * that does not decode, so either yields none; neither does a merge the\n * archive refuses (`merge-failed`, which `--approve` cannot pass). The merge\n * runs only when some definition in the delta is not living at its own\n * address already: nothing else the merge writes can be new, so a delta that\n * only restates what stands has nothing to compare and never pays for it.\n * The displacements ride the same run, and need one more trigger: a named\n * operation replacing a living one is itself a definition not living there,\n * but one written with no operationId at a living operation's address is\n * not, and it replaces that operation all the same.\n */\nexport async function operationArrivals(sides: PairSides<OpenapiDoc>, context?: FleetContext): Promise<OperationArrivals> {\n const none: OperationArrivals = { operations: [], displaced: [] };\n const { featPath, featDoc, livingPath, livingDoc, service } = sides;\n if (featDoc.unreadable || livingDoc.unreadable) return none;\n const living = opsPlaced(livingDoc.ops);\n const named = new Set(living.map(([, at]) => at));\n const overNamed = featDoc.anonymousOps.some((op) => named.has(operationAddress(op)));\n if (arrivals(living, opsPlaced(featDoc.ops), () => true).length === 0 && !overNamed) return none;\n const featureText = sides.featText ?? (await readOr(featPath, context));\n const livingExists = existsSync(livingPath);\n const livingText = livingExists ? await readOr(livingPath, context) : undefined;\n if (featureText === undefined || (livingExists && livingText === undefined)) return none;\n const merged = mergedOpenapiDoc({ livingText, livingDoc, featureText, service });\n if (merged === undefined) return none;\n // Every address the delta spells — a removal marker, an operation, named\n // or not — holds what the delta spells there, so no marker can stand\n // beside it.\n const spelled = new Set([...featDoc.ops, ...featDoc.anonymousRemovals, ...featDoc.anonymousOps].map(operationAddress));\n const placed = opsPlaced(merged.ops);\n const unnamed = new Set(livingDoc.anonymousOps.map(operationAddress));\n return {\n operations: arrivals(living, placed, (b, livesAt) => livesAt.includes(b) && !spelled.has(b), unnamed),\n displaced: displacements(living, placed, new Set(featDoc.ops.filter((op) => op.remove).map((op) => op.id))),\n };\n}\n\n/**\n * The living identities the merged contract answers nowhere, minus every one\n * a removal marker names: those are the removal gate's already — retired,\n * relocated, or a marker the exactness checks refuse — and grading them here\n * too would file one loss under two findings.\n */\nfunction displacements(living: readonly Placed[], merged: readonly Placed[], marked: ReadonlySet<string>): Displacement[] {\n const answered = new Set(merged.map(([id]) => id));\n const gone = [...new Set(living.map(([id]) => id))].filter((id) => !answered.has(id) && !marked.has(id));\n return gone.map((id) => ({\n id,\n at: living.filter(([i]) => i === id).map(([, address]) => {\n const by = merged.find(([, at]) => at === address)?.[0];\n return by === undefined ? { address } : { address, by };\n }),\n }));\n}\n\n/** What an event delta brings that the living contract does not have. */\nexport interface EventArrivals {\n /** `channels` and `operations` slots whose key the living contract lacks — their identity IS the key. */\n slots: AsyncapiSlot[];\n /** Message names at slots the living contract does not declare them in — the operation axis's arrivals. */\n messages: Arrival[];\n /**\n * The merged contract's tree, where the move-back remedy follows a `$ref`\n * back to the channel holding it (`moveBackRemedy`) — absent where the\n * merge refused, and then no message is graded.\n */\n mergedRoot?: unknown;\n}\n\n/**\n * The event axis's candidates. A message is graded by its NAME, not by its\n * key: the name is what every join reads, so a retired message redeclared\n * under a new key is the same message back, and a new message reusing a dead\n * key is not. A living side that does not answer (./event-pair.ts) proves\n * nothing, so it yields none; a merge the pair refuses grades no message.\n * The slots are read off the delta, and they are the merged contract's new\n * slots exactly: the merge writes every slot the delta declares, bar a quote,\n * which has a living counterpart.\n */\nexport function eventArrivals(read: EventPairRead): EventArrivals {\n const { featDoc, featSlots, livingDoc, livingSlots } = read;\n if (!read.livingAnswers || featDoc.unreadable || livingDoc.unreadable) return { slots: [], messages: [] };\n const slots = featSlots.filter((s) => !s.remove && s.section !== \"components.messages\" && !livingSlots.has(slotKey(s)));\n const merged = read.merged();\n if (merged === undefined) return { slots, messages: [] };\n const spelled = new Set(featSlots.filter((s) => s.section === \"components.messages\").map((s) => `${s.section}.${s.key}`));\n const markable = (b: string, livesAt: readonly string[]): boolean =>\n b.startsWith(\"channels.\") || (livesAt.includes(b) && !spelled.has(b));\n return { slots, messages: arrivals(messagesPlaced(livingDoc.messages), messagesPlaced(merged.doc.messages), markable), mergedRoot: merged.root };\n}\n"]}
@@ -0,0 +1,297 @@
1
+ /**
2
+ * The revival findings: a feature delta that would bring back what an
3
+ * ARCHIVED feature took out of the living contract — an operation, slot or
4
+ * message it retired, or an address it moved one away from, which would put
5
+ * it back there beside where it lives now.
6
+ *
7
+ * `openapi.op-revived` and `asyncapi.slot-revived` — one code per axis, because
8
+ * a caller acts the same way whichever slot section came back. Both are a
9
+ * warning that GATES archive, `openapi.baseline-missing`'s doctrine: the
10
+ * document is legal, and re-adding a retired operation can be exactly what a
11
+ * feature means (a rollback of a retirement, a deprecation reversed), so
12
+ * `--approve` carries the call. What it must never be again is SILENT — the
13
+ * merge cannot tell a quote of a dead operation from an addition, and treated
14
+ * every one as an addition.
15
+ *
16
+ * The candidates — what the contract the archive would WRITE answers that
17
+ * the living one does not (./arrivals.ts) — are computed where both
18
+ * documents are already in hand, in the feature gate's two walks
19
+ * (../../declared.ts, ../../events/declared.ts), and only graded here, so
20
+ * the archive walk (../archived.ts) is paid for only when the merged
21
+ * contract answers something at an address the living one does not.
22
+ * `serviceRevivals` asks the same two functions per axis standalone, for
23
+ * `loam rebase`, which reads no gate — on the event axis through the gate's
24
+ * own reading of the pair (../event-pair.ts) — so the two can never grade one
25
+ * tree two ways.
26
+ */
27
+ import { existsSync } from "node:fs";
28
+ import { featureSpecPaths } from "../../../repo/paths.js";
29
+ import { locateServicePaths } from "../../../repo/service-target.js";
30
+ import { readOpenapi } from "../../../openapi/doc.js";
31
+ import { readAsyncapi } from "../../../asyncapi/read.js";
32
+ import { entriesOf } from "../../../asyncapi/digest.js";
33
+ import { collectRefs } from "../../../openapi/depth.js";
34
+ import { retiredKey } from "../archived.js";
35
+ import { readEventPair } from "../event-pair.js";
36
+ import { eventArrivals, operationArrivals } from "./arrivals.js";
37
+ /** The two remedies, spelled once: which one applies is the human's call, never loam's. */
38
+ const REMEDY = "Delete the quote if you only restated it; archive with --approve if the feature brings it back on purpose.";
39
+ /**
40
+ * The vacations that make one arrival a revival — undefined when it is none.
41
+ * Either the living contract answers the identity nowhere, and an archived
42
+ * feature retired it (anywhere: a retired operation re-added at a new path is
43
+ * the same operation back, and a message is its name wherever it is
44
+ * declared) or moved it away from this very address; or the merged contract
45
+ * answers it at two or more addresses, and an archived feature retired it at,
46
+ * or moved it away from, this very address — an old address resurrected
47
+ * beside the current one. An identity the living contract still holds that
48
+ * the merged contract answers at exactly one address — a move back, a swap,
49
+ * a replacement with no operationId — is never a revival, and neither is an
50
+ * address no archived feature vacated. One the living contract holds nowhere
51
+ * is the first case at one address too: this once said "exactly one address
52
+ * is never a revival" unqualified, and a quote of an address a move vacated,
53
+ * after a hand edit took the id out of where the move put it, is one.
54
+ *
55
+ * Any archived feature — the one asking is never among them: coherence
56
+ * grades only features in flight (status/feature/feature.ts), so a vacation
57
+ * bearing the asking feature's id is another directory carrying the same
58
+ * id, and as real as anyone's. Excluding it by id, as this once did, could
59
+ * only hide a revival.
60
+ */
61
+ function revivalOf({ at, livesAt, besides }, vacations) {
62
+ if (vacations === undefined)
63
+ return undefined;
64
+ const [first, ...rest] = vacations.filter((v) => livesAt.length === 0 ? v.to.length === 0 || v.at === at : besides.length > 0 && v.at === at);
65
+ return first === undefined ? undefined : [first, ...rest];
66
+ }
67
+ /** The operation arrivals that are revivals — each named for what happened, retired or vacated. */
68
+ export function revivedOperations(service, arrived, index) {
69
+ const issues = [];
70
+ for (const arrival of arrived) {
71
+ const by = revivalOf(arrival, index.operations.get(retiredKey(service, arrival.id)));
72
+ if (by === undefined)
73
+ continue;
74
+ const { id, at, livesAt, besides } = arrival;
75
+ const what = livesAt.length === 0
76
+ ? `'${id}' (${at}), ${broughtBack(by, replacing(arrival, "holds"))}`
77
+ // A second address, not the operation back: it is living, so the
78
+ // remedy is which address to drop — never "bring it back".
79
+ : `'${id}' at ${at}, ${occupant(arrival) === undefined ? "an address the living contract no longer has" : "an address it no longer lives at"} — ${vacators(by, " there")}${present(by, livesAt, "lives")}, and archiving this delta would put it back at ${at} beside ${besides.join(" and ")}: one operationId at ${count(besides.length + 1)} addresses.${replacing(arrival, "holds")} ${dropOne(arrival, `add a removal marker for '${id}' at ${besides.join(" and ")} to this same delta${keeping(arrival, "address")}`)}`;
80
+ issues.push({ severity: "warn", gates: true, code: "openapi.op-revived", subject: service, message: `${service}: this feature's openapi.yaml spells ${what}` });
81
+ }
82
+ return issues;
83
+ }
84
+ /**
85
+ * How a delta takes a message name OUT of the places it is declared — the
86
+ * move-back remedy, per place, toward wherever the message is moved back to
87
+ * (`to`). A `components.messages` key is a slot, and a removal marker there
88
+ * retires what it declares. A declaration INLINE under a channel is not: it
89
+ * is the channel slot's interior (SCHEMA.md), so a marker nested on it
90
+ * retires nothing — `asyncapi.remove-marker-inline`, and the deep strip
91
+ * publishes the message without the marker. This once said "retire it at
92
+ * channels.<ck>.messages.<mk>", a remedy that, followed exactly, changed
93
+ * nothing and drew a second refusal. The channel is the unit: restated with
94
+ * the message as a `$ref` (an upsert replaces the interior), or retired. The
95
+ * channel key is read the way the archive plan's remove-marker-inline
96
+ * message reads it, so the two name the same channel.
97
+ *
98
+ * A `components.messages` key is retired by its marker, but a channel (or an
99
+ * operation) of the contract the merge would leave (`root`) that still
100
+ * `$ref`s it would point at nothing: its send stops sending the message,
101
+ * `asyncapi.remove-message-consumed` where the fleet consumes it. This once
102
+ * said only "retire it at components.messages.<K2>", a remedy that, followed
103
+ * exactly, drew that error — so every slot still pointing there is named,
104
+ * to restate with the `$ref` pointed at `to`.
105
+ */
106
+ export function moveBackRemedy(declaredAt, to, root) {
107
+ const steps = declaredAt.map((slot) => {
108
+ if (!slot.startsWith("channels.")) {
109
+ const holders = pointingAt(root, slot);
110
+ return holders.length === 0 ? `retire it at ${slot}` : `retire it at ${slot}, and restate ${holders.join(" and ")} with every $ref to ${slot} pointed at ${to}`;
111
+ }
112
+ const channel = slot.slice("channels.".length, slot.lastIndexOf(".messages."));
113
+ return `restate channel ${channel} with a $ref to ${to}, or retire channel ${channel}`;
114
+ });
115
+ return [...new Set(steps)].join("; and ");
116
+ }
117
+ /** The channels and operations of `root` holding a `$ref` to one `components.messages` slot, at any depth. */
118
+ function pointingAt(root, slot) {
119
+ const key = slot.slice("components.messages.".length);
120
+ // JSON Pointer escaping, `~` before `/`, so a key spelling either is the pointer that reaches it.
121
+ const pointer = `#/components/messages/${key.replace(/~/g, "~0").replace(/\//g, "~1")}`;
122
+ const sections = root !== null && typeof root === "object" ? root : {};
123
+ return ["channels", "operations"].flatMap((section) => entriesOf(sections[section])
124
+ .filter(([, node]) => collectRefs(node).includes(pointer))
125
+ .map(([key]) => `${section === "channels" ? "channel" : "operation"} ${key}`));
126
+ }
127
+ /** The event arrivals that are revivals — `revivedOperations`' rule, on the slot and the message name. */
128
+ export function revivedEvents(service, arrived, index) {
129
+ const issues = [];
130
+ const revive = (what) => {
131
+ issues.push({ severity: "warn", gates: true, code: "asyncapi.slot-revived", subject: service, message: `${service}: this feature's asyncapi.yaml declares ${what}` });
132
+ };
133
+ const revivedChannels = new Set();
134
+ for (const slot of arrived.slots) {
135
+ const by = index.slots.get(retiredKey(service, slot.section, slot.key));
136
+ if (by === undefined)
137
+ continue;
138
+ if (slot.section === "channels")
139
+ revivedChannels.add(slot.key);
140
+ revive(`${slot.section}.${slot.key}, ${broughtBack(by)}`);
141
+ }
142
+ for (const arrival of arrived.messages) {
143
+ // A message declared inline under a channel that is itself coming back is
144
+ // that channel's interior, and the channel's finding already names the
145
+ // revival — one act, one finding. Only while the merged contract declares
146
+ // the name nowhere else: where it does, the channel's finding says nothing
147
+ // of the second place, and this was once skipped all the same — a stale
148
+ // delta restating a channel whose inline message an archived feature
149
+ // re-declared under components archived under --approve into
150
+ // `asyncapi.duplicate-message`.
151
+ if (arrival.besides.length === 0 && [...revivedChannels].some((ck) => arrival.at.startsWith(`channels.${ck}.messages.`)))
152
+ continue;
153
+ const by = revivalOf(arrival, index.messages.get(retiredKey(service, arrival.id)));
154
+ if (by === undefined)
155
+ continue;
156
+ const { id, at, livesAt, besides } = arrival;
157
+ revive(livesAt.length === 0
158
+ ? `message '${id}' (${at}), ${broughtBack(by, replacing(arrival, "declares"))}`
159
+ : `message '${id}' at ${at}, ${arrival.replaces === undefined ? "a key the living contract no longer has" : "a key it is no longer declared at"} — ${vacators(by, " there")}${present(by, livesAt, "is declared")}, and archiving this delta would declare it at ${at} beside ${besides.join(" and ")}: one message name in ${count(besides.length + 1)} places.${replacing(arrival, "declares")} ${dropOne(arrival, `${moveBackRemedy(besides, at, arrived.mergedRoot)} in this same delta${keeping(arrival, "key")}`)}`);
160
+ }
161
+ return issues;
162
+ }
163
+ /**
164
+ * Both axes' revival findings for one service, read standalone — the gate's
165
+ * two walks compute the same arrivals from the documents they already hold;
166
+ * `loam rebase` holds none, and must not pin a revived operation as if this
167
+ * feature were adding it. One detection, the gate's: `operationArrivals` on
168
+ * the contract axis, and on the event axis `readEventPair` and
169
+ * `eventArrivals`, the walk's own reader and candidates. Asked of the text
170
+ * rebase will WRITE (`planned`), not the text it found: its repin can turn a
171
+ * skipped quote into an edit, and the revival that edit makes is the one the
172
+ * next validate reports — this once ran over the delta as on disk, before
173
+ * the repin, and stayed silent about it.
174
+ */
175
+ export async function serviceRevivals(request) {
176
+ const { docsDir, featureDir, service, retired, context, planned } = request;
177
+ const feature = featureSpecPaths(featureDir, service);
178
+ const living = await locateServicePaths(docsDir, service, context);
179
+ const issues = [];
180
+ if (existsSync(feature.openapi)) {
181
+ const featDoc = await readOpenapi(feature.openapi, context);
182
+ const livingDoc = await readOpenapi(living.openapi, context);
183
+ const sides = { featPath: feature.openapi, featDoc, livingPath: living.openapi, livingDoc, service, featText: planned?.get(feature.openapi) };
184
+ const ops = (await operationArrivals(sides, context)).operations;
185
+ if (ops.length > 0)
186
+ issues.push(...revivedOperations(service, ops, await retired()));
187
+ }
188
+ if (!existsSync(feature.asyncapi))
189
+ return issues;
190
+ const featDoc = await readAsyncapi(feature.asyncapi, context);
191
+ // An unreadable delta is `asyncapi.invalid` in the gate, which grades
192
+ // nothing else against it; the guards on the living side are the pair's.
193
+ if (featDoc.unreadable)
194
+ return issues;
195
+ const livingDoc = await readAsyncapi(living.asyncapi, context);
196
+ const sides = { featPath: feature.asyncapi, featDoc, livingPath: living.asyncapi, livingDoc, service, featText: planned?.get(feature.asyncapi) };
197
+ const events = eventArrivals(await readEventPair(sides, context));
198
+ if (events.slots.length > 0 || events.messages.length > 0)
199
+ issues.push(...revivedEvents(service, events, await retired()));
200
+ return issues;
201
+ }
202
+ /** The retired shape: absent from living, so the merge reads it as an addition. */
203
+ function broughtBack(by, replaced = "") {
204
+ return `which the living contract no longer has — ${vacators(by, "")}, and archiving this delta would put it back.${replaced} ${REMEDY}`;
205
+ }
206
+ /**
207
+ * How a finding names the entry living at the arrival's address — its
208
+ * identity quoted, or, for an operation written with no operationId, what it
209
+ * is; undefined where nothing lives there.
210
+ */
211
+ function occupant({ replaces, replacesUnnamed }) {
212
+ return replaces !== undefined ? `'${replaces}'` : replacesUnnamed === true ? "an operation with no operationId" : undefined;
213
+ }
214
+ /** The entry the merge would replace at the arrival's address, said as a sentence of its own — or nothing. */
215
+ function replacing(arrival, verb) {
216
+ const there = occupant(arrival);
217
+ return there === undefined ? "" : ` ${arrival.at} now ${verb} ${there}, and archiving this delta replaces it there.`;
218
+ }
219
+ /**
220
+ * The duplicate shape's remedy, naming the address to drop: the quote, if it
221
+ * only restated the entry; to move it back on purpose, every other address —
222
+ * through `moveBack` when this delta can take the entry out of all of them,
223
+ * and otherwise only by keeping both under `--approve`, never a marker at a
224
+ * key the delta already spells.
225
+ */
226
+ function dropOne({ at, besides, markable }, moveBack) {
227
+ const keep = `Delete the quote at ${at} if you only restated it, and make any change at ${besides.join(" and ")}`;
228
+ return markable
229
+ ? `${keep}; to move it back on purpose, ${moveBack}.`
230
+ : `${keep}; archive with --approve if the feature brings it back there on purpose.`;
231
+ }
232
+ /**
233
+ * A move back over another living entry takes that entry out too, unless the
234
+ * same delta puts it elsewhere — said in the remedy, because followed as it
235
+ * once read, the move back reached a clean gate and an archive that deleted
236
+ * the other entry with nothing naming it.
237
+ */
238
+ function keeping(arrival, place) {
239
+ const there = occupant(arrival);
240
+ if (there === undefined)
241
+ return "";
242
+ // An operation nobody can name is still what stands there, and the delta
243
+ // can restate it elsewhere all the same — said by what it is, not by an id.
244
+ return arrival.replaces === undefined
245
+ ? ` — and, if the operation with no operationId is to stay, define it at another ${place} in it`
246
+ : ` — and define ${there} at another ${place} in it if it is to stay`;
247
+ }
248
+ function count(n) {
249
+ return n === 2 ? "two" : String(n);
250
+ }
251
+ /** "FEAT-112", "FEAT-112 and FEAT-140", "FEAT-1, FEAT-2 and FEAT-3". */
252
+ function idList([first, ...rest]) {
253
+ return rest.reduce((said, id, i) => `${said}${i === rest.length - 1 ? " and" : ","} ${id}`, first);
254
+ }
255
+ /**
256
+ * Who took an entry out, and how — "archived FEAT-112 retired it",
257
+ * "archived FEAT-200 moved it to POST /y" — each feature once, in id order,
258
+ * movers that put it in the same place sharing one clause and retirers
259
+ * last. `there` places a retirement at the address the finding names, where
260
+ * the entry lives on elsewhere and the difference matters.
261
+ */
262
+ function vacators(by, there) {
263
+ const byDestination = new Map();
264
+ const retirers = [];
265
+ for (const { by: id, to } of by) {
266
+ if (to.length === 0) {
267
+ if (!retirers.includes(id))
268
+ retirers.push(id);
269
+ continue;
270
+ }
271
+ const where = to.join(" and ");
272
+ const ids = byDestination.get(where);
273
+ if (ids === undefined)
274
+ byDestination.set(where, [id]);
275
+ else if (!ids.includes(id))
276
+ ids.push(id);
277
+ }
278
+ const clauses = [...byDestination].map(([where, ids], i) => `${idList(ids)} ${i === 0 ? "moved it " : ""}to ${where}`);
279
+ const [first, ...rest] = retirers;
280
+ if (first !== undefined)
281
+ clauses.push(`${idList([first, ...rest])} retired it${there}`);
282
+ return `archived ${clauses.reduce((all, clause, i) => `${all}${i === clauses.length - 1 ? ", and" : ","} ${clause}`)}`;
283
+ }
284
+ /**
285
+ * Where the entry stands now — "…, where it lives now" when every vacation
286
+ * was a move to exactly there, and said apart otherwise ("; it lives at
287
+ * POST /z now"): the two part ways once anything lands after a move, and
288
+ * this once credited a later feature's address to the mover (`Vacated`).
289
+ * `verb` is how the axis says it — an operation "lives", a message "is
290
+ * declared".
291
+ */
292
+ function present(by, livesAt, verb) {
293
+ const now = new Set(livesAt);
294
+ const unchanged = by.every(({ to }) => to.length > 0 && to.length === now.size && to.every((where) => now.has(where)));
295
+ return unchanged ? `, where it ${verb} now` : `; it ${verb} at ${livesAt.join(" and ")} now`;
296
+ }
297
+ //# sourceMappingURL=revived.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"revived.js","sourceRoot":"","sources":["../../../../../src/core/coherence/retired/revival/revived.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The revival findings: a feature delta that would bring back what an\n * ARCHIVED feature took out of the living contract — an operation, slot or\n * message it retired, or an address it moved one away from, which would put\n * it back there beside where it lives now.\n *\n * `openapi.op-revived` and `asyncapi.slot-revived` — one code per axis, because\n * a caller acts the same way whichever slot section came back. Both are a\n * warning that GATES archive, `openapi.baseline-missing`'s doctrine: the\n * document is legal, and re-adding a retired operation can be exactly what a\n * feature means (a rollback of a retirement, a deprecation reversed), so\n * `--approve` carries the call. What it must never be again is SILENT — the\n * merge cannot tell a quote of a dead operation from an addition, and treated\n * every one as an addition.\n *\n * The candidates — what the contract the archive would WRITE answers that\n * the living one does not (./arrivals.ts) — are computed where both\n * documents are already in hand, in the feature gate's two walks\n * (../../declared.ts, ../../events/declared.ts), and only graded here, so\n * the archive walk (../archived.ts) is paid for only when the merged\n * contract answers something at an address the living one does not.\n * `serviceRevivals` asks the same two functions per axis standalone, for\n * `loam rebase`, which reads no gate — on the event axis through the gate's\n * own reading of the pair (../event-pair.ts) — so the two can never grade one\n * tree two ways.\n */\nimport { existsSync } from \"node:fs\";\nimport type { Issue } from \"../../../vocabulary/issue.js\";\nimport type { PathableService } from \"../../../kernel/ids/service.js\";\nimport type { DocsDir, FeatureDir } from \"../../../kernel/ids/dirs.js\";\nimport { featureSpecPaths } from \"../../../repo/paths.js\";\nimport { locateServicePaths } from \"../../../repo/service-target.js\";\nimport { readOpenapi } from \"../../../openapi/doc.js\";\nimport { readAsyncapi } from \"../../../asyncapi/read.js\";\nimport { entriesOf } from \"../../../asyncapi/digest.js\";\nimport { collectRefs } from \"../../../openapi/depth.js\";\nimport type { FleetContext } from \"../../../fleet-context.js\";\nimport { retiredKey, type RetiredIndex, type RetiredLookup, type Vacated, type Vacations } from \"../archived.js\";\nimport { readEventPair } from \"../event-pair.js\";\nimport { eventArrivals, operationArrivals, type Arrival, type EventArrivals } from \"./arrivals.js\";\n\n/** The two remedies, spelled once: which one applies is the human's call, never loam's. */\nconst REMEDY =\n \"Delete the quote if you only restated it; archive with --approve if the feature brings it back on purpose.\";\n\n/**\n * The vacations that make one arrival a revival — undefined when it is none.\n * Either the living contract answers the identity nowhere, and an archived\n * feature retired it (anywhere: a retired operation re-added at a new path is\n * the same operation back, and a message is its name wherever it is\n * declared) or moved it away from this very address; or the merged contract\n * answers it at two or more addresses, and an archived feature retired it at,\n * or moved it away from, this very address — an old address resurrected\n * beside the current one. An identity the living contract still holds that\n * the merged contract answers at exactly one address — a move back, a swap,\n * a replacement with no operationId — is never a revival, and neither is an\n * address no archived feature vacated. One the living contract holds nowhere\n * is the first case at one address too: this once said \"exactly one address\n * is never a revival\" unqualified, and a quote of an address a move vacated,\n * after a hand edit took the id out of where the move put it, is one.\n *\n * Any archived feature — the one asking is never among them: coherence\n * grades only features in flight (status/feature/feature.ts), so a vacation\n * bearing the asking feature's id is another directory carrying the same\n * id, and as real as anyone's. Excluding it by id, as this once did, could\n * only hide a revival.\n */\nfunction revivalOf({ at, livesAt, besides }: Arrival, vacations: Vacations | undefined): Vacations | undefined {\n if (vacations === undefined) return undefined;\n const [first, ...rest] = vacations.filter((v) =>\n livesAt.length === 0 ? v.to.length === 0 || v.at === at : besides.length > 0 && v.at === at,\n );\n return first === undefined ? undefined : [first, ...rest];\n}\n\n/** The operation arrivals that are revivals — each named for what happened, retired or vacated. */\nexport function revivedOperations(service: string, arrived: readonly Arrival[], index: RetiredIndex): Issue[] {\n const issues: Issue[] = [];\n for (const arrival of arrived) {\n const by = revivalOf(arrival, index.operations.get(retiredKey(service, arrival.id)));\n if (by === undefined) continue;\n const { id, at, livesAt, besides } = arrival;\n const what = livesAt.length === 0\n ? `'${id}' (${at}), ${broughtBack(by, replacing(arrival, \"holds\"))}`\n // A second address, not the operation back: it is living, so the\n // remedy is which address to drop — never \"bring it back\".\n : `'${id}' at ${at}, ${occupant(arrival) === undefined ? \"an address the living contract no longer has\" : \"an address it no longer lives at\"} — ${vacators(by, \" there\")}${present(by, livesAt, \"lives\")}, and archiving this delta would put it back at ${at} beside ${besides.join(\" and \")}: one operationId at ${count(besides.length + 1)} addresses.${replacing(arrival, \"holds\")} ${dropOne(arrival, `add a removal marker for '${id}' at ${besides.join(\" and \")} to this same delta${keeping(arrival, \"address\")}`)}`;\n issues.push({ severity: \"warn\", gates: true, code: \"openapi.op-revived\", subject: service, message: `${service}: this feature's openapi.yaml spells ${what}` });\n }\n return issues;\n}\n\n/**\n * How a delta takes a message name OUT of the places it is declared — the\n * move-back remedy, per place, toward wherever the message is moved back to\n * (`to`). A `components.messages` key is a slot, and a removal marker there\n * retires what it declares. A declaration INLINE under a channel is not: it\n * is the channel slot's interior (SCHEMA.md), so a marker nested on it\n * retires nothing — `asyncapi.remove-marker-inline`, and the deep strip\n * publishes the message without the marker. This once said \"retire it at\n * channels.<ck>.messages.<mk>\", a remedy that, followed exactly, changed\n * nothing and drew a second refusal. The channel is the unit: restated with\n * the message as a `$ref` (an upsert replaces the interior), or retired. The\n * channel key is read the way the archive plan's remove-marker-inline\n * message reads it, so the two name the same channel.\n *\n * A `components.messages` key is retired by its marker, but a channel (or an\n * operation) of the contract the merge would leave (`root`) that still\n * `$ref`s it would point at nothing: its send stops sending the message,\n * `asyncapi.remove-message-consumed` where the fleet consumes it. This once\n * said only \"retire it at components.messages.<K2>\", a remedy that, followed\n * exactly, drew that error — so every slot still pointing there is named,\n * to restate with the `$ref` pointed at `to`.\n */\nexport function moveBackRemedy(declaredAt: readonly string[], to: string, root: unknown): string {\n const steps = declaredAt.map((slot) => {\n if (!slot.startsWith(\"channels.\")) {\n const holders = pointingAt(root, slot);\n return holders.length === 0 ? `retire it at ${slot}` : `retire it at ${slot}, and restate ${holders.join(\" and \")} with every $ref to ${slot} pointed at ${to}`;\n }\n const channel = slot.slice(\"channels.\".length, slot.lastIndexOf(\".messages.\"));\n return `restate channel ${channel} with a $ref to ${to}, or retire channel ${channel}`;\n });\n return [...new Set(steps)].join(\"; and \");\n}\n\n/** The channels and operations of `root` holding a `$ref` to one `components.messages` slot, at any depth. */\nfunction pointingAt(root: unknown, slot: string): string[] {\n const key = slot.slice(\"components.messages.\".length);\n // JSON Pointer escaping, `~` before `/`, so a key spelling either is the pointer that reaches it.\n const pointer = `#/components/messages/${key.replace(/~/g, \"~0\").replace(/\\//g, \"~1\")}`;\n const sections = root !== null && typeof root === \"object\" ? (root as Record<string, unknown>) : {};\n return ([\"channels\", \"operations\"] as const).flatMap((section) =>\n entriesOf(sections[section])\n .filter(([, node]) => collectRefs(node).includes(pointer))\n .map(([key]) => `${section === \"channels\" ? \"channel\" : \"operation\"} ${key}`),\n );\n}\n\n/** The event arrivals that are revivals — `revivedOperations`' rule, on the slot and the message name. */\nexport function revivedEvents(service: string, arrived: EventArrivals, index: RetiredIndex): Issue[] {\n const issues: Issue[] = [];\n const revive = (what: string): void => {\n issues.push({ severity: \"warn\", gates: true, code: \"asyncapi.slot-revived\", subject: service, message: `${service}: this feature's asyncapi.yaml declares ${what}` });\n };\n const revivedChannels = new Set<string>();\n for (const slot of arrived.slots) {\n const by = index.slots.get(retiredKey(service, slot.section, slot.key));\n if (by === undefined) continue;\n if (slot.section === \"channels\") revivedChannels.add(slot.key);\n revive(`${slot.section}.${slot.key}, ${broughtBack(by)}`);\n }\n for (const arrival of arrived.messages) {\n // A message declared inline under a channel that is itself coming back is\n // that channel's interior, and the channel's finding already names the\n // revival — one act, one finding. Only while the merged contract declares\n // the name nowhere else: where it does, the channel's finding says nothing\n // of the second place, and this was once skipped all the same — a stale\n // delta restating a channel whose inline message an archived feature\n // re-declared under components archived under --approve into\n // `asyncapi.duplicate-message`.\n if (arrival.besides.length === 0 && [...revivedChannels].some((ck) => arrival.at.startsWith(`channels.${ck}.messages.`))) continue;\n const by = revivalOf(arrival, index.messages.get(retiredKey(service, arrival.id)));\n if (by === undefined) continue;\n const { id, at, livesAt, besides } = arrival;\n revive(livesAt.length === 0\n ? `message '${id}' (${at}), ${broughtBack(by, replacing(arrival, \"declares\"))}`\n : `message '${id}' at ${at}, ${arrival.replaces === undefined ? \"a key the living contract no longer has\" : \"a key it is no longer declared at\"} — ${vacators(by, \" there\")}${present(by, livesAt, \"is declared\")}, and archiving this delta would declare it at ${at} beside ${besides.join(\" and \")}: one message name in ${count(besides.length + 1)} places.${replacing(arrival, \"declares\")} ${dropOne(arrival, `${moveBackRemedy(besides, at, arrived.mergedRoot)} in this same delta${keeping(arrival, \"key\")}`)}`);\n }\n return issues;\n}\n\n/** What `serviceRevivals` needs: the feature, the service, and the run's reads. */\nexport interface ServiceRevivalRequest {\n docsDir: DocsDir;\n featureDir: FeatureDir;\n service: PathableService;\n retired: RetiredLookup;\n context?: FleetContext;\n /**\n * The text rebase will write, by the path it writes it to — a contract\n * delta absent here is graded as it stands on disk (`PairSides.featText`).\n */\n planned?: ReadonlyMap<string, string>;\n}\n\n/**\n * Both axes' revival findings for one service, read standalone — the gate's\n * two walks compute the same arrivals from the documents they already hold;\n * `loam rebase` holds none, and must not pin a revived operation as if this\n * feature were adding it. One detection, the gate's: `operationArrivals` on\n * the contract axis, and on the event axis `readEventPair` and\n * `eventArrivals`, the walk's own reader and candidates. Asked of the text\n * rebase will WRITE (`planned`), not the text it found: its repin can turn a\n * skipped quote into an edit, and the revival that edit makes is the one the\n * next validate reports — this once ran over the delta as on disk, before\n * the repin, and stayed silent about it.\n */\nexport async function serviceRevivals(request: ServiceRevivalRequest): Promise<Issue[]> {\n const { docsDir, featureDir, service, retired, context, planned } = request;\n const feature = featureSpecPaths(featureDir, service);\n const living = await locateServicePaths(docsDir, service, context);\n const issues: Issue[] = [];\n\n if (existsSync(feature.openapi)) {\n const featDoc = await readOpenapi(feature.openapi, context);\n const livingDoc = await readOpenapi(living.openapi, context);\n const sides = { featPath: feature.openapi, featDoc, livingPath: living.openapi, livingDoc, service, featText: planned?.get(feature.openapi) };\n const ops = (await operationArrivals(sides, context)).operations;\n if (ops.length > 0) issues.push(...revivedOperations(service, ops, await retired()));\n }\n\n if (!existsSync(feature.asyncapi)) return issues;\n const featDoc = await readAsyncapi(feature.asyncapi, context);\n // An unreadable delta is `asyncapi.invalid` in the gate, which grades\n // nothing else against it; the guards on the living side are the pair's.\n if (featDoc.unreadable) return issues;\n const livingDoc = await readAsyncapi(living.asyncapi, context);\n const sides = { featPath: feature.asyncapi, featDoc, livingPath: living.asyncapi, livingDoc, service, featText: planned?.get(feature.asyncapi) };\n const events = eventArrivals(await readEventPair(sides, context));\n if (events.slots.length > 0 || events.messages.length > 0) issues.push(...revivedEvents(service, events, await retired()));\n return issues;\n}\n\n/** The retired shape: absent from living, so the merge reads it as an addition. */\nfunction broughtBack(by: Vacations, replaced = \"\"): string {\n return `which the living contract no longer has — ${vacators(by, \"\")}, and archiving this delta would put it back.${replaced} ${REMEDY}`;\n}\n\n/**\n * How a finding names the entry living at the arrival's address — its\n * identity quoted, or, for an operation written with no operationId, what it\n * is; undefined where nothing lives there.\n */\nfunction occupant({ replaces, replacesUnnamed }: Arrival): string | undefined {\n return replaces !== undefined ? `'${replaces}'` : replacesUnnamed === true ? \"an operation with no operationId\" : undefined;\n}\n\n/** The entry the merge would replace at the arrival's address, said as a sentence of its own — or nothing. */\nfunction replacing(arrival: Arrival, verb: \"holds\" | \"declares\"): string {\n const there = occupant(arrival);\n return there === undefined ? \"\" : ` ${arrival.at} now ${verb} ${there}, and archiving this delta replaces it there.`;\n}\n\n/**\n * The duplicate shape's remedy, naming the address to drop: the quote, if it\n * only restated the entry; to move it back on purpose, every other address —\n * through `moveBack` when this delta can take the entry out of all of them,\n * and otherwise only by keeping both under `--approve`, never a marker at a\n * key the delta already spells.\n */\nfunction dropOne({ at, besides, markable }: Arrival, moveBack: string): string {\n const keep = `Delete the quote at ${at} if you only restated it, and make any change at ${besides.join(\" and \")}`;\n return markable\n ? `${keep}; to move it back on purpose, ${moveBack}.`\n : `${keep}; archive with --approve if the feature brings it back there on purpose.`;\n}\n\n/**\n * A move back over another living entry takes that entry out too, unless the\n * same delta puts it elsewhere — said in the remedy, because followed as it\n * once read, the move back reached a clean gate and an archive that deleted\n * the other entry with nothing naming it.\n */\nfunction keeping(arrival: Arrival, place: \"address\" | \"key\"): string {\n const there = occupant(arrival);\n if (there === undefined) return \"\";\n // An operation nobody can name is still what stands there, and the delta\n // can restate it elsewhere all the same — said by what it is, not by an id.\n return arrival.replaces === undefined\n ? ` — and, if the operation with no operationId is to stay, define it at another ${place} in it`\n : ` — and define ${there} at another ${place} in it if it is to stay`;\n}\n\nfunction count(n: number): string {\n return n === 2 ? \"two\" : String(n);\n}\n\n/** \"FEAT-112\", \"FEAT-112 and FEAT-140\", \"FEAT-1, FEAT-2 and FEAT-3\". */\nfunction idList([first, ...rest]: readonly [string, ...string[]]): string {\n return rest.reduce((said, id, i) => `${said}${i === rest.length - 1 ? \" and\" : \",\"} ${id}`, first);\n}\n\n/**\n * Who took an entry out, and how — \"archived FEAT-112 retired it\",\n * \"archived FEAT-200 moved it to POST /y\" — each feature once, in id order,\n * movers that put it in the same place sharing one clause and retirers\n * last. `there` places a retirement at the address the finding names, where\n * the entry lives on elsewhere and the difference matters.\n */\nfunction vacators(by: Vacations, there: string): string {\n const byDestination = new Map<string, [string, ...string[]]>();\n const retirers: string[] = [];\n for (const { by: id, to } of by) {\n if (to.length === 0) {\n if (!retirers.includes(id)) retirers.push(id);\n continue;\n }\n const where = to.join(\" and \");\n const ids = byDestination.get(where);\n if (ids === undefined) byDestination.set(where, [id]);\n else if (!ids.includes(id)) ids.push(id);\n }\n const clauses = [...byDestination].map(([where, ids], i) => `${idList(ids)} ${i === 0 ? \"moved it \" : \"\"}to ${where}`);\n const [first, ...rest] = retirers;\n if (first !== undefined) clauses.push(`${idList([first, ...rest])} retired it${there}`);\n return `archived ${clauses.reduce((all, clause, i) => `${all}${i === clauses.length - 1 ? \", and\" : \",\"} ${clause}`)}`;\n}\n\n/**\n * Where the entry stands now — \"…, where it lives now\" when every vacation\n * was a move to exactly there, and said apart otherwise (\"; it lives at\n * POST /z now\"): the two part ways once anything lands after a move, and\n * this once credited a later feature's address to the mover (`Vacated`).\n * `verb` is how the axis says it — an operation \"lives\", a message \"is\n * declared\".\n */\nfunction present(by: readonly Vacated[], livesAt: readonly string[], verb: \"lives\" | \"is declared\"): string {\n const now = new Set(livesAt);\n const unchanged = by.every(({ to }) => to.length > 0 && to.length === now.size && to.every((where) => now.has(where)));\n return unchanged ? `, where it ${verb} now` : `; it ${verb} at ${livesAt.join(\" and \")} now`;\n}\n"]}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * The three-way merge left its markers in the file — 1-based line numbers.
3
+ *
4
+ * The rule is `loam doctor`'s, verbatim, and it lives here now because doctor
5
+ * checked exactly one file (`architecture/landscape.likec4`) from a command
6
+ * that gates nothing. The same markers in a living `services/<svc>/spec.md`
7
+ * parse as prose: `loam validate --all` reported `valid: true`, and the next
8
+ * `loam archive` rewrote the requirements section and dropped the `=======`
9
+ * line with it, turning a conflict anyone can see into a document nobody can
10
+ * tell is wrong. For a shared docs repo where a fleet lands through PRs this is
11
+ * the DEFAULT failure, not an edge.
12
+ */
13
+ const CONFLICT_MARKERS = ["<<<<<<<", "=======", ">>>>>>>"];
14
+ export function conflictMarkerLines(source) {
15
+ const out = [];
16
+ source.split(/\r?\n/).forEach((line, i) => {
17
+ if (CONFLICT_MARKERS.some((m) => line.startsWith(m)))
18
+ out.push(i + 1);
19
+ });
20
+ return out;
21
+ }
22
+ /** One sentence for the breach, wherever it is found — doctor, validate, either axis. */
23
+ function conflictMessage(label, lines) {
24
+ return (`${label} still contains git conflict markers (line${lines.length === 1 ? "" : "s"} ${lines.join(", ")}) — ` +
25
+ `both sides of somebody's merge are in the file, so nothing it says is anyone's text. ` +
26
+ `Resolve the conflict before anything else: loam rewrites this document on archive, and a rewrite deletes ` +
27
+ `whichever marker lines fall inside the section it owns — a visible conflict becomes a silently malformed file.`);
28
+ }
29
+ /**
30
+ * The conflict-marker finding for a requirement document (living spec.md /
31
+ * arch.spec.md, or a feature's delta of one). Null when the text is clean.
32
+ *
33
+ * An error because the document is not valid — nobody wrote what it now says —
34
+ * and because the merge that would consume it is unsafe. It does not carry
35
+ * `gates`: that field is coherence's (issue.ts), and the archive gate has to
36
+ * ask this question itself.
37
+ */
38
+ export function documentConflictFinding(label, subject, text) {
39
+ const lines = conflictMarkerLines(text);
40
+ if (lines.length === 0)
41
+ return null;
42
+ return {
43
+ severity: "error",
44
+ code: "spec.merge-conflict",
45
+ subject,
46
+ message: conflictMessage(label, lines),
47
+ };
48
+ }
49
+ /** The same breach in the fleet map, where it costs every cross-service check at once. */
50
+ export function landscapeConflictFinding(label, text) {
51
+ const lines = conflictMarkerLines(text);
52
+ if (lines.length === 0)
53
+ return null;
54
+ return {
55
+ severity: "error",
56
+ code: "landscape.merge-conflict",
57
+ message: conflictMessage(label, lines),
58
+ };
59
+ }
60
+ //# sourceMappingURL=conflict-markers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conflict-markers.js","sourceRoot":"","sources":["../../src/core/conflict-markers.ts"],"names":[],"mappings":"AAYA;;;;;;;;;;;GAWG;AACH,MAAM,gBAAgB,GAAG,CAAC,SAAS,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;AAE3D,MAAM,UAAU,mBAAmB,CAAC,MAAc;IAChD,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE;QACxC,IAAI,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;YAAE,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACxE,CAAC,CAAC,CAAC;IACH,OAAO,GAAG,CAAC;AACb,CAAC;AAED,yFAAyF;AACzF,SAAS,eAAe,CAAC,KAAa,EAAE,KAAe;IACrD,OAAO,CACL,GAAG,KAAK,6CAA6C,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM;QAC5G,uFAAuF;QACvF,2GAA2G;QAC3G,gHAAgH,CACjH,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,uBAAuB,CAAC,KAAa,EAAE,OAAe,EAAE,IAAY;IAClF,MAAM,KAAK,GAAG,mBAAmB,CAAC,IAAI,CAAC,CAAC;IACxC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACpC,OAAO;QACL,QAAQ,EAAE,OAAO;QACjB,IAAI,EAAE,qBAAqB;QAC3B,OAAO;QACP,OAAO,EAAE,eAAe,CAAC,KAAK,EAAE,KAAK,CAAC;KACvC,CAAC;AACJ,CAAC;AAED,0FAA0F;AAC1F,MAAM,UAAU,wBAAwB,CAAC,KAAa,EAAE,IAAY;IAClE,MAAM,KAAK,GAAG,mBAAmB,CAAC,IAAI,CAAC,CAAC;IACxC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACpC,OAAO;QACL,QAAQ,EAAE,OAAO;QACjB,IAAI,EAAE,0BAA0B;QAChC,OAAO,EAAE,eAAe,CAAC,KAAK,EAAE,KAAK,CAAC;KACvC,CAAC;AACJ,CAAC","sourcesContent":["/**\n * Git conflict markers left in a document, and the findings they become.\n *\n * Split out of `fleet-context.ts` — the module that owes every READER the\n * check — because the rule itself is a leaf: doctor, validate's three target\n * kinds and coherence all grade marker breaches on text they already hold, and\n * none of them should have to import the whole read index (and the fleet it\n * pulls in behind it) to spell one line rule. The context keeps its\n * `conflictMarkers()` convenience over `readText`; the rule lives here.\n */\nimport type { Finding } from \"./vocabulary/report.js\";\n\n/**\n * The three-way merge left its markers in the file — 1-based line numbers.\n *\n * The rule is `loam doctor`'s, verbatim, and it lives here now because doctor\n * checked exactly one file (`architecture/landscape.likec4`) from a command\n * that gates nothing. The same markers in a living `services/<svc>/spec.md`\n * parse as prose: `loam validate --all` reported `valid: true`, and the next\n * `loam archive` rewrote the requirements section and dropped the `=======`\n * line with it, turning a conflict anyone can see into a document nobody can\n * tell is wrong. For a shared docs repo where a fleet lands through PRs this is\n * the DEFAULT failure, not an edge.\n */\nconst CONFLICT_MARKERS = [\"<<<<<<<\", \"=======\", \">>>>>>>\"];\n\nexport function conflictMarkerLines(source: string): number[] {\n const out: number[] = [];\n source.split(/\\r?\\n/).forEach((line, i) => {\n if (CONFLICT_MARKERS.some((m) => line.startsWith(m))) out.push(i + 1);\n });\n return out;\n}\n\n/** One sentence for the breach, wherever it is found — doctor, validate, either axis. */\nfunction conflictMessage(label: string, lines: number[]): string {\n return (\n `${label} still contains git conflict markers (line${lines.length === 1 ? \"\" : \"s\"} ${lines.join(\", \")}) — ` +\n `both sides of somebody's merge are in the file, so nothing it says is anyone's text. ` +\n `Resolve the conflict before anything else: loam rewrites this document on archive, and a rewrite deletes ` +\n `whichever marker lines fall inside the section it owns — a visible conflict becomes a silently malformed file.`\n );\n}\n\n/**\n * The conflict-marker finding for a requirement document (living spec.md /\n * arch.spec.md, or a feature's delta of one). Null when the text is clean.\n *\n * An error because the document is not valid — nobody wrote what it now says —\n * and because the merge that would consume it is unsafe. It does not carry\n * `gates`: that field is coherence's (issue.ts), and the archive gate has to\n * ask this question itself.\n */\nexport function documentConflictFinding(label: string, subject: string, text: string): Finding | null {\n const lines = conflictMarkerLines(text);\n if (lines.length === 0) return null;\n return {\n severity: \"error\",\n code: \"spec.merge-conflict\",\n subject,\n message: conflictMessage(label, lines),\n };\n}\n\n/** The same breach in the fleet map, where it costs every cross-service check at once. */\nexport function landscapeConflictFinding(label: string, text: string): Finding | null {\n const lines = conflictMarkerLines(text);\n if (lines.length === 0) return null;\n return {\n severity: \"error\",\n code: \"landscape.merge-conflict\",\n message: conflictMessage(label, lines),\n };\n}\n"]}