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

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 (1036) hide show
  1. package/CHANGELOG.md +2635 -86
  2. package/COMPARISON.md +80 -63
  3. package/CONTRIBUTING.md +84 -0
  4. package/MIGRATING-from-OpenSpec.md +213 -54
  5. package/QUICKSTART.md +125 -0
  6. package/README.md +450 -150
  7. package/ROADMAP.md +599 -0
  8. package/SCHEMA.md +2355 -256
  9. package/SECURITY.md +21 -3
  10. package/WORKFLOW.md +701 -0
  11. package/dist/cli.js +113 -19
  12. package/dist/cli.js.map +1 -1
  13. package/dist/commands/adopt/adopt.js +209 -0
  14. package/dist/commands/adopt/adopt.js.map +1 -0
  15. package/dist/commands/adopt/render.js +268 -0
  16. package/dist/commands/adopt/render.js.map +1 -0
  17. package/dist/commands/archive/archive.js +77 -0
  18. package/dist/commands/archive/archive.js.map +1 -0
  19. package/dist/commands/archive/plan/contracts/asyncapi.js +178 -0
  20. package/dist/commands/archive/plan/contracts/asyncapi.js.map +1 -0
  21. package/dist/commands/archive/plan/contracts/openapi.js +159 -0
  22. package/dist/commands/archive/plan/contracts/openapi.js.map +1 -0
  23. package/dist/commands/archive/plan/gate.js +323 -0
  24. package/dist/commands/archive/plan/gate.js.map +1 -0
  25. package/dist/commands/archive/plan/landscape.js +180 -0
  26. package/dist/commands/archive/plan/landscape.js.map +1 -0
  27. package/dist/commands/archive/plan/refusal.js +111 -0
  28. package/dist/commands/archive/plan/refusal.js.map +1 -0
  29. package/dist/commands/archive/plan/specs.js +237 -0
  30. package/dist/commands/archive/plan/specs.js.map +1 -0
  31. package/dist/commands/archive/plan/state.js +27 -0
  32. package/dist/commands/archive/plan/state.js.map +1 -0
  33. package/dist/commands/archive/run.js +252 -0
  34. package/dist/commands/archive/run.js.map +1 -0
  35. package/dist/commands/context/context.js +99 -0
  36. package/dist/commands/context/context.js.map +1 -0
  37. package/dist/commands/context/print.js +283 -0
  38. package/dist/commands/context/print.js.map +1 -0
  39. package/dist/commands/delta/delta.js +279 -0
  40. package/dist/commands/delta/delta.js.map +1 -0
  41. package/dist/commands/delta/print.js +205 -0
  42. package/dist/commands/delta/print.js.map +1 -0
  43. package/dist/commands/dependencies.js +9 -7
  44. package/dist/commands/dependencies.js.map +1 -1
  45. package/dist/commands/diff/diff.js +93 -0
  46. package/dist/commands/diff/diff.js.map +1 -0
  47. package/dist/commands/diff/print.js +38 -0
  48. package/dist/commands/diff/print.js.map +1 -0
  49. package/dist/commands/doctor.js +5 -4
  50. package/dist/commands/doctor.js.map +1 -1
  51. package/dist/commands/explain/explain.js +151 -0
  52. package/dist/commands/explain/explain.js.map +1 -0
  53. package/dist/commands/explore.js +29 -24
  54. package/dist/commands/explore.js.map +1 -1
  55. package/dist/commands/gate/gate.js +115 -0
  56. package/dist/commands/gate/gate.js.map +1 -0
  57. package/dist/commands/gate/print.js +54 -0
  58. package/dist/commands/gate/print.js.map +1 -0
  59. package/dist/commands/gherkin/commit.js +146 -0
  60. package/dist/commands/gherkin/commit.js.map +1 -0
  61. package/dist/commands/gherkin/gherkin.js +246 -0
  62. package/dist/commands/gherkin/gherkin.js.map +1 -0
  63. package/dist/commands/gherkin/reconcile.js +149 -0
  64. package/dist/commands/gherkin/reconcile.js.map +1 -0
  65. package/dist/commands/gherkin/render.js +77 -0
  66. package/dist/commands/gherkin/render.js.map +1 -0
  67. package/dist/commands/init/example.js +204 -0
  68. package/dist/commands/init/example.js.map +1 -0
  69. package/dist/commands/init/first-hour.js +28 -0
  70. package/dist/commands/init/first-hour.js.map +1 -0
  71. package/dist/commands/{init.js → init/init.js} +146 -71
  72. package/dist/commands/init/init.js.map +1 -0
  73. package/dist/commands/init/mcp.js +131 -0
  74. package/dist/commands/init/mcp.js.map +1 -0
  75. package/dist/commands/init/options.js +78 -0
  76. package/dist/commands/init/options.js.map +1 -0
  77. package/dist/commands/instructions.js +72 -14
  78. package/dist/commands/instructions.js.map +1 -1
  79. package/dist/commands/list/campaign/campaign.js +65 -0
  80. package/dist/commands/list/campaign/campaign.js.map +1 -0
  81. package/dist/commands/list/campaign/owners.js +65 -0
  82. package/dist/commands/list/campaign/owners.js.map +1 -0
  83. package/dist/commands/list/json.js +157 -0
  84. package/dist/commands/list/json.js.map +1 -0
  85. package/dist/commands/list/list.js +343 -0
  86. package/dist/commands/list/list.js.map +1 -0
  87. package/dist/commands/list/print.js +301 -0
  88. package/dist/commands/list/print.js.map +1 -0
  89. package/dist/commands/list/review.js +120 -0
  90. package/dist/commands/list/review.js.map +1 -0
  91. package/dist/commands/list/views.js +105 -0
  92. package/dist/commands/list/views.js.map +1 -0
  93. package/dist/commands/mcp/dispatch.js +183 -0
  94. package/dist/commands/mcp/dispatch.js.map +1 -0
  95. package/dist/commands/mcp/mcp.js +34 -0
  96. package/dist/commands/mcp/mcp.js.map +1 -0
  97. package/dist/commands/mcp/serve.js +55 -0
  98. package/dist/commands/mcp/serve.js.map +1 -0
  99. package/dist/commands/migrate-openspec/materialize/active.js +170 -0
  100. package/dist/commands/migrate-openspec/materialize/active.js.map +1 -0
  101. package/dist/commands/migrate-openspec/materialize/feature.js +41 -0
  102. package/dist/commands/migrate-openspec/materialize/feature.js.map +1 -0
  103. package/dist/commands/migrate-openspec/materialize/living.js +62 -0
  104. package/dist/commands/migrate-openspec/materialize/living.js.map +1 -0
  105. package/dist/commands/migrate-openspec/materialize/stage.js +142 -0
  106. package/dist/commands/migrate-openspec/materialize/stage.js.map +1 -0
  107. package/dist/commands/migrate-openspec/materialize/target.js +219 -0
  108. package/dist/commands/migrate-openspec/materialize/target.js.map +1 -0
  109. package/dist/commands/migrate-openspec/migrate-openspec.js +142 -0
  110. package/dist/commands/migrate-openspec/migrate-openspec.js.map +1 -0
  111. package/dist/commands/migrate-openspec/openspec/decisions.js +91 -0
  112. package/dist/commands/migrate-openspec/openspec/decisions.js.map +1 -0
  113. package/dist/commands/migrate-openspec/openspec/error.js +19 -0
  114. package/dist/commands/migrate-openspec/openspec/error.js.map +1 -0
  115. package/dist/commands/migrate-openspec/openspec/mapping.js +170 -0
  116. package/dist/commands/migrate-openspec/openspec/mapping.js.map +1 -0
  117. package/dist/commands/migrate-openspec/openspec/paths.js +43 -0
  118. package/dist/commands/migrate-openspec/openspec/paths.js.map +1 -0
  119. package/dist/commands/migrate-openspec/openspec/read.js +49 -0
  120. package/dist/commands/migrate-openspec/openspec/read.js.map +1 -0
  121. package/dist/commands/migrate-openspec/print.js +89 -0
  122. package/dist/commands/migrate-openspec/print.js.map +1 -0
  123. package/dist/commands/new/commit.js +76 -0
  124. package/dist/commands/new/commit.js.map +1 -0
  125. package/dist/commands/new/new.js +283 -0
  126. package/dist/commands/new/new.js.map +1 -0
  127. package/dist/commands/new/templates.js +355 -0
  128. package/dist/commands/new/templates.js.map +1 -0
  129. package/dist/commands/open.js +203 -0
  130. package/dist/commands/open.js.map +1 -0
  131. package/dist/commands/policy/format.js +152 -0
  132. package/dist/commands/policy/format.js.map +1 -0
  133. package/dist/commands/{docs-repo-gate.js → policy/gate.js} +11 -11
  134. package/dist/commands/policy/gate.js.map +1 -0
  135. package/dist/commands/rebase/edit.js +106 -0
  136. package/dist/commands/rebase/edit.js.map +1 -0
  137. package/dist/commands/rebase/living.js +185 -0
  138. package/dist/commands/rebase/living.js.map +1 -0
  139. package/dist/commands/rebase/plan.js +245 -0
  140. package/dist/commands/rebase/plan.js.map +1 -0
  141. package/dist/commands/rebase/rebase.js +275 -0
  142. package/dist/commands/rebase/rebase.js.map +1 -0
  143. package/dist/commands/seed/commit.js +192 -0
  144. package/dist/commands/seed/commit.js.map +1 -0
  145. package/dist/commands/seed/plan.js +133 -0
  146. package/dist/commands/seed/plan.js.map +1 -0
  147. package/dist/commands/seed/seed.js +172 -0
  148. package/dist/commands/seed/seed.js.map +1 -0
  149. package/dist/commands/show/feature.js +178 -0
  150. package/dist/commands/show/feature.js.map +1 -0
  151. package/dist/commands/show/marks.js +24 -0
  152. package/dist/commands/show/marks.js.map +1 -0
  153. package/dist/commands/{show.js → show/service.js} +63 -152
  154. package/dist/commands/show/service.js.map +1 -0
  155. package/dist/commands/show/show.js +77 -0
  156. package/dist/commands/show/show.js.map +1 -0
  157. package/dist/commands/status/json.js +45 -0
  158. package/dist/commands/status/json.js.map +1 -0
  159. package/dist/commands/status/print.js +157 -0
  160. package/dist/commands/status/print.js.map +1 -0
  161. package/dist/commands/status/status.js +119 -0
  162. package/dist/commands/status/status.js.map +1 -0
  163. package/dist/commands/steps/steps.js +189 -0
  164. package/dist/commands/steps/steps.js.map +1 -0
  165. package/dist/commands/subsystem/edit.js +192 -0
  166. package/dist/commands/subsystem/edit.js.map +1 -0
  167. package/dist/commands/subsystem/move.js +265 -0
  168. package/dist/commands/subsystem/move.js.map +1 -0
  169. package/dist/commands/subsystem/query.js +115 -0
  170. package/dist/commands/subsystem/query.js.map +1 -0
  171. package/dist/commands/subsystem/subsystem.js +101 -0
  172. package/dist/commands/subsystem/subsystem.js.map +1 -0
  173. package/dist/commands/subsystem/sync.js +103 -0
  174. package/dist/commands/subsystem/sync.js.map +1 -0
  175. package/dist/commands/subsystem/txn/txn.js +94 -0
  176. package/dist/commands/subsystem/txn/txn.js.map +1 -0
  177. package/dist/commands/subsystem/txn/views.js +70 -0
  178. package/dist/commands/subsystem/txn/views.js.map +1 -0
  179. package/dist/commands/unarchive/manifest.js +160 -0
  180. package/dist/commands/unarchive/manifest.js.map +1 -0
  181. package/dist/commands/{unarchive.js → unarchive/restore.js} +47 -160
  182. package/dist/commands/unarchive/restore.js.map +1 -0
  183. package/dist/commands/unarchive/unarchive.js +67 -0
  184. package/dist/commands/unarchive/unarchive.js.map +1 -0
  185. package/dist/commands/validate/arch-coverage.js +204 -0
  186. package/dist/commands/validate/arch-coverage.js.map +1 -0
  187. package/dist/commands/validate/checks/fleet-shape.js +296 -0
  188. package/dist/commands/validate/checks/fleet-shape.js.map +1 -0
  189. package/dist/commands/validate/checks/health-deps.js +55 -0
  190. package/dist/commands/validate/checks/health-deps.js.map +1 -0
  191. package/dist/commands/validate/checks/requirements.js +254 -0
  192. package/dist/commands/validate/checks/requirements.js.map +1 -0
  193. package/dist/commands/validate/checks/sources.js +76 -0
  194. package/dist/commands/validate/checks/sources.js.map +1 -0
  195. package/dist/commands/validate/checks/vocabulary.js +31 -0
  196. package/dist/commands/validate/checks/vocabulary.js.map +1 -0
  197. package/dist/commands/validate/feature.js +216 -0
  198. package/dist/commands/validate/feature.js.map +1 -0
  199. package/dist/commands/validate/fleet/census.js +69 -0
  200. package/dist/commands/validate/fleet/census.js.map +1 -0
  201. package/dist/commands/validate/fleet/kind-tags.js +39 -0
  202. package/dist/commands/validate/fleet/kind-tags.js.map +1 -0
  203. package/dist/commands/validate/fleet/landscape.js +353 -0
  204. package/dist/commands/validate/fleet/landscape.js.map +1 -0
  205. package/dist/commands/validate/fleet/load.js +52 -0
  206. package/dist/commands/validate/fleet/load.js.map +1 -0
  207. package/dist/commands/validate/fleet/obligations.js +270 -0
  208. package/dist/commands/validate/fleet/obligations.js.map +1 -0
  209. package/dist/commands/validate/fleet/scorecard/adoption.js +102 -0
  210. package/dist/commands/validate/fleet/scorecard/adoption.js.map +1 -0
  211. package/dist/commands/validate/fleet/scorecard/contracts.js +98 -0
  212. package/dist/commands/validate/fleet/scorecard/contracts.js.map +1 -0
  213. package/dist/commands/validate/fleet/scorecard/print.js +63 -0
  214. package/dist/commands/validate/fleet/scorecard/print.js.map +1 -0
  215. package/dist/commands/validate/fleet/scorecard/scorecard.js +156 -0
  216. package/dist/commands/validate/fleet/scorecard/scorecard.js.map +1 -0
  217. package/dist/commands/validate/fleet/usecases/capability-tag.js +94 -0
  218. package/dist/commands/validate/fleet/usecases/capability-tag.js.map +1 -0
  219. package/dist/commands/validate/fleet/usecases/place.js +13 -0
  220. package/dist/commands/validate/fleet/usecases/place.js.map +1 -0
  221. package/dist/commands/validate/fleet/usecases/requirement-tag.js +95 -0
  222. package/dist/commands/validate/fleet/usecases/requirement-tag.js.map +1 -0
  223. package/dist/commands/validate/fleet/usecases/steps.js +197 -0
  224. package/dist/commands/validate/fleet/usecases/steps.js.map +1 -0
  225. package/dist/commands/validate/fleet/usecases/usecases.js +99 -0
  226. package/dist/commands/validate/fleet/usecases/usecases.js.map +1 -0
  227. package/dist/commands/validate/fleet/views/ids.js +40 -0
  228. package/dist/commands/validate/fleet/views/ids.js.map +1 -0
  229. package/dist/commands/validate/fleet/views/stale.js +59 -0
  230. package/dist/commands/validate/fleet/views/stale.js.map +1 -0
  231. package/dist/commands/validate/links/corpus.js +92 -0
  232. package/dist/commands/validate/links/corpus.js.map +1 -0
  233. package/dist/commands/validate/links/glossary.js +75 -0
  234. package/dist/commands/validate/links/glossary.js.map +1 -0
  235. package/dist/commands/validate/report.js +269 -0
  236. package/dist/commands/validate/report.js.map +1 -0
  237. package/dist/commands/validate/service/api.js +338 -0
  238. package/dist/commands/validate/service/api.js.map +1 -0
  239. package/dist/commands/validate/service/events/events.js +219 -0
  240. package/dist/commands/validate/service/events/events.js.map +1 -0
  241. package/dist/commands/validate/service/events/message-producers.js +77 -0
  242. package/dist/commands/validate/service/events/message-producers.js.map +1 -0
  243. package/dist/commands/validate/service/evidence-pins.js +131 -0
  244. package/dist/commands/validate/service/evidence-pins.js.map +1 -0
  245. package/dist/commands/validate/service/service.js +251 -0
  246. package/dist/commands/validate/service/service.js.map +1 -0
  247. package/dist/commands/validate/service/specs.js +251 -0
  248. package/dist/commands/validate/service/specs.js.map +1 -0
  249. package/dist/commands/validate/service/spine.js +113 -0
  250. package/dist/commands/validate/service/spine.js.map +1 -0
  251. package/dist/commands/validate/validate.js +338 -0
  252. package/dist/commands/validate/validate.js.map +1 -0
  253. package/dist/commands/verify/cross/diff.js +182 -0
  254. package/dist/commands/verify/cross/diff.js.map +1 -0
  255. package/dist/commands/verify/evidence/contract.js +32 -0
  256. package/dist/commands/verify/evidence/contract.js.map +1 -0
  257. package/dist/commands/verify/evidence/pins.js +52 -0
  258. package/dist/commands/verify/evidence/pins.js.map +1 -0
  259. package/dist/commands/verify/evidence/read.js +72 -0
  260. package/dist/commands/verify/evidence/read.js.map +1 -0
  261. package/dist/commands/verify/frozen.js +241 -0
  262. package/dist/commands/verify/frozen.js.map +1 -0
  263. package/dist/commands/verify/record.js +226 -0
  264. package/dist/commands/verify/record.js.map +1 -0
  265. package/dist/commands/verify/report.js +223 -0
  266. package/dist/commands/verify/report.js.map +1 -0
  267. package/dist/commands/verify/results.js +246 -0
  268. package/dist/commands/verify/results.js.map +1 -0
  269. package/dist/commands/verify/verify.js +217 -0
  270. package/dist/commands/verify/verify.js.map +1 -0
  271. package/dist/commands/vouch/contract.js +11 -0
  272. package/dist/commands/vouch/contract.js.map +1 -0
  273. package/dist/commands/vouch/pack/contract.js +2 -0
  274. package/dist/commands/vouch/pack/contract.js.map +1 -0
  275. package/dist/commands/vouch/pack/pack.js +266 -0
  276. package/dist/commands/vouch/pack/pack.js.map +1 -0
  277. package/dist/commands/vouch/pack/print.js +271 -0
  278. package/dist/commands/vouch/pack/print.js.map +1 -0
  279. package/dist/commands/vouch/pack/sections.js +142 -0
  280. package/dist/commands/vouch/pack/sections.js.map +1 -0
  281. package/dist/commands/vouch/prompt/confirm.js +46 -0
  282. package/dist/commands/vouch/prompt/confirm.js.map +1 -0
  283. package/dist/commands/vouch/report.js +101 -0
  284. package/dist/commands/vouch/report.js.map +1 -0
  285. package/dist/commands/vouch/run.js +285 -0
  286. package/dist/commands/vouch/run.js.map +1 -0
  287. package/dist/commands/vouch/sample/plan.js +125 -0
  288. package/dist/commands/vouch/sample/plan.js.map +1 -0
  289. package/dist/commands/vouch/sample/print.js +109 -0
  290. package/dist/commands/vouch/sample/print.js.map +1 -0
  291. package/dist/commands/vouch/vet/verify.js +123 -0
  292. package/dist/commands/vouch/vet/verify.js.map +1 -0
  293. package/dist/commands/vouch/vouch.js +176 -0
  294. package/dist/commands/vouch/vouch.js.map +1 -0
  295. package/dist/core/agent/agents-md/artifacts.js +220 -0
  296. package/dist/core/agent/agents-md/artifacts.js.map +1 -0
  297. package/dist/core/agent/agents-md/command-map.js +324 -0
  298. package/dist/core/agent/agents-md/command-map.js.map +1 -0
  299. package/dist/core/agent/agents-md/cycle.js +165 -0
  300. package/dist/core/agent/agents-md/cycle.js.map +1 -0
  301. package/dist/core/agent/agents-md/map/explain.js +34 -0
  302. package/dist/core/agent/agents-md/map/explain.js.map +1 -0
  303. package/dist/core/agent/agents-md/map/lenses/context.js +41 -0
  304. package/dist/core/agent/agents-md/map/lenses/context.js.map +1 -0
  305. package/dist/core/agent/agents-md/map/lenses/diff.js +46 -0
  306. package/dist/core/agent/agents-md/map/lenses/diff.js.map +1 -0
  307. package/dist/core/agent/agents-md/map/lenses/gate.js +57 -0
  308. package/dist/core/agent/agents-md/map/lenses/gate.js.map +1 -0
  309. package/dist/core/agent/agents-md/map/mcp.js +41 -0
  310. package/dist/core/agent/agents-md/map/mcp.js.map +1 -0
  311. package/dist/core/agent/agents-md/map/status.js +62 -0
  312. package/dist/core/agent/agents-md/map/status.js.map +1 -0
  313. package/dist/core/agent/agents-md/map/subsystem.js +32 -0
  314. package/dist/core/agent/agents-md/map/subsystem.js.map +1 -0
  315. package/dist/core/agent/agents-md/map/usecases.js +60 -0
  316. package/dist/core/agent/agents-md/map/usecases.js.map +1 -0
  317. package/dist/core/agent/agents-md/refusals.js +246 -0
  318. package/dist/core/agent/agents-md/refusals.js.map +1 -0
  319. package/dist/core/agent/agents-md/shipped/archive-gate.js +98 -0
  320. package/dist/core/agent/agents-md/shipped/archive-gate.js.map +1 -0
  321. package/dist/core/agent/agents-md/spine.js +40 -0
  322. package/dist/core/agent/agents-md/spine.js.map +1 -0
  323. package/dist/core/agent/agents-md.js +170 -0
  324. package/dist/core/agent/agents-md.js.map +1 -0
  325. package/dist/core/{agents-stamp.js → agent/agents-stamp.js} +50 -0
  326. package/dist/core/agent/agents-stamp.js.map +1 -0
  327. package/dist/core/agent/contract.js +2 -0
  328. package/dist/core/agent/contract.js.map +1 -0
  329. package/dist/core/agent/protocol.js +193 -0
  330. package/dist/core/agent/protocol.js.map +1 -0
  331. package/dist/core/agent/scaffold.js +259 -0
  332. package/dist/core/agent/scaffold.js.map +1 -0
  333. package/dist/core/agent/support/report.js +103 -0
  334. package/dist/core/agent/support/report.js.map +1 -0
  335. package/dist/core/agent/tools/dialects.js +150 -0
  336. package/dist/core/agent/tools/dialects.js.map +1 -0
  337. package/dist/core/agent/tools/registry.js +228 -0
  338. package/dist/core/agent/tools/registry.js.map +1 -0
  339. package/dist/core/agent/workflows/adopt.js +133 -0
  340. package/dist/core/agent/workflows/adopt.js.map +1 -0
  341. package/dist/core/agent/workflows/check.js +337 -0
  342. package/dist/core/agent/workflows/check.js.map +1 -0
  343. package/dist/core/agent/workflows/closing.js +262 -0
  344. package/dist/core/agent/workflows/closing.js.map +1 -0
  345. package/dist/core/agent/workflows/feature.js +105 -0
  346. package/dist/core/agent/workflows/feature.js.map +1 -0
  347. package/dist/core/agent/workflows/implement.js +105 -0
  348. package/dist/core/agent/workflows/implement.js.map +1 -0
  349. package/dist/core/agent/workflows/reference/authoring.js +209 -0
  350. package/dist/core/agent/workflows/reference/authoring.js.map +1 -0
  351. package/dist/core/agent/workflows/reference/codes.js +65 -0
  352. package/dist/core/agent/workflows/reference/codes.js.map +1 -0
  353. package/dist/core/agent/workflows/reference/done-check.js +188 -0
  354. package/dist/core/agent/workflows/reference/done-check.js.map +1 -0
  355. package/dist/core/agent/workflows/reference/reference.js +16 -0
  356. package/dist/core/agent/workflows/reference/reference.js.map +1 -0
  357. package/dist/core/agent/workflows/reference/spine.js +297 -0
  358. package/dist/core/agent/workflows/reference/spine.js.map +1 -0
  359. package/dist/core/asyncapi/baseline/plan.js +110 -0
  360. package/dist/core/asyncapi/baseline/plan.js.map +1 -0
  361. package/dist/core/asyncapi/baseline/surfaces.js +54 -0
  362. package/dist/core/asyncapi/baseline/surfaces.js.map +1 -0
  363. package/dist/core/asyncapi/depth.js +164 -0
  364. package/dist/core/asyncapi/depth.js.map +1 -0
  365. package/dist/core/asyncapi/digest.js +141 -0
  366. package/dist/core/asyncapi/digest.js.map +1 -0
  367. package/dist/core/asyncapi/merge/components.js +91 -0
  368. package/dist/core/asyncapi/merge/components.js.map +1 -0
  369. package/dist/core/asyncapi/merge/error.js +33 -0
  370. package/dist/core/asyncapi/merge/error.js.map +1 -0
  371. package/dist/core/asyncapi/merge/markers.js +308 -0
  372. package/dist/core/asyncapi/merge/markers.js.map +1 -0
  373. package/dist/core/asyncapi/merge/merge.js +215 -0
  374. package/dist/core/asyncapi/merge/merge.js.map +1 -0
  375. package/dist/core/asyncapi/merge/pin.js +107 -0
  376. package/dist/core/asyncapi/merge/pin.js.map +1 -0
  377. package/dist/core/asyncapi/model.js +11 -0
  378. package/dist/core/asyncapi/model.js.map +1 -0
  379. package/dist/core/asyncapi/producers.js +50 -0
  380. package/dist/core/asyncapi/producers.js.map +1 -0
  381. package/dist/core/{asyncapi.js → asyncapi/read.js} +95 -109
  382. package/dist/core/asyncapi/read.js.map +1 -0
  383. package/dist/core/brief/brief.js +225 -0
  384. package/dist/core/brief/brief.js.map +1 -0
  385. package/dist/core/brief/checks.js +250 -0
  386. package/dist/core/brief/checks.js.map +1 -0
  387. package/dist/core/brief/landscape.js +194 -0
  388. package/dist/core/brief/landscape.js.map +1 -0
  389. package/dist/core/brief/targets.js +226 -0
  390. package/dist/core/brief/targets.js.map +1 -0
  391. package/dist/core/brief/unchecked.js +48 -0
  392. package/dist/core/brief/unchecked.js.map +1 -0
  393. package/dist/core/c4/arch.js +174 -0
  394. package/dist/core/c4/arch.js.map +1 -0
  395. package/dist/core/c4/likec4.js +90 -0
  396. package/dist/core/c4/likec4.js.map +1 -0
  397. package/dist/core/c4/parsed/deployment.js +158 -0
  398. package/dist/core/c4/parsed/deployment.js.map +1 -0
  399. package/dist/core/c4/parsed/dynamic-views.js +132 -0
  400. package/dist/core/c4/parsed/dynamic-views.js.map +1 -0
  401. package/dist/core/c4/parsed/specification.js +78 -0
  402. package/dist/core/c4/parsed/specification.js.map +1 -0
  403. package/dist/core/c4/parsed/values.js +57 -0
  404. package/dist/core/c4/parsed/values.js.map +1 -0
  405. package/dist/core/c4/parsed/view-ids.js +75 -0
  406. package/dist/core/c4/parsed/view-ids.js.map +1 -0
  407. package/dist/core/c4/project/architecture.js +45 -0
  408. package/dist/core/c4/project/architecture.js.map +1 -0
  409. package/dist/core/c4/project/documents.js +58 -0
  410. package/dist/core/c4/project/documents.js.map +1 -0
  411. package/dist/core/c4/project/load.js +187 -0
  412. package/dist/core/c4/project/load.js.map +1 -0
  413. package/dist/core/c4/project/staged.js +220 -0
  414. package/dist/core/c4/project/staged.js.map +1 -0
  415. package/dist/core/c4/resolve/service.js +159 -0
  416. package/dist/core/c4/resolve/service.js.map +1 -0
  417. package/dist/core/c4/resolve/steps.js +144 -0
  418. package/dist/core/c4/resolve/steps.js.map +1 -0
  419. package/dist/core/c4/seed/fleet-file.js +201 -0
  420. package/dist/core/c4/seed/fleet-file.js.map +1 -0
  421. package/dist/core/c4/seed/items.js +91 -0
  422. package/dist/core/c4/seed/items.js.map +1 -0
  423. package/dist/core/c4/seed/stamp.js +48 -0
  424. package/dist/core/c4/seed/stamp.js.map +1 -0
  425. package/dist/core/c4/seed/template.js +109 -0
  426. package/dist/core/c4/seed/template.js.map +1 -0
  427. package/dist/core/c4/source-mask.js +82 -0
  428. package/dist/core/c4/source-mask.js.map +1 -0
  429. package/dist/core/c4/source-scan.js +227 -0
  430. package/dist/core/c4/source-scan.js.map +1 -0
  431. package/dist/core/c4/splice/authored-source.js +101 -0
  432. package/dist/core/c4/splice/authored-source.js.map +1 -0
  433. package/dist/core/c4/splice/contract.js +10 -0
  434. package/dist/core/c4/splice/contract.js.map +1 -0
  435. package/dist/core/c4/splice/delta-blocks.js +139 -0
  436. package/dist/core/c4/splice/delta-blocks.js.map +1 -0
  437. package/dist/core/c4/splice/identity/edges.js +36 -0
  438. package/dist/core/c4/splice/identity/edges.js.map +1 -0
  439. package/dist/core/c4/splice/landscape-merge.js +269 -0
  440. package/dist/core/c4/splice/landscape-merge.js.map +1 -0
  441. package/dist/core/c4/splice/placement.js +194 -0
  442. package/dist/core/c4/splice/placement.js.map +1 -0
  443. package/dist/core/c4/workspace.js +174 -0
  444. package/dist/core/c4/workspace.js.map +1 -0
  445. package/dist/core/capabilities/authoring/notes.js +141 -0
  446. package/dist/core/capabilities/authoring/notes.js.map +1 -0
  447. package/dist/core/capabilities/capabilities.js +124 -0
  448. package/dist/core/capabilities/capabilities.js.map +1 -0
  449. package/dist/core/capabilities/delta/doc.js +50 -0
  450. package/dist/core/capabilities/delta/doc.js.map +1 -0
  451. package/dist/core/capabilities/delta/overlay.js +129 -0
  452. package/dist/core/capabilities/delta/overlay.js.map +1 -0
  453. package/dist/core/capabilities/delta/summary.js +57 -0
  454. package/dist/core/capabilities/delta/summary.js.map +1 -0
  455. package/dist/core/capabilities/delta/tree.js +43 -0
  456. package/dist/core/capabilities/delta/tree.js.map +1 -0
  457. package/dist/core/capabilities/delta/uncovered.js +222 -0
  458. package/dist/core/capabilities/delta/uncovered.js.map +1 -0
  459. package/dist/core/capabilities/findings.js +342 -0
  460. package/dist/core/capabilities/findings.js.map +1 -0
  461. package/dist/core/capabilities/realizes/findings.js +181 -0
  462. package/dist/core/capabilities/realizes/findings.js.map +1 -0
  463. package/dist/core/capabilities/realizes/join.js +143 -0
  464. package/dist/core/capabilities/realizes/join.js.map +1 -0
  465. package/dist/core/capabilities/rollup.js +199 -0
  466. package/dist/core/capabilities/rollup.js.map +1 -0
  467. package/dist/core/capabilities/tree.js +126 -0
  468. package/dist/core/capabilities/tree.js.map +1 -0
  469. package/dist/core/capabilities/usecase-join.js +277 -0
  470. package/dist/core/capabilities/usecase-join.js.map +1 -0
  471. package/dist/core/coherence/authoring/scaffold.js +177 -0
  472. package/dist/core/coherence/authoring/scaffold.js.map +1 -0
  473. package/dist/core/coherence/authoring/sentinels.js +74 -0
  474. package/dist/core/coherence/authoring/sentinels.js.map +1 -0
  475. package/dist/core/coherence/coherence.js +287 -0
  476. package/dist/core/coherence/coherence.js.map +1 -0
  477. package/dist/core/coherence/declared.js +269 -0
  478. package/dist/core/coherence/declared.js.map +1 -0
  479. package/dist/core/coherence/events/declared.js +206 -0
  480. package/dist/core/coherence/events/declared.js.map +1 -0
  481. package/dist/core/coherence/events/events.js +204 -0
  482. package/dist/core/coherence/events/events.js.map +1 -0
  483. package/dist/core/coherence/events/grades.js +166 -0
  484. package/dist/core/coherence/events/grades.js.map +1 -0
  485. package/dist/core/coherence/events/lookups.js +122 -0
  486. package/dist/core/coherence/events/lookups.js.map +1 -0
  487. package/dist/core/coherence/events/merged.js +40 -0
  488. package/dist/core/coherence/events/merged.js.map +1 -0
  489. package/dist/core/coherence/living.js +198 -0
  490. package/dist/core/coherence/living.js.map +1 -0
  491. package/dist/core/coherence/lookups.js +155 -0
  492. package/dist/core/coherence/lookups.js.map +1 -0
  493. package/dist/core/coherence/pending.js +39 -0
  494. package/dist/core/coherence/pending.js.map +1 -0
  495. package/dist/core/conflict-markers.js +60 -0
  496. package/dist/core/conflict-markers.js.map +1 -0
  497. package/dist/core/delta/claims.js +73 -0
  498. package/dist/core/delta/claims.js.map +1 -0
  499. package/dist/core/delta/delta.js +296 -0
  500. package/dist/core/delta/delta.js.map +1 -0
  501. package/dist/core/delta/document.js +177 -0
  502. package/dist/core/delta/document.js.map +1 -0
  503. package/dist/core/delta/scope.js +48 -0
  504. package/dist/core/delta/scope.js.map +1 -0
  505. package/dist/core/delta/select.js +237 -0
  506. package/dist/core/delta/select.js.map +1 -0
  507. package/dist/core/dependencies/dependencies.js +141 -0
  508. package/dist/core/dependencies/dependencies.js.map +1 -0
  509. package/dist/core/dependencies/facts.js +165 -0
  510. package/dist/core/dependencies/facts.js.map +1 -0
  511. package/dist/core/dependencies/fanin.js +88 -0
  512. package/dist/core/dependencies/fanin.js.map +1 -0
  513. package/dist/core/dependencies/graph.js +106 -0
  514. package/dist/core/dependencies/graph.js.map +1 -0
  515. package/dist/core/deployment/delta.js +188 -0
  516. package/dist/core/deployment/delta.js.map +1 -0
  517. package/dist/core/deployment/objects.js +145 -0
  518. package/dist/core/deployment/objects.js.map +1 -0
  519. package/dist/core/diff/base-git.js +148 -0
  520. package/dist/core/diff/base-git.js.map +1 -0
  521. package/dist/core/diff/base-state.js +209 -0
  522. package/dist/core/diff/base-state.js.map +1 -0
  523. package/dist/core/diff/current-state.js +96 -0
  524. package/dist/core/diff/current-state.js.map +1 -0
  525. package/dist/core/diff/scope/changed-paths.js +188 -0
  526. package/dist/core/diff/scope/changed-paths.js.map +1 -0
  527. package/dist/core/diff/semantic.js +243 -0
  528. package/dist/core/diff/semantic.js.map +1 -0
  529. package/dist/core/diff/victims.js +247 -0
  530. package/dist/core/diff/victims.js.map +1 -0
  531. package/dist/core/docs.js +7 -64
  532. package/dist/core/docs.js.map +1 -1
  533. package/dist/core/doctor/agents.js +222 -0
  534. package/dist/core/doctor/agents.js.map +1 -0
  535. package/dist/core/doctor/config.js +135 -0
  536. package/dist/core/doctor/config.js.map +1 -0
  537. package/dist/core/doctor/doctor.js +275 -0
  538. package/dist/core/doctor/doctor.js.map +1 -0
  539. package/dist/core/doctor/report.js +13 -0
  540. package/dist/core/doctor/report.js.map +1 -0
  541. package/dist/core/doctor/residue.js +110 -0
  542. package/dist/core/doctor/residue.js.map +1 -0
  543. package/dist/core/document/apply.js +77 -0
  544. package/dist/core/document/apply.js.map +1 -0
  545. package/dist/core/{frontmatter.js → document/frontmatter.js} +48 -2
  546. package/dist/core/document/frontmatter.js.map +1 -0
  547. package/dist/core/document/grammar/directives.js +143 -0
  548. package/dist/core/document/grammar/directives.js.map +1 -0
  549. package/dist/core/document/parse.js +263 -0
  550. package/dist/core/document/parse.js.map +1 -0
  551. package/dist/core/document/scenarios.js +221 -0
  552. package/dist/core/document/scenarios.js.map +1 -0
  553. package/dist/core/document/spec.js +241 -0
  554. package/dist/core/document/spec.js.map +1 -0
  555. package/dist/core/{config.js → envelope/config.js} +79 -18
  556. package/dist/core/envelope/config.js.map +1 -0
  557. package/dist/core/envelope/json.js +175 -0
  558. package/dist/core/envelope/json.js.map +1 -0
  559. package/dist/core/{version.js → envelope/version.js} +3 -3
  560. package/dist/core/envelope/version.js.map +1 -0
  561. package/dist/core/explain/families.js +175 -0
  562. package/dist/core/explain/families.js.map +1 -0
  563. package/dist/core/explain/fix-tables.js +178 -0
  564. package/dist/core/explain/fix-tables.js.map +1 -0
  565. package/dist/core/explain/lookup.js +181 -0
  566. package/dist/core/explain/lookup.js.map +1 -0
  567. package/dist/core/explain/refusals.js +49 -0
  568. package/dist/core/explain/refusals.js.map +1 -0
  569. package/dist/core/explain/terms.js +144 -0
  570. package/dist/core/explain/terms.js.map +1 -0
  571. package/dist/core/explore/describe.js +105 -0
  572. package/dist/core/explore/describe.js.map +1 -0
  573. package/dist/core/{explore.js → explore/explore.js} +50 -101
  574. package/dist/core/explore/explore.js.map +1 -0
  575. package/dist/core/fleet-context.js +120 -78
  576. package/dist/core/fleet-context.js.map +1 -1
  577. package/dist/core/gate/checks.js +201 -0
  578. package/dist/core/gate/checks.js.map +1 -0
  579. package/dist/core/gate/partners.js +205 -0
  580. package/dist/core/gate/partners.js.map +1 -0
  581. package/dist/core/gate/report.js +47 -0
  582. package/dist/core/gate/report.js.map +1 -0
  583. package/dist/core/gate/verification.js +113 -0
  584. package/dist/core/gate/verification.js.map +1 -0
  585. package/dist/core/gherkin/digest.js +60 -0
  586. package/dist/core/gherkin/digest.js.map +1 -0
  587. package/dist/core/gherkin/emit.js +177 -0
  588. package/dist/core/gherkin/emit.js.map +1 -0
  589. package/dist/core/gherkin/read.js +76 -0
  590. package/dist/core/gherkin/read.js.map +1 -0
  591. package/dist/core/gherkin/stale.js +234 -0
  592. package/dist/core/gherkin/stale.js.map +1 -0
  593. package/dist/core/gherkin/stamp.js +77 -0
  594. package/dist/core/gherkin/stamp.js.map +1 -0
  595. package/dist/core/gherkin/steps/catalogue.js +154 -0
  596. package/dist/core/gherkin/steps/catalogue.js.map +1 -0
  597. package/dist/core/gherkin/steps/inventory.js +98 -0
  598. package/dist/core/gherkin/steps/inventory.js.map +1 -0
  599. package/dist/core/gherkin/steps/phrase.js +72 -0
  600. package/dist/core/gherkin/steps/phrase.js.map +1 -0
  601. package/dist/core/glossary/delta.js +106 -0
  602. package/dist/core/glossary/delta.js.map +1 -0
  603. package/dist/core/glossary/tree.js +86 -0
  604. package/dist/core/glossary/tree.js.map +1 -0
  605. package/dist/core/kernel/concurrency.js.map +1 -0
  606. package/dist/core/{document-bytes.js → kernel/document-bytes.js} +1 -1
  607. package/dist/core/kernel/document-bytes.js.map +1 -0
  608. package/dist/core/kernel/fences.js +42 -0
  609. package/dist/core/kernel/fences.js.map +1 -0
  610. package/dist/core/kernel/ids/capability.js +72 -0
  611. package/dist/core/kernel/ids/capability.js.map +1 -0
  612. package/dist/core/kernel/ids/dirs.js +33 -0
  613. package/dist/core/kernel/ids/dirs.js.map +1 -0
  614. package/dist/core/kernel/ids/feature.js +75 -0
  615. package/dist/core/kernel/ids/feature.js.map +1 -0
  616. package/dist/core/kernel/ids/service.js +156 -0
  617. package/dist/core/kernel/ids/service.js.map +1 -0
  618. package/dist/core/kernel/ids/subsystem.js +63 -0
  619. package/dist/core/kernel/ids/subsystem.js.map +1 -0
  620. package/dist/core/{path-safety.js → kernel/path-safety.js} +18 -4
  621. package/dist/core/kernel/path-safety.js.map +1 -0
  622. package/dist/core/kernel/records.js.map +1 -0
  623. package/dist/core/links/backlinks.js +68 -0
  624. package/dist/core/links/backlinks.js.map +1 -0
  625. package/dist/core/links/case.js +74 -0
  626. package/dist/core/links/case.js.map +1 -0
  627. package/dist/core/links/corpus.js +104 -0
  628. package/dist/core/links/corpus.js.map +1 -0
  629. package/dist/core/links/findings.js +110 -0
  630. package/dist/core/links/findings.js.map +1 -0
  631. package/dist/core/links/parse.js +236 -0
  632. package/dist/core/links/parse.js.map +1 -0
  633. package/dist/core/mcp/argv.js +111 -0
  634. package/dist/core/mcp/argv.js.map +1 -0
  635. package/dist/core/mcp/author-tools.js +72 -0
  636. package/dist/core/mcp/author-tools.js.map +1 -0
  637. package/dist/core/mcp/framing.js +46 -0
  638. package/dist/core/mcp/framing.js.map +1 -0
  639. package/dist/core/mcp/protocol.js +280 -0
  640. package/dist/core/mcp/protocol.js.map +1 -0
  641. package/dist/core/mcp/tools.js +314 -0
  642. package/dist/core/mcp/tools.js.map +1 -0
  643. package/dist/core/obligations/obligations.js +106 -0
  644. package/dist/core/obligations/obligations.js.map +1 -0
  645. package/dist/core/openapi/baseline/gate.js +166 -0
  646. package/dist/core/openapi/baseline/gate.js.map +1 -0
  647. package/dist/core/openapi/baseline/plan.js +112 -0
  648. package/dist/core/openapi/baseline/plan.js.map +1 -0
  649. package/dist/core/openapi/baseline/record.js +175 -0
  650. package/dist/core/openapi/baseline/record.js.map +1 -0
  651. package/dist/core/openapi/depth.js +122 -0
  652. package/dist/core/openapi/depth.js.map +1 -0
  653. package/dist/core/openapi/digest.js +189 -0
  654. package/dist/core/openapi/digest.js.map +1 -0
  655. package/dist/core/{openapi.js → openapi/doc.js} +44 -106
  656. package/dist/core/openapi/doc.js.map +1 -0
  657. package/dist/core/openapi/merge/components.js +234 -0
  658. package/dist/core/openapi/merge/components.js.map +1 -0
  659. package/dist/core/openapi/merge/error.js +26 -0
  660. package/dist/core/openapi/merge/error.js.map +1 -0
  661. package/dist/core/openapi/merge/markers.js +208 -0
  662. package/dist/core/openapi/merge/markers.js.map +1 -0
  663. package/dist/core/openapi/merge/merge.js +256 -0
  664. package/dist/core/openapi/merge/merge.js.map +1 -0
  665. package/dist/core/openapi/merge/pin.js +128 -0
  666. package/dist/core/openapi/merge/pin.js.map +1 -0
  667. package/dist/core/openspec/decide/capabilities.js +244 -0
  668. package/dist/core/openspec/decide/capabilities.js.map +1 -0
  669. package/dist/core/openspec/decide/dispositions.js +63 -0
  670. package/dist/core/openspec/decide/dispositions.js.map +1 -0
  671. package/dist/core/openspec/decide/renames.js +179 -0
  672. package/dist/core/openspec/decide/renames.js.map +1 -0
  673. package/dist/core/openspec/decide/verdict.js +84 -0
  674. package/dist/core/openspec/decide/verdict.js.map +1 -0
  675. package/dist/core/openspec/inventory.js +221 -0
  676. package/dist/core/openspec/inventory.js.map +1 -0
  677. package/dist/core/openspec/model/mapping.js +76 -0
  678. package/dist/core/openspec/model/mapping.js.map +1 -0
  679. package/dist/core/openspec/model/model.js +65 -0
  680. package/dist/core/openspec/model/model.js.map +1 -0
  681. package/dist/core/openspec/scan/changes.js +235 -0
  682. package/dist/core/openspec/scan/changes.js.map +1 -0
  683. package/dist/core/openspec/scan/config.js +200 -0
  684. package/dist/core/openspec/scan/config.js.map +1 -0
  685. package/dist/core/openspec/scan/shape.js +260 -0
  686. package/dist/core/openspec/scan/shape.js.map +1 -0
  687. package/dist/core/openspec/scan/walk.js +133 -0
  688. package/dist/core/openspec/scan/walk.js.map +1 -0
  689. package/dist/core/openspec/scan/workspace.js +71 -0
  690. package/dist/core/openspec/scan/workspace.js.map +1 -0
  691. package/dist/core/owners/codeowners.js +141 -0
  692. package/dist/core/owners/codeowners.js.map +1 -0
  693. package/dist/core/pack/features.js +120 -0
  694. package/dist/core/pack/features.js.map +1 -0
  695. package/dist/core/pack/joins.js +112 -0
  696. package/dist/core/pack/joins.js.map +1 -0
  697. package/dist/core/pack/living.js +137 -0
  698. package/dist/core/pack/living.js.map +1 -0
  699. package/dist/core/pack/pack.js +76 -0
  700. package/dist/core/pack/pack.js.map +1 -0
  701. package/dist/core/permissions/permissions.js +87 -0
  702. package/dist/core/permissions/permissions.js.map +1 -0
  703. package/dist/core/projection/api.js +84 -0
  704. package/dist/core/projection/api.js.map +1 -0
  705. package/dist/core/projection/arch-slice.js +63 -0
  706. package/dist/core/projection/arch-slice.js.map +1 -0
  707. package/dist/core/projection/events.js +34 -0
  708. package/dist/core/projection/events.js.map +1 -0
  709. package/dist/core/provenance/findings.js +208 -0
  710. package/dist/core/provenance/findings.js.map +1 -0
  711. package/dist/core/provenance/git.js +225 -0
  712. package/dist/core/provenance/git.js.map +1 -0
  713. package/dist/core/provenance/gitq/moves.js +182 -0
  714. package/dist/core/provenance/gitq/moves.js.map +1 -0
  715. package/dist/core/provenance/gitq/vouched-ancestor.js +179 -0
  716. package/dist/core/provenance/gitq/vouched-ancestor.js.map +1 -0
  717. package/dist/core/provenance/sample/scope.js +238 -0
  718. package/dist/core/provenance/sample/scope.js.map +1 -0
  719. package/dist/core/provenance/sample/sections.js +61 -0
  720. package/dist/core/provenance/sample/sections.js.map +1 -0
  721. package/dist/core/provenance/sources.js +263 -0
  722. package/dist/core/provenance/sources.js.map +1 -0
  723. package/dist/core/provenance/stamp.js +232 -0
  724. package/dist/core/provenance/stamp.js.map +1 -0
  725. package/dist/core/provenance/walk.js +157 -0
  726. package/dist/core/provenance/walk.js.map +1 -0
  727. package/dist/core/repo/authored/paths.js +210 -0
  728. package/dist/core/repo/authored/paths.js.map +1 -0
  729. package/dist/core/repo/entries.js +126 -0
  730. package/dist/core/repo/entries.js.map +1 -0
  731. package/dist/core/repo/paths.js +277 -0
  732. package/dist/core/repo/paths.js.map +1 -0
  733. package/dist/core/repo/repo.js +248 -0
  734. package/dist/core/repo/repo.js.map +1 -0
  735. package/dist/core/repo/service-target.js +153 -0
  736. package/dist/core/repo/service-target.js.map +1 -0
  737. package/dist/core/repo/state.js +58 -0
  738. package/dist/core/repo/state.js.map +1 -0
  739. package/dist/core/repo/tree/find.js +52 -0
  740. package/dist/core/repo/tree/find.js.map +1 -0
  741. package/dist/core/repo/tree/fs.js +64 -0
  742. package/dist/core/repo/tree/fs.js.map +1 -0
  743. package/dist/core/repo/tree/marker.js +61 -0
  744. package/dist/core/repo/tree/marker.js.map +1 -0
  745. package/dist/core/repo/tree/views.js +172 -0
  746. package/dist/core/repo/tree/views.js.map +1 -0
  747. package/dist/core/repo/tree/walk.js +234 -0
  748. package/dist/core/repo/tree/walk.js.map +1 -0
  749. package/dist/core/results.js +99 -2
  750. package/dist/core/results.js.map +1 -1
  751. package/dist/core/scaffold/landscape.js +131 -0
  752. package/dist/core/scaffold/landscape.js.map +1 -0
  753. package/dist/core/scaffold/readme.js +84 -0
  754. package/dist/core/scaffold/readme.js.map +1 -0
  755. package/dist/core/staging/commit.js +241 -0
  756. package/dist/core/staging/commit.js.map +1 -0
  757. package/dist/core/staging/interrupted.js +96 -0
  758. package/dist/core/staging/interrupted.js.map +1 -0
  759. package/dist/core/staging/lock.js +206 -0
  760. package/dist/core/staging/lock.js.map +1 -0
  761. package/dist/core/staging/recovery/finding.js +35 -0
  762. package/dist/core/staging/recovery/finding.js.map +1 -0
  763. package/dist/core/staging/recovery/intent.js +98 -0
  764. package/dist/core/staging/recovery/intent.js.map +1 -0
  765. package/dist/core/staging/recovery/recover.js +126 -0
  766. package/dist/core/staging/recovery/recover.js.map +1 -0
  767. package/dist/core/staging/recovery/residue.js +62 -0
  768. package/dist/core/staging/recovery/residue.js.map +1 -0
  769. package/dist/core/staging/snapshot.js +202 -0
  770. package/dist/core/staging/snapshot.js.map +1 -0
  771. package/dist/core/staging/txn/forward.js +171 -0
  772. package/dist/core/staging/txn/forward.js.map +1 -0
  773. package/dist/core/staging/txn/journal.js +139 -0
  774. package/dist/core/staging/txn/journal.js.map +1 -0
  775. package/dist/core/staging/txn/transaction.js +75 -0
  776. package/dist/core/staging/txn/transaction.js.map +1 -0
  777. package/dist/core/staging/writes.js +113 -0
  778. package/dist/core/staging/writes.js.map +1 -0
  779. package/dist/core/status/actions/execution.js +49 -0
  780. package/dist/core/status/actions/execution.js.map +1 -0
  781. package/dist/core/status/contracts.js +102 -0
  782. package/dist/core/status/contracts.js.map +1 -0
  783. package/dist/core/status/feature/artifacts.js +196 -0
  784. package/dist/core/status/feature/artifacts.js.map +1 -0
  785. package/dist/core/status/feature/feature.js +207 -0
  786. package/dist/core/status/feature/feature.js.map +1 -0
  787. package/dist/core/status/feature/next.js +150 -0
  788. package/dist/core/status/feature/next.js.map +1 -0
  789. package/dist/core/status/feature/state.js +21 -0
  790. package/dist/core/status/feature/state.js.map +1 -0
  791. package/dist/core/status/fleet/fleet.js +197 -0
  792. package/dist/core/status/fleet/fleet.js.map +1 -0
  793. package/dist/core/status/fleet/next.js +207 -0
  794. package/dist/core/status/fleet/next.js.map +1 -0
  795. package/dist/core/status/interrupted.js +97 -0
  796. package/dist/core/status/interrupted.js.map +1 -0
  797. package/dist/core/status/report.js +31 -0
  798. package/dist/core/status/report.js.map +1 -0
  799. package/dist/core/status/scan.js +41 -0
  800. package/dist/core/status/scan.js.map +1 -0
  801. package/dist/core/status/verification.js +201 -0
  802. package/dist/core/status/verification.js.map +1 -0
  803. package/dist/core/usecases/capability.js +169 -0
  804. package/dist/core/usecases/capability.js.map +1 -0
  805. package/dist/core/usecases/delta/claims.js +116 -0
  806. package/dist/core/usecases/delta/claims.js.map +1 -0
  807. package/dist/core/usecases/delta/flows.js +103 -0
  808. package/dist/core/usecases/delta/flows.js.map +1 -0
  809. package/dist/core/usecases/delta/overlay.js +72 -0
  810. package/dist/core/usecases/delta/overlay.js.map +1 -0
  811. package/dist/core/usecases/fleet.js +137 -0
  812. package/dist/core/usecases/fleet.js.map +1 -0
  813. package/dist/core/usecases/operations.js +111 -0
  814. package/dist/core/usecases/operations.js.map +1 -0
  815. package/dist/core/usecases/place.js +44 -0
  816. package/dist/core/usecases/place.js.map +1 -0
  817. package/dist/core/usecases/touch.js +101 -0
  818. package/dist/core/usecases/touch.js.map +1 -0
  819. package/dist/core/verify/answers.js +173 -0
  820. package/dist/core/verify/answers.js.map +1 -0
  821. package/dist/core/verify/build.js +150 -0
  822. package/dist/core/verify/build.js.map +1 -0
  823. package/dist/core/verify/checklist.js +201 -0
  824. package/dist/core/verify/checklist.js.map +1 -0
  825. package/dist/core/verify/claims/identity.js +61 -0
  826. package/dist/core/verify/claims/identity.js.map +1 -0
  827. package/dist/core/verify/cross/diff.js +97 -0
  828. package/dist/core/verify/cross/diff.js.map +1 -0
  829. package/dist/core/verify/evidence/contract.js +169 -0
  830. package/dist/core/verify/evidence/contract.js.map +1 -0
  831. package/dist/core/verify/file.js +257 -0
  832. package/dist/core/verify/file.js.map +1 -0
  833. package/dist/core/verify/pins/lint.js +157 -0
  834. package/dist/core/verify/pins/lint.js.map +1 -0
  835. package/dist/core/verify/pins/pin.js +95 -0
  836. package/dist/core/verify/pins/pin.js.map +1 -0
  837. package/dist/core/verify/record.js +142 -0
  838. package/dist/core/verify/record.js.map +1 -0
  839. package/dist/core/verify/store/commit.js +89 -0
  840. package/dist/core/verify/store/commit.js.map +1 -0
  841. package/dist/core/verify/store/render.js +57 -0
  842. package/dist/core/verify/store/render.js.map +1 -0
  843. package/dist/core/vocabulary/health.js +91 -0
  844. package/dist/core/vocabulary/health.js.map +1 -0
  845. package/dist/core/vocabulary/issue.js +58 -0
  846. package/dist/core/vocabulary/issue.js.map +1 -0
  847. package/dist/core/vocabulary/maturity.js +145 -0
  848. package/dist/core/vocabulary/maturity.js.map +1 -0
  849. package/dist/core/{report.js → vocabulary/report.js} +30 -2
  850. package/dist/core/vocabulary/report.js.map +1 -0
  851. package/dist/core/vocabulary/steps.js +266 -0
  852. package/dist/core/vocabulary/steps.js.map +1 -0
  853. package/dist/core/workspace/discover.js +239 -0
  854. package/dist/core/workspace/discover.js.map +1 -0
  855. package/dist/core/workspace/render.js +52 -0
  856. package/dist/core/workspace/render.js.map +1 -0
  857. package/examples/README.md +189 -0
  858. package/examples/docs/architecture/adrs/0001-transactional-outbox.md +33 -0
  859. package/examples/docs/architecture/capabilities.yaml +31 -0
  860. package/examples/docs/architecture/landscape.likec4 +280 -0
  861. package/examples/docs/architecture/obligations.yaml +23 -0
  862. package/examples/docs/architecture/permissions.yaml +50 -0
  863. package/examples/docs/architecture/subsystems.likec4 +11 -0
  864. package/examples/docs/architecture/usecases/order-notification.likec4 +65 -0
  865. package/examples/docs/capabilities/checkout/spec.md +55 -0
  866. package/examples/docs/capabilities/identity/tokens/spec.md +42 -0
  867. package/examples/docs/capabilities/order-notifications/spec.md +43 -0
  868. package/examples/docs/features/FEAT-101-payment-splitting/adrs/0001-dedicated-split-service.md +18 -0
  869. package/examples/docs/features/FEAT-101-payment-splitting/delta.likec4 +94 -0
  870. package/examples/docs/features/FEAT-101-payment-splitting/intent.md +44 -0
  871. package/examples/docs/features/FEAT-101-payment-splitting/specs/checkout-web/spec.md +21 -0
  872. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-service/asyncapi.yaml +129 -0
  873. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-service/spec.md +36 -0
  874. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/arch.spec.md +40 -0
  875. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/openapi.yaml +116 -0
  876. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/spec.md +55 -0
  877. package/examples/docs/features/FEAT-112-retire-order-v1/intent.md +35 -0
  878. package/examples/docs/features/FEAT-112-retire-order-v1/specs/order-service/openapi.yaml +28 -0
  879. package/examples/docs/features/FEAT-112-retire-order-v1/specs/order-service/spec.md +17 -0
  880. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/architecture/landscape.likec4 +253 -0
  881. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/services/order-service/spec.md +121 -0
  882. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/services/payment-service/openapi.yaml +111 -0
  883. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/services/payment-service/spec.md +58 -0
  884. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/manifest.json +32 -0
  885. package/examples/docs/features/archive/FEAT-088-refunds/adrs/0001-refunds-stay-in-payment-service.md +26 -0
  886. package/examples/docs/features/archive/FEAT-088-refunds/delta.likec4 +28 -0
  887. package/examples/docs/features/archive/FEAT-088-refunds/intent.md +26 -0
  888. package/examples/docs/features/archive/FEAT-088-refunds/specs/order-service/spec.md +37 -0
  889. package/examples/docs/features/archive/FEAT-088-refunds/specs/payment-service/openapi.yaml +70 -0
  890. package/examples/docs/features/archive/FEAT-088-refunds/specs/payment-service/spec.md +23 -0
  891. package/examples/docs/features/archive/FEAT-088-refunds/verification.yaml +76 -0
  892. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/architecture/landscape.likec4 +275 -0
  893. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/payment-service/asyncapi.yaml +96 -0
  894. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/payment-service/spec.md +82 -0
  895. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/platform/notification-service/asyncapi.yaml +164 -0
  896. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/platform/notification-service/spec.md +91 -0
  897. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/manifest.json +46 -0
  898. package/examples/docs/features/archive/FEAT-120-refund-notification/delta.likec4 +36 -0
  899. package/examples/docs/features/archive/FEAT-120-refund-notification/intent.md +22 -0
  900. package/examples/docs/features/archive/FEAT-120-refund-notification/scenario-report.json +10 -0
  901. package/examples/docs/features/archive/FEAT-120-refund-notification/specs/notification-service/asyncapi.yaml +208 -0
  902. package/examples/docs/features/archive/FEAT-120-refund-notification/specs/notification-service/spec.md +24 -0
  903. package/examples/docs/features/archive/FEAT-120-refund-notification/specs/payment-service/asyncapi.yaml +137 -0
  904. package/examples/docs/features/archive/FEAT-120-refund-notification/specs/payment-service/spec.md +31 -0
  905. package/examples/docs/features/archive/FEAT-120-refund-notification/verification.yaml +84 -0
  906. package/examples/docs/glossary/order.md +15 -0
  907. package/examples/docs/glossary/payments/authorization.md +14 -0
  908. package/examples/docs/likec4.config.json +9 -0
  909. package/examples/docs/loam.json +3 -0
  910. package/examples/docs/services/checkout-web/model.likec4 +109 -0
  911. package/examples/docs/services/checkout-web/spec.md +91 -0
  912. package/examples/docs/services/checkout-web/ui/pages/checkout.page.yaml +40 -0
  913. package/examples/docs/services/checkout-web/ui/pages/order-status.page.yaml +24 -0
  914. package/examples/docs/services/checkout-web/ui/pages/split-payment.page.yaml +26 -0
  915. package/examples/docs/services/order-service/adrs/0001-orchestrated-order-lifecycle.md +52 -0
  916. package/examples/docs/services/order-service/arch.spec.md +127 -0
  917. package/examples/docs/services/order-service/asyncapi.yaml +108 -0
  918. package/examples/docs/services/order-service/health.yaml +57 -0
  919. package/examples/docs/services/order-service/model.likec4 +138 -0
  920. package/examples/docs/services/order-service/openapi.yaml +257 -0
  921. package/examples/docs/services/order-service/runbook.md +62 -0
  922. package/examples/docs/services/order-service/spec.md +134 -0
  923. package/examples/docs/services/payment-service/adrs/0001-payments-outbox.md +18 -0
  924. package/examples/docs/services/payment-service/adrs/0002-idempotency-keys-on-authorization.md +27 -0
  925. package/examples/docs/services/payment-service/arch.spec.md +73 -0
  926. package/examples/docs/services/payment-service/asyncapi.yaml +130 -0
  927. package/examples/docs/services/payment-service/health.yaml +39 -0
  928. package/examples/docs/services/payment-service/model.likec4 +67 -0
  929. package/examples/docs/services/payment-service/openapi.yaml +151 -0
  930. package/examples/docs/services/payment-service/runbook.md +37 -0
  931. package/examples/docs/services/payment-service/spec.md +88 -0
  932. package/examples/docs/services/platform/identity-service/adrs/0001-token-introspection-over-local-validation.md +60 -0
  933. package/examples/docs/services/platform/identity-service/arch.spec.md +117 -0
  934. package/examples/docs/services/platform/identity-service/health.yaml +70 -0
  935. package/examples/docs/services/platform/identity-service/model.likec4 +83 -0
  936. package/examples/docs/services/platform/identity-service/openapi.yaml +197 -0
  937. package/examples/docs/services/platform/identity-service/runbook.md +95 -0
  938. package/examples/docs/services/platform/identity-service/spec.md +119 -0
  939. package/examples/docs/services/platform/notification-service/asyncapi.yaml +199 -0
  940. package/examples/docs/services/platform/notification-service/health.yaml +35 -0
  941. package/examples/docs/services/platform/notification-service/model.likec4 +118 -0
  942. package/examples/docs/services/platform/notification-service/runbook.md +48 -0
  943. package/examples/docs/services/platform/notification-service/spec.md +112 -0
  944. package/examples/docs/services/platform/subsystem.yaml +2 -0
  945. package/examples/fleet.yaml +57 -0
  946. package/package.json +19 -6
  947. package/dist/commands/adopt.js +0 -240
  948. package/dist/commands/adopt.js.map +0 -1
  949. package/dist/commands/archive.js +0 -1313
  950. package/dist/commands/archive.js.map +0 -1
  951. package/dist/commands/delta.js +0 -388
  952. package/dist/commands/delta.js.map +0 -1
  953. package/dist/commands/docs-repo-gate.js.map +0 -1
  954. package/dist/commands/format.js +0 -17
  955. package/dist/commands/format.js.map +0 -1
  956. package/dist/commands/gherkin.js +0 -309
  957. package/dist/commands/gherkin.js.map +0 -1
  958. package/dist/commands/init.js.map +0 -1
  959. package/dist/commands/list.js +0 -295
  960. package/dist/commands/list.js.map +0 -1
  961. package/dist/commands/migrate-openspec.js +0 -950
  962. package/dist/commands/migrate-openspec.js.map +0 -1
  963. package/dist/commands/new.js +0 -413
  964. package/dist/commands/new.js.map +0 -1
  965. package/dist/commands/rebase.js +0 -356
  966. package/dist/commands/rebase.js.map +0 -1
  967. package/dist/commands/show.js.map +0 -1
  968. package/dist/commands/status.js +0 -262
  969. package/dist/commands/status.js.map +0 -1
  970. package/dist/commands/unarchive.js.map +0 -1
  971. package/dist/commands/validate.js +0 -1773
  972. package/dist/commands/validate.js.map +0 -1
  973. package/dist/commands/verify.js +0 -775
  974. package/dist/commands/verify.js.map +0 -1
  975. package/dist/commands/vouch.js +0 -421
  976. package/dist/commands/vouch.js.map +0 -1
  977. package/dist/core/agent.js +0 -2173
  978. package/dist/core/agent.js.map +0 -1
  979. package/dist/core/agents-stamp.js.map +0 -1
  980. package/dist/core/arch.js +0 -130
  981. package/dist/core/arch.js.map +0 -1
  982. package/dist/core/asyncapi.js.map +0 -1
  983. package/dist/core/brief.js +0 -755
  984. package/dist/core/brief.js.map +0 -1
  985. package/dist/core/coherence.js +0 -577
  986. package/dist/core/coherence.js.map +0 -1
  987. package/dist/core/concurrency.js.map +0 -1
  988. package/dist/core/config.js.map +0 -1
  989. package/dist/core/delta.js +0 -476
  990. package/dist/core/delta.js.map +0 -1
  991. package/dist/core/dependencies.js +0 -356
  992. package/dist/core/dependencies.js.map +0 -1
  993. package/dist/core/doctor.js +0 -596
  994. package/dist/core/doctor.js.map +0 -1
  995. package/dist/core/document-bytes.js.map +0 -1
  996. package/dist/core/explore.js.map +0 -1
  997. package/dist/core/frontmatter.js.map +0 -1
  998. package/dist/core/gherkin.js +0 -463
  999. package/dist/core/gherkin.js.map +0 -1
  1000. package/dist/core/health.js +0 -67
  1001. package/dist/core/health.js.map +0 -1
  1002. package/dist/core/ids.js +0 -122
  1003. package/dist/core/ids.js.map +0 -1
  1004. package/dist/core/issue.js +0 -9
  1005. package/dist/core/issue.js.map +0 -1
  1006. package/dist/core/json.js +0 -74
  1007. package/dist/core/json.js.map +0 -1
  1008. package/dist/core/likec4.js +0 -489
  1009. package/dist/core/likec4.js.map +0 -1
  1010. package/dist/core/maturity.js +0 -66
  1011. package/dist/core/maturity.js.map +0 -1
  1012. package/dist/core/openapi-merge.js +0 -552
  1013. package/dist/core/openapi-merge.js.map +0 -1
  1014. package/dist/core/openapi.js.map +0 -1
  1015. package/dist/core/openspec-inventory.js +0 -1440
  1016. package/dist/core/openspec-inventory.js.map +0 -1
  1017. package/dist/core/path-safety.js.map +0 -1
  1018. package/dist/core/provenance.js +0 -787
  1019. package/dist/core/provenance.js.map +0 -1
  1020. package/dist/core/records.js.map +0 -1
  1021. package/dist/core/repo.js +0 -438
  1022. package/dist/core/repo.js.map +0 -1
  1023. package/dist/core/report.js.map +0 -1
  1024. package/dist/core/spec.js +0 -505
  1025. package/dist/core/spec.js.map +0 -1
  1026. package/dist/core/staging.js +0 -890
  1027. package/dist/core/staging.js.map +0 -1
  1028. package/dist/core/status.js +0 -1132
  1029. package/dist/core/status.js.map +0 -1
  1030. package/dist/core/steps.js +0 -72
  1031. package/dist/core/steps.js.map +0 -1
  1032. package/dist/core/verify.js +0 -807
  1033. package/dist/core/verify.js.map +0 -1
  1034. package/dist/core/version.js.map +0 -1
  1035. /package/dist/core/{concurrency.js → kernel/concurrency.js} +0 -0
  1036. /package/dist/core/{records.js → kernel/records.js} +0 -0
