@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,286 @@
1
+ /**
2
+ * Markdown in: headings, fences, and the one `## Requirements` cut point.
3
+ *
4
+ * The cut point is spelled once here on purpose. The archive cut, archive's
5
+ * stray-requirement guard and the delta-shape exemption used to spell the same
6
+ * invariant three different ways, and one of them was a PREFIX match that also
7
+ * hit `## Requirements Extra`.
8
+ *
9
+ * Fence tracking is why this is not a set of regexes at the call sites: a
10
+ * `### Requirement:` inside a fenced code block is prose about a requirement,
11
+ * not one, and every heading walk here has to agree about that.
12
+ */
13
+ import { readFile } from "node:fs/promises";
14
+ import { decodeDocument } from "../kernel/document-bytes.js";
15
+ import { fenceTracker } from "../kernel/fences.js";
16
+ import { BASED_ON_LINE_RE, CAPABILITY_LINE_RE, KIND_RE, REALIZES_LINE_RE, REQUIREMENT_ID_LINE_RE, } from "./spec.js";
17
+ const REQ_RE = /^###\s+Requirement:\s*(.+?)\s*$/;
18
+ const SCN_RE = /^####\s+Scenario:\s*(.+?)\s*$/;
19
+ /**
20
+ * THE requirements section: the one H2 a living spec keeps its requirements
21
+ * under, the one section `loam archive` rewrites, and the one heading a delta
22
+ * may legally quote the living state beneath. One definition on purpose — the
23
+ * archive cut point, archive's stray-requirement guard, and the delta-shape
24
+ * exemption (core/delta/document.ts) used to spell this invariant three different ways,
25
+ * and the cut point's substring `indexOf("\n## Requirements")` was a PREFIX
26
+ * match that also hit `## Requirements Extra`. Full-line match on a trimmed
27
+ * heading, with KIND_RE's case and interior-whitespace tolerance.
28
+ */
29
+ const REQUIREMENTS_SECTION_RE = /^##\s+Requirements\s*$/i;
30
+ /** Is this H2 heading line (as sectionHeadings/`Requirement.section` spell it) the `## Requirements` heading? */
31
+ export function isRequirementsHeading(heading) {
32
+ return REQUIREMENTS_SECTION_RE.test(heading.trim());
33
+ }
34
+ /**
35
+ * Strip a leading UTF-8 BOM (U+FEFF), which editors on Windows write unasked.
36
+ *
37
+ * It has to happen here, at the two functions that take raw markdown, rather than
38
+ * at each `readFile` call: those are spread across half the commands, so any one of
39
+ * them could forget, and the failure is invisible. One byte was enough to void an
40
+ * entire delta — `KIND_RE` is anchored `^##`, delta files routinely open with
41
+ * `## MODIFIED Requirements` on line 1, and behind a BOM that line stopped being a
42
+ * heading, so every requirement in the file fell back to BASE and
43
+ * `applyRequirementDelta` skips BASE. Archive merged nothing and said nothing.
44
+ * OpenSpec's own reader strips it for exactly this reason.
45
+ *
46
+ * Only at position 0: elsewhere U+FEFF is a zero-width no-break space and belongs
47
+ * to the author's text.
48
+ */
49
+ function stripBom(md) {
50
+ return md.charCodeAt(0) === 0xfeff ? md.slice(1) : md;
51
+ }
52
+ /** Every H2 heading outside a fenced block, with its 1-based line number. */
53
+ export function sectionHeadings(md) {
54
+ const fenced = fenceTracker();
55
+ const out = [];
56
+ stripBom(md).split(/\r?\n/).forEach((line, i) => {
57
+ if (fenced(line))
58
+ return;
59
+ if (/^##\s+/.test(line) && !line.startsWith("###"))
60
+ out.push({ text: line.trim(), line: i + 1 });
61
+ });
62
+ return out;
63
+ }
64
+ /**
65
+ * Split a living spec around its requirements RUN — the stretch of
66
+ * `### Requirement:` blocks inside the `## Requirements` section — so a merge
67
+ * can rewrite exactly that and nothing else. All three slices reassemble the
68
+ * input byte-for-byte (`head + run + tail === text`):
69
+ *
70
+ * - `head` — everything before the first requirement in the section: the
71
+ * intro, the heading line itself, any prose under the heading.
72
+ * - `run` — from the first `### Requirement:` line to the section's end (the
73
+ * next `## ` heading, or EOF). Empty when the section holds no requirements.
74
+ * - `tail` — everything from the section's end onward.
75
+ *
76
+ * `requirements` is the run cut again at every `### Requirement:` heading —
77
+ * one raw slice per requirement, from its heading up to the next one (or the
78
+ * run's end), so `requirements.join("") === run`. A slice therefore carries
79
+ * whatever the author wrote below the requirement before the next heading,
80
+ * blank lines included, which is exactly the text parseRequirements attributes
81
+ * to that requirement. It exists so archive can keep the bytes of every
82
+ * requirement a delta did not touch instead of re-serializing the whole run:
83
+ * one ADDED requirement used to reflow every untouched requirement written
84
+ * without a blank line under its heading, and every one of those moves landed
85
+ * under the document's vouch stamp.
86
+ *
87
+ * Returns null when the document has no `## Requirements` heading at all.
88
+ * Only the FIRST matching heading opens the section; a caller that must not
89
+ * lose content behind a duplicate (archive) counts matches via
90
+ * sectionHeadings() and refuses. Heading detection matches parseRequirements:
91
+ * fenced lines are never structure, and a leading BOM hides no heading — but
92
+ * the slices themselves are raw bytes, BOM and CRLF included.
93
+ */
94
+ export function splitRequirementsSection(text) {
95
+ const fenced = fenceTracker();
96
+ let inSection = false;
97
+ let sectionStart = -1;
98
+ const starts = [];
99
+ let sectionEnd = text.length;
100
+ let offset = 0;
101
+ while (offset < text.length) {
102
+ const nl = text.indexOf("\n", offset);
103
+ const lineEnd = nl === -1 ? text.length : nl + 1;
104
+ let line = text.slice(offset, nl === -1 ? text.length : nl);
105
+ if (line.endsWith("\r"))
106
+ line = line.slice(0, -1);
107
+ // Position 0 only, mirroring stripBom: elsewhere U+FEFF is content.
108
+ if (offset === 0 && line.charCodeAt(0) === 0xfeff)
109
+ line = line.slice(1);
110
+ if (!fenced(line)) {
111
+ if (/^##\s+/.test(line) && !line.startsWith("###")) {
112
+ if (inSection) {
113
+ sectionEnd = offset;
114
+ inSection = false;
115
+ }
116
+ else if (sectionStart === -1 && isRequirementsHeading(line)) {
117
+ sectionStart = offset;
118
+ inSection = true;
119
+ }
120
+ }
121
+ else if (inSection && REQ_RE.test(line)) {
122
+ starts.push(offset);
123
+ }
124
+ }
125
+ offset = lineEnd;
126
+ }
127
+ if (sectionStart === -1)
128
+ return null;
129
+ const cut = starts[0] ?? sectionEnd;
130
+ return {
131
+ head: text.slice(0, cut),
132
+ run: text.slice(cut, sectionEnd),
133
+ tail: text.slice(sectionEnd),
134
+ requirements: starts.map((at, i) => text.slice(at, starts[i + 1] ?? sectionEnd)),
135
+ };
136
+ }
137
+ /**
138
+ * A requirement document from disk as text — decoded, or refused by name.
139
+ *
140
+ * The read that belongs with the parser, because `readFile(path, "utf8")` and
141
+ * `parseRequirements` together are a trap: a UTF-16 spec.md decodes to a string
142
+ * in which no line matches `^###\s+Requirement:`, so the parser returns [] and
143
+ * the document grades as an empty baseline instead of an unreadable one. Every
144
+ * question loam asks of a spec — is it covered, does the delta merge, what does
145
+ * the C4 spine touch — is then answered about a file nobody read.
146
+ *
147
+ * It THROWS (`NotUtf8DocumentError`, which names the path), unlike
148
+ * `readFrontmatter` next door, because the two failures are not the same
149
+ * failure. Frontmatter is read by the fleet enumeration, where one bad file
150
+ * must not cost the other 119 services, so there it is a flag. A requirement
151
+ * document is read by ONE target, and the caller is the only one who knows what
152
+ * to do about it: a read-only command turns it into a finding on that target
153
+ * (validate's `guarded`, which names the file and keeps grading the rest), a
154
+ * command that writes refuses outright rather than computing over mojibake.
155
+ */
156
+ export async function readRequirementsDocument(path) {
157
+ return decodeDocument(await readFile(path), path);
158
+ }
159
+ /** Parse all requirements (with their scenarios and delta kind) from a markdown doc. */
160
+ export function parseRequirements(md) {
161
+ const out = [];
162
+ let kind = "BASE";
163
+ let section;
164
+ let req = null;
165
+ let scn = null;
166
+ const fenced = fenceTracker();
167
+ for (const [index, line] of stripBom(md).split(/\r?\n/).entries()) {
168
+ if (fenced(line)) {
169
+ // Fenced content, marker included: body of whatever is open, never structure.
170
+ if (scn)
171
+ scn.lines.push(line);
172
+ else if (req)
173
+ req.text.push(line);
174
+ continue;
175
+ }
176
+ // Any H2 heading ends the current requirement/scenario capture — section prose
177
+ // must not leak into the previous scenario's body.
178
+ if (/^##\s+/.test(line) && !line.startsWith("###")) {
179
+ req = null;
180
+ scn = null;
181
+ section = line.trim();
182
+ const mk = KIND_RE.exec(line);
183
+ // A non-delta H2 (## Notes, ## Requirements…) starts an unrelated section:
184
+ // requirements under it are plain BASE, not part of a stale delta section.
185
+ kind = mk ? mk[1].toUpperCase() : "BASE";
186
+ continue;
187
+ }
188
+ const mr = REQ_RE.exec(line);
189
+ if (mr) {
190
+ req = {
191
+ kind,
192
+ name: mr[1],
193
+ text: [],
194
+ operations: [],
195
+ covers: [],
196
+ publishes: [],
197
+ consumes: [],
198
+ requires: [],
199
+ capabilities: [],
200
+ realizes: [],
201
+ scenarios: [],
202
+ section,
203
+ line: index + 1,
204
+ };
205
+ out.push(req);
206
+ scn = null;
207
+ continue;
208
+ }
209
+ const ms = SCN_RE.exec(line);
210
+ if (ms && req) {
211
+ // `index + 1` is the heading's own 1-based line, exactly as the
212
+ // requirement capture above records its `### Requirement:` — body line
213
+ // `lines[i]` then sits at `line + 1 + i`, because the capture below is
214
+ // contiguous from here to the next heading. Purely additive: nothing in
215
+ // `serializeRequirements` reads it, so `requirementDigest` cannot see it
216
+ // and no `Based-On:` pin in any living document moves because the parser
217
+ // learned where a scenario starts.
218
+ scn = { name: ms[1], lines: [], line: index + 1 };
219
+ req.scenarios.push(scn);
220
+ continue;
221
+ }
222
+ if (scn) {
223
+ scn.lines.push(line);
224
+ }
225
+ else if (req) {
226
+ req.text.push(line);
227
+ const mi = REQUIREMENT_ID_LINE_RE.exec(line);
228
+ if (mi)
229
+ req.id = mi[1].trim();
230
+ // Same keep-last quirk as Operations:/Covers: below — a repeated line is
231
+ // a document problem, reported as one (`delta.baseline-invalid`), never
232
+ // resolved differently by whoever happens to be reading.
233
+ const mb = BASED_ON_LINE_RE.exec(line);
234
+ if (mb)
235
+ req.basedOn = mb[1].trim();
236
+ const mo = /^\s*Operations?:\s*(.+?)\s*$/i.exec(line);
237
+ if (mo)
238
+ req.operations = mo[1].split(",").map((s) => s.trim()).filter((s) => s.length > 0);
239
+ // The Covers: mirror — same placement (requirement body, not a scenario),
240
+ // same comma grammar, and deliberately the same quirk: a second line
241
+ // REPLACES the first (assignment, not append), so the two lists can never
242
+ // drift apart in how they read a repeated line.
243
+ const mc = /^\s*Covers?:\s*(.+?)\s*$/i.exec(line);
244
+ if (mc)
245
+ req.covers = mc[1].split(",").map((s) => s.trim()).filter((s) => s.length > 0);
246
+ // The event axis, same grammar and the same keep-last quirk again. Note
247
+ // what is NOT happening here: the line stays in `req.text` like every
248
+ // other body line (the push above is unconditional), so it round-trips
249
+ // through `serializeRequirements` and rides inside `requirementDigest`
250
+ // exactly as `Operations:` does. That is what makes this parse purely
251
+ // additive — no living document's digest moves, and no `Based-On:` pin
252
+ // goes stale because loam learned to read one more line.
253
+ const mp = /^\s*Publishes?:\s*(.+?)\s*$/i.exec(line);
254
+ if (mp)
255
+ req.publishes = mp[1].split(",").map((s) => s.trim()).filter((s) => s.length > 0);
256
+ const mcon = /^\s*Consumes?:\s*(.+?)\s*$/i.exec(line);
257
+ if (mcon)
258
+ req.consumes = mcon[1].split(",").map((s) => s.trim()).filter((s) => s.length > 0);
259
+ // The authorization axis. Same grammar, same keep-last quirk, same purely
260
+ // additive parse — the line rides in `req.text` and therefore inside
261
+ // `requirementDigest`, so no living document moves because loam learned
262
+ // to read it.
263
+ const mreq = /^\s*Requires?:\s*(.+?)\s*$/i.exec(line);
264
+ if (mreq)
265
+ req.requires = mreq[1].split(",").map((s) => s.trim()).filter((s) => s.length > 0);
266
+ // The capability axis. Same grammar, same keep-last quirk, same purely
267
+ // additive parse as Requires: above — but note the OPT-IN differs: the
268
+ // vocabulary FILE (architecture/capabilities.yaml) is the opt-in for this
269
+ // axis, not the line, so entries parsed here grade as nothing at all
270
+ // until a fleet writes that file (core/capabilities/findings.ts).
271
+ const mcap = CAPABILITY_LINE_RE.exec(line);
272
+ if (mcap)
273
+ req.capabilities = mcap[1].split(",").map((s) => s.trim()).filter((s) => s.length > 0);
274
+ // The join INTO the authored business tree: `<capability-id>#<Requirement-ID>`
275
+ // entries, same comma grammar and same keep-last quirk as every line
276
+ // above. Split into its two halves nowhere near here —
277
+ // `core/capabilities/realizes/join.ts` owns that, because the rollup and
278
+ // the grades must not be able to disagree about where the separator is.
279
+ const mrl = REALIZES_LINE_RE.exec(line);
280
+ if (mrl)
281
+ req.realizes = mrl[1].split(",").map((s) => s.trim()).filter((s) => s.length > 0);
282
+ }
283
+ }
284
+ return out;
285
+ }
286
+ //# sourceMappingURL=parse.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse.js","sourceRoot":"","sources":["../../../src/core/document/parse.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Markdown in: headings, fences, and the one `## Requirements` cut point.\n *\n * The cut point is spelled once here on purpose. The archive cut, archive's\n * stray-requirement guard and the delta-shape exemption used to spell the same\n * invariant three different ways, and one of them was a PREFIX match that also\n * hit `## Requirements Extra`.\n *\n * Fence tracking is why this is not a set of regexes at the call sites: a\n * `### Requirement:` inside a fenced code block is prose about a requirement,\n * not one, and every heading walk here has to agree about that.\n */\nimport { readFile } from \"node:fs/promises\";\nimport { decodeDocument } from \"../kernel/document-bytes.js\";\nimport { fenceTracker } from \"../kernel/fences.js\";\nimport {\n BASED_ON_LINE_RE, CAPABILITY_LINE_RE, KIND_RE, REALIZES_LINE_RE, REQUIREMENT_ID_LINE_RE,\n type DeltaKind, type Requirement, type Scenario,\n} from \"./spec.js\";\n\nconst REQ_RE = /^###\\s+Requirement:\\s*(.+?)\\s*$/;\nconst SCN_RE = /^####\\s+Scenario:\\s*(.+?)\\s*$/;\n\n/**\n * THE requirements section: the one H2 a living spec keeps its requirements\n * under, the one section `loam archive` rewrites, and the one heading a delta\n * may legally quote the living state beneath. One definition on purpose — the\n * archive cut point, archive's stray-requirement guard, and the delta-shape\n * exemption (core/delta/document.ts) used to spell this invariant three different ways,\n * and the cut point's substring `indexOf(\"\\n## Requirements\")` was a PREFIX\n * match that also hit `## Requirements Extra`. Full-line match on a trimmed\n * heading, with KIND_RE's case and interior-whitespace tolerance.\n */\nconst REQUIREMENTS_SECTION_RE = /^##\\s+Requirements\\s*$/i;\n\n/** Is this H2 heading line (as sectionHeadings/`Requirement.section` spell it) the `## Requirements` heading? */\nexport function isRequirementsHeading(heading: string): boolean {\n return REQUIREMENTS_SECTION_RE.test(heading.trim());\n}\n\n/**\n * Strip a leading UTF-8 BOM (U+FEFF), which editors on Windows write unasked.\n *\n * It has to happen here, at the two functions that take raw markdown, rather than\n * at each `readFile` call: those are spread across half the commands, so any one of\n * them could forget, and the failure is invisible. One byte was enough to void an\n * entire delta — `KIND_RE` is anchored `^##`, delta files routinely open with\n * `## MODIFIED Requirements` on line 1, and behind a BOM that line stopped being a\n * heading, so every requirement in the file fell back to BASE and\n * `applyRequirementDelta` skips BASE. Archive merged nothing and said nothing.\n * OpenSpec's own reader strips it for exactly this reason.\n *\n * Only at position 0: elsewhere U+FEFF is a zero-width no-break space and belongs\n * to the author's text.\n */\nfunction stripBom(md: string): string {\n return md.charCodeAt(0) === 0xfeff ? md.slice(1) : md;\n}\n\n/** Every H2 heading outside a fenced block, with its 1-based line number. */\nexport function sectionHeadings(md: string): Array<{ text: string; line: number }> {\n const fenced = fenceTracker();\n const out: Array<{ text: string; line: number }> = [];\n stripBom(md).split(/\\r?\\n/).forEach((line, i) => {\n if (fenced(line)) return;\n if (/^##\\s+/.test(line) && !line.startsWith(\"###\")) out.push({ text: line.trim(), line: i + 1 });\n });\n return out;\n}\n\n/**\n * Split a living spec around its requirements RUN — the stretch of\n * `### Requirement:` blocks inside the `## Requirements` section — so a merge\n * can rewrite exactly that and nothing else. All three slices reassemble the\n * input byte-for-byte (`head + run + tail === text`):\n *\n * - `head` — everything before the first requirement in the section: the\n * intro, the heading line itself, any prose under the heading.\n * - `run` — from the first `### Requirement:` line to the section's end (the\n * next `## ` heading, or EOF). Empty when the section holds no requirements.\n * - `tail` — everything from the section's end onward.\n *\n * `requirements` is the run cut again at every `### Requirement:` heading —\n * one raw slice per requirement, from its heading up to the next one (or the\n * run's end), so `requirements.join(\"\") === run`. A slice therefore carries\n * whatever the author wrote below the requirement before the next heading,\n * blank lines included, which is exactly the text parseRequirements attributes\n * to that requirement. It exists so archive can keep the bytes of every\n * requirement a delta did not touch instead of re-serializing the whole run:\n * one ADDED requirement used to reflow every untouched requirement written\n * without a blank line under its heading, and every one of those moves landed\n * under the document's vouch stamp.\n *\n * Returns null when the document has no `## Requirements` heading at all.\n * Only the FIRST matching heading opens the section; a caller that must not\n * lose content behind a duplicate (archive) counts matches via\n * sectionHeadings() and refuses. Heading detection matches parseRequirements:\n * fenced lines are never structure, and a leading BOM hides no heading — but\n * the slices themselves are raw bytes, BOM and CRLF included.\n */\nexport function splitRequirementsSection(\n text: string,\n): { head: string; run: string; tail: string; requirements: string[] } | null {\n const fenced = fenceTracker();\n let inSection = false;\n let sectionStart = -1;\n const starts: number[] = [];\n let sectionEnd = text.length;\n let offset = 0;\n while (offset < text.length) {\n const nl = text.indexOf(\"\\n\", offset);\n const lineEnd = nl === -1 ? text.length : nl + 1;\n let line = text.slice(offset, nl === -1 ? text.length : nl);\n if (line.endsWith(\"\\r\")) line = line.slice(0, -1);\n // Position 0 only, mirroring stripBom: elsewhere U+FEFF is content.\n if (offset === 0 && line.charCodeAt(0) === 0xfeff) line = line.slice(1);\n if (!fenced(line)) {\n if (/^##\\s+/.test(line) && !line.startsWith(\"###\")) {\n if (inSection) {\n sectionEnd = offset;\n inSection = false;\n } else if (sectionStart === -1 && isRequirementsHeading(line)) {\n sectionStart = offset;\n inSection = true;\n }\n } else if (inSection && REQ_RE.test(line)) {\n starts.push(offset);\n }\n }\n offset = lineEnd;\n }\n if (sectionStart === -1) return null;\n const cut = starts[0] ?? sectionEnd;\n return {\n head: text.slice(0, cut),\n run: text.slice(cut, sectionEnd),\n tail: text.slice(sectionEnd),\n requirements: starts.map((at, i) => text.slice(at, starts[i + 1] ?? sectionEnd)),\n };\n}\n\n/**\n * A requirement document from disk as text — decoded, or refused by name.\n *\n * The read that belongs with the parser, because `readFile(path, \"utf8\")` and\n * `parseRequirements` together are a trap: a UTF-16 spec.md decodes to a string\n * in which no line matches `^###\\s+Requirement:`, so the parser returns [] and\n * the document grades as an empty baseline instead of an unreadable one. Every\n * question loam asks of a spec — is it covered, does the delta merge, what does\n * the C4 spine touch — is then answered about a file nobody read.\n *\n * It THROWS (`NotUtf8DocumentError`, which names the path), unlike\n * `readFrontmatter` next door, because the two failures are not the same\n * failure. Frontmatter is read by the fleet enumeration, where one bad file\n * must not cost the other 119 services, so there it is a flag. A requirement\n * document is read by ONE target, and the caller is the only one who knows what\n * to do about it: a read-only command turns it into a finding on that target\n * (validate's `guarded`, which names the file and keeps grading the rest), a\n * command that writes refuses outright rather than computing over mojibake.\n */\nexport async function readRequirementsDocument(path: string): Promise<string> {\n return decodeDocument(await readFile(path), path);\n}\n\n/** Parse all requirements (with their scenarios and delta kind) from a markdown doc. */\nexport function parseRequirements(md: string): Requirement[] {\n const out: Requirement[] = [];\n let kind: DeltaKind = \"BASE\";\n let section: string | undefined;\n let req: Requirement | null = null;\n let scn: Scenario | null = null;\n const fenced = fenceTracker();\n\n for (const [index, line] of stripBom(md).split(/\\r?\\n/).entries()) {\n if (fenced(line)) {\n // Fenced content, marker included: body of whatever is open, never structure.\n if (scn) scn.lines.push(line);\n else if (req) req.text.push(line);\n continue;\n }\n // Any H2 heading ends the current requirement/scenario capture — section prose\n // must not leak into the previous scenario's body.\n if (/^##\\s+/.test(line) && !line.startsWith(\"###\")) {\n req = null;\n scn = null;\n section = line.trim();\n const mk = KIND_RE.exec(line);\n // A non-delta H2 (## Notes, ## Requirements…) starts an unrelated section:\n // requirements under it are plain BASE, not part of a stale delta section.\n kind = mk ? (mk[1]!.toUpperCase() as DeltaKind) : \"BASE\";\n continue;\n }\n const mr = REQ_RE.exec(line);\n if (mr) {\n req = {\n kind,\n name: mr[1]!,\n text: [],\n operations: [],\n covers: [],\n publishes: [],\n consumes: [],\n requires: [],\n capabilities: [],\n realizes: [],\n scenarios: [],\n section,\n line: index + 1,\n };\n out.push(req);\n scn = null;\n continue;\n }\n const ms = SCN_RE.exec(line);\n if (ms && req) {\n // `index + 1` is the heading's own 1-based line, exactly as the\n // requirement capture above records its `### Requirement:` — body line\n // `lines[i]` then sits at `line + 1 + i`, because the capture below is\n // contiguous from here to the next heading. Purely additive: nothing in\n // `serializeRequirements` reads it, so `requirementDigest` cannot see it\n // and no `Based-On:` pin in any living document moves because the parser\n // learned where a scenario starts.\n scn = { name: ms[1]!, lines: [], line: index + 1 };\n req.scenarios.push(scn);\n continue;\n }\n if (scn) {\n scn.lines.push(line);\n } else if (req) {\n req.text.push(line);\n const mi = REQUIREMENT_ID_LINE_RE.exec(line);\n if (mi) req.id = mi[1]!.trim();\n // Same keep-last quirk as Operations:/Covers: below — a repeated line is\n // a document problem, reported as one (`delta.baseline-invalid`), never\n // resolved differently by whoever happens to be reading.\n const mb = BASED_ON_LINE_RE.exec(line);\n if (mb) req.basedOn = mb[1]!.trim();\n const mo = /^\\s*Operations?:\\s*(.+?)\\s*$/i.exec(line);\n if (mo) req.operations = mo[1]!.split(\",\").map((s) => s.trim()).filter((s) => s.length > 0);\n // The Covers: mirror — same placement (requirement body, not a scenario),\n // same comma grammar, and deliberately the same quirk: a second line\n // REPLACES the first (assignment, not append), so the two lists can never\n // drift apart in how they read a repeated line.\n const mc = /^\\s*Covers?:\\s*(.+?)\\s*$/i.exec(line);\n if (mc) req.covers = mc[1]!.split(\",\").map((s) => s.trim()).filter((s) => s.length > 0);\n // The event axis, same grammar and the same keep-last quirk again. Note\n // what is NOT happening here: the line stays in `req.text` like every\n // other body line (the push above is unconditional), so it round-trips\n // through `serializeRequirements` and rides inside `requirementDigest`\n // exactly as `Operations:` does. That is what makes this parse purely\n // additive — no living document's digest moves, and no `Based-On:` pin\n // goes stale because loam learned to read one more line.\n const mp = /^\\s*Publishes?:\\s*(.+?)\\s*$/i.exec(line);\n if (mp) req.publishes = mp[1]!.split(\",\").map((s) => s.trim()).filter((s) => s.length > 0);\n const mcon = /^\\s*Consumes?:\\s*(.+?)\\s*$/i.exec(line);\n if (mcon) req.consumes = mcon[1]!.split(\",\").map((s) => s.trim()).filter((s) => s.length > 0);\n // The authorization axis. Same grammar, same keep-last quirk, same purely\n // additive parse — the line rides in `req.text` and therefore inside\n // `requirementDigest`, so no living document moves because loam learned\n // to read it.\n const mreq = /^\\s*Requires?:\\s*(.+?)\\s*$/i.exec(line);\n if (mreq) req.requires = mreq[1]!.split(\",\").map((s) => s.trim()).filter((s) => s.length > 0);\n // The capability axis. Same grammar, same keep-last quirk, same purely\n // additive parse as Requires: above — but note the OPT-IN differs: the\n // vocabulary FILE (architecture/capabilities.yaml) is the opt-in for this\n // axis, not the line, so entries parsed here grade as nothing at all\n // until a fleet writes that file (core/capabilities/findings.ts).\n const mcap = CAPABILITY_LINE_RE.exec(line);\n if (mcap) req.capabilities = mcap[1]!.split(\",\").map((s) => s.trim()).filter((s) => s.length > 0);\n // The join INTO the authored business tree: `<capability-id>#<Requirement-ID>`\n // entries, same comma grammar and same keep-last quirk as every line\n // above. Split into its two halves nowhere near here —\n // `core/capabilities/realizes/join.ts` owns that, because the rollup and\n // the grades must not be able to disagree about where the separator is.\n const mrl = REALIZES_LINE_RE.exec(line);\n if (mrl) req.realizes = mrl[1]!.split(\",\").map((s) => s.trim()).filter((s) => s.length > 0);\n }\n }\n\n return out;\n}\n"]}
@@ -0,0 +1,238 @@
1
+ /**
2
+ * What a requirement's scenarios are MISSING, and where they contradict
3
+ * themselves — the coverage and shape questions `validate` asks of every spec.
4
+ *
5
+ * Separate from `./parse.ts` because these grade a parsed document rather than
6
+ * produce one, and separate from `./spec.ts` because they answer to
7
+ * `vocabulary/report.ts`: a stepless scenario is a Finding with a subject and a
8
+ * label, and that shape belongs to the report, not to the requirement.
9
+ */
10
+ import { scenarioGherkin } from "../vocabulary/steps.js";
11
+ import {} from "./spec.js";
12
+ /** Requirements with no scenario — the OpenSpec coverage rule (every requirement needs ≥1). */
13
+ export function requirementsMissingScenarios(reqs) {
14
+ return reqs.filter((r) => r.kind !== "REMOVED" && r.scenarios.length === 0);
15
+ }
16
+ /**
17
+ * `requirements.missing-scenarios` over the requirements the rule above
18
+ * returned — one spelling for `loam validate` (its `coverageFinding`) and
19
+ * `loam status` (`core/status/feature/feature.ts`), because status's rule is
20
+ * "never greener than the gates" and a second spelling of the same finding is
21
+ * how the two would come to disagree. `subject` names the service when the
22
+ * caller has one.
23
+ */
24
+ export function missingScenariosFinding(label, bare, subject) {
25
+ return {
26
+ severity: "error",
27
+ code: "requirements.missing-scenarios",
28
+ ...(subject === undefined ? {} : { subject }),
29
+ message: `${label}: ${bare.length} requirement(s) without a scenario`,
30
+ details: bare.map((r) => r.name),
31
+ };
32
+ }
33
+ /**
34
+ * Scenarios that satisfy the coverage rule above and test nothing.
35
+ *
36
+ * `requirementsMissingScenarios` counts HEADINGS, so a `#### Scenario:` with no
37
+ * recognizable Given/When/Then line satisfied the fleet gate's coverage claim
38
+ * outright — and it is not a hypothetical shape: it is what `loam new`
39
+ * scaffolds and what an agent writes when it puts the criteria in prose.
40
+ * Downstream the same emptiness is fatal twice over: cucumber runs a stepless
41
+ * scenario vacuously green, and `loam verify --results` can never confirm it.
42
+ *
43
+ * The detector is `loam gherkin`'s own — `scenarioGherkin` decides what a step
44
+ * IS, and a second opinion here would mean the gate and the emitted suite could
45
+ * disagree about whether a scenario has any. That import is the one place these
46
+ * two modules are circular (gherkin.ts parses requirements); both sides export
47
+ * only function declarations, which are hoisted, so neither evaluation order
48
+ * can observe a half-built module.
49
+ */
50
+ export function steplessScenarios(reqs) {
51
+ const out = [];
52
+ for (const r of reqs) {
53
+ if (r.kind === "REMOVED")
54
+ continue;
55
+ for (const s of r.scenarios) {
56
+ if (scenarioGherkin(s.lines).steps.length === 0)
57
+ out.push({ requirement: r.name, scenario: s.name });
58
+ }
59
+ }
60
+ return out;
61
+ }
62
+ /**
63
+ * The stepless half of the coverage check, as findings — the missing-scenario
64
+ * half stays where it is (`requirementsMissingScenarios`), because the two are
65
+ * different states with different fixes: one requirement owes acceptance
66
+ * criteria, the other owes STEPS in criteria somebody has already written.
67
+ *
68
+ * `label` is the coverage check's own label (`payment-service: requirements`),
69
+ * so both halves of one document name it the same way.
70
+ */
71
+ export function steplessFindings(label, subject, reqs) {
72
+ const bare = steplessScenarios(reqs);
73
+ if (bare.length === 0)
74
+ return [];
75
+ return [
76
+ {
77
+ severity: "error",
78
+ code: "requirements.stepless-scenario",
79
+ subject,
80
+ message: `${label}: ${bare.length} scenario(s) have a heading and no recognizable steps — ` +
81
+ `they satisfy the coverage rule and test nothing. Cucumber runs a stepless scenario vacuously green and ` +
82
+ `\`loam verify --results\` can never confirm it. Write the body as \`- **Given/When/Then**\` bullets.`,
83
+ details: bare.map((s) => `${s.requirement} — ${s.scenario}`),
84
+ text: { detailPrefix: "- " },
85
+ },
86
+ ];
87
+ }
88
+ /**
89
+ * Scenarios that have steps and assert NOTHING — a body of Given and When with
90
+ * no Then anywhere in it.
91
+ *
92
+ * The third state, and the one that survives both checks above: the requirement
93
+ * has a scenario, the scenario has steps, and the run can only ever confirm that
94
+ * the arrangement did not throw. `And`/`But` are continuations, so their meaning
95
+ * is decided by the keyword they follow — with no `Then` in the body there is
96
+ * nothing for them to continue but the setup.
97
+ *
98
+ * It matters more the more evidence rests on the suite. A stepless scenario is
99
+ * at least visible as an empty body; this one reads like a real test, emits real
100
+ * steps, runs green, and answers a `scenario.tested` claim to the same standard
101
+ * as a scenario that checks twenty things. Under a runner-neutral answer sheet —
102
+ * one `{digest, status}` entry, no steps to count — this document-side check is
103
+ * the only thing left that can tell the two apart.
104
+ */
105
+ export function assertionlessScenarios(reqs) {
106
+ const out = [];
107
+ for (const r of reqs) {
108
+ if (r.kind === "REMOVED")
109
+ continue;
110
+ for (const s of r.scenarios) {
111
+ const { steps } = scenarioGherkin(s.lines);
112
+ // Disjoint from stepless by construction: a body with no steps at all is
113
+ // that finding's, and reporting one scenario under both codes would offer
114
+ // two fixes for one defect.
115
+ if (steps.length > 0 && !steps.some((st) => /^Then\b/.test(st.text))) {
116
+ out.push({ requirement: r.name, scenario: s.name });
117
+ }
118
+ }
119
+ }
120
+ return out;
121
+ }
122
+ const PLACEHOLDER_RE = /<([^<>\s]+)>/g;
123
+ /**
124
+ * Every `<placeholder>` a scenario's steps reach for, arguments included.
125
+ *
126
+ * Docstrings and data tables are scanned too because cucumber substitutes into
127
+ * them: `<fee>` inside a request payload is a real reference, and a check that
128
+ * read only the step lines would call its column unreferenced and invite the
129
+ * author to delete the column the payload depends on.
130
+ */
131
+ function placeholdersUsed(steps) {
132
+ const used = new Set();
133
+ const scan = (text) => {
134
+ for (const m of text.matchAll(PLACEHOLDER_RE))
135
+ used.add(m[1]);
136
+ };
137
+ for (const st of steps) {
138
+ scan(st.text);
139
+ for (const l of st.docstring?.lines ?? [])
140
+ scan(l);
141
+ for (const row of st.table ?? [])
142
+ for (const cell of row)
143
+ scan(cell);
144
+ }
145
+ return used;
146
+ }
147
+ /**
148
+ * Scenarios whose `Examples` header and `<placeholders>` disagree.
149
+ *
150
+ * Only scenarios that HAVE an Examples table are considered, and that scoping is
151
+ * load-bearing twice over: a plain scenario's `<angle brackets>` are prose (a
152
+ * generic, a placeholder in a URL template, loam's own scaffold sentinels), and
153
+ * a fleet that never writes an outline must never earn a finding from this.
154
+ *
155
+ * The two halves are different defects. An UNBOUND placeholder is an error the
156
+ * runner cannot repair: cucumber substitutes nothing, so the step definition
157
+ * receives the literal text `<fee>` and either fails obscurely or — worse —
158
+ * matches and asserts against a string nobody meant. An UNREFERENCED column is a
159
+ * warning, because it is usually the fossil of a rename: the column still lists
160
+ * six cases, the step that used it now names something else, and the outline
161
+ * runs six identical passes that read as six cases of coverage.
162
+ */
163
+ export function examplesMismatches(reqs) {
164
+ const out = [];
165
+ for (const r of reqs) {
166
+ if (r.kind === "REMOVED")
167
+ continue;
168
+ for (const s of r.scenarios) {
169
+ const { steps, examples } = scenarioGherkin(s.lines);
170
+ if (examples === null)
171
+ continue;
172
+ const used = placeholdersUsed(steps);
173
+ const columns = new Set(examples.header);
174
+ const unbound = [...used].filter((p) => !columns.has(p)).sort();
175
+ const unreferenced = examples.header.filter((c) => !used.has(c));
176
+ if (unbound.length > 0 || unreferenced.length > 0) {
177
+ out.push({ requirement: r.name, scenario: s.name, unbound, unreferenced });
178
+ }
179
+ }
180
+ }
181
+ return out;
182
+ }
183
+ /**
184
+ * The Examples half, as findings — two codes rather than one with two
185
+ * severities, because a machine cannot branch on a severity that depends on the
186
+ * case, and the fixes differ: one adds a column, the other removes one or
187
+ * restores the reference that used to use it.
188
+ */
189
+ export function examplesFindings(label, subject, reqs) {
190
+ const all = examplesMismatches(reqs);
191
+ const findings = [];
192
+ const unbound = all.filter((m) => m.unbound.length > 0);
193
+ if (unbound.length > 0) {
194
+ findings.push({
195
+ severity: "error",
196
+ code: "requirements.examples-unbound",
197
+ subject,
198
+ message: `${label}: ${unbound.length} scenario(s) use a \`<placeholder>\` no \`Examples\` column supplies — ` +
199
+ `cucumber substitutes nothing, so the step receives the literal angle-bracket text. ` +
200
+ `Add the column, or correct the placeholder to one the header names.`,
201
+ details: unbound.map((m) => `${m.requirement} — ${m.scenario}: ${m.unbound.map((p) => `<${p}>`).join(", ")}`),
202
+ text: { detailPrefix: "- " },
203
+ });
204
+ }
205
+ const dead = all.filter((m) => m.unreferenced.length > 0);
206
+ if (dead.length > 0) {
207
+ findings.push({
208
+ severity: "warn",
209
+ code: "requirements.examples-unreferenced",
210
+ subject,
211
+ message: `${label}: ${dead.length} scenario(s) declare an \`Examples\` column no step refers to — ` +
212
+ `usually the fossil of a rename, and the outline then runs its rows as identical passes that read as cases. ` +
213
+ `Reference the column from a step, or drop it.`,
214
+ details: dead.map((m) => `${m.requirement} — ${m.scenario}: ${m.unreferenced.join(", ")}`),
215
+ text: { detailPrefix: "- " },
216
+ });
217
+ }
218
+ return findings;
219
+ }
220
+ /** The assertionless half, as findings — same label and subject as its two siblings. */
221
+ export function assertionlessFindings(label, subject, reqs) {
222
+ const mute = assertionlessScenarios(reqs);
223
+ if (mute.length === 0)
224
+ return [];
225
+ return [
226
+ {
227
+ severity: "error",
228
+ code: "requirements.assertionless-scenario",
229
+ subject,
230
+ message: `${label}: ${mute.length} scenario(s) have steps and no \`Then\` — ` +
231
+ `they arrange and act, and assert nothing. The run confirms only that the setup did not throw, ` +
232
+ `and the claim it answers is confirmed on that. Add the \`- **Then**\` the scenario was written for.`,
233
+ details: mute.map((s) => `${s.requirement} — ${s.scenario}`),
234
+ text: { detailPrefix: "- " },
235
+ },
236
+ ];
237
+ }
238
+ //# sourceMappingURL=scenarios.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scenarios.js","sourceRoot":"","sources":["../../../src/core/document/scenarios.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * What a requirement's scenarios are MISSING, and where they contradict\n * themselves — the coverage and shape questions `validate` asks of every spec.\n *\n * Separate from `./parse.ts` because these grade a parsed document rather than\n * produce one, and separate from `./spec.ts` because they answer to\n * `vocabulary/report.ts`: a stepless scenario is a Finding with a subject and a\n * label, and that shape belongs to the report, not to the requirement.\n */\nimport { scenarioGherkin, type EmittedStep } from \"../vocabulary/steps.js\";\nimport type { Finding } from \"../vocabulary/report.js\";\nimport { type Requirement } from \"./spec.js\";\n\n/** Requirements with no scenario — the OpenSpec coverage rule (every requirement needs ≥1). */\nexport function requirementsMissingScenarios(reqs: Requirement[]): Requirement[] {\n return reqs.filter((r) => r.kind !== \"REMOVED\" && r.scenarios.length === 0);\n}\n\n/**\n * `requirements.missing-scenarios` over the requirements the rule above\n * returned — one spelling for `loam validate` (its `coverageFinding`) and\n * `loam status` (`core/status/feature/feature.ts`), because status's rule is\n * \"never greener than the gates\" and a second spelling of the same finding is\n * how the two would come to disagree. `subject` names the service when the\n * caller has one.\n */\nexport function missingScenariosFinding(label: string, bare: readonly Requirement[], subject?: string): Finding {\n return {\n severity: \"error\",\n code: \"requirements.missing-scenarios\",\n ...(subject === undefined ? {} : { subject }),\n message: `${label}: ${bare.length} requirement(s) without a scenario`,\n details: bare.map((r) => r.name),\n };\n}\n\n/** A `#### Scenario:` heading whose body holds nothing a runner would execute. */\nexport interface SteplessScenario {\n requirement: string;\n scenario: string;\n}\n\n/**\n * Scenarios that satisfy the coverage rule above and test nothing.\n *\n * `requirementsMissingScenarios` counts HEADINGS, so a `#### Scenario:` with no\n * recognizable Given/When/Then line satisfied the fleet gate's coverage claim\n * outright — and it is not a hypothetical shape: it is what `loam new`\n * scaffolds and what an agent writes when it puts the criteria in prose.\n * Downstream the same emptiness is fatal twice over: cucumber runs a stepless\n * scenario vacuously green, and `loam verify --results` can never confirm it.\n *\n * The detector is `loam gherkin`'s own — `scenarioGherkin` decides what a step\n * IS, and a second opinion here would mean the gate and the emitted suite could\n * disagree about whether a scenario has any. That import is the one place these\n * two modules are circular (gherkin.ts parses requirements); both sides export\n * only function declarations, which are hoisted, so neither evaluation order\n * can observe a half-built module.\n */\nexport function steplessScenarios(reqs: Requirement[]): SteplessScenario[] {\n const out: SteplessScenario[] = [];\n for (const r of reqs) {\n if (r.kind === \"REMOVED\") continue;\n for (const s of r.scenarios) {\n if (scenarioGherkin(s.lines).steps.length === 0) out.push({ requirement: r.name, scenario: s.name });\n }\n }\n return out;\n}\n\n/**\n * The stepless half of the coverage check, as findings — the missing-scenario\n * half stays where it is (`requirementsMissingScenarios`), because the two are\n * different states with different fixes: one requirement owes acceptance\n * criteria, the other owes STEPS in criteria somebody has already written.\n *\n * `label` is the coverage check's own label (`payment-service: requirements`),\n * so both halves of one document name it the same way.\n */\nexport function steplessFindings(label: string, subject: string, reqs: Requirement[]): Finding[] {\n const bare = steplessScenarios(reqs);\n if (bare.length === 0) return [];\n return [\n {\n severity: \"error\",\n code: \"requirements.stepless-scenario\",\n subject,\n message:\n `${label}: ${bare.length} scenario(s) have a heading and no recognizable steps — ` +\n `they satisfy the coverage rule and test nothing. Cucumber runs a stepless scenario vacuously green and ` +\n `\\`loam verify --results\\` can never confirm it. Write the body as \\`- **Given/When/Then**\\` bullets.`,\n details: bare.map((s) => `${s.requirement} — ${s.scenario}`),\n text: { detailPrefix: \"- \" },\n },\n ];\n}\n\n/**\n * Scenarios that have steps and assert NOTHING — a body of Given and When with\n * no Then anywhere in it.\n *\n * The third state, and the one that survives both checks above: the requirement\n * has a scenario, the scenario has steps, and the run can only ever confirm that\n * the arrangement did not throw. `And`/`But` are continuations, so their meaning\n * is decided by the keyword they follow — with no `Then` in the body there is\n * nothing for them to continue but the setup.\n *\n * It matters more the more evidence rests on the suite. A stepless scenario is\n * at least visible as an empty body; this one reads like a real test, emits real\n * steps, runs green, and answers a `scenario.tested` claim to the same standard\n * as a scenario that checks twenty things. Under a runner-neutral answer sheet —\n * one `{digest, status}` entry, no steps to count — this document-side check is\n * the only thing left that can tell the two apart.\n */\nexport function assertionlessScenarios(reqs: Requirement[]): SteplessScenario[] {\n const out: SteplessScenario[] = [];\n for (const r of reqs) {\n if (r.kind === \"REMOVED\") continue;\n for (const s of r.scenarios) {\n const { steps } = scenarioGherkin(s.lines);\n // Disjoint from stepless by construction: a body with no steps at all is\n // that finding's, and reporting one scenario under both codes would offer\n // two fixes for one defect.\n if (steps.length > 0 && !steps.some((st) => /^Then\\b/.test(st.text))) {\n out.push({ requirement: r.name, scenario: s.name });\n }\n }\n }\n return out;\n}\n\n/** One scenario's disagreement between its `Examples` columns and its `<placeholders>`. */\nexport interface ExamplesMismatch {\n requirement: string;\n scenario: string;\n /** `<placeholders>` a step uses that no column supplies. */\n unbound: string[];\n /** Columns no step, docstring or data-table cell refers to. */\n unreferenced: string[];\n}\n\nconst PLACEHOLDER_RE = /<([^<>\\s]+)>/g;\n\n/**\n * Every `<placeholder>` a scenario's steps reach for, arguments included.\n *\n * Docstrings and data tables are scanned too because cucumber substitutes into\n * them: `<fee>` inside a request payload is a real reference, and a check that\n * read only the step lines would call its column unreferenced and invite the\n * author to delete the column the payload depends on.\n */\nfunction placeholdersUsed(steps: EmittedStep[]): Set<string> {\n const used = new Set<string>();\n const scan = (text: string): void => {\n for (const m of text.matchAll(PLACEHOLDER_RE)) used.add(m[1]!);\n };\n for (const st of steps) {\n scan(st.text);\n for (const l of st.docstring?.lines ?? []) scan(l);\n for (const row of st.table ?? []) for (const cell of row) scan(cell);\n }\n return used;\n}\n\n/**\n * Scenarios whose `Examples` header and `<placeholders>` disagree.\n *\n * Only scenarios that HAVE an Examples table are considered, and that scoping is\n * load-bearing twice over: a plain scenario's `<angle brackets>` are prose (a\n * generic, a placeholder in a URL template, loam's own scaffold sentinels), and\n * a fleet that never writes an outline must never earn a finding from this.\n *\n * The two halves are different defects. An UNBOUND placeholder is an error the\n * runner cannot repair: cucumber substitutes nothing, so the step definition\n * receives the literal text `<fee>` and either fails obscurely or — worse —\n * matches and asserts against a string nobody meant. An UNREFERENCED column is a\n * warning, because it is usually the fossil of a rename: the column still lists\n * six cases, the step that used it now names something else, and the outline\n * runs six identical passes that read as six cases of coverage.\n */\nexport function examplesMismatches(reqs: Requirement[]): ExamplesMismatch[] {\n const out: ExamplesMismatch[] = [];\n for (const r of reqs) {\n if (r.kind === \"REMOVED\") continue;\n for (const s of r.scenarios) {\n const { steps, examples } = scenarioGherkin(s.lines);\n if (examples === null) continue;\n const used = placeholdersUsed(steps);\n const columns = new Set(examples.header);\n const unbound = [...used].filter((p) => !columns.has(p)).sort();\n const unreferenced = examples.header.filter((c) => !used.has(c));\n if (unbound.length > 0 || unreferenced.length > 0) {\n out.push({ requirement: r.name, scenario: s.name, unbound, unreferenced });\n }\n }\n }\n return out;\n}\n\n/**\n * The Examples half, as findings — two codes rather than one with two\n * severities, because a machine cannot branch on a severity that depends on the\n * case, and the fixes differ: one adds a column, the other removes one or\n * restores the reference that used to use it.\n */\nexport function examplesFindings(label: string, subject: string, reqs: Requirement[]): Finding[] {\n const all = examplesMismatches(reqs);\n const findings: Finding[] = [];\n const unbound = all.filter((m) => m.unbound.length > 0);\n if (unbound.length > 0) {\n findings.push({\n severity: \"error\",\n code: \"requirements.examples-unbound\",\n subject,\n message:\n `${label}: ${unbound.length} scenario(s) use a \\`<placeholder>\\` no \\`Examples\\` column supplies — ` +\n `cucumber substitutes nothing, so the step receives the literal angle-bracket text. ` +\n `Add the column, or correct the placeholder to one the header names.`,\n details: unbound.map((m) => `${m.requirement} — ${m.scenario}: ${m.unbound.map((p) => `<${p}>`).join(\", \")}`),\n text: { detailPrefix: \"- \" },\n });\n }\n const dead = all.filter((m) => m.unreferenced.length > 0);\n if (dead.length > 0) {\n findings.push({\n severity: \"warn\",\n code: \"requirements.examples-unreferenced\",\n subject,\n message:\n `${label}: ${dead.length} scenario(s) declare an \\`Examples\\` column no step refers to — ` +\n `usually the fossil of a rename, and the outline then runs its rows as identical passes that read as cases. ` +\n `Reference the column from a step, or drop it.`,\n details: dead.map((m) => `${m.requirement} — ${m.scenario}: ${m.unreferenced.join(\", \")}`),\n text: { detailPrefix: \"- \" },\n });\n }\n return findings;\n}\n\n/** The assertionless half, as findings — same label and subject as its two siblings. */\nexport function assertionlessFindings(label: string, subject: string, reqs: Requirement[]): Finding[] {\n const mute = assertionlessScenarios(reqs);\n if (mute.length === 0) return [];\n return [\n {\n severity: \"error\",\n code: \"requirements.assertionless-scenario\",\n subject,\n message:\n `${label}: ${mute.length} scenario(s) have steps and no \\`Then\\` — ` +\n `they arrange and act, and assert nothing. The run confirms only that the setup did not throw, ` +\n `and the claim it answers is confirmed on that. Add the \\`- **Then**\\` the scenario was written for.`,\n details: mute.map((s) => `${s.requirement} — ${s.scenario}`),\n text: { detailPrefix: \"- \" },\n },\n ];\n}\n"]}