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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1256) hide show
  1. package/CHANGELOG.md +5992 -82
  2. package/COMPARISON.md +168 -63
  3. package/CONTRIBUTING.md +121 -0
  4. package/MIGRATING-from-OpenSpec.md +238 -55
  5. package/QUICKSTART.md +302 -0
  6. package/README.md +653 -144
  7. package/ROADMAP.md +1035 -0
  8. package/SCHEMA.md +3916 -263
  9. package/SECURITY.md +21 -3
  10. package/WORKFLOW.md +927 -0
  11. package/dist/cli.js +133 -21
  12. package/dist/cli.js.map +1 -1
  13. package/dist/commands/adopt/adopt.js +204 -0
  14. package/dist/commands/adopt/adopt.js.map +1 -0
  15. package/dist/commands/adopt/render.js +309 -0
  16. package/dist/commands/adopt/render.js.map +1 -0
  17. package/dist/commands/archive/archive.js +74 -0
  18. package/dist/commands/archive/archive.js.map +1 -0
  19. package/dist/commands/archive/closing.js +42 -0
  20. package/dist/commands/archive/closing.js.map +1 -0
  21. package/dist/commands/archive/plan/contracts/asyncapi.js +172 -0
  22. package/dist/commands/archive/plan/contracts/asyncapi.js.map +1 -0
  23. package/dist/commands/archive/plan/contracts/consumers.js +56 -0
  24. package/dist/commands/archive/plan/contracts/consumers.js.map +1 -0
  25. package/dist/commands/archive/plan/contracts/openapi.js +193 -0
  26. package/dist/commands/archive/plan/contracts/openapi.js.map +1 -0
  27. package/dist/commands/archive/plan/contracts/verdict-lines.js +103 -0
  28. package/dist/commands/archive/plan/contracts/verdict-lines.js.map +1 -0
  29. package/dist/commands/archive/plan/document/head.js +151 -0
  30. package/dist/commands/archive/plan/document/head.js.map +1 -0
  31. package/dist/commands/archive/plan/document/links.js +284 -0
  32. package/dist/commands/archive/plan/document/links.js.map +1 -0
  33. package/dist/commands/archive/plan/document/run.js +136 -0
  34. package/dist/commands/archive/plan/document/run.js.map +1 -0
  35. package/dist/commands/archive/plan/gate.js +319 -0
  36. package/dist/commands/archive/plan/gate.js.map +1 -0
  37. package/dist/commands/archive/plan/landscape.js +298 -0
  38. package/dist/commands/archive/plan/landscape.js.map +1 -0
  39. package/dist/commands/archive/plan/model/extending.js +85 -0
  40. package/dist/commands/archive/plan/model/extending.js.map +1 -0
  41. package/dist/commands/archive/plan/refusal.js +106 -0
  42. package/dist/commands/archive/plan/refusal.js.map +1 -0
  43. package/dist/commands/archive/plan/specs.js +318 -0
  44. package/dist/commands/archive/plan/specs.js.map +1 -0
  45. package/dist/commands/archive/plan/state.js +30 -0
  46. package/dist/commands/archive/plan/state.js.map +1 -0
  47. package/dist/commands/archive/run.js +355 -0
  48. package/dist/commands/archive/run.js.map +1 -0
  49. package/dist/commands/archive/shipped.js +49 -0
  50. package/dist/commands/archive/shipped.js.map +1 -0
  51. package/dist/commands/context/context.js +166 -0
  52. package/dist/commands/context/context.js.map +1 -0
  53. package/dist/commands/context/print.js +305 -0
  54. package/dist/commands/context/print.js.map +1 -0
  55. package/dist/commands/delta/delta.js +367 -0
  56. package/dist/commands/delta/delta.js.map +1 -0
  57. package/dist/commands/delta/print.js +221 -0
  58. package/dist/commands/delta/print.js.map +1 -0
  59. package/dist/commands/dependencies.js +6 -8
  60. package/dist/commands/dependencies.js.map +1 -1
  61. package/dist/commands/diff/diff.js +86 -0
  62. package/dist/commands/diff/diff.js.map +1 -0
  63. package/dist/commands/diff/print.js +38 -0
  64. package/dist/commands/diff/print.js.map +1 -0
  65. package/dist/commands/doctor.js +65 -5
  66. package/dist/commands/doctor.js.map +1 -1
  67. package/dist/commands/explain/explain.js +227 -0
  68. package/dist/commands/explain/explain.js.map +1 -0
  69. package/dist/commands/explore.js +39 -28
  70. package/dist/commands/explore.js.map +1 -1
  71. package/dist/commands/gate/gate.js +152 -0
  72. package/dist/commands/gate/gate.js.map +1 -0
  73. package/dist/commands/gate/print.js +66 -0
  74. package/dist/commands/gate/print.js.map +1 -0
  75. package/dist/commands/gherkin/commit.js +105 -0
  76. package/dist/commands/gherkin/commit.js.map +1 -0
  77. package/dist/commands/gherkin/gherkin.js +262 -0
  78. package/dist/commands/gherkin/gherkin.js.map +1 -0
  79. package/dist/commands/gherkin/reconcile.js +146 -0
  80. package/dist/commands/gherkin/reconcile.js.map +1 -0
  81. package/dist/commands/gherkin/render.js +77 -0
  82. package/dist/commands/gherkin/render.js.map +1 -0
  83. package/dist/commands/init/example.js +204 -0
  84. package/dist/commands/init/example.js.map +1 -0
  85. package/dist/commands/init/first-hour.js +72 -0
  86. package/dist/commands/init/first-hour.js.map +1 -0
  87. package/dist/commands/{init.js → init/init.js} +142 -71
  88. package/dist/commands/init/init.js.map +1 -0
  89. package/dist/commands/init/mcp.js +131 -0
  90. package/dist/commands/init/mcp.js.map +1 -0
  91. package/dist/commands/init/options.js +78 -0
  92. package/dist/commands/init/options.js.map +1 -0
  93. package/dist/commands/instructions.js +72 -14
  94. package/dist/commands/instructions.js.map +1 -1
  95. package/dist/commands/list/campaign/campaign.js +63 -0
  96. package/dist/commands/list/campaign/campaign.js.map +1 -0
  97. package/dist/commands/list/campaign/owners.js +65 -0
  98. package/dist/commands/list/campaign/owners.js.map +1 -0
  99. package/dist/commands/list/json.js +155 -0
  100. package/dist/commands/list/json.js.map +1 -0
  101. package/dist/commands/list/list.js +358 -0
  102. package/dist/commands/list/list.js.map +1 -0
  103. package/dist/commands/list/print.js +344 -0
  104. package/dist/commands/list/print.js.map +1 -0
  105. package/dist/commands/list/review.js +120 -0
  106. package/dist/commands/list/review.js.map +1 -0
  107. package/dist/commands/list/suites/suites.js +140 -0
  108. package/dist/commands/list/suites/suites.js.map +1 -0
  109. package/dist/commands/list/views.js +108 -0
  110. package/dist/commands/list/views.js.map +1 -0
  111. package/dist/commands/mcp/dispatch.js +238 -0
  112. package/dist/commands/mcp/dispatch.js.map +1 -0
  113. package/dist/commands/mcp/mcp.js +75 -0
  114. package/dist/commands/mcp/mcp.js.map +1 -0
  115. package/dist/commands/mcp/serve.js +55 -0
  116. package/dist/commands/mcp/serve.js.map +1 -0
  117. package/dist/commands/migrate-openspec/materialize/active.js +175 -0
  118. package/dist/commands/migrate-openspec/materialize/active.js.map +1 -0
  119. package/dist/commands/migrate-openspec/materialize/feature.js +41 -0
  120. package/dist/commands/migrate-openspec/materialize/feature.js.map +1 -0
  121. package/dist/commands/migrate-openspec/materialize/living.js +62 -0
  122. package/dist/commands/migrate-openspec/materialize/living.js.map +1 -0
  123. package/dist/commands/migrate-openspec/materialize/stage.js +143 -0
  124. package/dist/commands/migrate-openspec/materialize/stage.js.map +1 -0
  125. package/dist/commands/migrate-openspec/materialize/target.js +219 -0
  126. package/dist/commands/migrate-openspec/materialize/target.js.map +1 -0
  127. package/dist/commands/migrate-openspec/migrate-openspec.js +142 -0
  128. package/dist/commands/migrate-openspec/migrate-openspec.js.map +1 -0
  129. package/dist/commands/migrate-openspec/openspec/decisions.js +86 -0
  130. package/dist/commands/migrate-openspec/openspec/decisions.js.map +1 -0
  131. package/dist/commands/migrate-openspec/openspec/error.js +18 -0
  132. package/dist/commands/migrate-openspec/openspec/error.js.map +1 -0
  133. package/dist/commands/migrate-openspec/openspec/mapping.js +162 -0
  134. package/dist/commands/migrate-openspec/openspec/mapping.js.map +1 -0
  135. package/dist/commands/migrate-openspec/openspec/paths.js +40 -0
  136. package/dist/commands/migrate-openspec/openspec/paths.js.map +1 -0
  137. package/dist/commands/migrate-openspec/openspec/read.js +49 -0
  138. package/dist/commands/migrate-openspec/openspec/read.js.map +1 -0
  139. package/dist/commands/migrate-openspec/print.js +89 -0
  140. package/dist/commands/migrate-openspec/print.js.map +1 -0
  141. package/dist/commands/new/capability-template.js +118 -0
  142. package/dist/commands/new/capability-template.js.map +1 -0
  143. package/dist/commands/new/commit.js +62 -0
  144. package/dist/commands/new/commit.js.map +1 -0
  145. package/dist/commands/new/modifies.js +206 -0
  146. package/dist/commands/new/modifies.js.map +1 -0
  147. package/dist/commands/new/new.js +328 -0
  148. package/dist/commands/new/new.js.map +1 -0
  149. package/dist/commands/new/templates.js +279 -0
  150. package/dist/commands/new/templates.js.map +1 -0
  151. package/dist/commands/open.js +199 -0
  152. package/dist/commands/open.js.map +1 -0
  153. package/dist/commands/policy/format.js +152 -0
  154. package/dist/commands/policy/format.js.map +1 -0
  155. package/dist/commands/{docs-repo-gate.js → policy/gate.js} +38 -11
  156. package/dist/commands/policy/gate.js.map +1 -0
  157. package/dist/commands/rebase/edit.js +106 -0
  158. package/dist/commands/rebase/edit.js.map +1 -0
  159. package/dist/commands/rebase/living.js +185 -0
  160. package/dist/commands/rebase/living.js.map +1 -0
  161. package/dist/commands/rebase/plan.js +245 -0
  162. package/dist/commands/rebase/plan.js.map +1 -0
  163. package/dist/commands/rebase/rebase.js +300 -0
  164. package/dist/commands/rebase/rebase.js.map +1 -0
  165. package/dist/commands/seed/commit.js +221 -0
  166. package/dist/commands/seed/commit.js.map +1 -0
  167. package/dist/commands/seed/plan.js +278 -0
  168. package/dist/commands/seed/plan.js.map +1 -0
  169. package/dist/commands/seed/seed.js +174 -0
  170. package/dist/commands/seed/seed.js.map +1 -0
  171. package/dist/commands/show/feature.js +182 -0
  172. package/dist/commands/show/feature.js.map +1 -0
  173. package/dist/commands/show/introduced.js +157 -0
  174. package/dist/commands/show/introduced.js.map +1 -0
  175. package/dist/commands/show/marks.js +53 -0
  176. package/dist/commands/show/marks.js.map +1 -0
  177. package/dist/commands/show/service.js +239 -0
  178. package/dist/commands/show/service.js.map +1 -0
  179. package/dist/commands/show/show.js +87 -0
  180. package/dist/commands/show/show.js.map +1 -0
  181. package/dist/commands/status/fleet-next.js +90 -0
  182. package/dist/commands/status/fleet-next.js.map +1 -0
  183. package/dist/commands/status/json.js +47 -0
  184. package/dist/commands/status/json.js.map +1 -0
  185. package/dist/commands/status/print.js +209 -0
  186. package/dist/commands/status/print.js.map +1 -0
  187. package/dist/commands/status/status.js +115 -0
  188. package/dist/commands/status/status.js.map +1 -0
  189. package/dist/commands/steps/steps.js +269 -0
  190. package/dist/commands/steps/steps.js.map +1 -0
  191. package/dist/commands/subsystem/edit.js +192 -0
  192. package/dist/commands/subsystem/edit.js.map +1 -0
  193. package/dist/commands/subsystem/move.js +325 -0
  194. package/dist/commands/subsystem/move.js.map +1 -0
  195. package/dist/commands/subsystem/query.js +113 -0
  196. package/dist/commands/subsystem/query.js.map +1 -0
  197. package/dist/commands/subsystem/subsystem.js +98 -0
  198. package/dist/commands/subsystem/subsystem.js.map +1 -0
  199. package/dist/commands/subsystem/sync.js +318 -0
  200. package/dist/commands/subsystem/sync.js.map +1 -0
  201. package/dist/commands/subsystem/txn/exclude.js +132 -0
  202. package/dist/commands/subsystem/txn/exclude.js.map +1 -0
  203. package/dist/commands/subsystem/txn/links.js +128 -0
  204. package/dist/commands/subsystem/txn/links.js.map +1 -0
  205. package/dist/commands/subsystem/txn/report.js +174 -0
  206. package/dist/commands/subsystem/txn/report.js.map +1 -0
  207. package/dist/commands/subsystem/txn/txn.js +196 -0
  208. package/dist/commands/subsystem/txn/txn.js.map +1 -0
  209. package/dist/commands/subsystem/txn/views.js +249 -0
  210. package/dist/commands/subsystem/txn/views.js.map +1 -0
  211. package/dist/commands/tasks/actions.js +107 -0
  212. package/dist/commands/tasks/actions.js.map +1 -0
  213. package/dist/commands/tasks/render.js +253 -0
  214. package/dist/commands/tasks/render.js.map +1 -0
  215. package/dist/commands/tasks/tasks.js +119 -0
  216. package/dist/commands/tasks/tasks.js.map +1 -0
  217. package/dist/commands/unarchive/manifest.js +176 -0
  218. package/dist/commands/unarchive/manifest.js.map +1 -0
  219. package/dist/commands/unarchive/restore.js +254 -0
  220. package/dist/commands/unarchive/restore.js.map +1 -0
  221. package/dist/commands/unarchive/unarchive.js +59 -0
  222. package/dist/commands/unarchive/unarchive.js.map +1 -0
  223. package/dist/commands/validate/arch-coverage.js +245 -0
  224. package/dist/commands/validate/arch-coverage.js.map +1 -0
  225. package/dist/commands/validate/checks/fleet-shape.js +204 -0
  226. package/dist/commands/validate/checks/fleet-shape.js.map +1 -0
  227. package/dist/commands/validate/checks/health-deps.js +58 -0
  228. package/dist/commands/validate/checks/health-deps.js.map +1 -0
  229. package/dist/commands/validate/checks/introduced.js +102 -0
  230. package/dist/commands/validate/checks/introduced.js.map +1 -0
  231. package/dist/commands/validate/checks/requirements.js +264 -0
  232. package/dist/commands/validate/checks/requirements.js.map +1 -0
  233. package/dist/commands/validate/checks/sources.js +85 -0
  234. package/dist/commands/validate/checks/sources.js.map +1 -0
  235. package/dist/commands/validate/coverage/covers-after.js +105 -0
  236. package/dist/commands/validate/coverage/covers-after.js.map +1 -0
  237. package/dist/commands/validate/feature.js +222 -0
  238. package/dist/commands/validate/feature.js.map +1 -0
  239. package/dist/commands/validate/fleet/census.js +93 -0
  240. package/dist/commands/validate/fleet/census.js.map +1 -0
  241. package/dist/commands/validate/fleet/kind-tags.js +39 -0
  242. package/dist/commands/validate/fleet/kind-tags.js.map +1 -0
  243. package/dist/commands/validate/fleet/landscape.js +371 -0
  244. package/dist/commands/validate/fleet/landscape.js.map +1 -0
  245. package/dist/commands/validate/fleet/load.js +118 -0
  246. package/dist/commands/validate/fleet/load.js.map +1 -0
  247. package/dist/commands/validate/fleet/map/attest.js +98 -0
  248. package/dist/commands/validate/fleet/map/attest.js.map +1 -0
  249. package/dist/commands/validate/fleet/map/bindings.js +107 -0
  250. package/dist/commands/validate/fleet/map/bindings.js.map +1 -0
  251. package/dist/commands/validate/fleet/map/consumers.js +244 -0
  252. package/dist/commands/validate/fleet/map/consumers.js.map +1 -0
  253. package/dist/commands/validate/fleet/map/isolation.js +116 -0
  254. package/dist/commands/validate/fleet/map/isolation.js.map +1 -0
  255. package/dist/commands/validate/fleet/map/usecases.js +54 -0
  256. package/dist/commands/validate/fleet/map/usecases.js.map +1 -0
  257. package/dist/commands/validate/fleet/obligations.js +266 -0
  258. package/dist/commands/validate/fleet/obligations.js.map +1 -0
  259. package/dist/commands/validate/fleet/scorecard/adoption.js +102 -0
  260. package/dist/commands/validate/fleet/scorecard/adoption.js.map +1 -0
  261. package/dist/commands/validate/fleet/scorecard/contracts.js +98 -0
  262. package/dist/commands/validate/fleet/scorecard/contracts.js.map +1 -0
  263. package/dist/commands/validate/fleet/scorecard/print.js +71 -0
  264. package/dist/commands/validate/fleet/scorecard/print.js.map +1 -0
  265. package/dist/commands/validate/fleet/scorecard/scorecard.js +162 -0
  266. package/dist/commands/validate/fleet/scorecard/scorecard.js.map +1 -0
  267. package/dist/commands/validate/fleet/usecases/place.js +13 -0
  268. package/dist/commands/validate/fleet/usecases/place.js.map +1 -0
  269. package/dist/commands/validate/fleet/views/fleet-project.js +217 -0
  270. package/dist/commands/validate/fleet/views/fleet-project.js.map +1 -0
  271. package/dist/commands/validate/fleet/views/ids.js +75 -0
  272. package/dist/commands/validate/fleet/views/ids.js.map +1 -0
  273. package/dist/commands/validate/fleet/views/projects.js +278 -0
  274. package/dist/commands/validate/fleet/views/projects.js.map +1 -0
  275. package/dist/commands/validate/fleet/views/root-documents.js +83 -0
  276. package/dist/commands/validate/fleet/views/root-documents.js.map +1 -0
  277. package/dist/commands/validate/fleet/views/stale.js +52 -0
  278. package/dist/commands/validate/fleet/views/stale.js.map +1 -0
  279. package/dist/commands/validate/links/corpus.js +89 -0
  280. package/dist/commands/validate/links/corpus.js.map +1 -0
  281. package/dist/commands/validate/links/glossary.js +75 -0
  282. package/dist/commands/validate/links/glossary.js.map +1 -0
  283. package/dist/commands/validate/render/repeats.js +63 -0
  284. package/dist/commands/validate/render/repeats.js.map +1 -0
  285. package/dist/commands/validate/render/rollups.js +115 -0
  286. package/dist/commands/validate/render/rollups.js.map +1 -0
  287. package/dist/commands/validate/render/text.js +199 -0
  288. package/dist/commands/validate/render/text.js.map +1 -0
  289. package/dist/commands/validate/report.js +145 -0
  290. package/dist/commands/validate/report.js.map +1 -0
  291. package/dist/commands/validate/scope.js +113 -0
  292. package/dist/commands/validate/scope.js.map +1 -0
  293. package/dist/commands/validate/service/api.js +252 -0
  294. package/dist/commands/validate/service/api.js.map +1 -0
  295. package/dist/commands/validate/service/contracts/generated.js +134 -0
  296. package/dist/commands/validate/service/contracts/generated.js.map +1 -0
  297. package/dist/commands/validate/service/events/events.js +241 -0
  298. package/dist/commands/validate/service/events/events.js.map +1 -0
  299. package/dist/commands/validate/service/events/message-producers.js +77 -0
  300. package/dist/commands/validate/service/events/message-producers.js.map +1 -0
  301. package/dist/commands/validate/service/evidence-pins.js +177 -0
  302. package/dist/commands/validate/service/evidence-pins.js.map +1 -0
  303. package/dist/commands/validate/service/model/diverged.js +226 -0
  304. package/dist/commands/validate/service/model/diverged.js.map +1 -0
  305. package/dist/commands/validate/service/model/grade.js +163 -0
  306. package/dist/commands/validate/service/model/grade.js.map +1 -0
  307. package/dist/commands/validate/service/service.js +310 -0
  308. package/dist/commands/validate/service/service.js.map +1 -0
  309. package/dist/commands/validate/service/specs.js +279 -0
  310. package/dist/commands/validate/service/specs.js.map +1 -0
  311. package/dist/commands/validate/service/spine.js +148 -0
  312. package/dist/commands/validate/service/spine.js.map +1 -0
  313. package/dist/commands/validate/service/usecases/tags.js +113 -0
  314. package/dist/commands/validate/service/usecases/tags.js.map +1 -0
  315. package/dist/commands/validate/service/usecases/usecases.js +209 -0
  316. package/dist/commands/validate/service/usecases/usecases.js.map +1 -0
  317. package/dist/commands/validate/validate.js +363 -0
  318. package/dist/commands/validate/validate.js.map +1 -0
  319. package/dist/commands/verify/cross/diff.js +178 -0
  320. package/dist/commands/verify/cross/diff.js.map +1 -0
  321. package/dist/commands/verify/evidence/contract.js +32 -0
  322. package/dist/commands/verify/evidence/contract.js.map +1 -0
  323. package/dist/commands/verify/evidence/pins.js +52 -0
  324. package/dist/commands/verify/evidence/pins.js.map +1 -0
  325. package/dist/commands/verify/evidence/read.js +81 -0
  326. package/dist/commands/verify/evidence/read.js.map +1 -0
  327. package/dist/commands/verify/frozen.js +263 -0
  328. package/dist/commands/verify/frozen.js.map +1 -0
  329. package/dist/commands/verify/record.js +278 -0
  330. package/dist/commands/verify/record.js.map +1 -0
  331. package/dist/commands/verify/report.js +206 -0
  332. package/dist/commands/verify/report.js.map +1 -0
  333. package/dist/commands/verify/results.js +328 -0
  334. package/dist/commands/verify/results.js.map +1 -0
  335. package/dist/commands/verify/verify.js +220 -0
  336. package/dist/commands/verify/verify.js.map +1 -0
  337. package/dist/commands/vouch/contract.js +11 -0
  338. package/dist/commands/vouch/contract.js.map +1 -0
  339. package/dist/commands/vouch/pack/contract.js +2 -0
  340. package/dist/commands/vouch/pack/contract.js.map +1 -0
  341. package/dist/commands/vouch/pack/pack.js +266 -0
  342. package/dist/commands/vouch/pack/pack.js.map +1 -0
  343. package/dist/commands/vouch/pack/print.js +266 -0
  344. package/dist/commands/vouch/pack/print.js.map +1 -0
  345. package/dist/commands/vouch/pack/sections.js +141 -0
  346. package/dist/commands/vouch/pack/sections.js.map +1 -0
  347. package/dist/commands/vouch/prompt/confirm.js +46 -0
  348. package/dist/commands/vouch/prompt/confirm.js.map +1 -0
  349. package/dist/commands/vouch/report.js +101 -0
  350. package/dist/commands/vouch/report.js.map +1 -0
  351. package/dist/commands/vouch/run.js +230 -0
  352. package/dist/commands/vouch/run.js.map +1 -0
  353. package/dist/commands/vouch/sample/plan.js +111 -0
  354. package/dist/commands/vouch/sample/plan.js.map +1 -0
  355. package/dist/commands/vouch/sample/print.js +109 -0
  356. package/dist/commands/vouch/sample/print.js.map +1 -0
  357. package/dist/commands/vouch/vet/verify.js +155 -0
  358. package/dist/commands/vouch/vet/verify.js.map +1 -0
  359. package/dist/commands/vouch/vouch.js +169 -0
  360. package/dist/commands/vouch/vouch.js.map +1 -0
  361. package/dist/core/agent/agents-md/command-map.js +299 -0
  362. package/dist/core/agent/agents-md/command-map.js.map +1 -0
  363. package/dist/core/agent/agents-md/map/explain.js +46 -0
  364. package/dist/core/agent/agents-md/map/explain.js.map +1 -0
  365. package/dist/core/agent/agents-md/map/lenses/context.js +50 -0
  366. package/dist/core/agent/agents-md/map/lenses/context.js.map +1 -0
  367. package/dist/core/agent/agents-md/map/lenses/diff.js +59 -0
  368. package/dist/core/agent/agents-md/map/lenses/diff.js.map +1 -0
  369. package/dist/core/agent/agents-md/map/lenses/gate.js +65 -0
  370. package/dist/core/agent/agents-md/map/lenses/gate.js.map +1 -0
  371. package/dist/core/agent/agents-md/map/mcp.js +44 -0
  372. package/dist/core/agent/agents-md/map/mcp.js.map +1 -0
  373. package/dist/core/agent/agents-md/map/status.js +78 -0
  374. package/dist/core/agent/agents-md/map/status.js.map +1 -0
  375. package/dist/core/agent/agents-md/map/subsystem.js +104 -0
  376. package/dist/core/agent/agents-md/map/subsystem.js.map +1 -0
  377. package/dist/core/agent/agents-md/map/usecases.js +138 -0
  378. package/dist/core/agent/agents-md/map/usecases.js.map +1 -0
  379. package/dist/core/agent/agents-md/refusals.js +273 -0
  380. package/dist/core/agent/agents-md/refusals.js.map +1 -0
  381. package/dist/core/agent/agents-md.js +203 -0
  382. package/dist/core/agent/agents-md.js.map +1 -0
  383. package/dist/core/{agents-stamp.js → agent/agents-stamp.js} +60 -0
  384. package/dist/core/agent/agents-stamp.js.map +1 -0
  385. package/dist/core/agent/contract.js +2 -0
  386. package/dist/core/agent/contract.js.map +1 -0
  387. package/dist/core/agent/protocol.js +193 -0
  388. package/dist/core/agent/protocol.js.map +1 -0
  389. package/dist/core/agent/scaffold.js +254 -0
  390. package/dist/core/agent/scaffold.js.map +1 -0
  391. package/dist/core/agent/support/report.js +144 -0
  392. package/dist/core/agent/support/report.js.map +1 -0
  393. package/dist/core/agent/tools/dialects.js +151 -0
  394. package/dist/core/agent/tools/dialects.js.map +1 -0
  395. package/dist/core/agent/tools/registry.js +193 -0
  396. package/dist/core/agent/tools/registry.js.map +1 -0
  397. package/dist/core/agent/workflows/adopt.js +280 -0
  398. package/dist/core/agent/workflows/adopt.js.map +1 -0
  399. package/dist/core/agent/workflows/check.js +373 -0
  400. package/dist/core/agent/workflows/check.js.map +1 -0
  401. package/dist/core/agent/workflows/closing.js +323 -0
  402. package/dist/core/agent/workflows/closing.js.map +1 -0
  403. package/dist/core/agent/workflows/feature.js +220 -0
  404. package/dist/core/agent/workflows/feature.js.map +1 -0
  405. package/dist/core/agent/workflows/implement.js +188 -0
  406. package/dist/core/agent/workflows/implement.js.map +1 -0
  407. package/dist/core/agent/workflows/reference/authoring.js +311 -0
  408. package/dist/core/agent/workflows/reference/authoring.js.map +1 -0
  409. package/dist/core/agent/workflows/reference/codes.js +67 -0
  410. package/dist/core/agent/workflows/reference/codes.js.map +1 -0
  411. package/dist/core/agent/workflows/reference/done-check.js +210 -0
  412. package/dist/core/agent/workflows/reference/done-check.js.map +1 -0
  413. package/dist/core/agent/workflows/reference/drawing/drawing.js +253 -0
  414. package/dist/core/agent/workflows/reference/drawing/drawing.js.map +1 -0
  415. package/dist/core/agent/workflows/reference/reference.js +19 -0
  416. package/dist/core/agent/workflows/reference/reference.js.map +1 -0
  417. package/dist/core/agent/workflows/reference/spine.js +338 -0
  418. package/dist/core/agent/workflows/reference/spine.js.map +1 -0
  419. package/dist/core/asyncapi/baseline/plan.js +43 -0
  420. package/dist/core/asyncapi/baseline/plan.js.map +1 -0
  421. package/dist/core/asyncapi/baseline/surfaces.js +54 -0
  422. package/dist/core/asyncapi/baseline/surfaces.js.map +1 -0
  423. package/dist/core/asyncapi/depth.js +164 -0
  424. package/dist/core/asyncapi/depth.js.map +1 -0
  425. package/dist/core/asyncapi/digest.js +146 -0
  426. package/dist/core/asyncapi/digest.js.map +1 -0
  427. package/dist/core/asyncapi/merge/components.js +92 -0
  428. package/dist/core/asyncapi/merge/components.js.map +1 -0
  429. package/dist/core/asyncapi/merge/error.js +38 -0
  430. package/dist/core/asyncapi/merge/error.js.map +1 -0
  431. package/dist/core/asyncapi/merge/markers.js +290 -0
  432. package/dist/core/asyncapi/merge/markers.js.map +1 -0
  433. package/dist/core/asyncapi/merge/merge.js +195 -0
  434. package/dist/core/asyncapi/merge/merge.js.map +1 -0
  435. package/dist/core/asyncapi/merge/pin.js +83 -0
  436. package/dist/core/asyncapi/merge/pin.js.map +1 -0
  437. package/dist/core/asyncapi/model.js +11 -0
  438. package/dist/core/asyncapi/model.js.map +1 -0
  439. package/dist/core/asyncapi/producers.js +50 -0
  440. package/dist/core/asyncapi/producers.js.map +1 -0
  441. package/dist/core/asyncapi/read.js +263 -0
  442. package/dist/core/asyncapi/read.js.map +1 -0
  443. package/dist/core/brief/brief.js +285 -0
  444. package/dist/core/brief/brief.js.map +1 -0
  445. package/dist/core/brief/checks.js +385 -0
  446. package/dist/core/brief/checks.js.map +1 -0
  447. package/dist/core/brief/landscape.js +273 -0
  448. package/dist/core/brief/landscape.js.map +1 -0
  449. package/dist/core/brief/map/extend.js +84 -0
  450. package/dist/core/brief/map/extend.js.map +1 -0
  451. package/dist/core/brief/map/owed.js +266 -0
  452. package/dist/core/brief/map/owed.js.map +1 -0
  453. package/dist/core/brief/targets.js +304 -0
  454. package/dist/core/brief/targets.js.map +1 -0
  455. package/dist/core/brief/unchecked.js +58 -0
  456. package/dist/core/brief/unchecked.js.map +1 -0
  457. package/dist/core/c4/arch.js +190 -0
  458. package/dist/core/c4/arch.js.map +1 -0
  459. package/dist/core/c4/direction/direction.js +114 -0
  460. package/dist/core/c4/direction/direction.js.map +1 -0
  461. package/dist/core/c4/likec4.js +243 -0
  462. package/dist/core/c4/likec4.js.map +1 -0
  463. package/dist/core/c4/locate/unlocated.js +150 -0
  464. package/dist/core/c4/locate/unlocated.js.map +1 -0
  465. package/dist/core/c4/parsed/deployment.js +160 -0
  466. package/dist/core/c4/parsed/deployment.js.map +1 -0
  467. package/dist/core/c4/parsed/dynamic-views.js +132 -0
  468. package/dist/core/c4/parsed/dynamic-views.js.map +1 -0
  469. package/dist/core/c4/parsed/specification.js +78 -0
  470. package/dist/core/c4/parsed/specification.js.map +1 -0
  471. package/dist/core/c4/parsed/values.js +110 -0
  472. package/dist/core/c4/parsed/values.js.map +1 -0
  473. package/dist/core/c4/parsed/view-ids.js +113 -0
  474. package/dist/core/c4/parsed/view-ids.js.map +1 -0
  475. package/dist/core/c4/prefetch/fleet.js +134 -0
  476. package/dist/core/c4/prefetch/fleet.js.map +1 -0
  477. package/dist/core/c4/project/architecture.js +161 -0
  478. package/dist/core/c4/project/architecture.js.map +1 -0
  479. package/dist/core/c4/project/batch.js +140 -0
  480. package/dist/core/c4/project/batch.js.map +1 -0
  481. package/dist/core/c4/project/documents.js +89 -0
  482. package/dist/core/c4/project/documents.js.map +1 -0
  483. package/dist/core/c4/project/load.js +219 -0
  484. package/dist/core/c4/project/load.js.map +1 -0
  485. package/dist/core/c4/project/staged.js +277 -0
  486. package/dist/core/c4/project/staged.js.map +1 -0
  487. package/dist/core/c4/resolve/attested.js +0 -0
  488. package/dist/core/c4/resolve/attested.js.map +1 -0
  489. package/dist/core/c4/resolve/external.js +51 -0
  490. package/dist/core/c4/resolve/external.js.map +1 -0
  491. package/dist/core/c4/resolve/service.js +174 -0
  492. package/dist/core/c4/resolve/service.js.map +1 -0
  493. package/dist/core/c4/resolve/steps.js +290 -0
  494. package/dist/core/c4/resolve/steps.js.map +1 -0
  495. package/dist/core/c4/resolve/systems.js +154 -0
  496. package/dist/core/c4/resolve/systems.js.map +1 -0
  497. package/dist/core/c4/root-project/exclude.js +352 -0
  498. package/dist/core/c4/root-project/exclude.js.map +1 -0
  499. package/dist/core/c4/seed/fleet-file.js +201 -0
  500. package/dist/core/c4/seed/fleet-file.js.map +1 -0
  501. package/dist/core/c4/seed/items.js +91 -0
  502. package/dist/core/c4/seed/items.js.map +1 -0
  503. package/dist/core/c4/seed/stamp.js +48 -0
  504. package/dist/core/c4/seed/stamp.js.map +1 -0
  505. package/dist/core/c4/seed/template.js +173 -0
  506. package/dist/core/c4/seed/template.js.map +1 -0
  507. package/dist/core/c4/service-model/created/models.js +96 -0
  508. package/dist/core/c4/service-model/created/models.js.map +1 -0
  509. package/dist/core/c4/service-model/documents.js +47 -0
  510. package/dist/core/c4/service-model/documents.js.map +1 -0
  511. package/dist/core/c4/service-model/fleet/extending.js +82 -0
  512. package/dist/core/c4/service-model/fleet/extending.js.map +1 -0
  513. package/dist/core/c4/service-model/load.js +165 -0
  514. package/dist/core/c4/service-model/load.js.map +1 -0
  515. package/dist/core/c4/service-model/renderer.js +128 -0
  516. package/dist/core/c4/service-model/renderer.js.map +1 -0
  517. package/dist/core/c4/service-model/shape.js +106 -0
  518. package/dist/core/c4/service-model/shape.js.map +1 -0
  519. package/dist/core/c4/service-model/slice.js +188 -0
  520. package/dist/core/c4/service-model/slice.js.map +1 -0
  521. package/dist/core/c4/source-mask.js +369 -0
  522. package/dist/core/c4/source-mask.js.map +1 -0
  523. package/dist/core/c4/source-scan.js +308 -0
  524. package/dist/core/c4/source-scan.js.map +1 -0
  525. package/dist/core/c4/splice/authored-source.js +167 -0
  526. package/dist/core/c4/splice/authored-source.js.map +1 -0
  527. package/dist/core/c4/splice/contract.js +30 -0
  528. package/dist/core/c4/splice/contract.js.map +1 -0
  529. package/dist/core/c4/splice/delta-blocks.js +126 -0
  530. package/dist/core/c4/splice/delta-blocks.js.map +1 -0
  531. package/dist/core/c4/splice/identity/declared.js +87 -0
  532. package/dist/core/c4/splice/identity/declared.js.map +1 -0
  533. package/dist/core/c4/splice/identity/edges.js +73 -0
  534. package/dist/core/c4/splice/identity/edges.js.map +1 -0
  535. package/dist/core/c4/splice/identity/existing.js +80 -0
  536. package/dist/core/c4/splice/identity/existing.js.map +1 -0
  537. package/dist/core/c4/splice/identity/interior.js +80 -0
  538. package/dist/core/c4/splice/identity/interior.js.map +1 -0
  539. package/dist/core/c4/splice/identity/owner.js +50 -0
  540. package/dist/core/c4/splice/identity/owner.js.map +1 -0
  541. package/dist/core/c4/splice/landscape-merge.js +337 -0
  542. package/dist/core/c4/splice/landscape-merge.js.map +1 -0
  543. package/dist/core/c4/splice/model/merge.js +151 -0
  544. package/dist/core/c4/splice/model/merge.js.map +1 -0
  545. package/dist/core/c4/splice/placement.js +298 -0
  546. package/dist/core/c4/splice/placement.js.map +1 -0
  547. package/dist/core/c4/splice/text/spot.js +131 -0
  548. package/dist/core/c4/splice/text/spot.js.map +1 -0
  549. package/dist/core/c4/workspace.js +166 -0
  550. package/dist/core/c4/workspace.js.map +1 -0
  551. package/dist/core/capabilities/authoring/notes.js +141 -0
  552. package/dist/core/capabilities/authoring/notes.js.map +1 -0
  553. package/dist/core/capabilities/capabilities.js +124 -0
  554. package/dist/core/capabilities/capabilities.js.map +1 -0
  555. package/dist/core/capabilities/delta/doc.js +47 -0
  556. package/dist/core/capabilities/delta/doc.js.map +1 -0
  557. package/dist/core/capabilities/delta/overlay.js +129 -0
  558. package/dist/core/capabilities/delta/overlay.js.map +1 -0
  559. package/dist/core/capabilities/delta/summary.js +57 -0
  560. package/dist/core/capabilities/delta/summary.js.map +1 -0
  561. package/dist/core/capabilities/delta/tree.js +43 -0
  562. package/dist/core/capabilities/delta/tree.js.map +1 -0
  563. package/dist/core/capabilities/delta/uncovered.js +222 -0
  564. package/dist/core/capabilities/delta/uncovered.js.map +1 -0
  565. package/dist/core/capabilities/findings.js +338 -0
  566. package/dist/core/capabilities/findings.js.map +1 -0
  567. package/dist/core/capabilities/realizes/findings.js +174 -0
  568. package/dist/core/capabilities/realizes/findings.js.map +1 -0
  569. package/dist/core/capabilities/realizes/join.js +123 -0
  570. package/dist/core/capabilities/realizes/join.js.map +1 -0
  571. package/dist/core/capabilities/rollup.js +205 -0
  572. package/dist/core/capabilities/rollup.js.map +1 -0
  573. package/dist/core/capabilities/tree.js +104 -0
  574. package/dist/core/capabilities/tree.js.map +1 -0
  575. package/dist/core/capabilities/usecase-join.js +267 -0
  576. package/dist/core/capabilities/usecase-join.js.map +1 -0
  577. package/dist/core/coherence/authoring/scaffold.js +185 -0
  578. package/dist/core/coherence/authoring/scaffold.js.map +1 -0
  579. package/dist/core/coherence/authoring/sentinels.js +75 -0
  580. package/dist/core/coherence/authoring/sentinels.js.map +1 -0
  581. package/dist/core/coherence/calls/called.js +52 -0
  582. package/dist/core/coherence/calls/called.js.map +1 -0
  583. package/dist/core/coherence/coherence.js +332 -0
  584. package/dist/core/coherence/coherence.js.map +1 -0
  585. package/dist/core/coherence/consumed/operations.js +70 -0
  586. package/dist/core/coherence/consumed/operations.js.map +1 -0
  587. package/dist/core/coherence/consumed/refusal.js +38 -0
  588. package/dist/core/coherence/consumed/refusal.js.map +1 -0
  589. package/dist/core/coherence/covers/health.js +85 -0
  590. package/dist/core/coherence/covers/health.js.map +1 -0
  591. package/dist/core/coherence/declared.js +295 -0
  592. package/dist/core/coherence/declared.js.map +1 -0
  593. package/dist/core/coherence/events/declared.js +191 -0
  594. package/dist/core/coherence/events/declared.js.map +1 -0
  595. package/dist/core/coherence/events/events.js +335 -0
  596. package/dist/core/coherence/events/events.js.map +1 -0
  597. package/dist/core/coherence/events/grades.js +189 -0
  598. package/dist/core/coherence/events/grades.js.map +1 -0
  599. package/dist/core/coherence/events/lookups.js +63 -0
  600. package/dist/core/coherence/events/lookups.js.map +1 -0
  601. package/dist/core/coherence/events/produced.js +100 -0
  602. package/dist/core/coherence/events/produced.js.map +1 -0
  603. package/dist/core/coherence/living.js +198 -0
  604. package/dist/core/coherence/living.js.map +1 -0
  605. package/dist/core/coherence/lookups.js +95 -0
  606. package/dist/core/coherence/lookups.js.map +1 -0
  607. package/dist/core/coherence/pending.js +39 -0
  608. package/dist/core/coherence/pending.js.map +1 -0
  609. package/dist/core/coherence/retired/archived.js +285 -0
  610. package/dist/core/coherence/retired/archived.js.map +1 -0
  611. package/dist/core/coherence/retired/event-pair.js +62 -0
  612. package/dist/core/coherence/retired/event-pair.js.map +1 -0
  613. package/dist/core/coherence/retired/merged.js +79 -0
  614. package/dist/core/coherence/retired/merged.js.map +1 -0
  615. package/dist/core/coherence/retired/retirement.js +49 -0
  616. package/dist/core/coherence/retired/retirement.js.map +1 -0
  617. package/dist/core/coherence/retired/revival/arrivals.js +131 -0
  618. package/dist/core/coherence/retired/revival/arrivals.js.map +1 -0
  619. package/dist/core/coherence/retired/revival/revived.js +297 -0
  620. package/dist/core/coherence/retired/revival/revived.js.map +1 -0
  621. package/dist/core/conflict-markers.js +60 -0
  622. package/dist/core/conflict-markers.js.map +1 -0
  623. package/dist/core/consumers/after.js +113 -0
  624. package/dist/core/consumers/after.js.map +1 -0
  625. package/dist/core/consumers/consumers.js +296 -0
  626. package/dist/core/consumers/consumers.js.map +1 -0
  627. package/dist/core/consumers/current.js +211 -0
  628. package/dist/core/consumers/current.js.map +1 -0
  629. package/dist/core/consumers/scan.js +46 -0
  630. package/dist/core/consumers/scan.js.map +1 -0
  631. package/dist/core/consumers/state.js +27 -0
  632. package/dist/core/consumers/state.js.map +1 -0
  633. package/dist/core/delta/claims.js +73 -0
  634. package/dist/core/delta/claims.js.map +1 -0
  635. package/dist/core/delta/delta.js +341 -0
  636. package/dist/core/delta/delta.js.map +1 -0
  637. package/dist/core/delta/document.js +177 -0
  638. package/dist/core/delta/document.js.map +1 -0
  639. package/dist/core/delta/scope.js +48 -0
  640. package/dist/core/delta/scope.js.map +1 -0
  641. package/dist/core/delta/select.js +237 -0
  642. package/dist/core/delta/select.js.map +1 -0
  643. package/dist/core/dependencies/dependencies.js +141 -0
  644. package/dist/core/dependencies/dependencies.js.map +1 -0
  645. package/dist/core/dependencies/facts.js +165 -0
  646. package/dist/core/dependencies/facts.js.map +1 -0
  647. package/dist/core/dependencies/fanin.js +88 -0
  648. package/dist/core/dependencies/fanin.js.map +1 -0
  649. package/dist/core/dependencies/graph.js +106 -0
  650. package/dist/core/dependencies/graph.js.map +1 -0
  651. package/dist/core/deployment/delta.js +191 -0
  652. package/dist/core/deployment/delta.js.map +1 -0
  653. package/dist/core/deployment/objects.js +145 -0
  654. package/dist/core/deployment/objects.js.map +1 -0
  655. package/dist/core/diff/base-git.js +230 -0
  656. package/dist/core/diff/base-git.js.map +1 -0
  657. package/dist/core/diff/base-state.js +237 -0
  658. package/dist/core/diff/base-state.js.map +1 -0
  659. package/dist/core/diff/joins.js +136 -0
  660. package/dist/core/diff/joins.js.map +1 -0
  661. package/dist/core/diff/scope/changed-paths.js +204 -0
  662. package/dist/core/diff/scope/changed-paths.js.map +1 -0
  663. package/dist/core/diff/scope/edges.js +82 -0
  664. package/dist/core/diff/scope/edges.js.map +1 -0
  665. package/dist/core/diff/semantic.js +312 -0
  666. package/dist/core/diff/semantic.js.map +1 -0
  667. package/dist/core/docs.js +37 -85
  668. package/dist/core/docs.js.map +1 -1
  669. package/dist/core/doctor/agents.js +238 -0
  670. package/dist/core/doctor/agents.js.map +1 -0
  671. package/dist/core/doctor/config.js +139 -0
  672. package/dist/core/doctor/config.js.map +1 -0
  673. package/dist/core/doctor/doctor.js +355 -0
  674. package/dist/core/doctor/doctor.js.map +1 -0
  675. package/dist/core/doctor/report.js +13 -0
  676. package/dist/core/doctor/report.js.map +1 -0
  677. package/dist/core/doctor/reports/scan.js +242 -0
  678. package/dist/core/doctor/reports/scan.js.map +1 -0
  679. package/dist/core/doctor/residue.js +110 -0
  680. package/dist/core/doctor/residue.js.map +1 -0
  681. package/dist/core/document/apply.js +224 -0
  682. package/dist/core/document/apply.js.map +1 -0
  683. package/dist/core/{frontmatter.js → document/frontmatter.js} +103 -2
  684. package/dist/core/document/frontmatter.js.map +1 -0
  685. package/dist/core/document/grammar/directives.js +143 -0
  686. package/dist/core/document/grammar/directives.js.map +1 -0
  687. package/dist/core/document/parse.js +286 -0
  688. package/dist/core/document/parse.js.map +1 -0
  689. package/dist/core/document/scenarios.js +238 -0
  690. package/dist/core/document/scenarios.js.map +1 -0
  691. package/dist/core/document/spec.js +234 -0
  692. package/dist/core/document/spec.js.map +1 -0
  693. package/dist/core/{config.js → envelope/config.js} +89 -18
  694. package/dist/core/envelope/config.js.map +1 -0
  695. package/dist/core/envelope/json.js +209 -0
  696. package/dist/core/envelope/json.js.map +1 -0
  697. package/dist/core/{version.js → envelope/version.js} +3 -3
  698. package/dist/core/envelope/version.js.map +1 -0
  699. package/dist/core/explain/families.js +180 -0
  700. package/dist/core/explain/families.js.map +1 -0
  701. package/dist/core/explain/fix-tables.js +178 -0
  702. package/dist/core/explain/fix-tables.js.map +1 -0
  703. package/dist/core/explain/lookup.js +194 -0
  704. package/dist/core/explain/lookup.js.map +1 -0
  705. package/dist/core/explain/refusals.js +49 -0
  706. package/dist/core/explain/refusals.js.map +1 -0
  707. package/dist/core/explain/terms/documents.js +227 -0
  708. package/dist/core/explain/terms/documents.js.map +1 -0
  709. package/dist/core/explain/terms/done-check.js +144 -0
  710. package/dist/core/explain/terms/done-check.js.map +1 -0
  711. package/dist/core/explain/terms/entry.js +14 -0
  712. package/dist/core/explain/terms/entry.js.map +1 -0
  713. package/dist/core/explain/terms/stages.js +71 -0
  714. package/dist/core/explain/terms/stages.js.map +1 -0
  715. package/dist/core/explain/terms/tasks.js +97 -0
  716. package/dist/core/explain/terms/tasks.js.map +1 -0
  717. package/dist/core/explain/terms.js +103 -0
  718. package/dist/core/explain/terms.js.map +1 -0
  719. package/dist/core/explore/describe.js +105 -0
  720. package/dist/core/explore/describe.js.map +1 -0
  721. package/dist/core/explore/explore.js +204 -0
  722. package/dist/core/explore/explore.js.map +1 -0
  723. package/dist/core/fleet-context.js +174 -146
  724. package/dist/core/fleet-context.js.map +1 -1
  725. package/dist/core/gate/checks.js +208 -0
  726. package/dist/core/gate/checks.js.map +1 -0
  727. package/dist/core/gate/partners.js +246 -0
  728. package/dist/core/gate/partners.js.map +1 -0
  729. package/dist/core/gate/report.js +47 -0
  730. package/dist/core/gate/report.js.map +1 -0
  731. package/dist/core/gate/verification.js +176 -0
  732. package/dist/core/gate/verification.js.map +1 -0
  733. package/dist/core/gherkin/digest.js +60 -0
  734. package/dist/core/gherkin/digest.js.map +1 -0
  735. package/dist/core/gherkin/emit.js +177 -0
  736. package/dist/core/gherkin/emit.js.map +1 -0
  737. package/dist/core/gherkin/read.js +76 -0
  738. package/dist/core/gherkin/read.js.map +1 -0
  739. package/dist/core/gherkin/stale.js +210 -0
  740. package/dist/core/gherkin/stale.js.map +1 -0
  741. package/dist/core/gherkin/stamp.js +77 -0
  742. package/dist/core/gherkin/stamp.js.map +1 -0
  743. package/dist/core/gherkin/steps/catalogue.js +154 -0
  744. package/dist/core/gherkin/steps/catalogue.js.map +1 -0
  745. package/dist/core/gherkin/steps/inventory.js +98 -0
  746. package/dist/core/gherkin/steps/inventory.js.map +1 -0
  747. package/dist/core/gherkin/steps/phrase.js +72 -0
  748. package/dist/core/gherkin/steps/phrase.js.map +1 -0
  749. package/dist/core/glossary/delta.js +109 -0
  750. package/dist/core/glossary/delta.js.map +1 -0
  751. package/dist/core/glossary/tree.js +73 -0
  752. package/dist/core/glossary/tree.js.map +1 -0
  753. package/dist/core/{concurrency.js → kernel/concurrency.js} +19 -0
  754. package/dist/core/kernel/concurrency.js.map +1 -0
  755. package/dist/core/{document-bytes.js → kernel/document-bytes.js} +1 -1
  756. package/dist/core/kernel/document-bytes.js.map +1 -0
  757. package/dist/core/kernel/fences.js +42 -0
  758. package/dist/core/kernel/fences.js.map +1 -0
  759. package/dist/core/kernel/ids/capability.js +72 -0
  760. package/dist/core/kernel/ids/capability.js.map +1 -0
  761. package/dist/core/kernel/ids/dirs.js +33 -0
  762. package/dist/core/kernel/ids/dirs.js.map +1 -0
  763. package/dist/core/kernel/ids/feature.js +75 -0
  764. package/dist/core/kernel/ids/feature.js.map +1 -0
  765. package/dist/core/kernel/ids/fqn/ancestors.js +65 -0
  766. package/dist/core/kernel/ids/fqn/ancestors.js.map +1 -0
  767. package/dist/core/kernel/ids/service.js +156 -0
  768. package/dist/core/kernel/ids/service.js.map +1 -0
  769. package/dist/core/kernel/ids/subsystem.js +63 -0
  770. package/dist/core/kernel/ids/subsystem.js.map +1 -0
  771. package/dist/core/{path-safety.js → kernel/path-safety.js} +56 -4
  772. package/dist/core/kernel/path-safety.js.map +1 -0
  773. package/dist/core/{records.js → kernel/records.js} +11 -0
  774. package/dist/core/kernel/records.js.map +1 -0
  775. package/dist/core/links/backlinks.js +66 -0
  776. package/dist/core/links/backlinks.js.map +1 -0
  777. package/dist/core/links/case.js +74 -0
  778. package/dist/core/links/case.js.map +1 -0
  779. package/dist/core/links/corpus.js +118 -0
  780. package/dist/core/links/corpus.js.map +1 -0
  781. package/dist/core/links/findings.js +110 -0
  782. package/dist/core/links/findings.js.map +1 -0
  783. package/dist/core/links/parse.js +265 -0
  784. package/dist/core/links/parse.js.map +1 -0
  785. package/dist/core/mcp/argv.js +212 -0
  786. package/dist/core/mcp/argv.js.map +1 -0
  787. package/dist/core/mcp/author-tools.js +73 -0
  788. package/dist/core/mcp/author-tools.js.map +1 -0
  789. package/dist/core/mcp/framing.js +46 -0
  790. package/dist/core/mcp/framing.js.map +1 -0
  791. package/dist/core/mcp/protocol.js +280 -0
  792. package/dist/core/mcp/protocol.js.map +1 -0
  793. package/dist/core/mcp/tools.js +324 -0
  794. package/dist/core/mcp/tools.js.map +1 -0
  795. package/dist/core/obligations/obligations.js +106 -0
  796. package/dist/core/obligations/obligations.js.map +1 -0
  797. package/dist/core/openapi/baseline/gate.js +207 -0
  798. package/dist/core/openapi/baseline/gate.js.map +1 -0
  799. package/dist/core/openapi/baseline/plan.js +142 -0
  800. package/dist/core/openapi/baseline/plan.js.map +1 -0
  801. package/dist/core/openapi/baseline/record.js +174 -0
  802. package/dist/core/openapi/baseline/record.js.map +1 -0
  803. package/dist/core/openapi/contract-text.js +33 -0
  804. package/dist/core/openapi/contract-text.js.map +1 -0
  805. package/dist/core/openapi/contract-tree.js +301 -0
  806. package/dist/core/openapi/contract-tree.js.map +1 -0
  807. package/dist/core/openapi/depth.js +136 -0
  808. package/dist/core/openapi/depth.js.map +1 -0
  809. package/dist/core/openapi/digest.js +239 -0
  810. package/dist/core/openapi/digest.js.map +1 -0
  811. package/dist/core/{openapi.js → openapi/doc.js} +54 -108
  812. package/dist/core/openapi/doc.js.map +1 -0
  813. package/dist/core/openapi/merge/components.js +199 -0
  814. package/dist/core/openapi/merge/components.js.map +1 -0
  815. package/dist/core/openapi/merge/error.js +16 -0
  816. package/dist/core/openapi/merge/error.js.map +1 -0
  817. package/dist/core/openapi/merge/markers.js +204 -0
  818. package/dist/core/openapi/merge/markers.js.map +1 -0
  819. package/dist/core/openapi/merge/merge.js +232 -0
  820. package/dist/core/openapi/merge/merge.js.map +1 -0
  821. package/dist/core/openapi/merge/pin.js +110 -0
  822. package/dist/core/openapi/merge/pin.js.map +1 -0
  823. package/dist/core/openspec/decide/capabilities.js +244 -0
  824. package/dist/core/openspec/decide/capabilities.js.map +1 -0
  825. package/dist/core/openspec/decide/dispositions.js +63 -0
  826. package/dist/core/openspec/decide/dispositions.js.map +1 -0
  827. package/dist/core/openspec/decide/renames.js +179 -0
  828. package/dist/core/openspec/decide/renames.js.map +1 -0
  829. package/dist/core/openspec/decide/verdict.js +84 -0
  830. package/dist/core/openspec/decide/verdict.js.map +1 -0
  831. package/dist/core/openspec/inventory.js +220 -0
  832. package/dist/core/openspec/inventory.js.map +1 -0
  833. package/dist/core/openspec/model/mapping.js +78 -0
  834. package/dist/core/openspec/model/mapping.js.map +1 -0
  835. package/dist/core/openspec/model/model.js +70 -0
  836. package/dist/core/openspec/model/model.js.map +1 -0
  837. package/dist/core/openspec/scan/changes.js +241 -0
  838. package/dist/core/openspec/scan/changes.js.map +1 -0
  839. package/dist/core/openspec/scan/config.js +191 -0
  840. package/dist/core/openspec/scan/config.js.map +1 -0
  841. package/dist/core/openspec/scan/shape.js +304 -0
  842. package/dist/core/openspec/scan/shape.js.map +1 -0
  843. package/dist/core/openspec/scan/walk.js +116 -0
  844. package/dist/core/openspec/scan/walk.js.map +1 -0
  845. package/dist/core/openspec/scan/workspace.js +71 -0
  846. package/dist/core/openspec/scan/workspace.js.map +1 -0
  847. package/dist/core/owners/codeowners.js +141 -0
  848. package/dist/core/owners/codeowners.js.map +1 -0
  849. package/dist/core/pack/features.js +120 -0
  850. package/dist/core/pack/features.js.map +1 -0
  851. package/dist/core/pack/joins.js +112 -0
  852. package/dist/core/pack/joins.js.map +1 -0
  853. package/dist/core/pack/living.js +157 -0
  854. package/dist/core/pack/living.js.map +1 -0
  855. package/dist/core/pack/pack.js +120 -0
  856. package/dist/core/pack/pack.js.map +1 -0
  857. package/dist/core/permissions/permissions.js +87 -0
  858. package/dist/core/permissions/permissions.js.map +1 -0
  859. package/dist/core/projection/api.js +84 -0
  860. package/dist/core/projection/api.js.map +1 -0
  861. package/dist/core/projection/arch-slice.js +63 -0
  862. package/dist/core/projection/arch-slice.js.map +1 -0
  863. package/dist/core/projection/events.js +34 -0
  864. package/dist/core/projection/events.js.map +1 -0
  865. package/dist/core/projection/introduced.js +14 -0
  866. package/dist/core/projection/introduced.js.map +1 -0
  867. package/dist/core/provenance/findings.js +244 -0
  868. package/dist/core/provenance/findings.js.map +1 -0
  869. package/dist/core/provenance/git.js +201 -0
  870. package/dist/core/provenance/git.js.map +1 -0
  871. package/dist/core/provenance/gitq/moves.js +139 -0
  872. package/dist/core/provenance/gitq/moves.js.map +1 -0
  873. package/dist/core/provenance/gitq/vouched-ancestor.js +179 -0
  874. package/dist/core/provenance/gitq/vouched-ancestor.js.map +1 -0
  875. package/dist/core/provenance/sample/scope.js +238 -0
  876. package/dist/core/provenance/sample/scope.js.map +1 -0
  877. package/dist/core/provenance/sample/sections.js +61 -0
  878. package/dist/core/provenance/sample/sections.js.map +1 -0
  879. package/dist/core/provenance/sources.js +280 -0
  880. package/dist/core/provenance/sources.js.map +1 -0
  881. package/dist/core/provenance/stamp.js +220 -0
  882. package/dist/core/provenance/stamp.js.map +1 -0
  883. package/dist/core/provenance/walk.js +157 -0
  884. package/dist/core/provenance/walk.js.map +1 -0
  885. package/dist/core/repo/authored/paths.js +210 -0
  886. package/dist/core/repo/authored/paths.js.map +1 -0
  887. package/dist/core/repo/entries.js +126 -0
  888. package/dist/core/repo/entries.js.map +1 -0
  889. package/dist/core/repo/paths.js +322 -0
  890. package/dist/core/repo/paths.js.map +1 -0
  891. package/dist/core/repo/repo.js +308 -0
  892. package/dist/core/repo/repo.js.map +1 -0
  893. package/dist/core/repo/service-target.js +153 -0
  894. package/dist/core/repo/service-target.js.map +1 -0
  895. package/dist/core/repo/state.js +58 -0
  896. package/dist/core/repo/state.js.map +1 -0
  897. package/dist/core/repo/tree/find.js +61 -0
  898. package/dist/core/repo/tree/find.js.map +1 -0
  899. package/dist/core/repo/tree/fs.js +90 -0
  900. package/dist/core/repo/tree/fs.js.map +1 -0
  901. package/dist/core/repo/tree/marker.js +61 -0
  902. package/dist/core/repo/tree/marker.js.map +1 -0
  903. package/dist/core/repo/tree/render/body.js +258 -0
  904. package/dist/core/repo/tree/render/body.js.map +1 -0
  905. package/dist/core/repo/tree/render/projects.js +182 -0
  906. package/dist/core/repo/tree/render/projects.js.map +1 -0
  907. package/dist/core/repo/tree/render/service/header.js +125 -0
  908. package/dist/core/repo/tree/render/service/header.js.map +1 -0
  909. package/dist/core/repo/tree/render/service/peers.js +28 -0
  910. package/dist/core/repo/tree/render/service/peers.js.map +1 -0
  911. package/dist/core/repo/tree/render/service/view-id.js +67 -0
  912. package/dist/core/repo/tree/render/service/view-id.js.map +1 -0
  913. package/dist/core/repo/tree/render/service/views.js +78 -0
  914. package/dist/core/repo/tree/render/service/views.js.map +1 -0
  915. package/dist/core/repo/tree/render/stale.js +42 -0
  916. package/dist/core/repo/tree/render/stale.js.map +1 -0
  917. package/dist/core/repo/tree/render/text.js +84 -0
  918. package/dist/core/repo/tree/render/text.js.map +1 -0
  919. package/dist/core/repo/tree/render/views.js +293 -0
  920. package/dist/core/repo/tree/render/views.js.map +1 -0
  921. package/dist/core/repo/tree/walk.js +255 -0
  922. package/dist/core/repo/tree/walk.js.map +1 -0
  923. package/dist/core/results.js +146 -14
  924. package/dist/core/results.js.map +1 -1
  925. package/dist/core/scaffold/landscape.js +239 -0
  926. package/dist/core/scaffold/landscape.js.map +1 -0
  927. package/dist/core/scaffold/legacy.js +271 -0
  928. package/dist/core/scaffold/legacy.js.map +1 -0
  929. package/dist/core/scaffold/readme.js +84 -0
  930. package/dist/core/scaffold/readme.js.map +1 -0
  931. package/dist/core/staging/commit.js +252 -0
  932. package/dist/core/staging/commit.js.map +1 -0
  933. package/dist/core/staging/interrupted.js +96 -0
  934. package/dist/core/staging/interrupted.js.map +1 -0
  935. package/dist/core/staging/lock.js +268 -0
  936. package/dist/core/staging/lock.js.map +1 -0
  937. package/dist/core/staging/recovery/finding.js +35 -0
  938. package/dist/core/staging/recovery/finding.js.map +1 -0
  939. package/dist/core/staging/recovery/intent.js +95 -0
  940. package/dist/core/staging/recovery/intent.js.map +1 -0
  941. package/dist/core/staging/recovery/recover.js +204 -0
  942. package/dist/core/staging/recovery/recover.js.map +1 -0
  943. package/dist/core/staging/recovery/residue.js +62 -0
  944. package/dist/core/staging/recovery/residue.js.map +1 -0
  945. package/dist/core/staging/snapshot/manifest.js +188 -0
  946. package/dist/core/staging/snapshot/manifest.js.map +1 -0
  947. package/dist/core/staging/snapshot/snapshot.js +196 -0
  948. package/dist/core/staging/snapshot/snapshot.js.map +1 -0
  949. package/dist/core/staging/txn/forward.js +181 -0
  950. package/dist/core/staging/txn/forward.js.map +1 -0
  951. package/dist/core/staging/txn/journal.js +139 -0
  952. package/dist/core/staging/txn/journal.js.map +1 -0
  953. package/dist/core/staging/txn/transaction.js +75 -0
  954. package/dist/core/staging/txn/transaction.js.map +1 -0
  955. package/dist/core/staging/writes.js +113 -0
  956. package/dist/core/staging/writes.js.map +1 -0
  957. package/dist/core/status/actions/execution.js +60 -0
  958. package/dist/core/status/actions/execution.js.map +1 -0
  959. package/dist/core/status/contracts.js +126 -0
  960. package/dist/core/status/contracts.js.map +1 -0
  961. package/dist/core/status/feature/artifacts.js +196 -0
  962. package/dist/core/status/feature/artifacts.js.map +1 -0
  963. package/dist/core/status/feature/feature.js +214 -0
  964. package/dist/core/status/feature/feature.js.map +1 -0
  965. package/dist/core/status/feature/next.js +163 -0
  966. package/dist/core/status/feature/next.js.map +1 -0
  967. package/dist/core/status/feature/state.js +21 -0
  968. package/dist/core/status/feature/state.js.map +1 -0
  969. package/dist/core/status/feature/words.js +96 -0
  970. package/dist/core/status/feature/words.js.map +1 -0
  971. package/dist/core/status/fleet/fleet.js +216 -0
  972. package/dist/core/status/fleet/fleet.js.map +1 -0
  973. package/dist/core/status/fleet/next.js +302 -0
  974. package/dist/core/status/fleet/next.js.map +1 -0
  975. package/dist/core/status/interrupted.js +97 -0
  976. package/dist/core/status/interrupted.js.map +1 -0
  977. package/dist/core/status/report.js +31 -0
  978. package/dist/core/status/report.js.map +1 -0
  979. package/dist/core/status/scan.js +41 -0
  980. package/dist/core/status/scan.js.map +1 -0
  981. package/dist/core/status/verification.js +216 -0
  982. package/dist/core/status/verification.js.map +1 -0
  983. package/dist/core/tasks/packet.js +199 -0
  984. package/dist/core/tasks/packet.js.map +1 -0
  985. package/dist/core/tasks/record.js +43 -0
  986. package/dist/core/tasks/record.js.map +1 -0
  987. package/dist/core/tasks/sources.js +181 -0
  988. package/dist/core/tasks/sources.js.map +1 -0
  989. package/dist/core/tasks/stamps.js +76 -0
  990. package/dist/core/tasks/stamps.js.map +1 -0
  991. package/dist/core/tasks/unit.js +0 -0
  992. package/dist/core/tasks/unit.js.map +1 -0
  993. package/dist/core/usecases/capability.js +166 -0
  994. package/dist/core/usecases/capability.js.map +1 -0
  995. package/dist/core/usecases/delta/claims.js +140 -0
  996. package/dist/core/usecases/delta/claims.js.map +1 -0
  997. package/dist/core/usecases/delta/flows.js +101 -0
  998. package/dist/core/usecases/delta/flows.js.map +1 -0
  999. package/dist/core/usecases/delta/modified.js +315 -0
  1000. package/dist/core/usecases/delta/modified.js.map +1 -0
  1001. package/dist/core/usecases/delta/overlay.js +76 -0
  1002. package/dist/core/usecases/delta/overlay.js.map +1 -0
  1003. package/dist/core/usecases/fleet.js +296 -0
  1004. package/dist/core/usecases/fleet.js.map +1 -0
  1005. package/dist/core/usecases/grade/capability-tag.js +93 -0
  1006. package/dist/core/usecases/grade/capability-tag.js.map +1 -0
  1007. package/dist/core/usecases/grade/feature.js +88 -0
  1008. package/dist/core/usecases/grade/feature.js.map +1 -0
  1009. package/dist/core/usecases/grade/requirement-tag.js +94 -0
  1010. package/dist/core/usecases/grade/requirement-tag.js.map +1 -0
  1011. package/dist/core/usecases/grade/steps.js +266 -0
  1012. package/dist/core/usecases/grade/steps.js.map +1 -0
  1013. package/dist/core/usecases/grade/usecases.js +112 -0
  1014. package/dist/core/usecases/grade/usecases.js.map +1 -0
  1015. package/dist/core/usecases/operations.js +123 -0
  1016. package/dist/core/usecases/operations.js.map +1 -0
  1017. package/dist/core/usecases/place.js +44 -0
  1018. package/dist/core/usecases/place.js.map +1 -0
  1019. package/dist/core/usecases/service/exclude.js +119 -0
  1020. package/dist/core/usecases/service/exclude.js.map +1 -0
  1021. package/dist/core/usecases/service/flows.js +164 -0
  1022. package/dist/core/usecases/service/flows.js.map +1 -0
  1023. package/dist/core/usecases/suites/participants.js +83 -0
  1024. package/dist/core/usecases/suites/participants.js.map +1 -0
  1025. package/dist/core/usecases/suites/suites.js +45 -0
  1026. package/dist/core/usecases/suites/suites.js.map +1 -0
  1027. package/dist/core/usecases/touch.js +101 -0
  1028. package/dist/core/usecases/touch.js.map +1 -0
  1029. package/dist/core/verify/answers.js +180 -0
  1030. package/dist/core/verify/answers.js.map +1 -0
  1031. package/dist/core/verify/build.js +170 -0
  1032. package/dist/core/verify/build.js.map +1 -0
  1033. package/dist/core/verify/checklist.js +259 -0
  1034. package/dist/core/verify/checklist.js.map +1 -0
  1035. package/dist/core/verify/claims/identity.js +61 -0
  1036. package/dist/core/verify/claims/identity.js.map +1 -0
  1037. package/dist/core/verify/cross/diff.js +97 -0
  1038. package/dist/core/verify/cross/diff.js.map +1 -0
  1039. package/dist/core/verify/evidence/contract.js +169 -0
  1040. package/dist/core/verify/evidence/contract.js.map +1 -0
  1041. package/dist/core/verify/location.js +67 -0
  1042. package/dist/core/verify/location.js.map +1 -0
  1043. package/dist/core/verify/pins/lint.js +158 -0
  1044. package/dist/core/verify/pins/lint.js.map +1 -0
  1045. package/dist/core/verify/pins/pin.js +95 -0
  1046. package/dist/core/verify/pins/pin.js.map +1 -0
  1047. package/dist/core/verify/read/file.js +224 -0
  1048. package/dist/core/verify/read/file.js.map +1 -0
  1049. package/dist/core/verify/read/shape.js +169 -0
  1050. package/dist/core/verify/read/shape.js.map +1 -0
  1051. package/dist/core/verify/read/union.js +105 -0
  1052. package/dist/core/verify/read/union.js.map +1 -0
  1053. package/dist/core/verify/record.js +165 -0
  1054. package/dist/core/verify/record.js.map +1 -0
  1055. package/dist/core/verify/store/commit.js +99 -0
  1056. package/dist/core/verify/store/commit.js.map +1 -0
  1057. package/dist/core/verify/store/render.js +61 -0
  1058. package/dist/core/verify/store/render.js.map +1 -0
  1059. package/dist/core/vocabulary/health.js +91 -0
  1060. package/dist/core/vocabulary/health.js.map +1 -0
  1061. package/dist/core/vocabulary/issue.js +59 -0
  1062. package/dist/core/vocabulary/issue.js.map +1 -0
  1063. package/dist/core/vocabulary/maturity.js +216 -0
  1064. package/dist/core/vocabulary/maturity.js.map +1 -0
  1065. package/dist/core/vocabulary/report.js +90 -0
  1066. package/dist/core/vocabulary/report.js.map +1 -0
  1067. package/dist/core/vocabulary/steps.js +266 -0
  1068. package/dist/core/vocabulary/steps.js.map +1 -0
  1069. package/dist/core/workspace/discover.js +239 -0
  1070. package/dist/core/workspace/discover.js.map +1 -0
  1071. package/dist/core/workspace/render.js +52 -0
  1072. package/dist/core/workspace/render.js.map +1 -0
  1073. package/examples/README.md +232 -0
  1074. package/examples/docs/architecture/adrs/0001-transactional-outbox.md +33 -0
  1075. package/examples/docs/architecture/capabilities.yaml +31 -0
  1076. package/examples/docs/architecture/landscape.likec4 +336 -0
  1077. package/examples/docs/architecture/obligations.yaml +23 -0
  1078. package/examples/docs/architecture/permissions.yaml +50 -0
  1079. package/examples/docs/architecture/services.likec4 +70 -0
  1080. package/examples/docs/architecture/subsystems.likec4 +18 -0
  1081. package/examples/docs/architecture/usecases/order-notification.likec4 +74 -0
  1082. package/examples/docs/capabilities/checkout/spec.md +55 -0
  1083. package/examples/docs/capabilities/identity/tokens/spec.md +42 -0
  1084. package/examples/docs/capabilities/order-notifications/spec.md +43 -0
  1085. package/examples/docs/features/FEAT-101-payment-splitting/adrs/0001-dedicated-split-service.md +18 -0
  1086. package/examples/docs/features/FEAT-101-payment-splitting/delta.likec4 +94 -0
  1087. package/examples/docs/features/FEAT-101-payment-splitting/intent.md +44 -0
  1088. package/examples/docs/features/FEAT-101-payment-splitting/specs/checkout-web/spec.md +21 -0
  1089. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-service/asyncapi.yaml +132 -0
  1090. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-service/spec.md +36 -0
  1091. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/arch.spec.md +40 -0
  1092. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/openapi.yaml +116 -0
  1093. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/spec.md +55 -0
  1094. package/examples/docs/features/FEAT-112-retire-order-v1/intent.md +35 -0
  1095. package/examples/docs/features/FEAT-112-retire-order-v1/specs/order-service/openapi.yaml +31 -0
  1096. package/examples/docs/features/FEAT-112-retire-order-v1/specs/order-service/spec.md +17 -0
  1097. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/architecture/landscape.likec4 +253 -0
  1098. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/services/order-service/spec.md +121 -0
  1099. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/services/payment-service/openapi.yaml +111 -0
  1100. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/services/payment-service/spec.md +58 -0
  1101. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/manifest.json +32 -0
  1102. package/examples/docs/features/archive/FEAT-088-refunds/adrs/0001-refunds-stay-in-payment-service.md +26 -0
  1103. package/examples/docs/features/archive/FEAT-088-refunds/delta.likec4 +28 -0
  1104. package/examples/docs/features/archive/FEAT-088-refunds/intent.md +26 -0
  1105. package/examples/docs/features/archive/FEAT-088-refunds/specs/order-service/spec.md +37 -0
  1106. package/examples/docs/features/archive/FEAT-088-refunds/specs/payment-service/openapi.yaml +73 -0
  1107. package/examples/docs/features/archive/FEAT-088-refunds/specs/payment-service/spec.md +23 -0
  1108. package/examples/docs/features/archive/FEAT-088-refunds/verification.yaml +76 -0
  1109. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/architecture/landscape.likec4 +275 -0
  1110. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/payment-service/asyncapi.yaml +96 -0
  1111. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/payment-service/spec.md +82 -0
  1112. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/platform/notification-service/asyncapi.yaml +164 -0
  1113. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/platform/notification-service/spec.md +91 -0
  1114. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/manifest.json +46 -0
  1115. package/examples/docs/features/archive/FEAT-120-refund-notification/delta.likec4 +36 -0
  1116. package/examples/docs/features/archive/FEAT-120-refund-notification/intent.md +22 -0
  1117. package/examples/docs/features/archive/FEAT-120-refund-notification/scenario-report.json +10 -0
  1118. package/examples/docs/features/archive/FEAT-120-refund-notification/specs/notification-service/asyncapi.yaml +208 -0
  1119. package/examples/docs/features/archive/FEAT-120-refund-notification/specs/notification-service/spec.md +24 -0
  1120. package/examples/docs/features/archive/FEAT-120-refund-notification/specs/payment-service/asyncapi.yaml +137 -0
  1121. package/examples/docs/features/archive/FEAT-120-refund-notification/specs/payment-service/spec.md +31 -0
  1122. package/examples/docs/features/archive/FEAT-120-refund-notification/verification.yaml +84 -0
  1123. package/examples/docs/glossary/order.md +15 -0
  1124. package/examples/docs/glossary/payments/authorization.md +14 -0
  1125. package/examples/docs/likec4.config.json +8 -0
  1126. package/examples/docs/loam.json +3 -0
  1127. package/examples/docs/services/checkout-web/model.likec4 +92 -0
  1128. package/examples/docs/services/checkout-web/spec.md +91 -0
  1129. package/examples/docs/services/checkout-web/ui/pages/checkout.page.yaml +40 -0
  1130. package/examples/docs/services/checkout-web/ui/pages/order-status.page.yaml +24 -0
  1131. package/examples/docs/services/checkout-web/ui/pages/split-payment.page.yaml +26 -0
  1132. package/examples/docs/services/order-service/adrs/0001-orchestrated-order-lifecycle.md +52 -0
  1133. package/examples/docs/services/order-service/arch.spec.md +134 -0
  1134. package/examples/docs/services/order-service/asyncapi.yaml +109 -0
  1135. package/examples/docs/services/order-service/health.yaml +57 -0
  1136. package/examples/docs/services/order-service/model.likec4 +126 -0
  1137. package/examples/docs/services/order-service/openapi.yaml +257 -0
  1138. package/examples/docs/services/order-service/runbook.md +62 -0
  1139. package/examples/docs/services/order-service/spec.md +134 -0
  1140. package/examples/docs/services/payment-service/adrs/0001-payments-outbox.md +18 -0
  1141. package/examples/docs/services/payment-service/adrs/0002-idempotency-keys-on-authorization.md +27 -0
  1142. package/examples/docs/services/payment-service/arch.spec.md +76 -0
  1143. package/examples/docs/services/payment-service/asyncapi.yaml +130 -0
  1144. package/examples/docs/services/payment-service/health.yaml +39 -0
  1145. package/examples/docs/services/payment-service/model.likec4 +68 -0
  1146. package/examples/docs/services/payment-service/openapi.yaml +151 -0
  1147. package/examples/docs/services/payment-service/runbook.md +37 -0
  1148. package/examples/docs/services/payment-service/spec.md +88 -0
  1149. package/examples/docs/services/platform/identity-service/adrs/0001-token-introspection-over-local-validation.md +60 -0
  1150. package/examples/docs/services/platform/identity-service/arch.spec.md +120 -0
  1151. package/examples/docs/services/platform/identity-service/health.yaml +70 -0
  1152. package/examples/docs/services/platform/identity-service/model.likec4 +81 -0
  1153. package/examples/docs/services/platform/identity-service/openapi.yaml +197 -0
  1154. package/examples/docs/services/platform/identity-service/runbook.md +95 -0
  1155. package/examples/docs/services/platform/identity-service/spec.md +119 -0
  1156. package/examples/docs/services/platform/notification-service/asyncapi.yaml +200 -0
  1157. package/examples/docs/services/platform/notification-service/health.yaml +40 -0
  1158. package/examples/docs/services/platform/notification-service/model.likec4 +97 -0
  1159. package/examples/docs/services/platform/notification-service/runbook.md +48 -0
  1160. package/examples/docs/services/platform/notification-service/spec.md +112 -0
  1161. package/examples/docs/services/platform/subsystem.yaml +2 -0
  1162. package/examples/fleet.yaml +57 -0
  1163. package/package.json +19 -6
  1164. package/dist/commands/adopt.js +0 -240
  1165. package/dist/commands/adopt.js.map +0 -1
  1166. package/dist/commands/archive.js +0 -1313
  1167. package/dist/commands/archive.js.map +0 -1
  1168. package/dist/commands/delta.js +0 -388
  1169. package/dist/commands/delta.js.map +0 -1
  1170. package/dist/commands/docs-repo-gate.js.map +0 -1
  1171. package/dist/commands/format.js +0 -17
  1172. package/dist/commands/format.js.map +0 -1
  1173. package/dist/commands/gherkin.js +0 -309
  1174. package/dist/commands/gherkin.js.map +0 -1
  1175. package/dist/commands/init.js.map +0 -1
  1176. package/dist/commands/list.js +0 -295
  1177. package/dist/commands/list.js.map +0 -1
  1178. package/dist/commands/migrate-openspec.js +0 -950
  1179. package/dist/commands/migrate-openspec.js.map +0 -1
  1180. package/dist/commands/new.js +0 -413
  1181. package/dist/commands/new.js.map +0 -1
  1182. package/dist/commands/rebase.js +0 -356
  1183. package/dist/commands/rebase.js.map +0 -1
  1184. package/dist/commands/show.js +0 -320
  1185. package/dist/commands/show.js.map +0 -1
  1186. package/dist/commands/status.js +0 -262
  1187. package/dist/commands/status.js.map +0 -1
  1188. package/dist/commands/unarchive.js +0 -317
  1189. package/dist/commands/unarchive.js.map +0 -1
  1190. package/dist/commands/validate.js +0 -1773
  1191. package/dist/commands/validate.js.map +0 -1
  1192. package/dist/commands/verify.js +0 -775
  1193. package/dist/commands/verify.js.map +0 -1
  1194. package/dist/commands/vouch.js +0 -421
  1195. package/dist/commands/vouch.js.map +0 -1
  1196. package/dist/core/agent.js +0 -2173
  1197. package/dist/core/agent.js.map +0 -1
  1198. package/dist/core/agents-stamp.js.map +0 -1
  1199. package/dist/core/arch.js +0 -130
  1200. package/dist/core/arch.js.map +0 -1
  1201. package/dist/core/asyncapi.js +0 -253
  1202. package/dist/core/asyncapi.js.map +0 -1
  1203. package/dist/core/brief.js +0 -755
  1204. package/dist/core/brief.js.map +0 -1
  1205. package/dist/core/coherence.js +0 -577
  1206. package/dist/core/coherence.js.map +0 -1
  1207. package/dist/core/concurrency.js.map +0 -1
  1208. package/dist/core/config.js.map +0 -1
  1209. package/dist/core/delta.js +0 -476
  1210. package/dist/core/delta.js.map +0 -1
  1211. package/dist/core/dependencies.js +0 -356
  1212. package/dist/core/dependencies.js.map +0 -1
  1213. package/dist/core/doctor.js +0 -596
  1214. package/dist/core/doctor.js.map +0 -1
  1215. package/dist/core/document-bytes.js.map +0 -1
  1216. package/dist/core/explore.js +0 -225
  1217. package/dist/core/explore.js.map +0 -1
  1218. package/dist/core/frontmatter.js.map +0 -1
  1219. package/dist/core/gherkin.js +0 -463
  1220. package/dist/core/gherkin.js.map +0 -1
  1221. package/dist/core/health.js +0 -67
  1222. package/dist/core/health.js.map +0 -1
  1223. package/dist/core/ids.js +0 -122
  1224. package/dist/core/ids.js.map +0 -1
  1225. package/dist/core/issue.js +0 -9
  1226. package/dist/core/issue.js.map +0 -1
  1227. package/dist/core/json.js +0 -74
  1228. package/dist/core/json.js.map +0 -1
  1229. package/dist/core/likec4.js +0 -489
  1230. package/dist/core/likec4.js.map +0 -1
  1231. package/dist/core/maturity.js +0 -66
  1232. package/dist/core/maturity.js.map +0 -1
  1233. package/dist/core/openapi-merge.js +0 -552
  1234. package/dist/core/openapi-merge.js.map +0 -1
  1235. package/dist/core/openapi.js.map +0 -1
  1236. package/dist/core/openspec-inventory.js +0 -1440
  1237. package/dist/core/openspec-inventory.js.map +0 -1
  1238. package/dist/core/path-safety.js.map +0 -1
  1239. package/dist/core/provenance.js +0 -787
  1240. package/dist/core/provenance.js.map +0 -1
  1241. package/dist/core/records.js.map +0 -1
  1242. package/dist/core/repo.js +0 -438
  1243. package/dist/core/repo.js.map +0 -1
  1244. package/dist/core/report.js +0 -47
  1245. package/dist/core/report.js.map +0 -1
  1246. package/dist/core/spec.js +0 -505
  1247. package/dist/core/spec.js.map +0 -1
  1248. package/dist/core/staging.js +0 -890
  1249. package/dist/core/staging.js.map +0 -1
  1250. package/dist/core/status.js +0 -1132
  1251. package/dist/core/status.js.map +0 -1
  1252. package/dist/core/steps.js +0 -72
  1253. package/dist/core/steps.js.map +0 -1
  1254. package/dist/core/verify.js +0 -807
  1255. package/dist/core/verify.js.map +0 -1
  1256. package/dist/core/version.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capability-tag.js","sourceRoot":"","sources":["../../../../src/core/usecases/grade/capability-tag.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,OAAO,EACL,cAAc,EACd,OAAO,GAER,MAAM,oCAAoC,CAAC;AAK5C,qGAAqG;AACrG,SAAS,QAAQ,CAAC,EAAU;IAC1B,OAAO,GAAG,EAAE,MAAM,cAAc,GAAG,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC;AACpD,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,WAAW,CAAC,KAAa,EAAE,KAAiD;IACnF,MAAM,IAAI,GACR,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC;QACpB,CAAC,CAAC,iBAAiB,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;QAC1D,CAAC,CAAC,kFAAkF,CAAC;IACzF,OAAO,CACL,GAAG,KAAK,eAAe,KAAK,CAAC,GAAG,kCAAkC;QAClE,+CAA+C,KAAK,CAAC,IAAI,MAAM,IAAI,GAAG;QACtE,mIAAmI,CACpI,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,SAAS,WAAW,CAAC,KAAa,EAAE,KAAiD;IACnF,OAAO,CACL,GAAG,KAAK,eAAe,KAAK,CAAC,GAAG,SAAS,KAAK,CAAC,GAAG,CAAC,MAAM,oCAAoC;QAC7F,IAAI,KAAK,CAAC,IAAI,MAAM,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,mEAAmE;QAC3G,0GAA0G;QAC1G,2GAA2G;QAC3G,qBAAqB,CACtB,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,qBAAqB,CAAC,IAAgB,EAAE,MAAkC,EAAE,KAAgB;IAC1G,MAAM,QAAQ,GAAc,EAAE,CAAC;IAC/B,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU;YAAE,SAAS;QACxC,QAAQ,CAAC,IAAI,CAAC;YACZ,QAAQ,EAAE,OAAO;YACjB,IAAI,EAAE,+BAA+B;YACrC,wEAAwE;YACxE,0EAA0E;YAC1E,aAAa;YACb,OAAO,EAAE,IAAI,CAAC,EAAE;YAChB,OAAO,EAAE,KAAK,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC;SACnG,CAAC,CAAC;IACL,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC","sourcesContent":["/**\n * `usecase.capability-unresolved` — the `#cap-` tag that names no declared\n * capability, or more than one.\n *\n * The join itself lives in `core/capabilities/usecase-join.ts` and none of it is\n * repeated here: this module owns the grade and the sentence, nothing else. That\n * split is why the tag can answer \"many\" at all — the slug is not injective, so\n * `payments/refunds` and `payments-refunds` both flatten to\n * `payments-refunds` — and why the close candidates a message offers are real\n * declared ids rather than loam's flattened spelling of them.\n *\n * ERROR, the same grade `capability.unknown` carries on a `Capability:` line and\n * for its reason: an invented capability reads exactly like a real one. Here it\n * reads that way at flow altitude — the tag is what files a whole business\n * sequence under an owner, so a claim that resolves to nothing produces a use\n * case nobody can find and a capability nobody can see is realized.\n *\n * SUPPRESSED ENTIRELY when the vocabulary is absent or unreadable: the caller\n * resolves no claims at all in that case, so this answers with nothing. The\n * claims are RESOLVED BY THE CALLER rather than here because the `#req-` grade\n * beside this one is scoped by the very same verdicts, and two resolutions of\n * one view's tags are two chances to disagree about which capability a flow is\n * about. The ladder that produces the suppressing `null` is\n * `gradableCapabilityIds` in `core/capabilities/findings.ts` — one function, called by every site that needs the graded id list, this module's\n * callers in `commands/validate/fleet/map/usecases.ts` and `./feature.ts` included. The FILE is this axis's opt-in, so a\n * fleet with no `architecture/capabilities.yaml` produces no capability finding\n * at all, and an unreadable one is `capability.invalid` alone rather than one\n * unresolved tag per use case in the fleet, which is a cascade and not a\n * diagnosis. That rule is not re-decided here: a second reading of\n * `CapabilityVocabulary` anywhere in this package is the copy that goes stale\n * the day a fourth un-gradable state is added, so call the function.\n */\nimport {\n CAP_TAG_PREFIX,\n tagSlug,\n type CapabilityClaim,\n} from \"../../capabilities/usecase-join.js\";\nimport type { ParsedView } from \"../../c4/parsed/dynamic-views.js\";\nimport type { Finding } from \"../../vocabulary/report.js\";\nimport type { ViewPlace } from \"../place.js\";\n\n/** A capability id as an author must write it in a tag: `identity/tokens (#cap-identity-tokens)`. */\nfunction idAndTag(id: string): string {\n return `${id} (#${CAP_TAG_PREFIX}${tagSlug(id)})`;\n}\n\n/**\n * A tag nothing declares, with the close names spelled as TAGS as well as ids.\n *\n * Both spellings, because either alone sends the author somewhere wrong: the id\n * is what `capabilities.yaml` holds and the tag is what the view must carry, and\n * an author handed only `identity/tokens` writes `#cap-identity/tokens`, which\n * LikeC4 refuses to parse. The flattening rule is stated in the same breath so\n * the reader can derive the next one without being told again.\n */\nfunction noneMessage(where: string, claim: Extract<CapabilityClaim, { kind: \"none\" }>): string {\n const hint =\n claim.close.length > 0\n ? `Did you mean: ${claim.close.map(idAndTag).join(\", \")}?`\n : \"Declare it there (`capabilities: {<id>: {description, owner}}`), or fix the tag.\";\n return (\n `${where} is tagged #${claim.tag}, and no capability declared in ` +\n `architecture/capabilities.yaml flattens to '${claim.slug}'. ${hint} ` +\n \"A tag spells the id with every character outside `[A-Za-z0-9_-]` flattened to `-`, because that is all a LikeC4 tag name accepts.\"\n );\n}\n\n/**\n * A tag two or more declared ids answer to. Every colliding id is named — a\n * message that stopped at the first would be reporting the ambiguity while\n * hiding half of what makes it one.\n */\nfunction manyMessage(where: string, claim: Extract<CapabilityClaim, { kind: \"many\" }>): string {\n return (\n `${where} is tagged #${claim.tag}, and ${claim.ids.length} declared capabilities flatten to ` +\n `'${claim.slug}' (${claim.ids.join(\", \")}) — nothing in the tag can say which one this use case realizes. ` +\n \"Rename one of them in architecture/capabilities.yaml: a guessed capability files every hop of the flow, \" +\n \"and every rollup built over it, under an owner who never claimed it — and the wrong answer looks exactly \" +\n \"like the right one.\"\n );\n}\n\n/**\n * One finding per `#cap-` tag that does not resolve — never one per view.\n *\n * A view may legitimately carry two capability tags (a checkout flow that also\n * issues the identity token realizes both), and `resolveCapabilityTags` answers\n * each on its own terms for that reason. Collapsing them here would either\n * swallow a broken tag beside a working one or lose the capability the view\n * genuinely does realize; one tag, one verdict, one finding keeps both facts.\n */\nexport function capabilityTagFindings(view: ParsedView, claims: readonly CapabilityClaim[], place: ViewPlace): Finding[] {\n const findings: Finding[] = [];\n for (const claim of claims) {\n if (claim.kind === \"resolved\") continue;\n findings.push({\n severity: \"error\",\n code: \"usecase.capability-unresolved\",\n // The VIEW, not the tag: a subject is what a reader goes and opens, and\n // `subjectsWith` counts one broken use case once however many of its tags\n // are wrong.\n subject: view.id,\n message: claim.kind === \"none\" ? noneMessage(place(view), claim) : manyMessage(place(view), claim),\n });\n }\n return findings;\n}\n"]}
