@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
@@ -15,8 +15,9 @@
15
15
  * one module is what stops "new" being decided differently in three places.
16
16
  */
17
17
  import { existsSync } from "node:fs";
18
- import { loadFile } from "../../core/c4/likec4.js";
18
+ import {} from "../../core/c4/likec4.js";
19
19
  import { elementService, serviceResolver } from "../../core/c4/resolve/service.js";
20
+ import { groupsServices } from "../../core/c4/resolve/systems.js";
20
21
  import {} from "../../core/kernel/ids/service.js";
21
22
  import { landscapePath as landscapeFile } from "../../core/repo/paths.js";
22
23
  import { locateServicePaths } from "../../core/repo/service-target.js";
@@ -28,8 +29,9 @@ import { readHealth } from "../../core/vocabulary/health.js";
28
29
  import { FleetContext } from "../../core/fleet-context.js";
29
30
  import { ACTOR_KINDS, EXTERNAL_TAG } from "../../core/vocabulary/maturity.js";
30
31
  import { coversEntries, coversUnknownFindings } from "./checks/requirements.js";
32
+ import { deltaSpelledCovers, mergedMapOf, survivingEdgeCover, survivingElementCover } from "./coverage/covers-after.js";
31
33
  export async function deltaArchCoverage(delta) {
32
- const { docsDir, elements, relationships, taggedEls, taggedRels, archDeltas, featureServices, scenarioText, preloadedLand, fleet, } = delta;
34
+ const { docsDir, featureDir, featureId, elements, relationships, taggedEls, taggedRels, archDeltas, featureServices, scenarioText, preloadedLand, fleet, } = delta;
33
35
  const findings = [];
34
36
  // The delta's own element→service resolver, built once for the whole feature.
35
37
  // `serviceOf` is a one-shot wrapper that rebuilds its index on every call, and
@@ -48,6 +50,9 @@ export async function deltaArchCoverage(delta) {
48
50
  ...featureServices,
49
51
  ]);
50
52
  const svcOf = serviceResolver(elements, known);
53
+ // The map this feature's merge would leave, parsed at most once and only when
54
+ // a hint or a `Covers:` line needs it (./coverage/covers-after.ts says when).
55
+ const merged = mergedMapOf({ docsDir, featureDir, featureId, fleet, known });
51
56
  // Arch-edge coverage (heuristic, warn-only): each new tagged edge should be named by a scenario.
