@ybotok/loam 0.2.0-alpha.1 → 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 (901) hide show
  1. package/CHANGELOG.md +3448 -0
  2. package/COMPARISON.md +91 -3
  3. package/CONTRIBUTING.md +37 -0
  4. package/MIGRATING-from-OpenSpec.md +47 -23
  5. package/QUICKSTART.md +189 -12
  6. package/README.md +274 -65
  7. package/ROADMAP.md +572 -31
  8. package/SCHEMA.md +1709 -155
  9. package/WORKFLOW.md +298 -72
  10. package/dist/cli.js +26 -8
  11. package/dist/cli.js.map +1 -1
  12. package/dist/commands/adopt/adopt.js +5 -10
  13. package/dist/commands/adopt/adopt.js.map +1 -1
  14. package/dist/commands/adopt/render.js +50 -9
  15. package/dist/commands/adopt/render.js.map +1 -1
  16. package/dist/commands/archive/archive.js +16 -19
  17. package/dist/commands/archive/archive.js.map +1 -1
  18. package/dist/commands/archive/closing.js +42 -0
  19. package/dist/commands/archive/closing.js.map +1 -0
  20. package/dist/commands/archive/plan/contracts/asyncapi.js +36 -42
  21. package/dist/commands/archive/plan/contracts/asyncapi.js.map +1 -1
  22. package/dist/commands/archive/plan/contracts/consumers.js +56 -0
  23. package/dist/commands/archive/plan/contracts/consumers.js.map +1 -0
  24. package/dist/commands/archive/plan/contracts/openapi.js +77 -43
  25. package/dist/commands/archive/plan/contracts/openapi.js.map +1 -1
  26. package/dist/commands/archive/plan/contracts/verdict-lines.js +103 -0
  27. package/dist/commands/archive/plan/contracts/verdict-lines.js.map +1 -0
  28. package/dist/commands/archive/plan/document/head.js +151 -0
  29. package/dist/commands/archive/plan/document/head.js.map +1 -0
  30. package/dist/commands/archive/plan/document/links.js +284 -0
  31. package/dist/commands/archive/plan/document/links.js.map +1 -0
  32. package/dist/commands/archive/plan/document/run.js +136 -0
  33. package/dist/commands/archive/plan/document/run.js.map +1 -0
  34. package/dist/commands/archive/plan/gate.js +21 -19
  35. package/dist/commands/archive/plan/gate.js.map +1 -1
  36. package/dist/commands/archive/plan/landscape.js +167 -30
  37. package/dist/commands/archive/plan/landscape.js.map +1 -1
  38. package/dist/commands/archive/plan/model/extending.js +85 -0
  39. package/dist/commands/archive/plan/model/extending.js.map +1 -0
  40. package/dist/commands/archive/plan/refusal.js +14 -19
  41. package/dist/commands/archive/plan/refusal.js.map +1 -1
  42. package/dist/commands/archive/plan/specs.js +137 -56
  43. package/dist/commands/archive/plan/specs.js.map +1 -1
  44. package/dist/commands/archive/plan/state.js +3 -0
  45. package/dist/commands/archive/plan/state.js.map +1 -1
  46. package/dist/commands/archive/run.js +134 -30
  47. package/dist/commands/archive/run.js.map +1 -1
  48. package/dist/commands/archive/shipped.js +49 -0
  49. package/dist/commands/archive/shipped.js.map +1 -0
  50. package/dist/commands/context/context.js +85 -18
  51. package/dist/commands/context/context.js.map +1 -1
  52. package/dist/commands/context/print.js +29 -7
  53. package/dist/commands/context/print.js.map +1 -1
  54. package/dist/commands/delta/delta.js +102 -14
  55. package/dist/commands/delta/delta.js.map +1 -1
  56. package/dist/commands/delta/print.js +17 -1
  57. package/dist/commands/delta/print.js.map +1 -1
  58. package/dist/commands/dependencies.js +3 -7
  59. package/dist/commands/dependencies.js.map +1 -1
  60. package/dist/commands/diff/diff.js +20 -27
  61. package/dist/commands/diff/diff.js.map +1 -1
  62. package/dist/commands/doctor.js +60 -1
  63. package/dist/commands/doctor.js.map +1 -1
  64. package/dist/commands/explain/explain.js +89 -13
  65. package/dist/commands/explain/explain.js.map +1 -1
  66. package/dist/commands/explore.js +16 -10
  67. package/dist/commands/explore.js.map +1 -1
  68. package/dist/commands/gate/gate.js +45 -8
  69. package/dist/commands/gate/gate.js.map +1 -1
  70. package/dist/commands/gate/print.js +15 -3
  71. package/dist/commands/gate/print.js.map +1 -1
  72. package/dist/commands/gherkin/commit.js +13 -54
  73. package/dist/commands/gherkin/commit.js.map +1 -1
  74. package/dist/commands/gherkin/gherkin.js +36 -20
  75. package/dist/commands/gherkin/gherkin.js.map +1 -1
  76. package/dist/commands/gherkin/reconcile.js +10 -13
  77. package/dist/commands/gherkin/reconcile.js.map +1 -1
  78. package/dist/commands/init/first-hour.js +44 -0
  79. package/dist/commands/init/first-hour.js.map +1 -1
  80. package/dist/commands/init/init.js +18 -22
  81. package/dist/commands/init/init.js.map +1 -1
  82. package/dist/commands/list/campaign/campaign.js +4 -6
  83. package/dist/commands/list/campaign/campaign.js.map +1 -1
  84. package/dist/commands/list/json.js +5 -7
  85. package/dist/commands/list/json.js.map +1 -1
  86. package/dist/commands/list/list.js +44 -29
  87. package/dist/commands/list/list.js.map +1 -1
  88. package/dist/commands/list/print.js +52 -9
  89. package/dist/commands/list/print.js.map +1 -1
  90. package/dist/commands/list/suites/suites.js +140 -0
  91. package/dist/commands/list/suites/suites.js.map +1 -0
  92. package/dist/commands/list/views.js +37 -34
  93. package/dist/commands/list/views.js.map +1 -1
  94. package/dist/commands/mcp/dispatch.js +91 -36
  95. package/dist/commands/mcp/dispatch.js.map +1 -1
  96. package/dist/commands/mcp/mcp.js +56 -15
  97. package/dist/commands/mcp/mcp.js.map +1 -1
  98. package/dist/commands/mcp/serve.js.map +1 -1
  99. package/dist/commands/migrate-openspec/materialize/active.js +27 -22
  100. package/dist/commands/migrate-openspec/materialize/active.js.map +1 -1
  101. package/dist/commands/migrate-openspec/materialize/stage.js +4 -3
  102. package/dist/commands/migrate-openspec/materialize/stage.js.map +1 -1
  103. package/dist/commands/migrate-openspec/materialize/target.js +2 -2
  104. package/dist/commands/migrate-openspec/materialize/target.js.map +1 -1
  105. package/dist/commands/migrate-openspec/openspec/decisions.js +9 -14
  106. package/dist/commands/migrate-openspec/openspec/decisions.js.map +1 -1
  107. package/dist/commands/migrate-openspec/openspec/error.js +7 -8
  108. package/dist/commands/migrate-openspec/openspec/error.js.map +1 -1
  109. package/dist/commands/migrate-openspec/openspec/mapping.js +1 -9
  110. package/dist/commands/migrate-openspec/openspec/mapping.js.map +1 -1
  111. package/dist/commands/migrate-openspec/openspec/paths.js +3 -6
  112. package/dist/commands/migrate-openspec/openspec/paths.js.map +1 -1
  113. package/dist/commands/new/capability-template.js +118 -0
  114. package/dist/commands/new/capability-template.js.map +1 -0
  115. package/dist/commands/new/commit.js +8 -22
  116. package/dist/commands/new/commit.js.map +1 -1
  117. package/dist/commands/new/modifies.js +206 -0
  118. package/dist/commands/new/modifies.js.map +1 -0
  119. package/dist/commands/new/new.js +59 -14
  120. package/dist/commands/new/new.js.map +1 -1
  121. package/dist/commands/new/templates.js +48 -124
  122. package/dist/commands/new/templates.js.map +1 -1
  123. package/dist/commands/open.js +3 -7
  124. package/dist/commands/open.js.map +1 -1
  125. package/dist/commands/policy/gate.js +27 -0
  126. package/dist/commands/policy/gate.js.map +1 -1
  127. package/dist/commands/rebase/plan.js +2 -2
  128. package/dist/commands/rebase/plan.js.map +1 -1
  129. package/dist/commands/rebase/rebase.js +60 -35
  130. package/dist/commands/rebase/rebase.js.map +1 -1
  131. package/dist/commands/seed/commit.js +55 -26
  132. package/dist/commands/seed/commit.js.map +1 -1
  133. package/dist/commands/seed/plan.js +158 -13
  134. package/dist/commands/seed/plan.js.map +1 -1
  135. package/dist/commands/seed/seed.js +13 -11
  136. package/dist/commands/seed/seed.js.map +1 -1
  137. package/dist/commands/show/feature.js +9 -5
  138. package/dist/commands/show/feature.js.map +1 -1
  139. package/dist/commands/show/introduced.js +157 -0
  140. package/dist/commands/show/introduced.js.map +1 -0
  141. package/dist/commands/show/marks.js +35 -6
  142. package/dist/commands/show/marks.js.map +1 -1
  143. package/dist/commands/show/service.js +41 -33
  144. package/dist/commands/show/service.js.map +1 -1
  145. package/dist/commands/show/show.js +17 -7
  146. package/dist/commands/show/show.js.map +1 -1
  147. package/dist/commands/status/fleet-next.js +90 -0
  148. package/dist/commands/status/fleet-next.js.map +1 -0
  149. package/dist/commands/status/json.js +2 -0
  150. package/dist/commands/status/json.js.map +1 -1
  151. package/dist/commands/status/print.js +89 -37
  152. package/dist/commands/status/print.js.map +1 -1
  153. package/dist/commands/status/status.js +3 -7
  154. package/dist/commands/status/status.js.map +1 -1
  155. package/dist/commands/steps/steps.js +103 -23
  156. package/dist/commands/steps/steps.js.map +1 -1
  157. package/dist/commands/subsystem/edit.js +7 -7
  158. package/dist/commands/subsystem/edit.js.map +1 -1
  159. package/dist/commands/subsystem/move.js +106 -46
  160. package/dist/commands/subsystem/move.js.map +1 -1
  161. package/dist/commands/subsystem/query.js +2 -4
  162. package/dist/commands/subsystem/query.js.map +1 -1
  163. package/dist/commands/subsystem/subsystem.js +4 -7
  164. package/dist/commands/subsystem/subsystem.js.map +1 -1
  165. package/dist/commands/subsystem/sync.js +289 -74
  166. package/dist/commands/subsystem/sync.js.map +1 -1
  167. package/dist/commands/subsystem/txn/exclude.js +132 -0
  168. package/dist/commands/subsystem/txn/exclude.js.map +1 -0
  169. package/dist/commands/subsystem/txn/links.js +128 -0
  170. package/dist/commands/subsystem/txn/links.js.map +1 -0
  171. package/dist/commands/subsystem/txn/report.js +174 -0
  172. package/dist/commands/subsystem/txn/report.js.map +1 -0
  173. package/dist/commands/subsystem/txn/txn.js +147 -45
  174. package/dist/commands/subsystem/txn/txn.js.map +1 -1
  175. package/dist/commands/subsystem/txn/views.js +200 -21
  176. package/dist/commands/subsystem/txn/views.js.map +1 -1
  177. package/dist/commands/tasks/actions.js +107 -0
  178. package/dist/commands/tasks/actions.js.map +1 -0
  179. package/dist/commands/tasks/render.js +253 -0
  180. package/dist/commands/tasks/render.js.map +1 -0
  181. package/dist/commands/tasks/tasks.js +119 -0
  182. package/dist/commands/tasks/tasks.js.map +1 -0
  183. package/dist/commands/unarchive/manifest.js +42 -26
  184. package/dist/commands/unarchive/manifest.js.map +1 -1
  185. package/dist/commands/unarchive/restore.js +83 -33
  186. package/dist/commands/unarchive/restore.js.map +1 -1
  187. package/dist/commands/unarchive/unarchive.js +22 -30
  188. package/dist/commands/unarchive/unarchive.js.map +1 -1
  189. package/dist/commands/validate/arch-coverage.js +78 -27
  190. package/dist/commands/validate/arch-coverage.js.map +1 -1
  191. package/dist/commands/validate/checks/fleet-shape.js +34 -126
  192. package/dist/commands/validate/checks/fleet-shape.js.map +1 -1
  193. package/dist/commands/validate/checks/health-deps.js +9 -6
  194. package/dist/commands/validate/checks/health-deps.js.map +1 -1
  195. package/dist/commands/validate/checks/introduced.js +102 -0
  196. package/dist/commands/validate/checks/introduced.js.map +1 -0
  197. package/dist/commands/validate/checks/requirements.js +18 -8
  198. package/dist/commands/validate/checks/requirements.js.map +1 -1
  199. package/dist/commands/validate/checks/sources.js +11 -2
  200. package/dist/commands/validate/checks/sources.js.map +1 -1
  201. package/dist/commands/validate/coverage/covers-after.js +105 -0
  202. package/dist/commands/validate/coverage/covers-after.js.map +1 -0
  203. package/dist/commands/validate/feature.js +26 -20
  204. package/dist/commands/validate/feature.js.map +1 -1
  205. package/dist/commands/validate/fleet/census.js +37 -13
  206. package/dist/commands/validate/fleet/census.js.map +1 -1
  207. package/dist/commands/validate/fleet/landscape.js +144 -126
  208. package/dist/commands/validate/fleet/landscape.js.map +1 -1
  209. package/dist/commands/validate/fleet/load.js +66 -0
  210. package/dist/commands/validate/fleet/load.js.map +1 -1
  211. package/dist/commands/validate/fleet/map/attest.js +98 -0
  212. package/dist/commands/validate/fleet/map/attest.js.map +1 -0
  213. package/dist/commands/validate/fleet/map/bindings.js +107 -0
  214. package/dist/commands/validate/fleet/map/bindings.js.map +1 -0
  215. package/dist/commands/validate/fleet/map/consumers.js +244 -0
  216. package/dist/commands/validate/fleet/map/consumers.js.map +1 -0
  217. package/dist/commands/validate/fleet/map/isolation.js +116 -0
  218. package/dist/commands/validate/fleet/map/isolation.js.map +1 -0
  219. package/dist/commands/validate/fleet/map/usecases.js +54 -0
  220. package/dist/commands/validate/fleet/map/usecases.js.map +1 -0
  221. package/dist/commands/validate/fleet/obligations.js +44 -14
  222. package/dist/commands/validate/fleet/obligations.js.map +1 -1
  223. package/dist/commands/validate/fleet/scorecard/print.js +10 -2
  224. package/dist/commands/validate/fleet/scorecard/print.js.map +1 -1
  225. package/dist/commands/validate/fleet/scorecard/scorecard.js +17 -11
  226. package/dist/commands/validate/fleet/scorecard/scorecard.js.map +1 -1
  227. package/dist/commands/validate/fleet/usecases/place.js.map +1 -1
  228. package/dist/commands/validate/fleet/views/fleet-project.js +217 -0
  229. package/dist/commands/validate/fleet/views/fleet-project.js.map +1 -0
  230. package/dist/commands/validate/fleet/views/ids.js +50 -15
  231. package/dist/commands/validate/fleet/views/ids.js.map +1 -1
  232. package/dist/commands/validate/fleet/views/projects.js +278 -0
  233. package/dist/commands/validate/fleet/views/projects.js.map +1 -0
  234. package/dist/commands/validate/fleet/views/root-documents.js +83 -0
  235. package/dist/commands/validate/fleet/views/root-documents.js.map +1 -0
  236. package/dist/commands/validate/fleet/views/stale.js +40 -47
  237. package/dist/commands/validate/fleet/views/stale.js.map +1 -1
  238. package/dist/commands/validate/links/corpus.js +1 -4
  239. package/dist/commands/validate/links/corpus.js.map +1 -1
  240. package/dist/commands/validate/links/glossary.js.map +1 -1
  241. package/dist/commands/validate/render/repeats.js +63 -0
  242. package/dist/commands/validate/render/repeats.js.map +1 -0
  243. package/dist/commands/validate/render/rollups.js +115 -0
  244. package/dist/commands/validate/render/rollups.js.map +1 -0
  245. package/dist/commands/validate/render/text.js +199 -0
  246. package/dist/commands/validate/render/text.js.map +1 -0
  247. package/dist/commands/validate/report.js +36 -160
  248. package/dist/commands/validate/report.js.map +1 -1
  249. package/dist/commands/validate/scope.js +113 -0
  250. package/dist/commands/validate/scope.js.map +1 -0
  251. package/dist/commands/validate/service/api.js +21 -107
  252. package/dist/commands/validate/service/api.js.map +1 -1
  253. package/dist/commands/validate/service/contracts/generated.js +134 -0
  254. package/dist/commands/validate/service/contracts/generated.js.map +1 -0
  255. package/dist/commands/validate/service/events/events.js +36 -14
  256. package/dist/commands/validate/service/events/events.js.map +1 -1
  257. package/dist/commands/validate/service/events/message-producers.js +1 -1
  258. package/dist/commands/validate/service/events/message-producers.js.map +1 -1
  259. package/dist/commands/validate/service/evidence-pins.js +56 -10
  260. package/dist/commands/validate/service/evidence-pins.js.map +1 -1
  261. package/dist/commands/validate/service/model/diverged.js +226 -0
  262. package/dist/commands/validate/service/model/diverged.js.map +1 -0
  263. package/dist/commands/validate/service/model/grade.js +163 -0
  264. package/dist/commands/validate/service/model/grade.js.map +1 -0
  265. package/dist/commands/validate/service/service.js +121 -61
  266. package/dist/commands/validate/service/service.js.map +1 -1
  267. package/dist/commands/validate/service/specs.js +88 -28
  268. package/dist/commands/validate/service/specs.js.map +1 -1
  269. package/dist/commands/validate/service/spine.js +38 -3
  270. package/dist/commands/validate/service/spine.js.map +1 -1
  271. package/dist/commands/validate/service/usecases/tags.js +113 -0
  272. package/dist/commands/validate/service/usecases/tags.js.map +1 -0
  273. package/dist/commands/validate/service/usecases/usecases.js +209 -0
  274. package/dist/commands/validate/service/usecases/usecases.js.map +1 -0
  275. package/dist/commands/validate/validate.js +85 -60
  276. package/dist/commands/validate/validate.js.map +1 -1
  277. package/dist/commands/verify/cross/diff.js +2 -6
  278. package/dist/commands/verify/cross/diff.js.map +1 -1
  279. package/dist/commands/verify/evidence/contract.js +1 -1
  280. package/dist/commands/verify/evidence/contract.js.map +1 -1
  281. package/dist/commands/verify/evidence/read.js +12 -3
  282. package/dist/commands/verify/evidence/read.js.map +1 -1
  283. package/dist/commands/verify/frozen.js +45 -23
  284. package/dist/commands/verify/frozen.js.map +1 -1
  285. package/dist/commands/verify/record.js +69 -17
  286. package/dist/commands/verify/record.js.map +1 -1
  287. package/dist/commands/verify/report.js +27 -44
  288. package/dist/commands/verify/report.js.map +1 -1
  289. package/dist/commands/verify/results.js +112 -30
  290. package/dist/commands/verify/results.js.map +1 -1
  291. package/dist/commands/verify/verify.js +55 -52
  292. package/dist/commands/verify/verify.js.map +1 -1
  293. package/dist/commands/vouch/pack/pack.js +2 -2
  294. package/dist/commands/vouch/pack/pack.js.map +1 -1
  295. package/dist/commands/vouch/pack/print.js +1 -6
  296. package/dist/commands/vouch/pack/print.js.map +1 -1
  297. package/dist/commands/vouch/pack/sections.js +1 -2
  298. package/dist/commands/vouch/pack/sections.js.map +1 -1
  299. package/dist/commands/vouch/run.js +26 -81
  300. package/dist/commands/vouch/run.js.map +1 -1
  301. package/dist/commands/vouch/sample/plan.js +20 -34
  302. package/dist/commands/vouch/sample/plan.js.map +1 -1
  303. package/dist/commands/vouch/vet/verify.js +39 -7
  304. package/dist/commands/vouch/vet/verify.js.map +1 -1
  305. package/dist/commands/vouch/vouch.js +10 -17
  306. package/dist/commands/vouch/vouch.js.map +1 -1
  307. package/dist/core/agent/agents-md/command-map.js +81 -106
  308. package/dist/core/agent/agents-md/command-map.js.map +1 -1
  309. package/dist/core/agent/agents-md/map/explain.js +21 -9
  310. package/dist/core/agent/agents-md/map/explain.js.map +1 -1
  311. package/dist/core/agent/agents-md/map/lenses/context.js +17 -8
  312. package/dist/core/agent/agents-md/map/lenses/context.js.map +1 -1
  313. package/dist/core/agent/agents-md/map/lenses/diff.js +33 -20
  314. package/dist/core/agent/agents-md/map/lenses/diff.js.map +1 -1
  315. package/dist/core/agent/agents-md/map/lenses/gate.js +13 -5
  316. package/dist/core/agent/agents-md/map/lenses/gate.js.map +1 -1
  317. package/dist/core/agent/agents-md/map/mcp.js +10 -7
  318. package/dist/core/agent/agents-md/map/mcp.js.map +1 -1
  319. package/dist/core/agent/agents-md/map/status.js +24 -8
  320. package/dist/core/agent/agents-md/map/status.js.map +1 -1
  321. package/dist/core/agent/agents-md/map/subsystem.js +80 -8
  322. package/dist/core/agent/agents-md/map/subsystem.js.map +1 -1
  323. package/dist/core/agent/agents-md/map/usecases.js +88 -10
  324. package/dist/core/agent/agents-md/map/usecases.js.map +1 -1
  325. package/dist/core/agent/agents-md/refusals.js +49 -22
  326. package/dist/core/agent/agents-md/refusals.js.map +1 -1
  327. package/dist/core/agent/agents-md.js +39 -6
  328. package/dist/core/agent/agents-md.js.map +1 -1
  329. package/dist/core/agent/agents-stamp.js +10 -0
  330. package/dist/core/agent/agents-stamp.js.map +1 -1
  331. package/dist/core/agent/protocol.js +1 -1
  332. package/dist/core/agent/protocol.js.map +1 -1
  333. package/dist/core/agent/scaffold.js +10 -15
  334. package/dist/core/agent/scaffold.js.map +1 -1
  335. package/dist/core/agent/support/report.js +46 -5
  336. package/dist/core/agent/support/report.js.map +1 -1
  337. package/dist/core/agent/tools/dialects.js +1 -0
  338. package/dist/core/agent/tools/dialects.js.map +1 -1
  339. package/dist/core/agent/tools/registry.js +41 -76
  340. package/dist/core/agent/tools/registry.js.map +1 -1
  341. package/dist/core/agent/workflows/adopt.js +158 -11
  342. package/dist/core/agent/workflows/adopt.js.map +1 -1
  343. package/dist/core/agent/workflows/check.js +78 -39
  344. package/dist/core/agent/workflows/check.js.map +1 -1
  345. package/dist/core/agent/workflows/closing.js +88 -27
  346. package/dist/core/agent/workflows/closing.js.map +1 -1
  347. package/dist/core/agent/workflows/feature.js +128 -13
  348. package/dist/core/agent/workflows/feature.js.map +1 -1
  349. package/dist/core/agent/workflows/implement.js +96 -13
  350. package/dist/core/agent/workflows/implement.js.map +1 -1
  351. package/dist/core/agent/workflows/reference/authoring.js +106 -4
  352. package/dist/core/agent/workflows/reference/authoring.js.map +1 -1
  353. package/dist/core/agent/workflows/reference/codes.js +8 -6
  354. package/dist/core/agent/workflows/reference/codes.js.map +1 -1
  355. package/dist/core/agent/workflows/reference/done-check.js +37 -15
  356. package/dist/core/agent/workflows/reference/done-check.js.map +1 -1
  357. package/dist/core/agent/workflows/reference/drawing/drawing.js +253 -0
  358. package/dist/core/agent/workflows/reference/drawing/drawing.js.map +1 -0
  359. package/dist/core/agent/workflows/reference/reference.js +6 -3
  360. package/dist/core/agent/workflows/reference/reference.js.map +1 -1
  361. package/dist/core/agent/workflows/reference/spine.js +68 -27
  362. package/dist/core/agent/workflows/reference/spine.js.map +1 -1
  363. package/dist/core/asyncapi/baseline/plan.js +14 -81
  364. package/dist/core/asyncapi/baseline/plan.js.map +1 -1
  365. package/dist/core/asyncapi/digest.js +30 -25
  366. package/dist/core/asyncapi/digest.js.map +1 -1
  367. package/dist/core/asyncapi/merge/components.js +5 -4
  368. package/dist/core/asyncapi/merge/components.js.map +1 -1
  369. package/dist/core/asyncapi/merge/error.js +7 -2
  370. package/dist/core/asyncapi/merge/error.js.map +1 -1
  371. package/dist/core/asyncapi/merge/markers.js +32 -50
  372. package/dist/core/asyncapi/merge/markers.js.map +1 -1
  373. package/dist/core/asyncapi/merge/merge.js +33 -53
  374. package/dist/core/asyncapi/merge/merge.js.map +1 -1
  375. package/dist/core/asyncapi/merge/pin.js +12 -36
  376. package/dist/core/asyncapi/merge/pin.js.map +1 -1
  377. package/dist/core/asyncapi/model.js.map +1 -1
  378. package/dist/core/asyncapi/read.js +36 -12
  379. package/dist/core/asyncapi/read.js.map +1 -1
  380. package/dist/core/brief/brief.js +96 -36
  381. package/dist/core/brief/brief.js.map +1 -1
  382. package/dist/core/brief/checks.js +138 -3
  383. package/dist/core/brief/checks.js.map +1 -1
  384. package/dist/core/brief/landscape.js +209 -130
  385. package/dist/core/brief/landscape.js.map +1 -1
  386. package/dist/core/brief/map/extend.js +84 -0
  387. package/dist/core/brief/map/extend.js.map +1 -0
  388. package/dist/core/brief/map/owed.js +266 -0
  389. package/dist/core/brief/map/owed.js.map +1 -0
  390. package/dist/core/brief/targets.js +109 -31
  391. package/dist/core/brief/targets.js.map +1 -1
  392. package/dist/core/brief/unchecked.js +14 -3
  393. package/dist/core/brief/unchecked.js.map +1 -1
  394. package/dist/core/c4/arch.js +90 -182
  395. package/dist/core/c4/arch.js.map +1 -1
  396. package/dist/core/c4/direction/direction.js +114 -0
  397. package/dist/core/c4/direction/direction.js.map +1 -0
  398. package/dist/core/c4/likec4.js +169 -14
  399. package/dist/core/c4/likec4.js.map +1 -1
  400. package/dist/core/c4/locate/unlocated.js +150 -0
  401. package/dist/core/c4/locate/unlocated.js.map +1 -0
  402. package/dist/core/c4/parsed/deployment.js +160 -0
  403. package/dist/core/c4/parsed/deployment.js.map +1 -0
  404. package/dist/core/c4/parsed/dynamic-views.js.map +1 -1
  405. package/dist/core/c4/parsed/values.js +54 -1
  406. package/dist/core/c4/parsed/values.js.map +1 -1
  407. package/dist/core/c4/parsed/view-ids.js +39 -1
  408. package/dist/core/c4/parsed/view-ids.js.map +1 -1
  409. package/dist/core/c4/prefetch/fleet.js +134 -0
  410. package/dist/core/c4/prefetch/fleet.js.map +1 -0
  411. package/dist/core/c4/project/architecture.js +123 -7
  412. package/dist/core/c4/project/architecture.js.map +1 -1
  413. package/dist/core/c4/project/batch.js +140 -0
  414. package/dist/core/c4/project/batch.js.map +1 -0
  415. package/dist/core/c4/project/documents.js +43 -12
  416. package/dist/core/c4/project/documents.js.map +1 -1
  417. package/dist/core/c4/project/load.js +79 -43
  418. package/dist/core/c4/project/load.js.map +1 -1
  419. package/dist/core/c4/project/staged.js +277 -0
  420. package/dist/core/c4/project/staged.js.map +1 -0
  421. package/dist/core/c4/resolve/attested.js +0 -0
  422. package/dist/core/c4/resolve/attested.js.map +1 -0
  423. package/dist/core/c4/resolve/external.js +51 -0
  424. package/dist/core/c4/resolve/external.js.map +1 -0
  425. package/dist/core/c4/resolve/service.js +78 -17
  426. package/dist/core/c4/resolve/service.js.map +1 -1
  427. package/dist/core/c4/resolve/steps.js +290 -0
  428. package/dist/core/c4/resolve/steps.js.map +1 -0
  429. package/dist/core/c4/resolve/systems.js +154 -0
  430. package/dist/core/c4/resolve/systems.js.map +1 -0
  431. package/dist/core/c4/root-project/exclude.js +352 -0
  432. package/dist/core/c4/root-project/exclude.js.map +1 -0
  433. package/dist/core/c4/seed/template.js +65 -1
  434. package/dist/core/c4/seed/template.js.map +1 -1
  435. package/dist/core/c4/service-model/created/models.js +96 -0
  436. package/dist/core/c4/service-model/created/models.js.map +1 -0
  437. package/dist/core/c4/service-model/documents.js +47 -0
  438. package/dist/core/c4/service-model/documents.js.map +1 -0
  439. package/dist/core/c4/service-model/fleet/extending.js +82 -0
  440. package/dist/core/c4/service-model/fleet/extending.js.map +1 -0
  441. package/dist/core/c4/service-model/load.js +165 -0
  442. package/dist/core/c4/service-model/load.js.map +1 -0
  443. package/dist/core/c4/service-model/renderer.js +128 -0
  444. package/dist/core/c4/service-model/renderer.js.map +1 -0
  445. package/dist/core/c4/service-model/shape.js +106 -0
  446. package/dist/core/c4/service-model/shape.js.map +1 -0
  447. package/dist/core/c4/service-model/slice.js +188 -0
  448. package/dist/core/c4/service-model/slice.js.map +1 -0
  449. package/dist/core/c4/source-mask.js +297 -10
  450. package/dist/core/c4/source-mask.js.map +1 -1
  451. package/dist/core/c4/source-scan.js +222 -141
  452. package/dist/core/c4/source-scan.js.map +1 -1
  453. package/dist/core/c4/splice/authored-source.js +79 -13
  454. package/dist/core/c4/splice/authored-source.js.map +1 -1
  455. package/dist/core/c4/splice/contract.js +20 -0
  456. package/dist/core/c4/splice/contract.js.map +1 -1
  457. package/dist/core/c4/splice/delta-blocks.js +20 -20
  458. package/dist/core/c4/splice/delta-blocks.js.map +1 -1
  459. package/dist/core/c4/splice/identity/declared.js +87 -0
  460. package/dist/core/c4/splice/identity/declared.js.map +1 -0
  461. package/dist/core/c4/splice/identity/edges.js +37 -0
  462. package/dist/core/c4/splice/identity/edges.js.map +1 -1
  463. package/dist/core/c4/splice/identity/existing.js +80 -0
  464. package/dist/core/c4/splice/identity/existing.js.map +1 -0
  465. package/dist/core/c4/splice/identity/interior.js +80 -0
  466. package/dist/core/c4/splice/identity/interior.js.map +1 -0
  467. package/dist/core/c4/splice/identity/owner.js +50 -0
  468. package/dist/core/c4/splice/identity/owner.js.map +1 -0
  469. package/dist/core/c4/splice/landscape-merge.js +182 -114
  470. package/dist/core/c4/splice/landscape-merge.js.map +1 -1
  471. package/dist/core/c4/splice/model/merge.js +151 -0
  472. package/dist/core/c4/splice/model/merge.js.map +1 -0
  473. package/dist/core/c4/splice/placement.js +160 -56
  474. package/dist/core/c4/splice/placement.js.map +1 -1
  475. package/dist/core/c4/splice/text/spot.js +131 -0
  476. package/dist/core/c4/splice/text/spot.js.map +1 -0
  477. package/dist/core/c4/workspace.js +13 -19
  478. package/dist/core/c4/workspace.js.map +1 -1
  479. package/dist/core/capabilities/capabilities.js +6 -6
  480. package/dist/core/capabilities/capabilities.js.map +1 -1
  481. package/dist/core/capabilities/delta/doc.js +7 -10
  482. package/dist/core/capabilities/delta/doc.js.map +1 -1
  483. package/dist/core/capabilities/delta/uncovered.js +2 -2
  484. package/dist/core/capabilities/delta/uncovered.js.map +1 -1
  485. package/dist/core/capabilities/findings.js +18 -22
  486. package/dist/core/capabilities/findings.js.map +1 -1
  487. package/dist/core/capabilities/realizes/findings.js +12 -19
  488. package/dist/core/capabilities/realizes/findings.js.map +1 -1
  489. package/dist/core/capabilities/realizes/join.js +0 -20
  490. package/dist/core/capabilities/realizes/join.js.map +1 -1
  491. package/dist/core/capabilities/rollup.js +6 -0
  492. package/dist/core/capabilities/rollup.js.map +1 -1
  493. package/dist/core/capabilities/tree.js +6 -28
  494. package/dist/core/capabilities/tree.js.map +1 -1
  495. package/dist/core/capabilities/usecase-join.js +3 -13
  496. package/dist/core/capabilities/usecase-join.js.map +1 -1
  497. package/dist/core/coherence/authoring/scaffold.js +11 -3
  498. package/dist/core/coherence/authoring/scaffold.js.map +1 -1
  499. package/dist/core/coherence/authoring/sentinels.js +2 -1
  500. package/dist/core/coherence/authoring/sentinels.js.map +1 -1
  501. package/dist/core/coherence/calls/called.js +52 -0
  502. package/dist/core/coherence/calls/called.js.map +1 -0
  503. package/dist/core/coherence/coherence.js +103 -22
  504. package/dist/core/coherence/coherence.js.map +1 -1
  505. package/dist/core/coherence/consumed/operations.js +70 -0
  506. package/dist/core/coherence/consumed/operations.js.map +1 -0
  507. package/dist/core/coherence/consumed/refusal.js +38 -0
  508. package/dist/core/coherence/consumed/refusal.js.map +1 -0
  509. package/dist/core/coherence/covers/health.js +85 -0
  510. package/dist/core/coherence/covers/health.js.map +1 -0
  511. package/dist/core/coherence/declared.js +60 -34
  512. package/dist/core/coherence/declared.js.map +1 -1
  513. package/dist/core/coherence/events/declared.js +44 -59
  514. package/dist/core/coherence/events/declared.js.map +1 -1
  515. package/dist/core/coherence/events/events.js +147 -16
  516. package/dist/core/coherence/events/events.js.map +1 -1
  517. package/dist/core/coherence/events/grades.js +31 -8
  518. package/dist/core/coherence/events/grades.js.map +1 -1
  519. package/dist/core/coherence/events/lookups.js +28 -87
  520. package/dist/core/coherence/events/lookups.js.map +1 -1
  521. package/dist/core/coherence/events/produced.js +100 -0
  522. package/dist/core/coherence/events/produced.js.map +1 -0
  523. package/dist/core/coherence/lookups.js +18 -78
  524. package/dist/core/coherence/lookups.js.map +1 -1
  525. package/dist/core/coherence/retired/archived.js +285 -0
  526. package/dist/core/coherence/retired/archived.js.map +1 -0
  527. package/dist/core/coherence/retired/event-pair.js +62 -0
  528. package/dist/core/coherence/retired/event-pair.js.map +1 -0
  529. package/dist/core/coherence/retired/merged.js +79 -0
  530. package/dist/core/coherence/retired/merged.js.map +1 -0
  531. package/dist/core/coherence/retired/retirement.js +49 -0
  532. package/dist/core/coherence/retired/retirement.js.map +1 -0
  533. package/dist/core/coherence/retired/revival/arrivals.js +131 -0
  534. package/dist/core/coherence/retired/revival/arrivals.js.map +1 -0
  535. package/dist/core/coherence/retired/revival/revived.js +297 -0
  536. package/dist/core/coherence/retired/revival/revived.js.map +1 -0
  537. package/dist/core/consumers/after.js +113 -0
  538. package/dist/core/consumers/after.js.map +1 -0
  539. package/dist/core/consumers/consumers.js +296 -0
  540. package/dist/core/consumers/consumers.js.map +1 -0
  541. package/dist/core/consumers/current.js +211 -0
  542. package/dist/core/consumers/current.js.map +1 -0
  543. package/dist/core/consumers/scan.js +46 -0
  544. package/dist/core/consumers/scan.js.map +1 -0
  545. package/dist/core/consumers/state.js +27 -0
  546. package/dist/core/consumers/state.js.map +1 -0
  547. package/dist/core/delta/delta.js +51 -6
  548. package/dist/core/delta/delta.js.map +1 -1
  549. package/dist/core/dependencies/fanin.js +2 -2
  550. package/dist/core/dependencies/fanin.js.map +1 -1
  551. package/dist/core/deployment/delta.js +191 -0
  552. package/dist/core/deployment/delta.js.map +1 -0
  553. package/dist/core/deployment/objects.js +145 -0
  554. package/dist/core/deployment/objects.js.map +1 -0
  555. package/dist/core/diff/base-git.js +94 -12
  556. package/dist/core/diff/base-git.js.map +1 -1
  557. package/dist/core/diff/base-state.js +49 -21
  558. package/dist/core/diff/base-state.js.map +1 -1
  559. package/dist/core/diff/joins.js +136 -0
  560. package/dist/core/diff/joins.js.map +1 -0
  561. package/dist/core/diff/scope/changed-paths.js +22 -6
  562. package/dist/core/diff/scope/changed-paths.js.map +1 -1
  563. package/dist/core/diff/scope/edges.js +82 -0
  564. package/dist/core/diff/scope/edges.js.map +1 -0
  565. package/dist/core/diff/semantic.js +100 -31
  566. package/dist/core/diff/semantic.js.map +1 -1
  567. package/dist/core/docs.js +31 -22
  568. package/dist/core/docs.js.map +1 -1
  569. package/dist/core/doctor/agents.js +34 -18
  570. package/dist/core/doctor/agents.js.map +1 -1
  571. package/dist/core/doctor/config.js +7 -3
  572. package/dist/core/doctor/config.js.map +1 -1
  573. package/dist/core/doctor/doctor.js +91 -11
  574. package/dist/core/doctor/doctor.js.map +1 -1
  575. package/dist/core/doctor/report.js.map +1 -1
  576. package/dist/core/doctor/reports/scan.js +242 -0
  577. package/dist/core/doctor/reports/scan.js.map +1 -0
  578. package/dist/core/document/apply.js +158 -11
  579. package/dist/core/document/apply.js.map +1 -1
  580. package/dist/core/document/frontmatter.js +55 -0
  581. package/dist/core/document/frontmatter.js.map +1 -1
  582. package/dist/core/document/parse.js +29 -6
  583. package/dist/core/document/parse.js.map +1 -1
  584. package/dist/core/document/scenarios.js +17 -0
  585. package/dist/core/document/scenarios.js.map +1 -1
  586. package/dist/core/document/spec.js +4 -11
  587. package/dist/core/document/spec.js.map +1 -1
  588. package/dist/core/envelope/config.js +10 -0
  589. package/dist/core/envelope/config.js.map +1 -1
  590. package/dist/core/envelope/json.js +34 -0
  591. package/dist/core/envelope/json.js.map +1 -1
  592. package/dist/core/explain/families.js +26 -21
  593. package/dist/core/explain/families.js.map +1 -1
  594. package/dist/core/explain/lookup.js +14 -1
  595. package/dist/core/explain/lookup.js.map +1 -1
  596. package/dist/core/explain/refusals.js +5 -5
  597. package/dist/core/explain/refusals.js.map +1 -1
  598. package/dist/core/explain/terms/documents.js +227 -0
  599. package/dist/core/explain/terms/documents.js.map +1 -0
  600. package/dist/core/explain/terms/done-check.js +144 -0
  601. package/dist/core/explain/terms/done-check.js.map +1 -0
  602. package/dist/core/explain/terms/entry.js +14 -0
  603. package/dist/core/explain/terms/entry.js.map +1 -0
  604. package/dist/core/explain/terms/stages.js +71 -0
  605. package/dist/core/explain/terms/stages.js.map +1 -0
  606. package/dist/core/explain/terms/tasks.js +97 -0
  607. package/dist/core/explain/terms/tasks.js.map +1 -0
  608. package/dist/core/explain/terms.js +68 -109
  609. package/dist/core/explain/terms.js.map +1 -1
  610. package/dist/core/explore/explore.js +40 -10
  611. package/dist/core/explore/explore.js.map +1 -1
  612. package/dist/core/fleet-context.js +81 -95
  613. package/dist/core/fleet-context.js.map +1 -1
  614. package/dist/core/gate/checks.js +11 -4
  615. package/dist/core/gate/checks.js.map +1 -1
  616. package/dist/core/gate/partners.js +69 -28
  617. package/dist/core/gate/partners.js.map +1 -1
  618. package/dist/core/gate/report.js.map +1 -1
  619. package/dist/core/gate/verification.js +75 -12
  620. package/dist/core/gate/verification.js.map +1 -1
  621. package/dist/core/gherkin/stale.js +13 -37
  622. package/dist/core/gherkin/stale.js.map +1 -1
  623. package/dist/core/glossary/delta.js +10 -7
  624. package/dist/core/glossary/delta.js.map +1 -1
  625. package/dist/core/glossary/tree.js +6 -19
  626. package/dist/core/glossary/tree.js.map +1 -1
  627. package/dist/core/kernel/concurrency.js +19 -0
  628. package/dist/core/kernel/concurrency.js.map +1 -1
  629. package/dist/core/kernel/ids/fqn/ancestors.js +65 -0
  630. package/dist/core/kernel/ids/fqn/ancestors.js.map +1 -0
  631. package/dist/core/kernel/path-safety.js +38 -0
  632. package/dist/core/kernel/path-safety.js.map +1 -1
  633. package/dist/core/kernel/records.js +11 -0
  634. package/dist/core/kernel/records.js.map +1 -1
  635. package/dist/core/links/backlinks.js +1 -3
  636. package/dist/core/links/backlinks.js.map +1 -1
  637. package/dist/core/links/corpus.js +51 -37
  638. package/dist/core/links/corpus.js.map +1 -1
  639. package/dist/core/links/findings.js.map +1 -1
  640. package/dist/core/links/parse.js +38 -9
  641. package/dist/core/links/parse.js.map +1 -1
  642. package/dist/core/mcp/argv.js +101 -0
  643. package/dist/core/mcp/argv.js.map +1 -1
  644. package/dist/core/mcp/author-tools.js +2 -1
  645. package/dist/core/mcp/author-tools.js.map +1 -1
  646. package/dist/core/mcp/protocol.js +2 -2
  647. package/dist/core/mcp/protocol.js.map +1 -1
  648. package/dist/core/mcp/tools.js +43 -33
  649. package/dist/core/mcp/tools.js.map +1 -1
  650. package/dist/core/openapi/baseline/gate.js +53 -12
  651. package/dist/core/openapi/baseline/gate.js.map +1 -1
  652. package/dist/core/openapi/baseline/plan.js +40 -10
  653. package/dist/core/openapi/baseline/plan.js.map +1 -1
  654. package/dist/core/openapi/baseline/record.js +0 -1
  655. package/dist/core/openapi/baseline/record.js.map +1 -1
  656. package/dist/core/openapi/contract-text.js +33 -0
  657. package/dist/core/openapi/contract-text.js.map +1 -0
  658. package/dist/core/openapi/contract-tree.js +301 -0
  659. package/dist/core/openapi/contract-tree.js.map +1 -0
  660. package/dist/core/openapi/depth.js +38 -24
  661. package/dist/core/openapi/depth.js.map +1 -1
  662. package/dist/core/openapi/digest.js +52 -2
  663. package/dist/core/openapi/digest.js.map +1 -1
  664. package/dist/core/openapi/doc.js +12 -4
  665. package/dist/core/openapi/doc.js.map +1 -1
  666. package/dist/core/openapi/merge/components.js +25 -60
  667. package/dist/core/openapi/merge/components.js.map +1 -1
  668. package/dist/core/openapi/merge/error.js +3 -13
  669. package/dist/core/openapi/merge/error.js.map +1 -1
  670. package/dist/core/openapi/merge/markers.js +26 -30
  671. package/dist/core/openapi/merge/markers.js.map +1 -1
  672. package/dist/core/openapi/merge/merge.js +28 -52
  673. package/dist/core/openapi/merge/merge.js.map +1 -1
  674. package/dist/core/openapi/merge/pin.js +17 -35
  675. package/dist/core/openapi/merge/pin.js.map +1 -1
  676. package/dist/core/openspec/decide/verdict.js.map +1 -1
  677. package/dist/core/openspec/inventory.js +4 -5
  678. package/dist/core/openspec/inventory.js.map +1 -1
  679. package/dist/core/openspec/model/mapping.js +30 -28
  680. package/dist/core/openspec/model/mapping.js.map +1 -1
  681. package/dist/core/openspec/model/model.js +12 -7
  682. package/dist/core/openspec/model/model.js.map +1 -1
  683. package/dist/core/openspec/scan/changes.js +10 -4
  684. package/dist/core/openspec/scan/changes.js.map +1 -1
  685. package/dist/core/openspec/scan/config.js +7 -16
  686. package/dist/core/openspec/scan/config.js.map +1 -1
  687. package/dist/core/openspec/scan/shape.js +63 -19
  688. package/dist/core/openspec/scan/shape.js.map +1 -1
  689. package/dist/core/openspec/scan/walk.js +21 -38
  690. package/dist/core/openspec/scan/walk.js.map +1 -1
  691. package/dist/core/pack/living.js +43 -4
  692. package/dist/core/pack/living.js.map +1 -1
  693. package/dist/core/pack/pack.js +50 -6
  694. package/dist/core/pack/pack.js.map +1 -1
  695. package/dist/core/projection/arch-slice.js +2 -2
  696. package/dist/core/projection/arch-slice.js.map +1 -1
  697. package/dist/core/projection/introduced.js +14 -0
  698. package/dist/core/projection/introduced.js.map +1 -0
  699. package/dist/core/provenance/findings.js +48 -12
  700. package/dist/core/provenance/findings.js.map +1 -1
  701. package/dist/core/provenance/git.js +33 -57
  702. package/dist/core/provenance/git.js.map +1 -1
  703. package/dist/core/provenance/gitq/moves.js +71 -114
  704. package/dist/core/provenance/gitq/moves.js.map +1 -1
  705. package/dist/core/provenance/gitq/vouched-ancestor.js +2 -2
  706. package/dist/core/provenance/gitq/vouched-ancestor.js.map +1 -1
  707. package/dist/core/provenance/sources.js +23 -6
  708. package/dist/core/provenance/sources.js.map +1 -1
  709. package/dist/core/provenance/stamp.js +5 -17
  710. package/dist/core/provenance/stamp.js.map +1 -1
  711. package/dist/core/repo/authored/paths.js +18 -0
  712. package/dist/core/repo/authored/paths.js.map +1 -1
  713. package/dist/core/repo/entries.js.map +1 -1
  714. package/dist/core/repo/paths.js +92 -6
  715. package/dist/core/repo/paths.js.map +1 -1
  716. package/dist/core/repo/repo.js +74 -14
  717. package/dist/core/repo/repo.js.map +1 -1
  718. package/dist/core/repo/tree/find.js +12 -3
  719. package/dist/core/repo/tree/find.js.map +1 -1
  720. package/dist/core/repo/tree/fs.js +27 -1
  721. package/dist/core/repo/tree/fs.js.map +1 -1
  722. package/dist/core/repo/tree/render/body.js +258 -0
  723. package/dist/core/repo/tree/render/body.js.map +1 -0
  724. package/dist/core/repo/tree/render/projects.js +182 -0
  725. package/dist/core/repo/tree/render/projects.js.map +1 -0
  726. package/dist/core/repo/tree/render/service/header.js +125 -0
  727. package/dist/core/repo/tree/render/service/header.js.map +1 -0
  728. package/dist/core/repo/tree/render/service/peers.js +28 -0
  729. package/dist/core/repo/tree/render/service/peers.js.map +1 -0
  730. package/dist/core/repo/tree/render/service/view-id.js +67 -0
  731. package/dist/core/repo/tree/render/service/view-id.js.map +1 -0
  732. package/dist/core/repo/tree/render/service/views.js +78 -0
  733. package/dist/core/repo/tree/render/service/views.js.map +1 -0
  734. package/dist/core/repo/tree/render/stale.js +42 -0
  735. package/dist/core/repo/tree/render/stale.js.map +1 -0
  736. package/dist/core/repo/tree/render/text.js +84 -0
  737. package/dist/core/repo/tree/render/text.js.map +1 -0
  738. package/dist/core/repo/tree/render/views.js +293 -0
  739. package/dist/core/repo/tree/render/views.js.map +1 -0
  740. package/dist/core/repo/tree/walk.js +53 -32
  741. package/dist/core/repo/tree/walk.js.map +1 -1
  742. package/dist/core/results.js +47 -12
  743. package/dist/core/results.js.map +1 -1
  744. package/dist/core/scaffold/landscape.js +121 -13
  745. package/dist/core/scaffold/landscape.js.map +1 -1
  746. package/dist/core/scaffold/legacy.js +271 -0
  747. package/dist/core/scaffold/legacy.js.map +1 -0
  748. package/dist/core/staging/commit.js +26 -15
  749. package/dist/core/staging/commit.js.map +1 -1
  750. package/dist/core/staging/lock.js +74 -12
  751. package/dist/core/staging/lock.js.map +1 -1
  752. package/dist/core/staging/recovery/intent.js +2 -5
  753. package/dist/core/staging/recovery/intent.js.map +1 -1
  754. package/dist/core/staging/recovery/recover.js +84 -6
  755. package/dist/core/staging/recovery/recover.js.map +1 -1
  756. package/dist/core/staging/snapshot/manifest.js +188 -0
  757. package/dist/core/staging/snapshot/manifest.js.map +1 -0
  758. package/dist/core/staging/{snapshot.js → snapshot/snapshot.js} +39 -45
  759. package/dist/core/staging/snapshot/snapshot.js.map +1 -0
  760. package/dist/core/staging/txn/forward.js +24 -14
  761. package/dist/core/staging/txn/forward.js.map +1 -1
  762. package/dist/core/staging/writes.js.map +1 -1
  763. package/dist/core/status/actions/execution.js +11 -0
  764. package/dist/core/status/actions/execution.js.map +1 -1
  765. package/dist/core/status/contracts.js +39 -15
  766. package/dist/core/status/contracts.js.map +1 -1
  767. package/dist/core/status/feature/artifacts.js +33 -8
  768. package/dist/core/status/feature/artifacts.js.map +1 -1
  769. package/dist/core/status/feature/feature.js +24 -17
  770. package/dist/core/status/feature/feature.js.map +1 -1
  771. package/dist/core/status/feature/next.js +20 -7
  772. package/dist/core/status/feature/next.js.map +1 -1
  773. package/dist/core/status/feature/words.js +96 -0
  774. package/dist/core/status/feature/words.js.map +1 -0
  775. package/dist/core/status/fleet/fleet.js +43 -14
  776. package/dist/core/status/fleet/fleet.js.map +1 -1
  777. package/dist/core/status/fleet/next.js +153 -58
  778. package/dist/core/status/fleet/next.js.map +1 -1
  779. package/dist/core/status/report.js.map +1 -1
  780. package/dist/core/status/scan.js.map +1 -1
  781. package/dist/core/status/verification.js +30 -15
  782. package/dist/core/status/verification.js.map +1 -1
  783. package/dist/core/tasks/packet.js +199 -0
  784. package/dist/core/tasks/packet.js.map +1 -0
  785. package/dist/core/tasks/record.js +43 -0
  786. package/dist/core/tasks/record.js.map +1 -0
  787. package/dist/core/tasks/sources.js +181 -0
  788. package/dist/core/tasks/sources.js.map +1 -0
  789. package/dist/core/tasks/stamps.js +76 -0
  790. package/dist/core/tasks/stamps.js.map +1 -0
  791. package/dist/core/tasks/unit.js +0 -0
  792. package/dist/core/tasks/unit.js.map +1 -0
  793. package/dist/core/usecases/capability.js +11 -14
  794. package/dist/core/usecases/capability.js.map +1 -1
  795. package/dist/core/usecases/delta/claims.js +31 -7
  796. package/dist/core/usecases/delta/claims.js.map +1 -1
  797. package/dist/core/usecases/delta/flows.js +5 -7
  798. package/dist/core/usecases/delta/flows.js.map +1 -1
  799. package/dist/core/usecases/delta/modified.js +315 -0
  800. package/dist/core/usecases/delta/modified.js.map +1 -0
  801. package/dist/core/usecases/delta/overlay.js +32 -191
  802. package/dist/core/usecases/delta/overlay.js.map +1 -1
  803. package/dist/core/usecases/fleet.js +195 -36
  804. package/dist/core/usecases/fleet.js.map +1 -1
  805. package/dist/{commands/validate/fleet/usecases → core/usecases/grade}/capability-tag.js +8 -9
  806. package/dist/core/usecases/grade/capability-tag.js.map +1 -0
  807. package/dist/core/usecases/grade/feature.js +88 -0
  808. package/dist/core/usecases/grade/feature.js.map +1 -0
  809. package/dist/{commands/validate/fleet/usecases → core/usecases/grade}/requirement-tag.js +3 -4
  810. package/dist/core/usecases/grade/requirement-tag.js.map +1 -0
  811. package/dist/{commands/validate/fleet/usecases → core/usecases/grade}/steps.js +102 -33
  812. package/dist/core/usecases/grade/steps.js.map +1 -0
  813. package/dist/{commands/validate/fleet/usecases → core/usecases/grade}/usecases.js +23 -10
  814. package/dist/core/usecases/grade/usecases.js.map +1 -0
  815. package/dist/core/usecases/operations.js +26 -14
  816. package/dist/core/usecases/operations.js.map +1 -1
  817. package/dist/core/usecases/place.js.map +1 -1
  818. package/dist/core/usecases/service/exclude.js +119 -0
  819. package/dist/core/usecases/service/exclude.js.map +1 -0
  820. package/dist/core/usecases/service/flows.js +164 -0
  821. package/dist/core/usecases/service/flows.js.map +1 -0
  822. package/dist/core/usecases/suites/participants.js +83 -0
  823. package/dist/core/usecases/suites/participants.js.map +1 -0
  824. package/dist/core/usecases/suites/suites.js +45 -0
  825. package/dist/core/usecases/suites/suites.js.map +1 -0
  826. package/dist/core/verify/answers.js +12 -5
  827. package/dist/core/verify/answers.js.map +1 -1
  828. package/dist/core/verify/build.js +102 -82
  829. package/dist/core/verify/build.js.map +1 -1
  830. package/dist/core/verify/checklist.js +70 -12
  831. package/dist/core/verify/checklist.js.map +1 -1
  832. package/dist/core/verify/location.js +67 -0
  833. package/dist/core/verify/location.js.map +1 -0
  834. package/dist/core/verify/pins/lint.js +3 -2
  835. package/dist/core/verify/pins/lint.js.map +1 -1
  836. package/dist/core/verify/pins/pin.js +1 -1
  837. package/dist/core/verify/pins/pin.js.map +1 -1
  838. package/dist/core/verify/read/file.js +224 -0
  839. package/dist/core/verify/read/file.js.map +1 -0
  840. package/dist/core/verify/{file.js → read/shape.js} +16 -104
  841. package/dist/core/verify/read/shape.js.map +1 -0
  842. package/dist/core/verify/read/union.js +105 -0
  843. package/dist/core/verify/read/union.js.map +1 -0
  844. package/dist/core/verify/record.js +35 -12
  845. package/dist/core/verify/record.js.map +1 -1
  846. package/dist/core/verify/store/commit.js +40 -30
  847. package/dist/core/verify/store/commit.js.map +1 -1
  848. package/dist/core/verify/store/render.js +8 -4
  849. package/dist/core/verify/store/render.js.map +1 -1
  850. package/dist/core/vocabulary/issue.js +4 -0
  851. package/dist/core/vocabulary/issue.js.map +1 -1
  852. package/dist/core/vocabulary/maturity.js +75 -4
  853. package/dist/core/vocabulary/maturity.js.map +1 -1
  854. package/dist/core/vocabulary/report.js +16 -1
  855. package/dist/core/vocabulary/report.js.map +1 -1
  856. package/examples/README.md +54 -11
  857. package/examples/docs/architecture/landscape.likec4 +62 -6
  858. package/examples/docs/architecture/services.likec4 +70 -0
  859. package/examples/docs/architecture/subsystems.likec4 +7 -0
  860. package/examples/docs/architecture/usecases/order-notification.likec4 +16 -7
  861. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-service/asyncapi.yaml +11 -8
  862. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/openapi.yaml +6 -6
  863. package/examples/docs/features/FEAT-112-retire-order-v1/specs/order-service/openapi.yaml +4 -1
  864. package/examples/docs/features/archive/FEAT-088-refunds/specs/payment-service/openapi.yaml +13 -10
  865. package/examples/docs/likec4.config.json +0 -1
  866. package/examples/docs/services/checkout-web/model.likec4 +39 -56
  867. package/examples/docs/services/order-service/arch.spec.md +13 -6
  868. package/examples/docs/services/order-service/asyncapi.yaml +3 -2
  869. package/examples/docs/services/order-service/model.likec4 +58 -70
  870. package/examples/docs/services/payment-service/arch.spec.md +7 -4
  871. package/examples/docs/services/payment-service/model.likec4 +38 -37
  872. package/examples/docs/services/platform/identity-service/arch.spec.md +7 -4
  873. package/examples/docs/services/platform/identity-service/model.likec4 +35 -37
  874. package/examples/docs/services/platform/notification-service/asyncapi.yaml +2 -1
  875. package/examples/docs/services/platform/notification-service/health.yaml +8 -3
  876. package/examples/docs/services/platform/notification-service/model.likec4 +43 -64
  877. package/package.json +1 -1
  878. package/dist/commands/validate/checks/vocabulary.js +0 -31
  879. package/dist/commands/validate/checks/vocabulary.js.map +0 -1
  880. package/dist/commands/validate/fleet/usecases/capability-tag.js.map +0 -1
  881. package/dist/commands/validate/fleet/usecases/requirement-tag.js.map +0 -1
  882. package/dist/commands/validate/fleet/usecases/steps.js.map +0 -1
  883. package/dist/commands/validate/fleet/usecases/usecases.js.map +0 -1
  884. package/dist/core/agent/agents-md/artifacts.js +0 -220
  885. package/dist/core/agent/agents-md/artifacts.js.map +0 -1
  886. package/dist/core/agent/agents-md/cycle.js +0 -165
  887. package/dist/core/agent/agents-md/cycle.js.map +0 -1
  888. package/dist/core/agent/agents-md/shipped/archive-gate.js +0 -98
  889. package/dist/core/agent/agents-md/shipped/archive-gate.js.map +0 -1
  890. package/dist/core/agent/agents-md/spine.js +0 -40
  891. package/dist/core/agent/agents-md/spine.js.map +0 -1
  892. package/dist/core/coherence/events/merged.js +0 -40
  893. package/dist/core/coherence/events/merged.js.map +0 -1
  894. package/dist/core/diff/current-state.js +0 -96
  895. package/dist/core/diff/current-state.js.map +0 -1
  896. package/dist/core/diff/victims.js +0 -247
  897. package/dist/core/diff/victims.js.map +0 -1
  898. package/dist/core/repo/tree/views.js +0 -172
  899. package/dist/core/repo/tree/views.js.map +0 -1
  900. package/dist/core/staging/snapshot.js.map +0 -1
  901. package/dist/core/verify/file.js.map +0 -1
