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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1256) hide show
  1. package/CHANGELOG.md +5992 -82
  2. package/COMPARISON.md +168 -63
  3. package/CONTRIBUTING.md +121 -0
  4. package/MIGRATING-from-OpenSpec.md +238 -55
  5. package/QUICKSTART.md +302 -0
  6. package/README.md +653 -144
  7. package/ROADMAP.md +1035 -0
  8. package/SCHEMA.md +3916 -263
  9. package/SECURITY.md +21 -3
  10. package/WORKFLOW.md +927 -0
  11. package/dist/cli.js +133 -21
  12. package/dist/cli.js.map +1 -1
  13. package/dist/commands/adopt/adopt.js +204 -0
  14. package/dist/commands/adopt/adopt.js.map +1 -0
  15. package/dist/commands/adopt/render.js +309 -0
  16. package/dist/commands/adopt/render.js.map +1 -0
  17. package/dist/commands/archive/archive.js +74 -0
  18. package/dist/commands/archive/archive.js.map +1 -0
  19. package/dist/commands/archive/closing.js +42 -0
  20. package/dist/commands/archive/closing.js.map +1 -0
  21. package/dist/commands/archive/plan/contracts/asyncapi.js +172 -0
  22. package/dist/commands/archive/plan/contracts/asyncapi.js.map +1 -0
  23. package/dist/commands/archive/plan/contracts/consumers.js +56 -0
  24. package/dist/commands/archive/plan/contracts/consumers.js.map +1 -0
  25. package/dist/commands/archive/plan/contracts/openapi.js +193 -0
  26. package/dist/commands/archive/plan/contracts/openapi.js.map +1 -0
  27. package/dist/commands/archive/plan/contracts/verdict-lines.js +103 -0
  28. package/dist/commands/archive/plan/contracts/verdict-lines.js.map +1 -0
  29. package/dist/commands/archive/plan/document/head.js +151 -0
  30. package/dist/commands/archive/plan/document/head.js.map +1 -0
  31. package/dist/commands/archive/plan/document/links.js +284 -0
  32. package/dist/commands/archive/plan/document/links.js.map +1 -0
  33. package/dist/commands/archive/plan/document/run.js +136 -0
  34. package/dist/commands/archive/plan/document/run.js.map +1 -0
  35. package/dist/commands/archive/plan/gate.js +319 -0
  36. package/dist/commands/archive/plan/gate.js.map +1 -0
  37. package/dist/commands/archive/plan/landscape.js +298 -0
  38. package/dist/commands/archive/plan/landscape.js.map +1 -0
  39. package/dist/commands/archive/plan/model/extending.js +85 -0
  40. package/dist/commands/archive/plan/model/extending.js.map +1 -0
  41. package/dist/commands/archive/plan/refusal.js +106 -0
  42. package/dist/commands/archive/plan/refusal.js.map +1 -0
  43. package/dist/commands/archive/plan/specs.js +318 -0
  44. package/dist/commands/archive/plan/specs.js.map +1 -0
  45. package/dist/commands/archive/plan/state.js +30 -0
  46. package/dist/commands/archive/plan/state.js.map +1 -0
  47. package/dist/commands/archive/run.js +355 -0
  48. package/dist/commands/archive/run.js.map +1 -0
  49. package/dist/commands/archive/shipped.js +49 -0
  50. package/dist/commands/archive/shipped.js.map +1 -0
  51. package/dist/commands/context/context.js +166 -0
  52. package/dist/commands/context/context.js.map +1 -0
  53. package/dist/commands/context/print.js +305 -0
  54. package/dist/commands/context/print.js.map +1 -0
  55. package/dist/commands/delta/delta.js +367 -0
  56. package/dist/commands/delta/delta.js.map +1 -0
  57. package/dist/commands/delta/print.js +221 -0
  58. package/dist/commands/delta/print.js.map +1 -0
  59. package/dist/commands/dependencies.js +6 -8
  60. package/dist/commands/dependencies.js.map +1 -1
  61. package/dist/commands/diff/diff.js +86 -0
  62. package/dist/commands/diff/diff.js.map +1 -0
  63. package/dist/commands/diff/print.js +38 -0
  64. package/dist/commands/diff/print.js.map +1 -0
  65. package/dist/commands/doctor.js +65 -5
  66. package/dist/commands/doctor.js.map +1 -1
  67. package/dist/commands/explain/explain.js +227 -0
  68. package/dist/commands/explain/explain.js.map +1 -0
  69. package/dist/commands/explore.js +39 -28
  70. package/dist/commands/explore.js.map +1 -1
  71. package/dist/commands/gate/gate.js +152 -0
  72. package/dist/commands/gate/gate.js.map +1 -0
  73. package/dist/commands/gate/print.js +66 -0
  74. package/dist/commands/gate/print.js.map +1 -0
  75. package/dist/commands/gherkin/commit.js +105 -0
  76. package/dist/commands/gherkin/commit.js.map +1 -0
  77. package/dist/commands/gherkin/gherkin.js +262 -0
  78. package/dist/commands/gherkin/gherkin.js.map +1 -0
  79. package/dist/commands/gherkin/reconcile.js +146 -0
  80. package/dist/commands/gherkin/reconcile.js.map +1 -0
  81. package/dist/commands/gherkin/render.js +77 -0
  82. package/dist/commands/gherkin/render.js.map +1 -0
  83. package/dist/commands/init/example.js +204 -0
  84. package/dist/commands/init/example.js.map +1 -0
  85. package/dist/commands/init/first-hour.js +72 -0
  86. package/dist/commands/init/first-hour.js.map +1 -0
  87. package/dist/commands/{init.js → init/init.js} +142 -71
  88. package/dist/commands/init/init.js.map +1 -0
  89. package/dist/commands/init/mcp.js +131 -0
  90. package/dist/commands/init/mcp.js.map +1 -0
  91. package/dist/commands/init/options.js +78 -0
  92. package/dist/commands/init/options.js.map +1 -0
  93. package/dist/commands/instructions.js +72 -14
  94. package/dist/commands/instructions.js.map +1 -1
  95. package/dist/commands/list/campaign/campaign.js +63 -0
  96. package/dist/commands/list/campaign/campaign.js.map +1 -0
  97. package/dist/commands/list/campaign/owners.js +65 -0
  98. package/dist/commands/list/campaign/owners.js.map +1 -0
  99. package/dist/commands/list/json.js +155 -0
  100. package/dist/commands/list/json.js.map +1 -0
  101. package/dist/commands/list/list.js +358 -0
  102. package/dist/commands/list/list.js.map +1 -0
  103. package/dist/commands/list/print.js +344 -0
  104. package/dist/commands/list/print.js.map +1 -0
  105. package/dist/commands/list/review.js +120 -0
  106. package/dist/commands/list/review.js.map +1 -0
  107. package/dist/commands/list/suites/suites.js +140 -0
  108. package/dist/commands/list/suites/suites.js.map +1 -0
  109. package/dist/commands/list/views.js +108 -0
  110. package/dist/commands/list/views.js.map +1 -0
  111. package/dist/commands/mcp/dispatch.js +238 -0
  112. package/dist/commands/mcp/dispatch.js.map +1 -0
  113. package/dist/commands/mcp/mcp.js +75 -0
  114. package/dist/commands/mcp/mcp.js.map +1 -0
  115. package/dist/commands/mcp/serve.js +55 -0
  116. package/dist/commands/mcp/serve.js.map +1 -0
  117. package/dist/commands/migrate-openspec/materialize/active.js +175 -0
  118. package/dist/commands/migrate-openspec/materialize/active.js.map +1 -0
  119. package/dist/commands/migrate-openspec/materialize/feature.js +41 -0
  120. package/dist/commands/migrate-openspec/materialize/feature.js.map +1 -0
  121. package/dist/commands/migrate-openspec/materialize/living.js +62 -0
  122. package/dist/commands/migrate-openspec/materialize/living.js.map +1 -0
  123. package/dist/commands/migrate-openspec/materialize/stage.js +143 -0
  124. package/dist/commands/migrate-openspec/materialize/stage.js.map +1 -0
  125. package/dist/commands/migrate-openspec/materialize/target.js +219 -0
  126. package/dist/commands/migrate-openspec/materialize/target.js.map +1 -0
  127. package/dist/commands/migrate-openspec/migrate-openspec.js +142 -0
  128. package/dist/commands/migrate-openspec/migrate-openspec.js.map +1 -0
  129. package/dist/commands/migrate-openspec/openspec/decisions.js +86 -0
  130. package/dist/commands/migrate-openspec/openspec/decisions.js.map +1 -0
  131. package/dist/commands/migrate-openspec/openspec/error.js +18 -0
  132. package/dist/commands/migrate-openspec/openspec/error.js.map +1 -0
  133. package/dist/commands/migrate-openspec/openspec/mapping.js +162 -0
  134. package/dist/commands/migrate-openspec/openspec/mapping.js.map +1 -0
  135. package/dist/commands/migrate-openspec/openspec/paths.js +40 -0
  136. package/dist/commands/migrate-openspec/openspec/paths.js.map +1 -0
  137. package/dist/commands/migrate-openspec/openspec/read.js +49 -0
  138. package/dist/commands/migrate-openspec/openspec/read.js.map +1 -0
  139. package/dist/commands/migrate-openspec/print.js +89 -0
  140. package/dist/commands/migrate-openspec/print.js.map +1 -0
  141. package/dist/commands/new/capability-template.js +118 -0
  142. package/dist/commands/new/capability-template.js.map +1 -0
  143. package/dist/commands/new/commit.js +62 -0
  144. package/dist/commands/new/commit.js.map +1 -0
  145. package/dist/commands/new/modifies.js +206 -0
  146. package/dist/commands/new/modifies.js.map +1 -0
  147. package/dist/commands/new/new.js +328 -0
  148. package/dist/commands/new/new.js.map +1 -0
  149. package/dist/commands/new/templates.js +279 -0
  150. package/dist/commands/new/templates.js.map +1 -0
  151. package/dist/commands/open.js +199 -0
  152. package/dist/commands/open.js.map +1 -0
  153. package/dist/commands/policy/format.js +152 -0
  154. package/dist/commands/policy/format.js.map +1 -0
  155. package/dist/commands/{docs-repo-gate.js → policy/gate.js} +38 -11
  156. package/dist/commands/policy/gate.js.map +1 -0
  157. package/dist/commands/rebase/edit.js +106 -0
  158. package/dist/commands/rebase/edit.js.map +1 -0
  159. package/dist/commands/rebase/living.js +185 -0
  160. package/dist/commands/rebase/living.js.map +1 -0
  161. package/dist/commands/rebase/plan.js +245 -0
  162. package/dist/commands/rebase/plan.js.map +1 -0
  163. package/dist/commands/rebase/rebase.js +300 -0
  164. package/dist/commands/rebase/rebase.js.map +1 -0
  165. package/dist/commands/seed/commit.js +221 -0
  166. package/dist/commands/seed/commit.js.map +1 -0
  167. package/dist/commands/seed/plan.js +278 -0
  168. package/dist/commands/seed/plan.js.map +1 -0
  169. package/dist/commands/seed/seed.js +174 -0
  170. package/dist/commands/seed/seed.js.map +1 -0
  171. package/dist/commands/show/feature.js +182 -0
  172. package/dist/commands/show/feature.js.map +1 -0
  173. package/dist/commands/show/introduced.js +157 -0
  174. package/dist/commands/show/introduced.js.map +1 -0
  175. package/dist/commands/show/marks.js +53 -0
  176. package/dist/commands/show/marks.js.map +1 -0
  177. package/dist/commands/show/service.js +239 -0
  178. package/dist/commands/show/service.js.map +1 -0
  179. package/dist/commands/show/show.js +87 -0
  180. package/dist/commands/show/show.js.map +1 -0
  181. package/dist/commands/status/fleet-next.js +90 -0
  182. package/dist/commands/status/fleet-next.js.map +1 -0
  183. package/dist/commands/status/json.js +47 -0
  184. package/dist/commands/status/json.js.map +1 -0
  185. package/dist/commands/status/print.js +209 -0
  186. package/dist/commands/status/print.js.map +1 -0
  187. package/dist/commands/status/status.js +115 -0
  188. package/dist/commands/status/status.js.map +1 -0
  189. package/dist/commands/steps/steps.js +269 -0
  190. package/dist/commands/steps/steps.js.map +1 -0
  191. package/dist/commands/subsystem/edit.js +192 -0
  192. package/dist/commands/subsystem/edit.js.map +1 -0
  193. package/dist/commands/subsystem/move.js +325 -0
  194. package/dist/commands/subsystem/move.js.map +1 -0
  195. package/dist/commands/subsystem/query.js +113 -0
  196. package/dist/commands/subsystem/query.js.map +1 -0
  197. package/dist/commands/subsystem/subsystem.js +98 -0
  198. package/dist/commands/subsystem/subsystem.js.map +1 -0
  199. package/dist/commands/subsystem/sync.js +318 -0
  200. package/dist/commands/subsystem/sync.js.map +1 -0
  201. package/dist/commands/subsystem/txn/exclude.js +132 -0
  202. package/dist/commands/subsystem/txn/exclude.js.map +1 -0
  203. package/dist/commands/subsystem/txn/links.js +128 -0
  204. package/dist/commands/subsystem/txn/links.js.map +1 -0
  205. package/dist/commands/subsystem/txn/report.js +174 -0
  206. package/dist/commands/subsystem/txn/report.js.map +1 -0
  207. package/dist/commands/subsystem/txn/txn.js +196 -0
  208. package/dist/commands/subsystem/txn/txn.js.map +1 -0
  209. package/dist/commands/subsystem/txn/views.js +249 -0
  210. package/dist/commands/subsystem/txn/views.js.map +1 -0
  211. package/dist/commands/tasks/actions.js +107 -0
  212. package/dist/commands/tasks/actions.js.map +1 -0
  213. package/dist/commands/tasks/render.js +253 -0
  214. package/dist/commands/tasks/render.js.map +1 -0
  215. package/dist/commands/tasks/tasks.js +119 -0
  216. package/dist/commands/tasks/tasks.js.map +1 -0
  217. package/dist/commands/unarchive/manifest.js +176 -0
  218. package/dist/commands/unarchive/manifest.js.map +1 -0
  219. package/dist/commands/unarchive/restore.js +254 -0
  220. package/dist/commands/unarchive/restore.js.map +1 -0
  221. package/dist/commands/unarchive/unarchive.js +59 -0
  222. package/dist/commands/unarchive/unarchive.js.map +1 -0
  223. package/dist/commands/validate/arch-coverage.js +245 -0
  224. package/dist/commands/validate/arch-coverage.js.map +1 -0
  225. package/dist/commands/validate/checks/fleet-shape.js +204 -0
  226. package/dist/commands/validate/checks/fleet-shape.js.map +1 -0
  227. package/dist/commands/validate/checks/health-deps.js +58 -0
  228. package/dist/commands/validate/checks/health-deps.js.map +1 -0
  229. package/dist/commands/validate/checks/introduced.js +102 -0
  230. package/dist/commands/validate/checks/introduced.js.map +1 -0
  231. package/dist/commands/validate/checks/requirements.js +264 -0
  232. package/dist/commands/validate/checks/requirements.js.map +1 -0
  233. package/dist/commands/validate/checks/sources.js +85 -0
  234. package/dist/commands/validate/checks/sources.js.map +1 -0
  235. package/dist/commands/validate/coverage/covers-after.js +105 -0
  236. package/dist/commands/validate/coverage/covers-after.js.map +1 -0
  237. package/dist/commands/validate/feature.js +222 -0
  238. package/dist/commands/validate/feature.js.map +1 -0
  239. package/dist/commands/validate/fleet/census.js +93 -0
  240. package/dist/commands/validate/fleet/census.js.map +1 -0
  241. package/dist/commands/validate/fleet/kind-tags.js +39 -0
  242. package/dist/commands/validate/fleet/kind-tags.js.map +1 -0
  243. package/dist/commands/validate/fleet/landscape.js +371 -0
  244. package/dist/commands/validate/fleet/landscape.js.map +1 -0
  245. package/dist/commands/validate/fleet/load.js +118 -0
  246. package/dist/commands/validate/fleet/load.js.map +1 -0
  247. package/dist/commands/validate/fleet/map/attest.js +98 -0
  248. package/dist/commands/validate/fleet/map/attest.js.map +1 -0
  249. package/dist/commands/validate/fleet/map/bindings.js +107 -0
  250. package/dist/commands/validate/fleet/map/bindings.js.map +1 -0
  251. package/dist/commands/validate/fleet/map/consumers.js +244 -0
  252. package/dist/commands/validate/fleet/map/consumers.js.map +1 -0
  253. package/dist/commands/validate/fleet/map/isolation.js +116 -0
  254. package/dist/commands/validate/fleet/map/isolation.js.map +1 -0
  255. package/dist/commands/validate/fleet/map/usecases.js +54 -0
  256. package/dist/commands/validate/fleet/map/usecases.js.map +1 -0
  257. package/dist/commands/validate/fleet/obligations.js +266 -0
  258. package/dist/commands/validate/fleet/obligations.js.map +1 -0
  259. package/dist/commands/validate/fleet/scorecard/adoption.js +102 -0
  260. package/dist/commands/validate/fleet/scorecard/adoption.js.map +1 -0
  261. package/dist/commands/validate/fleet/scorecard/contracts.js +98 -0
  262. package/dist/commands/validate/fleet/scorecard/contracts.js.map +1 -0
  263. package/dist/commands/validate/fleet/scorecard/print.js +71 -0
  264. package/dist/commands/validate/fleet/scorecard/print.js.map +1 -0
  265. package/dist/commands/validate/fleet/scorecard/scorecard.js +162 -0
  266. package/dist/commands/validate/fleet/scorecard/scorecard.js.map +1 -0
  267. package/dist/commands/validate/fleet/usecases/place.js +13 -0
  268. package/dist/commands/validate/fleet/usecases/place.js.map +1 -0
  269. package/dist/commands/validate/fleet/views/fleet-project.js +217 -0
  270. package/dist/commands/validate/fleet/views/fleet-project.js.map +1 -0
  271. package/dist/commands/validate/fleet/views/ids.js +75 -0
  272. package/dist/commands/validate/fleet/views/ids.js.map +1 -0
  273. package/dist/commands/validate/fleet/views/projects.js +278 -0
  274. package/dist/commands/validate/fleet/views/projects.js.map +1 -0
  275. package/dist/commands/validate/fleet/views/root-documents.js +83 -0
  276. package/dist/commands/validate/fleet/views/root-documents.js.map +1 -0
  277. package/dist/commands/validate/fleet/views/stale.js +52 -0
  278. package/dist/commands/validate/fleet/views/stale.js.map +1 -0
  279. package/dist/commands/validate/links/corpus.js +89 -0
  280. package/dist/commands/validate/links/corpus.js.map +1 -0
  281. package/dist/commands/validate/links/glossary.js +75 -0
  282. package/dist/commands/validate/links/glossary.js.map +1 -0
  283. package/dist/commands/validate/render/repeats.js +63 -0
  284. package/dist/commands/validate/render/repeats.js.map +1 -0
  285. package/dist/commands/validate/render/rollups.js +115 -0
  286. package/dist/commands/validate/render/rollups.js.map +1 -0
  287. package/dist/commands/validate/render/text.js +199 -0
  288. package/dist/commands/validate/render/text.js.map +1 -0
  289. package/dist/commands/validate/report.js +145 -0
  290. package/dist/commands/validate/report.js.map +1 -0
  291. package/dist/commands/validate/scope.js +113 -0
  292. package/dist/commands/validate/scope.js.map +1 -0
  293. package/dist/commands/validate/service/api.js +252 -0
  294. package/dist/commands/validate/service/api.js.map +1 -0
  295. package/dist/commands/validate/service/contracts/generated.js +134 -0
  296. package/dist/commands/validate/service/contracts/generated.js.map +1 -0
  297. package/dist/commands/validate/service/events/events.js +241 -0
  298. package/dist/commands/validate/service/events/events.js.map +1 -0
  299. package/dist/commands/validate/service/events/message-producers.js +77 -0
  300. package/dist/commands/validate/service/events/message-producers.js.map +1 -0
  301. package/dist/commands/validate/service/evidence-pins.js +177 -0
  302. package/dist/commands/validate/service/evidence-pins.js.map +1 -0
  303. package/dist/commands/validate/service/model/diverged.js +226 -0
  304. package/dist/commands/validate/service/model/diverged.js.map +1 -0
  305. package/dist/commands/validate/service/model/grade.js +163 -0
  306. package/dist/commands/validate/service/model/grade.js.map +1 -0
  307. package/dist/commands/validate/service/service.js +310 -0
  308. package/dist/commands/validate/service/service.js.map +1 -0
  309. package/dist/commands/validate/service/specs.js +279 -0
  310. package/dist/commands/validate/service/specs.js.map +1 -0
  311. package/dist/commands/validate/service/spine.js +148 -0
  312. package/dist/commands/validate/service/spine.js.map +1 -0
  313. package/dist/commands/validate/service/usecases/tags.js +113 -0
  314. package/dist/commands/validate/service/usecases/tags.js.map +1 -0
  315. package/dist/commands/validate/service/usecases/usecases.js +209 -0
  316. package/dist/commands/validate/service/usecases/usecases.js.map +1 -0
  317. package/dist/commands/validate/validate.js +363 -0
  318. package/dist/commands/validate/validate.js.map +1 -0
  319. package/dist/commands/verify/cross/diff.js +178 -0
  320. package/dist/commands/verify/cross/diff.js.map +1 -0
  321. package/dist/commands/verify/evidence/contract.js +32 -0
  322. package/dist/commands/verify/evidence/contract.js.map +1 -0
  323. package/dist/commands/verify/evidence/pins.js +52 -0
  324. package/dist/commands/verify/evidence/pins.js.map +1 -0
  325. package/dist/commands/verify/evidence/read.js +81 -0
  326. package/dist/commands/verify/evidence/read.js.map +1 -0
  327. package/dist/commands/verify/frozen.js +263 -0
  328. package/dist/commands/verify/frozen.js.map +1 -0
  329. package/dist/commands/verify/record.js +278 -0
  330. package/dist/commands/verify/record.js.map +1 -0
  331. package/dist/commands/verify/report.js +206 -0
  332. package/dist/commands/verify/report.js.map +1 -0
  333. package/dist/commands/verify/results.js +328 -0
  334. package/dist/commands/verify/results.js.map +1 -0
  335. package/dist/commands/verify/verify.js +220 -0
  336. package/dist/commands/verify/verify.js.map +1 -0
  337. package/dist/commands/vouch/contract.js +11 -0
  338. package/dist/commands/vouch/contract.js.map +1 -0
  339. package/dist/commands/vouch/pack/contract.js +2 -0
  340. package/dist/commands/vouch/pack/contract.js.map +1 -0
  341. package/dist/commands/vouch/pack/pack.js +266 -0
  342. package/dist/commands/vouch/pack/pack.js.map +1 -0
  343. package/dist/commands/vouch/pack/print.js +266 -0
  344. package/dist/commands/vouch/pack/print.js.map +1 -0
  345. package/dist/commands/vouch/pack/sections.js +141 -0
  346. package/dist/commands/vouch/pack/sections.js.map +1 -0
  347. package/dist/commands/vouch/prompt/confirm.js +46 -0
  348. package/dist/commands/vouch/prompt/confirm.js.map +1 -0
  349. package/dist/commands/vouch/report.js +101 -0
  350. package/dist/commands/vouch/report.js.map +1 -0
  351. package/dist/commands/vouch/run.js +230 -0
  352. package/dist/commands/vouch/run.js.map +1 -0
  353. package/dist/commands/vouch/sample/plan.js +111 -0
  354. package/dist/commands/vouch/sample/plan.js.map +1 -0
  355. package/dist/commands/vouch/sample/print.js +109 -0
  356. package/dist/commands/vouch/sample/print.js.map +1 -0
  357. package/dist/commands/vouch/vet/verify.js +155 -0
  358. package/dist/commands/vouch/vet/verify.js.map +1 -0
  359. package/dist/commands/vouch/vouch.js +169 -0
  360. package/dist/commands/vouch/vouch.js.map +1 -0
  361. package/dist/core/agent/agents-md/command-map.js +299 -0
  362. package/dist/core/agent/agents-md/command-map.js.map +1 -0
  363. package/dist/core/agent/agents-md/map/explain.js +46 -0
  364. package/dist/core/agent/agents-md/map/explain.js.map +1 -0
  365. package/dist/core/agent/agents-md/map/lenses/context.js +50 -0
  366. package/dist/core/agent/agents-md/map/lenses/context.js.map +1 -0
  367. package/dist/core/agent/agents-md/map/lenses/diff.js +59 -0
  368. package/dist/core/agent/agents-md/map/lenses/diff.js.map +1 -0
  369. package/dist/core/agent/agents-md/map/lenses/gate.js +65 -0
  370. package/dist/core/agent/agents-md/map/lenses/gate.js.map +1 -0
  371. package/dist/core/agent/agents-md/map/mcp.js +44 -0
  372. package/dist/core/agent/agents-md/map/mcp.js.map +1 -0
  373. package/dist/core/agent/agents-md/map/status.js +78 -0
  374. package/dist/core/agent/agents-md/map/status.js.map +1 -0
  375. package/dist/core/agent/agents-md/map/subsystem.js +104 -0
  376. package/dist/core/agent/agents-md/map/subsystem.js.map +1 -0
  377. package/dist/core/agent/agents-md/map/usecases.js +138 -0
  378. package/dist/core/agent/agents-md/map/usecases.js.map +1 -0
  379. package/dist/core/agent/agents-md/refusals.js +273 -0
  380. package/dist/core/agent/agents-md/refusals.js.map +1 -0
  381. package/dist/core/agent/agents-md.js +203 -0
  382. package/dist/core/agent/agents-md.js.map +1 -0
  383. package/dist/core/{agents-stamp.js → agent/agents-stamp.js} +60 -0
  384. package/dist/core/agent/agents-stamp.js.map +1 -0
  385. package/dist/core/agent/contract.js +2 -0
  386. package/dist/core/agent/contract.js.map +1 -0
  387. package/dist/core/agent/protocol.js +193 -0
  388. package/dist/core/agent/protocol.js.map +1 -0
  389. package/dist/core/agent/scaffold.js +254 -0
  390. package/dist/core/agent/scaffold.js.map +1 -0
  391. package/dist/core/agent/support/report.js +144 -0
  392. package/dist/core/agent/support/report.js.map +1 -0
  393. package/dist/core/agent/tools/dialects.js +151 -0
  394. package/dist/core/agent/tools/dialects.js.map +1 -0
  395. package/dist/core/agent/tools/registry.js +193 -0
  396. package/dist/core/agent/tools/registry.js.map +1 -0
  397. package/dist/core/agent/workflows/adopt.js +280 -0
  398. package/dist/core/agent/workflows/adopt.js.map +1 -0
  399. package/dist/core/agent/workflows/check.js +373 -0
  400. package/dist/core/agent/workflows/check.js.map +1 -0
  401. package/dist/core/agent/workflows/closing.js +323 -0
  402. package/dist/core/agent/workflows/closing.js.map +1 -0
  403. package/dist/core/agent/workflows/feature.js +220 -0
  404. package/dist/core/agent/workflows/feature.js.map +1 -0
  405. package/dist/core/agent/workflows/implement.js +188 -0
  406. package/dist/core/agent/workflows/implement.js.map +1 -0
  407. package/dist/core/agent/workflows/reference/authoring.js +311 -0
  408. package/dist/core/agent/workflows/reference/authoring.js.map +1 -0
  409. package/dist/core/agent/workflows/reference/codes.js +67 -0
  410. package/dist/core/agent/workflows/reference/codes.js.map +1 -0
  411. package/dist/core/agent/workflows/reference/done-check.js +210 -0
  412. package/dist/core/agent/workflows/reference/done-check.js.map +1 -0
  413. package/dist/core/agent/workflows/reference/drawing/drawing.js +253 -0
  414. package/dist/core/agent/workflows/reference/drawing/drawing.js.map +1 -0
  415. package/dist/core/agent/workflows/reference/reference.js +19 -0
  416. package/dist/core/agent/workflows/reference/reference.js.map +1 -0
  417. package/dist/core/agent/workflows/reference/spine.js +338 -0
  418. package/dist/core/agent/workflows/reference/spine.js.map +1 -0
  419. package/dist/core/asyncapi/baseline/plan.js +43 -0
  420. package/dist/core/asyncapi/baseline/plan.js.map +1 -0
  421. package/dist/core/asyncapi/baseline/surfaces.js +54 -0
  422. package/dist/core/asyncapi/baseline/surfaces.js.map +1 -0
  423. package/dist/core/asyncapi/depth.js +164 -0
  424. package/dist/core/asyncapi/depth.js.map +1 -0
  425. package/dist/core/asyncapi/digest.js +146 -0
  426. package/dist/core/asyncapi/digest.js.map +1 -0
  427. package/dist/core/asyncapi/merge/components.js +92 -0
  428. package/dist/core/asyncapi/merge/components.js.map +1 -0
  429. package/dist/core/asyncapi/merge/error.js +38 -0
  430. package/dist/core/asyncapi/merge/error.js.map +1 -0
  431. package/dist/core/asyncapi/merge/markers.js +290 -0
  432. package/dist/core/asyncapi/merge/markers.js.map +1 -0
  433. package/dist/core/asyncapi/merge/merge.js +195 -0
  434. package/dist/core/asyncapi/merge/merge.js.map +1 -0
  435. package/dist/core/asyncapi/merge/pin.js +83 -0
  436. package/dist/core/asyncapi/merge/pin.js.map +1 -0
  437. package/dist/core/asyncapi/model.js +11 -0
  438. package/dist/core/asyncapi/model.js.map +1 -0
  439. package/dist/core/asyncapi/producers.js +50 -0
  440. package/dist/core/asyncapi/producers.js.map +1 -0
  441. package/dist/core/asyncapi/read.js +263 -0
  442. package/dist/core/asyncapi/read.js.map +1 -0
  443. package/dist/core/brief/brief.js +285 -0
  444. package/dist/core/brief/brief.js.map +1 -0
  445. package/dist/core/brief/checks.js +385 -0
  446. package/dist/core/brief/checks.js.map +1 -0
  447. package/dist/core/brief/landscape.js +273 -0
  448. package/dist/core/brief/landscape.js.map +1 -0
  449. package/dist/core/brief/map/extend.js +84 -0
  450. package/dist/core/brief/map/extend.js.map +1 -0
  451. package/dist/core/brief/map/owed.js +266 -0
  452. package/dist/core/brief/map/owed.js.map +1 -0
  453. package/dist/core/brief/targets.js +304 -0
  454. package/dist/core/brief/targets.js.map +1 -0
  455. package/dist/core/brief/unchecked.js +58 -0
  456. package/dist/core/brief/unchecked.js.map +1 -0
  457. package/dist/core/c4/arch.js +190 -0
  458. package/dist/core/c4/arch.js.map +1 -0
  459. package/dist/core/c4/direction/direction.js +114 -0
  460. package/dist/core/c4/direction/direction.js.map +1 -0
  461. package/dist/core/c4/likec4.js +243 -0
  462. package/dist/core/c4/likec4.js.map +1 -0
  463. package/dist/core/c4/locate/unlocated.js +150 -0
  464. package/dist/core/c4/locate/unlocated.js.map +1 -0
  465. package/dist/core/c4/parsed/deployment.js +160 -0
  466. package/dist/core/c4/parsed/deployment.js.map +1 -0
  467. package/dist/core/c4/parsed/dynamic-views.js +132 -0
  468. package/dist/core/c4/parsed/dynamic-views.js.map +1 -0
  469. package/dist/core/c4/parsed/specification.js +78 -0
  470. package/dist/core/c4/parsed/specification.js.map +1 -0
  471. package/dist/core/c4/parsed/values.js +110 -0
  472. package/dist/core/c4/parsed/values.js.map +1 -0
  473. package/dist/core/c4/parsed/view-ids.js +113 -0
  474. package/dist/core/c4/parsed/view-ids.js.map +1 -0
  475. package/dist/core/c4/prefetch/fleet.js +134 -0
  476. package/dist/core/c4/prefetch/fleet.js.map +1 -0
  477. package/dist/core/c4/project/architecture.js +161 -0
  478. package/dist/core/c4/project/architecture.js.map +1 -0
  479. package/dist/core/c4/project/batch.js +140 -0
  480. package/dist/core/c4/project/batch.js.map +1 -0
  481. package/dist/core/c4/project/documents.js +89 -0
  482. package/dist/core/c4/project/documents.js.map +1 -0
  483. package/dist/core/c4/project/load.js +219 -0
  484. package/dist/core/c4/project/load.js.map +1 -0
  485. package/dist/core/c4/project/staged.js +277 -0
  486. package/dist/core/c4/project/staged.js.map +1 -0
  487. package/dist/core/c4/resolve/attested.js +0 -0
  488. package/dist/core/c4/resolve/attested.js.map +1 -0
  489. package/dist/core/c4/resolve/external.js +51 -0
  490. package/dist/core/c4/resolve/external.js.map +1 -0
  491. package/dist/core/c4/resolve/service.js +174 -0
  492. package/dist/core/c4/resolve/service.js.map +1 -0
  493. package/dist/core/c4/resolve/steps.js +290 -0
  494. package/dist/core/c4/resolve/steps.js.map +1 -0
  495. package/dist/core/c4/resolve/systems.js +154 -0
  496. package/dist/core/c4/resolve/systems.js.map +1 -0
  497. package/dist/core/c4/root-project/exclude.js +352 -0
  498. package/dist/core/c4/root-project/exclude.js.map +1 -0
  499. package/dist/core/c4/seed/fleet-file.js +201 -0
  500. package/dist/core/c4/seed/fleet-file.js.map +1 -0
  501. package/dist/core/c4/seed/items.js +91 -0
  502. package/dist/core/c4/seed/items.js.map +1 -0
  503. package/dist/core/c4/seed/stamp.js +48 -0
  504. package/dist/core/c4/seed/stamp.js.map +1 -0
  505. package/dist/core/c4/seed/template.js +173 -0
  506. package/dist/core/c4/seed/template.js.map +1 -0
  507. package/dist/core/c4/service-model/created/models.js +96 -0
  508. package/dist/core/c4/service-model/created/models.js.map +1 -0
  509. package/dist/core/c4/service-model/documents.js +47 -0
  510. package/dist/core/c4/service-model/documents.js.map +1 -0
  511. package/dist/core/c4/service-model/fleet/extending.js +82 -0
  512. package/dist/core/c4/service-model/fleet/extending.js.map +1 -0
  513. package/dist/core/c4/service-model/load.js +165 -0
  514. package/dist/core/c4/service-model/load.js.map +1 -0
  515. package/dist/core/c4/service-model/renderer.js +128 -0
  516. package/dist/core/c4/service-model/renderer.js.map +1 -0
  517. package/dist/core/c4/service-model/shape.js +106 -0
  518. package/dist/core/c4/service-model/shape.js.map +1 -0
  519. package/dist/core/c4/service-model/slice.js +188 -0
  520. package/dist/core/c4/service-model/slice.js.map +1 -0
  521. package/dist/core/c4/source-mask.js +369 -0
  522. package/dist/core/c4/source-mask.js.map +1 -0
  523. package/dist/core/c4/source-scan.js +308 -0
  524. package/dist/core/c4/source-scan.js.map +1 -0
  525. package/dist/core/c4/splice/authored-source.js +167 -0
  526. package/dist/core/c4/splice/authored-source.js.map +1 -0
  527. package/dist/core/c4/splice/contract.js +30 -0
  528. package/dist/core/c4/splice/contract.js.map +1 -0
  529. package/dist/core/c4/splice/delta-blocks.js +126 -0
  530. package/dist/core/c4/splice/delta-blocks.js.map +1 -0
  531. package/dist/core/c4/splice/identity/declared.js +87 -0
  532. package/dist/core/c4/splice/identity/declared.js.map +1 -0
  533. package/dist/core/c4/splice/identity/edges.js +73 -0
  534. package/dist/core/c4/splice/identity/edges.js.map +1 -0
  535. package/dist/core/c4/splice/identity/existing.js +80 -0
  536. package/dist/core/c4/splice/identity/existing.js.map +1 -0
  537. package/dist/core/c4/splice/identity/interior.js +80 -0
  538. package/dist/core/c4/splice/identity/interior.js.map +1 -0
  539. package/dist/core/c4/splice/identity/owner.js +50 -0
  540. package/dist/core/c4/splice/identity/owner.js.map +1 -0
  541. package/dist/core/c4/splice/landscape-merge.js +337 -0
  542. package/dist/core/c4/splice/landscape-merge.js.map +1 -0
  543. package/dist/core/c4/splice/model/merge.js +151 -0
  544. package/dist/core/c4/splice/model/merge.js.map +1 -0
  545. package/dist/core/c4/splice/placement.js +298 -0
  546. package/dist/core/c4/splice/placement.js.map +1 -0
  547. package/dist/core/c4/splice/text/spot.js +131 -0
  548. package/dist/core/c4/splice/text/spot.js.map +1 -0
  549. package/dist/core/c4/workspace.js +166 -0
  550. package/dist/core/c4/workspace.js.map +1 -0
  551. package/dist/core/capabilities/authoring/notes.js +141 -0
  552. package/dist/core/capabilities/authoring/notes.js.map +1 -0
  553. package/dist/core/capabilities/capabilities.js +124 -0
  554. package/dist/core/capabilities/capabilities.js.map +1 -0
  555. package/dist/core/capabilities/delta/doc.js +47 -0
  556. package/dist/core/capabilities/delta/doc.js.map +1 -0
  557. package/dist/core/capabilities/delta/overlay.js +129 -0
  558. package/dist/core/capabilities/delta/overlay.js.map +1 -0
  559. package/dist/core/capabilities/delta/summary.js +57 -0
  560. package/dist/core/capabilities/delta/summary.js.map +1 -0
  561. package/dist/core/capabilities/delta/tree.js +43 -0
  562. package/dist/core/capabilities/delta/tree.js.map +1 -0
  563. package/dist/core/capabilities/delta/uncovered.js +222 -0
  564. package/dist/core/capabilities/delta/uncovered.js.map +1 -0
  565. package/dist/core/capabilities/findings.js +338 -0
  566. package/dist/core/capabilities/findings.js.map +1 -0
  567. package/dist/core/capabilities/realizes/findings.js +174 -0
  568. package/dist/core/capabilities/realizes/findings.js.map +1 -0
  569. package/dist/core/capabilities/realizes/join.js +123 -0
  570. package/dist/core/capabilities/realizes/join.js.map +1 -0
  571. package/dist/core/capabilities/rollup.js +205 -0
  572. package/dist/core/capabilities/rollup.js.map +1 -0
  573. package/dist/core/capabilities/tree.js +104 -0
  574. package/dist/core/capabilities/tree.js.map +1 -0
  575. package/dist/core/capabilities/usecase-join.js +267 -0
  576. package/dist/core/capabilities/usecase-join.js.map +1 -0
  577. package/dist/core/coherence/authoring/scaffold.js +185 -0
  578. package/dist/core/coherence/authoring/scaffold.js.map +1 -0
  579. package/dist/core/coherence/authoring/sentinels.js +75 -0
  580. package/dist/core/coherence/authoring/sentinels.js.map +1 -0
  581. package/dist/core/coherence/calls/called.js +52 -0
  582. package/dist/core/coherence/calls/called.js.map +1 -0
  583. package/dist/core/coherence/coherence.js +332 -0
  584. package/dist/core/coherence/coherence.js.map +1 -0
  585. package/dist/core/coherence/consumed/operations.js +70 -0
  586. package/dist/core/coherence/consumed/operations.js.map +1 -0
  587. package/dist/core/coherence/consumed/refusal.js +38 -0
  588. package/dist/core/coherence/consumed/refusal.js.map +1 -0
  589. package/dist/core/coherence/covers/health.js +85 -0
  590. package/dist/core/coherence/covers/health.js.map +1 -0
  591. package/dist/core/coherence/declared.js +295 -0
  592. package/dist/core/coherence/declared.js.map +1 -0
  593. package/dist/core/coherence/events/declared.js +191 -0
  594. package/dist/core/coherence/events/declared.js.map +1 -0
  595. package/dist/core/coherence/events/events.js +335 -0
  596. package/dist/core/coherence/events/events.js.map +1 -0
  597. package/dist/core/coherence/events/grades.js +189 -0
  598. package/dist/core/coherence/events/grades.js.map +1 -0
  599. package/dist/core/coherence/events/lookups.js +63 -0
  600. package/dist/core/coherence/events/lookups.js.map +1 -0
  601. package/dist/core/coherence/events/produced.js +100 -0
  602. package/dist/core/coherence/events/produced.js.map +1 -0
  603. package/dist/core/coherence/living.js +198 -0
  604. package/dist/core/coherence/living.js.map +1 -0
  605. package/dist/core/coherence/lookups.js +95 -0
  606. package/dist/core/coherence/lookups.js.map +1 -0
  607. package/dist/core/coherence/pending.js +39 -0
  608. package/dist/core/coherence/pending.js.map +1 -0
  609. package/dist/core/coherence/retired/archived.js +285 -0
  610. package/dist/core/coherence/retired/archived.js.map +1 -0
  611. package/dist/core/coherence/retired/event-pair.js +62 -0
  612. package/dist/core/coherence/retired/event-pair.js.map +1 -0
  613. package/dist/core/coherence/retired/merged.js +79 -0
  614. package/dist/core/coherence/retired/merged.js.map +1 -0
  615. package/dist/core/coherence/retired/retirement.js +49 -0
  616. package/dist/core/coherence/retired/retirement.js.map +1 -0
  617. package/dist/core/coherence/retired/revival/arrivals.js +131 -0
  618. package/dist/core/coherence/retired/revival/arrivals.js.map +1 -0
  619. package/dist/core/coherence/retired/revival/revived.js +297 -0
  620. package/dist/core/coherence/retired/revival/revived.js.map +1 -0
  621. package/dist/core/conflict-markers.js +60 -0
  622. package/dist/core/conflict-markers.js.map +1 -0
  623. package/dist/core/consumers/after.js +113 -0
  624. package/dist/core/consumers/after.js.map +1 -0
  625. package/dist/core/consumers/consumers.js +296 -0
  626. package/dist/core/consumers/consumers.js.map +1 -0
  627. package/dist/core/consumers/current.js +211 -0
  628. package/dist/core/consumers/current.js.map +1 -0
  629. package/dist/core/consumers/scan.js +46 -0
  630. package/dist/core/consumers/scan.js.map +1 -0
  631. package/dist/core/consumers/state.js +27 -0
  632. package/dist/core/consumers/state.js.map +1 -0
  633. package/dist/core/delta/claims.js +73 -0
  634. package/dist/core/delta/claims.js.map +1 -0
  635. package/dist/core/delta/delta.js +341 -0
  636. package/dist/core/delta/delta.js.map +1 -0
  637. package/dist/core/delta/document.js +177 -0
  638. package/dist/core/delta/document.js.map +1 -0
  639. package/dist/core/delta/scope.js +48 -0
  640. package/dist/core/delta/scope.js.map +1 -0
  641. package/dist/core/delta/select.js +237 -0
  642. package/dist/core/delta/select.js.map +1 -0
  643. package/dist/core/dependencies/dependencies.js +141 -0
  644. package/dist/core/dependencies/dependencies.js.map +1 -0
  645. package/dist/core/dependencies/facts.js +165 -0
  646. package/dist/core/dependencies/facts.js.map +1 -0
  647. package/dist/core/dependencies/fanin.js +88 -0
  648. package/dist/core/dependencies/fanin.js.map +1 -0
  649. package/dist/core/dependencies/graph.js +106 -0
  650. package/dist/core/dependencies/graph.js.map +1 -0
  651. package/dist/core/deployment/delta.js +191 -0
  652. package/dist/core/deployment/delta.js.map +1 -0
  653. package/dist/core/deployment/objects.js +145 -0
  654. package/dist/core/deployment/objects.js.map +1 -0
  655. package/dist/core/diff/base-git.js +230 -0
  656. package/dist/core/diff/base-git.js.map +1 -0
  657. package/dist/core/diff/base-state.js +237 -0
  658. package/dist/core/diff/base-state.js.map +1 -0
  659. package/dist/core/diff/joins.js +136 -0
  660. package/dist/core/diff/joins.js.map +1 -0
  661. package/dist/core/diff/scope/changed-paths.js +204 -0
  662. package/dist/core/diff/scope/changed-paths.js.map +1 -0
  663. package/dist/core/diff/scope/edges.js +82 -0
  664. package/dist/core/diff/scope/edges.js.map +1 -0
  665. package/dist/core/diff/semantic.js +312 -0
  666. package/dist/core/diff/semantic.js.map +1 -0
  667. package/dist/core/docs.js +37 -85
  668. package/dist/core/docs.js.map +1 -1
  669. package/dist/core/doctor/agents.js +238 -0
  670. package/dist/core/doctor/agents.js.map +1 -0
  671. package/dist/core/doctor/config.js +139 -0
  672. package/dist/core/doctor/config.js.map +1 -0
  673. package/dist/core/doctor/doctor.js +355 -0
  674. package/dist/core/doctor/doctor.js.map +1 -0
  675. package/dist/core/doctor/report.js +13 -0
  676. package/dist/core/doctor/report.js.map +1 -0
  677. package/dist/core/doctor/reports/scan.js +242 -0
  678. package/dist/core/doctor/reports/scan.js.map +1 -0
  679. package/dist/core/doctor/residue.js +110 -0
  680. package/dist/core/doctor/residue.js.map +1 -0
  681. package/dist/core/document/apply.js +224 -0
  682. package/dist/core/document/apply.js.map +1 -0
  683. package/dist/core/{frontmatter.js → document/frontmatter.js} +103 -2
  684. package/dist/core/document/frontmatter.js.map +1 -0
  685. package/dist/core/document/grammar/directives.js +143 -0
  686. package/dist/core/document/grammar/directives.js.map +1 -0
  687. package/dist/core/document/parse.js +286 -0
  688. package/dist/core/document/parse.js.map +1 -0
  689. package/dist/core/document/scenarios.js +238 -0
  690. package/dist/core/document/scenarios.js.map +1 -0
  691. package/dist/core/document/spec.js +234 -0
  692. package/dist/core/document/spec.js.map +1 -0
  693. package/dist/core/{config.js → envelope/config.js} +89 -18
  694. package/dist/core/envelope/config.js.map +1 -0
  695. package/dist/core/envelope/json.js +209 -0
  696. package/dist/core/envelope/json.js.map +1 -0
  697. package/dist/core/{version.js → envelope/version.js} +3 -3
  698. package/dist/core/envelope/version.js.map +1 -0
  699. package/dist/core/explain/families.js +180 -0
  700. package/dist/core/explain/families.js.map +1 -0
  701. package/dist/core/explain/fix-tables.js +178 -0
  702. package/dist/core/explain/fix-tables.js.map +1 -0
  703. package/dist/core/explain/lookup.js +194 -0
  704. package/dist/core/explain/lookup.js.map +1 -0
  705. package/dist/core/explain/refusals.js +49 -0
  706. package/dist/core/explain/refusals.js.map +1 -0
  707. package/dist/core/explain/terms/documents.js +227 -0
  708. package/dist/core/explain/terms/documents.js.map +1 -0
  709. package/dist/core/explain/terms/done-check.js +144 -0
  710. package/dist/core/explain/terms/done-check.js.map +1 -0
  711. package/dist/core/explain/terms/entry.js +14 -0
  712. package/dist/core/explain/terms/entry.js.map +1 -0
  713. package/dist/core/explain/terms/stages.js +71 -0
  714. package/dist/core/explain/terms/stages.js.map +1 -0
  715. package/dist/core/explain/terms/tasks.js +97 -0
  716. package/dist/core/explain/terms/tasks.js.map +1 -0
  717. package/dist/core/explain/terms.js +103 -0
  718. package/dist/core/explain/terms.js.map +1 -0
  719. package/dist/core/explore/describe.js +105 -0
  720. package/dist/core/explore/describe.js.map +1 -0
  721. package/dist/core/explore/explore.js +204 -0
  722. package/dist/core/explore/explore.js.map +1 -0
  723. package/dist/core/fleet-context.js +174 -146
  724. package/dist/core/fleet-context.js.map +1 -1
  725. package/dist/core/gate/checks.js +208 -0
  726. package/dist/core/gate/checks.js.map +1 -0
  727. package/dist/core/gate/partners.js +246 -0
  728. package/dist/core/gate/partners.js.map +1 -0
  729. package/dist/core/gate/report.js +47 -0
  730. package/dist/core/gate/report.js.map +1 -0
  731. package/dist/core/gate/verification.js +176 -0
  732. package/dist/core/gate/verification.js.map +1 -0
  733. package/dist/core/gherkin/digest.js +60 -0
  734. package/dist/core/gherkin/digest.js.map +1 -0
  735. package/dist/core/gherkin/emit.js +177 -0
  736. package/dist/core/gherkin/emit.js.map +1 -0
  737. package/dist/core/gherkin/read.js +76 -0
  738. package/dist/core/gherkin/read.js.map +1 -0
  739. package/dist/core/gherkin/stale.js +210 -0
  740. package/dist/core/gherkin/stale.js.map +1 -0
  741. package/dist/core/gherkin/stamp.js +77 -0
  742. package/dist/core/gherkin/stamp.js.map +1 -0
  743. package/dist/core/gherkin/steps/catalogue.js +154 -0
  744. package/dist/core/gherkin/steps/catalogue.js.map +1 -0
  745. package/dist/core/gherkin/steps/inventory.js +98 -0
  746. package/dist/core/gherkin/steps/inventory.js.map +1 -0
  747. package/dist/core/gherkin/steps/phrase.js +72 -0
  748. package/dist/core/gherkin/steps/phrase.js.map +1 -0
  749. package/dist/core/glossary/delta.js +109 -0
  750. package/dist/core/glossary/delta.js.map +1 -0
  751. package/dist/core/glossary/tree.js +73 -0
  752. package/dist/core/glossary/tree.js.map +1 -0
  753. package/dist/core/{concurrency.js → kernel/concurrency.js} +19 -0
  754. package/dist/core/kernel/concurrency.js.map +1 -0
  755. package/dist/core/{document-bytes.js → kernel/document-bytes.js} +1 -1
  756. package/dist/core/kernel/document-bytes.js.map +1 -0
  757. package/dist/core/kernel/fences.js +42 -0
  758. package/dist/core/kernel/fences.js.map +1 -0
  759. package/dist/core/kernel/ids/capability.js +72 -0
  760. package/dist/core/kernel/ids/capability.js.map +1 -0
  761. package/dist/core/kernel/ids/dirs.js +33 -0
  762. package/dist/core/kernel/ids/dirs.js.map +1 -0
  763. package/dist/core/kernel/ids/feature.js +75 -0
  764. package/dist/core/kernel/ids/feature.js.map +1 -0
  765. package/dist/core/kernel/ids/fqn/ancestors.js +65 -0
  766. package/dist/core/kernel/ids/fqn/ancestors.js.map +1 -0
  767. package/dist/core/kernel/ids/service.js +156 -0
  768. package/dist/core/kernel/ids/service.js.map +1 -0
  769. package/dist/core/kernel/ids/subsystem.js +63 -0
  770. package/dist/core/kernel/ids/subsystem.js.map +1 -0
  771. package/dist/core/{path-safety.js → kernel/path-safety.js} +56 -4
  772. package/dist/core/kernel/path-safety.js.map +1 -0
  773. package/dist/core/{records.js → kernel/records.js} +11 -0
  774. package/dist/core/kernel/records.js.map +1 -0
  775. package/dist/core/links/backlinks.js +66 -0
  776. package/dist/core/links/backlinks.js.map +1 -0
  777. package/dist/core/links/case.js +74 -0
  778. package/dist/core/links/case.js.map +1 -0
  779. package/dist/core/links/corpus.js +118 -0
  780. package/dist/core/links/corpus.js.map +1 -0
  781. package/dist/core/links/findings.js +110 -0
  782. package/dist/core/links/findings.js.map +1 -0
  783. package/dist/core/links/parse.js +265 -0
  784. package/dist/core/links/parse.js.map +1 -0
  785. package/dist/core/mcp/argv.js +212 -0
  786. package/dist/core/mcp/argv.js.map +1 -0
  787. package/dist/core/mcp/author-tools.js +73 -0
  788. package/dist/core/mcp/author-tools.js.map +1 -0
  789. package/dist/core/mcp/framing.js +46 -0
  790. package/dist/core/mcp/framing.js.map +1 -0
  791. package/dist/core/mcp/protocol.js +280 -0
  792. package/dist/core/mcp/protocol.js.map +1 -0
  793. package/dist/core/mcp/tools.js +324 -0
  794. package/dist/core/mcp/tools.js.map +1 -0
  795. package/dist/core/obligations/obligations.js +106 -0
  796. package/dist/core/obligations/obligations.js.map +1 -0
  797. package/dist/core/openapi/baseline/gate.js +207 -0
  798. package/dist/core/openapi/baseline/gate.js.map +1 -0
  799. package/dist/core/openapi/baseline/plan.js +142 -0
  800. package/dist/core/openapi/baseline/plan.js.map +1 -0
  801. package/dist/core/openapi/baseline/record.js +174 -0
  802. package/dist/core/openapi/baseline/record.js.map +1 -0
  803. package/dist/core/openapi/contract-text.js +33 -0
  804. package/dist/core/openapi/contract-text.js.map +1 -0
  805. package/dist/core/openapi/contract-tree.js +301 -0
  806. package/dist/core/openapi/contract-tree.js.map +1 -0
  807. package/dist/core/openapi/depth.js +136 -0
  808. package/dist/core/openapi/depth.js.map +1 -0
  809. package/dist/core/openapi/digest.js +239 -0
  810. package/dist/core/openapi/digest.js.map +1 -0
  811. package/dist/core/{openapi.js → openapi/doc.js} +54 -108
  812. package/dist/core/openapi/doc.js.map +1 -0
  813. package/dist/core/openapi/merge/components.js +199 -0
  814. package/dist/core/openapi/merge/components.js.map +1 -0
  815. package/dist/core/openapi/merge/error.js +16 -0
  816. package/dist/core/openapi/merge/error.js.map +1 -0
  817. package/dist/core/openapi/merge/markers.js +204 -0
  818. package/dist/core/openapi/merge/markers.js.map +1 -0
  819. package/dist/core/openapi/merge/merge.js +232 -0
  820. package/dist/core/openapi/merge/merge.js.map +1 -0
  821. package/dist/core/openapi/merge/pin.js +110 -0
  822. package/dist/core/openapi/merge/pin.js.map +1 -0
  823. package/dist/core/openspec/decide/capabilities.js +244 -0
  824. package/dist/core/openspec/decide/capabilities.js.map +1 -0
  825. package/dist/core/openspec/decide/dispositions.js +63 -0
  826. package/dist/core/openspec/decide/dispositions.js.map +1 -0
  827. package/dist/core/openspec/decide/renames.js +179 -0
  828. package/dist/core/openspec/decide/renames.js.map +1 -0
  829. package/dist/core/openspec/decide/verdict.js +84 -0
  830. package/dist/core/openspec/decide/verdict.js.map +1 -0
  831. package/dist/core/openspec/inventory.js +220 -0
  832. package/dist/core/openspec/inventory.js.map +1 -0
  833. package/dist/core/openspec/model/mapping.js +78 -0
  834. package/dist/core/openspec/model/mapping.js.map +1 -0
  835. package/dist/core/openspec/model/model.js +70 -0
  836. package/dist/core/openspec/model/model.js.map +1 -0
  837. package/dist/core/openspec/scan/changes.js +241 -0
  838. package/dist/core/openspec/scan/changes.js.map +1 -0
  839. package/dist/core/openspec/scan/config.js +191 -0
  840. package/dist/core/openspec/scan/config.js.map +1 -0
  841. package/dist/core/openspec/scan/shape.js +304 -0
  842. package/dist/core/openspec/scan/shape.js.map +1 -0
  843. package/dist/core/openspec/scan/walk.js +116 -0
  844. package/dist/core/openspec/scan/walk.js.map +1 -0
  845. package/dist/core/openspec/scan/workspace.js +71 -0
  846. package/dist/core/openspec/scan/workspace.js.map +1 -0
  847. package/dist/core/owners/codeowners.js +141 -0
  848. package/dist/core/owners/codeowners.js.map +1 -0
  849. package/dist/core/pack/features.js +120 -0
  850. package/dist/core/pack/features.js.map +1 -0
  851. package/dist/core/pack/joins.js +112 -0
  852. package/dist/core/pack/joins.js.map +1 -0
  853. package/dist/core/pack/living.js +157 -0
  854. package/dist/core/pack/living.js.map +1 -0
  855. package/dist/core/pack/pack.js +120 -0
  856. package/dist/core/pack/pack.js.map +1 -0
  857. package/dist/core/permissions/permissions.js +87 -0
  858. package/dist/core/permissions/permissions.js.map +1 -0
  859. package/dist/core/projection/api.js +84 -0
  860. package/dist/core/projection/api.js.map +1 -0
  861. package/dist/core/projection/arch-slice.js +63 -0
  862. package/dist/core/projection/arch-slice.js.map +1 -0
  863. package/dist/core/projection/events.js +34 -0
  864. package/dist/core/projection/events.js.map +1 -0
  865. package/dist/core/projection/introduced.js +14 -0
  866. package/dist/core/projection/introduced.js.map +1 -0
  867. package/dist/core/provenance/findings.js +244 -0
  868. package/dist/core/provenance/findings.js.map +1 -0
  869. package/dist/core/provenance/git.js +201 -0
  870. package/dist/core/provenance/git.js.map +1 -0
  871. package/dist/core/provenance/gitq/moves.js +139 -0
  872. package/dist/core/provenance/gitq/moves.js.map +1 -0
  873. package/dist/core/provenance/gitq/vouched-ancestor.js +179 -0
  874. package/dist/core/provenance/gitq/vouched-ancestor.js.map +1 -0
  875. package/dist/core/provenance/sample/scope.js +238 -0
  876. package/dist/core/provenance/sample/scope.js.map +1 -0
  877. package/dist/core/provenance/sample/sections.js +61 -0
  878. package/dist/core/provenance/sample/sections.js.map +1 -0
  879. package/dist/core/provenance/sources.js +280 -0
  880. package/dist/core/provenance/sources.js.map +1 -0
  881. package/dist/core/provenance/stamp.js +220 -0
  882. package/dist/core/provenance/stamp.js.map +1 -0
  883. package/dist/core/provenance/walk.js +157 -0
  884. package/dist/core/provenance/walk.js.map +1 -0
  885. package/dist/core/repo/authored/paths.js +210 -0
  886. package/dist/core/repo/authored/paths.js.map +1 -0
  887. package/dist/core/repo/entries.js +126 -0
  888. package/dist/core/repo/entries.js.map +1 -0
  889. package/dist/core/repo/paths.js +322 -0
  890. package/dist/core/repo/paths.js.map +1 -0
  891. package/dist/core/repo/repo.js +308 -0
  892. package/dist/core/repo/repo.js.map +1 -0
  893. package/dist/core/repo/service-target.js +153 -0
  894. package/dist/core/repo/service-target.js.map +1 -0
  895. package/dist/core/repo/state.js +58 -0
  896. package/dist/core/repo/state.js.map +1 -0
  897. package/dist/core/repo/tree/find.js +61 -0
  898. package/dist/core/repo/tree/find.js.map +1 -0
  899. package/dist/core/repo/tree/fs.js +90 -0
  900. package/dist/core/repo/tree/fs.js.map +1 -0
  901. package/dist/core/repo/tree/marker.js +61 -0
  902. package/dist/core/repo/tree/marker.js.map +1 -0
  903. package/dist/core/repo/tree/render/body.js +258 -0
  904. package/dist/core/repo/tree/render/body.js.map +1 -0
  905. package/dist/core/repo/tree/render/projects.js +182 -0
  906. package/dist/core/repo/tree/render/projects.js.map +1 -0
  907. package/dist/core/repo/tree/render/service/header.js +125 -0
  908. package/dist/core/repo/tree/render/service/header.js.map +1 -0
  909. package/dist/core/repo/tree/render/service/peers.js +28 -0
  910. package/dist/core/repo/tree/render/service/peers.js.map +1 -0
  911. package/dist/core/repo/tree/render/service/view-id.js +67 -0
  912. package/dist/core/repo/tree/render/service/view-id.js.map +1 -0
  913. package/dist/core/repo/tree/render/service/views.js +78 -0
  914. package/dist/core/repo/tree/render/service/views.js.map +1 -0
  915. package/dist/core/repo/tree/render/stale.js +42 -0
  916. package/dist/core/repo/tree/render/stale.js.map +1 -0
  917. package/dist/core/repo/tree/render/text.js +84 -0
  918. package/dist/core/repo/tree/render/text.js.map +1 -0
  919. package/dist/core/repo/tree/render/views.js +293 -0
  920. package/dist/core/repo/tree/render/views.js.map +1 -0
  921. package/dist/core/repo/tree/walk.js +255 -0
  922. package/dist/core/repo/tree/walk.js.map +1 -0
  923. package/dist/core/results.js +146 -14
  924. package/dist/core/results.js.map +1 -1
  925. package/dist/core/scaffold/landscape.js +239 -0
  926. package/dist/core/scaffold/landscape.js.map +1 -0
  927. package/dist/core/scaffold/legacy.js +271 -0
  928. package/dist/core/scaffold/legacy.js.map +1 -0
  929. package/dist/core/scaffold/readme.js +84 -0
  930. package/dist/core/scaffold/readme.js.map +1 -0
  931. package/dist/core/staging/commit.js +252 -0
  932. package/dist/core/staging/commit.js.map +1 -0
  933. package/dist/core/staging/interrupted.js +96 -0
  934. package/dist/core/staging/interrupted.js.map +1 -0
  935. package/dist/core/staging/lock.js +268 -0
  936. package/dist/core/staging/lock.js.map +1 -0
  937. package/dist/core/staging/recovery/finding.js +35 -0
  938. package/dist/core/staging/recovery/finding.js.map +1 -0
  939. package/dist/core/staging/recovery/intent.js +95 -0
  940. package/dist/core/staging/recovery/intent.js.map +1 -0
  941. package/dist/core/staging/recovery/recover.js +204 -0
  942. package/dist/core/staging/recovery/recover.js.map +1 -0
  943. package/dist/core/staging/recovery/residue.js +62 -0
  944. package/dist/core/staging/recovery/residue.js.map +1 -0
  945. package/dist/core/staging/snapshot/manifest.js +188 -0
  946. package/dist/core/staging/snapshot/manifest.js.map +1 -0
  947. package/dist/core/staging/snapshot/snapshot.js +196 -0
  948. package/dist/core/staging/snapshot/snapshot.js.map +1 -0
  949. package/dist/core/staging/txn/forward.js +181 -0
  950. package/dist/core/staging/txn/forward.js.map +1 -0
  951. package/dist/core/staging/txn/journal.js +139 -0
  952. package/dist/core/staging/txn/journal.js.map +1 -0
  953. package/dist/core/staging/txn/transaction.js +75 -0
  954. package/dist/core/staging/txn/transaction.js.map +1 -0
  955. package/dist/core/staging/writes.js +113 -0
  956. package/dist/core/staging/writes.js.map +1 -0
  957. package/dist/core/status/actions/execution.js +60 -0
  958. package/dist/core/status/actions/execution.js.map +1 -0
  959. package/dist/core/status/contracts.js +126 -0
  960. package/dist/core/status/contracts.js.map +1 -0
  961. package/dist/core/status/feature/artifacts.js +196 -0
  962. package/dist/core/status/feature/artifacts.js.map +1 -0
  963. package/dist/core/status/feature/feature.js +214 -0
  964. package/dist/core/status/feature/feature.js.map +1 -0
  965. package/dist/core/status/feature/next.js +163 -0
  966. package/dist/core/status/feature/next.js.map +1 -0
  967. package/dist/core/status/feature/state.js +21 -0
  968. package/dist/core/status/feature/state.js.map +1 -0
  969. package/dist/core/status/feature/words.js +96 -0
  970. package/dist/core/status/feature/words.js.map +1 -0
  971. package/dist/core/status/fleet/fleet.js +216 -0
  972. package/dist/core/status/fleet/fleet.js.map +1 -0
  973. package/dist/core/status/fleet/next.js +302 -0
  974. package/dist/core/status/fleet/next.js.map +1 -0
  975. package/dist/core/status/interrupted.js +97 -0
  976. package/dist/core/status/interrupted.js.map +1 -0
  977. package/dist/core/status/report.js +31 -0
  978. package/dist/core/status/report.js.map +1 -0
  979. package/dist/core/status/scan.js +41 -0
  980. package/dist/core/status/scan.js.map +1 -0
  981. package/dist/core/status/verification.js +216 -0
  982. package/dist/core/status/verification.js.map +1 -0
  983. package/dist/core/tasks/packet.js +199 -0
  984. package/dist/core/tasks/packet.js.map +1 -0
  985. package/dist/core/tasks/record.js +43 -0
  986. package/dist/core/tasks/record.js.map +1 -0
  987. package/dist/core/tasks/sources.js +181 -0
  988. package/dist/core/tasks/sources.js.map +1 -0
  989. package/dist/core/tasks/stamps.js +76 -0
  990. package/dist/core/tasks/stamps.js.map +1 -0
  991. package/dist/core/tasks/unit.js +0 -0
  992. package/dist/core/tasks/unit.js.map +1 -0
  993. package/dist/core/usecases/capability.js +166 -0
  994. package/dist/core/usecases/capability.js.map +1 -0
  995. package/dist/core/usecases/delta/claims.js +140 -0
  996. package/dist/core/usecases/delta/claims.js.map +1 -0
  997. package/dist/core/usecases/delta/flows.js +101 -0
  998. package/dist/core/usecases/delta/flows.js.map +1 -0
  999. package/dist/core/usecases/delta/modified.js +315 -0
  1000. package/dist/core/usecases/delta/modified.js.map +1 -0
  1001. package/dist/core/usecases/delta/overlay.js +76 -0
  1002. package/dist/core/usecases/delta/overlay.js.map +1 -0
  1003. package/dist/core/usecases/fleet.js +296 -0
  1004. package/dist/core/usecases/fleet.js.map +1 -0
  1005. package/dist/core/usecases/grade/capability-tag.js +93 -0
  1006. package/dist/core/usecases/grade/capability-tag.js.map +1 -0
  1007. package/dist/core/usecases/grade/feature.js +88 -0
  1008. package/dist/core/usecases/grade/feature.js.map +1 -0
  1009. package/dist/core/usecases/grade/requirement-tag.js +94 -0
  1010. package/dist/core/usecases/grade/requirement-tag.js.map +1 -0
  1011. package/dist/core/usecases/grade/steps.js +266 -0
  1012. package/dist/core/usecases/grade/steps.js.map +1 -0
  1013. package/dist/core/usecases/grade/usecases.js +112 -0
  1014. package/dist/core/usecases/grade/usecases.js.map +1 -0
  1015. package/dist/core/usecases/operations.js +123 -0
  1016. package/dist/core/usecases/operations.js.map +1 -0
  1017. package/dist/core/usecases/place.js +44 -0
  1018. package/dist/core/usecases/place.js.map +1 -0
  1019. package/dist/core/usecases/service/exclude.js +119 -0
  1020. package/dist/core/usecases/service/exclude.js.map +1 -0
  1021. package/dist/core/usecases/service/flows.js +164 -0
  1022. package/dist/core/usecases/service/flows.js.map +1 -0
  1023. package/dist/core/usecases/suites/participants.js +83 -0
  1024. package/dist/core/usecases/suites/participants.js.map +1 -0
  1025. package/dist/core/usecases/suites/suites.js +45 -0
  1026. package/dist/core/usecases/suites/suites.js.map +1 -0
  1027. package/dist/core/usecases/touch.js +101 -0
  1028. package/dist/core/usecases/touch.js.map +1 -0
  1029. package/dist/core/verify/answers.js +180 -0
  1030. package/dist/core/verify/answers.js.map +1 -0
  1031. package/dist/core/verify/build.js +170 -0
  1032. package/dist/core/verify/build.js.map +1 -0
  1033. package/dist/core/verify/checklist.js +259 -0
  1034. package/dist/core/verify/checklist.js.map +1 -0
  1035. package/dist/core/verify/claims/identity.js +61 -0
  1036. package/dist/core/verify/claims/identity.js.map +1 -0
  1037. package/dist/core/verify/cross/diff.js +97 -0
  1038. package/dist/core/verify/cross/diff.js.map +1 -0
  1039. package/dist/core/verify/evidence/contract.js +169 -0
  1040. package/dist/core/verify/evidence/contract.js.map +1 -0
  1041. package/dist/core/verify/location.js +67 -0
  1042. package/dist/core/verify/location.js.map +1 -0
  1043. package/dist/core/verify/pins/lint.js +158 -0
  1044. package/dist/core/verify/pins/lint.js.map +1 -0
  1045. package/dist/core/verify/pins/pin.js +95 -0
  1046. package/dist/core/verify/pins/pin.js.map +1 -0
  1047. package/dist/core/verify/read/file.js +224 -0
  1048. package/dist/core/verify/read/file.js.map +1 -0
  1049. package/dist/core/verify/read/shape.js +169 -0
  1050. package/dist/core/verify/read/shape.js.map +1 -0
  1051. package/dist/core/verify/read/union.js +105 -0
  1052. package/dist/core/verify/read/union.js.map +1 -0
  1053. package/dist/core/verify/record.js +165 -0
  1054. package/dist/core/verify/record.js.map +1 -0
  1055. package/dist/core/verify/store/commit.js +99 -0
  1056. package/dist/core/verify/store/commit.js.map +1 -0
  1057. package/dist/core/verify/store/render.js +61 -0
  1058. package/dist/core/verify/store/render.js.map +1 -0
  1059. package/dist/core/vocabulary/health.js +91 -0
  1060. package/dist/core/vocabulary/health.js.map +1 -0
  1061. package/dist/core/vocabulary/issue.js +59 -0
  1062. package/dist/core/vocabulary/issue.js.map +1 -0
  1063. package/dist/core/vocabulary/maturity.js +216 -0
  1064. package/dist/core/vocabulary/maturity.js.map +1 -0
  1065. package/dist/core/vocabulary/report.js +90 -0
  1066. package/dist/core/vocabulary/report.js.map +1 -0
  1067. package/dist/core/vocabulary/steps.js +266 -0
  1068. package/dist/core/vocabulary/steps.js.map +1 -0
  1069. package/dist/core/workspace/discover.js +239 -0
  1070. package/dist/core/workspace/discover.js.map +1 -0
  1071. package/dist/core/workspace/render.js +52 -0
  1072. package/dist/core/workspace/render.js.map +1 -0
  1073. package/examples/README.md +232 -0
  1074. package/examples/docs/architecture/adrs/0001-transactional-outbox.md +33 -0
  1075. package/examples/docs/architecture/capabilities.yaml +31 -0
  1076. package/examples/docs/architecture/landscape.likec4 +336 -0
  1077. package/examples/docs/architecture/obligations.yaml +23 -0
  1078. package/examples/docs/architecture/permissions.yaml +50 -0
  1079. package/examples/docs/architecture/services.likec4 +70 -0
  1080. package/examples/docs/architecture/subsystems.likec4 +18 -0
  1081. package/examples/docs/architecture/usecases/order-notification.likec4 +74 -0
  1082. package/examples/docs/capabilities/checkout/spec.md +55 -0
  1083. package/examples/docs/capabilities/identity/tokens/spec.md +42 -0
  1084. package/examples/docs/capabilities/order-notifications/spec.md +43 -0
  1085. package/examples/docs/features/FEAT-101-payment-splitting/adrs/0001-dedicated-split-service.md +18 -0
  1086. package/examples/docs/features/FEAT-101-payment-splitting/delta.likec4 +94 -0
  1087. package/examples/docs/features/FEAT-101-payment-splitting/intent.md +44 -0
  1088. package/examples/docs/features/FEAT-101-payment-splitting/specs/checkout-web/spec.md +21 -0
  1089. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-service/asyncapi.yaml +132 -0
  1090. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-service/spec.md +36 -0
  1091. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/arch.spec.md +40 -0
  1092. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/openapi.yaml +116 -0
  1093. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/spec.md +55 -0
  1094. package/examples/docs/features/FEAT-112-retire-order-v1/intent.md +35 -0
  1095. package/examples/docs/features/FEAT-112-retire-order-v1/specs/order-service/openapi.yaml +31 -0
  1096. package/examples/docs/features/FEAT-112-retire-order-v1/specs/order-service/spec.md +17 -0
  1097. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/architecture/landscape.likec4 +253 -0
  1098. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/services/order-service/spec.md +121 -0
  1099. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/services/payment-service/openapi.yaml +111 -0
  1100. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/services/payment-service/spec.md +58 -0
  1101. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/manifest.json +32 -0
  1102. package/examples/docs/features/archive/FEAT-088-refunds/adrs/0001-refunds-stay-in-payment-service.md +26 -0
  1103. package/examples/docs/features/archive/FEAT-088-refunds/delta.likec4 +28 -0
  1104. package/examples/docs/features/archive/FEAT-088-refunds/intent.md +26 -0
  1105. package/examples/docs/features/archive/FEAT-088-refunds/specs/order-service/spec.md +37 -0
  1106. package/examples/docs/features/archive/FEAT-088-refunds/specs/payment-service/openapi.yaml +73 -0
  1107. package/examples/docs/features/archive/FEAT-088-refunds/specs/payment-service/spec.md +23 -0
  1108. package/examples/docs/features/archive/FEAT-088-refunds/verification.yaml +76 -0
  1109. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/architecture/landscape.likec4 +275 -0
  1110. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/payment-service/asyncapi.yaml +96 -0
  1111. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/payment-service/spec.md +82 -0
  1112. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/platform/notification-service/asyncapi.yaml +164 -0
  1113. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/platform/notification-service/spec.md +91 -0
  1114. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/manifest.json +46 -0
  1115. package/examples/docs/features/archive/FEAT-120-refund-notification/delta.likec4 +36 -0
  1116. package/examples/docs/features/archive/FEAT-120-refund-notification/intent.md +22 -0
  1117. package/examples/docs/features/archive/FEAT-120-refund-notification/scenario-report.json +10 -0
  1118. package/examples/docs/features/archive/FEAT-120-refund-notification/specs/notification-service/asyncapi.yaml +208 -0
  1119. package/examples/docs/features/archive/FEAT-120-refund-notification/specs/notification-service/spec.md +24 -0
  1120. package/examples/docs/features/archive/FEAT-120-refund-notification/specs/payment-service/asyncapi.yaml +137 -0
  1121. package/examples/docs/features/archive/FEAT-120-refund-notification/specs/payment-service/spec.md +31 -0
  1122. package/examples/docs/features/archive/FEAT-120-refund-notification/verification.yaml +84 -0
  1123. package/examples/docs/glossary/order.md +15 -0
  1124. package/examples/docs/glossary/payments/authorization.md +14 -0
  1125. package/examples/docs/likec4.config.json +8 -0
  1126. package/examples/docs/loam.json +3 -0
  1127. package/examples/docs/services/checkout-web/model.likec4 +92 -0
  1128. package/examples/docs/services/checkout-web/spec.md +91 -0
  1129. package/examples/docs/services/checkout-web/ui/pages/checkout.page.yaml +40 -0
  1130. package/examples/docs/services/checkout-web/ui/pages/order-status.page.yaml +24 -0
  1131. package/examples/docs/services/checkout-web/ui/pages/split-payment.page.yaml +26 -0
  1132. package/examples/docs/services/order-service/adrs/0001-orchestrated-order-lifecycle.md +52 -0
  1133. package/examples/docs/services/order-service/arch.spec.md +134 -0
  1134. package/examples/docs/services/order-service/asyncapi.yaml +109 -0
  1135. package/examples/docs/services/order-service/health.yaml +57 -0
  1136. package/examples/docs/services/order-service/model.likec4 +126 -0
  1137. package/examples/docs/services/order-service/openapi.yaml +257 -0
  1138. package/examples/docs/services/order-service/runbook.md +62 -0
  1139. package/examples/docs/services/order-service/spec.md +134 -0
  1140. package/examples/docs/services/payment-service/adrs/0001-payments-outbox.md +18 -0
  1141. package/examples/docs/services/payment-service/adrs/0002-idempotency-keys-on-authorization.md +27 -0
  1142. package/examples/docs/services/payment-service/arch.spec.md +76 -0
  1143. package/examples/docs/services/payment-service/asyncapi.yaml +130 -0
  1144. package/examples/docs/services/payment-service/health.yaml +39 -0
  1145. package/examples/docs/services/payment-service/model.likec4 +68 -0
  1146. package/examples/docs/services/payment-service/openapi.yaml +151 -0
  1147. package/examples/docs/services/payment-service/runbook.md +37 -0
  1148. package/examples/docs/services/payment-service/spec.md +88 -0
  1149. package/examples/docs/services/platform/identity-service/adrs/0001-token-introspection-over-local-validation.md +60 -0
  1150. package/examples/docs/services/platform/identity-service/arch.spec.md +120 -0
  1151. package/examples/docs/services/platform/identity-service/health.yaml +70 -0
  1152. package/examples/docs/services/platform/identity-service/model.likec4 +81 -0
  1153. package/examples/docs/services/platform/identity-service/openapi.yaml +197 -0
  1154. package/examples/docs/services/platform/identity-service/runbook.md +95 -0
  1155. package/examples/docs/services/platform/identity-service/spec.md +119 -0
  1156. package/examples/docs/services/platform/notification-service/asyncapi.yaml +200 -0
  1157. package/examples/docs/services/platform/notification-service/health.yaml +40 -0
  1158. package/examples/docs/services/platform/notification-service/model.likec4 +97 -0
  1159. package/examples/docs/services/platform/notification-service/runbook.md +48 -0
  1160. package/examples/docs/services/platform/notification-service/spec.md +112 -0
  1161. package/examples/docs/services/platform/subsystem.yaml +2 -0
  1162. package/examples/fleet.yaml +57 -0
  1163. package/package.json +19 -6
  1164. package/dist/commands/adopt.js +0 -240
  1165. package/dist/commands/adopt.js.map +0 -1
  1166. package/dist/commands/archive.js +0 -1313
  1167. package/dist/commands/archive.js.map +0 -1
  1168. package/dist/commands/delta.js +0 -388
  1169. package/dist/commands/delta.js.map +0 -1
  1170. package/dist/commands/docs-repo-gate.js.map +0 -1
  1171. package/dist/commands/format.js +0 -17
  1172. package/dist/commands/format.js.map +0 -1
  1173. package/dist/commands/gherkin.js +0 -309
  1174. package/dist/commands/gherkin.js.map +0 -1
  1175. package/dist/commands/init.js.map +0 -1
  1176. package/dist/commands/list.js +0 -295
  1177. package/dist/commands/list.js.map +0 -1
  1178. package/dist/commands/migrate-openspec.js +0 -950
  1179. package/dist/commands/migrate-openspec.js.map +0 -1
  1180. package/dist/commands/new.js +0 -413
  1181. package/dist/commands/new.js.map +0 -1
  1182. package/dist/commands/rebase.js +0 -356
  1183. package/dist/commands/rebase.js.map +0 -1
  1184. package/dist/commands/show.js +0 -320
  1185. package/dist/commands/show.js.map +0 -1
  1186. package/dist/commands/status.js +0 -262
  1187. package/dist/commands/status.js.map +0 -1
  1188. package/dist/commands/unarchive.js +0 -317
  1189. package/dist/commands/unarchive.js.map +0 -1
  1190. package/dist/commands/validate.js +0 -1773
  1191. package/dist/commands/validate.js.map +0 -1
  1192. package/dist/commands/verify.js +0 -775
  1193. package/dist/commands/verify.js.map +0 -1
  1194. package/dist/commands/vouch.js +0 -421
  1195. package/dist/commands/vouch.js.map +0 -1
  1196. package/dist/core/agent.js +0 -2173
  1197. package/dist/core/agent.js.map +0 -1
  1198. package/dist/core/agents-stamp.js.map +0 -1
  1199. package/dist/core/arch.js +0 -130
  1200. package/dist/core/arch.js.map +0 -1
  1201. package/dist/core/asyncapi.js +0 -253
  1202. package/dist/core/asyncapi.js.map +0 -1
  1203. package/dist/core/brief.js +0 -755
  1204. package/dist/core/brief.js.map +0 -1
  1205. package/dist/core/coherence.js +0 -577
  1206. package/dist/core/coherence.js.map +0 -1
  1207. package/dist/core/concurrency.js.map +0 -1
  1208. package/dist/core/config.js.map +0 -1
  1209. package/dist/core/delta.js +0 -476
  1210. package/dist/core/delta.js.map +0 -1
  1211. package/dist/core/dependencies.js +0 -356
  1212. package/dist/core/dependencies.js.map +0 -1
  1213. package/dist/core/doctor.js +0 -596
  1214. package/dist/core/doctor.js.map +0 -1
  1215. package/dist/core/document-bytes.js.map +0 -1
  1216. package/dist/core/explore.js +0 -225
  1217. package/dist/core/explore.js.map +0 -1
  1218. package/dist/core/frontmatter.js.map +0 -1
  1219. package/dist/core/gherkin.js +0 -463
  1220. package/dist/core/gherkin.js.map +0 -1
  1221. package/dist/core/health.js +0 -67
  1222. package/dist/core/health.js.map +0 -1
  1223. package/dist/core/ids.js +0 -122
  1224. package/dist/core/ids.js.map +0 -1
  1225. package/dist/core/issue.js +0 -9
  1226. package/dist/core/issue.js.map +0 -1
  1227. package/dist/core/json.js +0 -74
  1228. package/dist/core/json.js.map +0 -1
  1229. package/dist/core/likec4.js +0 -489
  1230. package/dist/core/likec4.js.map +0 -1
  1231. package/dist/core/maturity.js +0 -66
  1232. package/dist/core/maturity.js.map +0 -1
  1233. package/dist/core/openapi-merge.js +0 -552
  1234. package/dist/core/openapi-merge.js.map +0 -1
  1235. package/dist/core/openapi.js.map +0 -1
  1236. package/dist/core/openspec-inventory.js +0 -1440
  1237. package/dist/core/openspec-inventory.js.map +0 -1
  1238. package/dist/core/path-safety.js.map +0 -1
  1239. package/dist/core/provenance.js +0 -787
  1240. package/dist/core/provenance.js.map +0 -1
  1241. package/dist/core/records.js.map +0 -1
  1242. package/dist/core/repo.js +0 -438
  1243. package/dist/core/repo.js.map +0 -1
  1244. package/dist/core/report.js +0 -47
  1245. package/dist/core/report.js.map +0 -1
  1246. package/dist/core/spec.js +0 -505
  1247. package/dist/core/spec.js.map +0 -1
  1248. package/dist/core/staging.js +0 -890
  1249. package/dist/core/staging.js.map +0 -1
  1250. package/dist/core/status.js +0 -1132
  1251. package/dist/core/status.js.map +0 -1
  1252. package/dist/core/steps.js +0 -72
  1253. package/dist/core/steps.js.map +0 -1
  1254. package/dist/core/verify.js +0 -807
  1255. package/dist/core/verify.js.map +0 -1
  1256. package/dist/core/version.js.map +0 -1
