@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,181 @@
1
+ /**
2
+ * The feature's own delta documents, read once: the requirement axes, the join
3
+ * from a scenario claim back to the words it was minted from, and whether the
4
+ * architecture and contract documents could be read at all.
5
+ *
6
+ * Everything here reads; nothing grades. The readability answers travel beside
7
+ * the counts for `core/projection/api.ts`'s reason, one axis over: a delta that
8
+ * does not parse yields an EMPTY change list, which is the same answer as a
9
+ * delta that genuinely changes nothing — and a packet is consumed as "what is
10
+ * left to do", where an empty answer over a YAML error reads as "nothing to do".
11
+ */
12
+ import { existsSync } from "node:fs";
13
+ import { errorText } from "../c4/likec4.js";
14
+ import { repoPath } from "../envelope/json.js";
15
+ import { scenarioBodyHash } from "../gherkin/digest.js";
16
+ import { requirementsMissingScenarios } from "../document/scenarios.js";
17
+ import { apiChanges } from "../projection/api.js";
18
+ import { eventChanges } from "../projection/events.js";
19
+ import { featurePaths, featureSpecPaths, SPEC_AXES } from "../repo/paths.js";
20
+ import { claimId, DIGEST_LENGTH, ID_LENGTH } from "../verify/claims/identity.js";
21
+ import { describedUnitId, doneCheck } from "./unit.js";
22
+ /**
23
+ * Both spec axes of every service the feature carries a delta for, in the order
24
+ * `core/verify/checklist.ts` walks them — service-major, `spec.md` before
25
+ * `arch.spec.md`. The order is load-bearing rather than tidy: it is what makes
26
+ * the recomputed claim ids below land on the same occurrence counters the
27
+ * checklist minted.
28
+ */
29
+ export async function readDeltaAxes(docsDir, featureDir, services, context) {
30
+ const out = [];
31
+ for (const service of services) {
32
+ const paths = featureSpecPaths(featureDir, service);
33
+ for (const axis of SPEC_AXES) {
34
+ const file = paths[axis.key];
35
+ if (!existsSync(file))
36
+ continue;
37
+ out.push({ service, axis, path: repoPath(docsDir, file), requirements: await context.readRequirements(file) });
38
+ }
39
+ }
40
+ return out;
41
+ }
42
+ /**
43
+ * Every scenario claim's source, keyed by the claim id it will carry.
44
+ *
45
+ * THE ID IS THE JOIN, and that is stronger than matching on the digest alone.
46
+ * A scenario claim's id is `claimId(featureId, "scenario.tested", tuple, seen)`
47
+ * over a tuple that already contains the requirement's identity, the scenario
48
+ * name and a prefix of the body hash — so recomputing it from the same walk, in
49
+ * the same order, with one shared occurrence map, reproduces the checklist's own
50
+ * answer rather than approximating it. Two identically-worded scenarios under
51
+ * one requirement share a digest and are still two questions: `claimId`'s `seen`
52
+ * counter numbers them in DOCUMENT ORDER, and this walk visits them in document
53
+ * order too, so the nth scenario pairs with the nth claim exactly.
54
+ *
55
+ * The digest is carried alongside and checked by the caller before a source is
56
+ * attached. That is the belt: if this walk and the checklist's ever disagreed
57
+ * about what a scenario says, the packet must show the unit with NO source
58
+ * rather than with somebody else's Given/When/Then.
59
+ *
60
+ * Only ADDED and MODIFIED requirements, exactly as the checklist does: a BASE
61
+ * requirement is the living state quoted inside the delta, and a REMOVED one is
62
+ * being retired. Neither is work anybody has to have done.
63
+ */
64
+ export function scenarioSources(featureId, axes) {
65
+ const out = new Map();
66
+ const seen = new Map();
67
+ for (const { service, axis, path, requirements } of axes) {
68
+ const arch = axis.key === "archSpec";
69
+ for (const requirement of requirements) {
70
+ if (requirement.kind === "BASE" || requirement.kind === "REMOVED")
71
+ continue;
72
+ const identity = requirement.id ?? requirement.name;
73
+ for (const scenario of requirement.scenarios) {
74
+ const body = scenarioBodyHash(service, scenario.lines, arch ? "arch" : "business");
75
+ // The tuple is `core/verify/checklist.ts`'s, part for part — the arch
76
+ // axis carries `arch.spec.md` as its second element, which is what keeps
77
+ // two identically-worded scenarios on the two axes two questions.
78
+ const parts = arch
79
+ ? [service, "arch.spec.md", identity, scenario.name, body.slice(0, ID_LENGTH)]
80
+ : [service, identity, scenario.name, body.slice(0, ID_LENGTH)];
81
+ const id = claimId(featureId, "scenario.tested", parts, seen);
82
+ out.set(id, {
83
+ digest: body.slice(0, DIGEST_LENGTH),
84
+ source: {
85
+ path,
86
+ ...(scenario.line === undefined ? {} : { line: scenario.line }),
87
+ requirement: requirement.name,
88
+ ...(requirement.id === undefined ? {} : { requirementId: requirement.id }),
89
+ scenario: scenario.name,
90
+ lines: scenario.lines,
91
+ },
92
+ });
93
+ }
94
+ }
95
+ }
96
+ return out;
97
+ }
98
+ /**
99
+ * The first BDD act, as units: a requirement nobody has written a scenario for.
100
+ *
101
+ * `requirementsMissingScenarios` is the coverage rule every other surface
102
+ * applies — REMOVED requirements are exempt there and stay exempt here, content
103
+ * on its way out owes no acceptance criteria — so a packet can never disagree
104
+ * with `loam validate` about which requirements are bare.
105
+ */
106
+ export function describeUnits(featureId, axes) {
107
+ const out = [];
108
+ for (const { service, axis, path, requirements } of axes) {
109
+ for (const requirement of requirementsMissingScenarios(requirements)) {
110
+ const id = describedUnitId(featureId, service, axis.file, requirement.id ?? requirement.name);
111
+ out.push({
112
+ id,
113
+ kind: "requirement.described",
114
+ subject: service,
115
+ at: "describe",
116
+ claim: `requirement '${requirement.name}' (${service}, ${axis.file}) has no scenarios` +
117
+ " — write the Given/When/Then first",
118
+ dependsOn: [],
119
+ source: {
120
+ path,
121
+ ...(requirement.line === undefined ? {} : { line: requirement.line }),
122
+ requirement: requirement.name,
123
+ ...(requirement.id === undefined ? {} : { requirementId: requirement.id }),
124
+ },
125
+ done: { check: doneCheck({ kind: "requirement.described" }) },
126
+ });
127
+ }
128
+ }
129
+ return out;
130
+ }
131
+ /**
132
+ * The two contract axes and the architecture delta, read for their COUNTS and
133
+ * for whether they could be read.
134
+ *
135
+ * The same readers `loam delta` projects through (`apiChanges`/`eventChanges`),
136
+ * so a packet can never report an operation the brief does not. The
137
+ * architecture half is read through the invocation's context, which means the
138
+ * parse is shared with the checklist derivation that has already loaded the same
139
+ * document — one LikeC4 workspace per invocation rather than two.
140
+ */
141
+ export async function readContracts(docsDir, featureDir, services, context) {
142
+ let operations = 0;
143
+ let messages = 0;
144
+ const broken = [];
145
+ for (const service of services) {
146
+ const paths = featureSpecPaths(featureDir, service);
147
+ const api = await apiChanges(paths.openapi);
148
+ const events = await eventChanges(paths.asyncapi);
149
+ if (api.unreadable || events.unreadable)
150
+ broken.push(service);
151
+ operations += api.changes.filter((change) => !change.remove).length;
152
+ messages += events.changes.filter((change) => !change.remove).length;
153
+ }
154
+ const delta = featurePaths(featureDir).delta;
155
+ let architecture;
156
+ if (existsSync(delta)) {
157
+ const loaded = await context.loadLikeC4(delta);
158
+ // The first error only: the packet says WHICH document could not be read and
159
+ // why, and a reader who needs the rest runs `loam validate --feature`, whose
160
+ // job the whole list is.
161
+ const first = loaded.errors[0];
162
+ if (first !== undefined)
163
+ architecture = errorText(first);
164
+ }
165
+ return {
166
+ operations,
167
+ messages,
168
+ unreadable: {
169
+ ...(architecture === undefined ? {} : { architecture }),
170
+ ...(broken.length === 0 ? {} : { contracts: broken }),
171
+ },
172
+ };
173
+ }
174
+ /** How many requirements and scenarios the delta axes hold, whatever their kind. */
175
+ export function axisSize(axes) {
176
+ return {
177
+ requirements: axes.reduce((n, a) => n + a.requirements.length, 0),
178
+ scenarios: axes.reduce((n, a) => n + a.requirements.reduce((m, r) => m + r.scenarios.length, 0), 0),
179
+ };
180
+ }
181
+ //# sourceMappingURL=sources.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sources.js","sourceRoot":"","sources":["../../../src/core/tasks/sources.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The feature's own delta documents, read once: the requirement axes, the join\n * from a scenario claim back to the words it was minted from, and whether the\n * architecture and contract documents could be read at all.\n *\n * Everything here reads; nothing grades. The readability answers travel beside\n * the counts for `core/projection/api.ts`'s reason, one axis over: a delta that\n * does not parse yields an EMPTY change list, which is the same answer as a\n * delta that genuinely changes nothing — and a packet is consumed as \"what is\n * left to do\", where an empty answer over a YAML error reads as \"nothing to do\".\n */\nimport { existsSync } from \"node:fs\";\nimport { errorText } from \"../c4/likec4.js\";\nimport { repoPath } from \"../envelope/json.js\";\nimport type { FleetContext } from \"../fleet-context.js\";\nimport { scenarioBodyHash } from \"../gherkin/digest.js\";\nimport type { DocsDir, FeatureDir } from \"../kernel/ids/dirs.js\";\nimport type { PathableService } from \"../kernel/ids/service.js\";\nimport { requirementsMissingScenarios } from \"../document/scenarios.js\";\nimport type { Requirement } from \"../document/spec.js\";\nimport { apiChanges } from \"../projection/api.js\";\nimport { eventChanges } from \"../projection/events.js\";\nimport { featurePaths, featureSpecPaths, SPEC_AXES, type SpecAxis } from \"../repo/paths.js\";\nimport { claimId, DIGEST_LENGTH, ID_LENGTH } from \"../verify/claims/identity.js\";\nimport { describedUnitId, doneCheck, type ScenarioSource, type TaskUnit } from \"./unit.js\";\n\n/** One spec axis of one service's delta, parsed. */\nexport interface DeltaAxis {\n service: string;\n axis: SpecAxis;\n /** Repo-relative, for the payload and for a human opening the file. */\n path: string;\n requirements: Requirement[];\n}\n\n/**\n * Both spec axes of every service the feature carries a delta for, in the order\n * `core/verify/checklist.ts` walks them — service-major, `spec.md` before\n * `arch.spec.md`. The order is load-bearing rather than tidy: it is what makes\n * the recomputed claim ids below land on the same occurrence counters the\n * checklist minted.\n */\nexport async function readDeltaAxes(\n docsDir: DocsDir,\n featureDir: FeatureDir,\n services: readonly PathableService[],\n context: FleetContext,\n): Promise<DeltaAxis[]> {\n const out: DeltaAxis[] = [];\n for (const service of services) {\n const paths = featureSpecPaths(featureDir, service);\n for (const axis of SPEC_AXES) {\n const file = paths[axis.key];\n if (!existsSync(file)) continue;\n out.push({ service, axis, path: repoPath(docsDir, file), requirements: await context.readRequirements(file) });\n }\n }\n return out;\n}\n\n/**\n * A scenario's words, with the digest the claim that owns them must carry. The\n * digest travels beside the source rather than inside it because it is not part\n * of the source — it is the proof that this walk and the checklist's are talking\n * about the same scenario.\n */\nexport interface MintedSource {\n digest: string;\n source: ScenarioSource;\n}\n\n/**\n * Every scenario claim's source, keyed by the claim id it will carry.\n *\n * THE ID IS THE JOIN, and that is stronger than matching on the digest alone.\n * A scenario claim's id is `claimId(featureId, \"scenario.tested\", tuple, seen)`\n * over a tuple that already contains the requirement's identity, the scenario\n * name and a prefix of the body hash — so recomputing it from the same walk, in\n * the same order, with one shared occurrence map, reproduces the checklist's own\n * answer rather than approximating it. Two identically-worded scenarios under\n * one requirement share a digest and are still two questions: `claimId`'s `seen`\n * counter numbers them in DOCUMENT ORDER, and this walk visits them in document\n * order too, so the nth scenario pairs with the nth claim exactly.\n *\n * The digest is carried alongside and checked by the caller before a source is\n * attached. That is the belt: if this walk and the checklist's ever disagreed\n * about what a scenario says, the packet must show the unit with NO source\n * rather than with somebody else's Given/When/Then.\n *\n * Only ADDED and MODIFIED requirements, exactly as the checklist does: a BASE\n * requirement is the living state quoted inside the delta, and a REMOVED one is\n * being retired. Neither is work anybody has to have done.\n */\nexport function scenarioSources(featureId: string, axes: readonly DeltaAxis[]): Map<string, MintedSource> {\n const out = new Map<string, MintedSource>();\n const seen = new Map<string, number>();\n for (const { service, axis, path, requirements } of axes) {\n const arch = axis.key === \"archSpec\";\n for (const requirement of requirements) {\n if (requirement.kind === \"BASE\" || requirement.kind === \"REMOVED\") continue;\n const identity = requirement.id ?? requirement.name;\n for (const scenario of requirement.scenarios) {\n const body = scenarioBodyHash(service, scenario.lines, arch ? \"arch\" : \"business\");\n // The tuple is `core/verify/checklist.ts`'s, part for part — the arch\n // axis carries `arch.spec.md` as its second element, which is what keeps\n // two identically-worded scenarios on the two axes two questions.\n const parts = arch\n ? [service, \"arch.spec.md\", identity, scenario.name, body.slice(0, ID_LENGTH)]\n : [service, identity, scenario.name, body.slice(0, ID_LENGTH)];\n const id = claimId(featureId, \"scenario.tested\", parts, seen);\n out.set(id, {\n digest: body.slice(0, DIGEST_LENGTH),\n source: {\n path,\n ...(scenario.line === undefined ? {} : { line: scenario.line }),\n requirement: requirement.name,\n ...(requirement.id === undefined ? {} : { requirementId: requirement.id }),\n scenario: scenario.name,\n lines: scenario.lines,\n },\n });\n }\n }\n }\n return out;\n}\n\n/**\n * The first BDD act, as units: a requirement nobody has written a scenario for.\n *\n * `requirementsMissingScenarios` is the coverage rule every other surface\n * applies — REMOVED requirements are exempt there and stay exempt here, content\n * on its way out owes no acceptance criteria — so a packet can never disagree\n * with `loam validate` about which requirements are bare.\n */\nexport function describeUnits(featureId: string, axes: readonly DeltaAxis[]): TaskUnit[] {\n const out: TaskUnit[] = [];\n for (const { service, axis, path, requirements } of axes) {\n for (const requirement of requirementsMissingScenarios(requirements)) {\n const id = describedUnitId(featureId, service, axis.file, requirement.id ?? requirement.name);\n out.push({\n id,\n kind: \"requirement.described\",\n subject: service,\n at: \"describe\",\n claim:\n `requirement '${requirement.name}' (${service}, ${axis.file}) has no scenarios` +\n \" — write the Given/When/Then first\",\n dependsOn: [],\n source: {\n path,\n ...(requirement.line === undefined ? {} : { line: requirement.line }),\n requirement: requirement.name,\n ...(requirement.id === undefined ? {} : { requirementId: requirement.id }),\n },\n done: { check: doneCheck({ kind: \"requirement.described\" }) },\n });\n }\n }\n return out;\n}\n\n/** What could not be read. Keys are omitted when clean, so `{}` never means \"checked and fine\". */\nexport interface Unreadable {\n architecture?: string;\n contracts?: string[];\n}\n\n/** The delta's size, as documents rather than as open work — see `WorkPacket.size`. */\nexport interface DeltaSize {\n requirements: number;\n scenarios: number;\n operations: number;\n messages: number;\n calls: number;\n}\n\n/**\n * The two contract axes and the architecture delta, read for their COUNTS and\n * for whether they could be read.\n *\n * The same readers `loam delta` projects through (`apiChanges`/`eventChanges`),\n * so a packet can never report an operation the brief does not. The\n * architecture half is read through the invocation's context, which means the\n * parse is shared with the checklist derivation that has already loaded the same\n * document — one LikeC4 workspace per invocation rather than two.\n */\nexport async function readContracts(\n docsDir: DocsDir,\n featureDir: FeatureDir,\n services: readonly PathableService[],\n context: FleetContext,\n): Promise<{ operations: number; messages: number; unreadable: Unreadable }> {\n let operations = 0;\n let messages = 0;\n const broken: string[] = [];\n for (const service of services) {\n const paths = featureSpecPaths(featureDir, service);\n const api = await apiChanges(paths.openapi);\n const events = await eventChanges(paths.asyncapi);\n if (api.unreadable || events.unreadable) broken.push(service);\n operations += api.changes.filter((change) => !change.remove).length;\n messages += events.changes.filter((change) => !change.remove).length;\n }\n const delta = featurePaths(featureDir).delta;\n let architecture: string | undefined;\n if (existsSync(delta)) {\n const loaded = await context.loadLikeC4(delta);\n // The first error only: the packet says WHICH document could not be read and\n // why, and a reader who needs the rest runs `loam validate --feature`, whose\n // job the whole list is.\n const first = loaded.errors[0];\n if (first !== undefined) architecture = errorText(first);\n }\n return {\n operations,\n messages,\n unreadable: {\n ...(architecture === undefined ? {} : { architecture }),\n ...(broken.length === 0 ? {} : { contracts: broken }),\n },\n };\n}\n\n/** How many requirements and scenarios the delta axes hold, whatever their kind. */\nexport function axisSize(axes: readonly DeltaAxis[]): { requirements: number; scenarios: number } {\n return {\n requirements: axes.reduce((n, a) => n + a.requirements.length, 0),\n scenarios: axes.reduce((n, a) => n + a.requirements.reduce((m, r) => m + r.scenarios.length, 0), 0),\n };\n}\n"]}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * What the generated suite in THIS repository already carries — read-only, and
3
+ * never written.
4
+ *
5
+ * `loam gherkin` stamps every scenario it emits with `@loam-digest-<16hex>`,
6
+ * the same hex a `scenario.tested` claim carries (`core/gherkin/digest.ts` owns
7
+ * the one recipe). So the presence of a stamp answers exactly one question: has
8
+ * a test skeleton for THESE words been generated yet? That is the difference
9
+ * between a unit waiting at `generate` and one waiting at `implement`, and it is
10
+ * the only reason a packet looks at the service repository at all.
11
+ *
12
+ * The resolution is `loam gherkin`'s own — `gherkinRoot` for the directory,
13
+ * `parseStampedFeature` for the bytes — because a second spelling of either
14
+ * would let the packet grade a suite the emitter does not own, or miss one it
15
+ * does.
16
+ *
17
+ * TWO ABSENCES, KEPT APART. A root directory that is not there means the suite
18
+ * has not been generated: the stamps ARE readable and the set is empty, so every
19
+ * scenario unit honestly reads `generate`. No binding, an unreadable repository,
20
+ * or an output directory that escapes it means loam COULD NOT LOOK, which is
21
+ * reported as "unknown" and never as an empty set — "nothing is wrong" and "I
22
+ * could not look" are opposite facts, and only one of them is a task list.
23
+ */
24
+ import { existsSync } from "node:fs";
25
+ import { readdir, readFile } from "node:fs/promises";
26
+ import { join } from "node:path";
27
+ import { parseStampedFeature } from "../gherkin/read.js";
28
+ import { gherkinRoot } from "../gherkin/stamp.js";
29
+ export async function readStamps(binding) {
30
+ const unknown = { state: "unknown", digests: new Set(), service: null };
31
+ if (binding.service === undefined)
32
+ return unknown;
33
+ let root;
34
+ try {
35
+ root = gherkinRoot(binding.repoDir, binding.gherkinDir);
36
+ }
37
+ catch {
38
+ // An output directory that escapes the repo is a configuration loam refuses
39
+ // to write through (`core/kernel/path-safety.ts`), so it is also one this
40
+ // must not read through — and it is a could-not-look, not an empty suite.
41
+ return unknown;
42
+ }
43
+ if (!existsSync(root))
44
+ return { state: "read", digests: new Set(), service: binding.service };
45
+ const digests = new Set();
46
+ let entries;
47
+ try {
48
+ entries = await readdir(root, { withFileTypes: true });
49
+ }
50
+ catch {
51
+ // The directory is there and will not open. Unreadable is not empty.
52
+ return unknown;
53
+ }
54
+ for (const entry of entries) {
55
+ if (entry.isDirectory() || !entry.name.endsWith(".feature"))
56
+ continue;
57
+ let text;
58
+ try {
59
+ text = await readFile(join(root, entry.name), "utf8");
60
+ }
61
+ catch {
62
+ // One unreadable file under a readable root: the rest of the suite still
63
+ // answers, and a file loam cannot read carries no stamps it may credit.
64
+ continue;
65
+ }
66
+ const stamped = parseStampedFeature(text);
67
+ // Null means line 1 is not loam's stamp — the file is not loam's writing,
68
+ // and no staleness judgment may be built on it.
69
+ if (stamped === null)
70
+ continue;
71
+ for (const scenario of stamped.scenarios)
72
+ digests.add(scenario.digest);
73
+ }
74
+ return { state: "read", digests, service: binding.service };
75
+ }
76
+ //# sourceMappingURL=stamps.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stamps.js","sourceRoot":"","sources":["../../../src/core/tasks/stamps.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAoBlD,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,OAAuB;IACtD,MAAM,OAAO,GAAiB,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,GAAG,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IACtF,IAAI,OAAO,CAAC,OAAO,KAAK,SAAS;QAAE,OAAO,OAAO,CAAC;IAClD,IAAI,IAAY,CAAC;IACjB,IAAI,CAAC;QACH,IAAI,GAAG,WAAW,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;IAC1D,CAAC;IAAC,MAAM,CAAC;QACP,4EAA4E;QAC5E,0EAA0E;QAC1E,0EAA0E;QAC1E,OAAO,OAAO,CAAC;IACjB,CAAC;IACD,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,GAAG,EAAE,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC;IAC9F,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAClC,IAAI,OAAO,CAAC;IACZ,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,OAAO,CAAC,IAAI,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IACzD,CAAC;IAAC,MAAM,CAAC;QACP,qEAAqE;QACrE,OAAO,OAAO,CAAC;IACjB,CAAC;IACD,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,KAAK,CAAC,WAAW,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC;YAAE,SAAS;QACtE,IAAI,IAAY,CAAC;QACjB,IAAI,CAAC;YACH,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,CAAC;QACxD,CAAC;QAAC,MAAM,CAAC;YACP,yEAAyE;YACzE,wEAAwE;YACxE,SAAS;QACX,CAAC;QACD,MAAM,OAAO,GAAG,mBAAmB,CAAC,IAAI,CAAC,CAAC;QAC1C,0EAA0E;QAC1E,gDAAgD;QAChD,IAAI,OAAO,KAAK,IAAI;YAAE,SAAS;QAC/B,KAAK,MAAM,QAAQ,IAAI,OAAO,CAAC,SAAS;YAAE,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IACzE,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC;AAC9D,CAAC","sourcesContent":["/**\n * What the generated suite in THIS repository already carries — read-only, and\n * never written.\n *\n * `loam gherkin` stamps every scenario it emits with `@loam-digest-<16hex>`,\n * the same hex a `scenario.tested` claim carries (`core/gherkin/digest.ts` owns\n * the one recipe). So the presence of a stamp answers exactly one question: has\n * a test skeleton for THESE words been generated yet? That is the difference\n * between a unit waiting at `generate` and one waiting at `implement`, and it is\n * the only reason a packet looks at the service repository at all.\n *\n * The resolution is `loam gherkin`'s own — `gherkinRoot` for the directory,\n * `parseStampedFeature` for the bytes — because a second spelling of either\n * would let the packet grade a suite the emitter does not own, or miss one it\n * does.\n *\n * TWO ABSENCES, KEPT APART. A root directory that is not there means the suite\n * has not been generated: the stamps ARE readable and the set is empty, so every\n * scenario unit honestly reads `generate`. No binding, an unreadable repository,\n * or an output directory that escapes it means loam COULD NOT LOOK, which is\n * reported as \"unknown\" and never as an empty set — \"nothing is wrong\" and \"I\n * could not look\" are opposite facts, and only one of them is a task list.\n */\nimport { existsSync } from \"node:fs\";\nimport { readdir, readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { parseStampedFeature } from \"../gherkin/read.js\";\nimport { gherkinRoot } from \"../gherkin/stamp.js\";\n\n/** Which repository's suite to read, as loam.json describes it. */\nexport interface GherkinBinding {\n /** The repo root loam.json was found in — never the cwd, which may be any subdirectory. */\n repoDir: string;\n /** The service this repository says it is; absent in a docs repo or an unbound checkout. */\n service?: string;\n /** `gherkinDir` from loam.json, when it names one. */\n gherkinDir?: string;\n}\n\nexport interface StampReading {\n state: \"read\" | \"unknown\";\n /** The `@loam-digest-…` values found. Meaningful only when `state` is \"read\". */\n digests: ReadonlySet<string>;\n /** The service the stamps belong to — nothing may be said about any other repository's suite. */\n service: string | null;\n}\n\nexport async function readStamps(binding: GherkinBinding): Promise<StampReading> {\n const unknown: StampReading = { state: \"unknown\", digests: new Set(), service: null };\n if (binding.service === undefined) return unknown;\n let root: string;\n try {\n root = gherkinRoot(binding.repoDir, binding.gherkinDir);\n } catch {\n // An output directory that escapes the repo is a configuration loam refuses\n // to write through (`core/kernel/path-safety.ts`), so it is also one this\n // must not read through — and it is a could-not-look, not an empty suite.\n return unknown;\n }\n if (!existsSync(root)) return { state: \"read\", digests: new Set(), service: binding.service };\n const digests = new Set<string>();\n let entries;\n try {\n entries = await readdir(root, { withFileTypes: true });\n } catch {\n // The directory is there and will not open. Unreadable is not empty.\n return unknown;\n }\n for (const entry of entries) {\n if (entry.isDirectory() || !entry.name.endsWith(\".feature\")) continue;\n let text: string;\n try {\n text = await readFile(join(root, entry.name), \"utf8\");\n } catch {\n // One unreadable file under a readable root: the rest of the suite still\n // answers, and a file loam cannot read carries no stamps it may credit.\n continue;\n }\n const stamped = parseStampedFeature(text);\n // Null means line 1 is not loam's stamp — the file is not loam's writing,\n // and no staleness judgment may be built on it.\n if (stamped === null) continue;\n for (const scenario of stamped.scenarios) digests.add(scenario.digest);\n }\n return { state: \"read\", digests, service: binding.service };\n}\n"]}
Binary file
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unit.js","sourceRoot":"","sources":["../../../src/core/tasks/unit.ts"],"names":[],"mappings":"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","sourcesContent":["/**\r\n * What a unit of work IS, and the total order they are read in.\r\n *\r\n * A unit is the third rendering of one ledger. `loam verify` answers \"answered\r\n * by whom\"; this answers \"what is still open, at which step, and what closes\r\n * it\". Nothing here is a second definition of a claim: for a claim-backed unit\r\n * the id, kind, subject, claim text, digest, operation and token are the\r\n * `Claim`'s own fields verbatim (`core/verify/checklist.ts`) — the task id IS\r\n * the claim id, which is what lets an agent hand a unit id straight to\r\n * `loam verify` and lets two runs be diffed.\r\n *\r\n * `at` is the step the unit is waiting at, and it is deliberately NOT spelled\r\n * `stage` or `verdict`: `stage` is the published `ArtifactStatus` key\r\n * (`core/status/report.ts`) and `verdict` is `VerificationVerdict`\r\n * (`core/verify/record.ts`). A third meaning for either word on a payload an\r\n * agent reads beside the other two is how a consumer comes to branch on the\r\n * wrong field.\r\n */\r\nimport { createHash } from \"node:crypto\";\r\nimport { CLAIM_KINDS, ID_LENGTH } from \"../verify/claims/identity.js\";\r\nimport { compareIds } from \"../repo/entries.js\";\r\n\r\n/**\r\n * Where a unit is waiting.\r\n *\r\n * `describe` is the first BDD act — a requirement with no scenario at all, so\r\n * there is nothing to generate a test from and nothing to claim. `generate`\r\n * means the scenario exists and this repository's generated suite does not\r\n * carry its stamp yet. `implement` is everything else that is open.\r\n * `attested` is the one step that is not work: the claim is confirmed on an\r\n * agent's word rather than on a run, so the unit never vanishes — it stays\r\n * visible, and closing it means a cucumber report, not an edit.\r\n */\r\nexport type TaskStep = \"describe\" | \"generate\" | \"implement\" | \"attested\";\r\n\r\n/** Where the words a unit is about are written down, so a reader can open the file. */\r\nexport interface RequirementSource {\r\n /** Repo-relative, like every path in the envelope. */\r\n path: string;\r\n /** 1-based heading line, when the parser recorded one. */\r\n line?: number;\r\n requirement: string;\r\n requirementId?: string;\r\n}\r\n\r\n/**\r\n * A scenario's source — the requirement's, plus the scenario's own words.\r\n *\r\n * A variant rather than four more optional fields on the shape above: `scenario`\r\n * and `lines` are only ever set together, and only for `scenario.tested`. The\r\n * body rides VERBATIM because it is the acceptance criterion the implementer is\r\n * meant to satisfy and the exact text the digest was taken over — paraphrasing\r\n * it here would be the one thing the whole digest chain exists to prevent.\r\n */\r\nexport interface ScenarioSource extends RequirementSource {\r\n scenario: string;\r\n lines: string[];\r\n}\r\n\r\nexport type TaskSource = RequirementSource | ScenarioSource;\r\n\r\nexport interface TaskUnit {\r\n /** The claim id verbatim, or a `requirement.described-…` id from `describedUnitId`. */\r\n id: string;\r\n kind: string;\r\n subject: string;\r\n at: TaskStep;\r\n claim: string;\r\n digest?: string;\r\n operation?: string;\r\n token?: string;\r\n dependsOn: string[];\r\n source?: TaskSource;\r\n done: { check: string };\r\n}\r\n\r\n/**\r\n * The one kind that is NOT a claim kind.\r\n *\r\n * `CLAIM_KINDS` is frozen: a member added to it re-hashes nothing, but it\r\n * changes the checklist's question set, and every `verification.yaml` in the\r\n * fleet would read as stale on upgrade. A requirement with no scenarios is also\r\n * not a promise anybody can answer with evidence — there is no text to test —\r\n * so it lives in a namespace of its own, with an id recipe of its own.\r\n */\r\nexport const DESCRIBED_KIND = \"requirement.described\";\r\n\r\n/**\r\n * The id of a `requirement.described` unit: content-derived, like a claim id\r\n * and for a claim id's reason — rename the requirement and the unit retires\r\n * itself rather than following a heading around.\r\n *\r\n * `\"loam.task\"` leads the tuple so this namespace can never collide with\r\n * `claimId`'s, whose tuples start with the feature id. NUL-joined for\r\n * `claimId`'s reason: no part's own text can spell the separator, so\r\n * [\"a b\",\"c\"] and [\"a\",\"b c\"] stay two units. `axisFile` is `spec.md` or\r\n * `arch.spec.md` — the two axes are two namespaces everywhere else in loam\r\n * (`core/gherkin/digest.ts` salts the scenario hash with it), and one\r\n * requirement name may legitimately appear on both.\r\n */\r\nexport function describedUnitId(\r\n featureId: string,\r\n service: string,\r\n axisFile: string,\r\n requirement: string,\r\n): string {\r\n const tuple = [\"loam.task\", featureId, DESCRIBED_KIND, service, axisFile, requirement].join(\"\u0000\");\r\n return `${DESCRIBED_KIND}-${createHash(\"sha256\").update(tuple).digest(\"hex\").slice(0, ID_LENGTH)}`;\r\n}\r\n\r\n/**\r\n * What closes this unit, in one sentence a reader can act on without opening\r\n * another document. Every arm names the mechanical channel that may answer it,\r\n * because the channels are not interchangeable: a scenario claim confirmed\r\n * without a run is `attested` and not `verified` (core/verify/record.ts), and an\r\n * api.exposes claim is answered by a contract report rather than by a cucumber\r\n * one.\r\n */\r\nexport function doneCheck(unit: { kind: string; digest?: string; operation?: string }): string {\r\n if (unit.kind === DESCRIBED_KIND) return \"the requirement carries at least one #### Scenario:\";\r\n if (unit.kind === \"scenario.tested\") {\r\n // Both report shapes by name: a fleet whose runner has no cucumber\r\n // formatter otherwise reads this as \"cucumber or nothing\", and the\r\n // runner-neutral shape exists precisely so it is not.\r\n return (\r\n `scenario @loam-digest-${unit.digest ?? \"\"} passes in a test run — a cucumber JSON report, ` +\r\n \"or a loamScenarioReport entry carrying that digest — and is recorded confirmed (loam verify --results)\"\r\n );\r\n }\r\n if (unit.kind === \"api.exposes\") {\r\n return `operationId '${unit.operation ?? \"\"}' reported passed via loam verify --contract-results and recorded`;\r\n }\r\n return \"recorded confirmed with file:line evidence (loam verify --record)\";\r\n}\r\n\r\n/**\r\n * The one edge v1 draws: a `c4.calls` unit depends on the `api.exposes` units\r\n * that promise the operation it calls.\r\n *\r\n * The join is EXACT and cross-kind on purpose — a call edge's `token` against a\r\n * provider claim's `operation`, never token against token. An AsyncAPI message\r\n * name and an operationId are different namespaces that routinely spell the\r\n * same word (`payment.Authorized` is not an operationId, but `createSplit` is a\r\n * perfectly plausible message name), and `event.declares` carries a `token`\r\n * too: joining on token equality would wire a consumer's call to an unrelated\r\n * message declaration and then order the whole packet by that fiction.\r\n * `operation` is set on `api.exposes` and nothing else — `core/verify/checklist.ts`\r\n * says so in the field's own docblock, and `contestedOperations` already\r\n * depends on it.\r\n *\r\n * Ordering is ADVICE, never a lock. The frontier does not exclude a unit for\r\n * having open dependencies; the sort merely puts providers first. An\r\n * implementer who starts at the consumer is not doing anything wrong, and a\r\n * packet that refused to show them the work would be a scheduler.\r\n */\r\nexport function linkDependencies(units: TaskUnit[]): void {\r\n const providers = new Map<string, string[]>();\r\n for (const unit of units) {\r\n if (unit.kind !== \"api.exposes\" || unit.operation === undefined) continue;\r\n const ids = providers.get(unit.operation) ?? [];\r\n ids.push(unit.id);\r\n providers.set(unit.operation, ids);\r\n }\r\n for (const unit of units) {\r\n if (unit.kind !== \"c4.calls\" || unit.token === undefined) continue;\r\n unit.dependsOn = [...(providers.get(unit.token) ?? [])].sort();\r\n }\r\n}\r\n\r\n/**\r\n * The reading order, total and deterministic — `--json` consumers diff it.\r\n *\r\n * Describe first, because a requirement with no scenario blocks the whole BDD\r\n * chain under it: there is nothing to generate and nothing to test. Then the\r\n * claim kinds in `CLAIM_KINDS` order, which is read off the vocabulary rather\r\n * than respelled here — that order already reads as the story of a feature (the\r\n * service exists, it exposes its operations, it declares its messages, the calls\r\n * into it are wired, the behaviour is tested), and a second copy of it would be\r\n * free to disagree.\r\n *\r\n * Within a kind a unit somebody depends on sorts before one nobody does, so the\r\n * provider of a shared operation leads its own kind. Then the subject by\r\n * `compareIds` (the fleet's one id ordering), then the source line so a service's\r\n * units read in document order, then the id as the final tiebreak — a unit with\r\n * no source must still land somewhere stable.\r\n */\r\nexport function sortUnits(units: TaskUnit[]): TaskUnit[] {\r\n const dependedOn = new Set(units.flatMap((unit) => unit.dependsOn));\r\n const kindRank = (unit: TaskUnit): number => {\r\n const index = (CLAIM_KINDS as readonly string[]).indexOf(unit.kind);\r\n // A kind outside the vocabulary sorts last rather than first: -1 would put\r\n // an unknown kind ahead of `service.exists`, which is the one position that\r\n // silently reorders every packet the day a kind is added.\r\n return index === -1 ? CLAIM_KINDS.length : index;\r\n };\r\n const lineOf = (unit: TaskUnit): number => unit.source?.line ?? Number.MAX_SAFE_INTEGER;\r\n return [...units].sort(\r\n (a, b) =>\r\n Number(a.at !== \"describe\") - Number(b.at !== \"describe\") ||\r\n kindRank(a) - kindRank(b) ||\r\n Number(dependedOn.has(b.id)) - Number(dependedOn.has(a.id)) ||\r\n compareIds(a.subject, b.subject) ||\r\n lineOf(a) - lineOf(b) ||\r\n compareIds(a.id, b.id),\r\n );\r\n}\r\n\r\n/** How many unit ids the frontier carries before it starts eliding. */\r\nexport const FRONTIER_LIMIT = 10;\r\n\r\n/** An open unit is one that is still work: `attested` is complete work resting on an assertion. */\r\nexport function isOpen(unit: TaskUnit): boolean {\r\n return unit.at !== \"attested\";\r\n}\r\n"]}
@@ -0,0 +1,166 @@
1
+ /**
2
+ * The capability half of the use-case axis: which flows CLAIM a declared
3
+ * capability, and which services those flows run through.
4
+ *
5
+ * `core/capabilities/usecase-join.ts` owns the tag grammar and the resolution
6
+ * ladder — it answers "what does this tag name?", including the `many` arm the
7
+ * slug's non-injectivity forces. This module asks the question the other way
8
+ * round: given a capability id somebody already has, which views carry its tag?
9
+ * That direction needs no ladder, because the id is not in doubt; it needs only
10
+ * the slug, so it takes the slug and stops.
11
+ *
12
+ * ## What this deliberately does NOT do
13
+ *
14
+ * It does not grade the tag. A view tagged `#cap-payments-refunds` matches BOTH
15
+ * `payments/refunds` and `payments-refunds` when a fleet declares both, and this
16
+ * module reports it under both — because that is what the tag says, and the tag
17
+ * is what the author wrote. `usecase.capability-unresolved` is already an ERROR
18
+ * over exactly that collision (`validate`'s use-case package), so a second
19
+ * verdict here would be a second answer to a question the gate has already
20
+ * settled. The same stance `PackPermission` takes on an undeclared permission:
21
+ * carry the claim, let validate convict it.
22
+ */
23
+ import { tagSlug, CAP_TAG_PREFIX, resolveCapabilityTags, resolveRequirementTags, } from "../capabilities/usecase-join.js";
24
+ import { capabilityRequirementIndex } from "../capabilities/findings.js";
25
+ import { compareIds } from "../repo/entries.js";
26
+ import { readUseCases } from "./fleet.js";
27
+ import { viewFile } from "./place.js";
28
+ import { participantsOf } from "./suites/participants.js";
29
+ /** The tag spelling a declared capability id would carry — `identity/tokens` → `cap-identity-tokens`. */
30
+ function tagFor(capability) {
31
+ return `${CAP_TAG_PREFIX}${tagSlug(capability)}`;
32
+ }
33
+ /** Does this view claim the capability? Exact tag match, case included, as `resolveCapabilityTags` matches. */
34
+ function claims(view, tag) {
35
+ return view.tags.includes(tag);
36
+ }
37
+ /**
38
+ * The flows claiming one declared capability, sorted by (file, id).
39
+ *
40
+ * Sorted rather than reported in LikeC4's record order for the reason every
41
+ * other list in this axis is: nothing has measured that the parse preserves
42
+ * declaration order, and a payload ordered by an unmeasured upstream detail
43
+ * reorders under a dependency bump.
44
+ */
45
+ export function flowsClaiming(scan, capability) {
46
+ if (scan.kind !== "read")
47
+ return [];
48
+ const tag = tagFor(capability);
49
+ return scan.views
50
+ .filter((view) => claims(view, tag))
51
+ .map((view) => ({ id: view.id, ...(view.title === undefined ? {} : { title: view.title }), file: viewFile(view) }))
52
+ .sort((a, b) => compareIds(a.file, b.file) || compareIds(a.id, b.id));
53
+ }
54
+ /**
55
+ * Every ENUMERATED service the flows claiming these capabilities run through.
56
+ *
57
+ * The restriction to the enumerated fleet is this function's own contract, not
58
+ * a guard somebody downstream is relying on: a step's endpoints resolve to
59
+ * whatever the element stands for, and a sequence diagram is full of endpoints
60
+ * that own no directory — the actor who starts the flow, the topic in the
61
+ * middle, the database at the end. A function called `servicesInFlows…` that
62
+ * answered `Customer` would be lying in its own name. `loam explore`, today's
63
+ * only caller, filters the result against its enumeration again for a different
64
+ * reason (it needs `ServiceEntry`s, in enumeration order), so removing the
65
+ * filter here would not currently change what that command prints — which is
66
+ * exactly why it is written down that the reason it exists is the return type,
67
+ * not the call site.
68
+ *
69
+ * The walk itself is `./suites/participants.ts`' `participantsOf`, which
70
+ * this function used to spell for itself: a suite asks the same question of a
71
+ * different set of views and needs the participants that resolve to NO service
72
+ * as well. The restriction now lives here as a choice — this function reads
73
+ * `services` and drops `unresolved` — rather than as a filter inside the walk,
74
+ * so the one union a test stand is provisioned from and the one `explore` seeds
75
+ * from cannot resolve an element two ways.
76
+ *
77
+ * The cost of the restriction, stated so the next reader can weigh it: a flow
78
+ * drawn through a service the fleet has not adopted yet contributes no seed.
79
+ * That service has no documentation to explore, so what is lost is a name in a
80
+ * list, and `usecase.step-unlinked` / `landscape.service-undocumented` are where
81
+ * the fleet is told about it.
82
+ */
83
+ export function servicesInFlowsClaiming(scan, capabilities) {
84
+ if (scan.kind !== "read")
85
+ return [];
86
+ const tags = new Set(capabilities.map(tagFor));
87
+ const claiming = scan.views.filter((view) => [...tags].some((tag) => claims(view, tag)));
88
+ return participantsOf(scan, claiming).services;
89
+ }
90
+ /**
91
+ * The `<capability>#<Requirement-ID>` pairs a fleet's flows RESOLVE to — the
92
+ * business promises a use case claims to keep.
93
+ *
94
+ * Lives in core rather than beside the grade that reports a broken tag, because
95
+ * two very different callers need the same answer and they must not compute it
96
+ * twice: `validate --all` subtracts these from
97
+ * `capability.requirement-unrealized` (a promise a flow keeps is not unkept),
98
+ * and `loam list capabilities` reports them beside the service requirements
99
+ * that realize the same promise. Two implementations of "which promises does
100
+ * this fleet keep" is two answers to the question the axis exists to settle.
101
+ *
102
+ * A MAP RATHER THAN A SET, because the two callers need different depths of the
103
+ * same answer and one of them needs names. `validate` only asks whether a
104
+ * promise is kept (`.has`, which a Map answers identically); a listing that said
105
+ * "kept" without saying by WHAT would leave a reader unable to open the flow, go
106
+ * look at its hops and judge whether the promise really is kept — which is the
107
+ * whole reason the listing carries the realizing service requirements by name
108
+ * rather than as a count. Widening the return type was cheaper than a second
109
+ * function, and a second function is how the two corpora start disagreeing.
110
+ *
111
+ * ONLY RESOLVED CLAIMS COUNT, and both halves must resolve: the `#cap-` tag to
112
+ * exactly one declared capability, and the `#req-` tag to exactly one of its
113
+ * requirements. A broken tag of either kind is already an ERROR
114
+ * (`usecase.capability-unresolved`, `usecase.requirement-unresolved`) and must
115
+ * never also mark a promise kept — a typo that silenced the unrealized warning
116
+ * would turn a mistake into a green fleet.
117
+ *
118
+ * `declared` carries the vocabulary ladder: `null` means there is nothing to
119
+ * grade against, and the honest answer is then an empty map — no flow can be
120
+ * said to keep a promise loam cannot see declared.
121
+ *
122
+ * Diff-stable by construction: the view ids under each promise are DEDUPLICATED
123
+ * and sorted with compareIds, so nothing here depends on LikeC4's view order,
124
+ * on how many tags one view carried, or on the readdir order the project was
125
+ * staged in. The map's own key order reaches no output — both callers look
126
+ * promises up by key — but the values are printed, so they are sorted.
127
+ */
128
+ export function useCaseRequirementClaims(views, declared, requirementsOf) {
129
+ const claimed = new Map();
130
+ if (declared !== null) {
131
+ for (const view of views) {
132
+ const scope = resolveCapabilityTags(view.tags, declared).flatMap((claim) => claim.kind === "resolved" ? [claim.id] : []);
133
+ for (const claim of resolveRequirementTags(view.tags, scope, requirementsOf)) {
134
+ if (claim.kind !== "resolved")
135
+ continue;
136
+ const key = `${claim.capability}#${claim.id}`;
137
+ const flows = claimed.get(key) ?? new Set();
138
+ flows.add(view.id);
139
+ claimed.set(key, flows);
140
+ }
141
+ }
142
+ }
143
+ return new Map([...claimed].map(([key, flows]) => [key, [...flows].sort(compareIds)]));
144
+ }
145
+ export async function promisesKeptByFlows(req) {
146
+ const scan = await readUseCases({ docsDir: req.docsDir, known: req.known });
147
+ if (scan.kind !== "read")
148
+ return { kind: "unreadable", errors: scan.errors };
149
+ // No flow, no claim — and no capability document is opened to prove it.
150
+ // `readUseCases`' byte gate answers a fleet with no use cases without starting
151
+ // LikeC4 at all, and reading every `capabilities/<id>/spec.md` here to resolve
152
+ // a tag set that is empty would put back the cost the gate exists to remove.
153
+ // The `read` arm is still what travels: the fleet WAS looked at.
154
+ if (scan.views.length === 0)
155
+ return { kind: "read", kept: new Map() };
156
+ const index = await capabilityRequirementIndex(req.vocab, req.read);
157
+ // `index.declared` rather than a second call to `gradableCapabilityIds`: the
158
+ // index applied the ladder when it was built, and two applications of one rule
159
+ // is where the two halves of this join start disagreeing about whether the
160
+ // vocabulary is gradable at all.
161
+ return {
162
+ kind: "read",
163
+ kept: useCaseRequirementClaims(scan.views, index.declared, (c) => index.byCapability.get(c)),
164
+ };
165
+ }
166
+ //# sourceMappingURL=capability.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capability.js","sourceRoot":"","sources":["../../../src/core/usecases/capability.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The capability half of the use-case axis: which flows CLAIM a declared\n * capability, and which services those flows run through.\n *\n * `core/capabilities/usecase-join.ts` owns the tag grammar and the resolution\n * ladder — it answers \"what does this tag name?\", including the `many` arm the\n * slug's non-injectivity forces. This module asks the question the other way\n * round: given a capability id somebody already has, which views carry its tag?\n * That direction needs no ladder, because the id is not in doubt; it needs only\n * the slug, so it takes the slug and stops.\n *\n * ## What this deliberately does NOT do\n *\n * It does not grade the tag. A view tagged `#cap-payments-refunds` matches BOTH\n * `payments/refunds` and `payments-refunds` when a fleet declares both, and this\n * module reports it under both — because that is what the tag says, and the tag\n * is what the author wrote. `usecase.capability-unresolved` is already an ERROR\n * over exactly that collision (`validate`'s use-case package), so a second\n * verdict here would be a second answer to a question the gate has already\n * settled. The same stance `PackPermission` takes on an undeclared permission:\n * carry the claim, let validate convict it.\n */\nimport {\n tagSlug,\n CAP_TAG_PREFIX,\n resolveCapabilityTags,\n resolveRequirementTags,\n} from \"../capabilities/usecase-join.js\";\nimport { capabilityRequirementIndex } from \"../capabilities/findings.js\";\nimport type { CapabilityVocabulary } from \"../capabilities/capabilities.js\";\nimport type { Requirement } from \"../document/spec.js\";\nimport { compareIds } from \"../repo/entries.js\";\nimport type { ParsedView } from \"../c4/parsed/dynamic-views.js\";\nimport type { DocsDir } from \"../kernel/ids/dirs.js\";\nimport { readUseCases, type UseCaseScan } from \"./fleet.js\";\nimport { viewFile } from \"./place.js\";\nimport { participantsOf } from \"./suites/participants.js\";\n\n/** One flow claiming a capability: enough to name it and to open the file it lives in. */\nexport interface ClaimingFlow {\n id: string;\n title?: string;\n /** Repo-relative document the view is written in. */\n file: string;\n}\n\n/** The tag spelling a declared capability id would carry — `identity/tokens` → `cap-identity-tokens`. */\nfunction tagFor(capability: string): string {\n return `${CAP_TAG_PREFIX}${tagSlug(capability)}`;\n}\n\n/** Does this view claim the capability? Exact tag match, case included, as `resolveCapabilityTags` matches. */\nfunction claims(view: ParsedView, tag: string): boolean {\n return view.tags.includes(tag);\n}\n\n/**\n * The flows claiming one declared capability, sorted by (file, id).\n *\n * Sorted rather than reported in LikeC4's record order for the reason every\n * other list in this axis is: nothing has measured that the parse preserves\n * declaration order, and a payload ordered by an unmeasured upstream detail\n * reorders under a dependency bump.\n */\nexport function flowsClaiming(scan: UseCaseScan, capability: string): ClaimingFlow[] {\n if (scan.kind !== \"read\") return [];\n const tag = tagFor(capability);\n return scan.views\n .filter((view) => claims(view, tag))\n .map((view) => ({ id: view.id, ...(view.title === undefined ? {} : { title: view.title }), file: viewFile(view) }))\n .sort((a, b) => compareIds(a.file, b.file) || compareIds(a.id, b.id));\n}\n\n/**\n * Every ENUMERATED service the flows claiming these capabilities run through.\n *\n * The restriction to the enumerated fleet is this function's own contract, not\n * a guard somebody downstream is relying on: a step's endpoints resolve to\n * whatever the element stands for, and a sequence diagram is full of endpoints\n * that own no directory — the actor who starts the flow, the topic in the\n * middle, the database at the end. A function called `servicesInFlows…` that\n * answered `Customer` would be lying in its own name. `loam explore`, today's\n * only caller, filters the result against its enumeration again for a different\n * reason (it needs `ServiceEntry`s, in enumeration order), so removing the\n * filter here would not currently change what that command prints — which is\n * exactly why it is written down that the reason it exists is the return type,\n * not the call site.\n *\n * The walk itself is `./suites/participants.ts`' `participantsOf`, which\n * this function used to spell for itself: a suite asks the same question of a\n * different set of views and needs the participants that resolve to NO service\n * as well. The restriction now lives here as a choice — this function reads\n * `services` and drops `unresolved` — rather than as a filter inside the walk,\n * so the one union a test stand is provisioned from and the one `explore` seeds\n * from cannot resolve an element two ways.\n *\n * The cost of the restriction, stated so the next reader can weigh it: a flow\n * drawn through a service the fleet has not adopted yet contributes no seed.\n * That service has no documentation to explore, so what is lost is a name in a\n * list, and `usecase.step-unlinked` / `landscape.service-undocumented` are where\n * the fleet is told about it.\n */\nexport function servicesInFlowsClaiming(scan: UseCaseScan, capabilities: readonly string[]): string[] {\n if (scan.kind !== \"read\") return [];\n const tags = new Set(capabilities.map(tagFor));\n const claiming = scan.views.filter((view) => [...tags].some((tag) => claims(view, tag)));\n return participantsOf(scan, claiming).services;\n}\n\n/**\n * The `<capability>#<Requirement-ID>` pairs a fleet's flows RESOLVE to — the\n * business promises a use case claims to keep.\n *\n * Lives in core rather than beside the grade that reports a broken tag, because\n * two very different callers need the same answer and they must not compute it\n * twice: `validate --all` subtracts these from\n * `capability.requirement-unrealized` (a promise a flow keeps is not unkept),\n * and `loam list capabilities` reports them beside the service requirements\n * that realize the same promise. Two implementations of \"which promises does\n * this fleet keep\" is two answers to the question the axis exists to settle.\n *\n * A MAP RATHER THAN A SET, because the two callers need different depths of the\n * same answer and one of them needs names. `validate` only asks whether a\n * promise is kept (`.has`, which a Map answers identically); a listing that said\n * \"kept\" without saying by WHAT would leave a reader unable to open the flow, go\n * look at its hops and judge whether the promise really is kept — which is the\n * whole reason the listing carries the realizing service requirements by name\n * rather than as a count. Widening the return type was cheaper than a second\n * function, and a second function is how the two corpora start disagreeing.\n *\n * ONLY RESOLVED CLAIMS COUNT, and both halves must resolve: the `#cap-` tag to\n * exactly one declared capability, and the `#req-` tag to exactly one of its\n * requirements. A broken tag of either kind is already an ERROR\n * (`usecase.capability-unresolved`, `usecase.requirement-unresolved`) and must\n * never also mark a promise kept — a typo that silenced the unrealized warning\n * would turn a mistake into a green fleet.\n *\n * `declared` carries the vocabulary ladder: `null` means there is nothing to\n * grade against, and the honest answer is then an empty map — no flow can be\n * said to keep a promise loam cannot see declared.\n *\n * Diff-stable by construction: the view ids under each promise are DEDUPLICATED\n * and sorted with compareIds, so nothing here depends on LikeC4's view order,\n * on how many tags one view carried, or on the readdir order the project was\n * staged in. The map's own key order reaches no output — both callers look\n * promises up by key — but the values are printed, so they are sorted.\n */\nexport function useCaseRequirementClaims(\n views: readonly ParsedView[],\n declared: readonly string[] | null,\n requirementsOf: (capability: string) => ReadonlySet<string> | undefined,\n): ReadonlyMap<string, string[]> {\n const claimed = new Map<string, Set<string>>();\n if (declared !== null) {\n for (const view of views) {\n const scope = resolveCapabilityTags(view.tags, declared).flatMap((claim) =>\n claim.kind === \"resolved\" ? [claim.id] : [],\n );\n for (const claim of resolveRequirementTags(view.tags, scope, requirementsOf)) {\n if (claim.kind !== \"resolved\") continue;\n const key = `${claim.capability}#${claim.id}`;\n const flows = claimed.get(key) ?? new Set<string>();\n flows.add(view.id);\n claimed.set(key, flows);\n }\n }\n }\n return new Map([...claimed].map(([key, flows]) => [key, [...flows].sort(compareIds)]));\n}\n\n/**\n * The same answer as `useCaseRequirementClaims`, read from disk — or the honest\n * refusal to give one.\n *\n * `validate --all` already holds the parsed project and has already applied the\n * vocabulary ladder by the time it grades, so it calls the pure function above\n * with what it has. `loam list capabilities` holds neither, and the three steps\n * between a docsDir and that answer — read the flows, take the ladder, index the\n * documents' requirement ids — are three chances to get the suppression rules\n * wrong. They live here rather than in the command for that reason and not for\n * brevity: a command that spelled `[...vocab.byId.keys()]` in place of the\n * ladder would report a flow's promise as kept against a vocabulary nobody could\n * read.\n *\n * THE `unreadable` ARM MUST TRAVEL. An `architecture/` that did not parse yields\n * no views, and an empty map is indistinguishable from \"no flow keeps\n * anything\" — which is the single wrong answer this axis exists to prevent, and\n * the reason `readUseCases` is a tagged union rather than a list.\n */\nexport type PromisesKept =\n | { kind: \"read\"; kept: ReadonlyMap<string, readonly string[]> }\n | { kind: \"unreadable\"; errors: string[] };\n\nexport interface PromisesKeptRequest {\n docsDir: DocsDir;\n vocab: CapabilityVocabulary;\n /** The enumerated fleet — `readUseCases`' own requirement, for its own reason. */\n known: ReadonlySet<string>;\n /** The requirement reader — pass a FleetContext's readRequirements, bound. */\n read: (path: string) => Promise<Requirement[]>;\n}\n\nexport async function promisesKeptByFlows(req: PromisesKeptRequest): Promise<PromisesKept> {\n const scan = await readUseCases({ docsDir: req.docsDir, known: req.known });\n if (scan.kind !== \"read\") return { kind: \"unreadable\", errors: scan.errors };\n // No flow, no claim — and no capability document is opened to prove it.\n // `readUseCases`' byte gate answers a fleet with no use cases without starting\n // LikeC4 at all, and reading every `capabilities/<id>/spec.md` here to resolve\n // a tag set that is empty would put back the cost the gate exists to remove.\n // The `read` arm is still what travels: the fleet WAS looked at.\n if (scan.views.length === 0) return { kind: \"read\", kept: new Map() };\n const index = await capabilityRequirementIndex(req.vocab, req.read);\n // `index.declared` rather than a second call to `gradableCapabilityIds`: the\n // index applied the ladder when it was built, and two applications of one rule\n // is where the two halves of this join start disagreeing about whether the\n // vocabulary is gradable at all.\n return {\n kind: \"read\",\n kept: useCaseRequirementClaims(scan.views, index.declared, (c) => index.byCapability.get(c)),\n };\n}\n"]}