@@ -9,6 +9,7 @@
9
9
  * The two change for different reasons: a new artifact edits the first, better
10
10
  * advice to a new fleet edits the second.
11
11
  */
12
+ import { LEGACY_LANDSCAPE_STUBS } from "./legacy.js";
12
13
  /**
13
14
  * The fleet map, empty but valid.
14
15
  *
@@ -38,6 +39,20 @@
38
39
  * The `views` block below has a deliberate second copy: `core/c4/seed/template.ts` emits the
39
40
  * same two views into a seeded landscape (two strikes; extract on a third), and test/seed.test.ts
40
41
  * compares the two blocks byte for byte — comments included — so whichever copy drifts fails.
42
+ *
43
+ * The seven RELATIONSHIP kinds are scaffolded for the element kinds' reason:
44
+ * they are vocabulary, not a guess about this fleet. Declared here, every
45
+ * extending model and every adoption borrows them, so the first edge anybody
46
+ * draws can say what it carries and which way it points. A real fleet drawn
47
+ * without them ended with every arrow pointing into its broker and its stores,
48
+ * because deployment configuration says only that two things are connected. A
49
+ * declaration here also keeps a feature archivable: the archive copies a
50
+ * delta's edge into this file and never a declaration, so a kind this file
51
+ * lacks refuses the merge (`merge-failed`). A `legend` view is NOT scaffolded:
52
+ * a view names only elements the model declares, this model is empty, and an
53
+ * invented example would be a box every fleet check grades. The comment says
54
+ * when to write one. The kinds block has the same deliberate second copy in
55
+ * `core/c4/seed/template.ts`, pinned the same way by test/seed.test.ts.
41
56
  */