@@ -0,0 +1,88 @@
1
+ /**
2
+ * A feature's own flows, graded the way `validate --all` will grade them once
3
+ * the archive has copied them into `architecture/usecases/`.
4
+ *
5
+ * WHY THIS EXISTS. The feature gate used to READ a feature's flows — parsed
6
+ * over the map its own merge would leave (`../delta/overlay.ts`), which is
7
+ * `usecase.flow-invalid` — and then grade only the promises they keep. Two
8
+ * flows the very next `validate --all` convicts passed it: one whose hop joins
9
+ * two services nothing on that map connects (`usecase.step-unbacked`), and one
10
+ * tagged `#req-` with no `#cap-` to scope it, or with a `#req-` naming no
11
+ * requirement (`usecase.requirement-unresolved`). Both archived at exit 0 under
12
+ * "living spec + landscape are now complete + current." (the real-fleet review,
13
+ * 2026-10-21). SCHEMA.md already said feature flows are graded against the map
14
+ * the merge leaves behind; for every grade but the parse, they were not.
15
+ *
16
+ * THE FLEET'S GRADER, NOT A COPY. `./usecases.ts` is `validate --all`'s own
17
+ * per-view loop — the opt-in, the capability and requirement tags, every hop —
18
+ * handed the staged post-merge model, the vocabulary and requirement index the
19
+ * merge would leave, and a `place` naming the file the author is still editing.
20
+ * A second verdict→code mapping for this scope would be the drift that
21
+ * package's banner forbids, and the drift would show up first as the gate
22
+ * passing what the fleet then fails.
23
+ *
24
+ * Issues, because the archive gate files Issues: every finding the grader
25
+ * writes carries a code the `IssueCode` union admits for exactly this
26
+ * (`core/vocabulary/issue.ts`). The severities travel unchanged — the two
27
+ * errors gate the archive, the two hop warnings and nothing else advise.
28
+ */
29
+ import { relative } from "node:path";
30
+ import { useCaseFindings } from "./usecases.js";
31
+ /**
32
+ * The codes `useCaseFindings` writes, each mapped to its `IssueCode` member — a
33
+ * table rather than a cast, so a sixth grade added to the fleet grader is a
34
+ * thrown error the first time a feature trips it rather than a finding this
35
+ * gate silently drops.
36
+ */
37
+ const AS_ISSUE = {
38
+ "usecase.capability-unresolved": "usecase.capability-unresolved",
39
+ "usecase.requirement-unresolved": "usecase.requirement-unresolved",
40
+ "usecase.step-unbacked": "usecase.step-unbacked",
41
+ "usecase.step-contested": "usecase.step-contested",
42
+ "usecase.step-unlinked": "usecase.step-unlinked",
43
+ };
44
+ /**
45
+ * Where a feature flow's finding says the view is:
46
+ * `features/FEAT-1-split/usecases/checkout.likec4 — dynamic view 'uc_checkout'`.
47
+ * The staged parse has already mapped `sourcePath` back to the authored file;
48
+ * this spells it docs-relative, the way every other feature finding names a file.
49
+ */
50
+ function featurePlace(docsDir) {
51
+ return (view) => {
52
+ const file = view.sourcePath === undefined ? "usecases/" : relative(docsDir, view.sourcePath).split(/[\\/]/).join("/");
53
+ return `${file} — dynamic view '${view.id}'`;
54
+ };
55
+ }
56
+ function asIssue(finding) {
57
+ if (finding.severity === "ok")
58
+ return [];
59
+ const code = AS_ISSUE[finding.code];
60
+ if (code === undefined) {
61
+ throw new Error(`the use-case grader wrote '${finding.code}', which the feature gate has no IssueCode for — add it to AS_ISSUE`);
62
+ }
63
+ return [
64
+ {
65
+ severity: finding.severity,
66
+ code,
67
+ ...(finding.subject === undefined ? {} : { subject: finding.subject }),
68
+ ...(finding.details === undefined ? {} : { details: finding.details }),
69
+ message: finding.message,
70
+ },
71
+ ];
72
+ }
73
+ export function featureFlowIssues(scope) {
74
+ const { scan } = scope;
75
+ if (scan.views.length === 0)
76
+ return [];
77
+ return useCaseFindings({
78
+ views: scan.views,
79
+ elements: scan.model.elements,
80
+ relationships: scan.model.relationships,
81
+ services: scan.model.known,
82
+ resolve: scan.resolve,
83
+ capabilities: scope.capabilities,
84
+ requirementsOf: scope.requirementsOf,
85
+ place: featurePlace(scope.docsDir),
86
+ }).flatMap(asIssue);
87
+ }
88
+ //# sourceMappingURL=feature.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"feature.js","sourceRoot":"","sources":["../../../../src/core/usecases/grade/feature.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAMrC,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAahD;;;;;GAKG;AACH,MAAM,QAAQ,GAAwC;IACpD,+BAA+B,EAAE,+BAA+B;IAChE,gCAAgC,EAAE,gCAAgC;IAClE,uBAAuB,EAAE,uBAAuB;IAChD,wBAAwB,EAAE,wBAAwB;IAClD,uBAAuB,EAAE,uBAAuB;CACjD,CAAC;AAEF;;;;;GAKG;AACH,SAAS,YAAY,CAAC,OAAgB;IACpC,OAAO,CAAC,IAAI,EAAE,EAAE;QACd,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACvH,OAAO,GAAG,IAAI,oBAAoB,IAAI,CAAC,EAAE,GAAG,CAAC;IAC/C,CAAC,CAAC;AACJ,CAAC;AAED,SAAS,OAAO,CAAC,OAAgB;IAC/B,IAAI,OAAO,CAAC,QAAQ,KAAK,IAAI;QAAE,OAAO,EAAE,CAAC;IACzC,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACpC,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,8BAA8B,OAAO,CAAC,IAAI,qEAAqE,CAAC,CAAC;IACnI,CAAC;IACD,OAAO;QACL;YACE,QAAQ,EAAE,OAAO,CAAC,QAAQ;YAC1B,IAAI;YACJ,GAAG,CAAC,OAAO,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC;YACtE,GAAG,CAAC,OAAO,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC;YACtE,OAAO,EAAE,OAAO,CAAC,OAAO;SACzB;KACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,KAAuB;IACvD,MAAM,EAAE,IAAI,EAAE,GAAG,KAAK,CAAC;IACvB,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IACvC,OAAO,eAAe,CAAC;QACrB,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,QAAQ;QAC7B,aAAa,EAAE,IAAI,CAAC,KAAK,CAAC,aAAa;QACvC,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK;QAC1B,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,YAAY,EAAE,KAAK,CAAC,YAAY;QAChC,cAAc,EAAE,KAAK,CAAC,cAAc;QACpC,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC,OAAO,CAAC;KACnC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;AACtB,CAAC","sourcesContent":["/**\n * A feature's own flows, graded the way `validate --all` will grade them once\n * the archive has copied them into `architecture/usecases/`.\n *\n * WHY THIS EXISTS. The feature gate used to READ a feature's flows — parsed\n * over the map its own merge would leave (`../delta/overlay.ts`), which is\n * `usecase.flow-invalid` — and then grade only the promises they keep. Two\n * flows the very next `validate --all` convicts passed it: one whose hop joins\n * two services nothing on that map connects (`usecase.step-unbacked`), and one\n * tagged `#req-` with no `#cap-` to scope it, or with a `#req-` naming no\n * requirement (`usecase.requirement-unresolved`). Both archived at exit 0 under\n * \"living spec + landscape are now complete + current.\" (the real-fleet review,\n * 2026-10-21). SCHEMA.md already said feature flows are graded against the map\n * the merge leaves behind; for every grade but the parse, they were not.\n *\n * THE FLEET'S GRADER, NOT A COPY. `./usecases.ts` is `validate --all`'s own\n * per-view loop — the opt-in, the capability and requirement tags, every hop —\n * handed the staged post-merge model, the vocabulary and requirement index the\n * merge would leave, and a `place` naming the file the author is still editing.\n * A second verdict→code mapping for this scope would be the drift that\n * package's banner forbids, and the drift would show up first as the gate\n * passing what the fleet then fails.\n *\n * Issues, because the archive gate files Issues: every finding the grader\n * writes carries a code the `IssueCode` union admits for exactly this\n * (`core/vocabulary/issue.ts`). The severities travel unchanged — the two\n * errors gate the archive, the two hop warnings and nothing else advise.\n */\nimport { relative } from \"node:path\";\nimport type { ParsedView } from \"../../c4/parsed/dynamic-views.js\";\nimport type { DocsDir } from \"../../kernel/ids/dirs.js\";\nimport type { Issue, IssueCode } from \"../../vocabulary/issue.js\";\nimport type { Finding } from \"../../vocabulary/report.js\";\nimport type { UseCaseScan } from \"../fleet.js\";\nimport { useCaseFindings } from \"./usecases.js\";\n\n/** What the feature's flows are graded against — everything as the merge would leave it. */\nexport interface FeatureFlowScope {\n docsDir: DocsDir;\n /** The feature's flows, parsed over the post-merge map — the readable arm only; unreadable is `usecase.flow-invalid`. */\n scan: Extract<UseCaseScan, { kind: \"read\" }>;\n /** The capability ids the merge would leave declared, or `null` when the vocabulary suspends the tag grades. */\n capabilities: readonly string[] | null;\n /** The requirement ids each capability document would declare after the merge. */\n requirementsOf: (capability: string) => ReadonlySet<string> | undefined;\n}\n\n/**\n * The codes `useCaseFindings` writes, each mapped to its `IssueCode` member — a\n * table rather than a cast, so a sixth grade added to the fleet grader is a\n * thrown error the first time a feature trips it rather than a finding this\n * gate silently drops.\n */\nconst AS_ISSUE: Readonly<Record<string, IssueCode>> = {\n \"usecase.capability-unresolved\": \"usecase.capability-unresolved\",\n \"usecase.requirement-unresolved\": \"usecase.requirement-unresolved\",\n \"usecase.step-unbacked\": \"usecase.step-unbacked\",\n \"usecase.step-contested\": \"usecase.step-contested\",\n \"usecase.step-unlinked\": \"usecase.step-unlinked\",\n};\n\n/**\n * Where a feature flow's finding says the view is:\n * `features/FEAT-1-split/usecases/checkout.likec4 — dynamic view 'uc_checkout'`.\n * The staged parse has already mapped `sourcePath` back to the authored file;\n * this spells it docs-relative, the way every other feature finding names a file.\n */\nfunction featurePlace(docsDir: DocsDir): (view: ParsedView) => string {\n return (view) => {\n const file = view.sourcePath === undefined ? \"usecases/\" : relative(docsDir, view.sourcePath).split(/[\\\\/]/).join(\"/\");\n return `${file} — dynamic view '${view.id}'`;\n };\n}\n\nfunction asIssue(finding: Finding): Issue[] {\n if (finding.severity === \"ok\") return [];\n const code = AS_ISSUE[finding.code];\n if (code === undefined) {\n throw new Error(`the use-case grader wrote '${finding.code}', which the feature gate has no IssueCode for — add it to AS_ISSUE`);\n }\n return [\n {\n severity: finding.severity,\n code,\n ...(finding.subject === undefined ? {} : { subject: finding.subject }),\n ...(finding.details === undefined ? {} : { details: finding.details }),\n message: finding.message,\n },\n ];\n}\n\nexport function featureFlowIssues(scope: FeatureFlowScope): Issue[] {\n const { scan } = scope;\n if (scan.views.length === 0) return [];\n return useCaseFindings({\n views: scan.views,\n elements: scan.model.elements,\n relationships: scan.model.relationships,\n services: scan.model.known,\n resolve: scan.resolve,\n capabilities: scope.capabilities,\n requirementsOf: scope.requirementsOf,\n place: featurePlace(scope.docsDir),\n }).flatMap(asIssue);\n}\n"]}
@@ -0,0 +1,94 @@
1
+ /**
2
+ * `usecase.requirement-unresolved` — the `#req-` tag that names no requirement
3
+ * of the capability the view is about.
4
+ *
5
+ * The join lives in `core/capabilities/usecase-join.ts` and none of it is
6
+ * repeated here: this module owns the grade and the sentences. Six arms, six
7
+ * fixes, and they are deliberately the same vocabulary
8
+ * `capability.realizes-unknown` uses for the OTHER carrier of this claim — an
9
+ * author who has learned one set of messages has learned both.
10
+ *
11
+ * ERROR, for `usecase.capability-unresolved`'s reason one join deeper: the tag
12
+ * is the architect's claim that a flow satisfies a named business promise, and a
13
+ * claim that resolves to nothing reads exactly like one that does — in the view,
14
+ * in review, and to anyone asking which flow keeps that promise.
15
+ *
16
+ * AN UNRESOLVED CLAIM SUPPRESSES NOTHING. `capability.requirement-unrealized`
17
+ * counts only RESOLVED claims, so a typo'd `#req-` tag leaves the requirement
18
+ * reported as realized by nobody — which is the truth, and is exactly what a
19
+ * broken claim should not be able to hide. The two findings arriving together is
20
+ * the intended reading: one says the tag is wrong, the other says the promise is
21
+ * still unkept.
22
+ */
23
+ import { REQ_TAG_PREFIX, tagSlug, resolveRequirementTags, } from "../../capabilities/usecase-join.js";
24
+ /** A `Requirement-ID` as an author must write it in a tag: `CHK.ONCE (#req-CHK-ONCE)`. */
25
+ function idAndTag(id) {
26
+ return `${id} (#${REQ_TAG_PREFIX}${tagSlug(id)})`;
27
+ }
28
+ /**
29
+ * The fix for one unresolved claim. The `unscoped` arm splits in two on the
30
+ * count, because none and several are opposite mistakes: one author forgot to
31
+ * say which capability, the other said two and left the id homeless.
32
+ */
33
+ function advice(claim) {
34
+ switch (claim.kind) {
35
+ case "unscoped":
36
+ return claim.capabilities.length === 0
37
+ ? "the view carries no `#cap-` tag that resolves to a declared capability, and a `Requirement-ID` is " +
38
+ "unique only inside its own document — so there is nothing for this id to be looked up in. " +
39
+ "Add the `#cap-<slug>` tag naming the capability this flow is about."
40
+ : `the view resolves ${claim.capabilities.length} capabilities (${claim.capabilities.join(", ")}), ` +
41
+ "so nothing says which document the id belongs to. A flow realizing promises from two capabilities " +
42
+ "needs one `#req-` tag per capability to be unambiguous, which the tag grammar cannot express — " +
43
+ "split the flow, or drop the `#req-` tag and let `Realizes:` on the service requirements carry it.";
44
+ case "undocumented":
45
+ return (`capability '${claim.capability}' is declared but has no capabilities/${claim.capability}/spec.md, ` +
46
+ "so it carries no requirements to satisfy. Write the document — a name alone can be claimed with " +
47
+ "`#cap-`, but only a document has promises a flow can keep.");
48
+ case "empty":
49
+ return (`capabilities/${claim.capability}/spec.md exists and declares no requirements yet — ` +
50
+ "add the `## Requirements` section, each requirement carrying its `Requirement-ID:`.");
51
+ case "none":
52
+ return claim.close.length > 0
53
+ ? `capabilities/${claim.capability}/spec.md declares no requirement flattening to '${claim.slug}'. ` +
54
+ `Did you mean: ${claim.close.map(idAndTag).join(", ")}?`
55
+ : `capabilities/${claim.capability}/spec.md declares no requirement flattening to '${claim.slug}' — ` +
56
+ "check the `Requirement-ID:` lines in that document.";
57
+ default:
58
+ return (`${claim.ids.length} requirements of '${claim.capability}' flatten to '${claim.slug}' ` +
59
+ `(${claim.ids.join(", ")}) — nothing in the tag can say which promise this flow keeps. ` +
60
+ "Rename one of them: a guessed requirement reports the wrong promise as kept and the right one as " +
61
+ "unimplemented, and both answers look exactly like the truth.");
62
+ }
63
+ }
64
+ /**
65
+ * One finding per `#req-` tag that does not resolve — never one per view.
66
+ *
67
+ * Several `#req-` tags on one view are legal and normal: a checkout flow that
68
+ * charges once AND honours the price keeps two promises, and there is no honest
69
+ * way to make its author pick one. So a broken tag beside a working one must
70
+ * neither swallow the break nor lose the promise the view genuinely does keep.
71
+ *
72
+ * `claims` is the view's OWN capability verdicts, already resolved by the
73
+ * caller — passed rather than recomputed so the scope this grade uses and the
74
+ * scope `capabilityTagFindings` graded are the same list, and an unresolved
75
+ * `#cap-` tag cannot silently scope a requirement lookup.
76
+ */
77
+ export function requirementTagFindings(view, claims, requirementsOf, place) {
78
+ const scope = claims.flatMap((claim) => (claim.kind === "resolved" ? [claim.id] : []));
79
+ const findings = [];
80
+ for (const claim of resolveRequirementTags(view.tags, scope, requirementsOf)) {
81
+ if (claim.kind === "resolved")
82
+ continue;
83
+ findings.push({
84
+ severity: "error",
85
+ code: "usecase.requirement-unresolved",
86
+ // The VIEW, not the tag — a subject is what a reader goes and opens, and
87
+ // one broken use case counts once however many of its tags are wrong.
88
+ subject: view.id,
89
+ message: `${place(view)} is tagged #${claim.tag}, and it does not resolve: ${advice(claim)}`,
90
+ });
91
+ }
92
+ return findings;
93
+ }
94
+ //# sourceMappingURL=requirement-tag.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"requirement-tag.js","sourceRoot":"","sources":["../../../../src/core/usecases/grade/requirement-tag.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,EACL,cAAc,EACd,OAAO,EACP,sBAAsB,GAGvB,MAAM,oCAAoC,CAAC;AAK5C,0FAA0F;AAC1F,SAAS,QAAQ,CAAC,EAAU;IAC1B,OAAO,GAAG,EAAE,MAAM,cAAc,GAAG,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC;AACpD,CAAC;AAED;;;;GAIG;AACH,SAAS,MAAM,CAAC,KAAsD;IACpE,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC;QACnB,KAAK,UAAU;YACb,OAAO,KAAK,CAAC,YAAY,CAAC,MAAM,KAAK,CAAC;gBACpC,CAAC,CAAC,oGAAoG;oBAClG,4FAA4F;oBAC5F,qEAAqE;gBACzE,CAAC,CAAC,qBAAqB,KAAK,CAAC,YAAY,CAAC,MAAM,kBAAkB,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK;oBAChG,oGAAoG;oBACpG,iGAAiG;oBACjG,mGAAmG,CAAC;QAC5G,KAAK,cAAc;YACjB,OAAO,CACL,eAAe,KAAK,CAAC,UAAU,yCAAyC,KAAK,CAAC,UAAU,YAAY;gBACpG,kGAAkG;gBAClG,4DAA4D,CAC7D,CAAC;QACJ,KAAK,OAAO;YACV,OAAO,CACL,gBAAgB,KAAK,CAAC,UAAU,qDAAqD;gBACrF,qFAAqF,CACtF,CAAC;QACJ,KAAK,MAAM;YACT,OAAO,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC;gBAC3B,CAAC,CAAC,gBAAgB,KAAK,CAAC,UAAU,mDAAmD,KAAK,CAAC,IAAI,KAAK;oBAChG,iBAAiB,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;gBAC5D,CAAC,CAAC,gBAAgB,KAAK,CAAC,UAAU,mDAAmD,KAAK,CAAC,IAAI,MAAM;oBACjG,qDAAqD,CAAC;QAC9D;YACE,OAAO,CACL,GAAG,KAAK,CAAC,GAAG,CAAC,MAAM,qBAAqB,KAAK,CAAC,UAAU,iBAAiB,KAAK,CAAC,IAAI,IAAI;gBACvF,IAAI,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,gEAAgE;gBACxF,mGAAmG;gBACnG,8DAA8D,CAC/D,CAAC;IACN,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,sBAAsB,CACpC,IAAgB,EAChB,MAAkC,EAClC,cAAuE,EACvE,KAAgB;IAEhB,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACvF,MAAM,QAAQ,GAAc,EAAE,CAAC;IAC/B,KAAK,MAAM,KAAK,IAAI,sBAAsB,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,cAAc,CAAC,EAAE,CAAC;QAC7E,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU;YAAE,SAAS;QACxC,QAAQ,CAAC,IAAI,CAAC;YACZ,QAAQ,EAAE,OAAO;YACjB,IAAI,EAAE,gCAAgC;YACtC,yEAAyE;YACzE,sEAAsE;YACtE,OAAO,EAAE,IAAI,CAAC,EAAE;YAChB,OAAO,EAAE,GAAG,KAAK,CAAC,IAAI,CAAC,eAAe,KAAK,CAAC,GAAG,8BAA8B,MAAM,CAAC,KAAK,CAAC,EAAE;SAC7F,CAAC,CAAC;IACL,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC","sourcesContent":["/**\n * `usecase.requirement-unresolved` — the `#req-` tag that names no requirement\n * of the capability the view is about.\n *\n * The join lives in `core/capabilities/usecase-join.ts` and none of it is\n * repeated here: this module owns the grade and the sentences. Six arms, six\n * fixes, and they are deliberately the same vocabulary\n * `capability.realizes-unknown` uses for the OTHER carrier of this claim — an\n * author who has learned one set of messages has learned both.\n *\n * ERROR, for `usecase.capability-unresolved`'s reason one join deeper: the tag\n * is the architect's claim that a flow satisfies a named business promise, and a\n * claim that resolves to nothing reads exactly like one that does — in the view,\n * in review, and to anyone asking which flow keeps that promise.\n *\n * AN UNRESOLVED CLAIM SUPPRESSES NOTHING. `capability.requirement-unrealized`\n * counts only RESOLVED claims, so a typo'd `#req-` tag leaves the requirement\n * reported as realized by nobody — which is the truth, and is exactly what a\n * broken claim should not be able to hide. The two findings arriving together is\n * the intended reading: one says the tag is wrong, the other says the promise is\n * still unkept.\n */\nimport {\n REQ_TAG_PREFIX,\n tagSlug,\n resolveRequirementTags,\n type CapabilityClaim,\n type RequirementClaim,\n} from \"../../capabilities/usecase-join.js\";\nimport type { ParsedView } from \"../../c4/parsed/dynamic-views.js\";\nimport type { Finding } from \"../../vocabulary/report.js\";\nimport type { ViewPlace } from \"../place.js\";\n\n/** A `Requirement-ID` as an author must write it in a tag: `CHK.ONCE (#req-CHK-ONCE)`. */\nfunction idAndTag(id: string): string {\n return `${id} (#${REQ_TAG_PREFIX}${tagSlug(id)})`;\n}\n\n/**\n * The fix for one unresolved claim. The `unscoped` arm splits in two on the\n * count, because none and several are opposite mistakes: one author forgot to\n * say which capability, the other said two and left the id homeless.\n */\nfunction advice(claim: Exclude<RequirementClaim, { kind: \"resolved\" }>): string {\n switch (claim.kind) {\n case \"unscoped\":\n return claim.capabilities.length === 0\n ? \"the view carries no `#cap-` tag that resolves to a declared capability, and a `Requirement-ID` is \" +\n \"unique only inside its own document — so there is nothing for this id to be looked up in. \" +\n \"Add the `#cap-<slug>` tag naming the capability this flow is about.\"\n : `the view resolves ${claim.capabilities.length} capabilities (${claim.capabilities.join(\", \")}), ` +\n \"so nothing says which document the id belongs to. A flow realizing promises from two capabilities \" +\n \"needs one `#req-` tag per capability to be unambiguous, which the tag grammar cannot express — \" +\n \"split the flow, or drop the `#req-` tag and let `Realizes:` on the service requirements carry it.\";\n case \"undocumented\":\n return (\n `capability '${claim.capability}' is declared but has no capabilities/${claim.capability}/spec.md, ` +\n \"so it carries no requirements to satisfy. Write the document — a name alone can be claimed with \" +\n \"`#cap-`, but only a document has promises a flow can keep.\"\n );\n case \"empty\":\n return (\n `capabilities/${claim.capability}/spec.md exists and declares no requirements yet — ` +\n \"add the `## Requirements` section, each requirement carrying its `Requirement-ID:`.\"\n );\n case \"none\":\n return claim.close.length > 0\n ? `capabilities/${claim.capability}/spec.md declares no requirement flattening to '${claim.slug}'. ` +\n `Did you mean: ${claim.close.map(idAndTag).join(\", \")}?`\n : `capabilities/${claim.capability}/spec.md declares no requirement flattening to '${claim.slug}' — ` +\n \"check the `Requirement-ID:` lines in that document.\";\n default:\n return (\n `${claim.ids.length} requirements of '${claim.capability}' flatten to '${claim.slug}' ` +\n `(${claim.ids.join(\", \")}) — nothing in the tag can say which promise this flow keeps. ` +\n \"Rename one of them: a guessed requirement reports the wrong promise as kept and the right one as \" +\n \"unimplemented, and both answers look exactly like the truth.\"\n );\n }\n}\n\n/**\n * One finding per `#req-` tag that does not resolve — never one per view.\n *\n * Several `#req-` tags on one view are legal and normal: a checkout flow that\n * charges once AND honours the price keeps two promises, and there is no honest\n * way to make its author pick one. So a broken tag beside a working one must\n * neither swallow the break nor lose the promise the view genuinely does keep.\n *\n * `claims` is the view's OWN capability verdicts, already resolved by the\n * caller — passed rather than recomputed so the scope this grade uses and the\n * scope `capabilityTagFindings` graded are the same list, and an unresolved\n * `#cap-` tag cannot silently scope a requirement lookup.\n */\nexport function requirementTagFindings(\n view: ParsedView,\n claims: readonly CapabilityClaim[],\n requirementsOf: (capability: string) => ReadonlySet<string> | undefined,\n place: ViewPlace,\n): Finding[] {\n const scope = claims.flatMap((claim) => (claim.kind === \"resolved\" ? [claim.id] : []));\n const findings: Finding[] = [];\n for (const claim of resolveRequirementTags(view.tags, scope, requirementsOf)) {\n if (claim.kind === \"resolved\") continue;\n findings.push({\n severity: \"error\",\n code: \"usecase.requirement-unresolved\",\n // The VIEW, not the tag — a subject is what a reader goes and opens, and\n // one broken use case counts once however many of its tags are wrong.\n subject: view.id,\n message: `${place(view)} is tagged #${claim.tag}, and it does not resolve: ${advice(claim)}`,\n });\n }\n return findings;\n}\n"]}
@@ -0,0 +1,266 @@
1
+ /**
2
+ * The three grades one hop of a use case can earn: `usecase.step-unbacked`,
3
+ * `usecase.step-contested` and `usecase.step-unlinked`.
4
+ *
5
+ * The attribution itself is `core/c4/resolve/steps.ts`'s `attributeStep` — which declared
6
+ * relationship backs a hop, oriented on `isBackward` and decided by the
7
+ * DISTINCT-op count — and none of that reasoning is repeated here. This module
8
+ * owns three things: which verdict earns which code, the four guards that keep
9
+ * the warn honest, and the sentences.
10
+ *
11
+ * TWO SCOPES, ONE GRADER. The fleet target grades the `architecture/` project's
12
+ * views and the service target grades a service's own project — every `.likec4`
13
+ * beside `model.likec4`, read the way the renderer reads it
14
+ * (`commands/validate/service/usecases/`). Both call `stepFindings` below with
15
+ * their own `StepGrading`; what differs is only where a finding says the view
16
+ * is (`place`). A second copy of the verdict→code mapping per scope is the
17
+ * drift this package's banner forbids, which is why the intra-service case is
18
+ * a fourth guard here rather than a grader of its own.
19
+ *
20
+ * WHY `step-unbacked` IS THE CHECK THAT EARNS THE FEATURE. A hop between two
21
+ * elements that both exist, with no relationship between them anywhere in the
22
+ * model, is ZERO LikeC4 errors: a `dynamic view` is allowed to show a call the
23
+ * model never declared, so the diagram renders, the project parses, and every
24
+ * other check in loam stays green. The flow reads as fine in every tool the
25
+ * fleet has. If loam does not convict it, nothing does — which is why it is an
26
+ * error rather than an advisory.
27
+ *
28
+ * ONE BREACH, ONE FINDING, and here that is structural rather than remembered.
29
+ * `contested` and `attributed` are disjoint verdicts, so deriving
30
+ * `step-unlinked` from the `attributed` arm — never from the candidate
31
+ * relationships — is what makes a contested step report once. A grader that
32
+ * walked `rels` looking for a missing `op` would convict the same hop twice:
33
+ * once for the disagreement, and once for whichever candidate happened to carry
34
+ * no operation at all.
35
+ */
36
+ import { attributeStep, pickingTitle } from "../../c4/resolve/steps.js";
37
+ import { ACTOR_KINDS } from "../../vocabulary/maturity.js";
38
+ import { stepPlace } from "../place.js";
39
+ /**
40
+ * `…checkout.likec4 — dynamic view 'uc_checkout' step 2 'authorizes the payment'`.
41
+ *
42
+ * Spelled once per hop in `stepFindings` and handed to each sentence builder as
43
+ * a string, rather than recomputed from the grading inside each of them: three
44
+ * builders reaching for `grading.place` on their own would be three
45
+ * places for one scope to forget the injection.
46
+ */
47
+ function placeOf(hop, grading) {
48
+ return `${grading.place(hop.view)} ${stepPlace(hop.step)}`;
49
+ }
50
+ /**
51
+ * A hop nothing in the model backs.
52
+ *
53
+ * Two fixes, because there are genuinely two mistakes that land here and the
54
+ * author is the only one who can say which they made: the edge really is
55
+ * missing, or the hop is a reply written the long way round. The second is
56
+ * offered as the OTHER spelling of what they already typed — suggesting the
57
+ * spelling they used would be a hint that restates the defect — and the sentence
58
+ * says which pair that spelling looks the hop up under, because `<-` attributes
59
+ * a reply to the CALL it answers rather than to the direction the message
60
+ * travels (`callPair` in core/c4/resolve/steps.ts holds the measurement).
61
+ */
62
+ function unbackedFinding(hop, attribution, place) {
63
+ const other = hop.step.isBackward
64
+ ? { spelling: `${hop.step.source} -> ${hop.step.target}`, when: "is not a return step" }
65
+ : { spelling: `${hop.step.target} <- ${hop.step.source}`, when: "is a return step" };
66
+ return {
67
+ severity: "error",
68
+ code: "usecase.step-unbacked",
69
+ subject: hop.view.id,
70
+ message: `${place}: nothing in the model declares ${attribution.from} -> ${attribution.to}, so this hop is ` +
71
+ "backed by no relationship — and LikeC4 reports no error for it, so the view still renders and the " +
72
+ "project still parses. Draw the edge in `model { }` (with `metadata { op '<operationId>' }` where it is " +
73
+ `a call), or, if this hop ${other.when}, write it as \`${other.spelling}\` — a reply is attributed to the ` +
74
+ `call it answers, so that spelling looks the hop up under ${attribution.to} -> ${attribution.from} instead.`,
75
+ };
76
+ }
77
+ /**
78
+ * `web -> orders.api "Calls createOrder" (op: createOrder)`, `(publishes: order.Placed)`,
79
+ * or `(no op)` where the edge declares no name at all.
80
+ *
81
+ * Every declared name is printed, the message ones included, because each is
82
+ * what the step's title can open with to pick this edge — a line that showed
83
+ * `no op` for a `publishes` edge would hide the one spelling that resolves it.
84
+ * An empty value is not printed: `op ''` parses, names nothing a title could
85
+ * open with, and `op: ` would read as a name somebody forgot to finish.
86
+ */
87
+ function candidateLine(rel) {
88
+ const names = [
89
+ ...(rel.op === undefined || rel.op === "" ? [] : [`op: ${rel.op}`]),
90
+ ...(rel.publishes === undefined || rel.publishes === "" ? [] : [`publishes: ${rel.publishes}`]),
91
+ ...(rel.consumes === undefined || rel.consumes === "" ? [] : [`consumes: ${rel.consumes}`]),
92
+ ];
93
+ return `${rel.source} -> ${rel.target} "${rel.title ?? ""}" (${names.length === 0 ? "no op" : names.join(", ")})`;
94
+ }
95
+ /**
96
+ * A hop whose candidates disagree about the operation, and whose title picks
97
+ * none of them.
98
+ *
99
+ * WARN, not error, because the model is complete — every candidate is a
100
+ * relationship somebody drew on purpose — and the honest answer is sometimes
101
+ * "two paths, one flow". What loam refuses to do is pick: a guessed operation is
102
+ * indistinguishable from a right one in every rollup built over the use case,
103
+ * and it stays wrong invisibly. The AUTHOR can pick, by opening the step's
104
+ * title with the operation id it means (`pickedByTitle` in
105
+ * core/c4/resolve/steps.ts), and the message leads with that repair because it
106
+ * is the one that works in every scope. The older "draw the hop between the
107
+ * elements that name exactly one" is still offered, last and qualified: it works
108
+ * where the graded project declares those elements — a service's own flow over
109
+ * its containers, a map that draws a service's containers itself — and is
110
+ * closed on a fleet flow whose services are single elements on the map, which
111
+ * is the hop that had no repair at all before the title could pick.
112
+ *
113
+ * The example spells the author's own title behind a candidate's declared name,
114
+ * so the line to write is visible rather than described, and `pickingTitle`
115
+ * chooses it by trying it — an example that would leave the hop contested is
116
+ * never offered. Which candidate it names is otherwise arbitrary, the first
117
+ * that works, and the sentence says "for example" because of it: `details` is
118
+ * where the author finds the one meant. When no single name settles the
119
+ * disagreement — every name shared by candidates that still disagree — there is
120
+ * no example to give, and the sentence goes without one.
121
+ *
122
+ * `details` carries every candidate rather than the distinct ops, because the
123
+ * repair is made on a RELATIONSHIP: the author has to find the edge that names
124
+ * the wrong operation, and a list of operation names does not say which edge
125
+ * that is. An absent `metadata { op }` prints as `no op` and is a candidate like
126
+ * any other — it is exactly as much of a disagreement as a second name.
127
+ */
128
+ function contestedFinding(hop, attribution, place) {
129
+ const example = pickingTitle(attribution.rels, hop.step.title);
130
+ return {
131
+ severity: "warn",
132
+ code: "usecase.step-contested",
133
+ subject: hop.view.id,
134
+ message: `${place}: ${attribution.rels.length} relationships back ${attribution.from} -> ` +
135
+ `${attribution.to} and they name ${attribution.ops.length} different operations, so nothing can say ` +
136
+ "which one this hop exercises. loam names the candidates instead of picking one — a guessed operation " +
137
+ "reads exactly like a right one in every rollup built over this flow. Say which one the hop means by " +
138
+ "opening the step's title with that candidate's operation id (or the message it publishes or consumes), " +
139
+ `then punctuation before any further words${example === undefined ? "" : ` — for example '${example}'`}; ` +
140
+ "or give the candidates one operation; or, where this project declares the elements behind each " +
141
+ "candidate, draw the hop between them.",
142
+ details: attribution.rels.map(candidateLine),
143
+ };
144
+ }
145
+ /**
146
+ * The service this hop calls, when the hop is a `step-unlinked` candidate at
147
+ * all — `null` when any of the four guards refuses. ALL FOUR are mechanical,
148
+ * and each closes a whole class of warnings that would otherwise be simply
149
+ * wrong. The count is stated because a reader auditing this function is meant to
150
+ * find four bullets and four `return null`s below and conclude that none of
151
+ * them is surplus: the one a miscount invites deleting is the actor guard, and
152
+ * deleting it puts the warning back on the first hop of almost every flow;
153
+ * deleting the last puts it on EVERY hop of every flow drawn inside a service.
154
+ *
155
+ * - A `publishes` or `consumes` on ANY candidate means the hop does reach a
156
+ * declared API — an AsyncAPI one. The event spine already grades it
157
+ * (`spine.message-undefined` and its family), and asking for an `op` as well
158
+ * would be loam demanding an HTTP operationId for a Kafka message. Read
159
+ * across every candidate rather than the first, because on the service tier
160
+ * the candidates are one call drawn as containers.
161
+ * - The target must resolve to a real `services/<id>/`. Without it every hop
162
+ * into an `#external` system, an actor, a database, a cache or a queue warns
163
+ * — none of which owns an `openapi.yaml`, so none of them CAN carry the
164
+ * operationId the message would be asking for. Through the shared resolver,
165
+ * so "the provider" here and "the provider" in the spine check cannot
166
+ * disagree about which element stands for which directory.
167
+ * - The CALLER must not be an actor. A person is not a caller: `customer ->
168
+ * checkoutWeb 'opens the basket'` is somebody using the app, and the app owes
169
+ * no operationId for a click. The guard above does not cover this, because it
170
+ * reads the TARGET — and the target here is one of ours, so without this the
171
+ * warning fired on the FIRST HOP OF ALMOST EVERY FLOW, which is where a
172
+ * sequence diagram puts its actor. Measured on the published example fleet
173
+ * before it was added. This is the same exemption `commands/validate/fleet/census.ts`,
174
+ * `commands/validate/arch-coverage.ts`, `core/gate/partners.ts` and `core/verify/checklist.ts`
175
+ * each already apply, through the same `ACTOR_KINDS` — a person was never a
176
+ * participant in any of loam's other censuses either.
177
+ * - The CALLER must not resolve to the provider itself. A hop between two
178
+ * containers of one service — `api -> db` inside a service's own project,
179
+ * or the same pair on a landscape that draws the service as containers —
180
+ * names no operation of that service's contract: an operationId is what a
181
+ * caller OUTSIDE the boundary uses, and a service owes none to itself. The
182
+ * three guards above all pass such a hop (the edge carries no message, the
183
+ * target IS a real `services/<id>/`, the caller is a container), so without
184
+ * this one the warning fired on every hop of every intra-service flow the
185
+ * moment loam started reading them — and the message ("names no operation
186
+ * of X's contract") was about X calling X. Through the same shared
187
+ * resolver as the provider, so the two sides of the comparison cannot
188
+ * disagree about which directory an element stands for.
189
+ *
190
+ * The op test reads the ATTRIBUTION rather than the relationships: an
191
+ * `attributed` verdict with no `op` means every candidate agreed the hop names
192
+ * no operation, which is the state this warn is about. Candidates that disagree
193
+ * never reach here at all — that is the suppression, and it is why it cannot be
194
+ * forgotten. Candidates the step's title picked out of a disagreement do reach
195
+ * here, as the picked ones only, and a pick never lands on an edge declaring no
196
+ * name: a title picks by `op`, `publishes` or `consumes`, so a picked verdict
197
+ * either carries its `op` or is a message hop the first guard lets go.
198
+ */
199
+ function unlinkedProvider(attribution, grading) {
200
+ if (attribution.op !== undefined)
201
+ return null;
202
+ if (attribution.rels.some((rel) => rel.publishes !== undefined || rel.consumes !== undefined))
203
+ return null;
204
+ if (isActor(attribution.from, grading.model.elements))
205
+ return null;
206
+ const provider = grading.resolve(attribution.to);
207
+ if (grading.resolve(attribution.from) === provider)
208
+ return null;
209
+ return grading.services.has(provider) ? provider : null;
210
+ }
211
+ /**
212
+ * Is this endpoint a person rather than a system?
213
+ *
214
+ * Exact id, not the ancestor walk the service resolver does: an actor is a
215
+ * top-level element in every landscape loam has seen, and a nested one would be
216
+ * a person inside a system, which is not a shape the model has. An endpoint that
217
+ * names no element cannot occur — a step naming one is a LikeC4 reference error,
218
+ * so the document never reaches a check.
219
+ */
220
+ function isActor(id, elements) {
221
+ const element = elements.find((candidate) => candidate.id === id);
222
+ return element !== undefined && ACTOR_KINDS.has(element.kind.toLowerCase());
223
+ }
224
+ /**
225
+ * A hop backed by the model and joined to no contract.
226
+ *
227
+ * The mirror of `spine.op-link-missing` at flow altitude: the use case reaches
228
+ * the fleet map and stops there, so nothing can say which operation of the
229
+ * provider's contract the step exercises — and the whole point of grading a use
230
+ * case is that the flow joins through to the API it drives.
231
+ */
232
+ function unlinkedFinding(hop, attribution, provider, place) {
233
+ const backing = attribution.rels.length === 1 ? "one relationship" : `${attribution.rels.length} relationships`;
234
+ return {
235
+ severity: "warn",
236
+ code: "usecase.step-unlinked",
237
+ subject: hop.view.id,
238
+ message: `${place}: ${attribution.from} -> ${attribution.to} is backed by ${backing} carrying no ` +
239
+ "`metadata { op }` and no `publishes`/`consumes`, so this hop names no operation of " +
240
+ `${provider}'s contract — the use case reaches the fleet map and stops there. Add ` +
241
+ "`metadata { op '<operationId>' }` to the edge in `model { }`, or `metadata { publishes '<message>' }` / " +
242
+ "`consumes` where the hop is an event.",
243
+ };
244
+ }
245
+ /**
246
+ * The findings one hop earns — at most one, whatever is wrong with it.
247
+ *
248
+ * A `switch` over the closed verdict union with every arm returning, so a fourth
249
+ * verdict added upstream is a compile error here rather than a hop that silently
250
+ * stops being graded.
251
+ */
252
+ export function stepFindings(hop, grading) {
253
+ const attribution = attributeStep(hop.step, grading.model);
254
+ const place = placeOf(hop, grading);
255
+ switch (attribution.verdict) {
256
+ case "unbacked":
257
+ return [unbackedFinding(hop, attribution, place)];
258
+ case "contested":
259
+ return [contestedFinding(hop, attribution, place)];
260
+ case "attributed": {
261
+ const provider = unlinkedProvider(attribution, grading);
262
+ return provider === null ? [] : [unlinkedFinding(hop, attribution, provider, place)];
263
+ }
264
+ }
265
+ }
266
+ //# sourceMappingURL=steps.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"steps.js","sourceRoot":"","sources":["../../../../src/core/usecases/grade/steps.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,OAAO,EAAE,aAAa,EAAE,YAAY,EAAwC,MAAM,2BAA2B,CAAC;AAG9G,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAE3D,OAAO,EAAE,SAAS,EAAkB,MAAM,aAAa,CAAC;AAmDxD;;;;;;;GAOG;AACH,SAAS,OAAO,CAAC,GAAe,EAAE,OAAoB;IACpD,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;AAC7D,CAAC;AAED;;;;;;;;;;;GAWG;AACH,SAAS,eAAe,CAAC,GAAe,EAAE,WAAqB,EAAE,KAAa;IAC5E,MAAM,KAAK,GAAG,GAAG,CAAC,IAAI,CAAC,UAAU;QAC/B,CAAC,CAAC,EAAE,QAAQ,EAAE,GAAG,GAAG,CAAC,IAAI,CAAC,MAAM,OAAO,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,sBAAsB,EAAE;QACxF,CAAC,CAAC,EAAE,QAAQ,EAAE,GAAG,GAAG,CAAC,IAAI,CAAC,MAAM,OAAO,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,kBAAkB,EAAE,CAAC;IACvF,OAAO;QACL,QAAQ,EAAE,OAAO;QACjB,IAAI,EAAE,uBAAuB;QAC7B,OAAO,EAAE,GAAG,CAAC,IAAI,CAAC,EAAE;QACpB,OAAO,EACL,GAAG,KAAK,mCAAmC,WAAW,CAAC,IAAI,OAAO,WAAW,CAAC,EAAE,mBAAmB;YACnG,oGAAoG;YACpG,yGAAyG;YACzG,4BAA4B,KAAK,CAAC,IAAI,mBAAmB,KAAK,CAAC,QAAQ,oCAAoC;YAC3G,4DAA4D,WAAW,CAAC,EAAE,OAAO,WAAW,CAAC,IAAI,WAAW;KAC/G,CAAC;AACJ,CAAC;AAED;;;;;;;;;GASG;AACH,SAAS,aAAa,CAAC,GAAQ;IAC7B,MAAM,KAAK,GAAG;QACZ,GAAG,CAAC,GAAG,CAAC,EAAE,KAAK,SAAS,IAAI,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC;QACnE,GAAG,CAAC,GAAG,CAAC,SAAS,KAAK,SAAS,IAAI,GAAG,CAAC,SAAS,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,cAAc,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC;QAC/F,GAAG,CAAC,GAAG,CAAC,QAAQ,KAAK,SAAS,IAAI,GAAG,CAAC,QAAQ,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,aAAa,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC;KAC5F,CAAC;IACF,OAAO,GAAG,GAAG,CAAC,MAAM,OAAO,GAAG,CAAC,MAAM,KAAK,GAAG,CAAC,KAAK,IAAI,EAAE,MAAM,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;AACpH,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,SAAS,gBAAgB,CAAC,GAAe,EAAE,WAAsB,EAAE,KAAa;IAC9E,MAAM,OAAO,GAAG,YAAY,CAAC,WAAW,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC/D,OAAO;QACL,QAAQ,EAAE,MAAM;QAChB,IAAI,EAAE,wBAAwB;QAC9B,OAAO,EAAE,GAAG,CAAC,IAAI,CAAC,EAAE;QACpB,OAAO,EACL,GAAG,KAAK,KAAK,WAAW,CAAC,IAAI,CAAC,MAAM,uBAAuB,WAAW,CAAC,IAAI,MAAM;YACjF,GAAG,WAAW,CAAC,EAAE,kBAAkB,WAAW,CAAC,GAAG,CAAC,MAAM,4CAA4C;YACrG,uGAAuG;YACvG,sGAAsG;YACtG,yGAAyG;YACzG,4CAA4C,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,mBAAmB,OAAO,GAAG,IAAI;YAC1G,iGAAiG;YACjG,uCAAuC;QACzC,OAAO,EAAE,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,aAAa,CAAC;KAC7C,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqDG;AACH,SAAS,gBAAgB,CAAC,WAAuB,EAAE,OAAoB;IACrE,IAAI,WAAW,CAAC,EAAE,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IAC9C,IAAI,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,SAAS,KAAK,SAAS,IAAI,GAAG,CAAC,QAAQ,KAAK,SAAS,CAAC;QAAE,OAAO,IAAI,CAAC;IAC3G,IAAI,OAAO,CAAC,WAAW,CAAC,IAAI,EAAE,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC;QAAE,OAAO,IAAI,CAAC;IACnE,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;IACjD,IAAI,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IAChE,OAAO,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC;AAC1D,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,OAAO,CAAC,EAAU,EAAE,QAAgB;IAC3C,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;IAClE,OAAO,OAAO,KAAK,SAAS,IAAI,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;AAC9E,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,eAAe,CAAC,GAAe,EAAE,WAAuB,EAAE,QAAgB,EAAE,KAAa;IAChG,MAAM,OAAO,GACX,WAAW,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,gBAAgB,CAAC;IAClG,OAAO;QACL,QAAQ,EAAE,MAAM;QAChB,IAAI,EAAE,uBAAuB;QAC7B,OAAO,EAAE,GAAG,CAAC,IAAI,CAAC,EAAE;QACpB,OAAO,EACL,GAAG,KAAK,KAAK,WAAW,CAAC,IAAI,OAAO,WAAW,CAAC,EAAE,iBAAiB,OAAO,eAAe;YACzF,qFAAqF;YACrF,GAAG,QAAQ,wEAAwE;YACnF,0GAA0G;YAC1G,uCAAuC;KAC1C,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,YAAY,CAAC,GAAe,EAAE,OAAoB;IAChE,MAAM,WAAW,GAAG,aAAa,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;IAC3D,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IACpC,QAAQ,WAAW,CAAC,OAAO,EAAE,CAAC;QAC5B,KAAK,UAAU;YACb,OAAO,CAAC,eAAe,CAAC,GAAG,EAAE,WAAW,EAAE,KAAK,CAAC,CAAC,CAAC;QACpD,KAAK,WAAW;YACd,OAAO,CAAC,gBAAgB,CAAC,GAAG,EAAE,WAAW,EAAE,KAAK,CAAC,CAAC,CAAC;QACrD,KAAK,YAAY,EAAE,CAAC;YAClB,MAAM,QAAQ,GAAG,gBAAgB,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;YACxD,OAAO,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,GAAG,EAAE,WAAW,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC;QACvF,CAAC;IACH,CAAC;AACH,CAAC","sourcesContent":["/**\n * The three grades one hop of a use case can earn: `usecase.step-unbacked`,\n * `usecase.step-contested` and `usecase.step-unlinked`.\n *\n * The attribution itself is `core/c4/resolve/steps.ts`'s `attributeStep` — which declared\n * relationship backs a hop, oriented on `isBackward` and decided by the\n * DISTINCT-op count — and none of that reasoning is repeated here. This module\n * owns three things: which verdict earns which code, the four guards that keep\n * the warn honest, and the sentences.\n *\n * TWO SCOPES, ONE GRADER. The fleet target grades the `architecture/` project's\n * views and the service target grades a service's own project — every `.likec4`\n * beside `model.likec4`, read the way the renderer reads it\n * (`commands/validate/service/usecases/`). Both call `stepFindings` below with\n * their own `StepGrading`; what differs is only where a finding says the view\n * is (`place`). A second copy of the verdict→code mapping per scope is the\n * drift this package's banner forbids, which is why the intra-service case is\n * a fourth guard here rather than a grader of its own.\n *\n * WHY `step-unbacked` IS THE CHECK THAT EARNS THE FEATURE. A hop between two\n * elements that both exist, with no relationship between them anywhere in the\n * model, is ZERO LikeC4 errors: a `dynamic view` is allowed to show a call the\n * model never declared, so the diagram renders, the project parses, and every\n * other check in loam stays green. The flow reads as fine in every tool the\n * fleet has. If loam does not convict it, nothing does — which is why it is an\n * error rather than an advisory.\n *\n * ONE BREACH, ONE FINDING, and here that is structural rather than remembered.\n * `contested` and `attributed` are disjoint verdicts, so deriving\n * `step-unlinked` from the `attributed` arm — never from the candidate\n * relationships — is what makes a contested step report once. A grader that\n * walked `rels` looking for a missing `op` would convict the same hop twice:\n * once for the disagreement, and once for whichever candidate happened to carry\n * no operation at all.\n */\nimport { attributeStep, pickingTitle, type StepAttribution, type StepScope } from \"../../c4/resolve/steps.js\";\nimport type { Elem, Rel } from \"../../c4/likec4.js\";\nimport type { ParsedStep, ParsedView } from \"../../c4/parsed/dynamic-views.js\";\nimport { ACTOR_KINDS } from \"../../vocabulary/maturity.js\";\nimport type { Finding } from \"../../vocabulary/report.js\";\nimport { stepPlace, type ViewPlace } from \"../place.js\";\n\n/** One hop being graded and the view it belongs to — never passed apart. */\nexport interface GradedStep {\n view: ParsedView;\n step: ParsedStep;\n}\n\n/**\n * What a hop is graded against, built ONCE per run.\n *\n * `services` and `model.known` are the same set by construction (`./usecases.ts`\n * builds both from one value), which is what stops \"which service is this\n * element\" being answered one way by the attribution and another by the provider\n * guard below. `resolve` is injected for the same reason `fleetShapeFindings`\n * takes it: the fleet target already holds the shared element→service resolver,\n * and a second one built here could not disagree today but would be a second\n * place to change.\n */\nexport interface StepGrading {\n model: StepScope;\n /**\n * The `services/<id>/` directories that exist. The SAME enumerated set in\n * both scopes — the service target hands over the whole fleet too, never an\n * empty set — so the documented invariant above (`services` and `model.known`\n * are one value) holds wherever this grader runs, and the intra-service\n * exemption is the fourth guard in `unlinkedProvider` rather than a scope\n * that quietly disables the provider test.\n */\n services: ReadonlySet<string>;\n /** The shared element→service resolver every other edge join uses. */\n resolve: (id: string) => string;\n /**\n * Where a finding says the view is — the opening of every message in this\n * family. REQUIRED since the graders moved into `core/`: the fleet target's\n * `landscape: architecture/<file> — dynamic view '<id>'` is `viewPlace` in\n * `commands/validate/fleet/usecases/place.ts`, command vocabulary core may not\n * import, so every scope states its own. The feature gate injects the feature's\n * `usecases/` file (`./feature.ts`), and the service target\n * injects its own, because a view read out of a service's project carries a\n * `sourcePath` relative to the SERVICE directory, and the `landscape:`\n * opening is the fleet target's name — a finding filed on a service must not\n * claim it (`../place.ts` records why the prefix stayed command vocabulary).\n */\n place: ViewPlace;\n}\n\ntype Unbacked = Extract<StepAttribution, { verdict: \"unbacked\" }>;\ntype Contested = Extract<StepAttribution, { verdict: \"contested\" }>;\ntype Attributed = Extract<StepAttribution, { verdict: \"attributed\" }>;\n\n/**\n * `…checkout.likec4 — dynamic view 'uc_checkout' step 2 'authorizes the payment'`.\n *\n * Spelled once per hop in `stepFindings` and handed to each sentence builder as\n * a string, rather than recomputed from the grading inside each of them: three\n * builders reaching for `grading.place` on their own would be three\n * places for one scope to forget the injection.\n */\nfunction placeOf(hop: GradedStep, grading: StepGrading): string {\n return `${grading.place(hop.view)} ${stepPlace(hop.step)}`;\n}\n\n/**\n * A hop nothing in the model backs.\n *\n * Two fixes, because there are genuinely two mistakes that land here and the\n * author is the only one who can say which they made: the edge really is\n * missing, or the hop is a reply written the long way round. The second is\n * offered as the OTHER spelling of what they already typed — suggesting the\n * spelling they used would be a hint that restates the defect — and the sentence\n * says which pair that spelling looks the hop up under, because `<-` attributes\n * a reply to the CALL it answers rather than to the direction the message\n * travels (`callPair` in core/c4/resolve/steps.ts holds the measurement).\n */\nfunction unbackedFinding(hop: GradedStep, attribution: Unbacked, place: string): Finding {\n const other = hop.step.isBackward\n ? { spelling: `${hop.step.source} -> ${hop.step.target}`, when: \"is not a return step\" }\n : { spelling: `${hop.step.target} <- ${hop.step.source}`, when: \"is a return step\" };\n return {\n severity: \"error\",\n code: \"usecase.step-unbacked\",\n subject: hop.view.id,\n message:\n `${place}: nothing in the model declares ${attribution.from} -> ${attribution.to}, so this hop is ` +\n \"backed by no relationship — and LikeC4 reports no error for it, so the view still renders and the \" +\n \"project still parses. Draw the edge in `model { }` (with `metadata { op '<operationId>' }` where it is \" +\n `a call), or, if this hop ${other.when}, write it as \\`${other.spelling}\\` — a reply is attributed to the ` +\n `call it answers, so that spelling looks the hop up under ${attribution.to} -> ${attribution.from} instead.`,\n };\n}\n\n/**\n * `web -> orders.api \"Calls createOrder\" (op: createOrder)`, `(publishes: order.Placed)`,\n * or `(no op)` where the edge declares no name at all.\n *\n * Every declared name is printed, the message ones included, because each is\n * what the step's title can open with to pick this edge — a line that showed\n * `no op` for a `publishes` edge would hide the one spelling that resolves it.\n * An empty value is not printed: `op ''` parses, names nothing a title could\n * open with, and `op: ` would read as a name somebody forgot to finish.\n */\nfunction candidateLine(rel: Rel): string {\n const names = [\n ...(rel.op === undefined || rel.op === \"\" ? [] : [`op: ${rel.op}`]),\n ...(rel.publishes === undefined || rel.publishes === \"\" ? [] : [`publishes: ${rel.publishes}`]),\n ...(rel.consumes === undefined || rel.consumes === \"\" ? [] : [`consumes: ${rel.consumes}`]),\n ];\n return `${rel.source} -> ${rel.target} \"${rel.title ?? \"\"}\" (${names.length === 0 ? \"no op\" : names.join(\", \")})`;\n}\n\n/**\n * A hop whose candidates disagree about the operation, and whose title picks\n * none of them.\n *\n * WARN, not error, because the model is complete — every candidate is a\n * relationship somebody drew on purpose — and the honest answer is sometimes\n * \"two paths, one flow\". What loam refuses to do is pick: a guessed operation is\n * indistinguishable from a right one in every rollup built over the use case,\n * and it stays wrong invisibly. The AUTHOR can pick, by opening the step's\n * title with the operation id it means (`pickedByTitle` in\n * core/c4/resolve/steps.ts), and the message leads with that repair because it\n * is the one that works in every scope. The older \"draw the hop between the\n * elements that name exactly one\" is still offered, last and qualified: it works\n * where the graded project declares those elements — a service's own flow over\n * its containers, a map that draws a service's containers itself — and is\n * closed on a fleet flow whose services are single elements on the map, which\n * is the hop that had no repair at all before the title could pick.\n *\n * The example spells the author's own title behind a candidate's declared name,\n * so the line to write is visible rather than described, and `pickingTitle`\n * chooses it by trying it — an example that would leave the hop contested is\n * never offered. Which candidate it names is otherwise arbitrary, the first\n * that works, and the sentence says \"for example\" because of it: `details` is\n * where the author finds the one meant. When no single name settles the\n * disagreement — every name shared by candidates that still disagree — there is\n * no example to give, and the sentence goes without one.\n *\n * `details` carries every candidate rather than the distinct ops, because the\n * repair is made on a RELATIONSHIP: the author has to find the edge that names\n * the wrong operation, and a list of operation names does not say which edge\n * that is. An absent `metadata { op }` prints as `no op` and is a candidate like\n * any other — it is exactly as much of a disagreement as a second name.\n */\nfunction contestedFinding(hop: GradedStep, attribution: Contested, place: string): Finding {\n const example = pickingTitle(attribution.rels, hop.step.title);\n return {\n severity: \"warn\",\n code: \"usecase.step-contested\",\n subject: hop.view.id,\n message:\n `${place}: ${attribution.rels.length} relationships back ${attribution.from} -> ` +\n `${attribution.to} and they name ${attribution.ops.length} different operations, so nothing can say ` +\n \"which one this hop exercises. loam names the candidates instead of picking one — a guessed operation \" +\n \"reads exactly like a right one in every rollup built over this flow. Say which one the hop means by \" +\n \"opening the step's title with that candidate's operation id (or the message it publishes or consumes), \" +\n `then punctuation before any further words${example === undefined ? \"\" : ` — for example '${example}'`}; ` +\n \"or give the candidates one operation; or, where this project declares the elements behind each \" +\n \"candidate, draw the hop between them.\",\n details: attribution.rels.map(candidateLine),\n };\n}\n\n/**\n * The service this hop calls, when the hop is a `step-unlinked` candidate at\n * all — `null` when any of the four guards refuses. ALL FOUR are mechanical,\n * and each closes a whole class of warnings that would otherwise be simply\n * wrong. The count is stated because a reader auditing this function is meant to\n * find four bullets and four `return null`s below and conclude that none of\n * them is surplus: the one a miscount invites deleting is the actor guard, and\n * deleting it puts the warning back on the first hop of almost every flow;\n * deleting the last puts it on EVERY hop of every flow drawn inside a service.\n *\n * - A `publishes` or `consumes` on ANY candidate means the hop does reach a\n * declared API — an AsyncAPI one. The event spine already grades it\n * (`spine.message-undefined` and its family), and asking for an `op` as well\n * would be loam demanding an HTTP operationId for a Kafka message. Read\n * across every candidate rather than the first, because on the service tier\n * the candidates are one call drawn as containers.\n * - The target must resolve to a real `services/<id>/`. Without it every hop\n * into an `#external` system, an actor, a database, a cache or a queue warns\n * — none of which owns an `openapi.yaml`, so none of them CAN carry the\n * operationId the message would be asking for. Through the shared resolver,\n * so \"the provider\" here and \"the provider\" in the spine check cannot\n * disagree about which element stands for which directory.\n * - The CALLER must not be an actor. A person is not a caller: `customer ->\n * checkoutWeb 'opens the basket'` is somebody using the app, and the app owes\n * no operationId for a click. The guard above does not cover this, because it\n * reads the TARGET — and the target here is one of ours, so without this the\n * warning fired on the FIRST HOP OF ALMOST EVERY FLOW, which is where a\n * sequence diagram puts its actor. Measured on the published example fleet\n * before it was added. This is the same exemption `commands/validate/fleet/census.ts`,\n * `commands/validate/arch-coverage.ts`, `core/gate/partners.ts` and `core/verify/checklist.ts`\n * each already apply, through the same `ACTOR_KINDS` — a person was never a\n * participant in any of loam's other censuses either.\n * - The CALLER must not resolve to the provider itself. A hop between two\n * containers of one service — `api -> db` inside a service's own project,\n * or the same pair on a landscape that draws the service as containers —\n * names no operation of that service's contract: an operationId is what a\n * caller OUTSIDE the boundary uses, and a service owes none to itself. The\n * three guards above all pass such a hop (the edge carries no message, the\n * target IS a real `services/<id>/`, the caller is a container), so without\n * this one the warning fired on every hop of every intra-service flow the\n * moment loam started reading them — and the message (\"names no operation\n * of X's contract\") was about X calling X. Through the same shared\n * resolver as the provider, so the two sides of the comparison cannot\n * disagree about which directory an element stands for.\n *\n * The op test reads the ATTRIBUTION rather than the relationships: an\n * `attributed` verdict with no `op` means every candidate agreed the hop names\n * no operation, which is the state this warn is about. Candidates that disagree\n * never reach here at all — that is the suppression, and it is why it cannot be\n * forgotten. Candidates the step's title picked out of a disagreement do reach\n * here, as the picked ones only, and a pick never lands on an edge declaring no\n * name: a title picks by `op`, `publishes` or `consumes`, so a picked verdict\n * either carries its `op` or is a message hop the first guard lets go.\n */\nfunction unlinkedProvider(attribution: Attributed, grading: StepGrading): string | null {\n if (attribution.op !== undefined) return null;\n if (attribution.rels.some((rel) => rel.publishes !== undefined || rel.consumes !== undefined)) return null;\n if (isActor(attribution.from, grading.model.elements)) return null;\n const provider = grading.resolve(attribution.to);\n if (grading.resolve(attribution.from) === provider) return null;\n return grading.services.has(provider) ? provider : null;\n}\n\n/**\n * Is this endpoint a person rather than a system?\n *\n * Exact id, not the ancestor walk the service resolver does: an actor is a\n * top-level element in every landscape loam has seen, and a nested one would be\n * a person inside a system, which is not a shape the model has. An endpoint that\n * names no element cannot occur — a step naming one is a LikeC4 reference error,\n * so the document never reaches a check.\n */\nfunction isActor(id: string, elements: Elem[]): boolean {\n const element = elements.find((candidate) => candidate.id === id);\n return element !== undefined && ACTOR_KINDS.has(element.kind.toLowerCase());\n}\n\n/**\n * A hop backed by the model and joined to no contract.\n *\n * The mirror of `spine.op-link-missing` at flow altitude: the use case reaches\n * the fleet map and stops there, so nothing can say which operation of the\n * provider's contract the step exercises — and the whole point of grading a use\n * case is that the flow joins through to the API it drives.\n */\nfunction unlinkedFinding(hop: GradedStep, attribution: Attributed, provider: string, place: string): Finding {\n const backing =\n attribution.rels.length === 1 ? \"one relationship\" : `${attribution.rels.length} relationships`;\n return {\n severity: \"warn\",\n code: \"usecase.step-unlinked\",\n subject: hop.view.id,\n message:\n `${place}: ${attribution.from} -> ${attribution.to} is backed by ${backing} carrying no ` +\n \"`metadata { op }` and no `publishes`/`consumes`, so this hop names no operation of \" +\n `${provider}'s contract — the use case reaches the fleet map and stops there. Add ` +\n \"`metadata { op '<operationId>' }` to the edge in `model { }`, or `metadata { publishes '<message>' }` / \" +\n \"`consumes` where the hop is an event.\",\n };\n}\n\n/**\n * The findings one hop earns — at most one, whatever is wrong with it.\n *\n * A `switch` over the closed verdict union with every arm returning, so a fourth\n * verdict added upstream is a compile error here rather than a hop that silently\n * stops being graded.\n */\nexport function stepFindings(hop: GradedStep, grading: StepGrading): Finding[] {\n const attribution = attributeStep(hop.step, grading.model);\n const place = placeOf(hop, grading);\n switch (attribution.verdict) {\n case \"unbacked\":\n return [unbackedFinding(hop, attribution, place)];\n case \"contested\":\n return [contestedFinding(hop, attribution, place)];\n case \"attributed\": {\n const provider = unlinkedProvider(attribution, grading);\n return provider === null ? [] : [unlinkedFinding(hop, attribution, provider, place)];\n }\n }\n}\n"]}