@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,61 @@
1
+ /**
2
+ * Name resolution over a walked tree — the questions every `loam subsystem`
3
+ * verb asks before it acts: what does this name denote, what sits beneath a
4
+ * subsystem, and which names come close to a miss. One module so `move`,
5
+ * `rm`, `new` and `history` cannot grow four private spellings of "the flat
6
+ * namespace" — the walk already enforces one namespace, and resolution must
7
+ * read it the same way.
8
+ */
9
+ import { closeIds } from "../../c4/arch.js";
10
+ /**
11
+ * Resolve one name against the flat namespace. Services win a tie on
12
+ * purpose: a tie IS `subsystem.name-collision`, already an error finding,
13
+ * and while it stands the service reading keeps every id-addressed command
14
+ * coherent.
15
+ */
16
+ export function findInTree(tree, name) {
17
+ const service = tree.services.find((s) => s.id === name);
18
+ if (service !== undefined)
19
+ return { kind: "service", service };
20
+ const subsystem = tree.subsystems.find((s) => s.name === name);
21
+ if (subsystem !== undefined)
22
+ return { kind: "subsystem", subsystem };
23
+ return null;
24
+ }
25
+ /** Every name the flat namespace holds — service ids and subsystem names together. */
26
+ export function treeNames(tree) {
27
+ return [...tree.services.map((s) => s.id), ...tree.subsystems.map((s) => s.name)];
28
+ }
29
+ /**
30
+ * The near-miss tail a refusal appends to its "no such name" sentence, over
31
+ * whichever pool the verb resolves against: the close names when there are
32
+ * any, else `otherwise` — the verb's own pointer at what exists, or "" for
33
+ * none. Eight refusals across `subsystem`, `adopt --subsystem` and
34
+ * `list --subsystem` end this way, and each spelled the conditional itself;
35
+ * the lead sentence and the fallback stay theirs, because those are what
36
+ * differ.
37
+ */
38
+ export function closeNamesHint(name, pool, otherwise) {
39
+ const close = closeIds(name, pool);
40
+ return close.length > 0 ? ` Close names: ${close.join(", ")}.` : otherwise;
41
+ }
42
+ /**
43
+ * Does the subsystem at `subPath` contain `path` — itself, or anywhere beneath
44
+ * it? The move-into-own-subtree refusal. The parameter is the name chain, not
45
+ * a `SubsystemEntry`, because a chain is all this comparison reads — the one
46
+ * caller outside this module (`move`) has a chain it just composed and no
47
+ * entry to hand, and a structural parameter it never reads would force a
48
+ * placeholder there.
49
+ */
50
+ export function withinSubsystem(subPath, path) {
51
+ return subPath.length <= path.length && subPath.every((name, i) => path[i] === name);
52
+ }
53
+ /** Services anywhere beneath a subsystem — the transitive membership the views and counts share. */
54
+ export function servicesUnder(tree, sub) {
55
+ return tree.services.filter((s) => sub.path.every((name, i) => s.subsystem[i] === name));
56
+ }
57
+ /** Child subsystems anywhere beneath one — `rm`'s other half of "empty". */
58
+ export function subsystemsUnder(tree, sub) {
59
+ return tree.subsystems.filter((c) => c !== sub && withinSubsystem(sub.path, c.path));
60
+ }
61
+ //# sourceMappingURL=find.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"find.js","sourceRoot":"","sources":["../../../../src/core/repo/tree/find.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAS5C;;;;;GAKG;AACH,MAAM,UAAU,UAAU,CAAC,IAAe,EAAE,IAAY;IACtD,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,CAAC;IACzD,IAAI,OAAO,KAAK,SAAS;QAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC;IAC/D,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;IAC/D,IAAI,SAAS,KAAK,SAAS;QAAE,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,SAAS,EAAE,CAAC;IACrE,OAAO,IAAI,CAAC;AACd,CAAC;AAED,sFAAsF;AACtF,MAAM,UAAU,SAAS,CAAC,IAAe;IACvC,OAAO,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AACpF,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,cAAc,CAAC,IAAY,EAAE,IAAc,EAAE,SAAiB;IAC5E,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACnC,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,iBAAiB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC;AAC7E,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,eAAe,CAAC,OAAiB,EAAE,IAAc;IAC/D,OAAO,OAAO,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,IAAI,OAAO,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC;AACvF,CAAC;AAED,oGAAoG;AACpG,MAAM,UAAU,aAAa,CAAC,IAAe,EAAE,GAAmB;IAChE,OAAO,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC;AAC3F,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,eAAe,CAAC,IAAe,EAAE,GAAmB;IAClE,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,GAAG,IAAI,eAAe,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AACvF,CAAC","sourcesContent":["/**\n * Name resolution over a walked tree — the questions every `loam subsystem`\n * verb asks before it acts: what does this name denote, what sits beneath a\n * subsystem, and which names come close to a miss. One module so `move`,\n * `rm`, `new` and `history` cannot grow four private spellings of \"the flat\n * namespace\" — the walk already enforces one namespace, and resolution must\n * read it the same way.\n */\nimport { closeIds } from \"../../c4/arch.js\";\nimport type { FleetTree, SubsystemEntry, WalkedService } from \"./walk.js\";\n\n/** What a name denotes in the tree — a service, a subsystem, or nothing. */\nexport type TreeHit =\n | { kind: \"service\"; service: WalkedService }\n | { kind: \"subsystem\"; subsystem: SubsystemEntry }\n | null;\n\n/**\n * Resolve one name against the flat namespace. Services win a tie on\n * purpose: a tie IS `subsystem.name-collision`, already an error finding,\n * and while it stands the service reading keeps every id-addressed command\n * coherent.\n */\nexport function findInTree(tree: FleetTree, name: string): TreeHit {\n const service = tree.services.find((s) => s.id === name);\n if (service !== undefined) return { kind: \"service\", service };\n const subsystem = tree.subsystems.find((s) => s.name === name);\n if (subsystem !== undefined) return { kind: \"subsystem\", subsystem };\n return null;\n}\n\n/** Every name the flat namespace holds — service ids and subsystem names together. */\nexport function treeNames(tree: FleetTree): string[] {\n return [...tree.services.map((s) => s.id), ...tree.subsystems.map((s) => s.name)];\n}\n\n/**\n * The near-miss tail a refusal appends to its \"no such name\" sentence, over\n * whichever pool the verb resolves against: the close names when there are\n * any, else `otherwise` — the verb's own pointer at what exists, or \"\" for\n * none. Eight refusals across `subsystem`, `adopt --subsystem` and\n * `list --subsystem` end this way, and each spelled the conditional itself;\n * the lead sentence and the fallback stay theirs, because those are what\n * differ.\n */\nexport function closeNamesHint(name: string, pool: string[], otherwise: string): string {\n const close = closeIds(name, pool);\n return close.length > 0 ? ` Close names: ${close.join(\", \")}.` : otherwise;\n}\n\n/**\n * Does the subsystem at `subPath` contain `path` — itself, or anywhere beneath\n * it? The move-into-own-subtree refusal. The parameter is the name chain, not\n * a `SubsystemEntry`, because a chain is all this comparison reads — the one\n * caller outside this module (`move`) has a chain it just composed and no\n * entry to hand, and a structural parameter it never reads would force a\n * placeholder there.\n */\nexport function withinSubsystem(subPath: string[], path: string[]): boolean {\n return subPath.length <= path.length && subPath.every((name, i) => path[i] === name);\n}\n\n/** Services anywhere beneath a subsystem — the transitive membership the views and counts share. */\nexport function servicesUnder(tree: FleetTree, sub: SubsystemEntry): WalkedService[] {\n return tree.services.filter((s) => sub.path.every((name, i) => s.subsystem[i] === name));\n}\n\n/** Child subsystems anywhere beneath one — `rm`'s other half of \"empty\". */\nexport function subsystemsUnder(tree: FleetTree, sub: SubsystemEntry): SubsystemEntry[] {\n return tree.subsystems.filter((c) => c !== sub && withinSubsystem(sub.path, c.path));\n}\n"]}
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Directory-entry questions the enumerations share, symlinks followed.
3
+ *
4
+ * Moved here from `repo/repo.ts` when the tree walk arrived: the walk and the
5
+ * feature enumeration must answer "what IS this entry" identically, and the
6
+ * package direction is `repo → repo/tree` (never back — `walk.ts` says why),
7
+ * so the shared spelling lives on this side of the edge.
8
+ */
9
+ import { existsSync, realpathSync, statSync } from "node:fs";
10
+ import { readdir } from "node:fs/promises";
11
+ import { join } from "node:path";
12
+ /**
13
+ * What a directory entry IS, following a symlink to find out.
14
+ *
15
+ * `readdir(withFileTypes)` does not follow symlinks: for a symlink `Dirent`
16
+ * every `isDirectory()`/`isFile()` is false, whatever it points at. That made a
17
+ * symlinked `services/<id>/` or `features/<id>/` vanish from every enumeration
18
+ * at once — `list`, `validate --all`, the fleet gate — with no diagnostic
19
+ * anywhere, which is the one outcome a shared docs repo cannot survive: the
20
+ * fleet gate reported a service that is not there as fine because it never saw
21
+ * it. Composing a docs repo out of symlinks (a worktree, a submodule, one
22
+ * service's directory shared between two checkouts) is legitimate, so they are
23
+ * FOLLOWED rather than refused. A dangling link stats as nothing and is skipped
24
+ * exactly as an absent directory is — it is not a service, and saying so would
25
+ * mean inventing an entry to hang the complaint on.
26
+ */
27
+ export function entryIs(dir, e, want) {
28
+ if (!e.isSymbolicLink())
29
+ return want === "dir" ? e.isDirectory() : e.isFile();
30
+ try {
31
+ const s = statSync(join(dir, e.name));
32
+ return want === "dir" ? s.isDirectory() : s.isFile();
33
+ }
34
+ catch {
35
+ return false;
36
+ }
37
+ }
38
+ /**
39
+ * Markdown files sitting directly in `dir`, sorted, as full paths — the ADR
40
+ * corpus, and the only place that rule is spelled. Symlinks are resolved
41
+ * through `entryIs`, which is the whole reason this is shared: `show` once kept
42
+ * a second copy that tested `Dirent.isFile()` itself — always false for a
43
+ * symlink, whatever it points at — so a docs repo composed of symlinks (the
44
+ * layout `entryIs` above exists to support) had `loam list` and `loam show`
45
+ * reporting different ADR counts for the same service. One rule, one answer.
46
+ *
47
+ * The list, not the count, is the primitive: the link check reads these same
48
+ * files, and a corpus that disagreed with the count would grade documents the
49
+ * fleet listing says are not there.
50
+ */
51
+ export async function markdownFiles(dir) {
52
+ if (!existsSync(dir))
53
+ return [];
54
+ const entries = await readdir(dir, { withFileTypes: true });
55
+ return entries
56
+ .filter((e) => e.name.endsWith(".md") && entryIs(dir, e, "file"))
57
+ .map((e) => join(dir, e.name))
58
+ .sort();
59
+ }
60
+ /** How many markdown files sit directly in `dir` — the ADR count, over the corpus above. */
61
+ export async function countMarkdown(dir) {
62
+ return (await markdownFiles(dir)).length;
63
+ }
64
+ /**
65
+ * Mark a directory as descended-into; false when it (or another name for it)
66
+ * already was. The symlink-cycle guard every walk that follows links through
67
+ * `entryIs` carries — the service tree (`./walk.ts`), the capability tree, the
68
+ * glossary, the generated-gherkin scan — and for one reason: a followed cycle
69
+ * without a visited set recurses until the stack ends. A path realpath cannot
70
+ * resolve is one whose children cannot be read either, so it is never entered.
71
+ */
72
+ export function markDescended(dir, visited) {
73
+ let real;
74
+ try {
75
+ real = realpathSync(dir);
76
+ }
77
+ catch {
78
+ return false;
79
+ }
80
+ if (visited.has(real))
81
+ return false;
82
+ visited.add(real);
83
+ return true;
84
+ }
85
+ /** Sorted non-dot subdirectory names, links followed — a tree walk's deterministic child order. */
86
+ export async function subdirNames(dir) {
87
+ const entries = await readdir(dir, { withFileTypes: true });
88
+ return entries.filter((e) => !e.name.startsWith(".") && entryIs(dir, e, "dir")).map((e) => e.name).sort();
89
+ }
90
+ //# sourceMappingURL=fs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fs.js","sourceRoot":"","sources":["../../../../src/core/repo/tree/fs.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,QAAQ,EAAe,MAAM,SAAS,CAAC;AAC1E,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAC3C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,OAAO,CAAC,GAAW,EAAE,CAAS,EAAE,IAAoB;IAClE,IAAI,CAAC,CAAC,CAAC,cAAc,EAAE;QAAE,OAAO,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;IAC9E,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QACtC,OAAO,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;IACvD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,GAAW;IAC7C,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,EAAE,CAAC;IAChC,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5D,OAAO,OAAO;SACX,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC;SAChE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;SAC7B,IAAI,EAAE,CAAC;AACZ,CAAC;AAED,4FAA4F;AAC5F,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,GAAW;IAC7C,OAAO,CAAC,MAAM,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC;AAC3C,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,aAAa,CAAC,GAAW,EAAE,OAAoB;IAC7D,IAAI,IAAY,CAAC;IACjB,IAAI,CAAC;QACH,IAAI,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IACpC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAClB,OAAO,IAAI,CAAC;AACd,CAAC;AAED,mGAAmG;AACnG,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,GAAW;IAC3C,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5D,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;AAC5G,CAAC","sourcesContent":["/**\n * Directory-entry questions the enumerations share, symlinks followed.\n *\n * Moved here from `repo/repo.ts` when the tree walk arrived: the walk and the\n * feature enumeration must answer \"what IS this entry\" identically, and the\n * package direction is `repo → repo/tree` (never back — `walk.ts` says why),\n * so the shared spelling lives on this side of the edge.\n */\nimport { existsSync, realpathSync, statSync, type Dirent } from \"node:fs\";\nimport { readdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\n/**\n * What a directory entry IS, following a symlink to find out.\n *\n * `readdir(withFileTypes)` does not follow symlinks: for a symlink `Dirent`\n * every `isDirectory()`/`isFile()` is false, whatever it points at. That made a\n * symlinked `services/<id>/` or `features/<id>/` vanish from every enumeration\n * at once — `list`, `validate --all`, the fleet gate — with no diagnostic\n * anywhere, which is the one outcome a shared docs repo cannot survive: the\n * fleet gate reported a service that is not there as fine because it never saw\n * it. Composing a docs repo out of symlinks (a worktree, a submodule, one\n * service's directory shared between two checkouts) is legitimate, so they are\n * FOLLOWED rather than refused. A dangling link stats as nothing and is skipped\n * exactly as an absent directory is — it is not a service, and saying so would\n * mean inventing an entry to hang the complaint on.\n */\nexport function entryIs(dir: string, e: Dirent, want: \"dir\" | \"file\"): boolean {\n if (!e.isSymbolicLink()) return want === \"dir\" ? e.isDirectory() : e.isFile();\n try {\n const s = statSync(join(dir, e.name));\n return want === \"dir\" ? s.isDirectory() : s.isFile();\n } catch {\n return false;\n }\n}\n\n/**\n * Markdown files sitting directly in `dir`, sorted, as full paths — the ADR\n * corpus, and the only place that rule is spelled. Symlinks are resolved\n * through `entryIs`, which is the whole reason this is shared: `show` once kept\n * a second copy that tested `Dirent.isFile()` itself — always false for a\n * symlink, whatever it points at — so a docs repo composed of symlinks (the\n * layout `entryIs` above exists to support) had `loam list` and `loam show`\n * reporting different ADR counts for the same service. One rule, one answer.\n *\n * The list, not the count, is the primitive: the link check reads these same\n * files, and a corpus that disagreed with the count would grade documents the\n * fleet listing says are not there.\n */\nexport async function markdownFiles(dir: string): Promise<string[]> {\n if (!existsSync(dir)) return [];\n const entries = await readdir(dir, { withFileTypes: true });\n return entries\n .filter((e) => e.name.endsWith(\".md\") && entryIs(dir, e, \"file\"))\n .map((e) => join(dir, e.name))\n .sort();\n}\n\n/** How many markdown files sit directly in `dir` — the ADR count, over the corpus above. */\nexport async function countMarkdown(dir: string): Promise<number> {\n return (await markdownFiles(dir)).length;\n}\n\n/**\n * Mark a directory as descended-into; false when it (or another name for it)\n * already was. The symlink-cycle guard every walk that follows links through\n * `entryIs` carries — the service tree (`./walk.ts`), the capability tree, the\n * glossary, the generated-gherkin scan — and for one reason: a followed cycle\n * without a visited set recurses until the stack ends. A path realpath cannot\n * resolve is one whose children cannot be read either, so it is never entered.\n */\nexport function markDescended(dir: string, visited: Set<string>): boolean {\n let real: string;\n try {\n real = realpathSync(dir);\n } catch {\n return false;\n }\n if (visited.has(real)) return false;\n visited.add(real);\n return true;\n}\n\n/** Sorted non-dot subdirectory names, links followed — a tree walk's deterministic child order. */\nexport async function subdirNames(dir: string): Promise<string[]> {\n const entries = await readdir(dir, { withFileTypes: true });\n return entries.filter((e) => !e.name.startsWith(\".\") && entryIs(dir, e, \"dir\")).map((e) => e.name).sort();\n}\n"]}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * The subsystem marker: `subsystem.yaml`, the one file that makes a directory
3
+ * under `services/` a GROUP rather than a service.
4
+ *
5
+ * Presence classifies; content is metadata. The walk decides what a directory
6
+ * IS from the marker's existence alone, so a marker that cannot be read still
7
+ * classifies its directory as a subsystem — anything else would let a corrupt
8
+ * byte reinterpret a whole subtree as a service and swallow the fleet beneath
9
+ * it, the exact silent-shrink the three-way classification exists to refuse.
10
+ * An unreadable marker is reported as exactly one `subsystem.invalid` finding
11
+ * instead (`walk.ts` emits it from the `invalid` field here).
12
+ *
13
+ * The defensive-read shape is `core/permissions/permissions.ts`'s: every wrong
14
+ * shape is an `invalid` sentence naming what is wrong, never a throw — this is
15
+ * a read model, and a marker somebody hand-edited badly must not take down the
16
+ * enumeration that would report it.
17
+ */
18
+ import { readFile } from "node:fs/promises";
19
+ import { parse as parseYaml } from "yaml";
20
+ import { isRecord } from "../../kernel/records.js";
21
+ /** The marker's filename — spelled here and nowhere else. */
22
+ export const SUBSYSTEM_MARKER = "subsystem.yaml";
23
+ /**
24
+ * Read one marker. An EMPTY file is a valid marker with no metadata — the
25
+ * marker's job is done by existing, and `title`/`description`/`owner` are all
26
+ * optional. A `members` key is invalid on purpose: placement is recorded
27
+ * exactly once, in the directory itself, and a membership list would be a
28
+ * second copy that merges, drifts and lies (SCHEMA.md's marker-not-manifest
29
+ * rule).
30
+ */
31
+ export async function readSubsystemMarker(path) {
32
+ let doc;
33
+ try {
34
+ doc = parseYaml(await readFile(path, "utf8"));
35
+ }
36
+ catch (e) {
37
+ return { invalid: e instanceof Error ? e.message : String(e) };
38
+ }
39
+ if (doc === null || doc === undefined)
40
+ return {};
41
+ if (!isRecord(doc))
42
+ return { invalid: "the document is not a mapping" };
43
+ if (doc["members"] !== undefined) {
44
+ return {
45
+ invalid: "it declares `members` — a subsystem's members are the service directories inside it, " +
46
+ "recorded exactly once, in the directory itself; a list here would be a second copy that drifts",
47
+ };
48
+ }
49
+ for (const field of ["title", "description", "owner"]) {
50
+ const value = doc[field];
51
+ if (value !== undefined && typeof value !== "string") {
52
+ return { invalid: `\`${field}\` is not a string` };
53
+ }
54
+ }
55
+ return {
56
+ ...(typeof doc["title"] === "string" ? { title: doc["title"] } : {}),
57
+ ...(typeof doc["description"] === "string" ? { description: doc["description"] } : {}),
58
+ ...(typeof doc["owner"] === "string" ? { owner: doc["owner"] } : {}),
59
+ };
60
+ }
61
+ //# sourceMappingURL=marker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"marker.js","sourceRoot":"","sources":["../../../../src/core/repo/tree/marker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,KAAK,IAAI,SAAS,EAAE,MAAM,MAAM,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAEnD,6DAA6D;AAC7D,MAAM,CAAC,MAAM,gBAAgB,GAAG,gBAAgB,CAAC;AAUjD;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,IAAY;IACpD,IAAI,GAAY,CAAC;IACjB,IAAI,CAAC;QACH,GAAG,GAAG,SAAS,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;IAChD,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,EAAE,OAAO,EAAE,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;IACjE,CAAC;IACD,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,SAAS;QAAE,OAAO,EAAE,CAAC;IACjD,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,EAAE,OAAO,EAAE,+BAA+B,EAAE,CAAC;IACxE,IAAI,GAAG,CAAC,SAAS,CAAC,KAAK,SAAS,EAAE,CAAC;QACjC,OAAO;YACL,OAAO,EACL,uFAAuF;gBACvF,gGAAgG;SACnG,CAAC;IACJ,CAAC;IACD,KAAK,MAAM,KAAK,IAAI,CAAC,OAAO,EAAE,aAAa,EAAE,OAAO,CAAU,EAAE,CAAC;QAC/D,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC;QACzB,IAAI,KAAK,KAAK,SAAS,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YACrD,OAAO,EAAE,OAAO,EAAE,KAAK,KAAK,oBAAoB,EAAE,CAAC;QACrD,CAAC;IACH,CAAC;IACD,OAAO;QACL,GAAG,CAAC,OAAO,GAAG,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACpE,GAAG,CAAC,OAAO,GAAG,CAAC,aAAa,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,GAAG,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACtF,GAAG,CAAC,OAAO,GAAG,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACrE,CAAC;AACJ,CAAC","sourcesContent":["/**\n * The subsystem marker: `subsystem.yaml`, the one file that makes a directory\n * under `services/` a GROUP rather than a service.\n *\n * Presence classifies; content is metadata. The walk decides what a directory\n * IS from the marker's existence alone, so a marker that cannot be read still\n * classifies its directory as a subsystem — anything else would let a corrupt\n * byte reinterpret a whole subtree as a service and swallow the fleet beneath\n * it, the exact silent-shrink the three-way classification exists to refuse.\n * An unreadable marker is reported as exactly one `subsystem.invalid` finding\n * instead (`walk.ts` emits it from the `invalid` field here).\n *\n * The defensive-read shape is `core/permissions/permissions.ts`'s: every wrong\n * shape is an `invalid` sentence naming what is wrong, never a throw — this is\n * a read model, and a marker somebody hand-edited badly must not take down the\n * enumeration that would report it.\n */\nimport { readFile } from \"node:fs/promises\";\nimport { parse as parseYaml } from \"yaml\";\nimport { isRecord } from \"../../kernel/records.js\";\n\n/** The marker's filename — spelled here and nowhere else. */\nexport const SUBSYSTEM_MARKER = \"subsystem.yaml\";\n\nexport interface SubsystemMeta {\n title?: string;\n description?: string;\n owner?: string;\n /** Why the file could not be read as subsystem metadata, when it could not. */\n invalid?: string;\n}\n\n/**\n * Read one marker. An EMPTY file is a valid marker with no metadata — the\n * marker's job is done by existing, and `title`/`description`/`owner` are all\n * optional. A `members` key is invalid on purpose: placement is recorded\n * exactly once, in the directory itself, and a membership list would be a\n * second copy that merges, drifts and lies (SCHEMA.md's marker-not-manifest\n * rule).\n */\nexport async function readSubsystemMarker(path: string): Promise<SubsystemMeta> {\n let doc: unknown;\n try {\n doc = parseYaml(await readFile(path, \"utf8\"));\n } catch (e) {\n return { invalid: e instanceof Error ? e.message : String(e) };\n }\n if (doc === null || doc === undefined) return {};\n if (!isRecord(doc)) return { invalid: \"the document is not a mapping\" };\n if (doc[\"members\"] !== undefined) {\n return {\n invalid:\n \"it declares `members` — a subsystem's members are the service directories inside it, \" +\n \"recorded exactly once, in the directory itself; a list here would be a second copy that drifts\",\n };\n }\n for (const field of [\"title\", \"description\", \"owner\"] as const) {\n const value = doc[field];\n if (value !== undefined && typeof value !== \"string\") {\n return { invalid: `\\`${field}\\` is not a string` };\n }\n }\n return {\n ...(typeof doc[\"title\"] === \"string\" ? { title: doc[\"title\"] } : {}),\n ...(typeof doc[\"description\"] === \"string\" ? { description: doc[\"description\"] } : {}),\n ...(typeof doc[\"owner\"] === \"string\" ? { owner: doc[\"owner\"] } : {}),\n };\n}\n"]}
@@ -0,0 +1,258 @@
1
+ /**
2
+ * What one subsystem's generated view SHOWS: which boxes it draws around the
3
+ * services beneath a directory, and the one thing it may say about the map.
4
+ *
5
+ * Split from `../views.ts` when that file crossed the 400-line limit: the file
6
+ * render (header, view ids, staleness comparison) and the body render (the
7
+ * boxes) are two subjects, and the seam is exactly where the second one
8
+ * consults the LANDSCAPE. Everything here reads element ids and nothing else —
9
+ * no view is ever parsed (docs/DESIGN.md rule 26), and the generated file
10
+ * stays a pure function of the tree plus the committed map.
11
+ */
12
+ import {} from "../../../c4/likec4.js";
13
+ import { serviceResolver } from "../../../c4/resolve/service.js";
14
+ import { servicesUnder, withinSubsystem } from "../find.js";
15
+ import { subsystemLabel } from "./text.js";
16
+ export function renderContext(tree, elements) {
17
+ const known = new Set(tree.services.map((s) => s.id));
18
+ const resolve = serviceResolver(elements, known);
19
+ return {
20
+ tree,
21
+ elementOf: elementByService(tree, elements, resolve),
22
+ elementIds: new Set(elements.map((e) => e.id)),
23
+ isServiceElement: (id) => known.has(resolve(id)),
24
+ };
25
+ }
26
+ /**
27
+ * Three shapes, and which one applies is a fact about the landscape rather
28
+ * than a setting:
29
+ *
30
+ * 1. **The model draws this group.** Some ancestor element holds exactly this
31
+ * subsystem's members and nothing else, so the view includes it beside the
32
+ * leaves and the renderer nests them inside the box the AUTHOR drew, with
33
+ * the author's own title. Measured: including the ancestor alone renders
34
+ * one empty box and the leaves alone render flat — both lines are needed.
35
+ * 2. **The model is flat.** No member element is nested at all, so there is
36
+ * no authored box to agree with, and the view wraps the members in a
37
+ * `group '<title>'` of its own — a real named box in the renderer, derived
38
+ * from the DIRECTORY the services already sit in, mirroring the subtree so
39
+ * a parent subsystem shows its children as boxes rather than as one pile.
40
+ * Nothing is invented: the grouping is the tree, and the tree is what this
41
+ * file has always mirrored.
42
+ * 3. **The model nests them, differently.** The members ARE nested but no
43
+ * ancestor owns exactly them — the directory tree and the map disagree
44
+ * about this group. loam draws no box (a synthetic one would silently
45
+ * replace the author's boundary with the folder's, and the picture would
46
+ * look the same whether or not the two agree) and writes ONE comment line
47
+ * saying so, outside the view body. That comment is the whole of loam's
48
+ * answer to the drift: it grades nothing, it fails nothing, and it appears
49
+ * in the diff of the very commit that caused it — placement stays a fact
50
+ * nothing branches on.
51
+ */
52
+ export function viewBody(ctx, sub) {
53
+ const members = memberElements(ctx, sub);
54
+ if (members.length === 0)
55
+ return { lines: [], disclosure: null, of: null };
56
+ if (members.every((id) => !id.includes("."))) {
57
+ return { lines: [...groupedBody(ctx, sub, " "), ...boundaryLines(members)], disclosure: null, of: null };
58
+ }
59
+ const includes = [...ownedAncestors(ctx, sub), ...members].map((id) => ` include ${id}`);
60
+ const lines = [...includes, ...boundaryLines(members)];
61
+ const owner = owningAncestor(ctx, sub);
62
+ if (owner !== null)
63
+ return { lines, disclosure: null, of: owner };
64
+ const shared = sharedAncestor(ctx, members);
65
+ return {
66
+ lines,
67
+ of: null,
68
+ disclosure: shared === null
69
+ ? "model: no boundary — these members do not share a containing element."
70
+ : `model: no boundary — ${shared} also holds services outside this subsystem.`,
71
+ };
72
+ }
73
+ /**
74
+ * What this group TOUCHES: for each member, every edge it has in either
75
+ * direction, so the view answers "what does payments talk to" and not only
76
+ * "who is in payments".
77
+ *
78
+ * **The measured trap, and it is why these lines are appended by the caller of
79
+ * `groupedBody` rather than inside it:** placed INSIDE the `group { }` block of
80
+ * the flat-map body shape, this exact predicate parses and validates with ZERO
81
+ * errors and draws a false picture. Measured at likec4 1.59.2 on a flat map of
82
+ * `alpha, beta` grouped and `outsider, store` outside it: at view level the two
83
+ * neighbours are drawn with no parent, correctly outside the box; moved inside
84
+ * the `group { }`, both are drawn as CHILDREN of that group — the diagram then
85
+ * claims `outsider` and `store` are part of the subsystem. A maintainer tidying
86
+ * the body by moving these lines next to the includes they refer to would ship
87
+ * that, and nothing anywhere would report it. They belong at view level, always.
88
+ *
89
+ * The WILDCARD is correct here, and that is not an inconsistency with the
90
+ * per-service views, which measure it as a defect (`./service/peers.ts`): at
91
+ * subsystem altitude a counterpart collapsing to its own group box is exactly
92
+ * the sentence "payments touches identity", and — once those group boxes are
93
+ * themselves views' subjects (`of <ancestor>`) — it is a click-through into
94
+ * that subsystem. At service altitude the same collapse is a lie about who
95
+ * calls whom.
96
+ *
97
+ * MEMBERS only, never `ownedAncestors`: `-> *` on an authored container pulls
98
+ * in every edge any descendant of it has, and in the `// model: no boundary`
99
+ * shape that container also holds services outside this subsystem — the view
100
+ * would draw traffic that is nobody-here's. Measured at 58 services in 11
101
+ * groups: 13-15 nodes and 31-39 edges per subsystem view, of which 11-12 nodes
102
+ * carry drill-down — the members into their own service views, the neighbouring
103
+ * group boxes into THEIR subsystem views.
104
+ */
105
+ function boundaryLines(members) {
106
+ return ["", ...members.map((id) => ` include ${id} -> *, * -> ${id}`)];
107
+ }
108
+ /**
109
+ * The flat-model body: this subsystem as a box, its child subsystems as boxes
110
+ * inside it, its own services as leaves. Recursive, and the recursion is the
111
+ * point — a parent subsystem's view is otherwise one undifferentiated pile of
112
+ * every service beneath it.
113
+ *
114
+ * An empty child renders an empty named box, which is what the tree says: the
115
+ * group exists and holds nothing yet.
116
+ */
117
+ function groupedBody(ctx, sub, indent) {
118
+ const inner = `${indent} `;
119
+ const out = [`${indent}group '${subsystemLabel(sub)}' {`];
120
+ for (const child of childSubsystems(ctx, sub))
121
+ out.push(...groupedBody(ctx, child, inner));
122
+ for (const id of directMemberElements(ctx, sub))
123
+ out.push(`${inner}include ${id}`);
124
+ out.push(`${indent}}`);
125
+ return out;
126
+ }
127
+ /** The child subsystems one level down, ordered by name. */
128
+ function childSubsystems(ctx, sub) {
129
+ return ctx.tree.subsystems
130
+ .filter((c) => c.path.length === sub.path.length + 1 && withinSubsystem(sub.path, c.path))
131
+ .sort((a, b) => (a.name < b.name ? -1 : 1));
132
+ }
133
+ /** The drawn elements of the services filed in THIS directory, not in a child. */
134
+ function directMemberElements(ctx, sub) {
135
+ return drawnElements(ctx, membersOf(ctx.tree, sub).filter((s) => s.subsystem.length === sub.path.length));
136
+ }
137
+ /** The drawn elements of every service beneath this subsystem, ordered by service id. */
138
+ function memberElements(ctx, sub) {
139
+ return drawnElements(ctx, membersOf(ctx.tree, sub));
140
+ }
141
+ /**
142
+ * The element ids these services resolve to. A service the map does not draw
143
+ * is omitted rather than invented: the omission is already an error
144
+ * (`landscape.service-unmodelled`), and rendering only what the committed
145
+ * documents resolve keeps the output a function of committed bytes alone.
146
+ */
147
+ function drawnElements(ctx, services) {
148
+ return services.map((s) => ctx.elementOf.get(s.id)).filter((id) => id !== undefined);
149
+ }
150
+ /**
151
+ * The boxes a nested-model view draws: this subsystem's own owning ancestor
152
+ * when it has one, plus the owning ancestor of every subsystem beneath it — so
153
+ * a parent view keeps its children's boundaries instead of flattening them
154
+ * into one box. Sorted and de-duplicated, because two subsystems resolve to
155
+ * one element only in a tree that already reports a collision.
156
+ */
157
+ function ownedAncestors(ctx, sub) {
158
+ const found = new Set();
159
+ for (const candidate of ctx.tree.subsystems) {
160
+ if (!withinSubsystem(sub.path, candidate.path))
161
+ continue;
162
+ const owner = owningAncestor(ctx, candidate);
163
+ if (owner !== null)
164
+ found.add(owner);
165
+ }
166
+ return [...found].sort();
167
+ }
168
+ /**
169
+ * The deepest ancestor element that holds exactly this subsystem's members —
170
+ * or null when no element does.
171
+ *
172
+ * "Exactly" is the whole guard, and dropping it was measured on loam's own
173
+ * `examples/docs`: the members' longest common ancestor there is a group of
174
+ * five services while the subsystem holds two, so an unguarded include would
175
+ * generate a box labelled for the group with two of its five children drawn
176
+ * inside it — a diagram asserting something false, in a file the reader is
177
+ * told not to edit. Tightness is judged over ELEMENTS rather than over
178
+ * documented services: mid-adoption a group commonly holds systems no
179
+ * `services/<id>/` exists for yet, and counting only the documented ones would
180
+ * draw that same false box for the whole of an adoption.
181
+ *
182
+ * An ancestor that is itself a service's element is refused separately: one
183
+ * service's box containing another's is a picture of nothing.
184
+ */
185
+ function owningAncestor(ctx, sub) {
186
+ const members = memberElements(ctx, sub);
187
+ if (members.length === 0)
188
+ return null;
189
+ const owned = new Set(members);
190
+ for (const candidate of ancestorChain(members)) {
191
+ if (!ctx.elementIds.has(candidate) || ctx.isServiceElement(candidate))
192
+ continue;
193
+ if (ownsExactly(ctx, candidate, owned))
194
+ return candidate;
195
+ }
196
+ return null;
197
+ }
198
+ /** The deepest common ancestor the map declares at all — the disclosure's subject. */
199
+ function sharedAncestor(ctx, members) {
200
+ return ancestorChain(members).find((id) => ctx.elementIds.has(id)) ?? null;
201
+ }
202
+ /** The common proper ancestors of every member id, deepest first. */
203
+ function ancestorChain(members) {
204
+ const segments = members.map((id) => id.split("."));
205
+ let common = Math.min(...segments.map((s) => s.length - 1));
206
+ for (let i = 0; i < common; i++) {
207
+ if (!segments.every((s) => s[i] === segments[0][i])) {
208
+ common = i;
209
+ break;
210
+ }
211
+ }
212
+ const out = [];
213
+ for (let depth = common; depth > 0; depth--)
214
+ out.push(segments[0].slice(0, depth).join("."));
215
+ return out;
216
+ }
217
+ /**
218
+ * Does every element beneath `ancestor` belong to this subsystem — as a
219
+ * member, as one of a member's own containers, or as a container of one?
220
+ */
221
+ function ownsExactly(ctx, ancestor, members) {
222
+ const prefix = `${ancestor}.`;
223
+ for (const id of ctx.elementIds) {
224
+ if (!id.startsWith(prefix))
225
+ continue;
226
+ const claimed = [...members].some((m) => id === m || id.startsWith(`${m}.`) || m.startsWith(`${id}.`));
227
+ if (!claimed)
228
+ return false;
229
+ }
230
+ return true;
231
+ }
232
+ /**
233
+ * The landscape element standing for each service id: for every element,
234
+ * resolve it through the shared join, and let the SHALLOWEST element win
235
+ * (document order breaking ties). Shallowest, because `serviceResolver`
236
+ * resolves a service's own containers to the service too, and a view should
237
+ * include the service-level box, not whichever nested container happened to be
238
+ * declared first.
239
+ */
240
+ function elementByService(tree, elements, resolve) {
241
+ const known = new Set(tree.services.map((s) => s.id));
242
+ const depth = (id) => id.split(".").length;
243
+ const out = new Map();
244
+ for (const e of elements) {
245
+ const service = resolve(e.id);
246
+ if (!known.has(service))
247
+ continue;
248
+ const held = out.get(service);
249
+ if (held === undefined || depth(e.id) < depth(held))
250
+ out.set(service, e.id);
251
+ }
252
+ return out;
253
+ }
254
+ /** Services beneath this subsystem at any depth, ordered by id — the transitive membership. */
255
+ function membersOf(tree, sub) {
256
+ return [...servicesUnder(tree, sub)].sort((a, b) => (a.id < b.id ? -1 : 1));
257
+ }
258
+ //# sourceMappingURL=body.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"body.js","sourceRoot":"","sources":["../../../../../src/core/repo/tree/render/body.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * What one subsystem's generated view SHOWS: which boxes it draws around the\n * services beneath a directory, and the one thing it may say about the map.\n *\n * Split from `../views.ts` when that file crossed the 400-line limit: the file\n * render (header, view ids, staleness comparison) and the body render (the\n * boxes) are two subjects, and the seam is exactly where the second one\n * consults the LANDSCAPE. Everything here reads element ids and nothing else —\n * no view is ever parsed (docs/DESIGN.md rule 26), and the generated file\n * stays a pure function of the tree plus the committed map.\n */\nimport { type Elem } from \"../../../c4/likec4.js\";\nimport { serviceResolver } from \"../../../c4/resolve/service.js\";\nimport { servicesUnder, withinSubsystem } from \"../find.js\";\nimport type { FleetTree, SubsystemEntry, WalkedService } from \"../walk.js\";\nimport { subsystemLabel } from \"./text.js\";\n\n/**\n * Everything a view's body needs from the landscape, resolved ONCE: the\n * element standing for each service, every element id the map declares, and\n * whether an element is a service's own box. A record rather than four\n * threaded parameters because the body render recurses down the subsystem\n * subtree and would otherwise sit on the parameter limit at every hop\n * (`docs/CODE-STYLE.md`'s own prescription).\n */\nexport interface RenderContext {\n tree: FleetTree;\n elementOf: Map<string, string>;\n elementIds: ReadonlySet<string>;\n isServiceElement: (id: string) => boolean;\n}\n\nexport function renderContext(tree: FleetTree, elements: Elem[]): RenderContext {\n const known: ReadonlySet<string> = new Set(tree.services.map((s) => s.id));\n const resolve = serviceResolver(elements, known);\n return {\n tree,\n elementOf: elementByService(tree, elements, resolve),\n elementIds: new Set(elements.map((e) => e.id)),\n isServiceElement: (id: string): boolean => known.has(resolve(id)),\n };\n}\n\n/** A view's body lines, the one comment the render may write above it, and its subject. */\nexport interface ViewBody {\n lines: string[];\n disclosure: string | null;\n /**\n * The element this view is declared `of`, or null when the map holds none\n * that owns exactly this subsystem. It is computed here rather than by the\n * file render because `owningAncestor` below already decides it — the same\n * answer decides which of the three body shapes applies, and two callers\n * deriving it separately could draw the boundary of one element while\n * declaring the view of another.\n */\n of: string | null;\n}\n\n/**\n * Three shapes, and which one applies is a fact about the landscape rather\n * than a setting:\n *\n * 1. **The model draws this group.** Some ancestor element holds exactly this\n * subsystem's members and nothing else, so the view includes it beside the\n * leaves and the renderer nests them inside the box the AUTHOR drew, with\n * the author's own title. Measured: including the ancestor alone renders\n * one empty box and the leaves alone render flat — both lines are needed.\n * 2. **The model is flat.** No member element is nested at all, so there is\n * no authored box to agree with, and the view wraps the members in a\n * `group '<title>'` of its own — a real named box in the renderer, derived\n * from the DIRECTORY the services already sit in, mirroring the subtree so\n * a parent subsystem shows its children as boxes rather than as one pile.\n * Nothing is invented: the grouping is the tree, and the tree is what this\n * file has always mirrored.\n * 3. **The model nests them, differently.** The members ARE nested but no\n * ancestor owns exactly them — the directory tree and the map disagree\n * about this group. loam draws no box (a synthetic one would silently\n * replace the author's boundary with the folder's, and the picture would\n * look the same whether or not the two agree) and writes ONE comment line\n * saying so, outside the view body. That comment is the whole of loam's\n * answer to the drift: it grades nothing, it fails nothing, and it appears\n * in the diff of the very commit that caused it — placement stays a fact\n * nothing branches on.\n */\nexport function viewBody(ctx: RenderContext, sub: SubsystemEntry): ViewBody {\n const members = memberElements(ctx, sub);\n if (members.length === 0) return { lines: [], disclosure: null, of: null };\n if (members.every((id) => !id.includes(\".\"))) {\n return { lines: [...groupedBody(ctx, sub, \" \"), ...boundaryLines(members)], disclosure: null, of: null };\n }\n const includes = [...ownedAncestors(ctx, sub), ...members].map((id) => ` include ${id}`);\n const lines = [...includes, ...boundaryLines(members)];\n const owner = owningAncestor(ctx, sub);\n if (owner !== null) return { lines, disclosure: null, of: owner };\n const shared = sharedAncestor(ctx, members);\n return {\n lines,\n of: null,\n disclosure:\n shared === null\n ? \"model: no boundary — these members do not share a containing element.\"\n : `model: no boundary — ${shared} also holds services outside this subsystem.`,\n };\n}\n\n/**\n * What this group TOUCHES: for each member, every edge it has in either\n * direction, so the view answers \"what does payments talk to\" and not only\n * \"who is in payments\".\n *\n * **The measured trap, and it is why these lines are appended by the caller of\n * `groupedBody` rather than inside it:** placed INSIDE the `group { }` block of\n * the flat-map body shape, this exact predicate parses and validates with ZERO\n * errors and draws a false picture. Measured at likec4 1.59.2 on a flat map of\n * `alpha, beta` grouped and `outsider, store` outside it: at view level the two\n * neighbours are drawn with no parent, correctly outside the box; moved inside\n * the `group { }`, both are drawn as CHILDREN of that group — the diagram then\n * claims `outsider` and `store` are part of the subsystem. A maintainer tidying\n * the body by moving these lines next to the includes they refer to would ship\n * that, and nothing anywhere would report it. They belong at view level, always.\n *\n * The WILDCARD is correct here, and that is not an inconsistency with the\n * per-service views, which measure it as a defect (`./service/peers.ts`): at\n * subsystem altitude a counterpart collapsing to its own group box is exactly\n * the sentence \"payments touches identity\", and — once those group boxes are\n * themselves views' subjects (`of <ancestor>`) — it is a click-through into\n * that subsystem. At service altitude the same collapse is a lie about who\n * calls whom.\n *\n * MEMBERS only, never `ownedAncestors`: `-> *` on an authored container pulls\n * in every edge any descendant of it has, and in the `// model: no boundary`\n * shape that container also holds services outside this subsystem — the view\n * would draw traffic that is nobody-here's. Measured at 58 services in 11\n * groups: 13-15 nodes and 31-39 edges per subsystem view, of which 11-12 nodes\n * carry drill-down — the members into their own service views, the neighbouring\n * group boxes into THEIR subsystem views.\n */\nfunction boundaryLines(members: readonly string[]): string[] {\n return [\"\", ...members.map((id) => ` include ${id} -> *, * -> ${id}`)];\n}\n\n/**\n * The flat-model body: this subsystem as a box, its child subsystems as boxes\n * inside it, its own services as leaves. Recursive, and the recursion is the\n * point — a parent subsystem's view is otherwise one undifferentiated pile of\n * every service beneath it.\n *\n * An empty child renders an empty named box, which is what the tree says: the\n * group exists and holds nothing yet.\n */\nfunction groupedBody(ctx: RenderContext, sub: SubsystemEntry, indent: string): string[] {\n const inner = `${indent} `;\n const out = [`${indent}group '${subsystemLabel(sub)}' {`];\n for (const child of childSubsystems(ctx, sub)) out.push(...groupedBody(ctx, child, inner));\n for (const id of directMemberElements(ctx, sub)) out.push(`${inner}include ${id}`);\n out.push(`${indent}}`);\n return out;\n}\n\n/** The child subsystems one level down, ordered by name. */\nfunction childSubsystems(ctx: RenderContext, sub: SubsystemEntry): SubsystemEntry[] {\n return ctx.tree.subsystems\n .filter((c) => c.path.length === sub.path.length + 1 && withinSubsystem(sub.path, c.path))\n .sort((a, b) => (a.name < b.name ? -1 : 1));\n}\n\n/** The drawn elements of the services filed in THIS directory, not in a child. */\nfunction directMemberElements(ctx: RenderContext, sub: SubsystemEntry): string[] {\n return drawnElements(\n ctx,\n membersOf(ctx.tree, sub).filter((s) => s.subsystem.length === sub.path.length),\n );\n}\n\n/** The drawn elements of every service beneath this subsystem, ordered by service id. */\nfunction memberElements(ctx: RenderContext, sub: SubsystemEntry): string[] {\n return drawnElements(ctx, membersOf(ctx.tree, sub));\n}\n\n/**\n * The element ids these services resolve to. A service the map does not draw\n * is omitted rather than invented: the omission is already an error\n * (`landscape.service-unmodelled`), and rendering only what the committed\n * documents resolve keeps the output a function of committed bytes alone.\n */\nfunction drawnElements(ctx: RenderContext, services: WalkedService[]): string[] {\n return services.map((s) => ctx.elementOf.get(s.id)).filter((id): id is string => id !== undefined);\n}\n\n/**\n * The boxes a nested-model view draws: this subsystem's own owning ancestor\n * when it has one, plus the owning ancestor of every subsystem beneath it — so\n * a parent view keeps its children's boundaries instead of flattening them\n * into one box. Sorted and de-duplicated, because two subsystems resolve to\n * one element only in a tree that already reports a collision.\n */\nfunction ownedAncestors(ctx: RenderContext, sub: SubsystemEntry): string[] {\n const found = new Set<string>();\n for (const candidate of ctx.tree.subsystems) {\n if (!withinSubsystem(sub.path, candidate.path)) continue;\n const owner = owningAncestor(ctx, candidate);\n if (owner !== null) found.add(owner);\n }\n return [...found].sort();\n}\n\n/**\n * The deepest ancestor element that holds exactly this subsystem's members —\n * or null when no element does.\n *\n * \"Exactly\" is the whole guard, and dropping it was measured on loam's own\n * `examples/docs`: the members' longest common ancestor there is a group of\n * five services while the subsystem holds two, so an unguarded include would\n * generate a box labelled for the group with two of its five children drawn\n * inside it — a diagram asserting something false, in a file the reader is\n * told not to edit. Tightness is judged over ELEMENTS rather than over\n * documented services: mid-adoption a group commonly holds systems no\n * `services/<id>/` exists for yet, and counting only the documented ones would\n * draw that same false box for the whole of an adoption.\n *\n * An ancestor that is itself a service's element is refused separately: one\n * service's box containing another's is a picture of nothing.\n */\nfunction owningAncestor(ctx: RenderContext, sub: SubsystemEntry): string | null {\n const members = memberElements(ctx, sub);\n if (members.length === 0) return null;\n const owned = new Set(members);\n for (const candidate of ancestorChain(members)) {\n if (!ctx.elementIds.has(candidate) || ctx.isServiceElement(candidate)) continue;\n if (ownsExactly(ctx, candidate, owned)) return candidate;\n }\n return null;\n}\n\n/** The deepest common ancestor the map declares at all — the disclosure's subject. */\nfunction sharedAncestor(ctx: RenderContext, members: string[]): string | null {\n return ancestorChain(members).find((id) => ctx.elementIds.has(id)) ?? null;\n}\n\n/** The common proper ancestors of every member id, deepest first. */\nfunction ancestorChain(members: string[]): string[] {\n const segments = members.map((id) => id.split(\".\"));\n let common = Math.min(...segments.map((s) => s.length - 1));\n for (let i = 0; i < common; i++) {\n if (!segments.every((s) => s[i] === segments[0]![i])) {\n common = i;\n break;\n }\n }\n const out: string[] = [];\n for (let depth = common; depth > 0; depth--) out.push(segments[0]!.slice(0, depth).join(\".\"));\n return out;\n}\n\n/**\n * Does every element beneath `ancestor` belong to this subsystem — as a\n * member, as one of a member's own containers, or as a container of one?\n */\nfunction ownsExactly(ctx: RenderContext, ancestor: string, members: ReadonlySet<string>): boolean {\n const prefix = `${ancestor}.`;\n for (const id of ctx.elementIds) {\n if (!id.startsWith(prefix)) continue;\n const claimed = [...members].some((m) => id === m || id.startsWith(`${m}.`) || m.startsWith(`${id}.`));\n if (!claimed) return false;\n }\n return true;\n}\n\n/**\n * The landscape element standing for each service id: for every element,\n * resolve it through the shared join, and let the SHALLOWEST element win\n * (document order breaking ties). Shallowest, because `serviceResolver`\n * resolves a service's own containers to the service too, and a view should\n * include the service-level box, not whichever nested container happened to be\n * declared first.\n */\nfunction elementByService(\n tree: FleetTree,\n elements: Elem[],\n resolve: (id: string) => string,\n): Map<string, string> {\n const known: ReadonlySet<string> = new Set(tree.services.map((s) => s.id));\n const depth = (id: string): number => id.split(\".\").length;\n const out = new Map<string, string>();\n for (const e of elements) {\n const service = resolve(e.id);\n if (!known.has(service)) continue;\n const held = out.get(service);\n if (held === undefined || depth(e.id) < depth(held)) out.set(service, e.id);\n }\n return out;\n}\n\n/** Services beneath this subsystem at any depth, ordered by id — the transitive membership. */\nfunction membersOf(tree: FleetTree, sub: SubsystemEntry): WalkedService[] {\n return [...servicesUnder(tree, sub)].sort((a, b) => (a.id < b.id ? -1 : 1));\n}\n"]}