42
57
  export const LANDSCAPE_STUB = `// The fleet map: every service in services/ appears here, and every call
43
58
  // between two of them is an edge. This file is written by hand — loam never
@@ -54,16 +69,37 @@ export const LANDSCAPE_STUB = `// The fleet map: every service in services/ appe
54
69
  // and give each call the operationId it uses, so requirements, C4 and OpenAPI
55
70
  // can be cross-checked:
56
71
  //
57
- // checkoutWeb -> paymentService 'Authorizes' {
72
+ // checkoutWeb -[calls]-> paymentService 'Authorizes' {
58
73
  // metadata { op 'authorizePayment' }
59
74
  // }
60
75
  //
76
+ // Every edge says what it carries with one of the relationship kinds declared
77
+ // below, and points the way the evidence says — never a guess:
78
+ //
79
+ // checkoutWeb -[calls]-> orderService a synchronous request
80
+ // orderService -[publishes]-> kafka.orderEvents producer to topic
81
+ // kafka.orderEvents -[delivers]-> paymentService topic to consumer
82
+ // paymentService -[reads]-> ordersDb always service to store; the
83
+ // style puts the head on the reader
84
+ // orderService -[connects]-> kafka no direction established yet
85
+ //
86
+ // Configuration that only names an address says two things are connected and
87
+ // nothing more: that is \`connects\`, and adopting the service from its code
88
+ // turns it into the real kind. Once the map has a real edge of each kind, add
89
+ // a \`legend\` view that draws one of each. \`loam instructions loam-drawing\`
90
+ // has the whole convention.
91
+ //
61
92
  // The \`views\` block at the bottom is for LikeC4's own tooling — loam reads