@@ -0,0 +1,312 @@
1
+ /**
2
+ * The diff computation: join the base fleet (`./base-state.ts`) against the
3
+ * working tree (`core/consumers/current.ts`) and say, per service, what changed in
4
+ * FLEET-MEANINGFUL terms — requirements by identity and digest, operations
5
+ * and messages by their join tokens and their `$ref`-closure digests,
6
+ * cross-service joins by tuple — with the authored consumers of every
7
+ * removal, deprecation and modification named (`core/consumers/consumers.ts`),
8
+ * and the cross-service joins that appeared or went away (`./joins.ts`).
9
+ *
10
+ * Two disciplines rule every branch here. Removal is graded against who still
11
+ * depends on it: a removal nobody names is a warning, a removal the fleet
12
+ * still joins to is an error and sets `breaking`. A MODIFICATION is never an
13
+ * error, whoever is joined to it: whether a changed schema breaks its readers
14
+ * is a field-level question loam hands to oasdiff on purpose, so the finding
15
+ * names the consumers and the tool, and stops there. And "nobody could look" is
16
+ * never "nothing changed": an unreadable artifact on EITHER side suspends
17
+ * that subject's axis — recorded in `unreadable[]`, counted in the summary,
18
+ * carried into the exit code by the command — instead of letting an
19
+ * unreadable base read as everything-added or an unreadable working file
20
+ * read as everything-removed. The one thing that is not a suspension is a
21
+ * contract the base held byte-for-byte: somebody COULD look, at the bytes,
22
+ * and they did not change (`comparable`, `UNTOUCHED_SKIPS`).
23
+ */
24
+ import { requirementDigest } from "../document/spec.js";
25
+ import { rawServiceId } from "../kernel/ids/service.js";
26
+ import { consumerStance, scanDetails } from "../consumers/scan.js";
27
+ import { consumerJoinChanges } from "./joins.js";
28
+ /** Severity is a fact about the code, not a call-site choice — one table, no drift. */
29
+ const DIFF_SEVERITY = {
30
+ "diff.service-added": "ok",
31
+ "diff.service-removed": "warn",
32
+ "diff.requirement-added": "ok",
33
+ "diff.requirement-removed": "warn",
34
+ "diff.requirement-modified": "ok",
35
+ "diff.op-added": "ok",
36
+ "diff.op-removed": "warn",
37
+ "diff.op-removed-consumed": "error",
38
+ "diff.op-deprecated": "warn",
39
+ "diff.op-modified": "warn",
40
+ "diff.message-added": "ok",
41
+ "diff.message-removed": "warn",
42
+ "diff.message-removed-consumed": "error",
43
+ "diff.message-modified": "warn",
44
+ "diff.consumer-added": "ok",
45
+ "diff.consumer-removed": "ok",
46
+ };
47
+ function found(code, message, details) {
48
+ const carry = details !== undefined && details.length > 0;
49
+ return { severity: DIFF_SEVERITY[code], code, message, ...(carry ? { details } : {}) };
50
+ }
51
+ /**
52
+ * A side the service does not exist on: absence everywhere, honestly. The id is
53
+ * a key of one of the two sides' maps, each keyed by a directory's leaf name.
54
+ */
55
+ const ABSENT = { kind: "absent" };
56
+ const emptyState = (id) => ({ id: rawServiceId(id), dir: "", spec: ABSENT, archSpec: ABSENT, openapi: ABSENT, asyncapi: ABSENT });
57
+ /**
58
+ * The axes on which an unreadable document the branch left byte-identical is
59
+ * SKIPPED rather than suspended: the two contracts. Identical bytes are a
60
+ * proof, not a guess — the same parser over the same bytes cannot read
61
+ * differently on the two sides, so there is nothing of this document's own
62
+ * to diff, and suspending it anyway made every `loam diff` exit 1 over a
63
+ * fleet that holds one AsyncAPI 2.x file (unreadable by policy since
64
+ * core/asyncapi/read.ts refused pre-3.0), whatever the branch changed.
65
+ *
66
+ * Not the spec axes, and that is the victims scan's doing, not an oversight:
67
+ * an unreadable spec.md or arch.spec.md is also the document ANOTHER
68
+ * service's removal could not be checked against (`core/consumers/consumers.ts`'s
69
+ * `scanRequirements`), and its `unreadable[]` entry here is what carries that
70
+ * suspension to exit 1 (`opsDiff`'s removal branch says so). No scan reads a
71
+ * contract it could not parse as evidence of anything — `producers` takes
72
+ * positive evidence only — so skipping one hides no other answer.
73
+ */
74
+ const UNTOUCHED_SKIPS = new Set(["openapi", "asyncapi"]);
75
+ /**
76
+ * Guard one axis pair: record unreadable sides on the sink and say whether
77
+ * the axis may be compared at all. Reading one good side against a suspended
78
+ * one would grade absence it never proved. A contract unreadable on BOTH
79
+ * sides with one byte hash is the branch's untouched file: not compared and
80
+ * not recorded either (`UNTOUCHED_SKIPS`). A changed one, or one only one
81
+ * side cannot read, still suspends.
82
+ */
83
+ function comparable(sink, axis, pair) {
84
+ const { base, current } = pair;
85
+ if (UNTOUCHED_SKIPS.has(axis) && base.kind === "unreadable" && current.kind === "unreadable" &&
86
+ base.bytes !== undefined && base.bytes === current.bytes)
87
+ return false;
88
+ for (const side of ["base", "current"]) {
89
+ const state = pair[side];
90
+ if (state.kind === "unreadable")
91
+ sink.unreadable.push({ side, axis, path: state.path, error: state.error });
92
+ }
93
+ return pair.base.kind !== "unreadable" && pair.current.kind !== "unreadable";
94
+ }
95
+ const valueOr = (axis) => (axis.kind === "read" ? axis.value : []);
96
+ /** Identity: `Requirement-ID:` when authored, the heading otherwise — the same join `loam rebase` pins against. */
97
+ const reqKey = (r) => (r.id !== undefined ? `id:${r.id}` : `name:${r.name}`);
98
+ const reqLabel = (r) => (r.id !== undefined ? `${r.name} [${r.id}]` : r.name);
99
+ /** First declaration wins a duplicated key — the same arbitrary-but-stated pick every join on these axes makes. */
100
+ function firstWins(items, key) {
101
+ const map = new Map();
102
+ for (const item of items)
103
+ if (!map.has(key(item)))
104
+ map.set(key(item), item);
105
+ return map;
106
+ }
107
+ /** Entry comparator by map key — explicit, because the default sort stringifies whole entries. */
108
+ const byKey = (a, b) => (a[0] < b[0] ? -1 : 1);
109
+ function requirementsDiff(sink, pair) {
110
+ // v1 diffs spec.md's requirements only; arch.spec.md is read for the
111
+ // Consumes: join but its requirement inventory is deferred (the two axes
112
+ // are separate namespaces, and diffing both doubles the surface). Both
113
+ // pairs are guarded BEFORE the early return, so a service whose two spec
114
+ // files are both unreadable reports both suspensions, not just the first.
115
+ const specComparable = comparable(sink, "spec", { base: pair.base.spec, current: pair.current.spec });
116
+ comparable(sink, "archSpec", { base: pair.base.archSpec, current: pair.current.archSpec });
117
+ if (!specComparable)
118
+ return;
119
+ const base = firstWins(valueOr(pair.base.spec), reqKey);
120
+ const current = firstWins(valueOr(pair.current.spec), reqKey);
121
+ for (const [key, r] of [...current].sort(byKey)) {
122
+ const before = base.get(key);
123
+ if (before === undefined)
124
+ sink.findings.push(found("diff.requirement-added", `living requirement added since base: '${reqLabel(r)}'`));
125
+ else if (requirementDigest(before) !== requirementDigest(r)) {
126
+ sink.findings.push(found("diff.requirement-modified", `living requirement modified since base: '${reqLabel(r)}'`));
127
+ }
128
+ }
129
+ for (const [key, r] of [...base].sort(byKey)) {
130
+ if (!current.has(key))
131
+ sink.findings.push(found("diff.requirement-removed", `living requirement removed since base: '${reqLabel(r)}'`));
132
+ }
133
+ }
134
+ /**
135
+ * The second half of every modification message. loam joins consumers to the
136
+ * thing that moved; it does not read what a schema SAYS (core/brief/unchecked.ts
137
+ * lists that as unchecked), so a breaking rename and a new optional field are
138
+ * the same finding here — the specialist diff tells them apart.
139
+ */
140
+ const notGraded = (tool) => `loam does not grade whether the change is breaking — run ${tool} on the two states of this contract`;
141
+ async function opsDiff(sink, pair, victims) {
142
+ if (!comparable(sink, "openapi", { base: pair.base.openapi, current: pair.current.openapi }))
143
+ return;
144
+ const base = firstWins(valueOr(pair.base.openapi), (op) => op.id);
145
+ const current = firstWins(valueOr(pair.current.openapi), (op) => op.id);
146
+ for (const [id, op] of [...current].sort(byKey)) {
147
+ const before = base.get(id);
148
+ if (before === undefined) {
149
+ sink.findings.push(found("diff.op-added", `operation '${id}' added since base (${op.method.toUpperCase()} ${op.path})`));
150
+ }
151
+ else if (!before.deprecated && op.deprecated) {
152
+ const scan = await victims.opConsumers(sink.id, id);
153
+ sink.findings.push(found("diff.op-deprecated", `operation '${id}' is deprecated since base — ${consumerStance(scan)}`, scanDetails(scan)));
154
+ }
155
+ else if (before.closureDigest !== op.closureDigest || before.path !== op.path || before.method !== op.method) {
156
+ // `else`, because setting the flag moves the digest by itself (it is a
157
+ // key of the node): a deprecation already names the same consumers, and
158
+ // a second finding over them would say nothing new. The digest covers
159
+ // the `$ref` closure — a field renamed in a shared component is exactly
160
+ // the change this code exists for, and the operation's own bytes never
161
+ // move for it. A relocated slot is a change too, though the node is not.
162
+ const scan = await victims.opConsumers(sink.id, id);
163
+ sink.findings.push(found("diff.op-modified", `operation '${id}' (${op.method.toUpperCase()} ${op.path}) changed since base, in its own definition or a schema it references — ${consumerStance(scan)}; ${notGraded("`oasdiff breaking`")}`, scanDetails(scan)));
164
+ }
165
+ }
166
+ for (const [id] of [...base].sort(byKey)) {
167
+ if (current.has(id))
168
+ continue;
169
+ const scan = await victims.opConsumers(sink.id, id);
170
+ if (scan.victims.length > 0) {
171
+ sink.findings.push(found("diff.op-removed-consumed", `operation '${id}' was removed since base and the current fleet still names it — these joins break`, scanDetails(scan)));
172
+ }
173
+ else if (scan.suspended.length > 0) {
174
+ // "Nobody could be checked" is not "nobody names it", so this message
175
+ // must not assert a negative the scan never proved. An unreadable
176
+ // consumer document carries the run to exit 1 through its own
177
+ // unreadable[] entry; a caller drawn with no op does not — it stays this
178
+ // warning, so a seeded, op-less map does not fail every removal.
179
+ sink.findings.push(found("diff.op-removed", `operation '${id}' was removed since base; whether the current fleet still names it could NOT be fully answered — ${scan.suspended.length} possible consumer(s) could not be checked`, scanDetails(scan)));
180
+ }
181
+ else {
182
+ sink.findings.push(found("diff.op-removed", `operation '${id}' was removed since base; no current edge, requirement or use-case hop names it`));
183
+ }
184
+ }
185
+ }
186
+ async function messagesDiff(sink, pair, victims) {
187
+ if (!comparable(sink, "asyncapi", { base: pair.base.asyncapi, current: pair.current.asyncapi }))
188
+ return;
189
+ const base = firstWins(valueOr(pair.base.asyncapi), (m) => m.name);
190
+ const current = firstWins(valueOr(pair.current.asyncapi), (m) => m.name);
191
+ for (const [name, message] of [...current].sort(byKey)) {
192
+ const before = base.get(name);
193
+ if (before === undefined) {
194
+ sink.findings.push(found("diff.message-added", `message '${name}' added since base`));
195
+ }
196
+ else if (before.closureDigest !== message.closureDigest) {
197
+ const scan = await victims.messageConsumers(sink.id, name);
198
+ sink.findings.push(found("diff.message-modified", `message '${name}' changed since base, in its declaration or a schema its payload references — ${consumerStance(scan)}; ${notGraded("`asyncapi diff`")}`, scanDetails(scan)));
199
+ }
200
+ }
201
+ for (const [name] of [...base].sort(byKey)) {
202
+ if (current.has(name))
203
+ continue;
204
+ // Fleet-global join: a name another current service still SENDS is not
205
+ // orphaned (positive evidence only — an unreadable contract never vouches,
206
+ // and a service that only receives it is one of its consumers, never its
207
+ // producer: `producers` says why that distinction is the gate's too). Nor
208
+ // is one an #external element still publishes, by validate's own rule
209
+ // (`externalProducer` says why): counting the fleet's senders alone made
210
+ // this removal an error that the next `validate --all` called clean.
211
+ const elsewhere = (await victims.producers(name)).filter((d) => d !== sink.id);
212
+ const outside = await victims.externalProducer(name);
213
+ const senders = outside === null ? elsewhere : [...elsewhere, `${outside} (#external)`];
214
+ if (senders.length > 0) {
215
+ sink.findings.push(found("diff.message-removed", `message '${name}' was removed since base; still sent by ${senders.join(", ")}`));
216
+ continue;
217
+ }
218
+ const scan = await victims.messageConsumers(sink.id, name);
219
+ if (scan.victims.length > 0) {
220
+ sink.findings.push(found("diff.message-removed-consumed", `message '${name}' was removed since base and the current fleet still consumes it — these joins break`, scanDetails(scan)));
221
+ }
222
+ else if (scan.suspended.length > 0) {
223
+ sink.findings.push(found("diff.message-removed", `message '${name}' was removed since base; whether anything still consumes it could NOT be fully answered — ${scan.suspended.length} consumer document(s) were not scannable`, scanDetails(scan)));
224
+ }
225
+ else {
226
+ sink.findings.push(found("diff.message-removed", `message '${name}' was removed since base; nothing currently consumes it`));
227
+ }
228
+ }
229
+ }
230
+ /** The graded join changes (`./joins.ts`) as findings on each PROVIDER — the service whose surface the join lands on. */
231
+ function consumerFindings(input) {
232
+ const changes = consumerJoinChanges({
233
+ base: input.base.services,
234
+ baseAmbiguous: new Set(input.base.ambiguous.keys()),
235
+ current: input.current.services,
236
+ currentAmbiguous: new Set(input.current.ambiguous.keys()),
237
+ });
238
+ const byProvider = new Map();
239
+ for (const { t, change } of changes) {
240
+ const what = t.kind === "op" ? `operation '${t.token}'` : `message '${t.token}'`;
241
+ const message = change === "added"
242
+ ? `${t.consumer}'s living requirements now name this service's ${what} — a cross-service join appeared since base`
243
+ : `${t.consumer}'s living requirements no longer name this service's ${what} — a cross-service join went away`;
244
+ // The call sits directly in the push — assigned to a `const x = found(…)`
245
+ // it reads as an arrow-function DECLARATION to the stable-code collector,
246
+ // and both consumer codes silently leave the guarded set.
247
+ byProvider.set(t.provider, [
248
+ ...(byProvider.get(t.provider) ?? []),
249
+ found(change === "added" ? "diff.consumer-added" : "diff.consumer-removed", message),
250
+ ]);
251
+ }
252
+ return byProvider;
253
+ }
254
+ async function diffService(unit) {
255
+ const sink = { id: unit.id, change: "unchanged", findings: [], unreadable: [] };
256
+ if (unit.base === undefined)
257
+ sink.findings.push(found("diff.service-added", `service '${unit.id}' added since base`));
258
+ if (unit.current === undefined && unit.base !== undefined) {
259
+ sink.findings.push(found("diff.service-removed", `service '${unit.id}' (${unit.base.dir}) is gone from the working tree`));
260
+ }
261
+ const pair = { base: unit.base ?? emptyState(unit.id), current: unit.current ?? emptyState(unit.id) };
262
+ requirementsDiff(sink, pair);
263
+ await opsDiff(sink, pair, unit.victims);
264
+ await messagesDiff(sink, pair, unit.victims);
265
+ return sink;
266
+ }
267
+ export async function computeDiff(input) {
268
+ const sides = [input.base.services, input.base.ambiguous, input.current.services, input.current.ambiguous];
269
+ const ids = [...new Set(sides.flatMap((side) => [...side.keys()]))].sort();
270
+ const joins = consumerFindings({ base: input.base, current: input.current });
271
+ const services = [];
272
+ // Sequential on purpose: the report's order IS the contract (identical
273
+ // states must emit identical bytes), the work per service is in-memory
274
+ // joins, and the one expensive read — the victim index's landscape — is
275
+ // memoised behind its first ask, so a fan-out would buy nothing.
276
+ for (const id of ids) {
277
+ const claimants = [...(input.base.ambiguous.get(id) ?? []), ...(input.current.ambiguous.get(id) ?? [])];
278
+ if (claimants.length > 0) {
279
+ // An id two directories claim — either side — has no single state to
280
+ // diff; the whole subject suspends (containment), and the live walk's
281
+ // `subsystem.name-collision` names the same defect for validate.
282
+ services.push({ id, change: "changed", findings: [], unreadable: [], ambiguous: claimants });
283
+ continue;
284
+ }
285
+ const sink = await diffService({ id, base: input.base.services.get(id), current: input.current.services.get(id), victims: input.victims });
286
+ sink.findings.push(...(joins.get(id) ?? []));
287
+ if (input.base.services.has(id) && !input.current.services.has(id))
288
+ sink.change = "removed";
289
+ else if (!input.base.services.has(id))
290
+ sink.change = "added";
291
+ else
292
+ sink.change = sink.findings.length > 0 || sink.unreadable.length > 0 ? "changed" : "unchanged";
293
+ services.push(sink);
294
+ }
295
+ const all = services.flatMap((s) => s.findings);
296
+ const count = (codes) => all.filter(codes).length;
297
+ return {
298
+ services,
299
+ breaking: all.some((f) => f.severity === "error"),
300
+ summary: {
301
+ added: count((f) => f.code.endsWith("-added")),
302
+ removed: count((f) => f.code.endsWith("-removed") || f.code.endsWith("-removed-consumed")),
303
+ // Requirements, operations and messages alike: a reader scanning the one
304
+ // summary line must not see "0 modified" over a PR that renamed a field.
305
+ modified: count((f) => f.code.endsWith("-modified")),
306
+ deprecated: count((f) => f.code === "diff.op-deprecated"),
307
+ unreadable: services.reduce((n, s) => n + s.unreadable.length, 0) +
308
+ services.filter((s) => s.ambiguous !== undefined).length,
309
+ },
310
+ };
311
+ }
312
+ //# sourceMappingURL=semantic.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"semantic.js","sourceRoot":"","sources":["../../../src/core/diff/semantic.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The diff computation: join the base fleet (`./base-state.ts`) against the\n * working tree (`core/consumers/current.ts`) and say, per service, what changed in\n * FLEET-MEANINGFUL terms — requirements by identity and digest, operations\n * and messages by their join tokens and their `$ref`-closure digests,\n * cross-service joins by tuple — with the authored consumers of every\n * removal, deprecation and modification named (`core/consumers/consumers.ts`),\n * and the cross-service joins that appeared or went away (`./joins.ts`).\n *\n * Two disciplines rule every branch here. Removal is graded against who still\n * depends on it: a removal nobody names is a warning, a removal the fleet\n * still joins to is an error and sets `breaking`. A MODIFICATION is never an\n * error, whoever is joined to it: whether a changed schema breaks its readers\n * is a field-level question loam hands to oasdiff on purpose, so the finding\n * names the consumers and the tool, and stops there. And \"nobody could look\" is\n * never \"nothing changed\": an unreadable artifact on EITHER side suspends\n * that subject's axis — recorded in `unreadable[]`, counted in the summary,\n * carried into the exit code by the command — instead of letting an\n * unreadable base read as everything-added or an unreadable working file\n * read as everything-removed. The one thing that is not a suspension is a\n * contract the base held byte-for-byte: somebody COULD look, at the bytes,\n * and they did not change (`comparable`, `UNTOUCHED_SKIPS`).\n */\nimport { requirementDigest, type Requirement } from \"../document/spec.js\";\nimport type { Severity, Finding } from \"../vocabulary/report.js\";\nimport type { BaseFleet } from \"./base-state.js\";\nimport { rawServiceId } from \"../kernel/ids/service.js\";\nimport type { AxisState, ServiceState } from \"../consumers/state.js\";\nimport type { CurrentFleet } from \"../consumers/current.js\";\nimport { consumerStance, scanDetails } from \"../consumers/scan.js\";\nimport type { ConsumerIndex } from \"../consumers/consumers.js\";\nimport { consumerJoinChanges } from \"./joins.js\";\n\n/**\n * The stable finding codes `loam diff` emits. Codes are the machine contract;\n * prose may be reworded, these may not. Documented (backticked) in the\n * generated AGENTS.md's diff section — codes-drift enforces that.\n */\nexport type DiffCode =\n /** A `services/<id>/` directory exists now that did not at the base ref. */\n | \"diff.service-added\"\n /** A service present at the base ref is gone from the working tree. */\n | \"diff.service-removed\"\n /** A living requirement (by `Requirement-ID:`, else heading) not present at base. */\n | \"diff.requirement-added\"\n /** A base requirement no longer in the living spec. */\n | \"diff.requirement-removed\"\n /** Same requirement identity on both sides, `requirementDigest` moved — rebase pins never move it. */\n | \"diff.requirement-modified\"\n /** An operationId in the living contract absent at base. */\n | \"diff.op-added\"\n /** A base operationId gone from the living contract, and no current consumer names it. */\n | \"diff.op-removed\"\n /** Removed since base AND the current fleet still names it — landscape edge or foreign living requirement; details list the victims. Sets `breaking`. */\n | \"diff.op-removed-consumed\"\n /** `deprecated: true` introduced since base; details name the current consumers. */\n | \"diff.op-deprecated\"\n /** Same operationId on both sides, and its node or anything its internal `$ref`s reach moved; details name the authored consumers. Whether it BREAKS them is oasdiff's question, not loam's. */\n | \"diff.op-modified\"\n /** An AsyncAPI message name absent at base. */\n | \"diff.message-added\"\n /** A base message gone, nothing currently consumes it (or another service still sends it — the message says). */\n | \"diff.message-removed\"\n /** Removed since base AND still consumed — a `Consumes:` line or a consumes-edge; details list the victims. Sets `breaking`. */\n | \"diff.message-removed-consumed\"\n /** Same message name on both sides, and its declaration or anything its internal `$ref`s reach moved; details name the authored consumers. Whether it BREAKS them is not graded. */\n | \"diff.message-modified\"\n /** A cross-service join appeared since base: another service's living requirement now names this service's operation or message. */\n | \"diff.consumer-added\"\n /** A cross-service join present at base is gone. */\n | \"diff.consumer-removed\";\n\n/** Severity is a fact about the code, not a call-site choice — one table, no drift. */\nconst DIFF_SEVERITY: Record<DiffCode, Severity> = {\n \"diff.service-added\": \"ok\",\n \"diff.service-removed\": \"warn\",\n \"diff.requirement-added\": \"ok\",\n \"diff.requirement-removed\": \"warn\",\n \"diff.requirement-modified\": \"ok\",\n \"diff.op-added\": \"ok\",\n \"diff.op-removed\": \"warn\",\n \"diff.op-removed-consumed\": \"error\",\n \"diff.op-deprecated\": \"warn\",\n \"diff.op-modified\": \"warn\",\n \"diff.message-added\": \"ok\",\n \"diff.message-removed\": \"warn\",\n \"diff.message-removed-consumed\": \"error\",\n \"diff.message-modified\": \"warn\",\n \"diff.consumer-added\": \"ok\",\n \"diff.consumer-removed\": \"ok\",\n};\n\nfunction found(code: DiffCode, message: string, details?: string[]): Finding {\n const carry = details !== undefined && details.length > 0;\n return { severity: DIFF_SEVERITY[code], code, message, ...(carry ? { details } : {}) };\n}\n\n/** One suspended axis: which side could not be read, and why. */\nexport interface UnreadableEntry {\n side: \"base\" | \"current\";\n axis: \"spec\" | \"archSpec\" | \"openapi\" | \"asyncapi\";\n path: string;\n error: string;\n}\n\nexport interface ServiceDiff {\n id: string;\n change: \"added\" | \"removed\" | \"changed\" | \"unchanged\";\n findings: Finding[];\n unreadable: UnreadableEntry[];\n /** Directories claiming this id when more than one does, on either side — every finding suspended. */\n ambiguous?: string[];\n}\n\nexport interface FleetDiff {\n services: ServiceDiff[];\n /** True iff any error-severity finding — a removal the fleet still consumes. */\n breaking: boolean;\n /** `unreadable` counts suspended axes plus ambiguous base identities: places nobody could look. */\n summary: { added: number; removed: number; modified: number; deprecated: number; unreadable: number };\n}\n\n/**\n * A side the service does not exist on: absence everywhere, honestly. The id is\n * a key of one of the two sides' maps, each keyed by a directory's leaf name.\n */\nconst ABSENT = { kind: \"absent\" } as const;\nconst emptyState = (id: string): ServiceState => ({ id: rawServiceId(id), dir: \"\", spec: ABSENT, archSpec: ABSENT, openapi: ABSENT, asyncapi: ABSENT });\n\n/**\n * The axes on which an unreadable document the branch left byte-identical is\n * SKIPPED rather than suspended: the two contracts. Identical bytes are a\n * proof, not a guess — the same parser over the same bytes cannot read\n * differently on the two sides, so there is nothing of this document's own\n * to diff, and suspending it anyway made every `loam diff` exit 1 over a\n * fleet that holds one AsyncAPI 2.x file (unreadable by policy since\n * core/asyncapi/read.ts refused pre-3.0), whatever the branch changed.\n *\n * Not the spec axes, and that is the victims scan's doing, not an oversight:\n * an unreadable spec.md or arch.spec.md is also the document ANOTHER\n * service's removal could not be checked against (`core/consumers/consumers.ts`'s\n * `scanRequirements`), and its `unreadable[]` entry here is what carries that\n * suspension to exit 1 (`opsDiff`'s removal branch says so). No scan reads a\n * contract it could not parse as evidence of anything — `producers` takes\n * positive evidence only — so skipping one hides no other answer.\n */\nconst UNTOUCHED_SKIPS: ReadonlySet<UnreadableEntry[\"axis\"]> = new Set([\"openapi\", \"asyncapi\"]);\n\n/**\n * Guard one axis pair: record unreadable sides on the sink and say whether\n * the axis may be compared at all. Reading one good side against a suspended\n * one would grade absence it never proved. A contract unreadable on BOTH\n * sides with one byte hash is the branch's untouched file: not compared and\n * not recorded either (`UNTOUCHED_SKIPS`). A changed one, or one only one\n * side cannot read, still suspends.\n */\nfunction comparable(sink: ServiceDiff, axis: UnreadableEntry[\"axis\"], pair: { base: AxisState<unknown>; current: AxisState<unknown> }): boolean {\n const { base, current } = pair;\n if (UNTOUCHED_SKIPS.has(axis) && base.kind === \"unreadable\" && current.kind === \"unreadable\" &&\n base.bytes !== undefined && base.bytes === current.bytes) return false;\n for (const side of [\"base\", \"current\"] as const) {\n const state = pair[side];\n if (state.kind === \"unreadable\") sink.unreadable.push({ side, axis, path: state.path, error: state.error });\n }\n return pair.base.kind !== \"unreadable\" && pair.current.kind !== \"unreadable\";\n}\n\nconst valueOr = <T>(axis: AxisState<T[]>): T[] => (axis.kind === \"read\" ? axis.value : []);\n\n/** Identity: `Requirement-ID:` when authored, the heading otherwise — the same join `loam rebase` pins against. */\nconst reqKey = (r: Requirement): string => (r.id !== undefined ? `id:${r.id}` : `name:${r.name}`);\nconst reqLabel = (r: Requirement): string => (r.id !== undefined ? `${r.name} [${r.id}]` : r.name);\n\n/** First declaration wins a duplicated key — the same arbitrary-but-stated pick every join on these axes makes. */\nfunction firstWins<T>(items: T[], key: (item: T) => string): Map<string, T> {\n const map = new Map<string, T>();\n for (const item of items) if (!map.has(key(item))) map.set(key(item), item);\n return map;\n}\n\n/** Entry comparator by map key — explicit, because the default sort stringifies whole entries. */\nconst byKey = <T>(a: [string, T], b: [string, T]): number => (a[0] < b[0] ? -1 : 1);\n\nfunction requirementsDiff(sink: ServiceDiff, pair: { base: ServiceState; current: ServiceState }): void {\n // v1 diffs spec.md's requirements only; arch.spec.md is read for the\n // Consumes: join but its requirement inventory is deferred (the two axes\n // are separate namespaces, and diffing both doubles the surface). Both\n // pairs are guarded BEFORE the early return, so a service whose two spec\n // files are both unreadable reports both suspensions, not just the first.\n const specComparable = comparable(sink, \"spec\", { base: pair.base.spec, current: pair.current.spec });\n comparable(sink, \"archSpec\", { base: pair.base.archSpec, current: pair.current.archSpec });\n if (!specComparable) return;\n const base = firstWins(valueOr(pair.base.spec), reqKey);\n const current = firstWins(valueOr(pair.current.spec), reqKey);\n for (const [key, r] of [...current].sort(byKey)) {\n const before = base.get(key);\n if (before === undefined) sink.findings.push(found(\"diff.requirement-added\", `living requirement added since base: '${reqLabel(r)}'`));\n else if (requirementDigest(before) !== requirementDigest(r)) {\n sink.findings.push(found(\"diff.requirement-modified\", `living requirement modified since base: '${reqLabel(r)}'`));\n }\n }\n for (const [key, r] of [...base].sort(byKey)) {\n if (!current.has(key)) sink.findings.push(found(\"diff.requirement-removed\", `living requirement removed since base: '${reqLabel(r)}'`));\n }\n}\n\n/**\n * The second half of every modification message. loam joins consumers to the\n * thing that moved; it does not read what a schema SAYS (core/brief/unchecked.ts\n * lists that as unchecked), so a breaking rename and a new optional field are\n * the same finding here — the specialist diff tells them apart.\n */\nconst notGraded = (tool: string): string =>\n `loam does not grade whether the change is breaking — run ${tool} on the two states of this contract`;\n\nasync function opsDiff(sink: ServiceDiff, pair: { base: ServiceState; current: ServiceState }, victims: ConsumerIndex): Promise<void> {\n if (!comparable(sink, \"openapi\", { base: pair.base.openapi, current: pair.current.openapi })) return;\n const base = firstWins(valueOr(pair.base.openapi), (op) => op.id);\n const current = firstWins(valueOr(pair.current.openapi), (op) => op.id);\n for (const [id, op] of [...current].sort(byKey)) {\n const before = base.get(id);\n if (before === undefined) {\n sink.findings.push(found(\"diff.op-added\", `operation '${id}' added since base (${op.method.toUpperCase()} ${op.path})`));\n } else if (!before.deprecated && op.deprecated) {\n const scan = await victims.opConsumers(sink.id, id);\n sink.findings.push(found(\"diff.op-deprecated\", `operation '${id}' is deprecated since base — ${consumerStance(scan)}`, scanDetails(scan)));\n } else if (before.closureDigest !== op.closureDigest || before.path !== op.path || before.method !== op.method) {\n // `else`, because setting the flag moves the digest by itself (it is a\n // key of the node): a deprecation already names the same consumers, and\n // a second finding over them would say nothing new. The digest covers\n // the `$ref` closure — a field renamed in a shared component is exactly\n // the change this code exists for, and the operation's own bytes never\n // move for it. A relocated slot is a change too, though the node is not.\n const scan = await victims.opConsumers(sink.id, id);\n sink.findings.push(found(\n \"diff.op-modified\",\n `operation '${id}' (${op.method.toUpperCase()} ${op.path}) changed since base, in its own definition or a schema it references — ${consumerStance(scan)}; ${notGraded(\"`oasdiff breaking`\")}`,\n scanDetails(scan),\n ));\n }\n }\n for (const [id] of [...base].sort(byKey)) {\n if (current.has(id)) continue;\n const scan = await victims.opConsumers(sink.id, id);\n if (scan.victims.length > 0) {\n sink.findings.push(found(\"diff.op-removed-consumed\", `operation '${id}' was removed since base and the current fleet still names it — these joins break`, scanDetails(scan)));\n } else if (scan.suspended.length > 0) {\n // \"Nobody could be checked\" is not \"nobody names it\", so this message\n // must not assert a negative the scan never proved. An unreadable\n // consumer document carries the run to exit 1 through its own\n // unreadable[] entry; a caller drawn with no op does not — it stays this\n // warning, so a seeded, op-less map does not fail every removal.\n sink.findings.push(found(\"diff.op-removed\", `operation '${id}' was removed since base; whether the current fleet still names it could NOT be fully answered — ${scan.suspended.length} possible consumer(s) could not be checked`, scanDetails(scan)));\n } else {\n sink.findings.push(found(\"diff.op-removed\", `operation '${id}' was removed since base; no current edge, requirement or use-case hop names it`));\n }\n }\n}\n\nasync function messagesDiff(sink: ServiceDiff, pair: { base: ServiceState; current: ServiceState }, victims: ConsumerIndex): Promise<void> {\n if (!comparable(sink, \"asyncapi\", { base: pair.base.asyncapi, current: pair.current.asyncapi })) return;\n const base = firstWins(valueOr(pair.base.asyncapi), (m) => m.name);\n const current = firstWins(valueOr(pair.current.asyncapi), (m) => m.name);\n for (const [name, message] of [...current].sort(byKey)) {\n const before = base.get(name);\n if (before === undefined) {\n sink.findings.push(found(\"diff.message-added\", `message '${name}' added since base`));\n } else if (before.closureDigest !== message.closureDigest) {\n const scan = await victims.messageConsumers(sink.id, name);\n sink.findings.push(found(\n \"diff.message-modified\",\n `message '${name}' changed since base, in its declaration or a schema its payload references — ${consumerStance(scan)}; ${notGraded(\"`asyncapi diff`\")}`,\n scanDetails(scan),\n ));\n }\n }\n for (const [name] of [...base].sort(byKey)) {\n if (current.has(name)) continue;\n // Fleet-global join: a name another current service still SENDS is not\n // orphaned (positive evidence only — an unreadable contract never vouches,\n // and a service that only receives it is one of its consumers, never its\n // producer: `producers` says why that distinction is the gate's too). Nor\n // is one an #external element still publishes, by validate's own rule\n // (`externalProducer` says why): counting the fleet's senders alone made\n // this removal an error that the next `validate --all` called clean.\n const elsewhere = (await victims.producers(name)).filter((d) => d !== sink.id);\n const outside = await victims.externalProducer(name);\n const senders = outside === null ? elsewhere : [...elsewhere, `${outside} (#external)`];\n if (senders.length > 0) {\n sink.findings.push(found(\"diff.message-removed\", `message '${name}' was removed since base; still sent by ${senders.join(\", \")}`));\n continue;\n }\n const scan = await victims.messageConsumers(sink.id, name);\n if (scan.victims.length > 0) {\n sink.findings.push(found(\"diff.message-removed-consumed\", `message '${name}' was removed since base and the current fleet still consumes it — these joins break`, scanDetails(scan)));\n } else if (scan.suspended.length > 0) {\n sink.findings.push(found(\"diff.message-removed\", `message '${name}' was removed since base; whether anything still consumes it could NOT be fully answered — ${scan.suspended.length} consumer document(s) were not scannable`, scanDetails(scan)));\n } else {\n sink.findings.push(found(\"diff.message-removed\", `message '${name}' was removed since base; nothing currently consumes it`));\n }\n }\n}\n\n/** The graded join changes (`./joins.ts`) as findings on each PROVIDER — the service whose surface the join lands on. */\nfunction consumerFindings(input: { base: BaseFleet; current: CurrentFleet }): Map<string, Finding[]> {\n const changes = consumerJoinChanges({\n base: input.base.services,\n baseAmbiguous: new Set(input.base.ambiguous.keys()),\n current: input.current.services,\n currentAmbiguous: new Set(input.current.ambiguous.keys()),\n });\n const byProvider = new Map<string, Finding[]>();\n for (const { t, change } of changes) {\n const what = t.kind === \"op\" ? `operation '${t.token}'` : `message '${t.token}'`;\n const message = change === \"added\"\n ? `${t.consumer}'s living requirements now name this service's ${what} — a cross-service join appeared since base`\n : `${t.consumer}'s living requirements no longer name this service's ${what} — a cross-service join went away`;\n // The call sits directly in the push — assigned to a `const x = found(…)`\n // it reads as an arrow-function DECLARATION to the stable-code collector,\n // and both consumer codes silently leave the guarded set.\n byProvider.set(t.provider, [\n ...(byProvider.get(t.provider) ?? []),\n found(change === \"added\" ? \"diff.consumer-added\" : \"diff.consumer-removed\", message),\n ]);\n }\n return byProvider;\n}\n\nasync function diffService(unit: { id: string; base?: ServiceState; current?: ServiceState; victims: ConsumerIndex }): Promise<ServiceDiff> {\n const sink: ServiceDiff = { id: unit.id, change: \"unchanged\", findings: [], unreadable: [] };\n if (unit.base === undefined) sink.findings.push(found(\"diff.service-added\", `service '${unit.id}' added since base`));\n if (unit.current === undefined && unit.base !== undefined) {\n sink.findings.push(found(\"diff.service-removed\", `service '${unit.id}' (${unit.base.dir}) is gone from the working tree`));\n }\n const pair = { base: unit.base ?? emptyState(unit.id), current: unit.current ?? emptyState(unit.id) };\n requirementsDiff(sink, pair);\n await opsDiff(sink, pair, unit.victims);\n await messagesDiff(sink, pair, unit.victims);\n return sink;\n}\n\nexport async function computeDiff(input: { base: BaseFleet; current: CurrentFleet; victims: ConsumerIndex }): Promise<FleetDiff> {\n const sides = [input.base.services, input.base.ambiguous, input.current.services, input.current.ambiguous];\n const ids = [...new Set(sides.flatMap((side) => [...side.keys()]))].sort();\n const joins = consumerFindings({ base: input.base, current: input.current });\n const services: ServiceDiff[] = [];\n // Sequential on purpose: the report's order IS the contract (identical\n // states must emit identical bytes), the work per service is in-memory\n // joins, and the one expensive read — the victim index's landscape — is\n // memoised behind its first ask, so a fan-out would buy nothing.\n for (const id of ids) {\n const claimants = [...(input.base.ambiguous.get(id) ?? []), ...(input.current.ambiguous.get(id) ?? [])];\n if (claimants.length > 0) {\n // An id two directories claim — either side — has no single state to\n // diff; the whole subject suspends (containment), and the live walk's\n // `subsystem.name-collision` names the same defect for validate.\n services.push({ id, change: \"changed\", findings: [], unreadable: [], ambiguous: claimants });\n continue;\n }\n const sink = await diffService({ id, base: input.base.services.get(id), current: input.current.services.get(id), victims: input.victims });\n sink.findings.push(...(joins.get(id) ?? []));\n if (input.base.services.has(id) && !input.current.services.has(id)) sink.change = \"removed\";\n else if (!input.base.services.has(id)) sink.change = \"added\";\n else sink.change = sink.findings.length > 0 || sink.unreadable.length > 0 ? \"changed\" : \"unchanged\";\n services.push(sink);\n }\n const all = services.flatMap((s) => s.findings);\n const count = (codes: (f: Finding) => boolean): number => all.filter(codes).length;\n return {\n services,\n breaking: all.some((f) => f.severity === \"error\"),\n summary: {\n added: count((f) => f.code.endsWith(\"-added\")),\n removed: count((f) => f.code.endsWith(\"-removed\") || f.code.endsWith(\"-removed-consumed\")),\n // Requirements, operations and messages alike: a reader scanning the one\n // summary line must not see \"0 modified\" over a PR that renamed a field.\n modified: count((f) => f.code.endsWith(\"-modified\")),\n deprecated: count((f) => f.code === \"diff.op-deprecated\"),\n unreadable:\n services.reduce((n, s) => n + s.unreadable.length, 0) +\n services.filter((s) => s.ambiguous !== undefined).length,\n },\n };\n}\n"]}
package/dist/core/docs.js CHANGED
@@ -11,8 +11,10 @@
11
11
  import { mkdir, writeFile } from "node:fs/promises";
