@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":"modified.js","sourceRoot":"","sources":["../../../../src/core/usecases/delta/modified.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The LIVING flows whose `#req-` tag claims a requirement this feature changes:\n * `usecase.requirement-modified` for one it rewrites, and\n * `usecase.requirement-unresolved` for one it takes away.\n *\n * THE HOLE. A `#req-` tag joins a flow to one named promise, and the join is by\n * id. A MODIFIED requirement keeps its id and replaces its whole text, so after\n * the archive the tag still resolves, every grade of the flow stays green — and\n * the flow can be drawing exactly the behaviour the new wording forbids: an\n * event path the requirement now says is gone, a hop through a service it no\n * longer names. Nothing in loam reads a flow's MEANING, so nothing can say\n * whether the drawing still keeps the promise. What loam can say is that the\n * promise moved under it, and it said nothing.\n *\n * A WARNING, AND IT NEVER GATES. Rewording a promise a flow keeps is ordinary;\n * the flow may well still keep it. This names each flow and the requirement, so\n * the author reads one against the other while the feature is still open — and\n * redraws the flow in the same change where it no longer holds.\n *\n * A REMOVAL IS THE FLEET'S OWN ERROR, ONE ARCHIVE EARLY. The merge deletes the\n * promise and leaves the tag, so the very next `validate --all` reports the flow\n * `usecase.requirement-unresolved` — while the feature gate had said nothing and\n * the archive had exited 0 (the real-fleet review, 2026-10-21). That grade holds\n * no judgement about the drawing: the tag resolves to nothing, whatever the flow\n * shows. So it is raised here under the SAME code, at the same severity, with\n * the VIEW as its subject as at fleet altitude — the fleet's grade predicted,\n * not a second opinion beside it — and as an error it gates the archive.\n * `--approve` may walk past it, for `capability.remove-requirement-realized`'s\n * reason one carrier over: retiring a promise something still claims is the\n * author's call about the feature, loam reads the flow perfectly well (this is\n * no `usecase.flow-invalid` blindness), and the living docs then carry exactly\n * the error this named.\n *\n * GRADED AGAINST WHAT THE MERGE LEAVES, not against the REMOVED list. Each\n * document's after-side is the merge's own fold (`applyRequirementDelta`), so a\n * removal the same delta re-spells under an id that flattens to the same tag\n * leaves the tag resolving and earns nothing, exactly as the fleet will grade\n * it. The same verdict is asked of a MODIFIED: it keeps its id, but\n * an id this feature adds beside it may flatten to the same tag, and then the\n * merge breaks the tag too — the error, not the warning, whose \"the tag will\n * still resolve\" would be false. And only a claim that resolves TODAY is asked\n * about: one that is already broken is `validate --all`'s finding now, and\n * reporting it again here would be one mistake counted twice.\n *\n * TWO ALTITUDES, TWO SCOPES — the ones `validate --all` resolves the tag with.\n * A flow in `architecture/` keeps a BUSINESS promise: its `#req-` tag is scoped\n * by its `#cap-` tag to a capability document (`core/capabilities/usecase-join.ts`),\n * so it is asked about the capability requirements this feature changes. A\n * flow beside a service's model keeps that SERVICE's promise: its `#req-` tag is\n * scoped by the directory to the ids of that service's spec.md and arch.spec.md\n * (`commands/validate/service/usecases/tags.ts`), so it is asked about the\n * service requirements this feature changes there — and only the services the\n * feature's `specs/` touch can hold one. BOTH documents are that scope, so the\n * one a touched service carries no delta for is read as it stands: without it\n * an id the other document also declares would read as gone after the merge,\n * and gate an archive the fleet then grades green. The feature's own\n * `usecases/` are not living and are graded against the new text already\n * (`../grade/feature.ts`).\n *\n * WHAT IT COSTS. Nothing, for a feature that modifies and removes no\n * requirement — which is nearly every feature, and the caller does not call\n * this then. For one that does, a byte scan for the tag's own spelling\n * (`req-<slug>`) over the documents that could declare it, the living document\n * of a touched service's other axis, and a LikeC4 load only for a project one\n * of them is in: a tag name is one token, so a document without its characters\n * cannot carry it. A project that does not parse is skipped, not reported —\n * `validate --all` owns that answer (`usecase.flow-invalid`, `landscape.invalid`),\n * and a finding about one requirement must not become a second report of a\n * broken map.\n */\nimport { existsSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport { join, relative } from \"node:path\";\nimport {\n REQ_TAG_PREFIX,\n resolveCapabilityTags,\n resolveRequirementTags,\n tagSlug,\n type RequirementClaim,\n} from \"../../capabilities/usecase-join.js\";\nimport { gradableCapabilityIds } from \"../../capabilities/findings.js\";\nimport type { CapabilityVocabulary } from \"../../capabilities/capabilities.js\";\nimport type { CapabilityDeltaDoc } from \"../../capabilities/delta/uncovered.js\";\nimport { architectureDocuments } from \"../../c4/project/documents.js\";\nimport { architectureProjectDocuments } from \"../../c4/project/architecture.js\";\nimport type { ParsedView } from \"../../c4/parsed/dynamic-views.js\";\nimport type { LoadedDoc } from \"../../c4/likec4.js\";\nimport type { ServiceModel } from \"../../c4/service-model/load.js\";\nimport { applyRequirementDelta, replacementsOf, type Replacement } from \"../../document/apply.js\";\nimport type { Requirement } from \"../../document/spec.js\";\nimport type { DocsDir } from \"../../kernel/ids/dirs.js\";\nimport { SPEC_AXES, type ServicePaths, type SpecAxis } from \"../../repo/paths.js\";\nimport { compareIds } from \"../../repo/entries.js\";\nimport type { Issue } from \"../../vocabulary/issue.js\";\nimport { useCasesIn } from \"../fleet.js\";\nimport { viewFile } from \"../place.js\";\nimport { readServiceFlows } from \"../service/flows.js\";\n\n/** One delta document beside the living one it merges into — a capability's, or one spec axis of a service. */\nexport interface DeltaPair {\n /** The capability id, or the service id. */\n id: string;\n reqs: readonly Requirement[];\n living: readonly Requirement[];\n}\n\n/** One spec axis of a service the feature touches, and where that service lives — asked only for one whose delta changes something. */\nexport interface ServiceDeltaPair extends DeltaPair {\n /** Which of the service's two documents this is: the other is read as it stands when the feature carries no delta for it. */\n axis: SpecAxis[\"key\"];\n paths: () => Promise<ServicePaths>;\n}\n\nexport interface ChangedPromiseRequest {\n docsDir: DocsDir;\n /** The feature's capability deltas — what an `architecture/` flow's tag is asked about. */\n capabilities: readonly CapabilityDeltaDoc[];\n /** The feature's service deltas, one entry per spec axis — what a service's own flow is asked about. */\n services: readonly ServiceDeltaPair[];\n /** The capability vocabulary a `#cap-` tag resolves against. */\n vocabulary: CapabilityVocabulary;\n /** The enumerated fleet, for the element→service resolver's reason (`../fleet.ts`). */\n known: ReadonlySet<string>;\n /**\n * A service's model, read the way its shape demands. Injected for\n * `./overlay.ts`'s reason: a memoised read does not justify an edge from\n * `core/usecases/` to `fleet-context`.\n */\n serviceModel: (paths: ServicePaths) => Promise<ServiceModel>;\n /**\n * The `architecture/` project, as the invocation already holds it — the\n * same injection, for the same reason: `validate --all` and `status` run this\n * walk once per active feature, and a fresh load per feature is a LikeC4\n * workspace each.\n */\n architecture: () => Promise<LoadedDoc>;\n /** A living requirements document, parsed — a touched service's axis the feature carries no delta for. Injected for the same reason again. */\n readRequirements: (path: string) => Promise<Requirement[]>;\n}\n\n/** One living flow, located, and the scope its `#req-` tag resolves in. */\ninterface LivingFlow {\n view: ParsedView;\n /** The repo-relative file a reader opens. */\n file: string;\n /** The capability ids its own `#cap-` tags resolve to, or — beside a model — its service alone. */\n scope: string[];\n /** Which of the two scopes `scope` is in: a capability id and a service id may be spelled alike. */\n altitude: Altitude;\n}\n\ntype Altitude = \"capability\" | \"service\";\n\ntype Resolved = Extract<RequirementClaim, { kind: \"resolved\" }>;\n\n/**\n * Per document id — a capability, or a service's two axes together, the one\n * set its directory-scoped tag is read against — the ids a tag resolves\n * against today and after the merge, and which living ids this feature\n * rewrites or retires.\n */\ninterface Table {\n living: Map<string, Set<string>>;\n merged: Map<string, Set<string>>;\n modified: Map<string, Set<string>>;\n removed: Map<string, Set<string>>;\n}\n\nexport async function changedPromiseFlowIssues(req: ChangedPromiseRequest): Promise<Issue[]> {\n const tables: Record<Altitude, Table> = {\n capability: tableOf(req.capabilities),\n service: tableOf(await withUntouchedAxes(req)),\n };\n const flows = [\n ...(await fleetFlows(req, changedIds(tables.capability))),\n ...(await serviceFlows(req, changedIds(tables.service))),\n ];\n const issues: Issue[] = [];\n for (const flow of flows.sort((a, b) => compareIds(a.file, b.file) || compareIds(a.view.id, b.view.id))) {\n const table = tables[flow.altitude];\n const after = new Map(resolveRequirementTags(flow.view.tags, flow.scope, (id) => table.merged.get(id)).map((c) => [c.tag, c]));\n for (const claim of resolveRequirementTags(flow.view.tags, flow.scope, (id) => table.living.get(id))) {\n if (claim.kind !== \"resolved\") continue;\n const change = changeOf(table, claim);\n if (change === null) continue;\n // The merge's verdict first, for either change: a MODIFIED keeps its id,\n // but an id this feature adds beside it can flatten to the same tag, and\n // then the warning's \"the tag will still resolve\" would be false.\n const later = after.get(claim.tag);\n if (later !== undefined && later.kind !== \"resolved\") issues.push(brokenIssue(flow, claim, { change, later }));\n else if (change === \"MODIFIES\") issues.push(modifiedIssue(flow, claim));\n }\n }\n return issues;\n}\n\nfunction changeOf(table: Table, claim: Resolved): \"MODIFIES\" | \"REMOVES\" | null {\n if (table.modified.get(claim.capability)?.has(claim.id) === true) return \"MODIFIES\";\n return table.removed.get(claim.capability)?.has(claim.id) === true ? \"REMOVES\" : null;\n}\n\nfunction whose(flow: LivingFlow, claim: Resolved): string {\n return flow.altitude === \"capability\" ? `${claim.capability}#${claim.id}` : `${claim.capability}'s requirement ${claim.id}`;\n}\n\nfunction modifiedIssue(flow: LivingFlow, claim: Resolved): Issue {\n return {\n severity: \"warn\",\n code: \"usecase.requirement-modified\",\n subject: claim.capability,\n message:\n `${flow.file}: flow '${flow.view.id}' is tagged #${claim.tag} — it claims ${whose(flow, claim)}, which this feature MODIFIES. ` +\n `The tag will still resolve after the archive and nothing grades what the flow draws against the new ` +\n `wording: read the flow against the replacement, and redraw it in this change if it no longer keeps the promise.`,\n locations: [{ path: flow.file, role: \"primary\" }],\n };\n}\n\n/**\n * The tag the merge breaks. Two ways, and each has its own fix: a removal\n * leaves nothing the tag names, and an id this feature adds can flatten to the\n * same tag as the one it claims — the only way a MODIFIED, which keeps its id,\n * can break it at all.\n */\nfunction brokenIssue(\n flow: LivingFlow,\n claim: Resolved,\n broken: { change: \"MODIFIES\" | \"REMOVES\"; later: Exclude<RequirementClaim, { kind: \"resolved\" }> },\n): Issue {\n const { change, later } = broken;\n const [why, fix] =\n later.kind === \"many\"\n ? [\n `${later.ids.length} requirements will flatten to '${later.slug}' (${later.ids.join(\", \")}), so nothing in the tag can say which promise the flow keeps`,\n \"rename one of the colliding ids in this change\",\n ]\n : [\n \"nothing it names is left\",\n \"drop the tag (or point it at the promise that replaces this one) in this change, or MODIFY the requirement instead of removing it\",\n ];\n return {\n severity: \"error\",\n code: \"usecase.requirement-unresolved\",\n // The VIEW, as `validate --all` names it once the archive lands — so the\n // prediction and the outcome are about one thing a reader opens.\n subject: flow.view.id,\n message:\n `${flow.file}: flow '${flow.view.id}' is tagged #${claim.tag} — it claims ${whose(flow, claim)}, which this feature ${change}. ` +\n `After the archive the tag no longer resolves — ${why} — and \\`loam validate --all\\` reports this flow with this ` +\n `same error: ${fix}.`,\n locations: [{ path: flow.file, role: \"primary\" }],\n };\n}\n\n/**\n * Each document's table rows. The modified and removed ids are named by the id\n * the LIVING document gives them — selected by `replacementsOf`, the merge's own\n * walk, so a MODIFIED or REMOVED written by heading alone still names the id a\n * tag carries — and the after-side is that same merge's result. A document the\n * merge would refuse keeps its living ids on both sides and changes nothing:\n * the delta gate reports it, and nothing here has a true thing to say about a\n * merge that cannot happen.\n *\n * TODAY'S side leaves out a living requirement sitting under a REMOVED heading,\n * as both fleet indexes do (`capabilityRequirementIndex`, `requirementIdsOf`):\n * a tag resolving only through one is already the fleet's error. The fold\n * still runs on the whole living list, because that is the archive's input.\n */\nfunction tableOf(docs: readonly DeltaPair[]): Table {\n const table: Table = { living: new Map(), merged: new Map(), modified: new Map(), removed: new Map() };\n for (const doc of docs) {\n const living = doc.living.filter((r) => r.kind !== \"REMOVED\");\n let fold: { replaced: Replacement[]; merged: readonly Requirement[] };\n try {\n fold = { replaced: replacementsOf([...doc.living], [...doc.reqs]), merged: applyRequirementDelta([...doc.living], [...doc.reqs]) };\n } catch {\n fold = { replaced: [], merged: living };\n }\n idsInto(table.living, doc.id, living);\n idsInto(table.merged, doc.id, fold.merged);\n for (const r of fold.replaced) {\n if (r.living.id === undefined || (r.kind !== \"MODIFIED\" && r.kind !== \"REMOVED\")) continue;\n const into = r.kind === \"MODIFIED\" ? table.modified : table.removed;\n into.set(doc.id, (into.get(doc.id) ?? new Set()).add(r.living.id));\n }\n }\n return table;\n}\n\n/** A document's ids, unioned into its row — created even when empty, which is the `empty` arm's answer rather than `undocumented`'s. */\nfunction idsInto(rows: Map<string, Set<string>>, id: string, reqs: readonly Requirement[]): void {\n const ids = rows.get(id) ?? new Set<string>();\n for (const r of reqs) if (r.id !== undefined) ids.add(r.id);\n rows.set(id, ids);\n}\n\n/** The ids each document's delta modifies or removes — what a flow has to mention to be asked about at all. */\nfunction changedIds(table: Table): Map<string, Set<string>> {\n const out = new Map<string, Set<string>>();\n for (const rows of [table.modified, table.removed]) {\n for (const [id, ids] of rows) out.set(id, new Set([...(out.get(id) ?? []), ...ids]));\n }\n return out;\n}\n\n/**\n * The service pairs, plus — for each service whose delta modifies or removes\n * something — every document of it the feature carries no delta for, as it\n * stands (`reqs: []`, so it changes nothing and only widens both sides).\n * `requirementIdsOf` (`commands/validate/service/usecases/usecases.ts`) reads\n * both documents for a service-local tag, skipping a requirement under a\n * REMOVED heading; so must this, or a tag the untouched document keeps\n * resolving reads as broken — and one only a REMOVED entry there answers reads\n * as kept, though the archive leaves that document as it is.\n */\nasync function withUntouchedAxes(req: ChangedPromiseRequest): Promise<DeltaPair[]> {\n const out: DeltaPair[] = [...req.services];\n const asked = new Set<string>();\n // Sequential, and it costs nothing worth racing: a feature names a handful of\n // services, each read is one memoised document, and most services here\n // already have both axes in the feature or no second document at all.\n for (const pair of req.services) {\n const own = req.services.filter((p) => p.id === pair.id);\n if (asked.has(pair.id) || !own.some((p) => p.reqs.some((r) => r.kind === \"MODIFIED\" || r.kind === \"REMOVED\"))) continue;\n asked.add(pair.id);\n const paths = await pair.paths();\n for (const axis of SPEC_AXES) {\n if (own.some((p) => p.axis === axis.key) || !existsSync(paths[axis.key])) continue;\n const living = (await req.readRequirements(paths[axis.key])).filter((r) => r.kind !== \"REMOVED\");\n out.push({ id: pair.id, reqs: [], living });\n }\n }\n return out;\n}\n\n/** The tag spellings that could claim one of these ids. */\nfunction needlesFor(changed: ReadonlyMap<string, ReadonlySet<string>>): string[] {\n return [...new Set([...changed.values()].flatMap((ids) => [...ids].map((id) => `${REQ_TAG_PREFIX}${tagSlug(id)}`)))];\n}\n\n/** Does any of these documents contain one of the tag spellings at all? Unreadable fails closed, as `../fleet.ts`'s gate does. */\nasync function mentions(paths: readonly string[], needles: readonly string[]): Promise<boolean> {\n for (const path of paths) {\n try {\n const text = (await readFile(path)).toString(\"latin1\");\n if (needles.some((needle) => text.includes(needle))) return true;\n } catch {\n return true;\n }\n }\n return false;\n}\n\nasync function fleetFlows(req: ChangedPromiseRequest, changed: ReadonlyMap<string, ReadonlySet<string>>): Promise<LivingFlow[]> {\n // The vocabulary ladder (`core/capabilities/findings.ts`): with nothing\n // declared no `#cap-` tag resolves, so no fleet flow can be said to claim anything.\n const declared = gradableCapabilityIds(req.vocabulary);\n if (changed.size === 0 || declared === null) return [];\n if (!(await mentions(await architectureProjectDocuments(req.docsDir), needlesFor(changed)))) return [];\n const read = useCasesIn(await req.architecture(), req.known);\n if (read.kind !== \"read\") return [];\n return read.views.map((view) => ({\n view,\n file: viewFile(view),\n scope: resolveCapabilityTags(view.tags, declared).flatMap((c) => (c.kind === \"resolved\" ? [c.id] : [])),\n altitude: \"capability\" as const,\n }));\n}\n\nasync function serviceFlows(req: ChangedPromiseRequest, changed: ReadonlyMap<string, ReadonlySet<string>>): Promise<LivingFlow[]> {\n const out: LivingFlow[] = [];\n for (const [service, ids] of changed) {\n // Sequential on purpose, for `../fleet.ts`'s gate's reason: nearly every\n // service answers from one readdir and a byte scan, and the rare one that\n // opens a workspace should not be raced by the ones that do not need one.\n const pair = req.services.find((doc) => doc.id === service);\n if (pair === undefined) continue;\n const paths = await pair.paths();\n if (!(await mentions(await architectureDocuments(paths.dir), needlesFor(new Map([[service, ids]]))))) continue;\n const model = await req.serviceModel(paths);\n if (model.mapUnreadable || model.doc.errors.length > 0) continue;\n const flows = await readServiceFlows({\n paths,\n model: model.doc,\n known: req.known,\n ...(model.shape === \"extending\" && model.project !== null\n ? { extending: { docsDir: req.docsDir, project: model.project } }\n : {}),\n });\n if (flows.kind !== \"read\") continue;\n for (const view of flows.views) {\n const file = relative(req.docsDir, join(paths.dir, view.sourcePath ?? \"model.likec4\")).split(/[\\\\/]/).join(\"/\");\n out.push({ view, file, scope: [service], altitude: \"service\" });\n }\n }\n return out;\n}\n"]}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * A feature's flows, read against the fleet map AS THIS FEATURE'S MERGE WOULD
3
+ * LEAVE IT.
4
+ *
5
+ * The staging and the merge preview that make that possible are no longer here:
6
+ * they moved to `core/c4/project/staged.ts` when the deployment slot became the
7
+ * second feature-local `.likec4` document, because a second copy of that
8
+ * machinery is the copy that drifts, and the two would disagree first about the
9
+ * merge preview — the one thing both axes' refusals rest on. That module's
10
+ * header carries the WHY of the post-merge corpus; this one keeps what is
11
+ * particular to use cases, which is the interpretation: which of the staged
12
+ * views are this feature's, and what they resolve against.
13
+ *
14
+ * FAIL CLOSED, and not silently. Every failure is the `unreadable` arm carrying
15
+ * LikeC4's own messages: a flow this cannot read is never a flow that grades
16
+ * clean, which is the asymmetry `../fleet.ts` states for the fleet-scope scan.
17
+ */
18
+ import {} from "../../c4/likec4.js";
19
+ import { stageMergedProject } from "../../c4/project/staged.js";
20
+ import { serviceResolver } from "../../c4/resolve/service.js";
21
+ import { isUseCase } from "../fleet.js";
22
+ import { featureFlows, USECASE_SUBDIR } from "./flows.js";
23
+ /**
24
+ * The flows this feature carries, parsed over the post-merge map — or the
25
+ * honest refusal to say.
26
+ *
27
+ * A feature with no `usecases/` directory is `read` with no views, at the cost
28
+ * of one walk over a directory that is not there. That is the axis's
29
+ * per-feature opt-in and the whole price a fleet that has not adopted it pays.
30
+ */
31
+ export async function readFeatureFlows(req) {
32
+ const flows = await featureFlows(req.featureDir);
33
+ if (flows.length === 0) {
34
+ return { kind: "read", views: [], model: { elements: [], relationships: [], known: req.known }, resolve: (id) => id };
35
+ }
36
+ // AFTER the early return, which is what makes the thunk worth its shape: the
37
+ // fleet read is paid only by a feature that actually brings a flow.
38
+ const models = req.models === undefined ? undefined : await req.models();
39
+ const staged = await stageMergedProject({
40
+ docsDir: req.docsDir,
41
+ featureDir: req.featureDir,
42
+ featureId: req.featureId,
43
+ documents: flows.map((flow) => ({ rel: `${USECASE_SUBDIR}/${flow.rel}`, path: flow.path })),
44
+ ...(req.load === undefined ? {} : { load: req.load }),
45
+ ...(models === undefined ? {} : { models }),
46
+ });
47
+ return interpret(staged, req.known);
48
+ }
49
+ /**
50
+ * The staged parse as the use-case axis reads it.
51
+ *
52
+ * THE FEATURE'S OWN FLOWS ONLY. A living use case is the fleet scan's to report,
53
+ * and repeating it here would file somebody else's finding against this
54
+ * feature's gate — the same scoping every other feature-side check keeps.
55
+ */
56
+ function interpret(staged, known) {
57
+ if (staged.kind === "unreadable")
58
+ return { kind: "unreadable", errors: staged.errors };
59
+ const { doc, real, mine } = staged;
60
+ // Through `isUseCase`, because `UseCaseScan.views` is documented as the
61
+ // reserved-tag views ONLY and this is the type's second producer. The
62
+ // resolvers below filter on the prefix anyway, so no answer changes today —
63
+ // but `flowsClaiming` and `servicesInFlowsClaiming` take a `UseCaseScan` and
64
+ // read `scan.views` straight, and the whole point of exporting one predicate
65
+ // was that a second spelling of the opt-in drifts.
66
+ const views = (doc.views ?? [])
67
+ .filter((view) => view.sourcePath !== undefined && mine.has(view.sourcePath))
68
+ .filter(isUseCase);
69
+ return {
70
+ kind: "read",
71
+ views: views.map((view) => ({ ...view, sourcePath: view.sourcePath === undefined ? view.sourcePath : real(view.sourcePath) })),
72
+ model: { elements: doc.elements, relationships: doc.relationships, known },
73
+ resolve: serviceResolver(doc.elements, known),
74
+ };
75
+ }
76
+ //# sourceMappingURL=overlay.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"overlay.js","sourceRoot":"","sources":["../../../../src/core/usecases/delta/overlay.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * A feature's flows, read against the fleet map AS THIS FEATURE'S MERGE WOULD\n * LEAVE IT.\n *\n * The staging and the merge preview that make that possible are no longer here:\n * they moved to `core/c4/project/staged.ts` when the deployment slot became the\n * second feature-local `.likec4` document, because a second copy of that\n * machinery is the copy that drifts, and the two would disagree first about the\n * merge preview — the one thing both axes' refusals rest on. That module's\n * header carries the WHY of the post-merge corpus; this one keeps what is\n * particular to use cases, which is the interpretation: which of the staged\n * views are this feature's, and what they resolve against.\n *\n * FAIL CLOSED, and not silently. Every failure is the `unreadable` arm carrying\n * LikeC4's own messages: a flow this cannot read is never a flow that grades\n * clean, which is the asymmetry `../fleet.ts` states for the fleet-scope scan.\n */\nimport { type LoadedDoc } from \"../../c4/likec4.js\";\nimport { stageMergedProject, type StagedProject } from \"../../c4/project/staged.js\";\nimport type { ExtendingModel } from \"../../c4/splice/contract.js\";\nimport { serviceResolver } from \"../../c4/resolve/service.js\";\nimport type { DocsDir, FeatureDir } from \"../../kernel/ids/dirs.js\";\nimport { isUseCase, type UseCaseScan } from \"../fleet.js\";\nimport { featureFlows, USECASE_SUBDIR } from \"./flows.js\";\n\n/** Everything the overlay needs, and nothing it would have to read twice. */\nexport interface FlowOverlayRequest {\n docsDir: DocsDir;\n featureDir: FeatureDir;\n /** The feature's id — the tag that selects the delta's own additions. */\n featureId: string;\n /**\n * The enumerated fleet, for the element→service resolver. It rides in for the\n * reason every other edge join carries it: without it a hop drawn into a\n * modelled container `payment.api` resolves to a service called \"api\" that\n * has never existed.\n */\n known: ReadonlySet<string>;\n /**\n * The caller's memoised LikeC4 read, when it has one. Only `delta.likec4` goes\n * through it, and only to compute the merge preview — but the caller\n * (`featureCoherence`) has already loaded that exact document, and loading one\n * spins a fresh Langium workspace, which `core/coherence/coherence.ts` calls\n * the dominant per-feature cost.\n *\n * A FUNCTION rather than the `FleetContext` itself, deliberately: this package\n * has no edge to `core/fleet-context.ts`, one memoised read does not justify\n * adding one, and the edge would push `core/usecases/` up a DAG level for\n * nothing. Absent, the load happens directly, which is right for a caller\n * running outside an invocation index.\n */\n load?: (path: string) => Promise<LoadedDoc>;\n /**\n * The fleet's extending models, for the merge preview — the SAME list\n * `loam archive` routes with. Without it the preview holds interior the\n * archive will put in `services/<…>/model.likec4`, so a hop naming\n * `<service-fqn>.<container>` resolves here and against nothing once the flow\n * is living: `usecase.flow-invalid` fails open, and it is the gate\n * `--approve` cannot override (verification 2026-09-04, review F8).\n *\n * A THUNK, and both halves of that matter. A function for the reason `load`\n * is one: the reader takes a `FleetContext` and this package has no edge to\n * it, so the caller that owns the fleet read supplies the answer. LAZY\n * because the early return above is the axis's per-feature opt-in — a feature\n * with no `usecases/` directory must not pay for a fleet enumeration and one\n * read per extending model to be told there is nothing to grade.\n */\n models?: () => Promise<readonly ExtendingModel[]>;\n}\n\n/**\n * The flows this feature carries, parsed over the post-merge map — or the\n * honest refusal to say.\n *\n * A feature with no `usecases/` directory is `read` with no views, at the cost\n * of one walk over a directory that is not there. That is the axis's\n * per-feature opt-in and the whole price a fleet that has not adopted it pays.\n */\nexport async function readFeatureFlows(req: FlowOverlayRequest): Promise<UseCaseScan> {\n const flows = await featureFlows(req.featureDir);\n if (flows.length === 0) {\n return { kind: \"read\", views: [], model: { elements: [], relationships: [], known: req.known }, resolve: (id) => id };\n }\n // AFTER the early return, which is what makes the thunk worth its shape: the\n // fleet read is paid only by a feature that actually brings a flow.\n const models = req.models === undefined ? undefined : await req.models();\n const staged = await stageMergedProject({\n docsDir: req.docsDir,\n featureDir: req.featureDir,\n featureId: req.featureId,\n documents: flows.map((flow) => ({ rel: `${USECASE_SUBDIR}/${flow.rel}`, path: flow.path })),\n ...(req.load === undefined ? {} : { load: req.load }),\n ...(models === undefined ? {} : { models }),\n });\n return interpret(staged, req.known);\n}\n\n/**\n * The staged parse as the use-case axis reads it.\n *\n * THE FEATURE'S OWN FLOWS ONLY. A living use case is the fleet scan's to report,\n * and repeating it here would file somebody else's finding against this\n * feature's gate — the same scoping every other feature-side check keeps.\n */\nfunction interpret(staged: StagedProject, known: ReadonlySet<string>): UseCaseScan {\n if (staged.kind === \"unreadable\") return { kind: \"unreadable\", errors: staged.errors };\n const { doc, real, mine } = staged;\n // Through `isUseCase`, because `UseCaseScan.views` is documented as the\n // reserved-tag views ONLY and this is the type's second producer. The\n // resolvers below filter on the prefix anyway, so no answer changes today —\n // but `flowsClaiming` and `servicesInFlowsClaiming` take a `UseCaseScan` and\n // read `scan.views` straight, and the whole point of exporting one predicate\n // was that a second spelling of the opt-in drifts.\n const views = (doc.views ?? [])\n .filter((view) => view.sourcePath !== undefined && mine.has(view.sourcePath))\n .filter(isUseCase);\n return {\n kind: \"read\",\n views: views.map((view) => ({ ...view, sourcePath: view.sourcePath === undefined ? view.sourcePath : real(view.sourcePath) })),\n model: { elements: doc.elements, relationships: doc.relationships, known },\n resolve: serviceResolver(doc.elements, known),\n };\n}\n"]}
@@ -0,0 +1,296 @@
1
+ /**
2
+ * The fleet's use cases, read once for whoever asks — and NOT read at all when
3
+ * the fleet demonstrably has none.
4
+ *
5
+ * `validate --all` grades use cases as part of a run that was already loading
6
+ * `architecture/` as a LikeC4 project, so it pays nothing extra. Every reader
7
+ * added in phase 4 is in a different position: `loam diff`, `loam delta`,
8
+ * `loam context` and `loam explore` did not load the fleet map as a project
9
+ * before, and `loam delta` in particular sits in `/loam-implement`'s inner loop
10
+ * — a Langium workspace spin-up there is felt on every iteration of somebody's
11
+ * day. So this module's whole job is to answer "which use cases does the fleet
12
+ * declare?" and, in the common case where the answer is none, to answer it
13
+ * without starting LikeC4 at all.
14
+ *
15
+ * THE CHEAP GATE IS A BYTE SCAN, and it is sound rather than heuristic. A view
16
+ * is a use case only if it carries a reserved tag — `#cap-<slug>`,
17
+ * `#req-<slug>` or `#suite-<name>`, `isUseCase` below is the whole test — and
18
+ * a view carries a tag only through a REFERENCE written in the document that
19
+ * declares the view. LikeC4's grammar spells every tag reference `HashId`: the
20
+ * `#` terminal, then the name. Measured at the 1.59.2 pin, the `#` is
21
+ * mandatory — a bare `suite-smoke` in a view body fails to resolve, and
22
+ * `tags #suite-smoke` fails to parse — but LikeC4's four hidden tokens may sit
23
+ * between the `#` and the name: `# suite-smoke`, a `#` ending one line with
24
+ * the name on the next, and a block comment in between all parse to the tag
25
+ * `suite-smoke`. So the scan finds each `#`, skips exactly those tokens
26
+ * (`referencesReservedTag`), and asks whether a reserved prefix starts there.
27
+ * A document set in which no file does declares no use case, however badly it
28
+ * parses, and `{ views: [] }` is the correct answer, not an evasion. A
29
+ * `tag cap-…` line in a `specification` block is a declaration, not a
30
+ * reference, and does not open the gate: a tag no view carries opts nothing
31
+ * in.
32
+ *
33
+ * THE `#` IS WHAT KEEPS PROSE OUT. The scan used to look for the bare
34
+ * substrings, so a view titled 'What the e2e-suite-a job exercises', or a
35
+ * comment naming `req-` in passing, opened it. At fleet scope that cost one
36
+ * project load, because a map that does not parse is `landscape.invalid`
37
+ * whether or not the gate opens; at service scope (`./service/flows.ts`) it
38
+ * turned an untagged hand-drawn sibling that did not parse into
39
+ * `usecase.flow-invalid` — an error, exit 1 — over a diagram that opted
40
+ * nothing in. A `#` followed by a reserved prefix still opens it wherever it
41
+ * is written, a comment or a description included: that over-scan is
42
+ * accepted, because it is spelled as the tag syntax, and the scan must never
43
+ * be narrower than the parser.
44
+ *
45
+ * The scan reads bytes rather than decoded text on purpose: it looks for
46
+ * ASCII, and `readFile(path, "utf8")` on a document that is not UTF-8 would
47
+ * substitute U+FFFD and could hide it. Decoded as latin1 instead, every byte is
48
+ * one character, and the bytes of a multi-byte sequence never read as ASCII.
49
+ *
50
+ * EVERY PREFIX, because the gate and the predicate answer one question and a
51
+ * gate narrower than the predicate is silence rather than a smaller answer. A
52
+ * fleet whose only flow is tagged `#req-` alone writes `cap-` nowhere, so a
53
+ * `cap-`-only scan returned `false` and none of the five readers ever loaded
54
+ * the project — the widening below would have fixed nothing without this one.
55
+ * The suite prefix joined for the same reason the day a `#suite-`-only view
56
+ * became a use case: both now read one list, `USE_CASE_TAG_PREFIXES`, so a
57
+ * fourth prefix cannot be added to one and not the other.
58
+ *
59
+ * The gate FAILS CLOSED. A document this module cannot open is treated as one
60
+ * that might mention the prefix, so the project load happens and reports the
61
+ * failure as a hole. The alternative — reading an EACCES as "no tag here" — is
62
+ * the fail-open shape docs/CODE-STYLE.md forbids at a validator, arriving in an
63
+ * optimisation.
64
+ */
65
+ import { readFile } from "node:fs/promises";
66
+ import { CAP_TAG_PREFIX, REQ_TAG_PREFIX } from "../capabilities/usecase-join.js";
67
+ import { architectureProjectDocuments, loadArchitecture } from "../c4/project/architecture.js";
68
+ import { errorText } from "../c4/likec4.js";
69
+ import { serviceResolver } from "../c4/resolve/service.js";
70
+ import { SUITE_TAG_PREFIX } from "./suites/suites.js";
71
+ /**
72
+ * Every reserved prefix that opts a view in — the one list both the byte gate
73
+ * and `isUseCase` read, so the two cannot disagree about which tags make a use
74
+ * case. `cap-` and `req-` are spelled by the capability join that resolves
75
+ * them; `suite-` by `./suites/suites.ts`, which groups by it and resolves
76
+ * nothing, because a suite name is checked by LikeC4's own undeclared-tag
77
+ * refusal rather than by a vocabulary.
78
+ */
79
+ const USE_CASE_TAG_PREFIXES = [CAP_TAG_PREFIX, REQ_TAG_PREFIX, SUITE_TAG_PREFIX];
80
+ /**
81
+ * Does any document in the set reference a reserved tag — a `#`, then only
82
+ * LikeC4's hidden tokens, then `cap-`, `req-` or `suite-`?
83
+ *
84
+ * Sequential and short-circuiting ON PURPOSE — the usual "no await in a loop"
85
+ * rule is about independent work that all has to finish, and this loop exists
86
+ * precisely so that a fleet whose first file declares a use case stops reading
87
+ * the other ninety-nine.
88
+ *
89
+ * What the scan lets through costs differently at its two callers, and the
90
+ * header above names both. A `#req-…` written in a comment opens it: at fleet
91
+ * scope that is one project load loam could have skipped, a slower right
92
+ * answer; at service scope it loads a sibling set that may not parse, and a
93
+ * broken one is then `usecase.flow-invalid` — an error, but over a document
94
+ * that spelled the tag syntax. Prose without the `#` opens neither. Missing a
95
+ * reference would cost a wrong answer at both: a use case nobody graded.
96
+ *
97
+ * Exported for the service-scope reader (`./service/flows.ts`), which asks the
98
+ * same question of the `.likec4` files beside one `model.likec4`: a sibling set
99
+ * that references no reserved tag declares no use case, so a hand-drawn
100
+ * `views.likec4` costs that service no LikeC4 workspace. One gate, two callers,
101
+ * because a second byte scan spelled in the service package would be free to
102
+ * disagree with this one about which prefixes opt a view in.
103
+ */
104
+ export async function mentionsTagPrefix(paths) {
105
+ for (const path of paths) {
106
+ try {
107
+ const bytes = await readFile(path);
108
+ if (referencesReservedTag(bytes.toString("latin1")))
109
+ return true;
110
+ }
111
+ catch {
112
+ // Unreadable is not "no tag": the project load below owns that failure and
113
+ // will report it as a hole naming the document. Answering `false` here
114
+ // would let an unopenable file grade the fleet as having no use cases.
115
+ return true;
116
+ }
117
+ }
118
+ return false;
119
+ }
120
+ /**
121
+ * Is a reserved prefix written as a tag reference anywhere in this text? Every
122
+ * `#` is tried, wherever it stands — in a view body, a comment, a string —
123
+ * because the scan may over-approximate the parser and never under-approximate
124
+ * it.
125
+ *
126
+ * A text with no `#`, or with no reserved prefix anywhere in it, cannot answer
127
+ * yes, so it is answered before the table below is built: that is nearly every
128
+ * document, and it costs those two native searches and no allocation.
129
+ *
130
+ * Exported for its own test (test/usecase-byte-gate.test.ts), which holds it to
131
+ * the walk the first version made from each `#` over crafted inputs, and holds
132
+ * its cost to one pass over inputs that walk took minutes on.
133
+ */
134
+ export function referencesReservedTag(text) {
135
+ const first = text.indexOf("#");
136
+ if (first === -1 || !USE_CASE_TAG_PREFIXES.some((prefix) => text.includes(prefix)))
137
+ return false;
138
+ const nameAt = hiddenRunEnds(text);
139
+ for (let hash = first; hash !== -1; hash = text.indexOf("#", hash + 1)) {
140
+ const name = nameAt[hash + 1];
141
+ if (USE_CASE_TAG_PREFIXES.some((prefix) => text.startsWith(prefix, name)))
142
+ return true;
143
+ }
144
+ return false;
145
+ }
146
+ /**
147
+ * For every position in `text`, where the next token LikeC4 would read starts
148
+ * from there: past whitespace, line breaks, `//` line comments and block
149
+ * comments — the four terminals the 1.59.2 grammar marks hidden (`WS`, `NL`,
150
+ * `LINE_COMMENT`, `BLOCK_COMMENT`), which its lexer drops between the `#` of a
151
+ * tag reference and the name. Index `text.length` is the end itself.
152
+ *
153
+ * ONE PASS, FROM THE END, so every answer is built from answers already known
154
+ * and the whole table costs one visit per character, however the `#`s and the
155
+ * comments interleave. The first version walked forward from each `#` instead,
156
+ * and a run of hidden tokens with `#`s inside it was re-walked once per `#`:
157
+ * `#/*` repeated took 17.6 s on 100 KB (each unclosed opener searched the rest
158
+ * of the file for a closer), and `#//` repeated on one line, or the same `#/*`
159
+ * run closed once at its end, were quadratic the same way. Remembering only
160
+ * where the closer search last failed would have fixed the first of those
161
+ * three and left the other two; nothing short of reusing every answer fixes
162
+ * the shape, and this scan runs over every document on every reader's path.
163
+ *
164
+ * A hand loop rather than one regular expression: a repeated group of
165
+ * alternatives that can each consume a comment backtracks exponentially on a
166
+ * long run of slashes. An UNTERMINATED block comment is not one LikeC4 can lex
167
+ * as a comment, so only the `/*` itself is stepped over and a name written
168
+ * after it still counts: that can open the gate more often, never less, and
169
+ * the document cannot parse anyway — the load the gate opens is what reports
170
+ * it. The closer is searched from two past the opener, so the `*` of an opener
171
+ * never doubles as the `*` of its closer, exactly as the lexer reads it.
172
+ */
173
+ function hiddenRunEnds(text) {
174
+ const end = new Int32Array(text.length + 1);
175
+ end[text.length] = text.length;
176
+ // The nearest line break at or after the position being read, and the
177
+ // nearest `*/` at or after the NEXT position and the one after that — an
178
+ // opener at `at` searches from `at + 2`, and the pass meets that position
179
+ // before it meets `at`. -1 is "none".
180
+ let lineBreak = text.length;
181
+ let closeFromNext = -1;
182
+ let closeFromAfterNext = -1;
183
+ for (let at = text.length - 1; at >= 0; at -= 1) {
184
+ const char = text[at];
185
+ const closeFromHere = char === "*" && text[at + 1] === "/" ? at : closeFromNext;
186
+ if (char === "\r" || char === "\n")
187
+ lineBreak = at;
188
+ if (char === " " || char === "\t" || char === "\r" || char === "\n") {
189
+ end[at] = end[at + 1];
190
+ }
191
+ else if (char === "/" && text[at + 1] === "/") {
192
+ // The comment runs to the line break and leaves it unread; the break is
193
+ // whitespace, so the run goes on from there. No break: the text ends.
194
+ end[at] = end[lineBreak];
195
+ }
196
+ else if (char === "/" && text[at + 1] === "*") {
197
+ end[at] = closeFromAfterNext === -1 ? end[at + 2] : end[closeFromAfterNext + 2];
198
+ }
199
+ else {
200
+ end[at] = at;
201
+ }
202
+ closeFromAfterNext = closeFromNext;
203
+ closeFromNext = closeFromHere;
204
+ }
205
+ return end;
206
+ }
207
+ /**
208
+ * Is this a use case at all? — the ONE answer, for `validate` and every reader
209
+ * alike.
210
+ *
211
+ * ANY RESERVED PREFIX OPTS A VIEW IN. A view carrying `#req-CHK-ONCE` and no
212
+ * `#cap-` tag is an author who asked to be graded and forgot half the claim; it
213
+ * earns `usecase.requirement-unresolved`'s `unscoped` arm rather than silence,
214
+ * and SCHEMA.md has said so since the tag shipped. A view carrying only
215
+ * `#suite-<name>` claims no capability and no requirement and is still a use
216
+ * case — the owner's call, recorded in SCHEMA.md: putting a journey in a suite
217
+ * is asking for it to be run, and a journey a test stand is provisioned from
218
+ * must be held to the model hop by hop like any other.
219
+ *
220
+ * It is exported because it was the asymmetry, not the rule, that was the
221
+ * defect. `validate --all` widened here and the readers did not, so a
222
+ * `#req-`-only flow was graded hop by hop by the gate and invisible to `loam
223
+ * diff`, `delta`, `status`, the packs and `list capabilities` — a fleet where
224
+ * the gate and the report disagree about what exists, which is worse than
225
+ * either answer alone. One predicate is what stops that recurring: a caller
226
+ * that spells `startsWith` itself is a second answer waiting to drift.
227
+ *
228
+ * The parameter is the smallest shape the test needs rather than `ParsedView`,
229
+ * so a caller holding a view-like row does not have to build one to ask. Every
230
+ * prefix test matches its reader's exactly, case included, so a view can never
231
+ * be opted in here and read as untagged in `resolveCapabilityTags` or
232
+ * `suiteNames`.
233
+ *
234
+ * NOT the same question as `flowsClaiming`'s. That one asks which flows claim
235
+ * capability X and matches the whole `cap-<slug>` tag; a `#req-`-only view
236
+ * claims none, and it is correct for it to stay out of that answer while
237
+ * counting as a use case here.
238
+ */
239
+ export function isUseCase(view) {
240
+ return view.tags.some((tag) => USE_CASE_TAG_PREFIXES.some((prefix) => tag.startsWith(prefix)));
241
+ }
242
+ /**
243
+ * The fleet's declared use cases, with the model they are drawn over.
244
+ *
245
+ * Reads only, throws nothing, and refuses nothing: every failure is the
246
+ * `unreadable` arm. Callers memoise this per invocation — nothing is cached
247
+ * here, because a module-level cache keyed on a docsDir would leak across the
248
+ * `chdir`-per-test processes AGENTS.md warns about and, in a long-running host,
249
+ * across invocations.
250
+ */
251
+ export async function readUseCases(req) {
252
+ const none = {
253
+ kind: "read",
254
+ views: [],
255
+ model: { elements: [], relationships: [], known: req.known },
256
+ resolve: (id) => id,
257
+ };
258
+ // EXACTLY the documents `loadArchitecture` will load two lines down, root
259
+ // `exclude` and all — `architectureProjectDocuments` is that one answer
260
+ // (`c4/project/architecture.ts`). The gate used to walk `architecture/` for
261
+ // itself and skip the exclude, which could only over-scan: the byte gate
262
+ // reading a document the loader then drops decides "there might be a use
263
+ // case here" and pays for a project load that finds none. Never a wrong
264
+ // answer, but two lists that disagree about what the project is, and the
265
+ // next reader to take the wider one for the project's would be wrong.
266
+ const documents = await architectureProjectDocuments(req.docsDir);
267
+ if (!(await mentionsTagPrefix(documents)))
268
+ return none;
269
+ return useCasesIn(await loadArchitecture(req.docsDir), req.known);
270
+ }
271
+ /**
272
+ * The use cases of an `architecture/` project somebody has ALREADY loaded —
273
+ * `readUseCases` minus its byte gate and its load.
274
+ *
275
+ * For a reader that needs the project anyway: the consumer index
276
+ * (`core/consumers/`) reads the project's edges and its hops off one load, and
277
+ * going through `readUseCases` there would parse the same documents a second
278
+ * time behind a gate whose whole purpose is to skip a load that has already
279
+ * happened. The answer is the same one: a project with no reserved-tag view
280
+ * yields `read` with no views, exactly what the gate returns without loading.
281
+ */
282
+ export function useCasesIn(doc, known) {
283
+ // loam's standing rule, at project altitude: errors mean no model. A use-case
284
+ // file with one unresolved element leaves the whole project unusable, and
285
+ // grading a flow against half a map is the wrong answer this refuses to give.
286
+ if (doc.errors.length > 0) {
287
+ return { kind: "unreadable", errors: doc.errors.map(errorText) };
288
+ }
289
+ return {
290
+ kind: "read",
291
+ views: (doc.views ?? []).filter(isUseCase),
292
+ model: { elements: doc.elements, relationships: doc.relationships, known },
293
+ resolve: serviceResolver(doc.elements, known),
294
+ };
295
+ }
296
+ //# sourceMappingURL=fleet.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fleet.js","sourceRoot":"","sources":["../../../src/core/usecases/fleet.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+DG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAEjF,OAAO,EAAE,4BAA4B,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAC/F,OAAO,EAAE,SAAS,EAAkB,MAAM,iBAAiB,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAE3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEtD;;;;;;;GAOG;AACH,MAAM,qBAAqB,GAAsB,CAAC,cAAc,EAAE,cAAc,EAAE,gBAAgB,CAAC,CAAC;AA+DpG;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,KAAwB;IAC9D,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,CAAC;YACnC,IAAI,qBAAqB,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;gBAAE,OAAO,IAAI,CAAC;QACnE,CAAC;QAAC,MAAM,CAAC;YACP,2EAA2E;YAC3E,uEAAuE;YACvE,uEAAuE;YACvE,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,qBAAqB,CAAC,IAAY;IAChD,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAChC,IAAI,KAAK,KAAK,CAAC,CAAC,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IACjG,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;IACnC,KAAK,IAAI,IAAI,GAAG,KAAK,EAAE,IAAI,KAAK,CAAC,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,IAAI,GAAG,CAAC,CAAC,EAAE,CAAC;QACvE,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,GAAG,CAAC,CAAE,CAAC;QAC/B,IAAI,qBAAqB,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;YAAE,OAAO,IAAI,CAAC;IACzF,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,SAAS,aAAa,CAAC,IAAY;IACjC,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC5C,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC;IAC/B,sEAAsE;IACtE,yEAAyE;IACzE,0EAA0E;IAC1E,sCAAsC;IACtC,IAAI,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC;IAC5B,IAAI,aAAa,GAAG,CAAC,CAAC,CAAC;IACvB,IAAI,kBAAkB,GAAG,CAAC,CAAC,CAAC;IAC5B,KAAK,IAAI,EAAE,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,EAAE,CAAC;QAChD,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC;QACtB,MAAM,aAAa,GAAG,IAAI,KAAK,GAAG,IAAI,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC;QAChF,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI;YAAE,SAAS,GAAG,EAAE,CAAC;QACnD,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;YACpE,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,EAAE,GAAG,CAAC,CAAE,CAAC;QACzB,CAAC;aAAM,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;YAChD,wEAAwE;YACxE,sEAAsE;YACtE,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,SAAS,CAAE,CAAC;QAC5B,CAAC;aAAM,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;YAChD,GAAG,CAAC,EAAE,CAAC,GAAG,kBAAkB,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,CAAE,CAAC,CAAC,CAAC,GAAG,CAAC,kBAAkB,GAAG,CAAC,CAAE,CAAC;QACpF,CAAC;aAAM,CAAC;YACN,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC;QACf,CAAC;QACD,kBAAkB,GAAG,aAAa,CAAC;QACnC,aAAa,GAAG,aAAa,CAAC;IAChC,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,MAAM,UAAU,SAAS,CAAC,IAAiC;IACzD,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AACjG,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,GAAmB;IACpD,MAAM,IAAI,GAAgB;QACxB,IAAI,EAAE,MAAM;QACZ,KAAK,EAAE,EAAE;QACT,KAAK,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,aAAa,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE;QAC5D,OAAO,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE;KACpB,CAAC;IACF,0EAA0E;IAC1E,wEAAwE;IACxE,4EAA4E;IAC5E,yEAAyE;IACzE,yEAAyE;IACzE,wEAAwE;IACxE,yEAAyE;IACzE,sEAAsE;IACtE,MAAM,SAAS,GAAG,MAAM,4BAA4B,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAClE,IAAI,CAAC,CAAC,MAAM,iBAAiB,CAAC,SAAS,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IAEvD,OAAO,UAAU,CAAC,MAAM,gBAAgB,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC;AACpE,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,UAAU,CAAC,GAAc,EAAE,KAA0B;IACnE,8EAA8E;IAC9E,0EAA0E;IAC1E,8EAA8E;IAC9E,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;IACnE,CAAC;IACD,OAAO;QACL,IAAI,EAAE,MAAM;QACZ,KAAK,EAAE,CAAC,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC;QAC1C,KAAK,EAAE,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,EAAE,aAAa,EAAE,GAAG,CAAC,aAAa,EAAE,KAAK,EAAE;QAC1E,OAAO,EAAE,eAAe,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC;KAC9C,CAAC;AACJ,CAAC","sourcesContent":["/**\n * The fleet's use cases, read once for whoever asks — and NOT read at all when\n * the fleet demonstrably has none.\n *\n * `validate --all` grades use cases as part of a run that was already loading\n * `architecture/` as a LikeC4 project, so it pays nothing extra. Every reader\n * added in phase 4 is in a different position: `loam diff`, `loam delta`,\n * `loam context` and `loam explore` did not load the fleet map as a project\n * before, and `loam delta` in particular sits in `/loam-implement`'s inner loop\n * — a Langium workspace spin-up there is felt on every iteration of somebody's\n * day. So this module's whole job is to answer \"which use cases does the fleet\n * declare?\" and, in the common case where the answer is none, to answer it\n * without starting LikeC4 at all.\n *\n * THE CHEAP GATE IS A BYTE SCAN, and it is sound rather than heuristic. A view\n * is a use case only if it carries a reserved tag — `#cap-<slug>`,\n * `#req-<slug>` or `#suite-<name>`, `isUseCase` below is the whole test — and\n * a view carries a tag only through a REFERENCE written in the document that\n * declares the view. LikeC4's grammar spells every tag reference `HashId`: the\n * `#` terminal, then the name. Measured at the 1.59.2 pin, the `#` is\n * mandatory — a bare `suite-smoke` in a view body fails to resolve, and\n * `tags #suite-smoke` fails to parse — but LikeC4's four hidden tokens may sit\n * between the `#` and the name: `# suite-smoke`, a `#` ending one line with\n * the name on the next, and a block comment in between all parse to the tag\n * `suite-smoke`. So the scan finds each `#`, skips exactly those tokens\n * (`referencesReservedTag`), and asks whether a reserved prefix starts there.\n * A document set in which no file does declares no use case, however badly it\n * parses, and `{ views: [] }` is the correct answer, not an evasion. A\n * `tag cap-…` line in a `specification` block is a declaration, not a\n * reference, and does not open the gate: a tag no view carries opts nothing\n * in.\n *\n * THE `#` IS WHAT KEEPS PROSE OUT. The scan used to look for the bare\n * substrings, so a view titled 'What the e2e-suite-a job exercises', or a\n * comment naming `req-` in passing, opened it. At fleet scope that cost one\n * project load, because a map that does not parse is `landscape.invalid`\n * whether or not the gate opens; at service scope (`./service/flows.ts`) it\n * turned an untagged hand-drawn sibling that did not parse into\n * `usecase.flow-invalid` — an error, exit 1 — over a diagram that opted\n * nothing in. A `#` followed by a reserved prefix still opens it wherever it\n * is written, a comment or a description included: that over-scan is\n * accepted, because it is spelled as the tag syntax, and the scan must never\n * be narrower than the parser.\n *\n * The scan reads bytes rather than decoded text on purpose: it looks for\n * ASCII, and `readFile(path, \"utf8\")` on a document that is not UTF-8 would\n * substitute U+FFFD and could hide it. Decoded as latin1 instead, every byte is\n * one character, and the bytes of a multi-byte sequence never read as ASCII.\n *\n * EVERY PREFIX, because the gate and the predicate answer one question and a\n * gate narrower than the predicate is silence rather than a smaller answer. A\n * fleet whose only flow is tagged `#req-` alone writes `cap-` nowhere, so a\n * `cap-`-only scan returned `false` and none of the five readers ever loaded\n * the project — the widening below would have fixed nothing without this one.\n * The suite prefix joined for the same reason the day a `#suite-`-only view\n * became a use case: both now read one list, `USE_CASE_TAG_PREFIXES`, so a\n * fourth prefix cannot be added to one and not the other.\n *\n * The gate FAILS CLOSED. A document this module cannot open is treated as one\n * that might mention the prefix, so the project load happens and reports the\n * failure as a hole. The alternative — reading an EACCES as \"no tag here\" — is\n * the fail-open shape docs/CODE-STYLE.md forbids at a validator, arriving in an\n * optimisation.\n */\nimport { readFile } from \"node:fs/promises\";\nimport type { StepScope } from \"../c4/resolve/steps.js\";\nimport { CAP_TAG_PREFIX, REQ_TAG_PREFIX } from \"../capabilities/usecase-join.js\";\nimport type { ParsedView } from \"../c4/parsed/dynamic-views.js\";\nimport { architectureProjectDocuments, loadArchitecture } from \"../c4/project/architecture.js\";\nimport { errorText, type LoadedDoc } from \"../c4/likec4.js\";\nimport { serviceResolver } from \"../c4/resolve/service.js\";\nimport type { DocsDir } from \"../kernel/ids/dirs.js\";\nimport { SUITE_TAG_PREFIX } from \"./suites/suites.js\";\n\n/**\n * Every reserved prefix that opts a view in — the one list both the byte gate\n * and `isUseCase` read, so the two cannot disagree about which tags make a use\n * case. `cap-` and `req-` are spelled by the capability join that resolves\n * them; `suite-` by `./suites/suites.ts`, which groups by it and resolves\n * nothing, because a suite name is checked by LikeC4's own undeclared-tag\n * refusal rather than by a vocabulary.\n */\nconst USE_CASE_TAG_PREFIXES: readonly string[] = [CAP_TAG_PREFIX, REQ_TAG_PREFIX, SUITE_TAG_PREFIX];\n\n/**\n * What the fleet's use cases are, or the honest refusal to say.\n *\n * Two variants rather than a record with an `unreadable` flag, because the\n * fields are not independent: a project that did not parse has no elements to\n * resolve against and no views to grade, and a caller handed\n * `{ views: [], unreadable: true }` is one `.length` check away from printing\n * \"no use cases touch this service\" about a fleet nobody could read. Tagged,\n * that state stops being constructible — every caller has to name the\n * `unreadable` arm to get at the views.\n *\n * `read` with an empty `views` is the ordinary answer for a fleet that draws no\n * use cases, and it is exactly what the cheap gate returns without loading\n * anything: the gate is an optimisation over a question with a known answer,\n * never a third verdict.\n */\nexport type UseCaseScan =\n | {\n kind: \"read\";\n /** The reserved-tag views ONLY — `isUseCase` below is the opt-in, and the only one. */\n views: readonly ParsedView[];\n /**\n * What a hop is attributed against, built ONCE per scan. It carries the\n * fleet set that `resolve` below was built from, which is what stops\n * \"which service is this element\" being answered one way by\n * `attributeStep`'s fallback tier and another by a caller's own join —\n * the same reason `validate`'s `StepGrading` holds both together.\n *\n * `known` is REQUIRED here while `StepScope` leaves it optional, and the\n * narrowing is load-bearing rather than tidy: every scan is built from a\n * `UseCaseRequest` that has one, so a consumer reading `model.known` was\n * writing an `undefined` branch that could not be reached and could not be\n * tested. A `StepScope` is still what `attributeStep` receives.\n */\n model: StepScope & { known: ReadonlySet<string> };\n /** One element→service resolver for the whole scan, built with the enumerated fleet. */\n resolve: (id: string) => string;\n }\n | {\n kind: \"unreadable\";\n /**\n * LikeC4's own messages, so a caller can say WHICH document broke —\n * spelled through `errorText` like every other diagnostic loam prints.\n * They used to travel raw, so the 1-based line was missing and one\n * dropped quote in the map put a 143 KB parser message into the\n * `useCaseScan.error` of every service's `loam context --json`.\n */\n errors: string[];\n };\n\nexport interface UseCaseRequest {\n docsDir: DocsDir;\n /**\n * The enumerated fleet. It rides into the resolver for the reason every other\n * edge join carries it: without it, a step drawn into a modelled container\n * `payment.api` resolves to a service called \"api\" that has never existed\n * (docs/DESIGN.md's serviceResolver-known row).\n */\n known: ReadonlySet<string>;\n}\n\n/**\n * Does any document in the set reference a reserved tag — a `#`, then only\n * LikeC4's hidden tokens, then `cap-`, `req-` or `suite-`?\n *\n * Sequential and short-circuiting ON PURPOSE — the usual \"no await in a loop\"\n * rule is about independent work that all has to finish, and this loop exists\n * precisely so that a fleet whose first file declares a use case stops reading\n * the other ninety-nine.\n *\n * What the scan lets through costs differently at its two callers, and the\n * header above names both. A `#req-…` written in a comment opens it: at fleet\n * scope that is one project load loam could have skipped, a slower right\n * answer; at service scope it loads a sibling set that may not parse, and a\n * broken one is then `usecase.flow-invalid` — an error, but over a document\n * that spelled the tag syntax. Prose without the `#` opens neither. Missing a\n * reference would cost a wrong answer at both: a use case nobody graded.\n *\n * Exported for the service-scope reader (`./service/flows.ts`), which asks the\n * same question of the `.likec4` files beside one `model.likec4`: a sibling set\n * that references no reserved tag declares no use case, so a hand-drawn\n * `views.likec4` costs that service no LikeC4 workspace. One gate, two callers,\n * because a second byte scan spelled in the service package would be free to\n * disagree with this one about which prefixes opt a view in.\n */\nexport async function mentionsTagPrefix(paths: readonly string[]): Promise<boolean> {\n for (const path of paths) {\n try {\n const bytes = await readFile(path);\n if (referencesReservedTag(bytes.toString(\"latin1\"))) return true;\n } catch {\n // Unreadable is not \"no tag\": the project load below owns that failure and\n // will report it as a hole naming the document. Answering `false` here\n // would let an unopenable file grade the fleet as having no use cases.\n return true;\n }\n }\n return false;\n}\n\n/**\n * Is a reserved prefix written as a tag reference anywhere in this text? Every\n * `#` is tried, wherever it stands — in a view body, a comment, a string —\n * because the scan may over-approximate the parser and never under-approximate\n * it.\n *\n * A text with no `#`, or with no reserved prefix anywhere in it, cannot answer\n * yes, so it is answered before the table below is built: that is nearly every\n * document, and it costs those two native searches and no allocation.\n *\n * Exported for its own test (test/usecase-byte-gate.test.ts), which holds it to\n * the walk the first version made from each `#` over crafted inputs, and holds\n * its cost to one pass over inputs that walk took minutes on.\n */\nexport function referencesReservedTag(text: string): boolean {\n const first = text.indexOf(\"#\");\n if (first === -1 || !USE_CASE_TAG_PREFIXES.some((prefix) => text.includes(prefix))) return false;\n const nameAt = hiddenRunEnds(text);\n for (let hash = first; hash !== -1; hash = text.indexOf(\"#\", hash + 1)) {\n const name = nameAt[hash + 1]!;\n if (USE_CASE_TAG_PREFIXES.some((prefix) => text.startsWith(prefix, name))) return true;\n }\n return false;\n}\n\n/**\n * For every position in `text`, where the next token LikeC4 would read starts\n * from there: past whitespace, line breaks, `//` line comments and block\n * comments — the four terminals the 1.59.2 grammar marks hidden (`WS`, `NL`,\n * `LINE_COMMENT`, `BLOCK_COMMENT`), which its lexer drops between the `#` of a\n * tag reference and the name. Index `text.length` is the end itself.\n *\n * ONE PASS, FROM THE END, so every answer is built from answers already known\n * and the whole table costs one visit per character, however the `#`s and the\n * comments interleave. The first version walked forward from each `#` instead,\n * and a run of hidden tokens with `#`s inside it was re-walked once per `#`:\n * `#/*` repeated took 17.6 s on 100 KB (each unclosed opener searched the rest\n * of the file for a closer), and `#//` repeated on one line, or the same `#/*`\n * run closed once at its end, were quadratic the same way. Remembering only\n * where the closer search last failed would have fixed the first of those\n * three and left the other two; nothing short of reusing every answer fixes\n * the shape, and this scan runs over every document on every reader's path.\n *\n * A hand loop rather than one regular expression: a repeated group of\n * alternatives that can each consume a comment backtracks exponentially on a\n * long run of slashes. An UNTERMINATED block comment is not one LikeC4 can lex\n * as a comment, so only the `/*` itself is stepped over and a name written\n * after it still counts: that can open the gate more often, never less, and\n * the document cannot parse anyway — the load the gate opens is what reports\n * it. The closer is searched from two past the opener, so the `*` of an opener\n * never doubles as the `*` of its closer, exactly as the lexer reads it.\n */\nfunction hiddenRunEnds(text: string): Int32Array {\n const end = new Int32Array(text.length + 1);\n end[text.length] = text.length;\n // The nearest line break at or after the position being read, and the\n // nearest `*/` at or after the NEXT position and the one after that — an\n // opener at `at` searches from `at + 2`, and the pass meets that position\n // before it meets `at`. -1 is \"none\".\n let lineBreak = text.length;\n let closeFromNext = -1;\n let closeFromAfterNext = -1;\n for (let at = text.length - 1; at >= 0; at -= 1) {\n const char = text[at];\n const closeFromHere = char === \"*\" && text[at + 1] === \"/\" ? at : closeFromNext;\n if (char === \"\\r\" || char === \"\\n\") lineBreak = at;\n if (char === \" \" || char === \"\\t\" || char === \"\\r\" || char === \"\\n\") {\n end[at] = end[at + 1]!;\n } else if (char === \"/\" && text[at + 1] === \"/\") {\n // The comment runs to the line break and leaves it unread; the break is\n // whitespace, so the run goes on from there. No break: the text ends.\n end[at] = end[lineBreak]!;\n } else if (char === \"/\" && text[at + 1] === \"*\") {\n end[at] = closeFromAfterNext === -1 ? end[at + 2]! : end[closeFromAfterNext + 2]!;\n } else {\n end[at] = at;\n }\n closeFromAfterNext = closeFromNext;\n closeFromNext = closeFromHere;\n }\n return end;\n}\n\n/**\n * Is this a use case at all? — the ONE answer, for `validate` and every reader\n * alike.\n *\n * ANY RESERVED PREFIX OPTS A VIEW IN. A view carrying `#req-CHK-ONCE` and no\n * `#cap-` tag is an author who asked to be graded and forgot half the claim; it\n * earns `usecase.requirement-unresolved`'s `unscoped` arm rather than silence,\n * and SCHEMA.md has said so since the tag shipped. A view carrying only\n * `#suite-<name>` claims no capability and no requirement and is still a use\n * case — the owner's call, recorded in SCHEMA.md: putting a journey in a suite\n * is asking for it to be run, and a journey a test stand is provisioned from\n * must be held to the model hop by hop like any other.\n *\n * It is exported because it was the asymmetry, not the rule, that was the\n * defect. `validate --all` widened here and the readers did not, so a\n * `#req-`-only flow was graded hop by hop by the gate and invisible to `loam\n * diff`, `delta`, `status`, the packs and `list capabilities` — a fleet where\n * the gate and the report disagree about what exists, which is worse than\n * either answer alone. One predicate is what stops that recurring: a caller\n * that spells `startsWith` itself is a second answer waiting to drift.\n *\n * The parameter is the smallest shape the test needs rather than `ParsedView`,\n * so a caller holding a view-like row does not have to build one to ask. Every\n * prefix test matches its reader's exactly, case included, so a view can never\n * be opted in here and read as untagged in `resolveCapabilityTags` or\n * `suiteNames`.\n *\n * NOT the same question as `flowsClaiming`'s. That one asks which flows claim\n * capability X and matches the whole `cap-<slug>` tag; a `#req-`-only view\n * claims none, and it is correct for it to stay out of that answer while\n * counting as a use case here.\n */\nexport function isUseCase(view: { tags: readonly string[] }): boolean {\n return view.tags.some((tag) => USE_CASE_TAG_PREFIXES.some((prefix) => tag.startsWith(prefix)));\n}\n\n/**\n * The fleet's declared use cases, with the model they are drawn over.\n *\n * Reads only, throws nothing, and refuses nothing: every failure is the\n * `unreadable` arm. Callers memoise this per invocation — nothing is cached\n * here, because a module-level cache keyed on a docsDir would leak across the\n * `chdir`-per-test processes AGENTS.md warns about and, in a long-running host,\n * across invocations.\n */\nexport async function readUseCases(req: UseCaseRequest): Promise<UseCaseScan> {\n const none: UseCaseScan = {\n kind: \"read\",\n views: [],\n model: { elements: [], relationships: [], known: req.known },\n resolve: (id) => id,\n };\n // EXACTLY the documents `loadArchitecture` will load two lines down, root\n // `exclude` and all — `architectureProjectDocuments` is that one answer\n // (`c4/project/architecture.ts`). The gate used to walk `architecture/` for\n // itself and skip the exclude, which could only over-scan: the byte gate\n // reading a document the loader then drops decides \"there might be a use\n // case here\" and pays for a project load that finds none. Never a wrong\n // answer, but two lists that disagree about what the project is, and the\n // next reader to take the wider one for the project's would be wrong.\n const documents = await architectureProjectDocuments(req.docsDir);\n if (!(await mentionsTagPrefix(documents))) return none;\n\n return useCasesIn(await loadArchitecture(req.docsDir), req.known);\n}\n\n/**\n * The use cases of an `architecture/` project somebody has ALREADY loaded —\n * `readUseCases` minus its byte gate and its load.\n *\n * For a reader that needs the project anyway: the consumer index\n * (`core/consumers/`) reads the project's edges and its hops off one load, and\n * going through `readUseCases` there would parse the same documents a second\n * time behind a gate whose whole purpose is to skip a load that has already\n * happened. The answer is the same one: a project with no reserved-tag view\n * yields `read` with no views, exactly what the gate returns without loading.\n */\nexport function useCasesIn(doc: LoadedDoc, known: ReadonlySet<string>): UseCaseScan {\n // loam's standing rule, at project altitude: errors mean no model. A use-case\n // file with one unresolved element leaves the whole project unusable, and\n // grading a flow against half a map is the wrong answer this refuses to give.\n if (doc.errors.length > 0) {\n return { kind: \"unreadable\", errors: doc.errors.map(errorText) };\n }\n return {\n kind: \"read\",\n views: (doc.views ?? []).filter(isUseCase),\n model: { elements: doc.elements, relationships: doc.relationships, known },\n resolve: serviceResolver(doc.elements, known),\n };\n}\n"]}
@@ -0,0 +1,93 @@
1
+ /**
2
+ * `usecase.capability-unresolved` — the `#cap-` tag that names no declared
3
+ * capability, or more than one.
4
+ *
5
+ * The join itself lives in `core/capabilities/usecase-join.ts` and none of it is
6
+ * repeated here: this module owns the grade and the sentence, nothing else. That
7
+ * split is why the tag can answer "many" at all — the slug is not injective, so
8
+ * `payments/refunds` and `payments-refunds` both flatten to
9
+ * `payments-refunds` — and why the close candidates a message offers are real
10
+ * declared ids rather than loam's flattened spelling of them.
11
+ *
12
+ * ERROR, the same grade `capability.unknown` carries on a `Capability:` line and
13
+ * for its reason: an invented capability reads exactly like a real one. Here it
14
+ * reads that way at flow altitude — the tag is what files a whole business
15
+ * sequence under an owner, so a claim that resolves to nothing produces a use
16
+ * case nobody can find and a capability nobody can see is realized.
17
+ *
18
+ * SUPPRESSED ENTIRELY when the vocabulary is absent or unreadable: the caller
19
+ * resolves no claims at all in that case, so this answers with nothing. The
20
+ * claims are RESOLVED BY THE CALLER rather than here because the `#req-` grade
21
+ * beside this one is scoped by the very same verdicts, and two resolutions of
22
+ * one view's tags are two chances to disagree about which capability a flow is
23
+ * about. The ladder that produces the suppressing `null` is
24
+ * `gradableCapabilityIds` in `core/capabilities/findings.ts` — one function, called by every site that needs the graded id list, this module's
25
+ * callers in `commands/validate/fleet/map/usecases.ts` and `./feature.ts` included. The FILE is this axis's opt-in, so a
26
+ * fleet with no `architecture/capabilities.yaml` produces no capability finding
27
+ * at all, and an unreadable one is `capability.invalid` alone rather than one
28
+ * unresolved tag per use case in the fleet, which is a cascade and not a
29
+ * diagnosis. That rule is not re-decided here: a second reading of
30
+ * `CapabilityVocabulary` anywhere in this package is the copy that goes stale
31
+ * the day a fourth un-gradable state is added, so call the function.
32
+ */
33
+ import { CAP_TAG_PREFIX, tagSlug, } from "../../capabilities/usecase-join.js";
34
+ /** A capability id as an author must write it in a tag: `identity/tokens (#cap-identity-tokens)`. */
35
+ function idAndTag(id) {
36
+ return `${id} (#${CAP_TAG_PREFIX}${tagSlug(id)})`;
37
+ }
38
+ /**
39
+ * A tag nothing declares, with the close names spelled as TAGS as well as ids.
40
+ *
41
+ * Both spellings, because either alone sends the author somewhere wrong: the id
42
+ * is what `capabilities.yaml` holds and the tag is what the view must carry, and
43
+ * an author handed only `identity/tokens` writes `#cap-identity/tokens`, which
44
+ * LikeC4 refuses to parse. The flattening rule is stated in the same breath so
45
+ * the reader can derive the next one without being told again.
46
+ */
47
+ function noneMessage(where, claim) {
48
+ const hint = claim.close.length > 0
49
+ ? `Did you mean: ${claim.close.map(idAndTag).join(", ")}?`
50
+ : "Declare it there (`capabilities: {<id>: {description, owner}}`), or fix the tag.";
51
+ return (`${where} is tagged #${claim.tag}, and no capability declared in ` +
52
+ `architecture/capabilities.yaml flattens to '${claim.slug}'. ${hint} ` +
53
+ "A tag spells the id with every character outside `[A-Za-z0-9_-]` flattened to `-`, because that is all a LikeC4 tag name accepts.");
54
+ }
55
+ /**
56
+ * A tag two or more declared ids answer to. Every colliding id is named — a
57
+ * message that stopped at the first would be reporting the ambiguity while
58
+ * hiding half of what makes it one.
59
+ */
60
+ function manyMessage(where, claim) {
61
+ return (`${where} is tagged #${claim.tag}, and ${claim.ids.length} declared capabilities flatten to ` +
62
+ `'${claim.slug}' (${claim.ids.join(", ")}) — nothing in the tag can say which one this use case realizes. ` +
63
+ "Rename one of them in architecture/capabilities.yaml: a guessed capability files every hop of the flow, " +
64
+ "and every rollup built over it, under an owner who never claimed it — and the wrong answer looks exactly " +
65
+ "like the right one.");
66
+ }
67
+ /**
68
+ * One finding per `#cap-` tag that does not resolve — never one per view.
69
+ *
70
+ * A view may legitimately carry two capability tags (a checkout flow that also
71
+ * issues the identity token realizes both), and `resolveCapabilityTags` answers
72
+ * each on its own terms for that reason. Collapsing them here would either
73
+ * swallow a broken tag beside a working one or lose the capability the view
74
+ * genuinely does realize; one tag, one verdict, one finding keeps both facts.
75
+ */
76
+ export function capabilityTagFindings(view, claims, place) {
77
+ const findings = [];
78
+ for (const claim of claims) {
79
+ if (claim.kind === "resolved")
80
+ continue;
81
+ findings.push({
82
+ severity: "error",
83
+ code: "usecase.capability-unresolved",
84
+ // The VIEW, not the tag: a subject is what a reader goes and opens, and
85
+ // `subjectsWith` counts one broken use case once however many of its tags
86
+ // are wrong.
87
+ subject: view.id,
88
+ message: claim.kind === "none" ? noneMessage(place(view), claim) : manyMessage(place(view), claim),
89
+ });
90
+ }
91
+ return findings;
92
+ }
93
+ //# sourceMappingURL=capability-tag.js.map