62
93
  // the model and never a view. Render with \`npx likec4 start\` from the docs
63
- // repo root, which likec4.config.json scopes to this directory. (A service
64
- // model or a feature delta renders from its OWN directory, e.g.
65
- // \`npx likec4 start services/<id>\`: each declares its own \`specification\`
66
- // block, so the renderer can only be given one of them at a time.) Keep views
94
+ // repo root, which likec4.config.json scopes to this directory. A service's
95
+ // \`services/<id>/model.likec4\` EXTENDS this map: it declares no
96
+ // \`specification\` block of its own, so it belongs to THIS project and renders
97
+ // with it, containers and all. A model that declares its own \`specification\`
98
+ // stands alone instead — it renders only from its own directory
99
+ // (\`npx likec4 start services/<id>\`), and the \`exclude\` list in the root
100
+ // likec4.config.json has to cover that directory or its declarations collide
101
+ // with this file's. \`loam subsystem sync\` maintains both, so neither is
102
+ // hand-edited. Keep views
67
103
  // scoped, because computing one is superlinear in the number of edges — the
68
104
  // \`fleet\` view below stays affordable precisely because it excludes the
69
105
  // platform hubs.
@@ -96,6 +132,48 @@ specification {
96
132
  // without losing "who depends on the Identity Provider", which the platform
97
133
  // view answers.
98
134
  tag platform
135
+
136
+ // One kind per kind of traffic, each with one direction. The style is the
137
+ // picture: amber for messages, green for data at rest, gray and dashed for
138
+ // a connection nobody has given a direction yet. Never tag a kind: LikeC4
139
+ // copies a kind's tags onto every edge of it.
140
+ relationship publishes {
141
+ color amber
142
+ line solid
143
+ head normal
144
+ }
145
+ relationship delivers {
146
+ color amber
147
+ line solid
148
+ head normal
149
+ }
150
+ relationship reads {
151
+ color green
152
+ head none
153
+ tail normal
154
+ }
155
+ relationship writes {
156
+ color green
157
+ head normal
158
+ }
159
+ relationship readsWrites {
160
+ color green
161
+ head normal
162
+ tail normal
163
+ }
164
+ relationship calls {
165
+ color secondary
166
+ line solid
167
+ head normal
168
+ }
169
+ relationship connects {
170
+ color gray
171
+ line dashed
172
+ head none
173
+ // A marker at the source: an edge with no arrowhead at either end is laid
174
+ // out unconstrained, and enough of them flatten a view into one band.
175
+ tail odot
176
+ }
99
177
  }