12
12
  import { existsSync } from "node:fs";
13
13
  import { join, resolve } from "node:path";
14
- import { AGENTS_MD } from "./agent.js";
15
- import { AGENTS_FILENAME } from "./repo.js";
14
+ import { AGENTS_MD } from "./agent/agents-md.js";
15
+ import { LANDSCAPE_STUB } from "./scaffold/landscape.js";
16
+ import { README_FILENAME, README_MD } from "./scaffold/readme.js";
17
+ import { AGENTS_FILENAME, LIKEC4_PROJECT_FILENAME, LIKEC4_ROOT_PROJECT } from "./repo/paths.js";
16
18
  /**
17
19
  * Top-level layout of the shared docs repo, and part of its identity rather
18
20
  * than a convenience: `services/` is what makes a directory a docs repo —
@@ -30,100 +32,47 @@ const EMPTY_SUBDIRS = [
30
32
  ["services", ".gitkeep"],
31
33
  ["features", ".gitkeep"],
32
34
  ];
33
- /**
34
- * The fleet map, empty but valid.
35
- *
36
- * Nobody writes this file automatically — `adopt` deliberately does not touch
37
- * it, because who calls whom is a human judgement and a generated landscape
38
- * would be a guess presented as the map. But "nobody writes it" used to mean
39
- * "it is simply absent", and an absent landscape is the one artifact whose
40
- * absence silences the fleet-wide checks entirely: every cross-service breach
41
- * `validate` exists to find is invisible on a repo with no landscape.
42
- *
43
- * So the scaffold lays down the empty map instead: the four element kinds a
44
- * fleet actually uses are declared, the model is empty, and the comments say
45
- * what to add and why. The first `loam adopt` then has somewhere to be drawn.
46
- *
47
- * No `views` block, deliberately. loam reads elements and relationships and
48
- * never a view, so the scaffolded `view index { include * }` was a diagram loam
49
- * planted on every repo and then never drew — and views are the expensive half
50
- * of LikeC4: computing them is superlinear in edge count (120 services / 300
51
- * calls does not finish in three minutes; parsing the same file takes 11 ms).
52
- * loam stopped computing views, so the block is free for loam itself now, but
53
- * scaffolding one still hands the user a fleet-sized bill for the first tool
54
- * that does compute it. Teams who want diagrams declare their own.
55
- */
56
- const LANDSCAPE_STUB = `// The fleet map: every service in services/ appears here, and every call
57
- // between two of them is an edge. This file is written by hand — loam never
58
- // guesses it, because "who calls whom" is the one fact no generator can read
59
- // off a repository.
60
- //
61
- // After \`loam adopt --service <id>\`, add the service here:
62
- //
63
- // paymentService = softwareSystem 'payment-service' {
64
- // description 'Owns payment authorization/capture'
65
- // metadata { service 'payment-service' } // binds the box to services/<id>/
66
- // }
67
- //
68
- // and give each call the operationId it uses, so requirements, C4 and OpenAPI
69
- // can be cross-checked:
70
- //
71
- // checkoutWeb -> paymentService 'Authorizes' {
72
- // metadata { op 'authorizePayment' }
73
- // }
74
- //
75
- // There is no \`views\` block, on purpose: loam reads the model and never a
76
- // view, so it would draw nothing. Add views here if you want diagrams, and
77
- // render them with LikeC4's own tooling — \`npx likec4 start\` from the docs
78
- // repo root, which likec4.config.json scopes to this directory. (A service
79
- // model or a feature delta renders from its OWN directory, e.g.
80
- // \`npx likec4 start services/<id>\`: each declares its own \`specification\`
81
- // block, so the renderer can only be given one of them at a time.) Scope your
82
- // views, because computing one is superlinear in the number of edges and an
83
- // \`include *\` over a whole fleet takes minutes.
84
-
85
- specification {
86
- element person
87
- element softwareSystem
88
- element container
89
- element database
90
- }
91
-
92
- model {
93
- }
94
- `;
95
35
  /**
96
36
  * The LikeC4 project file, and the one thing in the docs repo loam writes for a
97
37
  * tool other than itself.
98
38
  *
99
39
  * LikeC4's workspace loader merges EVERY `.likec4` file under a directory tree
100
- * into one model. loam's layout is the opposite by design: the landscape,
101
- * each `services/<id>/model.likec4` and each `features/<FEAT>/delta.likec4` is
102
- * parsed in isolation (`loadSource`, one file, one throwaway workspace), so
103
- * every one of them legitimately declares its own `specification { … }` block
104
- * and re-declares the elements it needs to talk about. Point the real renderer
105
- * at the repository root and those declarations collide: on loam's own
106
- * `examples/docs` — four files — `npx likec4 start` reported 16 errors, sixteen
107
- * duplicate kinds and names, while `loam validate --all` reported none. Both
108
- * were right; only one of them was reading the tree as a workspace.
40
+ * into one model, and whether that is what loam wants depends on the document.
41
+ * A feature's `features/<FEAT>/delta.likec4` is parsed in isolation and declares
42
+ * its own `specification { … }` block, so merging it into the root would report
43
+ * every declaration as a duplicate — measured on loam's own `examples/docs`:
44
+ * `npx likec4 start` reported 16 errors, sixteen duplicate kinds and names,
45
+ * while `loam validate --all` reported none. Both were right; only one of them
46
+ * was reading the tree as a workspace. That directory is therefore excluded
47
+ * here, permanently.
109
48
  *
110
- * So the root is declared as one LikeC4 project holding the landscape, and the
111
- * two directories whose files are meant to be read alone are excluded from it.
112
- * That makes `npx likec4 start` in the docs repo — the command loam's own docs
113
- * have always recommended — render the fleet map instead of failing. A service
114
- * model or a feature delta is still rendered by pointing the renderer at its own
115
- * directory, which is what parsing them in isolation meant all along.
49
+ * `services/**` is NOT, and that is this file's one substantive change since the
50
+ * axis that let a model EXTEND the fleet map. A model written that way declares
51
+ * no kinds of its own and says what is inside an element the map already draws,
52
+ * so the root project is the only place it parses — and excluding it renders the
53
+ * service as a box with nothing inside. A model that STANDS ALONE still has to
54
+ * be excluded, and `loam subsystem sync` is what adds `services/<tree>/**` for
55
+ * each one and removes the entry again when a model migrates. A fresh repo's
56
+ * models are extending, so the scaffold starts with no `services/` entry at all.
116
57
  *
117
58
  * `**\/node_modules/**` is repeated because naming `exclude` replaces LikeC4's
118
- * default rather than adding to it. loam reads none of this file: it is written
119
- * once, never re-read, and a team that wants a different project layout owns it
120
- * like every other scaffolded file.
59
+ * default rather than adding to it.
60
+ *
61
+ * OWNERSHIP, corrected. This file is still the team's — written once by
62
+ * `loam init --create`, never regenerated, and a team that wants a different
63
+ * project layout keeps it. But loam is no longer blind to it: it reads ONE
64
+ * literal fact out of it (`core/c4/root-project/exclude.ts`, `readRootExclude`
65
+ * — the `exclude` list and nothing else), because that list decides whether an
66
+ * extending model is renderable at all, and it MAINTAINS the `services/` entries
67
+ * in it through `loam subsystem sync`. Every other key, and every entry that is
68
+ * not about `services/`, is left exactly as written. The filename and the root
69
+ * project's name are spelled in `repo/paths.ts`, beside every other file loam
70
+ * writes.
121
71
  */