52
57
  for (const r of taggedRels) {
53
58
  const target = svcOf(r.target);
@@ -66,8 +71,12 @@ export async function deltaArchCoverage(delta) {
66
71
  // this is where agent-built code cuts its corners — the outbox, the retries,
67
72
  // the alerts — because no business scenario was ever going to mention them.
68
73
  // Grouping-only elements take the same exemptions the fleet map applies
69
- // (person kinds, #external) — one set, in checks/vocabulary.ts, so "not a
70
- // service" cannot mean two things. Warnings, never archive gates; `--strict`
74
+ // (person kinds, #external) — one set, in core/vocabulary/maturity.ts, so
75
+ // "not a service" cannot mean two things — and so does a GROUPING, an element
76
+ // that stands for no service and contains one (core/c4/resolve/systems.ts).
77
+ // A new domain drawn around a new service was asked for a `Covers:` line of
78
+ // its own: there is no obligation a group can carry, and the service inside
79
+ // it is graded on its own. Warnings, never archive gates; `--strict`
71
80
  // escalates.
72
81
  //
73
82
  // Only requirements the archive will MERGE grant coverage here. In a delta,
@@ -88,11 +97,7 @@ export async function deltaArchCoverage(delta) {
88
97
  const livingLandscape = async () => {
89
98
  if (living === undefined) {
90
99
  const lp = landscapeFile(docsDir);
91
- living = existsSync(lp)
92
- ? fleet === undefined
93
- ? await loadFile(lp)
94
- : await fleet.loadLikeC4(lp)
95
- : null;
100
+ living = existsSync(lp) ? await fleet.loadLikeC4(lp) : null;
96
101
  }
97
102
  return living;
98
103
  };
@@ -117,17 +122,22 @@ export async function deltaArchCoverage(delta) {
117
122
  const edgeKey = (source, target) => JSON.stringify([source, target]);
118
123
  const baseEdges = new Set((base?.relationships ?? []).map((r) => edgeKey(baseSvcOf(r.source), baseSvcOf(r.target))));
119
124
  for (const e of taggedEls) {
120
- if (ACTOR_KINDS.has(e.kind.toLowerCase()) || e.tags.includes(EXTERNAL_TAG))
125
+ if (ACTOR_KINDS.has(e.kind.toLowerCase()) || e.tags.includes(EXTERNAL_TAG) || groupsServices(e, elements, known))
121
126
  continue;
122
127
  if (baseIds.has(e.id) || baseServices.has(elementService(e)))
123
128
  continue;
124
129
  if (activeCovers.some((c) => coversElement(c, e)))
125
130
  continue;
131
+ // Spelled in the space it will live in, the line covers it too: the id the
132
+ // merge gives an element is the one the hint below recommends.
133
+ const cover = await survivingElementCover(e, { svcOf, known }, merged);
134
+ if (activeCovers.some((c) => c.form === "element" && c.id === cover))
135
+ continue;
126
136
  findings.push({
127
137
  severity: "warn",
128
138
  code: "c4.uncovered",
129
139
  subject: elementService(e),
130
- message: `delta adds '${e.title}' (${e.id}) but no arch requirement covers it — add 'Covers: ${e.id}' to a specs/<svc>/arch.spec.md delta, or its architectural obligations ship unchecked`,
140
+ message: `delta adds '${e.title}' (${e.id}) but no arch requirement covers it — add 'Covers: ${cover}' to a specs/<svc>/arch.spec.md delta, or its architectural obligations ship unchecked`,
131
141
  });
132
142
  }
133
143
  for (const r of taggedRels) {
@@ -139,7 +149,7 @@ export async function deltaArchCoverage(delta) {
139
149
  severity: "warn",
140
150
  code: "c4.uncovered",
141
151
  subject: svcOf(r.target),
142
- message: `delta adds edge ${svcOf(r.source)} → ${svcOf(r.target)} ("${r.title ?? ""}") but no arch requirement covers it — add 'Covers: ${r.source} -> ${r.target}' to a specs/<svc>/arch.spec.md delta`,
152
+ message: `delta adds edge ${svcOf(r.source)} → ${svcOf(r.target)} ("${r.title ?? ""}") but no arch requirement covers it — add 'Covers: ${survivingEdgeCover(r, svcOf)}' to a specs/<svc>/arch.spec.md delta`,
143
153
  });
144
154
  }
145
155
  // covers.unknown, feature scope. Resolution looks at the delta itself, the
@@ -153,30 +163,71 @@ export async function deltaArchCoverage(delta) {
153
163
  const landParses = land !== null && land.errors.length === 0 ? land : null;
154
164
  const baseElements = [...elements, ...(landParses?.elements ?? [])];
155
165
  const baseRels = [...relationships, ...(landParses?.relationships ?? [])];
166
+ // A feature never brings topology through `delta.likec4` — a `deployment { }`
167
+ // block in one is refused by the merge — so the living map is the whole
168
+ // scope for a `node:` entry in a delta, exactly as it is in service scope.
169
+ const baseDeployment = landParses?.deployment;
156
170
  for (const { service: svc, reqs } of archDeltas) {
157
171
  // An unreadable living health.yaml mutes the alert:/sli: entries here
158
172
  // exactly as in service scope — the health.invalid finding itself
159
173
  // belongs to the service target, which owns the file's diagnosis.
160
- const health = await readHealth((await locateServicePaths(docsDir, svc, fleet)).health);
161
- let scope = { elements: baseElements, relationships: baseRels, health: health.ids, known };
174
+ const svcPaths = await locateServicePaths(docsDir, svc, fleet);
175
+ const health = await readHealth(svcPaths.health);
176
+ // Through the ONE reader of `model.likec4`: a model that EXTENDS the map
177
+ // is not a file this could open, and reading it as one would answer with
178
+ // a pile of parse errors — which this arm reads as "no widening", so
179
+ // every `Covers:` line naming a container of a migrated service would be
180
+ // convicted as a typo. `mapUnreadable` is the same silence for the same
181
+ // reason: nothing may widen a scope out of a document nobody could read.
182
+ // Read at most once, and only when a line needs it.
183
+ let modelRead;
184
+ const model = () => (modelRead ??= (async () => {
185
+ const m = existsSync(svcPaths.model) ? await fleet.serviceModel(docsDir, svcPaths) : null;
186
+ return m !== null && !m.mapUnreadable && m.doc.errors.length === 0
187
+ ? { elements: m.doc.elements, relationships: m.doc.relationships }
188
+ : { elements: [], relationships: [] };
189
+ })());
190
+ let scope = {
191
+ elements: baseElements,
192
+ relationships: baseRels,
193
+ ...(baseDeployment === undefined ? {} : { deployment: baseDeployment }),
194
+ health: health.ids,
195
+ known,
196
+ };
162
197
  const unresolved = coversUnknownFindings(reqs, { where: `${svc}: arch.spec.md`, subject: svc }, scope, health.unreadable);
163
198
  if (unresolved.length > 0) {
164
- const modelPath = (await locateServicePaths(docsDir, svc, fleet)).model;
165
- const model = existsSync(modelPath)
166
- ? fleet === undefined
167
- ? await loadFile(modelPath)
168
- : await fleet.loadLikeC4(modelPath)
169
- : null;
170
- if (model !== null && model.errors.length === 0) {
171
- scope = {
172
- elements: [...baseElements, ...model.elements],
173
- relationships: [...baseRels, ...model.relationships],
174
- health: health.ids,
175
- known,
176
- };
199
+ const m = await model();
200
+ // Widened, never narrowed: the topology rides along. Rebuilding the
201
+ // record without it convicted every `node:` entry as a typo the moment
202
+ // another entry beside it sent the scope here.
203
+ scope = {
204
+ ...scope,
205
+ elements: [...baseElements, ...m.elements],
206
+ relationships: [...baseRels, ...m.relationships],
207
+ };
208
+ // The map the merge would leave widens it last, and only for a line still
209
+ // unresolved: one spelled the way the living map will spell an element
210
+ // this feature adds resolves there and nowhere else yet — and it is the
211
+ // spelling the hints recommend.
212
+ const after = coversUnknownFindings(reqs, { where: svc, subject: svc }, scope, health.unreadable).length > 0 ? (await merged())?.doc : undefined;
213
+ if (after !== undefined) {
214
+ scope = { ...scope, elements: [...scope.elements, ...after.elements], relationships: [...scope.relationships, ...after.relationships] };
177
215
  }
178
216
  findings.push(...coversUnknownFindings(reqs, { where: `${svc}: arch.spec.md`, subject: svc }, scope, health.unreadable));
179
217
  }
218
+ // And the lines that DID resolve, read in the space they will live in:
219
+ // one that answered only through the delta's own ids is `covers.unknown`
220
+ // the moment the archive lands it (./coverage/covers-after.ts).
221
+ findings.push(...(await deltaSpelledCovers({
222
+ service: svc,
223
+ reqs,
224
+ featureScope: scope,
225
+ living: { elements: landParses?.elements ?? [], relationships: landParses?.relationships ?? [] },
226
+ model,
227
+ elements,
228
+ svcOf,
229
+ merged,
230
+ })));
180
231
  }
181
232
  }
182
233
  return findings;
@@ -1 +1 @@
1
- {"version":3,"file":"arch-coverage.js","sourceRoot":"","sources":["../../../src/commands/validate/arch-coverage.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Whether the architecture a delta INTRODUCES is covered by a requirement that\n * will actually merge.\n *\n * Three findings, one question asked three ways: `archedge.uncovered` (a\n * scenario names the new edge — heuristic, warn-only), `c4.uncovered` (an\n * arch.spec.md requirement covers the new element or edge — mechanical), and\n * `covers.unknown` (the `Covers:` line resolves to something real). This is\n * where agent-built code cuts its corners — the outbox, the retries, the alerts\n * — because no business scenario was ever going to mention them.\n *\n * Split out of `validateFeature` because it is the only part of the feature\n * target that needs the LIVING landscape: everything else there reads the\n * feature directory alone. Keeping the lazy load and its two exemption sets in\n * one module is what stops \"new\" being decided differently in three places.\n */\nimport { existsSync } from \"node:fs\";\nimport { loadFile, type Elem, type LoadedDoc, type Rel } from \"../../core/c4/likec4.js\";\nimport { elementService, serviceResolver } from \"../../core/c4/resolve/service.js\";\nimport { type PathableService } from \"../../core/kernel/ids/service.js\";\nimport { landscapePath as landscapeFile } from \"../../core/repo/paths.js\";\nimport { locateServicePaths } from \"../../core/repo/service-target.js\";\nimport { enumeratedServiceIds } from \"../../core/repo/service-target.js\";\nimport { type Finding } from \"../../core/vocabulary/report.js\";\nimport { type Requirement } from \"../../core/document/spec.js\";\nimport { coversEdge, coversElement, type CoverageScope } from \"../../core/c4/arch.js\";\nimport { readHealth } from \"../../core/vocabulary/health.js\";\nimport { FleetContext } from \"../../core/fleet-context.js\";\nimport { ACTOR_KINDS, EXTERNAL_TAG } from \"../../core/vocabulary/maturity.js\";\nimport { coversEntries, coversUnknownFindings } from \"./checks/requirements.js\";\nimport type { DocsDir } from \"../../core/kernel/ids/dirs.js\";\n\n/** One feature delta's architecture, and everything needed to decide what in it is new. */\nexport interface DeltaArch {\n docsDir: DocsDir;\n /** Every element the delta declares — the resolver's index, and `coversEdge`'s scope. */\n elements: Elem[];\n /** Every relationship the delta declares. */\n relationships: Rel[];\n /** The delta's own additions: elements and edges carrying the feature id as a tag. */\n taggedEls: Elem[];\n taggedRels: Rel[];\n /** Each addressed service's arch.spec.md delta, in enumeration order. */\n archDeltas: Array<{ service: PathableService; reqs: Requirement[] }>;\n /**\n * Every service the feature's `specs/` addresses — not just the ones with an\n * arch delta. The resolver's fleet set unions these in because a service the\n * feature INTRODUCES has no `services/` directory yet, and without its name\n * an edge into that service's own modelled container resolved to the\n * container's title — a phantom the fleet half alone cannot rule out.\n */\n featureServices: PathableService[];\n /** Every scenario the feature's deltas carry, lowercased — the heuristic's haystack. */\n scenarioText: string;\n /** The living landscape under --all; undefined means \"load it if you need it\", null \"there is none\". */\n preloadedLand?: LoadedDoc | null;\n fleet?: FleetContext;\n}\n\nexport async function deltaArchCoverage(delta: DeltaArch): Promise<Finding[]> {\n const {\n docsDir,\n elements,\n relationships,\n taggedEls,\n taggedRels,\n archDeltas,\n featureServices,\n scenarioText,\n preloadedLand,\n fleet,\n } = delta;\n const findings: Finding[] = [];\n\n // The delta's own element→service resolver, built once for the whole feature.\n // `serviceOf` is a one-shot wrapper that rebuilds its index on every call, and\n // the two loops below ask it up to five times per tagged edge — so a delta\n // over a large model paid for one Map of every element per question asked.\n // The enumerated fleet — `services/` plus the feature's own `specs/` names,\n // where a service it introduces lives — rides into it, and into `baseSvcOf`\n // below, which MUST resolve the same way or the already-living exemption\n // keys never match: so an edge drawn into a modelled container\n // (`payment.api`) grades against the service that owns it instead of a\n // service called \"api\" that has never existed. An unenumerable services/\n // degrades to the feature's own names, exactly what every caller got before\n // the set existed.\n const known: ReadonlySet<string> = new Set<string>([\n ...(await enumeratedServiceIds(docsDir, fleet)),\n ...featureServices,\n ]);\n const svcOf = serviceResolver(elements, known);\n\n // Arch-edge coverage (heuristic, warn-only): each new tagged edge should be named by a scenario.\n for (const r of taggedRels) {\n const target = svcOf(r.target);\n const covered = edgeCovered(target, r.title, scenarioText);\n findings.push({\n severity: covered ? \"ok\" : \"warn\",\n code: covered ? \"archedge.covered\" : \"archedge.uncovered\",\n subject: target,\n message: `${svcOf(r.source)} → ${target} \"${r.title ?? \"\"}\"${covered ? \"\" : \" — no scenario names it\"}`,\n text: { indent: 4, header: \"arch-edge coverage (heuristic):\" },\n });\n }\n\n // The architecture spec axis, feature scope — the mechanical counterpart of\n // the heuristic above. Every NEW tagged element and edge in the delta wants a\n // `Covers:` line in one of the feature's arch.spec.md deltas (c4.uncovered):\n // this is where agent-built code cuts its corners — the outbox, the retries,\n // the alerts — because no business scenario was ever going to mention them.\n // Grouping-only elements take the same exemptions the fleet map applies\n // (person kinds, #external) — one set, in checks/vocabulary.ts, so \"not a\n // service\" cannot mean two things. Warnings, never archive gates; `--strict`\n // escalates.\n //\n // Only requirements the archive will MERGE grant coverage here. In a delta,\n // BASE means \"the living state, quoted\": it merges nothing, emits no\n // .feature, and yields no scenario.tested claim — so a Covers: line under a\n // plain `## Requirements` quote is an obligation that ships nowhere, and\n // counting it silenced c4.uncovered for free. (The service-scope pass keeps\n // the unfiltered call: a LIVING spec is legitimately all BASE.)\n const activeCovers = archDeltas.flatMap(({ reqs }) =>\n coversEntries(reqs.filter((r) => r.kind === \"ADDED\" || r.kind === \"MODIFIED\")),\n );\n\n // What the living landscape ALREADY holds. A delta has to re-declare the\n // elements its new edges attach to, and authors tag those re-declarations\n // along with everything else — so a requirements-only feature that touches an\n // existing service was told to write `Covers:` lines for architecture it is\n // not adding. c4.uncovered is an obligation on NEW architecture; an element\n // the living landscape already resolves is not new, whatever the tag says.\n // Loaded lazily: a delta with nothing tagged never pays for the parse.\n let living: LoadedDoc | null | undefined = preloadedLand;\n const livingLandscape = async (): Promise<LoadedDoc | null> => {\n if (living === undefined) {\n const lp = landscapeFile(docsDir);\n living = existsSync(lp)\n ? fleet === undefined\n ? await loadFile(lp)\n : await fleet.loadLikeC4(lp)\n : null;\n }\n return living;\n };\n const alreadyLiving = async (): Promise<LoadedDoc | null> => {\n if (taggedEls.length === 0 && taggedRels.length === 0) return null;\n const doc = await livingLandscape();\n return doc !== null && doc.errors.length === 0 ? doc : null;\n };\n const base = await alreadyLiving();\n const baseSvcOf = base === null ? null : serviceResolver(base.elements, known);\n const baseIds = new Set(base?.elements.map((e) => e.id) ?? []);\n const baseServices = new Set((base?.elements ?? []).map(elementService));\n // How a service→service pair is keyed, spelled ONCE. The two sides used to\n // join with different separators — a NUL where the set was built, a space\n // where it was queried — so the exemption never matched anything, and every\n // edge a delta re-declares verbatim (which it must, to attach anything to\n // it) was reported as new architecture nobody covers. The join is structural\n // rather than a separator character: the last one was a NUL, and a raw NUL in\n // a template literal makes the source read as binary to `file` and invisible\n // to `grep` — which is how a one-character mismatch survived review.\n const edgeKey = (source: string, target: string): string => JSON.stringify([source, target]);\n const baseEdges = new Set(\n (base?.relationships ?? []).map((r) => edgeKey(baseSvcOf!(r.source), baseSvcOf!(r.target))),\n );\n\n for (const e of taggedEls) {\n if (ACTOR_KINDS.has(e.kind.toLowerCase()) || e.tags.includes(EXTERNAL_TAG)) continue;\n if (baseIds.has(e.id) || baseServices.has(elementService(e))) continue;\n if (activeCovers.some((c) => coversElement(c, e))) continue;\n findings.push({\n severity: \"warn\",\n code: \"c4.uncovered\",\n subject: elementService(e),\n message: `delta adds '${e.title}' (${e.id}) but no arch requirement covers it — add 'Covers: ${e.id}' to a specs/<svc>/arch.spec.md delta, or its architectural obligations ship unchecked`,\n });\n }\n for (const r of taggedRels) {\n if (baseEdges.has(edgeKey(svcOf(r.source), svcOf(r.target)))) continue;\n if (activeCovers.some((c) => coversEdge(c, r, elements, known))) continue;\n findings.push({\n severity: \"warn\",\n code: \"c4.uncovered\",\n subject: svcOf(r.target),\n message: `delta adds edge ${svcOf(r.source)} → ${svcOf(r.target)} (\"${r.title ?? \"\"}\") but no arch requirement covers it — add 'Covers: ${r.source} -> ${r.target}' to a specs/<svc>/arch.spec.md delta`,\n });\n }\n\n // covers.unknown, feature scope. Resolution looks at the delta itself, the\n // living landscape, the service's own model and its health.yaml — a delta's\n // arch requirement may cover an element it adds, one that already exists, or\n // an alert the service declares. The landscape and each model are loaded\n // lazily, and only when an entry fails against what is already in hand: the\n // clean path never pays for a workspace spin.\n if (archDeltas.some(({ reqs }) => coversEntries(reqs).length > 0)) {\n const land = await livingLandscape();\n const landParses = land !== null && land.errors.length === 0 ? land : null;\n const baseElements = [...elements, ...(landParses?.elements ?? [])];\n const baseRels = [...relationships, ...(landParses?.relationships ?? [])];\n for (const { service: svc, reqs } of archDeltas) {\n // An unreadable living health.yaml mutes the alert:/sli: entries here\n // exactly as in service scope — the health.invalid finding itself\n // belongs to the service target, which owns the file's diagnosis.\n const health = await readHealth((await locateServicePaths(docsDir, svc, fleet)).health);\n let scope: CoverageScope = { elements: baseElements, relationships: baseRels, health: health.ids, known };\n const unresolved = coversUnknownFindings(reqs, { where: `${svc}: arch.spec.md`, subject: svc }, scope, health.unreadable);\n if (unresolved.length > 0) {\n const modelPath = (await locateServicePaths(docsDir, svc, fleet)).model;\n const model = existsSync(modelPath)\n ? fleet === undefined\n ? await loadFile(modelPath)\n : await fleet.loadLikeC4(modelPath)\n : null;\n if (model !== null && model.errors.length === 0) {\n scope = {\n elements: [...baseElements, ...model.elements],\n relationships: [...baseRels, ...model.relationships],\n health: health.ids,\n known,\n };\n }\n findings.push(...coversUnknownFindings(reqs, { where: `${svc}: arch.spec.md`, subject: svc }, scope, health.unreadable));\n }\n }\n }\n\n return findings;\n}\n\n/** Heuristic: an edge is \"covered\" if a scenario names the target or a keyword from the edge title. */\nfunction edgeCovered(target: string, title: string | undefined, scenarioText: string): boolean {\n if (scenarioText.includes(target.toLowerCase())) return true;\n for (const token of (title ?? \"\").split(/[^A-Za-z0-9]+/)) {\n if (token.length >= 5 && scenarioText.includes(token.toLowerCase())) return true;\n }\n return false;\n}\n"]}
1
+ {"version":3,"file":"arch-coverage.js","sourceRoot":"","sources":["../../../src/commands/validate/arch-coverage.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Whether the architecture a delta INTRODUCES is covered by a requirement that\n * will actually merge.\n *\n * Three findings, one question asked three ways: `archedge.uncovered` (a\n * scenario names the new edge — heuristic, warn-only), `c4.uncovered` (an\n * arch.spec.md requirement covers the new element or edge — mechanical), and\n * `covers.unknown` (the `Covers:` line resolves to something real). This is\n * where agent-built code cuts its corners — the outbox, the retries, the alerts\n * — because no business scenario was ever going to mention them.\n *\n * Split out of `validateFeature` because it is the only part of the feature\n * target that needs the LIVING landscape: everything else there reads the\n * feature directory alone. Keeping the lazy load and its two exemption sets in\n * one module is what stops \"new\" being decided differently in three places.\n */\nimport { existsSync } from \"node:fs\";\nimport { type Elem, type LoadedDoc, type Rel } from \"../../core/c4/likec4.js\";\nimport { elementService, serviceResolver } from \"../../core/c4/resolve/service.js\";\nimport { groupsServices } from \"../../core/c4/resolve/systems.js\";\nimport { type PathableService } from \"../../core/kernel/ids/service.js\";\nimport { landscapePath as landscapeFile } from \"../../core/repo/paths.js\";\nimport { locateServicePaths } from \"../../core/repo/service-target.js\";\nimport { enumeratedServiceIds } from \"../../core/repo/service-target.js\";\nimport { type Finding } from \"../../core/vocabulary/report.js\";\nimport { type Requirement } from \"../../core/document/spec.js\";\nimport { coversEdge, coversElement, type CoverageScope } from \"../../core/c4/arch.js\";\nimport { readHealth } from \"../../core/vocabulary/health.js\";\nimport { FleetContext } from \"../../core/fleet-context.js\";\nimport { ACTOR_KINDS, EXTERNAL_TAG } from \"../../core/vocabulary/maturity.js\";\nimport { coversEntries, coversUnknownFindings } from \"./checks/requirements.js\";\nimport { deltaSpelledCovers, mergedMapOf, survivingEdgeCover, survivingElementCover } from \"./coverage/covers-after.js\";\nimport type { DocsDir, FeatureDir } from \"../../core/kernel/ids/dirs.js\";\n\n/** One feature delta's architecture, and everything needed to decide what in it is new. */\nexport interface DeltaArch {\n docsDir: DocsDir;\n /** The feature itself — what the merge preview a `Covers:` line is checked against is computed from. */\n featureDir: FeatureDir;\n featureId: string;\n /** Every element the delta declares — the resolver's index, and `coversEdge`'s scope. */\n elements: Elem[];\n /** Every relationship the delta declares. */\n relationships: Rel[];\n /** The delta's own additions: elements and edges carrying the feature id as a tag. */\n taggedEls: Elem[];\n taggedRels: Rel[];\n /** Each addressed service's arch.spec.md delta, in enumeration order. */\n archDeltas: Array<{ service: PathableService; reqs: Requirement[] }>;\n /**\n * Every service the feature's `specs/` addresses — not just the ones with an\n * arch delta. The resolver's fleet set unions these in because a service the\n * feature INTRODUCES has no `services/` directory yet, and without its name\n * an edge into that service's own modelled container resolved to the\n * container's title — a phantom the fleet half alone cannot rule out.\n */\n featureServices: PathableService[];\n /** Every scenario the feature's deltas carry, lowercased — the heuristic's haystack. */\n scenarioText: string;\n /** The living landscape under --all; undefined means \"load it if you need it\", null \"there is none\". */\n preloadedLand?: LoadedDoc | null;\n /**\n * The read index the service models below are read through. Required, for\n * `validateService`'s reason: `serviceModel` needs the enumeration and a\n * document memo to answer at all. Every validate mode builds one before it\n * grades anything — `--feature` included (`validate.ts`) — so there is no\n * second, unmemoised reading rule here for a run that arrived without one.\n */\n fleet: FleetContext;\n}\n\nexport async function deltaArchCoverage(delta: DeltaArch): Promise<Finding[]> {\n const {\n docsDir,\n featureDir,\n featureId,\n elements,\n relationships,\n taggedEls,\n taggedRels,\n archDeltas,\n featureServices,\n scenarioText,\n preloadedLand,\n fleet,\n } = delta;\n const findings: Finding[] = [];\n\n // The delta's own element→service resolver, built once for the whole feature.\n // `serviceOf` is a one-shot wrapper that rebuilds its index on every call, and\n // the two loops below ask it up to five times per tagged edge — so a delta\n // over a large model paid for one Map of every element per question asked.\n // The enumerated fleet — `services/` plus the feature's own `specs/` names,\n // where a service it introduces lives — rides into it, and into `baseSvcOf`\n // below, which MUST resolve the same way or the already-living exemption\n // keys never match: so an edge drawn into a modelled container\n // (`payment.api`) grades against the service that owns it instead of a\n // service called \"api\" that has never existed. An unenumerable services/\n // degrades to the feature's own names, exactly what every caller got before\n // the set existed.\n const known: ReadonlySet<string> = new Set<string>([\n ...(await enumeratedServiceIds(docsDir, fleet)),\n ...featureServices,\n ]);\n const svcOf = serviceResolver(elements, known);\n // The map this feature's merge would leave, parsed at most once and only when\n // a hint or a `Covers:` line needs it (./coverage/covers-after.ts says when).\n const merged = mergedMapOf({ docsDir, featureDir, featureId, fleet, known });\n\n // Arch-edge coverage (heuristic, warn-only): each new tagged edge should be named by a scenario.\n for (const r of taggedRels) {\n const target = svcOf(r.target);\n const covered = edgeCovered(target, r.title, scenarioText);\n findings.push({\n severity: covered ? \"ok\" : \"warn\",\n code: covered ? \"archedge.covered\" : \"archedge.uncovered\",\n subject: target,\n message: `${svcOf(r.source)} → ${target} \"${r.title ?? \"\"}\"${covered ? \"\" : \" — no scenario names it\"}`,\n text: { indent: 4, header: \"arch-edge coverage (heuristic):\" },\n });\n }\n\n // The architecture spec axis, feature scope — the mechanical counterpart of\n // the heuristic above. Every NEW tagged element and edge in the delta wants a\n // `Covers:` line in one of the feature's arch.spec.md deltas (c4.uncovered):\n // this is where agent-built code cuts its corners — the outbox, the retries,\n // the alerts — because no business scenario was ever going to mention them.\n // Grouping-only elements take the same exemptions the fleet map applies\n // (person kinds, #external) — one set, in core/vocabulary/maturity.ts, so\n // \"not a service\" cannot mean two things — and so does a GROUPING, an element\n // that stands for no service and contains one (core/c4/resolve/systems.ts).\n // A new domain drawn around a new service was asked for a `Covers:` line of\n // its own: there is no obligation a group can carry, and the service inside\n // it is graded on its own. Warnings, never archive gates; `--strict`\n // escalates.\n //\n // Only requirements the archive will MERGE grant coverage here. In a delta,\n // BASE means \"the living state, quoted\": it merges nothing, emits no\n // .feature, and yields no scenario.tested claim — so a Covers: line under a\n // plain `## Requirements` quote is an obligation that ships nowhere, and\n // counting it silenced c4.uncovered for free. (The service-scope pass keeps\n // the unfiltered call: a LIVING spec is legitimately all BASE.)\n const activeCovers = archDeltas.flatMap(({ reqs }) =>\n coversEntries(reqs.filter((r) => r.kind === \"ADDED\" || r.kind === \"MODIFIED\")),\n );\n\n // What the living landscape ALREADY holds. A delta has to re-declare the\n // elements its new edges attach to, and authors tag those re-declarations\n // along with everything else — so a requirements-only feature that touches an\n // existing service was told to write `Covers:` lines for architecture it is\n // not adding. c4.uncovered is an obligation on NEW architecture; an element\n // the living landscape already resolves is not new, whatever the tag says.\n // Loaded lazily: a delta with nothing tagged never pays for the parse.\n let living: LoadedDoc | null | undefined = preloadedLand;\n const livingLandscape = async (): Promise<LoadedDoc | null> => {\n if (living === undefined) {\n const lp = landscapeFile(docsDir);\n living = existsSync(lp) ? await fleet.loadLikeC4(lp) : null;\n }\n return living;\n };\n const alreadyLiving = async (): Promise<LoadedDoc | null> => {\n if (taggedEls.length === 0 && taggedRels.length === 0) return null;\n const doc = await livingLandscape();\n return doc !== null && doc.errors.length === 0 ? doc : null;\n };\n const base = await alreadyLiving();\n const baseSvcOf = base === null ? null : serviceResolver(base.elements, known);\n const baseIds = new Set(base?.elements.map((e) => e.id) ?? []);\n const baseServices = new Set((base?.elements ?? []).map(elementService));\n // How a service→service pair is keyed, spelled ONCE. The two sides used to\n // join with different separators — a NUL where the set was built, a space\n // where it was queried — so the exemption never matched anything, and every\n // edge a delta re-declares verbatim (which it must, to attach anything to\n // it) was reported as new architecture nobody covers. The join is structural\n // rather than a separator character: the last one was a NUL, and a raw NUL in\n // a template literal makes the source read as binary to `file` and invisible\n // to `grep` — which is how a one-character mismatch survived review.\n const edgeKey = (source: string, target: string): string => JSON.stringify([source, target]);\n const baseEdges = new Set(\n (base?.relationships ?? []).map((r) => edgeKey(baseSvcOf!(r.source), baseSvcOf!(r.target))),\n );\n\n for (const e of taggedEls) {\n if (ACTOR_KINDS.has(e.kind.toLowerCase()) || e.tags.includes(EXTERNAL_TAG) || groupsServices(e, elements, known)) continue;\n if (baseIds.has(e.id) || baseServices.has(elementService(e))) continue;\n if (activeCovers.some((c) => coversElement(c, e))) continue;\n // Spelled in the space it will live in, the line covers it too: the id the\n // merge gives an element is the one the hint below recommends.\n const cover = await survivingElementCover(e, { svcOf, known }, merged);\n if (activeCovers.some((c) => c.form === \"element\" && c.id === cover)) continue;\n findings.push({\n severity: \"warn\",\n code: \"c4.uncovered\",\n subject: elementService(e),\n message: `delta adds '${e.title}' (${e.id}) but no arch requirement covers it — add 'Covers: ${cover}' to a specs/<svc>/arch.spec.md delta, or its architectural obligations ship unchecked`,\n });\n }\n for (const r of taggedRels) {\n if (baseEdges.has(edgeKey(svcOf(r.source), svcOf(r.target)))) continue;\n if (activeCovers.some((c) => coversEdge(c, r, elements, known))) continue;\n findings.push({\n severity: \"warn\",\n code: \"c4.uncovered\",\n subject: svcOf(r.target),\n message: `delta adds edge ${svcOf(r.source)} → ${svcOf(r.target)} (\"${r.title ?? \"\"}\") but no arch requirement covers it — add 'Covers: ${survivingEdgeCover(r, svcOf)}' to a specs/<svc>/arch.spec.md delta`,\n });\n }\n\n // covers.unknown, feature scope. Resolution looks at the delta itself, the\n // living landscape, the service's own model and its health.yaml — a delta's\n // arch requirement may cover an element it adds, one that already exists, or\n // an alert the service declares. The landscape and each model are loaded\n // lazily, and only when an entry fails against what is already in hand: the\n // clean path never pays for a workspace spin.\n if (archDeltas.some(({ reqs }) => coversEntries(reqs).length > 0)) {\n const land = await livingLandscape();\n const landParses = land !== null && land.errors.length === 0 ? land : null;\n const baseElements = [...elements, ...(landParses?.elements ?? [])];\n const baseRels = [...relationships, ...(landParses?.relationships ?? [])];\n // A feature never brings topology through `delta.likec4` — a `deployment { }`\n // block in one is refused by the merge — so the living map is the whole\n // scope for a `node:` entry in a delta, exactly as it is in service scope.\n const baseDeployment = landParses?.deployment;\n for (const { service: svc, reqs } of archDeltas) {\n // An unreadable living health.yaml mutes the alert:/sli: entries here\n // exactly as in service scope — the health.invalid finding itself\n // belongs to the service target, which owns the file's diagnosis.\n const svcPaths = await locateServicePaths(docsDir, svc, fleet);\n const health = await readHealth(svcPaths.health);\n // Through the ONE reader of `model.likec4`: a model that EXTENDS the map\n // is not a file this could open, and reading it as one would answer with\n // a pile of parse errors — which this arm reads as \"no widening\", so\n // every `Covers:` line naming a container of a migrated service would be\n // convicted as a typo. `mapUnreadable` is the same silence for the same\n // reason: nothing may widen a scope out of a document nobody could read.\n // Read at most once, and only when a line needs it.\n let modelRead: Promise<{ elements: Elem[]; relationships: Rel[] }> | undefined;\n const model = (): Promise<{ elements: Elem[]; relationships: Rel[] }> =>\n (modelRead ??= (async () => {\n const m = existsSync(svcPaths.model) ? await fleet.serviceModel(docsDir, svcPaths) : null;\n return m !== null && !m.mapUnreadable && m.doc.errors.length === 0\n ? { elements: m.doc.elements, relationships: m.doc.relationships }\n : { elements: [], relationships: [] };\n })());\n let scope: CoverageScope = {\n elements: baseElements,\n relationships: baseRels,\n ...(baseDeployment === undefined ? {} : { deployment: baseDeployment }),\n health: health.ids,\n known,\n };\n const unresolved = coversUnknownFindings(reqs, { where: `${svc}: arch.spec.md`, subject: svc }, scope, health.unreadable);\n if (unresolved.length > 0) {\n const m = await model();\n // Widened, never narrowed: the topology rides along. Rebuilding the\n // record without it convicted every `node:` entry as a typo the moment\n // another entry beside it sent the scope here.\n scope = {\n ...scope,\n elements: [...baseElements, ...m.elements],\n relationships: [...baseRels, ...m.relationships],\n };\n // The map the merge would leave widens it last, and only for a line still\n // unresolved: one spelled the way the living map will spell an element\n // this feature adds resolves there and nowhere else yet — and it is the\n // spelling the hints recommend.\n const after = coversUnknownFindings(reqs, { where: svc, subject: svc }, scope, health.unreadable).length > 0 ? (await merged())?.doc : undefined;\n if (after !== undefined) {\n scope = { ...scope, elements: [...scope.elements, ...after.elements], relationships: [...scope.relationships, ...after.relationships] };\n }\n findings.push(...coversUnknownFindings(reqs, { where: `${svc}: arch.spec.md`, subject: svc }, scope, health.unreadable));\n }\n // And the lines that DID resolve, read in the space they will live in:\n // one that answered only through the delta's own ids is `covers.unknown`\n // the moment the archive lands it (./coverage/covers-after.ts).\n findings.push(\n ...(await deltaSpelledCovers({\n service: svc,\n reqs,\n featureScope: scope,\n living: { elements: landParses?.elements ?? [], relationships: landParses?.relationships ?? [] },\n model,\n elements,\n svcOf,\n merged,\n })),\n );\n }\n }\n\n return findings;\n}\n\n/** Heuristic: an edge is \"covered\" if a scenario names the target or a keyword from the edge title. */\nfunction edgeCovered(target: string, title: string | undefined, scenarioText: string): boolean {\n if (scenarioText.includes(target.toLowerCase())) return true;\n for (const token of (title ?? \"\").split(/[^A-Za-z0-9]+/)) {\n if (token.length >= 5 && scenarioText.includes(token.toLowerCase())) return true;\n }\n return false;\n}\n"]}
@@ -1,41 +1,35 @@
1
1
  /**
2
- * Fleet-shape advisories over the parsed landscape: the two ways a fleet map
3
- * stops answering questions as it grows, caught while the map is already in
4
- * memory.
2
+ * Fleet-shape advisories over the parsed landscape: the way a fleet map stops
3
+ * answering questions as it grows, caught while the map is already in memory.
5
4
  *
6
- * Both shapes become visible at service three rather than service two.
5
+ * The shape becomes visible at service three rather than service two.
7
6
  * Ubiquitous infrastructure — logging Kafka, an identity provider, service
8
7
  * discovery — takes one inbound edge per modelled service until the map is a
9
8
  * hairball around it; deleting the element fixes the picture and loses "who
10
9
  * depends on the Identity Provider", which is the question the map exists to
11
10
  * answer during an incident. Tagging keeps both: the fleet view excludes
12
- * `#platform`, and a platform view keeps the dependents. And a datastore drawn as a fleet-level
13
- * peer makes a claim its consumer count either supports or refutes: one
14
- * consumer means the drawing is false — the store is that service's
15
- * internals, not a system in its own right — while two or more mean the
16
- * strongest coupling two services can have, which deserves to be stated
17
- * rather than inferred.
11
+ * `#platform`, and a platform view keeps the dependents.
18
12
  *
19
- * Everything here is O(relationships) over data the fleet target already
20
- * holds. loam still reads no code and decides no policy: the team chooses
21
- * what counts as platform and which data is truly shared — these warnings
22
- * only name the shapes that are usually wrong.
13
+ * The DATASTORE half of this pair moved to `../fleet/map/consumers.ts` when its
14
+ * consumer count stopped being a fact about the map alone: a private store now
15
+ * lives nested inside its owner's element, and the services reaching it are
16
+ * attested in their own models (E3/R1). The census both checks read is built
17
+ * there and handed in here as `consumers`, so a hub and a store can never
18
+ * disagree about who consumes what.
19
+ *
20
+ * loam still reads no code and decides no policy: the team chooses what counts
21
+ * as platform — this warning only names a shape that is usually wrong.
23
22
  */
24
23
  import { existsSync } from "node:fs";
25
- import { readFile } from "node:fs/promises";
26
24
  import {} from "../../../core/c4/likec4.js";
27
- import {} from "../../../core/kernel/ids/service.js";
28
25
  import {} from "../../../core/vocabulary/report.js";
29
26
  import {} from "../../../core/repo/entries.js";
30
27
  import { permissionsPath, servicePathsAt } from "../../../core/repo/paths.js";
31
28
  import { readVocabulary } from "../../../core/permissions/permissions.js";
32
- import { readCapabilityVocabulary } from "../../../core/capabilities/capabilities.js";
33
29
  import { capabilityDocFindings, capabilityRequirementIndex, docMissingFindings, gradableCapabilityIds, invalidVocabularyFinding, unrealizedFindings, } from "../../../core/capabilities/findings.js";
34
30
  import { useCaseRequirementClaims } from "../../../core/usecases/capability.js";
35
31
  import { capabilityRollup, usedCapabilities } from "../../../core/capabilities/rollup.js";
36
32
  import { requirementUnrealizedFindings } from "../../../core/capabilities/realizes/findings.js";
37
- import { parseRequirements } from "../../../core/document/parse.js";
38
- import {} from "../../../core/document/spec.js";
39
33
  import { FleetContext } from "../../../core/fleet-context.js";
40
34
  import { EXTERNAL_TAG, PLATFORM_TAG } from "../../../core/vocabulary/maturity.js";
41
35
  /**
@@ -45,91 +39,33 @@ import { EXTERNAL_TAG, PLATFORM_TAG } from "../../../core/vocabulary/maturity.js
45
39
  * the shared hub starts making the map unreadable.
46
40
  */
47
41
  export const PLATFORM_CANDIDATE_MIN_CONSUMERS = 3;
48
- /** The element kind read as a datastore, compared case-insensitively. */
49
- const DATASTORE_KIND = "database";
50
42
  export function fleetShapeFindings(shape) {
51
- const { drawn, relationships, services, resolve } = shape;
43
+ const { drawn, services } = shape;
52
44
  const findings = [];
53
- // Distinct consumer SERVICES of an element, its nested children included: an
54
- // edge into `kafka.paymentEvents` is consumption of `kafka`. Persons, other
55
- // external systems and unresolved sources never count — a consumer is a
56
- // source the shared resolver files under a real services/<id>/, so two edges
57
- // from one service are one consumer.
58
- const consumersOf = (e) => {
59
- const out = new Set();
60
- for (const r of relationships) {
61
- if (r.target !== e.id && !r.target.startsWith(`${e.id}.`))
62
- continue;
63
- const svc = resolve(r.source);
64
- if (services.has(svc))
65
- out.add(svc);
66
- }
67
- return [...out].sort();
68
- };
69
45
  for (const e of drawn) {
70
46
  // An element that stands for a real service is the fleet itself, not its
71
- // shape: many consumers is what a well-used service looks like, and a
72
- // datastore bound to a directory is graded by the binding checks instead.
47
+ // shape: many consumers is what a well-used service looks like.
73
48
  if (e.service !== undefined || services.has(e.title))
74
49
  continue;
75
- const consumers = consumersOf(e);
76
- if (e.tags.includes(EXTERNAL_TAG) &&
77
- !e.tags.includes(PLATFORM_TAG) &&
78
- consumers.length >= PLATFORM_CANDIDATE_MIN_CONSUMERS) {
79
- findings.push({
80
- severity: "warn",
81
- code: "landscape.platform-candidate",
82
- subject: e.title,
83
- message: `landscape: '${e.title}' is consumed by ${consumers.length} services (${consumers.join(", ")}) ` +
84
- `and is not tagged #platform — a hub like this takes one more edge per modelled service until ` +
85
- `the fleet view is unreadable. Declare \`tag platform\` in the specification block and tag the ` +
86
- `element (LikeC4 refuses an undeclared tag, so both steps are needed): the fleet view then ` +
87
- `excludes it, and a platform view over \`include * -> element.tag = #platform\` keeps ` +
88
- `"who depends on it" answerable`,
89
- });
90
- }
91
- if (e.kind.toLowerCase() !== DATASTORE_KIND || consumers.length === 0)
50
+ if (!e.tags.includes(EXTERNAL_TAG) || e.tags.includes(PLATFORM_TAG))
92
51
  continue;
93
- if (consumers.length === 1) {
94
- findings.push({
95
- severity: "warn",
96
- code: "landscape.datastore-private",
97
- subject: e.title,
98
- message: `landscape: '${e.title}' is a datastore with a single consumer at fleet level ` +
99
- `('${consumers[0]}') — drawn as a peer it reads as a system in its own right, available to ` +
100
- `be depended on. Move it into ${shape.pathOf(consumers[0])}/model.likec4 as a nested container ` +
101
- `and delete it here, or add the second consumer's edge if another service really reaches ` +
102
- `the same data`,
103
- });
104
- }
105
- else {
106
- findings.push({
107
- severity: "warn",
108
- code: "landscape.datastore-shared",
109
- subject: e.title,
110
- message: `landscape: '${e.title}' is a datastore shared by ${consumers.length} services ` +
111
- `(${consumers.join(", ")}) — the strongest coupling two services can have, and the hardest ` +
112
- `to undo. Shared means the same DATA: if they read the same tables or keys, keep it drawn ` +
113
- `and let this warning state the coupling; if they only share a host or cluster (two schemas, ` +
114
- `two lock paths), that is operational blast radius — a runbook fact — and the honest model ` +
115
- `is one private store per service`,
116
- });
117
- }
52
+ const consumers = shape.consumers(e.id);
53
+ if (consumers.length < PLATFORM_CANDIDATE_MIN_CONSUMERS)
54
+ continue;
55
+ findings.push({
56
+ severity: "warn",
57
+ code: "landscape.platform-candidate",
58
+ subject: e.title,
59
+ message: `landscape: '${e.title}' is consumed by ${consumers.length} services (${consumers.join(", ")}) ` +
60
+ `and is not tagged #platform — a hub like this takes one more edge per modelled service until ` +
61
+ `the fleet view is unreadable. Declare \`tag platform\` in the specification block and tag the ` +
62
+ `element (LikeC4 refuses an undeclared tag, so both steps are needed): the fleet view then ` +
63
+ `excludes it, and a platform view over \`include * -> element.tag = #platform\` keeps ` +
64
+ `"who depends on it" answerable`,
65
+ });
118
66
  }
119
67
  return findings;
120
68
  }
121
- /**
122
- * The #external element that declares it PUBLISHES this message, or null —
123
- * the landscape-side half of the event spine's fleet question, beside the
124
- * other checks that read tags off the drawn map.
125
- *
126
- * Positive evidence only: an edge carrying `metadata { publishes '<msg>' }`
127
- * whose source element — itself or a declared ancestor, since the edge may
128
- * point out of a topic nested inside the broker — is tagged #external and
129
- * resolves to no known service directory. The resolution guard is what keeps
130
- * a mis-tagged internal service reading as unproduced: a tag is cheap to
131
- * write, and a services/<id>/ directory outranks it.
132
- */
133
69
  /**
134
70
  * The authorization vocabulary graded against the fleet that uses it — the half
135
71
  * of the axis no single service can answer.
@@ -165,14 +101,14 @@ export async function permissionFindings(docsDir, services, fleet) {
165
101
  for (const entry of services) {
166
102
  const paths = servicePathsAt(entry.dir);
167
103
  for (const path of [paths.spec, paths.archSpec]) {
168
- // Existence first, and for BOTH readers: arch.spec.md is optional (most
104
+ // Existence first, and for BOTH documents: arch.spec.md is optional (most
169
105
  // of a legacy fleet has none) and spec.md is missing on a half-adopted
170
106
  // service. `FleetContext.readRequirements` throws ENOENT, which surfaces
171
107
  // as `repository-unavailable` and takes the whole `--all` run down — an
172
108
  // absent optional artifact must never be able to do that.
173
109
  if (!existsSync(path))
174
110
  continue;
175
- const reqs = fleet === undefined ? await readRequirementsAt(path) : await fleet.readRequirements(path);
111
+ const reqs = await fleet.readRequirements(path);
176
112
  for (const r of reqs) {
177
113
  if (r.kind !== "REMOVED")
178
114
  for (const p of r.requires)
@@ -192,12 +128,6 @@ export async function permissionFindings(docsDir, services, fleet) {
192
128
  },
193
129
  ];
194
130
  }
195
- /** The uncached read, for the `--service` path where no fleet context exists. */
196
- async function readRequirementsAt(path) {
197
- if (!existsSync(path))
198
- return [];
199
- return parseRequirements(await readFile(path, "utf8"));
200
- }
201
131
  /**
202
132
  * The capability vocabulary graded against the fleet that realizes it — the
203
133
  * axis's fleet half, beside permissionFindings and shaped by the same two
@@ -227,10 +157,10 @@ async function readRequirementsAt(path) {
227
157
  * nobody read.
228
158
  */
229
159
  export async function capabilityFleetFindings(docsDir, services, fleet, flows) {
230
- const vocab = fleet === undefined ? await readCapabilityVocabulary(docsDir) : await fleet.capabilities(docsDir);
160
+ const vocab = await fleet.capabilities(docsDir);
231
161
  if (!vocab.present)
232
162
  return [];
233
- const read = fleet === undefined ? readRequirementsAt : (p) => fleet.readRequirements(p);
163
+ const read = (p) => fleet.readRequirements(p);
234
164
  const authored = docMissingFindings(vocab.tree);
235
165
  for (const doc of vocab.tree.docs)
236
166
  authored.push(...capabilityDocFindings(await read(doc.spec), doc.id));
@@ -271,26 +201,4 @@ export async function capabilityFleetFindings(docsDir, services, fleet, flows) {
271
201
  ...requirementUnrealizedFindings(unrealizedRequirements),
272
202
  ];
273
203
  }
274
- export function externalProducerOf(message, land, landSvcOf, known) {
275
- if (land === null || land.errors.length > 0 || landSvcOf === null)
276
- return null;
277
- const knownIds = known;
278
- const byId = new Map(land.elements.map((e) => [e.id, e]));
279
- for (const r of land.relationships) {
280
- if (r.publishes !== message)
281
- continue;
282
- if (knownIds.has(landSvcOf(r.source)))
283
- continue;
284
- for (let id = r.source;;) {
285
- const e = byId.get(id);
286
- if (e !== undefined && e.tags.includes(EXTERNAL_TAG))
287
- return e.title;
288
- const dot = id.lastIndexOf(".");
289
- if (dot === -1)
290
- break;
291
- id = id.slice(0, dot);
292
- }
293
- }
294
- return null;
295
- }
296
204
  //# sourceMappingURL=fleet-shape.js.map