@@ -0,0 +1,174 @@
1
+ /**
2
+ * The architecture spec axis — the grammar and resolution of `Covers:` — and
3
+ * the same endpoint join, reused, for the steps of a use case.
4
+ *
5
+ * A business spec will never mention the transactional outbox; that is
6
+ * architecture, and it lives in `arch.spec.md` — same requirement/scenario
7
+ * grammar as spec.md, same delta algebra, same merge. What is new is the
8
+ * `Covers:` line: where a business requirement declares the OPERATIONS it
9
+ * governs, an architecture requirement declares the MODEL OBJECTS its
10
+ * scenarios exercise, so coverage can be derived mechanically instead of
11
+ * trusted to an author who was never going to write the outbox down.
12
+ *
13
+ * Four entry forms, resolved against the documents loam already reads:
14
+ *
15
+ * paymentService.db a C4 element id — resolved against the
16
+ * in-scope elements the way every check joins
17
+ * them: the id itself, or the service the
18
+ * element stands for (binding, then title);
19
+ * paymentService -> kafka an edge — each side resolved the same way,
20
+ * against the declared relationships;
21
+ * alert:<id> / sli:<id> a health signal — ids `health.yaml`
22
+ * declares (core/vocabulary/health.ts);
23
+ * node:<id>, node:a -> node:b a deployment object — a node or an instance
24
+ * in the landscape's `deployment { }` model,
25
+ * matched literally. This is the form that
26
+ * lets a requirement about replication name
27
+ * the two clusters it is written about
28
+ * (ROADMAP's deployment axis).
29
+ *
30
+ * Resolution never reads code. An entry that resolves to nothing is the typo
31
+ * guard (`covers.unknown`, warn); the emitters live with the other validate
32
+ * checks, this module owns only the grammar and the matching.
33
+ *
34
+ * `attributeStep` used to sit at the foot of this file and now lives in
35
+ * `./resolve/steps.ts`. It answers the same shape of question for a different
36
+ * axis — which declared relationship backs a `dynamic view`'s hop — over the
37
+ * same two tiers and the same cached resolver, and the seam was named here long
38
+ * before the line limit forced it. What the two still share is
39
+ * `./resolve/service.ts`'s `resolverFor`, which is where that cache moved with
40
+ * it: one id→service resolver per document, serving both axes.
41
+ */
42
+ import {} from "./likec4.js";
43
+ import { elementService, resolverFor } from "./resolve/service.js";
44
+ /** Parse one comma-separated `Covers:` entry into its form. Never fails: an
45
+ * unclassifiable string is an element entry that will not resolve, and the
46
+ * covers.unknown message is a better diagnosis than a parse refusal. */
47
+ export function parseCoversEntry(raw) {
48
+ const alert = /^alert:\s*(.+)$/.exec(raw);
49
+ if (alert)
50
+ return { form: "alert", id: alert[1].trim(), raw };
51
+ const sli = /^sli:\s*(.+)$/.exec(raw);
52
+ if (sli)
53
+ return { form: "sli", id: sli[1].trim(), raw };
54
+ const edge = /^(.+?)\s*->\s*(.+)$/.exec(raw);
55
+ if (edge) {
56
+ const source = edge[1].trim();
57
+ const target = edge[2].trim();
58
+ const from = nodeId(source);
59
+ const to = nodeId(target);
60
+ // BOTH sides, or neither. A mixed entry stays an ordinary edge whose
61
+ // prefixed side then resolves to nothing — which is the honest answer:
62
+ // there is no edge in any model with one endpoint in the logical map and
63
+ // one in the deployment map, so accepting a half-prefixed line would be
64
+ // inventing a join rather than reading one. The `->` split runs FIRST for
65
+ // the same reason the alert/sli tests do: `node:a -> node:b` read as a
66
+ // single id would be one entry that can never resolve.
67
+ if (from !== undefined && to !== undefined)
68
+ return { form: "node-edge", source: from, target: to, raw };
69
+ return { form: "edge", source, target, raw };
70
+ }
71
+ const node = nodeId(raw);
72
+ if (node !== undefined)
73
+ return { form: "node", id: node, raw };
74
+ return { form: "element", id: raw, raw };
75
+ }
76
+ /** The id behind a `node:` prefix, or nothing when the entry does not carry one. */
77
+ function nodeId(text) {
78
+ const m = /^node:\s*(.+)$/.exec(text);
79
+ return m === null ? undefined : m[1].trim();
80
+ }
81
+ /** Does an element entry name this element? Its id, or the service it stands for. */
82
+ function namesElement(name, e) {
83
+ return e.id === name || elementService(e) === name;
84
+ }
85
+ /** Does an edge entry's side name this relationship endpoint? */
86
+ function namesEndpoint(name, endpointId, elements, known) {
87
+ return endpointId === name || resolverFor(elements, known)(endpointId) === name;
88
+ }
89
+ /** Does a Covers entry match this element? (Only element entries can.) */
90
+ export function coversElement(entry, e) {
91
+ return entry.form === "element" && namesElement(entry.id, e);
92
+ }
93
+ /** Does a Covers entry match this relationship? Endpoints resolved within `elements`, through `known` where the caller has the fleet. */
94
+ export function coversEdge(entry, r, elements, known) {
95
+ return (entry.form === "edge" &&
96
+ namesEndpoint(entry.source, r.source, elements, known) &&
97
+ namesEndpoint(entry.target, r.target, elements, known));
98
+ }
99
+ /** Does a Covers entry name this deployment node or instance? Matched literally — see `entryResolves`. */
100
+ export function coversDeployNode(entry, id) {
101
+ return entry.form === "node" && entry.id === id;
102
+ }
103
+ /** Does a Covers entry name this deployment edge? Both endpoints, literally. */
104
+ export function coversDeployEdge(entry, source, target) {
105
+ return entry.form === "node-edge" && entry.source === source && entry.target === target;
106
+ }
107
+ /** Does the entry resolve to ANYTHING in scope? False is `covers.unknown`. */
108
+ export function entryResolves(entry, scope) {
109
+ switch (entry.form) {
110
+ case "alert":
111
+ return scope.health.alerts.includes(entry.id);
112
+ case "sli":
113
+ return scope.health.slis.includes(entry.id);
114
+ case "edge":
115
+ return scope.relationships.some((r) => coversEdge(entry, r, scope.elements, scope.known));
116
+ case "element":
117
+ return scope.elements.some((e) => coversElement(entry, e));
118
+ case "node":
119
+ return deployedIds(scope).includes(entry.id);
120
+ case "node-edge":
121
+ // Endpoints matched literally, and only literally. The logical forms
122
+ // resolve a name through `serviceResolver` because an author writes
123
+ // `checkout-web -> payment-service` about an edge the model draws between
124
+ // two containers; a deployment id is already the exact path to one place
125
+ // on the map, there is no coarser name for it, and inventing one would
126
+ // make `node:eu.dcA` silently match an edge between two clusters inside
127
+ // it.
128
+ return (scope.deployment?.relationships ?? []).some((r) => r.source === entry.source && r.target === entry.target);
129
+ }
130
+ }
131
+ /** Every deployment object a `node:` entry may name: the nodes, and the instances in them. */
132
+ function deployedIds(scope) {
133
+ const d = scope.deployment;
134
+ if (d === undefined)
135
+ return [];
136
+ return [...d.nodes.map((n) => n.id), ...d.instances.map((i) => i.id)];
137
+ }
138
+ /** Ids a covers.unknown hint may offer for a mistyped entry — always real ones. */
139
+ export function coversCandidates(entry, scope) {
140
+ switch (entry.form) {
141
+ case "alert":
142
+ return closeIds(entry.id, scope.health.alerts).map((id) => `alert:${id}`);
143
+ case "sli":
144
+ return closeIds(entry.id, scope.health.slis).map((id) => `sli:${id}`);
145
+ case "edge":
146
+ case "node-edge":
147
+ // Cheap on purpose: no pairwise edge fuzzing — the sides are element
148
+ // names, so the element hint is the useful one.
149
+ return [];
150
+ case "element":
151
+ return closeIds(entry.id, [...new Set(scope.elements.map((e) => e.id))]);
152
+ case "node":
153
+ // Offered WITH the prefix, because that is the line the author has to
154
+ // type. A hint spelling an id the grammar would then read as an element
155
+ // entry is a hint that sends the reader round the loop a second time.
156
+ return closeIds(entry.id, [...new Set(deployedIds(scope))]).map((id) => `node:${id}`);
157
+ }
158
+ }
159
+ /**
160
+ * Existing ids near a misspelling — substring containment either way, else a
161
+ * shared 3-character prefix. Deliberately dumb: no fuzzy library for one hint,
162
+ * and every id offered is real, so the hint can never point at the typo itself.
163
+ * (Moved here from validate.ts once `covers.unknown` became its second user.)
164
+ */
165
+ export function closeIds(typo, ids) {
166
+ const t = typo.toLowerCase();
167
+ return ids
168
+ .filter((id) => {
169
+ const i = id.toLowerCase();
170
+ return i.includes(t) || t.includes(i) || (t.length >= 3 && i.startsWith(t.slice(0, 3)));
171
+ })
172
+ .slice(0, 5);
173
+ }
174
+ //# sourceMappingURL=arch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"arch.js","sourceRoot":"","sources":["../../../src/core/c4/arch.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The architecture spec axis — the grammar and resolution of `Covers:` — and\n * the same endpoint join, reused, for the steps of a use case.\n *\n * A business spec will never mention the transactional outbox; that is\n * architecture, and it lives in `arch.spec.md` — same requirement/scenario\n * grammar as spec.md, same delta algebra, same merge. What is new is the\n * `Covers:` line: where a business requirement declares the OPERATIONS it\n * governs, an architecture requirement declares the MODEL OBJECTS its\n * scenarios exercise, so coverage can be derived mechanically instead of\n * trusted to an author who was never going to write the outbox down.\n *\n * Four entry forms, resolved against the documents loam already reads:\n *\n * paymentService.db a C4 element id — resolved against the\n * in-scope elements the way every check joins\n * them: the id itself, or the service the\n * element stands for (binding, then title);\n * paymentService -> kafka an edge — each side resolved the same way,\n * against the declared relationships;\n * alert:<id> / sli:<id> a health signal — ids `health.yaml`\n * declares (core/vocabulary/health.ts);\n * node:<id>, node:a -> node:b a deployment object — a node or an instance\n * in the landscape's `deployment { }` model,\n * matched literally. This is the form that\n * lets a requirement about replication name\n * the two clusters it is written about\n * (ROADMAP's deployment axis).\n *\n * Resolution never reads code. An entry that resolves to nothing is the typo\n * guard (`covers.unknown`, warn); the emitters live with the other validate\n * checks, this module owns only the grammar and the matching.\n *\n * `attributeStep` used to sit at the foot of this file and now lives in\n * `./resolve/steps.ts`. It answers the same shape of question for a different\n * axis — which declared relationship backs a `dynamic view`'s hop — over the\n * same two tiers and the same cached resolver, and the seam was named here long\n * before the line limit forced it. What the two still share is\n * `./resolve/service.ts`'s `resolverFor`, which is where that cache moved with\n * it: one id→service resolver per document, serving both axes.\n */\nimport { type Elem, type Rel } from \"./likec4.js\";\nimport type { DeploymentModel } from \"./parsed/deployment.js\";\nimport { elementService, resolverFor } from \"./resolve/service.js\";\nimport type { HealthIds } from \"../vocabulary/health.js\";\n\nexport type CoversEntry =\n | { form: \"element\"; id: string; raw: string }\n | { form: \"edge\"; source: string; target: string; raw: string }\n | { form: \"alert\" | \"sli\"; id: string; raw: string }\n /**\n * A deployment object — `node:eu.dcA.k8sA`, and the edge form\n * `node:a -> node:b`. One prefix covers deployment NODES and the INSTANCES\n * inside them, because both are places on the same map and a requirement\n * about replication names an instance as readily as a datacenter. A second\n * prefix for the second kind would make an author pick between two spellings\n * for one question, and pick wrong.\n */\n | { form: \"node\"; id: string; raw: string }\n | { form: \"node-edge\"; source: string; target: string; raw: string };\n\n/** Parse one comma-separated `Covers:` entry into its form. Never fails: an\n * unclassifiable string is an element entry that will not resolve, and the\n * covers.unknown message is a better diagnosis than a parse refusal. */\nexport function parseCoversEntry(raw: string): CoversEntry {\n const alert = /^alert:\\s*(.+)$/.exec(raw);\n if (alert) return { form: \"alert\", id: alert[1]!.trim(), raw };\n const sli = /^sli:\\s*(.+)$/.exec(raw);\n if (sli) return { form: \"sli\", id: sli[1]!.trim(), raw };\n const edge = /^(.+?)\\s*->\\s*(.+)$/.exec(raw);\n if (edge) {\n const source = edge[1]!.trim();\n const target = edge[2]!.trim();\n const from = nodeId(source);\n const to = nodeId(target);\n // BOTH sides, or neither. A mixed entry stays an ordinary edge whose\n // prefixed side then resolves to nothing — which is the honest answer:\n // there is no edge in any model with one endpoint in the logical map and\n // one in the deployment map, so accepting a half-prefixed line would be\n // inventing a join rather than reading one. The `->` split runs FIRST for\n // the same reason the alert/sli tests do: `node:a -> node:b` read as a\n // single id would be one entry that can never resolve.\n if (from !== undefined && to !== undefined) return { form: \"node-edge\", source: from, target: to, raw };\n return { form: \"edge\", source, target, raw };\n }\n const node = nodeId(raw);\n if (node !== undefined) return { form: \"node\", id: node, raw };\n return { form: \"element\", id: raw, raw };\n}\n\n/** The id behind a `node:` prefix, or nothing when the entry does not carry one. */\nfunction nodeId(text: string): string | undefined {\n const m = /^node:\\s*(.+)$/.exec(text);\n return m === null ? undefined : m[1]!.trim();\n}\n\n/**\n * What `Covers:` entries resolve against: every element and relationship in\n * view (a service's own model plus the landscape; for a feature, the delta\n * plus both), and the health ids of the service whose spec is being read.\n */\nexport interface CoverageScope {\n elements: Elem[];\n relationships: Rel[];\n /**\n * The fleet's topology, for the `node:` forms — the LANDSCAPE's deployment\n * model and no other, even though a service's own `model.likec4` may legally\n * declare one. Topology is a fleet-level fact for the reason a cross-service\n * flow is: `architecture/` is the one place that already holds every edge\n * crossing two services, and a per-service deployment block would let two\n * documents disagree about where one container runs with nothing able to say\n * which is right. Absent for every fleet that draws none, which is what makes\n * a `node:` entry there resolve to nothing and report the typo.\n */\n deployment?: DeploymentModel;\n health: HealthIds;\n /**\n * The enumerated fleet (plus the feature's own `specs/` names, where the\n * caller has them). The Covers matcher resolves edge ENDPOINTS with it, and\n * it must be the SAME set the caller's own findings resolve with: the finding\n * says \"write `Covers: checkout-web -> payment-service`\" with the fleet in\n * hand, and a matcher resolving without it answered that exact line with\n * `covers.unknown` whenever the edge landed on a modelled container.\n */\n known?: ReadonlySet<string>;\n}\n\n/** Does an element entry name this element? Its id, or the service it stands for. */\nfunction namesElement(name: string, e: Elem): boolean {\n return e.id === name || elementService(e) === name;\n}\n\n/** Does an edge entry's side name this relationship endpoint? */\nfunction namesEndpoint(\n name: string,\n endpointId: string,\n elements: Elem[],\n known?: ReadonlySet<string>,\n): boolean {\n return endpointId === name || resolverFor(elements, known)(endpointId) === name;\n}\n\n/** Does a Covers entry match this element? (Only element entries can.) */\nexport function coversElement(entry: CoversEntry, e: Elem): boolean {\n return entry.form === \"element\" && namesElement(entry.id, e);\n}\n\n/** Does a Covers entry match this relationship? Endpoints resolved within `elements`, through `known` where the caller has the fleet. */\nexport function coversEdge(entry: CoversEntry, r: Rel, elements: Elem[], known?: ReadonlySet<string>): boolean {\n return (\n entry.form === \"edge\" &&\n namesEndpoint(entry.source, r.source, elements, known) &&\n namesEndpoint(entry.target, r.target, elements, known)\n );\n}\n\n/** Does a Covers entry name this deployment node or instance? Matched literally — see `entryResolves`. */\nexport function coversDeployNode(entry: CoversEntry, id: string): boolean {\n return entry.form === \"node\" && entry.id === id;\n}\n\n/** Does a Covers entry name this deployment edge? Both endpoints, literally. */\nexport function coversDeployEdge(entry: CoversEntry, source: string, target: string): boolean {\n return entry.form === \"node-edge\" && entry.source === source && entry.target === target;\n}\n\n/** Does the entry resolve to ANYTHING in scope? False is `covers.unknown`. */\nexport function entryResolves(entry: CoversEntry, scope: CoverageScope): boolean {\n switch (entry.form) {\n case \"alert\":\n return scope.health.alerts.includes(entry.id);\n case \"sli\":\n return scope.health.slis.includes(entry.id);\n case \"edge\":\n return scope.relationships.some((r) => coversEdge(entry, r, scope.elements, scope.known));\n case \"element\":\n return scope.elements.some((e) => coversElement(entry, e));\n case \"node\":\n return deployedIds(scope).includes(entry.id);\n case \"node-edge\":\n // Endpoints matched literally, and only literally. The logical forms\n // resolve a name through `serviceResolver` because an author writes\n // `checkout-web -> payment-service` about an edge the model draws between\n // two containers; a deployment id is already the exact path to one place\n // on the map, there is no coarser name for it, and inventing one would\n // make `node:eu.dcA` silently match an edge between two clusters inside\n // it.\n return (scope.deployment?.relationships ?? []).some(\n (r) => r.source === entry.source && r.target === entry.target,\n );\n }\n}\n\n/** Every deployment object a `node:` entry may name: the nodes, and the instances in them. */\nfunction deployedIds(scope: CoverageScope): string[] {\n const d = scope.deployment;\n if (d === undefined) return [];\n return [...d.nodes.map((n) => n.id), ...d.instances.map((i) => i.id)];\n}\n\n/** Ids a covers.unknown hint may offer for a mistyped entry — always real ones. */\nexport function coversCandidates(entry: CoversEntry, scope: CoverageScope): string[] {\n switch (entry.form) {\n case \"alert\":\n return closeIds(entry.id, scope.health.alerts).map((id) => `alert:${id}`);\n case \"sli\":\n return closeIds(entry.id, scope.health.slis).map((id) => `sli:${id}`);\n case \"edge\":\n case \"node-edge\":\n // Cheap on purpose: no pairwise edge fuzzing — the sides are element\n // names, so the element hint is the useful one.\n return [];\n case \"element\":\n return closeIds(entry.id, [...new Set(scope.elements.map((e) => e.id))]);\n case \"node\":\n // Offered WITH the prefix, because that is the line the author has to\n // type. A hint spelling an id the grammar would then read as an element\n // entry is a hint that sends the reader round the loop a second time.\n return closeIds(entry.id, [...new Set(deployedIds(scope))]).map((id) => `node:${id}`);\n }\n}\n\n/**\n * Existing ids near a misspelling — substring containment either way, else a\n * shared 3-character prefix. Deliberately dumb: no fuzzy library for one hint,\n * and every id offered is real, so the hint can never point at the typo itself.\n * (Moved here from validate.ts once `covers.unknown` became its second user.)\n */\nexport function closeIds(typo: string, ids: readonly string[]): string[] {\n const t = typo.toLowerCase();\n return ids\n .filter((id) => {\n const i = id.toLowerCase();\n return i.includes(t) || t.includes(i) || (t.length >= 3 && i.startsWith(t.slice(0, 3)));\n })\n .slice(0, 5);\n}\n\n"]}
@@ -0,0 +1,90 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { LikeC4 } from "likec4";
3
+ import { declaredService } from "../kernel/ids/service.js";
4
+ import { readDynamicViews } from "./parsed/dynamic-views.js";
5
+ import { readViewIds } from "./parsed/view-ids.js";
6
+ import { readSpecification } from "./parsed/specification.js";
7
+ import { readDeployment } from "./parsed/deployment.js";
8
+ import { descText, metaKey } from "./parsed/values.js";
9
+ /** Flatten a LikeC4 model into loam's neutral `Elem`/`Rel` view. */
10
+ export function flattenModel(model) {
11
+ const elements = [...model.elements()].map((e) => {
12
+ // The one crossing between LikeC4's parse output and loam's type system:
13
+ // a `metadata { service '...' }` binding is text somebody wrote, and this
14
+ // is where it acquires a type that says so.
15
+ const bound = metaKey(e.metadata, "service");
16
+ return {
17
+ id: e.id,
18
+ kind: e.kind,
19
+ title: e.title,
20
+ description: descText(e.description),
21
+ ...(bound === undefined ? {} : { service: declaredService(bound) }),
22
+ tags: [...(e.tags ?? [])],
23
+ };
24
+ });
25
+ const relationships = [...model.relationships()].map((r) => ({
26
+ source: r.source.id,
27
+ target: r.target.id,
28
+ // LikeC4 reports an untitled edge as title: null — normalize to the declared `title?: string`.
29
+ title: r.title ?? undefined,
30
+ op: metaKey(r.metadata, "op"),
31
+ publishes: metaKey(r.metadata, "publishes"),
32
+ consumes: metaKey(r.metadata, "consumes"),
33
+ tags: [...(r.tags ?? [])],
34
+ }));
35
+ return { elements, relationships };
36
+ }
37
+ /**
38
+ * Load and validate a single self-contained `.likec4` document, in-process
39
+ * (no external tool, no JVM). Returns validation errors and, if clean, the
40
+ * flattened elements + relationships.
41
+ */
42
+ export async function loadFile(path) {
43
+ return loadSource(await readFile(path, "utf8"));
44
+ }
45
+ /**
46
+ * `loadFile` for text that is not (yet) on disk — what the archive merge uses
47
+ * to prove a computed landscape parses BEFORE anything is written.
48
+ */
49
+ export async function loadSource(src) {
50
+ // LikeC4 owns a Langium workspace and registers a process-exit listener for
51
+ // it. Validation creates many short-lived instances, so every acquired
52
+ // instance must be disposed even on an invalid document or a failed model
53
+ // computation. Its logger is disabled because diagnostics are returned in
54
+ // LoadedDoc instead of being written out-of-band to stderr.
55
+ const likec4 = await LikeC4.fromSource(src, { logger: false });
56
+ try {
57
+ // Assigned, not cast: LikeC4 declares `getErrors()` as a non-nullable array
58
+ // whose element type is structurally wider than ours, so the compiler can
59
+ // check the shape here. The cast was the only thing standing between a
60
+ // dependency renaming `message` and a build that still succeeded — and the
61
+ // `?? []` it carried could never fire.
62
+ const errors = likec4.getErrors();
63
+ if (errors.length > 0) {
64
+ return { errors, elements: [], relationships: [] };
65
+ }
66
+ // `parsedModel`, not `computedModel`: the computed stage RESOLVES every
67
+ // view — expanding its predicates against the model and deriving the
68
+ // ancestor edges a diagram needs (and computing a default view when the
69
+ // document declares none). loam reads what a view DECLARES and never what a
70
+ // view SHOWS (docs/DESIGN.md rule 26), so none of that resolution is ever
71
+ // wanted; it renders nothing. That work is superlinear in the number of
72
+ // RELATIONSHIPS, so a landscape at fleet shape turned `loam list` from under
73
+ // a second into minutes. The elements and relationships below are identical
74
+ // either way. The `await` is load-bearing for anything reading `$data`: it is
75
+ // undefined on the unresolved promise.
76
+ const model = (await likec4.parsedModel());
77
+ return {
78
+ errors,
79
+ specification: readSpecification(model.specification),
80
+ views: readDynamicViews(model),
81
+ viewIds: readViewIds(model),
82
+ deployment: readDeployment(model),
83
+ ...flattenModel(model),
84
+ };
85
+ }
86
+ finally {
87
+ await likec4.dispose();
88
+ }
89
+ }
90
+ //# sourceMappingURL=likec4.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"likec4.js","sourceRoot":"","sources":["../../../src/core/c4/likec4.ts"],"names":[],"mappings":"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","sourcesContent":["import { readFile } from \"node:fs/promises\";\nimport { LikeC4 } from \"likec4\";\nimport { declaredService, type DeclaredService } from \"../kernel/ids/service.js\";\nimport { readDynamicViews, type ParsedView } from \"./parsed/dynamic-views.js\";\nimport { readViewIds, type ViewIdClaim } from \"./parsed/view-ids.js\";\nimport { readSpecification, type DocSpecification } from \"./parsed/specification.js\";\nimport { readDeployment, type DeploymentModel } from \"./parsed/deployment.js\";\nimport { descText, metaKey } from \"./parsed/values.js\";\n\n/** A parse/validation issue reported by LikeC4. */\nexport interface LikeC4Error {\n message: string;\n line?: number;\n sourceFsPath?: string;\n}\n\n/** loam-neutral element view (flattened from the LikeC4 parsed model). */\nexport interface Elem {\n id: string;\n kind: string;\n title: string;\n description?: string;\n /**\n * The `services/<id>` directory this element stands for, from the element's\n * `metadata { service '...' }`. Absent on the elements nobody has bound —\n * see `elementService` for the fallback.\n */\n service?: DeclaredService;\n tags: string[];\n}\n\n/** loam-neutral relationship view. */\nexport interface Rel {\n source: string;\n target: string;\n title?: string;\n /** OpenAPI operationId this call uses, from the relationship's `metadata { op '...' }`. */\n op?: string;\n /**\n * AsyncAPI message this edge PRODUCES, from `metadata { publishes '...' }`.\n * Resolved against the edge SOURCE's own contract: a service publishes what it\n * declares an `action: send` for.\n */\n publishes?: string;\n /**\n * AsyncAPI message this edge CONSUMES, from `metadata { consumes '...' }`.\n * Two keys rather than one directional `message`, because the async spine is\n * not symmetric with the HTTP one: there the PROVIDER owns the contract and\n * every consumer is checked against it, while here the PRODUCER owns the\n * message and the consumer lives in another repository entirely. Which side of\n * an edge owes the declaration has to be readable from the edge itself — the\n * arrow cannot say it, because a Kafka edge points at the broker from both\n * ends.\n */\n consumes?: string;\n tags: string[];\n}\n\nexport interface LoadedDoc {\n errors: LikeC4Error[];\n elements: Elem[];\n relationships: Rel[];\n /**\n * The document's `specification { }` block — what its KINDS declare, as\n * opposed to what its elements do. Optional because a document that did not\n * parse has none, and because the several `LoadedDoc` literals standing in for\n * an absent file (`show`'s missing model.likec4, `unreadableLandscape`) have\n * nothing to put here: a reader must treat \"absent\" and \"declares nothing\" the\n * same way. See `./parsed/specification.ts` for why loam reads it at all —\n * short version: since LikeC4 1.59.0 a kind can carry tags, and only the\n * specification can tell an inherited tag from an authored one.\n */\n specification?: DocSpecification;\n /**\n * The `dynamic view`s the document DECLARES — the ordered steps of a use\n * case, never a rendering (docs/DESIGN.md rule 26). Optional for exactly the\n * reason `specification` is: a document that did not parse has none, and the\n * several `LoadedDoc` literals standing in for an absent file have nothing to\n * put here. Absent and empty mean the same thing to every reader — no views\n * were declared, or none could be read — and neither is a finding: a fleet\n * that draws no diagrams owes loam no views block.\n */\n views?: ParsedView[];\n /**\n * The ids of every view the document AUTHORS, static ones included — a census,\n * not a read of what any of them shows. Separate from `views` above because\n * the two answer different questions off different filters (see\n * `./parsed/view-ids.ts`), and because a static view contributes an id and\n * nothing else loam may look at.\n */\n viewIds?: ViewIdClaim[];\n /**\n * The `deployment { }` model the document declares — nodes, instances and the\n * edges between them (`./parsed/deployment.ts`). Optional for the reason\n * `views` is, and read the same way by every consumer: absent and empty mean\n * \"no topology\", and neither is a finding. A fleet that draws no deployment\n * owes loam none, which is also the whole opt-in the axis has.\n */\n deployment?: DeploymentModel;\n}\n\n/**\n * The slice of a LikeC4 model loam reads: elements and relationships, and on\n * each of those only id/kind/title/description/tags/metadata.\n *\n * It is a type of its own, rather than an inline cast at the one call site,\n * because BOTH of LikeC4's model stages expose exactly this slice — which is\n * what makes the cheap stage a safe substitute for the expensive one. The\n * substitution is pinned in test/likec4-model-parity.test.ts, which flattens\n * both stages through `flattenModel` below and compares the results.\n *\n * Views are deliberately NOT in this interface, even though loam does read them.\n * What this interface pins is the two-stage PARITY that makes the cheap stage a\n * safe substitute for the expensive one — and the stages are not claimed to\n * agree about views, nor need to: the parsed stage is the only one rule 26\n * permits. That read has its own adapter, `./parsed/dynamic-views.ts`.\n */\nexport interface ReadableModel {\n elements: () => Iterable<{\n id: string;\n kind: string;\n title: string;\n description?: unknown;\n tags?: readonly string[];\n metadata?: unknown;\n }>;\n relationships: () => Iterable<{\n source: { id: string };\n target: { id: string };\n title?: string | null;\n tags?: readonly string[];\n metadata?: unknown;\n }>;\n /**\n * The parsed `specification { }` block. Typed `unknown` and normalized by\n * `readSpecification` rather than described here, because it is NOT part of\n * the two-stage parity this interface pins: the shape is LikeC4's internal\n * record (1.59.2 spells element-kind tags and relationship-kind tags\n * differently), and writing it out here would be a structural claim about a\n * dependency's internals that the compiler would then enforce against us.\n */\n specification?: unknown;\n}\n\n/** Flatten a LikeC4 model into loam's neutral `Elem`/`Rel` view. */\nexport function flattenModel(model: ReadableModel): { elements: Elem[]; relationships: Rel[] } {\n const elements: Elem[] = [...model.elements()].map((e) => {\n // The one crossing between LikeC4's parse output and loam's type system:\n // a `metadata { service '...' }` binding is text somebody wrote, and this\n // is where it acquires a type that says so.\n const bound = metaKey(e.metadata, \"service\");\n return {\n id: e.id,\n kind: e.kind,\n title: e.title,\n description: descText(e.description),\n ...(bound === undefined ? {} : { service: declaredService(bound) }),\n tags: [...(e.tags ?? [])],\n };\n });\n const relationships: Rel[] = [...model.relationships()].map((r) => ({\n source: r.source.id,\n target: r.target.id,\n // LikeC4 reports an untitled edge as title: null — normalize to the declared `title?: string`.\n title: r.title ?? undefined,\n op: metaKey(r.metadata, \"op\"),\n publishes: metaKey(r.metadata, \"publishes\"),\n consumes: metaKey(r.metadata, \"consumes\"),\n tags: [...(r.tags ?? [])],\n }));\n return { elements, relationships };\n}\n\n/**\n * Load and validate a single self-contained `.likec4` document, in-process\n * (no external tool, no JVM). Returns validation errors and, if clean, the\n * flattened elements + relationships.\n */\nexport async function loadFile(path: string): Promise<LoadedDoc> {\n return loadSource(await readFile(path, \"utf8\"));\n}\n\n/**\n * `loadFile` for text that is not (yet) on disk — what the archive merge uses\n * to prove a computed landscape parses BEFORE anything is written.\n */\nexport async function loadSource(src: string): Promise<LoadedDoc> {\n // LikeC4 owns a Langium workspace and registers a process-exit listener for\n // it. Validation creates many short-lived instances, so every acquired\n // instance must be disposed even on an invalid document or a failed model\n // computation. Its logger is disabled because diagnostics are returned in\n // LoadedDoc instead of being written out-of-band to stderr.\n const likec4 = await LikeC4.fromSource(src, { logger: false });\n try {\n // Assigned, not cast: LikeC4 declares `getErrors()` as a non-nullable array\n // whose element type is structurally wider than ours, so the compiler can\n // check the shape here. The cast was the only thing standing between a\n // dependency renaming `message` and a build that still succeeded — and the\n // `?? []` it carried could never fire.\n const errors: LikeC4Error[] = likec4.getErrors();\n if (errors.length > 0) {\n return { errors, elements: [], relationships: [] };\n }\n\n // `parsedModel`, not `computedModel`: the computed stage RESOLVES every\n // view — expanding its predicates against the model and deriving the\n // ancestor edges a diagram needs (and computing a default view when the\n // document declares none). loam reads what a view DECLARES and never what a\n // view SHOWS (docs/DESIGN.md rule 26), so none of that resolution is ever\n // wanted; it renders nothing. That work is superlinear in the number of\n // RELATIONSHIPS, so a landscape at fleet shape turned `loam list` from under\n // a second into minutes. The elements and relationships below are identical\n // either way. The `await` is load-bearing for anything reading `$data`: it is\n // undefined on the unresolved promise.\n const model = (await likec4.parsedModel()) as ReadableModel;\n return {\n errors,\n specification: readSpecification(model.specification),\n views: readDynamicViews(model),\n viewIds: readViewIds(model),\n deployment: readDeployment(model),\n ...flattenModel(model),\n };\n } finally {\n await likec4.dispose();\n }\n}\n"]}
@@ -0,0 +1,158 @@
1
+ /**
2
+ * The DEPLOYMENT model a document declares — which physical nodes exist, which
3
+ * containers are instanced where, and what talks to what across them.
4
+ *
5
+ * A `deployment { }` block has been legal in a docs repo since LikeC4 could
6
+ * parse one, and until this reader existed loam saw none of it. The parser
7
+ * resolved every `instanceOf` — so a container renamed out from under a
8
+ * deployment node already failed the gate — and after that no requirement could
9
+ * name a node, no `#obl-` tag on a datacenter was graded, and the context pack
10
+ * an agent implements from did not mention topology at all. Integrity held at
11
+ * the level of syntax and was absent at the level of requirements. ROADMAP's
12
+ * deployment axis and `meta/docs/features/FEAT-1-the-deployment-axis/` are the
13
+ * item and the specification; this module is its first half.
14
+ *
15
+ * ## Why this is a `parsed/` reader and not a package of its own
16
+ *
17
+ * It is the same job the three modules beside it do: take one corner of
18
+ * LikeC4's parse output and hand back a loam-neutral record, defensively, with
19
+ * its shape assumptions owned outright. `readSpecification`, `readDynamicViews`
20
+ * and `readViewIds` are all called on the line above `flattenModel(model)` in
21
+ * each of loam's three loaders, and so is this. FEAT-1's delta said
22
+ * `src/core/c4/deploy/`; a package holding this alone would be a directory
23
+ * pretending to be a subject (docs/DESIGN.md), and the delta was corrected
24
+ * rather than the code bent to it — which is what an unarchived feature is for.
25
+ *
26
+ * **`parsed/` is now AT its five-file limit.** The next reader here needs a
27
+ * split first, and the seam to split on is the one this file does not share:
28
+ * `dynamic-views.ts` and `view-ids.ts` read `$data`, this one and
29
+ * `specification.ts` read the model surface.
30
+ *
31
+ * ## What is read, and what is deliberately left
32
+ *
33
+ * Nodes, instances and relationships, with the ids, titles and tags each
34
+ * carries. MEASURED at the 1.59.2 pin, and every line of it needed measuring
35
+ * rather than assuming:
36
+ *
37
+ * - `nodes()` returns deployment NODES only — an `instanceOf` is not among
38
+ * them, which is why instances are a second list rather than a filter.
39
+ * - an instance carries the LOGICAL element it deploys as `element.id`, and
40
+ * that is the whole join back to the C4 model: `eu.a.dbA -> orders.db`.
41
+ * - both nodes and instances carry `tags`, so `#obl-geo` on a datacenter is
42
+ * readable — the fail-open case that made this an item.
43
+ * - a relationship carries `tags` and `metadata` DIRECTLY (`r.metadata`, no
44
+ * `$relationship` indirection), and both model stages return byte-identical
45
+ * results, which is what lets `test/likec4-model-parity.test.ts` cover this
46
+ * read with the substitution it already pins.
47
+ * - a document with NO `deployment { }` block still returns a deployment
48
+ * object whose three iterators are empty. Absent and empty are therefore the
49
+ * same answer here, deliberately: no reader may distinguish "declares none"
50
+ * from "could not be read", because the second is what the defensive returns
51
+ * below produce and a fleet that draws no topology owes loam nothing.
52
+ *
53
+ * `metadata` is NOT carried on the records below, and neither is an instance's
54
+ * `kind`. Both are readable; no check reads them yet, and a field carried
55
+ * before a caller needs it is a field nobody notices going wrong. Add one with
56
+ * the check that consumes it.
57
+ */
58
+ /** No topology — what an absent block and an unreadable one both come back as. */
59
+ export const NO_DEPLOYMENT = { nodes: [], instances: [], relationships: [] };
60
+ /** Is there anything here? The opt-in every deployment check is gated on. */
61
+ export function hasDeployment(d) {
62
+ return d.nodes.length > 0 || d.instances.length > 0 || d.relationships.length > 0;
63
+ }
64
+ /** A record, or nothing — the parse surface hands back `unknown`. */
65
+ function record(v) {
66
+ return v && typeof v === "object" && !Array.isArray(v) ? v : undefined;
67
+ }
68
+ /** An iterable produced by `name()`, or an empty one when the surface is not what we measured. */
69
+ function iterate(source, name) {
70
+ const fn = source[name];
71
+ if (typeof fn !== "function")
72
+ return [];
73
+ try {
74
+ const out = fn.call(source);
75
+ // A generator satisfies this; so does an array. Anything else is a shape
76
+ // change upstream, and the honest answer to one is "no topology read".
77
+ return out !== null && typeof out === "object" && Symbol.iterator in out
78
+ ? [...out]
79
+ : [];
80
+ }
81
+ catch {
82
+ return [];
83
+ }
84
+ }
85
+ /** A string field, or the empty string — never `undefined` leaking into a record. */
86
+ function str(o, key) {
87
+ const v = o[key];
88
+ return typeof v === "string" ? v : "";
89
+ }
90
+ /** Tags as loam models them: a plain array of strings, always present. */
91
+ function tags(o) {
92
+ const v = o["tags"];
93
+ return Array.isArray(v) ? v.filter((t) => typeof t === "string") : [];
94
+ }
95
+ /**
96
+ * Read the deployment model off an awaited `parsedModel()`.
97
+ *
98
+ * Defensive throughout, in the shape `readViewIds` established: an entry
99
+ * missing the one field that identifies it is DROPPED rather than reported with
100
+ * a hole, and a surface that is not what was measured yields an empty model
101
+ * instead of throwing. A check that cannot see the topology must say
102
+ * could-not-look through its own silence, never fail the fleet's parse.
103
+ */
104
+ export function readDeployment(model) {
105
+ const root = record(model);
106
+ if (root === undefined)
107
+ return NO_DEPLOYMENT;
108
+ const deployment = record(root["deployment"]);
109
+ if (deployment === undefined)
110
+ return NO_DEPLOYMENT;
111
+ const nodes = [];
112
+ for (const raw of iterate(deployment, "nodes")) {
113
+ const n = record(raw);
114
+ if (n === undefined)
115
+ continue;
116
+ const id = str(n, "id");
117
+ if (id === "")
118
+ continue;
119
+ nodes.push({ id, kind: str(n, "kind"), title: str(n, "title"), tags: tags(n) });
120
+ }
121
+ const instances = [];
122
+ for (const raw of iterate(deployment, "instances")) {
123
+ const i = record(raw);
124
+ if (i === undefined)
125
+ continue;
126
+ const id = str(i, "id");
127
+ // The logical element is the whole point of the record. An instance whose
128
+ // element cannot be read joins to nothing, so reporting it would put a
129
+ // deployed thing on the map that no requirement could ever cover.
130
+ const element = record(i["element"]);
131
+ if (id === "" || element === undefined)
132
+ continue;
133
+ const elementId = str(element, "id");
134
+ if (elementId === "")
135
+ continue;
136
+ instances.push({ id, element: elementId, title: str(i, "title"), tags: tags(i) });
137
+ }
138
+ const relationships = [];
139
+ for (const raw of iterate(deployment, "relationships")) {
140
+ const r = record(raw);
141
+ if (r === undefined)
142
+ continue;
143
+ const source = record(r["source"]);
144
+ const target = record(r["target"]);
145
+ if (source === undefined || target === undefined)
146
+ continue;
147
+ const from = str(source, "id");
148
+ const to = str(target, "id");
149
+ if (from === "" || to === "")
150
+ continue;
151
+ // LikeC4 reports an untitled edge as `title: null` — normalized to the
152
+ // declared optional exactly as `flattenModel` does for the logical model.
153
+ const title = typeof r["title"] === "string" ? r["title"] : undefined;
154
+ relationships.push({ source: from, target: to, ...(title === undefined ? {} : { title }), tags: tags(r) });
155
+ }
156
+ return { nodes, instances, relationships };
157
+ }
158
+ //# sourceMappingURL=deployment.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deployment.js","sourceRoot":"","sources":["../../../../src/core/c4/parsed/deployment.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The DEPLOYMENT model a document declares — which physical nodes exist, which\n * containers are instanced where, and what talks to what across them.\n *\n * A `deployment { }` block has been legal in a docs repo since LikeC4 could\n * parse one, and until this reader existed loam saw none of it. The parser\n * resolved every `instanceOf` — so a container renamed out from under a\n * deployment node already failed the gate — and after that no requirement could\n * name a node, no `#obl-` tag on a datacenter was graded, and the context pack\n * an agent implements from did not mention topology at all. Integrity held at\n * the level of syntax and was absent at the level of requirements. ROADMAP's\n * deployment axis and `meta/docs/features/FEAT-1-the-deployment-axis/` are the\n * item and the specification; this module is its first half.\n *\n * ## Why this is a `parsed/` reader and not a package of its own\n *\n * It is the same job the three modules beside it do: take one corner of\n * LikeC4's parse output and hand back a loam-neutral record, defensively, with\n * its shape assumptions owned outright. `readSpecification`, `readDynamicViews`\n * and `readViewIds` are all called on the line above `flattenModel(model)` in\n * each of loam's three loaders, and so is this. FEAT-1's delta said\n * `src/core/c4/deploy/`; a package holding this alone would be a directory\n * pretending to be a subject (docs/DESIGN.md), and the delta was corrected\n * rather than the code bent to it — which is what an unarchived feature is for.\n *\n * **`parsed/` is now AT its five-file limit.** The next reader here needs a\n * split first, and the seam to split on is the one this file does not share:\n * `dynamic-views.ts` and `view-ids.ts` read `$data`, this one and\n * `specification.ts` read the model surface.\n *\n * ## What is read, and what is deliberately left\n *\n * Nodes, instances and relationships, with the ids, titles and tags each\n * carries. MEASURED at the 1.59.2 pin, and every line of it needed measuring\n * rather than assuming:\n *\n * - `nodes()` returns deployment NODES only — an `instanceOf` is not among\n * them, which is why instances are a second list rather than a filter.\n * - an instance carries the LOGICAL element it deploys as `element.id`, and\n * that is the whole join back to the C4 model: `eu.a.dbA -> orders.db`.\n * - both nodes and instances carry `tags`, so `#obl-geo` on a datacenter is\n * readable — the fail-open case that made this an item.\n * - a relationship carries `tags` and `metadata` DIRECTLY (`r.metadata`, no\n * `$relationship` indirection), and both model stages return byte-identical\n * results, which is what lets `test/likec4-model-parity.test.ts` cover this\n * read with the substitution it already pins.\n * - a document with NO `deployment { }` block still returns a deployment\n * object whose three iterators are empty. Absent and empty are therefore the\n * same answer here, deliberately: no reader may distinguish \"declares none\"\n * from \"could not be read\", because the second is what the defensive returns\n * below produce and a fleet that draws no topology owes loam nothing.\n *\n * `metadata` is NOT carried on the records below, and neither is an instance's\n * `kind`. Both are readable; no check reads them yet, and a field carried\n * before a caller needs it is a field nobody notices going wrong. Add one with\n * the check that consumes it.\n */\n\n/** One deployment node — a region, a datacenter, a cluster; the kinds are the fleet's own. */\nexport interface DeployNode {\n /** The dotted path LikeC4 gives it: `eu.dcA.k8sA`. */\n id: string;\n /** The `deploymentNode` kind the specification declares. */\n kind: string;\n title: string;\n tags: string[];\n}\n\n/** One deployed instance of a logical element. */\nexport interface DeployInstance {\n id: string;\n /**\n * The id of the C4 element this instance deploys — the join back to the\n * logical model, and the only reason an instance is worth reading at all.\n */\n element: string;\n title: string;\n tags: string[];\n}\n\n/** One edge between deployment objects — replication, failover, a network hop. */\nexport interface DeployRel {\n source: string;\n target: string;\n title?: string;\n tags: string[];\n}\n\n/** A document's whole deployment model, flattened. */\nexport interface DeploymentModel {\n nodes: DeployNode[];\n instances: DeployInstance[];\n relationships: DeployRel[];\n}\n\n/** No topology — what an absent block and an unreadable one both come back as. */\nexport const NO_DEPLOYMENT: DeploymentModel = { nodes: [], instances: [], relationships: [] };\n\n/** Is there anything here? The opt-in every deployment check is gated on. */\nexport function hasDeployment(d: DeploymentModel): boolean {\n return d.nodes.length > 0 || d.instances.length > 0 || d.relationships.length > 0;\n}\n\n/** A record, or nothing — the parse surface hands back `unknown`. */\nfunction record(v: unknown): Record<string, unknown> | undefined {\n return v && typeof v === \"object\" && !Array.isArray(v) ? (v as Record<string, unknown>) : undefined;\n}\n\n/** An iterable produced by `name()`, or an empty one when the surface is not what we measured. */\nfunction iterate(source: Record<string, unknown>, name: string): unknown[] {\n const fn = source[name];\n if (typeof fn !== \"function\") return [];\n try {\n const out: unknown = (fn as () => unknown).call(source);\n // A generator satisfies this; so does an array. Anything else is a shape\n // change upstream, and the honest answer to one is \"no topology read\".\n return out !== null && typeof out === \"object\" && Symbol.iterator in (out as object)\n ? [...(out as Iterable<unknown>)]\n : [];\n } catch {\n return [];\n }\n}\n\n/** A string field, or the empty string — never `undefined` leaking into a record. */\nfunction str(o: Record<string, unknown>, key: string): string {\n const v = o[key];\n return typeof v === \"string\" ? v : \"\";\n}\n\n/** Tags as loam models them: a plain array of strings, always present. */\nfunction tags(o: Record<string, unknown>): string[] {\n const v = o[\"tags\"];\n return Array.isArray(v) ? v.filter((t): t is string => typeof t === \"string\") : [];\n}\n\n/**\n * Read the deployment model off an awaited `parsedModel()`.\n *\n * Defensive throughout, in the shape `readViewIds` established: an entry\n * missing the one field that identifies it is DROPPED rather than reported with\n * a hole, and a surface that is not what was measured yields an empty model\n * instead of throwing. A check that cannot see the topology must say\n * could-not-look through its own silence, never fail the fleet's parse.\n */\nexport function readDeployment(model: unknown): DeploymentModel {\n const root = record(model);\n if (root === undefined) return NO_DEPLOYMENT;\n const deployment = record(root[\"deployment\"]);\n if (deployment === undefined) return NO_DEPLOYMENT;\n\n const nodes: DeployNode[] = [];\n for (const raw of iterate(deployment, \"nodes\")) {\n const n = record(raw);\n if (n === undefined) continue;\n const id = str(n, \"id\");\n if (id === \"\") continue;\n nodes.push({ id, kind: str(n, \"kind\"), title: str(n, \"title\"), tags: tags(n) });\n }\n\n const instances: DeployInstance[] = [];\n for (const raw of iterate(deployment, \"instances\")) {\n const i = record(raw);\n if (i === undefined) continue;\n const id = str(i, \"id\");\n // The logical element is the whole point of the record. An instance whose\n // element cannot be read joins to nothing, so reporting it would put a\n // deployed thing on the map that no requirement could ever cover.\n const element = record(i[\"element\"]);\n if (id === \"\" || element === undefined) continue;\n const elementId = str(element, \"id\");\n if (elementId === \"\") continue;\n instances.push({ id, element: elementId, title: str(i, \"title\"), tags: tags(i) });\n }\n\n const relationships: DeployRel[] = [];\n for (const raw of iterate(deployment, \"relationships\")) {\n const r = record(raw);\n if (r === undefined) continue;\n const source = record(r[\"source\"]);\n const target = record(r[\"target\"]);\n if (source === undefined || target === undefined) continue;\n const from = str(source, \"id\");\n const to = str(target, \"id\");\n if (from === \"\" || to === \"\") continue;\n // LikeC4 reports an untitled edge as `title: null` — normalized to the\n // declared optional exactly as `flattenModel` does for the logical model.\n const title = typeof r[\"title\"] === \"string\" ? r[\"title\"] : undefined;\n relationships.push({ source: from, target: to, ...(title === undefined ? {} : { title }), tags: tags(r) });\n }\n\n return { nodes, instances, relationships };\n}\n"]}