122
- export const LIKEC4_PROJECT_FILENAME = "likec4.config.json";
123
72
  export const LIKEC4_PROJECT_CONFIG = `${JSON.stringify({
124
- name: "fleet",
73
+ name: LIKEC4_ROOT_PROJECT,
125
74
  title: "Fleet landscape",
126
- exclude: ["**/node_modules/**", "services/**", "features/**"],
75
+ exclude: ["**/node_modules/**", "features/**"],
127
76
  }, null, 2)}\n`;
128
77
  /**
129
78
  * The placeholder that makes an empty scaffolded directory survive a clone.
@@ -183,6 +132,9 @@ export async function scaffoldDocs(docsDir) {
183
132
  export function docsRepoFiles(opts = {}) {
184
133
  const preamble = opts.landscapePreamble === undefined ? "" : `${opts.landscapePreamble.trimEnd()}\n//\n`;
185
134
  return [
135
+ // The one file addressed to a person, first because a forge renders it as
136
+ // the landing page and a reader meets it before anything else here.
137
+ [README_FILENAME, README_MD],
186
138
  // The process contract lives with the docs it describes, so an agent handed
187
139
  // only the docs repo still knows the cycle.
188
140
  [AGENTS_FILENAME, AGENTS_MD],
@@ -1 +1 @@
1
- {"version":3,"file":"docs.js","sourceRoot":"","sources":["../../src/core/docs.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Scaffolding for the shared docs repo.\n *\n * There is deliberately no manifest. `init` used to write a `loam.docs.json`\n * listing the repo's services; nothing ever read it — `repo.ts` enumerates from\n * the filesystem, because files are the source of truth — and nothing ever\n * updated it, so it named an empty fleet forever. A second list of services is\n * exactly the drift `loam validate` now cross-checks the landscape for; the\n * cheapest way to keep it honest is not to have it.\n */\nimport { mkdir, writeFile } from \"node:fs/promises\";\nimport { existsSync } from \"node:fs\";\nimport { join, resolve } from \"node:path\";\nimport { AGENTS_MD } from \"./agent.js\";\nimport { AGENTS_FILENAME } from \"./repo.js\";\n\n/**\n * Top-level layout of the shared docs repo, and part of its identity rather\n * than a convenience: `services/` is what makes a directory a docs repo —\n * `init` will not join one without it, and every enumerating command refuses a\n * `docsDir` that has none. So it is laid down even when nothing is in it yet.\n */\nexport const DOCS_SUBDIRS = [\"architecture\", \"services\", \"features\"] as const;\n\n/**\n * The scaffolded directories that start out empty, and the file that keeps each\n * of them in version control. See {@link GITKEEP}. Spelled as pairs so the\n * marker's name is written once — `listServices` and `listFeatures` enumerate\n * subdirectories only, so a file here is invisible to both.\n */\nconst EMPTY_SUBDIRS = [\n [\"services\", \".gitkeep\"],\n [\"features\", \".gitkeep\"],\n] as const;\n\n/**\n * The fleet map, empty but valid.\n *\n * Nobody writes this file automatically — `adopt` deliberately does not touch\n * it, because who calls whom is a human judgement and a generated landscape\n * would be a guess presented as the map. But \"nobody writes it\" used to mean\n * \"it is simply absent\", and an absent landscape is the one artifact whose\n * absence silences the fleet-wide checks entirely: every cross-service breach\n * `validate` exists to find is invisible on a repo with no landscape.\n *\n * So the scaffold lays down the empty map instead: the four element kinds a\n * fleet actually uses are declared, the model is empty, and the comments say\n * what to add and why. The first `loam adopt` then has somewhere to be drawn.\n *\n * No `views` block, deliberately. loam reads elements and relationships and\n * never a view, so the scaffolded `view index { include * }` was a diagram loam\n * planted on every repo and then never drew — and views are the expensive half\n * of LikeC4: computing them is superlinear in edge count (120 services / 300\n * calls does not finish in three minutes; parsing the same file takes 11 ms).\n * loam stopped computing views, so the block is free for loam itself now, but\n * scaffolding one still hands the user a fleet-sized bill for the first tool\n * that does compute it. Teams who want diagrams declare their own.\n */\nconst LANDSCAPE_STUB = `// The fleet map: every service in services/ appears here, and every call\n// between two of them is an edge. This file is written by hand — loam never\n// guesses it, because \"who calls whom\" is the one fact no generator can read\n// off a repository.\n//\n// After \\`loam adopt --service <id>\\`, add the service here:\n//\n// paymentService = softwareSystem 'payment-service' {\n// description 'Owns payment authorization/capture'\n// metadata { service 'payment-service' } // binds the box to services/<id>/\n// }\n//\n// and give each call the operationId it uses, so requirements, C4 and OpenAPI\n// can be cross-checked:\n//\n// checkoutWeb -> paymentService 'Authorizes' {\n// metadata { op 'authorizePayment' }\n// }\n//\n// There is no \\`views\\` block, on purpose: loam reads the model and never a\n// view, so it would draw nothing. Add views here if you want diagrams, and\n// render them with LikeC4's own tooling — \\`npx likec4 start\\` from the docs\n// repo root, which likec4.config.json scopes to this directory. (A service\n// model or a feature delta renders from its OWN directory, e.g.\n// \\`npx likec4 start services/<id>\\`: each declares its own \\`specification\\`\n// block, so the renderer can only be given one of them at a time.) Scope your\n// views, because computing one is superlinear in the number of edges and an\n// \\`include *\\` over a whole fleet takes minutes.\n\nspecification {\n element person\n element softwareSystem\n element container\n element database\n}\n\nmodel {\n}\n`;\n\n/**\n * The LikeC4 project file, and the one thing in the docs repo loam writes for a\n * tool other than itself.\n *\n * LikeC4's workspace loader merges EVERY `.likec4` file under a directory tree\n * into one model. loam's layout is the opposite by design: the landscape,\n * each `services/<id>/model.likec4` and each `features/<FEAT>/delta.likec4` is\n * parsed in isolation (`loadSource`, one file, one throwaway workspace), so\n * every one of them legitimately declares its own `specification { … }` block\n * and re-declares the elements it needs to talk about. Point the real renderer\n * at the repository root and those declarations collide: on loam's own\n * `examples/docs` — four files — `npx likec4 start` reported 16 errors, sixteen\n * duplicate kinds and names, while `loam validate --all` reported none. Both\n * were right; only one of them was reading the tree as a workspace.\n *\n * So the root is declared as one LikeC4 project holding the landscape, and the\n * two directories whose files are meant to be read alone are excluded from it.\n * That makes `npx likec4 start` in the docs repo — the command loam's own docs\n * have always recommended — render the fleet map instead of failing. A service\n * model or a feature delta is still rendered by pointing the renderer at its own\n * directory, which is what parsing them in isolation meant all along.\n *\n * `**\\/node_modules/**` is repeated because naming `exclude` replaces LikeC4's\n * default rather than adding to it. loam reads none of this file: it is written\n * once, never re-read, and a team that wants a different project layout owns it\n * like every other scaffolded file.\n */\nexport const LIKEC4_PROJECT_FILENAME = \"likec4.config.json\";\n\nexport const LIKEC4_PROJECT_CONFIG = `${JSON.stringify(\n {\n name: \"fleet\",\n title: \"Fleet landscape\",\n exclude: [\"**/node_modules/**\", \"services/**\", \"features/**\"],\n },\n null,\n 2,\n)}\\n`;\n\n/**\n * The placeholder that makes an empty scaffolded directory survive a clone.\n *\n * git tracks files, not directories, so `services/` and `features/` — created\n * empty by `loam init --create` — were absent for everyone after the first push:\n * the person who ran init had a green repo, and the second person to clone it\n * got `doctor.services-missing`, a BLOCKER, on a repository nobody had touched.\n * A repo that cannot survive being cloned is not a shared docs repo.\n */\nconst GITKEEP = \"\";\n\n/**\n * The docs repo's own loam.json. It makes the docs repo self-describing: a\n * command run from inside it (or from any directory under it) finds this file\n * first and resolves the fleet to the repo it is standing in, instead of\n * walking out to whatever service repo happens to be above.\n *\n * `\".\"` and not an absolute path for the same reason every other docsDir is\n * stored as written: this file is committed and cloned to machines whose\n * directory layout nobody here can predict.\n */\nconst DOCS_SELF_CONFIG = `${JSON.stringify({ docsDir: \".\" }, null, 2)}\\n`;\n\nexport interface ScaffoldResult {\n root: string;\n created: string[];\n}\n\n/** Idempotently create the docs-repo skeleton. Existing files/dirs are left untouched. */\nexport async function scaffoldDocs(docsDir: string): Promise<ScaffoldResult> {\n const root = resolve(docsDir);\n const created: string[] = [];\n\n await mkdir(root, { recursive: true });\n\n for (const dir of DOCS_SUBDIRS) {\n const p = join(root, dir);\n if (!existsSync(p)) {\n await mkdir(p, { recursive: true });\n created.push(p);\n }\n }\n\n // Never overwritten, all three of them — a team's own house rules, their own\n // map and their own config outrank the template. The order here IS the order\n // `init` probes for what it will skip; keep the two lists in step.\n for (const [rel, content] of docsRepoFiles()) {\n const path = join(root, rel);\n if (!existsSync(path)) {\n await writeFile(path, content, \"utf8\");\n created.push(path);\n }\n }\n\n return { root, created };\n}\n\nexport interface DocsRepoFileOptions {\n /**\n * Comment lines prepended to the landscape stub, for a scaffold with a reason\n * of its own to hand over an empty map — `migrate-openspec` stages a docs repo\n * out of a corpus that HAS no topology, and says so where the migrator reads.\n *\n * A parameter and not a second template on purpose. The rest of the stub —\n * how to declare a service, how to bind an edge to an operationId, why there\n * is no `views` block — is the same advice however the repo came to exist, and\n * the migration used to carry its own shorter copy of it: two files that were\n * both correct on the day they were written and could only diverge after.\n */\n landscapePreamble?: string;\n}\n\n/**\n * The files every docs repo starts with, relative to its root, in creation\n * order. `init` scaffolds them directly; `migrate-openspec` stages the same\n * bytes into its target, because the whole point of migrating into a docs repo\n * is that it be the docs repo `loam init` makes.\n *\n * Exported as paths only (via `plannedDocsFiles`) where `init` reports what it\n * will skip — a duplicate list is exactly the drift that made `created +\n * skipped` disagree with reality.\n */\nexport function docsRepoFiles(opts: DocsRepoFileOptions = {}): Array<[string, string]> {\n const preamble = opts.landscapePreamble === undefined ? \"\" : `${opts.landscapePreamble.trimEnd()}\\n//\\n`;\n return [\n // The process contract lives with the docs it describes, so an agent handed\n // only the docs repo still knows the cycle.\n [AGENTS_FILENAME, AGENTS_MD],\n [join(\"architecture\", \"landscape.likec4\"), `${preamble}${LANDSCAPE_STUB}`],\n [\"loam.json\", DOCS_SELF_CONFIG],\n [LIKEC4_PROJECT_FILENAME, LIKEC4_PROJECT_CONFIG],\n // The two directories git would otherwise drop on the way to the next\n // clone. `architecture/` needs none — the landscape above is in it.\n ...EMPTY_SUBDIRS.map(([dir, keep]) => [join(dir, keep), GITKEEP] as [string, string]),\n ];\n}\n\n/** Everything `scaffoldDocs(docsDir)` would create, in the order it creates it. */\nexport function plannedDocsFiles(docsDir: string): string[] {\n const root = resolve(docsDir);\n return [\n ...DOCS_SUBDIRS.map((d) => join(root, d)),\n ...docsRepoFiles().map(([rel]) => join(root, rel)),\n ];\n}\n"]}
1
+ {"version":3,"file":"docs.js","sourceRoot":"","sources":["../../src/core/docs.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Scaffolding for the shared docs repo.\n *\n * There is deliberately no manifest. `init` used to write a `loam.docs.json`\n * listing the repo's services; nothing ever read it — `repo.ts` enumerates from\n * the filesystem, because files are the source of truth — and nothing ever\n * updated it, so it named an empty fleet forever. A second list of services is\n * exactly the drift `loam validate` now cross-checks the landscape for; the\n * cheapest way to keep it honest is not to have it.\n */\nimport { mkdir, writeFile } from \"node:fs/promises\";\nimport { existsSync } from \"node:fs\";\nimport { join, resolve } from \"node:path\";\nimport { AGENTS_MD } from \"./agent/agents-md.js\";\nimport { LANDSCAPE_STUB } from \"./scaffold/landscape.js\";\nimport { README_FILENAME, README_MD } from \"./scaffold/readme.js\";\nimport { AGENTS_FILENAME, LIKEC4_PROJECT_FILENAME, LIKEC4_ROOT_PROJECT } from \"./repo/paths.js\";\n\n/**\n * Top-level layout of the shared docs repo, and part of its identity rather\n * than a convenience: `services/` is what makes a directory a docs repo —\n * `init` will not join one without it, and every enumerating command refuses a\n * `docsDir` that has none. So it is laid down even when nothing is in it yet.\n */\nexport const DOCS_SUBDIRS = [\"architecture\", \"services\", \"features\"] as const;\n\n/**\n * The scaffolded directories that start out empty, and the file that keeps each\n * of them in version control. See {@link GITKEEP}. Spelled as pairs so the\n * marker's name is written once — `listServices` and `listFeatures` enumerate\n * subdirectories only, so a file here is invisible to both.\n */\nconst EMPTY_SUBDIRS = [\n [\"services\", \".gitkeep\"],\n [\"features\", \".gitkeep\"],\n] as const;\n\n/**\n * The LikeC4 project file, and the one thing in the docs repo loam writes for a\n * tool other than itself.\n *\n * LikeC4's workspace loader merges EVERY `.likec4` file under a directory tree\n * into one model, and whether that is what loam wants depends on the document.\n * A feature's `features/<FEAT>/delta.likec4` is parsed in isolation and declares\n * its own `specification { … }` block, so merging it into the root would report\n * every declaration as a duplicate — measured on loam's own `examples/docs`:\n * `npx likec4 start` reported 16 errors, sixteen duplicate kinds and names,\n * while `loam validate --all` reported none. Both were right; only one of them\n * was reading the tree as a workspace. That directory is therefore excluded\n * here, permanently.\n *\n * `services/**` is NOT, and that is this file's one substantive change since the\n * axis that let a model EXTEND the fleet map. A model written that way declares\n * no kinds of its own and says what is inside an element the map already draws,\n * so the root project is the only place it parses — and excluding it renders the\n * service as a box with nothing inside. A model that STANDS ALONE still has to\n * be excluded, and `loam subsystem sync` is what adds `services/<tree>/**` for\n * each one and removes the entry again when a model migrates. A fresh repo's\n * models are extending, so the scaffold starts with no `services/` entry at all.\n *\n * `**\\/node_modules/**` is repeated because naming `exclude` replaces LikeC4's\n * default rather than adding to it.\n *\n * OWNERSHIP, corrected. This file is still the team's — written once by\n * `loam init --create`, never regenerated, and a team that wants a different\n * project layout keeps it. But loam is no longer blind to it: it reads ONE\n * literal fact out of it (`core/c4/root-project/exclude.ts`, `readRootExclude`\n * — the `exclude` list and nothing else), because that list decides whether an\n * extending model is renderable at all, and it MAINTAINS the `services/` entries\n * in it through `loam subsystem sync`. Every other key, and every entry that is\n * not about `services/`, is left exactly as written. The filename and the root\n * project's name are spelled in `repo/paths.ts`, beside every other file loam\n * writes.\n */\nexport const LIKEC4_PROJECT_CONFIG = `${JSON.stringify(\n {\n name: LIKEC4_ROOT_PROJECT,\n title: \"Fleet landscape\",\n exclude: [\"**/node_modules/**\", \"features/**\"],\n },\n null,\n 2,\n)}\\n`;\n\n/**\n * The placeholder that makes an empty scaffolded directory survive a clone.\n *\n * git tracks files, not directories, so `services/` and `features/` — created\n * empty by `loam init --create` — were absent for everyone after the first push:\n * the person who ran init had a green repo, and the second person to clone it\n * got `doctor.services-missing`, a BLOCKER, on a repository nobody had touched.\n * A repo that cannot survive being cloned is not a shared docs repo.\n */\nconst GITKEEP = \"\";\n\n/**\n * The docs repo's own loam.json. It makes the docs repo self-describing: a\n * command run from inside it (or from any directory under it) finds this file\n * first and resolves the fleet to the repo it is standing in, instead of\n * walking out to whatever service repo happens to be above.\n *\n * `\".\"` and not an absolute path for the same reason every other docsDir is\n * stored as written: this file is committed and cloned to machines whose\n * directory layout nobody here can predict.\n */\nconst DOCS_SELF_CONFIG = `${JSON.stringify({ docsDir: \".\" }, null, 2)}\\n`;\n\nexport interface ScaffoldResult {\n root: string;\n created: string[];\n}\n\n/** Idempotently create the docs-repo skeleton. Existing files/dirs are left untouched. */\nexport async function scaffoldDocs(docsDir: string): Promise<ScaffoldResult> {\n const root = resolve(docsDir);\n const created: string[] = [];\n\n await mkdir(root, { recursive: true });\n\n for (const dir of DOCS_SUBDIRS) {\n const p = join(root, dir);\n if (!existsSync(p)) {\n await mkdir(p, { recursive: true });\n created.push(p);\n }\n }\n\n // Never overwritten, all three of them — a team's own house rules, their own\n // map and their own config outrank the template. The order here IS the order\n // `init` probes for what it will skip; keep the two lists in step.\n for (const [rel, content] of docsRepoFiles()) {\n const path = join(root, rel);\n if (!existsSync(path)) {\n await writeFile(path, content, \"utf8\");\n created.push(path);\n }\n }\n\n return { root, created };\n}\n\nexport interface DocsRepoFileOptions {\n /**\n * Comment lines prepended to the landscape stub, for a scaffold with a reason\n * of its own to hand over an empty map — `migrate-openspec` stages a docs repo\n * out of a corpus that HAS no topology, and says so where the migrator reads.\n *\n * A parameter and not a second template on purpose. The rest of the stub —\n * how to declare a service, how to bind an edge to an operationId, why there\n * is no `views` block — is the same advice however the repo came to exist, and\n * the migration used to carry its own shorter copy of it: two files that were\n * both correct on the day they were written and could only diverge after.\n */\n landscapePreamble?: string;\n}\n\n/**\n * The files every docs repo starts with, relative to its root, in creation\n * order. `init` scaffolds them directly; `migrate-openspec` stages the same\n * bytes into its target, because the whole point of migrating into a docs repo\n * is that it be the docs repo `loam init` makes.\n *\n * Exported as paths only (via `plannedDocsFiles`) where `init` reports what it\n * will skip — a duplicate list is exactly the drift that made `created +\n * skipped` disagree with reality.\n */\nexport function docsRepoFiles(opts: DocsRepoFileOptions = {}): Array<[string, string]> {\n const preamble = opts.landscapePreamble === undefined ? \"\" : `${opts.landscapePreamble.trimEnd()}\\n//\\n`;\n return [\n // The one file addressed to a person, first because a forge renders it as\n // the landing page and a reader meets it before anything else here.\n [README_FILENAME, README_MD],\n // The process contract lives with the docs it describes, so an agent handed\n // only the docs repo still knows the cycle.\n [AGENTS_FILENAME, AGENTS_MD],\n [join(\"architecture\", \"landscape.likec4\"), `${preamble}${LANDSCAPE_STUB}`],\n [\"loam.json\", DOCS_SELF_CONFIG],\n [LIKEC4_PROJECT_FILENAME, LIKEC4_PROJECT_CONFIG],\n // The two directories git would otherwise drop on the way to the next\n // clone. `architecture/` needs none — the landscape above is in it.\n ...EMPTY_SUBDIRS.map(([dir, keep]) => [join(dir, keep), GITKEEP] as [string, string]),\n ];\n}\n\n/** Everything `scaffoldDocs(docsDir)` would create, in the order it creates it. */\nexport function plannedDocsFiles(docsDir: string): string[] {\n const root = resolve(docsDir);\n return [\n ...DOCS_SUBDIRS.map((d) => join(root, d)),\n ...docsRepoFiles().map(([rel]) => join(root, rel)),\n ];\n}\n"]}