100
178
 
101
179
  model {
@@ -115,17 +193,47 @@ views {
115
193
  }
116
194
  `;
117
195
  /**
118
- * Whether the fleet map is still the scaffold's own bytes — the sentinel
196
+ * The one thing loam itself ever writes ABOVE the stub: `core/docs.ts`'s
197
+ * `landscapePreamble`, spliced in as `${preamble.trimEnd()}\n//\n` — comment
198
+ * lines, closed by a bare `//` that separates the caller's sentence from the
199
+ * scaffold's own opening paragraph. `migrate-openspec` is the only caller.
200
+ *
201
+ * Matched as a SHAPE rather than as the migrator's exact sentence because the
202
+ * preamble is a parameter, and because the alternative is a second copy of that
203
+ * sentence in a package `core/scaffold/` must not import from
204
+ * (`commands/migrate-openspec/materialize/target.ts`). The shape is tight where
205
+ * it has to be: the closing bare `//` is what a hand-written note above the map
206
+ * does not have.
207
+ */
208
+ const LOAM_PREAMBLE = /^(?:\/\/[^\n]*\n)*\/\/\n$/;
209
+ /**
210
+ * Whether the fleet map is still a scaffold's own bytes — the sentinel
119
211
  * doctrine of core/coherence/authoring/sentinels.ts: the writer above and this
120
- * checker read ONE string, so they cannot drift apart. `endsWith`, not
121
- * equality, because `migrate-openspec` prepends a `landscapePreamble` to the
122
- * identical stub; CRLF-normalised because a checkout under core.autocrlf is
123
- * still untouched. A hand-edit inside the stub body breaks the suffix match —
124
- * the safe failure mode is a false "authored", which merely drops one teaching
125
- * step from `loam status`'s empty-fleet ladder (core/status/fleet/next.ts).
212
+ * checker read ONE string, so they cannot drift apart. CRLF-normalised because
213
+ * a checkout under core.autocrlf is still untouched. Every generation loam ever
214
+ * wrote counts, not just the current one — see `LEGACY_LANDSCAPE_STUBS`. A
215
+ * hand-edit inside the stub body breaks the match — the safe failure mode is a
216
+ * false "authored", which merely drops one teaching step from `loam status`'s
217
+ * empty-fleet ladder (core/status/fleet/next.ts).
218
+ *
219
+ * ANCHORED AT BOTH ENDS, past a preamble loam wrote itself. This was a bare
220
+ * `endsWith`, so anything a person put ABOVE the stub was invisible to the
221
+ * guard: `loam seed` overwrote a two-line "OWNED BY THE ARCHITECTURE GUILD — do
222
+ * not regenerate" header while printing "replaced the scaffold's untouched
223
+ * stub", against its own promise that "Seed never overwrites human work"
224
+ * (`commands/seed/commit.ts`; verification 2026-09-04, second pass). The suffix
225
+ * match existed for the migration preamble alone, so that is now the only
226
+ * prefix accepted, and everything else above the stub makes the file authored.
126
227
  */
127
228
  export function isLandscapeStub(content) {
128
229
  const normal = (s) => s.replace(/\r\n/g, "\n").trimEnd();
129
- return normal(content).endsWith(normal(LANDSCAPE_STUB));
230
+ const seen = normal(content);
231
+ return [LANDSCAPE_STUB, ...LEGACY_LANDSCAPE_STUBS].some((stub) => {
232
+ const body = normal(stub);
233
+ if (!seen.endsWith(body))
234
+ return false;
235
+ const prefix = seen.slice(0, seen.length - body.length);
236
+ return prefix === "" || LOAM_PREAMBLE.test(prefix);
237
+ });
130
238
  }
131
239
  //# sourceMappingURL=landscape.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"landscape.js","sourceRoot":"","sources":["../../../src/core/scaffold/landscape.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0E7B,CAAC;AAEF;;;;;;;;;GASG;AACH,MAAM,UAAU,eAAe,CAAC,OAAe;IAC7C,MAAM,MAAM,GAAG,CAAC,CAAS,EAAU,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC;IACzE,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC;AAC1D,CAAC","sourcesContent":["/**\n * The bytes a brand-new docs repo's fleet map starts with, and the one\n * question anybody asks of them afterwards: has a human touched this yet?\n *\n * Split out of `../docs.ts` when the README joined the scaffold and the file\n * reached its line limit, and the seam was already there: `docs.ts` says what\n * a docs repo is MADE OF — which directories, which files, in what order —\n * while this package holds the CONTENT of the authored templates it lays down.\n * The two change for different reasons: a new artifact edits the first, better\n * advice to a new fleet edits the second.\n */\n\n/**\n * The fleet map, empty but valid.\n *\n * Nobody writes this file automatically — `adopt` deliberately does not touch\n * it, because who calls whom is a human judgement and a generated landscape\n * would be a guess presented as the map. But \"nobody writes it\" used to mean\n * \"it is simply absent\", and an absent landscape is the one artifact whose\n * absence silences the fleet-wide checks entirely: every cross-service breach\n * `validate` exists to find is invisible on a repo with no landscape.\n *\n * So the scaffold lays down the empty map instead: the four element kinds a\n * fleet actually uses are declared, the model is empty, and the comments say\n * what to add and why. The first `loam adopt` then has somewhere to be drawn.\n *\n * A `views` block IS scaffolded — reversing the decision this comment used to\n * record, which was: no views, because computing one is superlinear in edge\n * count and a scaffolded `include *` handed every repo a fleet-sized bill for\n * the first tool that renders. That cost was real and still is; what changed\n * is the shape of the block. A fleet map stops being readable at the third\n * service unless platform infrastructure is split out, and the split's\n * `exclude element.tag = #platform` is exactly the\n * pruning that keeps the fleet view's render affordable — the scaffold now\n * pays the old objection instead of ignoring it. loam itself still reads\n * elements and relationships and never a view. The platform view's predicate\n * is scaffolded because it is the line users mistype: the obvious spelling\n * draws boxes with no edges.\n * The `views` block below has a deliberate second copy: `core/c4/seed/template.ts` emits the\n * same two views into a seeded landscape (two strikes; extract on a third), and test/seed.test.ts\n * compares the two blocks byte for byte — comments included — so whichever copy drifts fails.\n */\nexport const LANDSCAPE_STUB = `// The fleet map: every service in services/ appears here, and every call\n// between two of them is an edge. This file is written by hand — loam never\n// guesses it, because \"who calls whom\" is the one fact no generator can read\n// off a repository.\n//\n// After \\`loam adopt --service <id>\\`, add the service here:\n//\n// paymentService = softwareSystem 'payment-service' {\n// description 'Owns payment authorization/capture'\n// metadata { service 'payment-service' } // binds the box to services/<id>/\n// }\n//\n// and give each call the operationId it uses, so requirements, C4 and OpenAPI\n// can be cross-checked:\n//\n// checkoutWeb -> paymentService 'Authorizes' {\n// metadata { op 'authorizePayment' }\n// }\n//\n// The \\`views\\` block at the bottom is for LikeC4's own tooling — loam reads\n// the model and never a view. Render with \\`npx likec4 start\\` from the docs\n// repo root, which likec4.config.json scopes to this directory. (A service\n// model or a feature delta renders from its OWN directory, e.g.\n// \\`npx likec4 start services/<id>\\`: each declares its own \\`specification\\`\n// block, so the renderer can only be given one of them at a time.) Keep views\n// scoped, because computing one is superlinear in the number of edges — the\n// \\`fleet\\` view below stays affordable precisely because it excludes the\n// platform hubs.\n//\n// One shape is worth getting right before the fleet is drawn: a shared broker.\n// Kafka as a single element becomes the node every service points at, and any\n// view over it is a star nobody can read. Model the TOPIC instead — a \\`topic\\`\n// nested inside the broker's element, edges pointing at \\`kafka.<topic>\\` — which\n// splits one hub of degree sixty into a dozen small ones and is the truer model\n// besides. Tag the KIND, not just the broker: LikeC4 does not inherit tags, so a\n// topic under an \\`#external\\` broker is not external itself and \\`validate\\` asks\n// for a services/ directory nobody owes.\n//\n// specification {\n// element topic {\n// #external\n// style { shape queue }\n// }\n// }\n\nspecification {\n element person\n element softwareSystem\n element container\n element database\n\n // Ubiquitous infrastructure — logging Kafka, auth, service discovery — takes\n // one inbound edge per service, and by the third service the fleet view is a\n // hairball. Tag those elements #platform: the fleet view excludes them\n // without losing \"who depends on the Identity Provider\", which the platform\n // view answers.\n tag platform\n}\n\nmodel {\n}\n\nviews {\n view fleet {\n include *\n exclude element.tag = #platform\n }\n // The obvious spelling — \\`include element.tag = #platform\\` — draws the\n // platform boxes with NO edges and no consumers. The predicate that works is\n // the relationship form below.\n view platform {\n include * -> element.tag = #platform\n }\n}\n`;\n\n/**\n * Whether the fleet map is still the scaffold's own bytes — the sentinel\n * doctrine of core/coherence/authoring/sentinels.ts: the writer above and this\n * checker read ONE string, so they cannot drift apart. `endsWith`, not\n * equality, because `migrate-openspec` prepends a `landscapePreamble` to the\n * identical stub; CRLF-normalised because a checkout under core.autocrlf is\n * still untouched. A hand-edit inside the stub body breaks the suffix match —\n * the safe failure mode is a false \"authored\", which merely drops one teaching\n * step from `loam status`'s empty-fleet ladder (core/status/fleet/next.ts).\n */\nexport function isLandscapeStub(content: string): boolean {\n const normal = (s: string): string => s.replace(/\\r\\n/g, \"\\n\").trimEnd();\n return normal(content).endsWith(normal(LANDSCAPE_STUB));\n}\n"]}
1
+ {"version":3,"file":"landscape.js","sourceRoot":"","sources":["../../../src/core/scaffold/landscape.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAErD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyI7B,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,MAAM,aAAa,GAAG,2BAA2B,CAAC;AAElD;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,eAAe,CAAC,OAAe;IAC7C,MAAM,MAAM,GAAG,CAAC,CAAS,EAAU,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC;IACzE,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;IAC7B,OAAO,CAAC,cAAc,EAAE,GAAG,sBAAsB,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE;QAC/D,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;QAC1B,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;YAAE,OAAO,KAAK,CAAC;QACvC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;QACxD,OAAO,MAAM,KAAK,EAAE,IAAI,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;AACL,CAAC","sourcesContent":["/**\n * The bytes a brand-new docs repo's fleet map starts with, and the one\n * question anybody asks of them afterwards: has a human touched this yet?\n *\n * Split out of `../docs.ts` when the README joined the scaffold and the file\n * reached its line limit, and the seam was already there: `docs.ts` says what\n * a docs repo is MADE OF — which directories, which files, in what order —\n * while this package holds the CONTENT of the authored templates it lays down.\n * The two change for different reasons: a new artifact edits the first, better\n * advice to a new fleet edits the second.\n */\n\nimport { LEGACY_LANDSCAPE_STUBS } from \"./legacy.js\";\n\n/**\n * The fleet map, empty but valid.\n *\n * Nobody writes this file automatically — `adopt` deliberately does not touch\n * it, because who calls whom is a human judgement and a generated landscape\n * would be a guess presented as the map. But \"nobody writes it\" used to mean\n * \"it is simply absent\", and an absent landscape is the one artifact whose\n * absence silences the fleet-wide checks entirely: every cross-service breach\n * `validate` exists to find is invisible on a repo with no landscape.\n *\n * So the scaffold lays down the empty map instead: the four element kinds a\n * fleet actually uses are declared, the model is empty, and the comments say\n * what to add and why. The first `loam adopt` then has somewhere to be drawn.\n *\n * A `views` block IS scaffolded — reversing the decision this comment used to\n * record, which was: no views, because computing one is superlinear in edge\n * count and a scaffolded `include *` handed every repo a fleet-sized bill for\n * the first tool that renders. That cost was real and still is; what changed\n * is the shape of the block. A fleet map stops being readable at the third\n * service unless platform infrastructure is split out, and the split's\n * `exclude element.tag = #platform` is exactly the\n * pruning that keeps the fleet view's render affordable — the scaffold now\n * pays the old objection instead of ignoring it. loam itself still reads\n * elements and relationships and never a view. The platform view's predicate\n * is scaffolded because it is the line users mistype: the obvious spelling\n * draws boxes with no edges.\n * The `views` block below has a deliberate second copy: `core/c4/seed/template.ts` emits the\n * same two views into a seeded landscape (two strikes; extract on a third), and test/seed.test.ts\n * compares the two blocks byte for byte — comments included — so whichever copy drifts fails.\n *\n * The seven RELATIONSHIP kinds are scaffolded for the element kinds' reason:\n * they are vocabulary, not a guess about this fleet. Declared here, every\n * extending model and every adoption borrows them, so the first edge anybody\n * draws can say what it carries and which way it points. A real fleet drawn\n * without them ended with every arrow pointing into its broker and its stores,\n * because deployment configuration says only that two things are connected. A\n * declaration here also keeps a feature archivable: the archive copies a\n * delta's edge into this file and never a declaration, so a kind this file\n * lacks refuses the merge (`merge-failed`). A `legend` view is NOT scaffolded:\n * a view names only elements the model declares, this model is empty, and an\n * invented example would be a box every fleet check grades. The comment says\n * when to write one. The kinds block has the same deliberate second copy in\n * `core/c4/seed/template.ts`, pinned the same way by test/seed.test.ts.\n */\nexport const LANDSCAPE_STUB = `// The fleet map: every service in services/ appears here, and every call\n// between two of them is an edge. This file is written by hand — loam never\n// guesses it, because \"who calls whom\" is the one fact no generator can read\n// off a repository.\n//\n// After \\`loam adopt --service <id>\\`, add the service here:\n//\n// paymentService = softwareSystem 'payment-service' {\n// description 'Owns payment authorization/capture'\n// metadata { service 'payment-service' } // binds the box to services/<id>/\n// }\n//\n// and give each call the operationId it uses, so requirements, C4 and OpenAPI\n// can be cross-checked:\n//\n// checkoutWeb -[calls]-> paymentService 'Authorizes' {\n// metadata { op 'authorizePayment' }\n// }\n//\n// Every edge says what it carries with one of the relationship kinds declared\n// below, and points the way the evidence says — never a guess:\n//\n// checkoutWeb -[calls]-> orderService a synchronous request\n// orderService -[publishes]-> kafka.orderEvents producer to topic\n// kafka.orderEvents -[delivers]-> paymentService topic to consumer\n// paymentService -[reads]-> ordersDb always service to store; the\n// style puts the head on the reader\n// orderService -[connects]-> kafka no direction established yet\n//\n// Configuration that only names an address says two things are connected and\n// nothing more: that is \\`connects\\`, and adopting the service from its code\n// turns it into the real kind. Once the map has a real edge of each kind, add\n// a \\`legend\\` view that draws one of each. \\`loam instructions loam-drawing\\`\n// has the whole convention.\n//\n// The \\`views\\` block at the bottom is for LikeC4's own tooling — loam reads\n// the model and never a view. Render with \\`npx likec4 start\\` from the docs\n// repo root, which likec4.config.json scopes to this directory. A service's\n// \\`services/<id>/model.likec4\\` EXTENDS this map: it declares no\n// \\`specification\\` block of its own, so it belongs to THIS project and renders\n// with it, containers and all. A model that declares its own \\`specification\\`\n// stands alone instead — it renders only from its own directory\n// (\\`npx likec4 start services/<id>\\`), and the \\`exclude\\` list in the root\n// likec4.config.json has to cover that directory or its declarations collide\n// with this file's. \\`loam subsystem sync\\` maintains both, so neither is\n// hand-edited. Keep views\n// scoped, because computing one is superlinear in the number of edges — the\n// \\`fleet\\` view below stays affordable precisely because it excludes the\n// platform hubs.\n//\n// One shape is worth getting right before the fleet is drawn: a shared broker.\n// Kafka as a single element becomes the node every service points at, and any\n// view over it is a star nobody can read. Model the TOPIC instead — a \\`topic\\`\n// nested inside the broker's element, edges pointing at \\`kafka.<topic>\\` — which\n// splits one hub of degree sixty into a dozen small ones and is the truer model\n// besides. Tag the KIND, not just the broker: LikeC4 does not inherit tags, so a\n// topic under an \\`#external\\` broker is not external itself and \\`validate\\` asks\n// for a services/ directory nobody owes.\n//\n// specification {\n// element topic {\n// #external\n// style { shape queue }\n// }\n// }\n\nspecification {\n element person\n element softwareSystem\n element container\n element database\n\n // Ubiquitous infrastructure — logging Kafka, auth, service discovery — takes\n // one inbound edge per service, and by the third service the fleet view is a\n // hairball. Tag those elements #platform: the fleet view excludes them\n // without losing \"who depends on the Identity Provider\", which the platform\n // view answers.\n tag platform\n\n // One kind per kind of traffic, each with one direction. The style is the\n // picture: amber for messages, green for data at rest, gray and dashed for\n // a connection nobody has given a direction yet. Never tag a kind: LikeC4\n // copies a kind's tags onto every edge of it.\n relationship publishes {\n color amber\n line solid\n head normal\n }\n relationship delivers {\n color amber\n line solid\n head normal\n }\n relationship reads {\n color green\n head none\n tail normal\n }\n relationship writes {\n color green\n head normal\n }\n relationship readsWrites {\n color green\n head normal\n tail normal\n }\n relationship calls {\n color secondary\n line solid\n head normal\n }\n relationship connects {\n color gray\n line dashed\n head none\n // A marker at the source: an edge with no arrowhead at either end is laid\n // out unconstrained, and enough of them flatten a view into one band.\n tail odot\n }\n}\n\nmodel {\n}\n\nviews {\n view fleet {\n include *\n exclude element.tag = #platform\n }\n // The obvious spelling — \\`include element.tag = #platform\\` — draws the\n // platform boxes with NO edges and no consumers. The predicate that works is\n // the relationship form below.\n view platform {\n include * -> element.tag = #platform\n }\n}\n`;\n\n/**\n * The one thing loam itself ever writes ABOVE the stub: `core/docs.ts`'s\n * `landscapePreamble`, spliced in as `${preamble.trimEnd()}\\n//\\n` — comment\n * lines, closed by a bare `//` that separates the caller's sentence from the\n * scaffold's own opening paragraph. `migrate-openspec` is the only caller.\n *\n * Matched as a SHAPE rather than as the migrator's exact sentence because the\n * preamble is a parameter, and because the alternative is a second copy of that\n * sentence in a package `core/scaffold/` must not import from\n * (`commands/migrate-openspec/materialize/target.ts`). The shape is tight where\n * it has to be: the closing bare `//` is what a hand-written note above the map\n * does not have.\n */\nconst LOAM_PREAMBLE = /^(?:\\/\\/[^\\n]*\\n)*\\/\\/\\n$/;\n\n/**\n * Whether the fleet map is still a scaffold's own bytes — the sentinel\n * doctrine of core/coherence/authoring/sentinels.ts: the writer above and this\n * checker read ONE string, so they cannot drift apart. CRLF-normalised because\n * a checkout under core.autocrlf is still untouched. Every generation loam ever\n * wrote counts, not just the current one — see `LEGACY_LANDSCAPE_STUBS`. A\n * hand-edit inside the stub body breaks the match — the safe failure mode is a\n * false \"authored\", which merely drops one teaching step from `loam status`'s\n * empty-fleet ladder (core/status/fleet/next.ts).\n *\n * ANCHORED AT BOTH ENDS, past a preamble loam wrote itself. This was a bare\n * `endsWith`, so anything a person put ABOVE the stub was invisible to the\n * guard: `loam seed` overwrote a two-line \"OWNED BY THE ARCHITECTURE GUILD — do\n * not regenerate\" header while printing \"replaced the scaffold's untouched\n * stub\", against its own promise that \"Seed never overwrites human work\"\n * (`commands/seed/commit.ts`; verification 2026-09-04, second pass). The suffix\n * match existed for the migration preamble alone, so that is now the only\n * prefix accepted, and everything else above the stub makes the file authored.\n */\nexport function isLandscapeStub(content: string): boolean {\n const normal = (s: string): string => s.replace(/\\r\\n/g, \"\\n\").trimEnd();\n const seen = normal(content);\n return [LANDSCAPE_STUB, ...LEGACY_LANDSCAPE_STUBS].some((stub) => {\n const body = normal(stub);\n if (!seen.endsWith(body)) return false;\n const prefix = seen.slice(0, seen.length - body.length);\n return prefix === \"\" || LOAM_PREAMBLE.test(prefix);\n });\n}\n"]}
@@ -0,0 +1,271 @@
1
+ /**
2
+ * Every fleet map an earlier loam scaffolded, frozen, so `isLandscapeStub` in
3
+ * ./landscape.ts can still tell an untouched old scaffold from a hand-drawn map.
4
+ *
5
+ * Moved out of ./landscape.ts when that file neared its line limit, along the
6
+ * seam the two halves already had: ./landscape.ts holds the stub loam writes
7
+ * NOW and the predicate that reads it, this module holds what loam wrote
8
+ * before. The first changes whenever the advice to a new fleet improves; this
9
+ * one only ever grows by one entry, when that happens.
10
+ */
11
+ /**
12
+ * Stubs earlier versions of loam wrote, FROZEN — never re-derived from
13
+ * `LANDSCAPE_STUB` in ./landscape.ts, or an edit to it would silently rewrite
14
+ * history.
15
+ *
16
+ * `isLandscapeStub` is a suffix match on the exact bytes, and `loam seed`
17
+ * refuses (`seed-landscape-edited`) on a map it judges authored. So editing
18
+ * the stub reclassifies every untouched older scaffold as hand-edited, in
19
+ * repositories nobody has touched — the teaching step disappears from `loam
20
+ * status` and `seed` refuses a map its own scaffold wrote. Each entry is one
21
+ * shipped generation of the file, OLDEST FIRST, appended when
22
+ * `LANDSCAPE_STUB`'s text changes — every generation loam ever wrote is here,
23
+ * not just the previous one, since a repository scaffolded two releases ago is
24
+ * as untouched as one scaffolded yesterday.
25
+ *
26
+ * Generation 1 (v0.1.0-beta.1, .2): the stub lived in core/docs.ts, carried no
27
+ * `views` block at all ("on purpose: loam reads the model and never a view")
28
+ * and no `tag platform`.
29
+ * Generation 2 (v0.1.0-beta.3): the same file with the render paragraph
30
+ * rewritten — still no `views` block, still no `tag platform`.
31
+ * Generation 3 (v0.2.0-alpha.1 through .5): the `views` paragraph taught the
32
+ * retired shape — that a service model "renders from its OWN directory" and
33
+ * "each declares its own `specification` block" — which was written before an
34
+ * extending model belonged to the root project.
35
+ * Generation 4 (v0.2.0-alpha.6 through .11): the extending shape's render
36
+ * paragraph and the shared-broker advice, with no relationship kinds — every
37
+ * edge a plain `->`, which is how a fleet drawn from deployment configuration
38
+ * ended with every arrow pointing into its broker and its stores.
39
+ */
40
+ export const LEGACY_LANDSCAPE_STUBS = [
41
+ `// The fleet map: every service in services/ appears here, and every call
42
+ // between two of them is an edge. This file is written by hand — loam never
43
+ // guesses it, because "who calls whom" is the one fact no generator can read
44
+ // off a repository.
45
+ //
46
+ // After \`loam adopt --service <id>\`, add the service here:
47
+ //
48
+ // paymentService = softwareSystem 'payment-service' {
49
+ // description 'Owns payment authorization/capture'
50
+ // metadata { service 'payment-service' } // binds the box to services/<id>/
51
+ // }
52
+ //
53
+ // and give each call the operationId it uses, so requirements, C4 and OpenAPI
54
+ // can be cross-checked:
55
+ //
56
+ // checkoutWeb -> paymentService 'Authorizes' {
57
+ // metadata { op 'authorizePayment' }
58
+ // }
59
+ //
60
+ // There is no \`views\` block, on purpose: loam reads the model and never a
61
+ // view, so it would draw nothing. Add views here if you want diagrams, and
62
+ // render them with LikeC4's own tooling (\`npx likec4 start\`) — but scope them,
63
+ // because computing a view is superlinear in the number of edges and an
64
+ // \`include *\` over a whole fleet takes minutes.
65
+
66
+ specification {
67
+ element person
68
+ element softwareSystem
69
+ element container
70
+ element database
71
+ }
72
+
73
+ model {
74
+ }
75
+ `,
76
+ `// The fleet map: every service in services/ appears here, and every call
77
+ // between two of them is an edge. This file is written by hand — loam never
78
+ // guesses it, because "who calls whom" is the one fact no generator can read
79
+ // off a repository.
80
+ //
81
+ // After \`loam adopt --service <id>\`, add the service here:
82
+ //
83
+ // paymentService = softwareSystem 'payment-service' {
84
+ // description 'Owns payment authorization/capture'
85
+ // metadata { service 'payment-service' } // binds the box to services/<id>/
86
+ // }
87
+ //
88
+ // and give each call the operationId it uses, so requirements, C4 and OpenAPI
89
+ // can be cross-checked:
90
+ //
91
+ // checkoutWeb -> paymentService 'Authorizes' {
92
+ // metadata { op 'authorizePayment' }
93
+ // }
94
+ //
95
+ // There is no \`views\` block, on purpose: loam reads the model and never a
96
+ // view, so it would draw nothing. Add views here if you want diagrams, and
97
+ // render them with LikeC4's own tooling — \`npx likec4 start\` from the docs
98
+ // repo root, which likec4.config.json scopes to this directory. (A service
99
+ // model or a feature delta renders from its OWN directory, e.g.
100
+ // \`npx likec4 start services/<id>\`: each declares its own \`specification\`
101
+ // block, so the renderer can only be given one of them at a time.) Scope your
102
+ // views, because computing one is superlinear in the number of edges and an
103
+ // \`include *\` over a whole fleet takes minutes.
104
+
105
+ specification {
106
+ element person
107
+ element softwareSystem
108
+ element container
109
+ element database
110
+ }
111
+
112
+ model {
113
+ }
114
+ `,
115
+ `// The fleet map: every service in services/ appears here, and every call
116
+ // between two of them is an edge. This file is written by hand — loam never
117
+ // guesses it, because "who calls whom" is the one fact no generator can read
118
+ // off a repository.
119
+ //
120
+ // After \`loam adopt --service <id>\`, add the service here:
121
+ //
122
+ // paymentService = softwareSystem 'payment-service' {
123
+ // description 'Owns payment authorization/capture'
124
+ // metadata { service 'payment-service' } // binds the box to services/<id>/
125
+ // }
126
+ //
127
+ // and give each call the operationId it uses, so requirements, C4 and OpenAPI
128
+ // can be cross-checked:
129
+ //
130
+ // checkoutWeb -> paymentService 'Authorizes' {
131
+ // metadata { op 'authorizePayment' }
132
+ // }
133
+ //
134
+ // The \`views\` block at the bottom is for LikeC4's own tooling — loam reads
135
+ // the model and never a view. Render with \`npx likec4 start\` from the docs
136
+ // repo root, which likec4.config.json scopes to this directory. (A service
137
+ // model or a feature delta renders from its OWN directory, e.g.
138
+ // \`npx likec4 start services/<id>\`: each declares its own \`specification\`
139
+ // block, so the renderer can only be given one of them at a time.) Keep views
140
+ // scoped, because computing one is superlinear in the number of edges — the
141
+ // \`fleet\` view below stays affordable precisely because it excludes the
142
+ // platform hubs.
143
+ //
144
+ // One shape is worth getting right before the fleet is drawn: a shared broker.
145
+ // Kafka as a single element becomes the node every service points at, and any
146
+ // view over it is a star nobody can read. Model the TOPIC instead — a \`topic\`
147
+ // nested inside the broker's element, edges pointing at \`kafka.<topic>\` — which
148
+ // splits one hub of degree sixty into a dozen small ones and is the truer model
149
+ // besides. Tag the KIND, not just the broker: LikeC4 does not inherit tags, so a
150
+ // topic under an \`#external\` broker is not external itself and \`validate\` asks
151
+ // for a services/ directory nobody owes.
152
+ //
153
+ // specification {
154
+ // element topic {
155
+ // #external
156
+ // style { shape queue }
157
+ // }
158
+ // }
159
+
160
+ specification {
161
+ element person
162
+ element softwareSystem
163
+ element container
164
+ element database
165
+
166
+ // Ubiquitous infrastructure — logging Kafka, auth, service discovery — takes
167
+ // one inbound edge per service, and by the third service the fleet view is a
168
+ // hairball. Tag those elements #platform: the fleet view excludes them
169
+ // without losing "who depends on the Identity Provider", which the platform
170
+ // view answers.
171
+ tag platform
172
+ }
173
+
174
+ model {
175
+ }
176
+
177
+ views {
178
+ view fleet {
179
+ include *
180
+ exclude element.tag = #platform
181
+ }
182
+ // The obvious spelling — \`include element.tag = #platform\` — draws the
183
+ // platform boxes with NO edges and no consumers. The predicate that works is
184
+ // the relationship form below.
185
+ view platform {
186
+ include * -> element.tag = #platform
187
+ }
188
+ }
189
+ `,
190
+ `// The fleet map: every service in services/ appears here, and every call
191
+ // between two of them is an edge. This file is written by hand — loam never
192
+ // guesses it, because "who calls whom" is the one fact no generator can read
193
+ // off a repository.
194
+ //
195
+ // After \`loam adopt --service <id>\`, add the service here:
196
+ //
197
+ // paymentService = softwareSystem 'payment-service' {
198
+ // description 'Owns payment authorization/capture'
199
+ // metadata { service 'payment-service' } // binds the box to services/<id>/
200
+ // }
201
+ //
202
+ // and give each call the operationId it uses, so requirements, C4 and OpenAPI
203
+ // can be cross-checked:
204
+ //
205
+ // checkoutWeb -> paymentService 'Authorizes' {
206
+ // metadata { op 'authorizePayment' }
207
+ // }
208
+ //
209
+ // The \`views\` block at the bottom is for LikeC4's own tooling — loam reads
210
+ // the model and never a view. Render with \`npx likec4 start\` from the docs
211
+ // repo root, which likec4.config.json scopes to this directory. A service's
212
+ // \`services/<id>/model.likec4\` EXTENDS this map: it declares no
213
+ // \`specification\` block of its own, so it belongs to THIS project and renders
214
+ // with it, containers and all. A model that declares its own \`specification\`
215
+ // stands alone instead — it renders only from its own directory
216
+ // (\`npx likec4 start services/<id>\`), and the \`exclude\` list in the root
217
+ // likec4.config.json has to cover that directory or its declarations collide
218
+ // with this file's. \`loam subsystem sync\` maintains both, so neither is
219
+ // hand-edited. Keep views
220
+ // scoped, because computing one is superlinear in the number of edges — the
221
+ // \`fleet\` view below stays affordable precisely because it excludes the
222
+ // platform hubs.
223
+ //
224
+ // One shape is worth getting right before the fleet is drawn: a shared broker.
225
+ // Kafka as a single element becomes the node every service points at, and any
226
+ // view over it is a star nobody can read. Model the TOPIC instead — a \`topic\`
227
+ // nested inside the broker's element, edges pointing at \`kafka.<topic>\` — which
228
+ // splits one hub of degree sixty into a dozen small ones and is the truer model
229
+ // besides. Tag the KIND, not just the broker: LikeC4 does not inherit tags, so a
230
+ // topic under an \`#external\` broker is not external itself and \`validate\` asks
231
+ // for a services/ directory nobody owes.
232
+ //
233
+ // specification {
234
+ // element topic {
235
+ // #external
236
+ // style { shape queue }
237
+ // }
238
+ // }
239
+
240
+ specification {
241
+ element person
242
+ element softwareSystem
243
+ element container
244
+ element database
245
+
246
+ // Ubiquitous infrastructure — logging Kafka, auth, service discovery — takes
247
+ // one inbound edge per service, and by the third service the fleet view is a
248
+ // hairball. Tag those elements #platform: the fleet view excludes them
249
+ // without losing "who depends on the Identity Provider", which the platform
250
+ // view answers.
251
+ tag platform
252
+ }
253
+
254
+ model {
255
+ }
256
+
257
+ views {
258
+ view fleet {
259
+ include *
260
+ exclude element.tag = #platform
261
+ }
262
+ // The obvious spelling — \`include element.tag = #platform\` — draws the
263
+ // platform boxes with NO edges and no consumers. The predicate that works is
264
+ // the relationship form below.
265
+ view platform {
266
+ include * -> element.tag = #platform
267
+ }
268
+ }
269
+ `,
270
+ ];
271
+ //# sourceMappingURL=legacy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"legacy.js","sourceRoot":"","sources":["../../../src/core/scaffold/legacy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAsB;IACvD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkCD;IACC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsCD;IACC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0ED;IACC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+ED;CACA,CAAC","sourcesContent":["/**\n * Every fleet map an earlier loam scaffolded, frozen, so `isLandscapeStub` in\n * ./landscape.ts can still tell an untouched old scaffold from a hand-drawn map.\n *\n * Moved out of ./landscape.ts when that file neared its line limit, along the\n * seam the two halves already had: ./landscape.ts holds the stub loam writes\n * NOW and the predicate that reads it, this module holds what loam wrote\n * before. The first changes whenever the advice to a new fleet improves; this\n * one only ever grows by one entry, when that happens.\n */\n\n/**\n * Stubs earlier versions of loam wrote, FROZEN — never re-derived from\n * `LANDSCAPE_STUB` in ./landscape.ts, or an edit to it would silently rewrite\n * history.\n *\n * `isLandscapeStub` is a suffix match on the exact bytes, and `loam seed`\n * refuses (`seed-landscape-edited`) on a map it judges authored. So editing\n * the stub reclassifies every untouched older scaffold as hand-edited, in\n * repositories nobody has touched — the teaching step disappears from `loam\n * status` and `seed` refuses a map its own scaffold wrote. Each entry is one\n * shipped generation of the file, OLDEST FIRST, appended when\n * `LANDSCAPE_STUB`'s text changes — every generation loam ever wrote is here,\n * not just the previous one, since a repository scaffolded two releases ago is\n * as untouched as one scaffolded yesterday.\n *\n * Generation 1 (v0.1.0-beta.1, .2): the stub lived in core/docs.ts, carried no\n * `views` block at all (\"on purpose: loam reads the model and never a view\")\n * and no `tag platform`.\n * Generation 2 (v0.1.0-beta.3): the same file with the render paragraph\n * rewritten — still no `views` block, still no `tag platform`.\n * Generation 3 (v0.2.0-alpha.1 through .5): the `views` paragraph taught the\n * retired shape — that a service model \"renders from its OWN directory\" and\n * \"each declares its own `specification` block\" — which was written before an\n * extending model belonged to the root project.\n * Generation 4 (v0.2.0-alpha.6 through .11): the extending shape's render\n * paragraph and the shared-broker advice, with no relationship kinds — every\n * edge a plain `->`, which is how a fleet drawn from deployment configuration\n * ended with every arrow pointing into its broker and its stores.\n */\nexport const LEGACY_LANDSCAPE_STUBS: readonly string[] = [\n `// The fleet map: every service in services/ appears here, and every call\n// between two of them is an edge. This file is written by hand — loam never\n// guesses it, because \"who calls whom\" is the one fact no generator can read\n// off a repository.\n//\n// After \\`loam adopt --service <id>\\`, add the service here:\n//\n// paymentService = softwareSystem 'payment-service' {\n// description 'Owns payment authorization/capture'\n// metadata { service 'payment-service' } // binds the box to services/<id>/\n// }\n//\n// and give each call the operationId it uses, so requirements, C4 and OpenAPI\n// can be cross-checked:\n//\n// checkoutWeb -> paymentService 'Authorizes' {\n// metadata { op 'authorizePayment' }\n// }\n//\n// There is no \\`views\\` block, on purpose: loam reads the model and never a\n// view, so it would draw nothing. Add views here if you want diagrams, and\n// render them with LikeC4's own tooling (\\`npx likec4 start\\`) — but scope them,\n// because computing a view is superlinear in the number of edges and an\n// \\`include *\\` over a whole fleet takes minutes.\n\nspecification {\n element person\n element softwareSystem\n element container\n element database\n}\n\nmodel {\n}\n`,\n `// The fleet map: every service in services/ appears here, and every call\n// between two of them is an edge. This file is written by hand — loam never\n// guesses it, because \"who calls whom\" is the one fact no generator can read\n// off a repository.\n//\n// After \\`loam adopt --service <id>\\`, add the service here:\n//\n// paymentService = softwareSystem 'payment-service' {\n// description 'Owns payment authorization/capture'\n// metadata { service 'payment-service' } // binds the box to services/<id>/\n// }\n//\n// and give each call the operationId it uses, so requirements, C4 and OpenAPI\n// can be cross-checked:\n//\n// checkoutWeb -> paymentService 'Authorizes' {\n// metadata { op 'authorizePayment' }\n// }\n//\n// There is no \\`views\\` block, on purpose: loam reads the model and never a\n// view, so it would draw nothing. Add views here if you want diagrams, and\n// render them with LikeC4's own tooling — \\`npx likec4 start\\` from the docs\n// repo root, which likec4.config.json scopes to this directory. (A service\n// model or a feature delta renders from its OWN directory, e.g.\n// \\`npx likec4 start services/<id>\\`: each declares its own \\`specification\\`\n// block, so the renderer can only be given one of them at a time.) Scope your\n// views, because computing one is superlinear in the number of edges and an\n// \\`include *\\` over a whole fleet takes minutes.\n\nspecification {\n element person\n element softwareSystem\n element container\n element database\n}\n\nmodel {\n}\n`,\n `// The fleet map: every service in services/ appears here, and every call\n// between two of them is an edge. This file is written by hand — loam never\n// guesses it, because \"who calls whom\" is the one fact no generator can read\n// off a repository.\n//\n// After \\`loam adopt --service <id>\\`, add the service here:\n//\n// paymentService = softwareSystem 'payment-service' {\n// description 'Owns payment authorization/capture'\n// metadata { service 'payment-service' } // binds the box to services/<id>/\n// }\n//\n// and give each call the operationId it uses, so requirements, C4 and OpenAPI\n// can be cross-checked:\n//\n// checkoutWeb -> paymentService 'Authorizes' {\n// metadata { op 'authorizePayment' }\n// }\n//\n// The \\`views\\` block at the bottom is for LikeC4's own tooling — loam reads\n// the model and never a view. Render with \\`npx likec4 start\\` from the docs\n// repo root, which likec4.config.json scopes to this directory. (A service\n// model or a feature delta renders from its OWN directory, e.g.\n// \\`npx likec4 start services/<id>\\`: each declares its own \\`specification\\`\n// block, so the renderer can only be given one of them at a time.) Keep views\n// scoped, because computing one is superlinear in the number of edges — the\n// \\`fleet\\` view below stays affordable precisely because it excludes the\n// platform hubs.\n//\n// One shape is worth getting right before the fleet is drawn: a shared broker.\n// Kafka as a single element becomes the node every service points at, and any\n// view over it is a star nobody can read. Model the TOPIC instead — a \\`topic\\`\n// nested inside the broker's element, edges pointing at \\`kafka.<topic>\\` — which\n// splits one hub of degree sixty into a dozen small ones and is the truer model\n// besides. Tag the KIND, not just the broker: LikeC4 does not inherit tags, so a\n// topic under an \\`#external\\` broker is not external itself and \\`validate\\` asks\n// for a services/ directory nobody owes.\n//\n// specification {\n// element topic {\n// #external\n// style { shape queue }\n// }\n// }\n\nspecification {\n element person\n element softwareSystem\n element container\n element database\n\n // Ubiquitous infrastructure — logging Kafka, auth, service discovery — takes\n // one inbound edge per service, and by the third service the fleet view is a\n // hairball. Tag those elements #platform: the fleet view excludes them\n // without losing \"who depends on the Identity Provider\", which the platform\n // view answers.\n tag platform\n}\n\nmodel {\n}\n\nviews {\n view fleet {\n include *\n exclude element.tag = #platform\n }\n // The obvious spelling — \\`include element.tag = #platform\\` — draws the\n // platform boxes with NO edges and no consumers. The predicate that works is\n // the relationship form below.\n view platform {\n include * -> element.tag = #platform\n }\n}\n`,\n `// The fleet map: every service in services/ appears here, and every call\n// between two of them is an edge. This file is written by hand — loam never\n// guesses it, because \"who calls whom\" is the one fact no generator can read\n// off a repository.\n//\n// After \\`loam adopt --service <id>\\`, add the service here:\n//\n// paymentService = softwareSystem 'payment-service' {\n// description 'Owns payment authorization/capture'\n// metadata { service 'payment-service' } // binds the box to services/<id>/\n// }\n//\n// and give each call the operationId it uses, so requirements, C4 and OpenAPI\n// can be cross-checked:\n//\n// checkoutWeb -> paymentService 'Authorizes' {\n// metadata { op 'authorizePayment' }\n// }\n//\n// The \\`views\\` block at the bottom is for LikeC4's own tooling — loam reads\n// the model and never a view. Render with \\`npx likec4 start\\` from the docs\n// repo root, which likec4.config.json scopes to this directory. A service's\n// \\`services/<id>/model.likec4\\` EXTENDS this map: it declares no\n// \\`specification\\` block of its own, so it belongs to THIS project and renders\n// with it, containers and all. A model that declares its own \\`specification\\`\n// stands alone instead — it renders only from its own directory\n// (\\`npx likec4 start services/<id>\\`), and the \\`exclude\\` list in the root\n// likec4.config.json has to cover that directory or its declarations collide\n// with this file's. \\`loam subsystem sync\\` maintains both, so neither is\n// hand-edited. Keep views\n// scoped, because computing one is superlinear in the number of edges — the\n// \\`fleet\\` view below stays affordable precisely because it excludes the\n// platform hubs.\n//\n// One shape is worth getting right before the fleet is drawn: a shared broker.\n// Kafka as a single element becomes the node every service points at, and any\n// view over it is a star nobody can read. Model the TOPIC instead — a \\`topic\\`\n// nested inside the broker's element, edges pointing at \\`kafka.<topic>\\` — which\n// splits one hub of degree sixty into a dozen small ones and is the truer model\n// besides. Tag the KIND, not just the broker: LikeC4 does not inherit tags, so a\n// topic under an \\`#external\\` broker is not external itself and \\`validate\\` asks\n// for a services/ directory nobody owes.\n//\n// specification {\n// element topic {\n// #external\n// style { shape queue }\n// }\n// }\n\nspecification {\n element person\n element softwareSystem\n element container\n element database\n\n // Ubiquitous infrastructure — logging Kafka, auth, service discovery — takes\n // one inbound edge per service, and by the third service the fleet view is a\n // hairball. Tag those elements #platform: the fleet view excludes them\n // without losing \"who depends on the Identity Provider\", which the platform\n // view answers.\n tag platform\n}\n\nmodel {\n}\n\nviews {\n view fleet {\n include *\n exclude element.tag = #platform\n }\n // The obvious spelling — \\`include element.tag = #platform\\` — draws the\n // platform boxes with NO edges and no consumers. The predicate that works is\n // the relationship form below.\n view platform {\n include * -> element.tag = #platform\n }\n}\n`,\n];\n"]}
@@ -15,7 +15,8 @@
15
15
  */
16
16
  import { existsSync } from "node:fs";
17
17
  import { link, mkdir, readFile, rename, rm, rmdir, unlink, writeFile } from "node:fs/promises";
18
- import { basename, dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
18
+ import { basename, dirname, join, resolve } from "node:path";
19
+ import { isPathInside, withoutNamespacePrefix } from "../kernel/path-safety.js";
19
20
  import { sameBytes, toBytes } from "./writes.js";
20
21
  /**
21
22
  * The target changed between the pre-image staging read and the swap.
@@ -47,9 +48,7 @@ export async function stageWrites(writes) {
47
48
  const staged = [];
48
49
  try {
49
50
  for (const [i, write] of writes.entries()) {
50
- // mkdir(recursive) reports the topmost directory it had to create — the
51
- // handle a rollback needs to put the tree back the way it found it.
52
- const createdDir = (await mkdir(dirname(write.path), { recursive: true })) ?? null;
51
+ const createdDir = await mkdirReportingCreated(dirname(write.path));
53
52
  const before = existsSync(write.path) ? await readFile(write.path) : null;
54
53
  const content = toBytes(write.content);
55
54
  let tmp = null;
@@ -140,6 +139,21 @@ export async function rollbackStaged(staged) {
140
139
  await discardStaged(staged);
141
140
  return failures;
142
141
  }
142
+ /**
143
+ * `mkdir -p`, reporting the topmost directory it had to create — the handle a
144
+ * rollback needs to put the tree back the way it found it — or null when every
145
+ * one already existed.
146
+ *
147
+ * The report is never handed on raw. On Windows, Node spells it with a `\\?\`
148
+ * prefix that no other path loam holds carries, and a rollback comparing the
149
+ * two spellings found nothing to prune (`withoutNamespacePrefix` has the
150
+ * measurement). Every caller that keeps a created directory for its rollback
151
+ * takes it from here, so the plain spelling is decided once.
152
+ */
153
+ export async function mkdirReportingCreated(dir) {
154
+ const created = await mkdir(dir, { recursive: true });
155
+ return created === undefined ? null : withoutNamespacePrefix(created);
156
+ }
143
157
  /** Write `content` to `path` through a temp file in the same directory. */
144
158
  export async function atomicWrite(path, content) {
145
159
  const tmp = tempPath(path, 0);
@@ -169,20 +183,11 @@ async function discardStaged(staged) {
169
183
  await quietRm(s.tmp);
170
184
  const roots = staged.filter((s) => s.createdDir !== null).map((s) => resolve(s.createdDir));
171
185
  for (const s of [...staged].reverse()) {
172
- const root = roots.find((candidate) => contains(candidate, s.write.path));
186
+ const root = roots.find((candidate) => isPathInside(candidate, s.write.path));
173
187
  if (root !== undefined)
174
188
  await quietPruneEmptyParents(dirname(s.write.path), root);
175
189
  }
176
190
  }
177
- function contains(parent, candidate) {
178
- const rel = relative(parent, resolve(candidate));
179
- return rel === "" || (!rel.startsWith(`..${sep}`) && rel !== ".." && !isAbsolute(rel));
180
- }
181
- /**
182
- * Undo the directories a write had to create, from `start` up to and including
183
- * `boundary`. Remove only directories that are still EMPTY: anything else in
184
- * there arrived after we made it, and belongs to whoever put it there.
185
- */
186
191
  /** Remove `dir` if it is empty. Best effort — a directory left standing is noise, not corruption. */
187
192
  export async function quietRmdir(dir) {
188
193
  try {
@@ -192,10 +197,16 @@ export async function quietRmdir(dir) {
192
197
  // Not empty, or not ours.
193
198
  }
194
199
  }
200
+ /**
201
+ * Undo the directories a write had to create, from `start` up to and including
202
+ * `boundary` — or, for unarchive, the ones a restore's deletes left empty.
203
+ * Remove only directories that are still EMPTY: anything else in there arrived
204
+ * after we made it, and belongs to whoever put it there.
205
+ */
195
206
  export async function quietPruneEmptyParents(start, boundary) {
196
207
  let cursor = resolve(start);
197
208
  const root = resolve(boundary);
198
- while (contains(root, cursor)) {
209
+ while (isPathInside(root, cursor)) {
199
210
  try {
200
211
  await rmdir(cursor);
201
212
  }