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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1256) hide show
  1. package/CHANGELOG.md +5992 -82
  2. package/COMPARISON.md +168 -63
  3. package/CONTRIBUTING.md +121 -0
  4. package/MIGRATING-from-OpenSpec.md +238 -55
  5. package/QUICKSTART.md +302 -0
  6. package/README.md +653 -144
  7. package/ROADMAP.md +1035 -0
  8. package/SCHEMA.md +3916 -263
  9. package/SECURITY.md +21 -3
  10. package/WORKFLOW.md +927 -0
  11. package/dist/cli.js +133 -21
  12. package/dist/cli.js.map +1 -1
  13. package/dist/commands/adopt/adopt.js +204 -0
  14. package/dist/commands/adopt/adopt.js.map +1 -0
  15. package/dist/commands/adopt/render.js +309 -0
  16. package/dist/commands/adopt/render.js.map +1 -0
  17. package/dist/commands/archive/archive.js +74 -0
  18. package/dist/commands/archive/archive.js.map +1 -0
  19. package/dist/commands/archive/closing.js +42 -0
  20. package/dist/commands/archive/closing.js.map +1 -0
  21. package/dist/commands/archive/plan/contracts/asyncapi.js +172 -0
  22. package/dist/commands/archive/plan/contracts/asyncapi.js.map +1 -0
  23. package/dist/commands/archive/plan/contracts/consumers.js +56 -0
  24. package/dist/commands/archive/plan/contracts/consumers.js.map +1 -0
  25. package/dist/commands/archive/plan/contracts/openapi.js +193 -0
  26. package/dist/commands/archive/plan/contracts/openapi.js.map +1 -0
  27. package/dist/commands/archive/plan/contracts/verdict-lines.js +103 -0
  28. package/dist/commands/archive/plan/contracts/verdict-lines.js.map +1 -0
  29. package/dist/commands/archive/plan/document/head.js +151 -0
  30. package/dist/commands/archive/plan/document/head.js.map +1 -0
  31. package/dist/commands/archive/plan/document/links.js +284 -0
  32. package/dist/commands/archive/plan/document/links.js.map +1 -0
  33. package/dist/commands/archive/plan/document/run.js +136 -0
  34. package/dist/commands/archive/plan/document/run.js.map +1 -0
  35. package/dist/commands/archive/plan/gate.js +319 -0
  36. package/dist/commands/archive/plan/gate.js.map +1 -0
  37. package/dist/commands/archive/plan/landscape.js +298 -0
  38. package/dist/commands/archive/plan/landscape.js.map +1 -0
  39. package/dist/commands/archive/plan/model/extending.js +85 -0
  40. package/dist/commands/archive/plan/model/extending.js.map +1 -0
  41. package/dist/commands/archive/plan/refusal.js +106 -0
  42. package/dist/commands/archive/plan/refusal.js.map +1 -0
  43. package/dist/commands/archive/plan/specs.js +318 -0
  44. package/dist/commands/archive/plan/specs.js.map +1 -0
  45. package/dist/commands/archive/plan/state.js +30 -0
  46. package/dist/commands/archive/plan/state.js.map +1 -0
  47. package/dist/commands/archive/run.js +355 -0
  48. package/dist/commands/archive/run.js.map +1 -0
  49. package/dist/commands/archive/shipped.js +49 -0
  50. package/dist/commands/archive/shipped.js.map +1 -0
  51. package/dist/commands/context/context.js +166 -0
  52. package/dist/commands/context/context.js.map +1 -0
  53. package/dist/commands/context/print.js +305 -0
  54. package/dist/commands/context/print.js.map +1 -0
  55. package/dist/commands/delta/delta.js +367 -0
  56. package/dist/commands/delta/delta.js.map +1 -0
  57. package/dist/commands/delta/print.js +221 -0
  58. package/dist/commands/delta/print.js.map +1 -0
  59. package/dist/commands/dependencies.js +6 -8
  60. package/dist/commands/dependencies.js.map +1 -1
  61. package/dist/commands/diff/diff.js +86 -0
  62. package/dist/commands/diff/diff.js.map +1 -0
  63. package/dist/commands/diff/print.js +38 -0
  64. package/dist/commands/diff/print.js.map +1 -0
  65. package/dist/commands/doctor.js +65 -5
  66. package/dist/commands/doctor.js.map +1 -1
  67. package/dist/commands/explain/explain.js +227 -0
  68. package/dist/commands/explain/explain.js.map +1 -0
  69. package/dist/commands/explore.js +39 -28
  70. package/dist/commands/explore.js.map +1 -1
  71. package/dist/commands/gate/gate.js +152 -0
  72. package/dist/commands/gate/gate.js.map +1 -0
  73. package/dist/commands/gate/print.js +66 -0
  74. package/dist/commands/gate/print.js.map +1 -0
  75. package/dist/commands/gherkin/commit.js +105 -0
  76. package/dist/commands/gherkin/commit.js.map +1 -0
  77. package/dist/commands/gherkin/gherkin.js +262 -0
  78. package/dist/commands/gherkin/gherkin.js.map +1 -0
  79. package/dist/commands/gherkin/reconcile.js +146 -0
  80. package/dist/commands/gherkin/reconcile.js.map +1 -0
  81. package/dist/commands/gherkin/render.js +77 -0
  82. package/dist/commands/gherkin/render.js.map +1 -0
  83. package/dist/commands/init/example.js +204 -0
  84. package/dist/commands/init/example.js.map +1 -0
  85. package/dist/commands/init/first-hour.js +72 -0
  86. package/dist/commands/init/first-hour.js.map +1 -0
  87. package/dist/commands/{init.js → init/init.js} +142 -71
  88. package/dist/commands/init/init.js.map +1 -0
  89. package/dist/commands/init/mcp.js +131 -0
  90. package/dist/commands/init/mcp.js.map +1 -0
  91. package/dist/commands/init/options.js +78 -0
  92. package/dist/commands/init/options.js.map +1 -0
  93. package/dist/commands/instructions.js +72 -14
  94. package/dist/commands/instructions.js.map +1 -1
  95. package/dist/commands/list/campaign/campaign.js +63 -0
  96. package/dist/commands/list/campaign/campaign.js.map +1 -0
  97. package/dist/commands/list/campaign/owners.js +65 -0
  98. package/dist/commands/list/campaign/owners.js.map +1 -0
  99. package/dist/commands/list/json.js +155 -0
  100. package/dist/commands/list/json.js.map +1 -0
  101. package/dist/commands/list/list.js +358 -0
  102. package/dist/commands/list/list.js.map +1 -0
  103. package/dist/commands/list/print.js +344 -0
  104. package/dist/commands/list/print.js.map +1 -0
  105. package/dist/commands/list/review.js +120 -0
  106. package/dist/commands/list/review.js.map +1 -0
  107. package/dist/commands/list/suites/suites.js +140 -0
  108. package/dist/commands/list/suites/suites.js.map +1 -0
  109. package/dist/commands/list/views.js +108 -0
  110. package/dist/commands/list/views.js.map +1 -0
  111. package/dist/commands/mcp/dispatch.js +238 -0
  112. package/dist/commands/mcp/dispatch.js.map +1 -0
  113. package/dist/commands/mcp/mcp.js +75 -0
  114. package/dist/commands/mcp/mcp.js.map +1 -0
  115. package/dist/commands/mcp/serve.js +55 -0
  116. package/dist/commands/mcp/serve.js.map +1 -0
  117. package/dist/commands/migrate-openspec/materialize/active.js +175 -0
  118. package/dist/commands/migrate-openspec/materialize/active.js.map +1 -0
  119. package/dist/commands/migrate-openspec/materialize/feature.js +41 -0
  120. package/dist/commands/migrate-openspec/materialize/feature.js.map +1 -0
  121. package/dist/commands/migrate-openspec/materialize/living.js +62 -0
  122. package/dist/commands/migrate-openspec/materialize/living.js.map +1 -0
  123. package/dist/commands/migrate-openspec/materialize/stage.js +143 -0
  124. package/dist/commands/migrate-openspec/materialize/stage.js.map +1 -0
  125. package/dist/commands/migrate-openspec/materialize/target.js +219 -0
  126. package/dist/commands/migrate-openspec/materialize/target.js.map +1 -0
  127. package/dist/commands/migrate-openspec/migrate-openspec.js +142 -0
  128. package/dist/commands/migrate-openspec/migrate-openspec.js.map +1 -0
  129. package/dist/commands/migrate-openspec/openspec/decisions.js +86 -0
  130. package/dist/commands/migrate-openspec/openspec/decisions.js.map +1 -0
  131. package/dist/commands/migrate-openspec/openspec/error.js +18 -0
  132. package/dist/commands/migrate-openspec/openspec/error.js.map +1 -0
  133. package/dist/commands/migrate-openspec/openspec/mapping.js +162 -0
  134. package/dist/commands/migrate-openspec/openspec/mapping.js.map +1 -0
  135. package/dist/commands/migrate-openspec/openspec/paths.js +40 -0
  136. package/dist/commands/migrate-openspec/openspec/paths.js.map +1 -0
  137. package/dist/commands/migrate-openspec/openspec/read.js +49 -0
  138. package/dist/commands/migrate-openspec/openspec/read.js.map +1 -0
  139. package/dist/commands/migrate-openspec/print.js +89 -0
  140. package/dist/commands/migrate-openspec/print.js.map +1 -0
  141. package/dist/commands/new/capability-template.js +118 -0
  142. package/dist/commands/new/capability-template.js.map +1 -0
  143. package/dist/commands/new/commit.js +62 -0
  144. package/dist/commands/new/commit.js.map +1 -0
  145. package/dist/commands/new/modifies.js +206 -0
  146. package/dist/commands/new/modifies.js.map +1 -0
  147. package/dist/commands/new/new.js +328 -0
  148. package/dist/commands/new/new.js.map +1 -0
  149. package/dist/commands/new/templates.js +279 -0
  150. package/dist/commands/new/templates.js.map +1 -0
  151. package/dist/commands/open.js +199 -0
  152. package/dist/commands/open.js.map +1 -0
  153. package/dist/commands/policy/format.js +152 -0
  154. package/dist/commands/policy/format.js.map +1 -0
  155. package/dist/commands/{docs-repo-gate.js → policy/gate.js} +38 -11
  156. package/dist/commands/policy/gate.js.map +1 -0
  157. package/dist/commands/rebase/edit.js +106 -0
  158. package/dist/commands/rebase/edit.js.map +1 -0
  159. package/dist/commands/rebase/living.js +185 -0
  160. package/dist/commands/rebase/living.js.map +1 -0
  161. package/dist/commands/rebase/plan.js +245 -0
  162. package/dist/commands/rebase/plan.js.map +1 -0
  163. package/dist/commands/rebase/rebase.js +300 -0
  164. package/dist/commands/rebase/rebase.js.map +1 -0
  165. package/dist/commands/seed/commit.js +221 -0
  166. package/dist/commands/seed/commit.js.map +1 -0
  167. package/dist/commands/seed/plan.js +278 -0
  168. package/dist/commands/seed/plan.js.map +1 -0
  169. package/dist/commands/seed/seed.js +174 -0
  170. package/dist/commands/seed/seed.js.map +1 -0
  171. package/dist/commands/show/feature.js +182 -0
  172. package/dist/commands/show/feature.js.map +1 -0
  173. package/dist/commands/show/introduced.js +157 -0
  174. package/dist/commands/show/introduced.js.map +1 -0
  175. package/dist/commands/show/marks.js +53 -0
  176. package/dist/commands/show/marks.js.map +1 -0
  177. package/dist/commands/show/service.js +239 -0
  178. package/dist/commands/show/service.js.map +1 -0
  179. package/dist/commands/show/show.js +87 -0
  180. package/dist/commands/show/show.js.map +1 -0
  181. package/dist/commands/status/fleet-next.js +90 -0
  182. package/dist/commands/status/fleet-next.js.map +1 -0
  183. package/dist/commands/status/json.js +47 -0
  184. package/dist/commands/status/json.js.map +1 -0
  185. package/dist/commands/status/print.js +209 -0
  186. package/dist/commands/status/print.js.map +1 -0
  187. package/dist/commands/status/status.js +115 -0
  188. package/dist/commands/status/status.js.map +1 -0
  189. package/dist/commands/steps/steps.js +269 -0
  190. package/dist/commands/steps/steps.js.map +1 -0
  191. package/dist/commands/subsystem/edit.js +192 -0
  192. package/dist/commands/subsystem/edit.js.map +1 -0
  193. package/dist/commands/subsystem/move.js +325 -0
  194. package/dist/commands/subsystem/move.js.map +1 -0
  195. package/dist/commands/subsystem/query.js +113 -0
  196. package/dist/commands/subsystem/query.js.map +1 -0
  197. package/dist/commands/subsystem/subsystem.js +98 -0
  198. package/dist/commands/subsystem/subsystem.js.map +1 -0
  199. package/dist/commands/subsystem/sync.js +318 -0
  200. package/dist/commands/subsystem/sync.js.map +1 -0
  201. package/dist/commands/subsystem/txn/exclude.js +132 -0
  202. package/dist/commands/subsystem/txn/exclude.js.map +1 -0
  203. package/dist/commands/subsystem/txn/links.js +128 -0
  204. package/dist/commands/subsystem/txn/links.js.map +1 -0
  205. package/dist/commands/subsystem/txn/report.js +174 -0
  206. package/dist/commands/subsystem/txn/report.js.map +1 -0
  207. package/dist/commands/subsystem/txn/txn.js +196 -0
  208. package/dist/commands/subsystem/txn/txn.js.map +1 -0
  209. package/dist/commands/subsystem/txn/views.js +249 -0
  210. package/dist/commands/subsystem/txn/views.js.map +1 -0
  211. package/dist/commands/tasks/actions.js +107 -0
  212. package/dist/commands/tasks/actions.js.map +1 -0
  213. package/dist/commands/tasks/render.js +253 -0
  214. package/dist/commands/tasks/render.js.map +1 -0
  215. package/dist/commands/tasks/tasks.js +119 -0
  216. package/dist/commands/tasks/tasks.js.map +1 -0
  217. package/dist/commands/unarchive/manifest.js +176 -0
  218. package/dist/commands/unarchive/manifest.js.map +1 -0
  219. package/dist/commands/unarchive/restore.js +254 -0
  220. package/dist/commands/unarchive/restore.js.map +1 -0
  221. package/dist/commands/unarchive/unarchive.js +59 -0
  222. package/dist/commands/unarchive/unarchive.js.map +1 -0
  223. package/dist/commands/validate/arch-coverage.js +245 -0
  224. package/dist/commands/validate/arch-coverage.js.map +1 -0
  225. package/dist/commands/validate/checks/fleet-shape.js +204 -0
  226. package/dist/commands/validate/checks/fleet-shape.js.map +1 -0
  227. package/dist/commands/validate/checks/health-deps.js +58 -0
  228. package/dist/commands/validate/checks/health-deps.js.map +1 -0
  229. package/dist/commands/validate/checks/introduced.js +102 -0
  230. package/dist/commands/validate/checks/introduced.js.map +1 -0
  231. package/dist/commands/validate/checks/requirements.js +264 -0
  232. package/dist/commands/validate/checks/requirements.js.map +1 -0
  233. package/dist/commands/validate/checks/sources.js +85 -0
  234. package/dist/commands/validate/checks/sources.js.map +1 -0
  235. package/dist/commands/validate/coverage/covers-after.js +105 -0
  236. package/dist/commands/validate/coverage/covers-after.js.map +1 -0
  237. package/dist/commands/validate/feature.js +222 -0
  238. package/dist/commands/validate/feature.js.map +1 -0
  239. package/dist/commands/validate/fleet/census.js +93 -0
  240. package/dist/commands/validate/fleet/census.js.map +1 -0
  241. package/dist/commands/validate/fleet/kind-tags.js +39 -0
  242. package/dist/commands/validate/fleet/kind-tags.js.map +1 -0
  243. package/dist/commands/validate/fleet/landscape.js +371 -0
  244. package/dist/commands/validate/fleet/landscape.js.map +1 -0
  245. package/dist/commands/validate/fleet/load.js +118 -0
  246. package/dist/commands/validate/fleet/load.js.map +1 -0
  247. package/dist/commands/validate/fleet/map/attest.js +98 -0
  248. package/dist/commands/validate/fleet/map/attest.js.map +1 -0
  249. package/dist/commands/validate/fleet/map/bindings.js +107 -0
  250. package/dist/commands/validate/fleet/map/bindings.js.map +1 -0
  251. package/dist/commands/validate/fleet/map/consumers.js +244 -0
  252. package/dist/commands/validate/fleet/map/consumers.js.map +1 -0
  253. package/dist/commands/validate/fleet/map/isolation.js +116 -0
  254. package/dist/commands/validate/fleet/map/isolation.js.map +1 -0
  255. package/dist/commands/validate/fleet/map/usecases.js +54 -0
  256. package/dist/commands/validate/fleet/map/usecases.js.map +1 -0
  257. package/dist/commands/validate/fleet/obligations.js +266 -0
  258. package/dist/commands/validate/fleet/obligations.js.map +1 -0
  259. package/dist/commands/validate/fleet/scorecard/adoption.js +102 -0
  260. package/dist/commands/validate/fleet/scorecard/adoption.js.map +1 -0
  261. package/dist/commands/validate/fleet/scorecard/contracts.js +98 -0
  262. package/dist/commands/validate/fleet/scorecard/contracts.js.map +1 -0
  263. package/dist/commands/validate/fleet/scorecard/print.js +71 -0
  264. package/dist/commands/validate/fleet/scorecard/print.js.map +1 -0
  265. package/dist/commands/validate/fleet/scorecard/scorecard.js +162 -0
  266. package/dist/commands/validate/fleet/scorecard/scorecard.js.map +1 -0
  267. package/dist/commands/validate/fleet/usecases/place.js +13 -0
  268. package/dist/commands/validate/fleet/usecases/place.js.map +1 -0
  269. package/dist/commands/validate/fleet/views/fleet-project.js +217 -0
  270. package/dist/commands/validate/fleet/views/fleet-project.js.map +1 -0
  271. package/dist/commands/validate/fleet/views/ids.js +75 -0
  272. package/dist/commands/validate/fleet/views/ids.js.map +1 -0
  273. package/dist/commands/validate/fleet/views/projects.js +278 -0
  274. package/dist/commands/validate/fleet/views/projects.js.map +1 -0
  275. package/dist/commands/validate/fleet/views/root-documents.js +83 -0
  276. package/dist/commands/validate/fleet/views/root-documents.js.map +1 -0
  277. package/dist/commands/validate/fleet/views/stale.js +52 -0
  278. package/dist/commands/validate/fleet/views/stale.js.map +1 -0
  279. package/dist/commands/validate/links/corpus.js +89 -0
  280. package/dist/commands/validate/links/corpus.js.map +1 -0
  281. package/dist/commands/validate/links/glossary.js +75 -0
  282. package/dist/commands/validate/links/glossary.js.map +1 -0
  283. package/dist/commands/validate/render/repeats.js +63 -0
  284. package/dist/commands/validate/render/repeats.js.map +1 -0
  285. package/dist/commands/validate/render/rollups.js +115 -0
  286. package/dist/commands/validate/render/rollups.js.map +1 -0
  287. package/dist/commands/validate/render/text.js +199 -0
  288. package/dist/commands/validate/render/text.js.map +1 -0
  289. package/dist/commands/validate/report.js +145 -0
  290. package/dist/commands/validate/report.js.map +1 -0
  291. package/dist/commands/validate/scope.js +113 -0
  292. package/dist/commands/validate/scope.js.map +1 -0
  293. package/dist/commands/validate/service/api.js +252 -0
  294. package/dist/commands/validate/service/api.js.map +1 -0
  295. package/dist/commands/validate/service/contracts/generated.js +134 -0
  296. package/dist/commands/validate/service/contracts/generated.js.map +1 -0
  297. package/dist/commands/validate/service/events/events.js +241 -0
  298. package/dist/commands/validate/service/events/events.js.map +1 -0
  299. package/dist/commands/validate/service/events/message-producers.js +77 -0
  300. package/dist/commands/validate/service/events/message-producers.js.map +1 -0
  301. package/dist/commands/validate/service/evidence-pins.js +177 -0
  302. package/dist/commands/validate/service/evidence-pins.js.map +1 -0
  303. package/dist/commands/validate/service/model/diverged.js +226 -0
  304. package/dist/commands/validate/service/model/diverged.js.map +1 -0
  305. package/dist/commands/validate/service/model/grade.js +163 -0
  306. package/dist/commands/validate/service/model/grade.js.map +1 -0
  307. package/dist/commands/validate/service/service.js +310 -0
  308. package/dist/commands/validate/service/service.js.map +1 -0
  309. package/dist/commands/validate/service/specs.js +279 -0
  310. package/dist/commands/validate/service/specs.js.map +1 -0
  311. package/dist/commands/validate/service/spine.js +148 -0
  312. package/dist/commands/validate/service/spine.js.map +1 -0
  313. package/dist/commands/validate/service/usecases/tags.js +113 -0
  314. package/dist/commands/validate/service/usecases/tags.js.map +1 -0
  315. package/dist/commands/validate/service/usecases/usecases.js +209 -0
  316. package/dist/commands/validate/service/usecases/usecases.js.map +1 -0
  317. package/dist/commands/validate/validate.js +363 -0
  318. package/dist/commands/validate/validate.js.map +1 -0
  319. package/dist/commands/verify/cross/diff.js +178 -0
  320. package/dist/commands/verify/cross/diff.js.map +1 -0
  321. package/dist/commands/verify/evidence/contract.js +32 -0
  322. package/dist/commands/verify/evidence/contract.js.map +1 -0
  323. package/dist/commands/verify/evidence/pins.js +52 -0
  324. package/dist/commands/verify/evidence/pins.js.map +1 -0
  325. package/dist/commands/verify/evidence/read.js +81 -0
  326. package/dist/commands/verify/evidence/read.js.map +1 -0
  327. package/dist/commands/verify/frozen.js +263 -0
  328. package/dist/commands/verify/frozen.js.map +1 -0
  329. package/dist/commands/verify/record.js +278 -0
  330. package/dist/commands/verify/record.js.map +1 -0
  331. package/dist/commands/verify/report.js +206 -0
  332. package/dist/commands/verify/report.js.map +1 -0
  333. package/dist/commands/verify/results.js +328 -0
  334. package/dist/commands/verify/results.js.map +1 -0
  335. package/dist/commands/verify/verify.js +220 -0
  336. package/dist/commands/verify/verify.js.map +1 -0
  337. package/dist/commands/vouch/contract.js +11 -0
  338. package/dist/commands/vouch/contract.js.map +1 -0
  339. package/dist/commands/vouch/pack/contract.js +2 -0
  340. package/dist/commands/vouch/pack/contract.js.map +1 -0
  341. package/dist/commands/vouch/pack/pack.js +266 -0
  342. package/dist/commands/vouch/pack/pack.js.map +1 -0
  343. package/dist/commands/vouch/pack/print.js +266 -0
  344. package/dist/commands/vouch/pack/print.js.map +1 -0
  345. package/dist/commands/vouch/pack/sections.js +141 -0
  346. package/dist/commands/vouch/pack/sections.js.map +1 -0
  347. package/dist/commands/vouch/prompt/confirm.js +46 -0
  348. package/dist/commands/vouch/prompt/confirm.js.map +1 -0
  349. package/dist/commands/vouch/report.js +101 -0
  350. package/dist/commands/vouch/report.js.map +1 -0
  351. package/dist/commands/vouch/run.js +230 -0
  352. package/dist/commands/vouch/run.js.map +1 -0
  353. package/dist/commands/vouch/sample/plan.js +111 -0
  354. package/dist/commands/vouch/sample/plan.js.map +1 -0
  355. package/dist/commands/vouch/sample/print.js +109 -0
  356. package/dist/commands/vouch/sample/print.js.map +1 -0
  357. package/dist/commands/vouch/vet/verify.js +155 -0
  358. package/dist/commands/vouch/vet/verify.js.map +1 -0
  359. package/dist/commands/vouch/vouch.js +169 -0
  360. package/dist/commands/vouch/vouch.js.map +1 -0
  361. package/dist/core/agent/agents-md/command-map.js +299 -0
  362. package/dist/core/agent/agents-md/command-map.js.map +1 -0
  363. package/dist/core/agent/agents-md/map/explain.js +46 -0
  364. package/dist/core/agent/agents-md/map/explain.js.map +1 -0
  365. package/dist/core/agent/agents-md/map/lenses/context.js +50 -0
  366. package/dist/core/agent/agents-md/map/lenses/context.js.map +1 -0
  367. package/dist/core/agent/agents-md/map/lenses/diff.js +59 -0
  368. package/dist/core/agent/agents-md/map/lenses/diff.js.map +1 -0
  369. package/dist/core/agent/agents-md/map/lenses/gate.js +65 -0
  370. package/dist/core/agent/agents-md/map/lenses/gate.js.map +1 -0
  371. package/dist/core/agent/agents-md/map/mcp.js +44 -0
  372. package/dist/core/agent/agents-md/map/mcp.js.map +1 -0
  373. package/dist/core/agent/agents-md/map/status.js +78 -0
  374. package/dist/core/agent/agents-md/map/status.js.map +1 -0
  375. package/dist/core/agent/agents-md/map/subsystem.js +104 -0
  376. package/dist/core/agent/agents-md/map/subsystem.js.map +1 -0
  377. package/dist/core/agent/agents-md/map/usecases.js +138 -0
  378. package/dist/core/agent/agents-md/map/usecases.js.map +1 -0
  379. package/dist/core/agent/agents-md/refusals.js +273 -0
  380. package/dist/core/agent/agents-md/refusals.js.map +1 -0
  381. package/dist/core/agent/agents-md.js +203 -0
  382. package/dist/core/agent/agents-md.js.map +1 -0
  383. package/dist/core/{agents-stamp.js → agent/agents-stamp.js} +60 -0
  384. package/dist/core/agent/agents-stamp.js.map +1 -0
  385. package/dist/core/agent/contract.js +2 -0
  386. package/dist/core/agent/contract.js.map +1 -0
  387. package/dist/core/agent/protocol.js +193 -0
  388. package/dist/core/agent/protocol.js.map +1 -0
  389. package/dist/core/agent/scaffold.js +254 -0
  390. package/dist/core/agent/scaffold.js.map +1 -0
  391. package/dist/core/agent/support/report.js +144 -0
  392. package/dist/core/agent/support/report.js.map +1 -0
  393. package/dist/core/agent/tools/dialects.js +151 -0
  394. package/dist/core/agent/tools/dialects.js.map +1 -0
  395. package/dist/core/agent/tools/registry.js +193 -0
  396. package/dist/core/agent/tools/registry.js.map +1 -0
  397. package/dist/core/agent/workflows/adopt.js +280 -0
  398. package/dist/core/agent/workflows/adopt.js.map +1 -0
  399. package/dist/core/agent/workflows/check.js +373 -0
  400. package/dist/core/agent/workflows/check.js.map +1 -0
  401. package/dist/core/agent/workflows/closing.js +323 -0
  402. package/dist/core/agent/workflows/closing.js.map +1 -0
  403. package/dist/core/agent/workflows/feature.js +220 -0
  404. package/dist/core/agent/workflows/feature.js.map +1 -0
  405. package/dist/core/agent/workflows/implement.js +188 -0
  406. package/dist/core/agent/workflows/implement.js.map +1 -0
  407. package/dist/core/agent/workflows/reference/authoring.js +311 -0
  408. package/dist/core/agent/workflows/reference/authoring.js.map +1 -0
  409. package/dist/core/agent/workflows/reference/codes.js +67 -0
  410. package/dist/core/agent/workflows/reference/codes.js.map +1 -0
  411. package/dist/core/agent/workflows/reference/done-check.js +210 -0
  412. package/dist/core/agent/workflows/reference/done-check.js.map +1 -0
  413. package/dist/core/agent/workflows/reference/drawing/drawing.js +253 -0
  414. package/dist/core/agent/workflows/reference/drawing/drawing.js.map +1 -0
  415. package/dist/core/agent/workflows/reference/reference.js +19 -0
  416. package/dist/core/agent/workflows/reference/reference.js.map +1 -0
  417. package/dist/core/agent/workflows/reference/spine.js +338 -0
  418. package/dist/core/agent/workflows/reference/spine.js.map +1 -0
  419. package/dist/core/asyncapi/baseline/plan.js +43 -0
  420. package/dist/core/asyncapi/baseline/plan.js.map +1 -0
  421. package/dist/core/asyncapi/baseline/surfaces.js +54 -0
  422. package/dist/core/asyncapi/baseline/surfaces.js.map +1 -0
  423. package/dist/core/asyncapi/depth.js +164 -0
  424. package/dist/core/asyncapi/depth.js.map +1 -0
  425. package/dist/core/asyncapi/digest.js +146 -0
  426. package/dist/core/asyncapi/digest.js.map +1 -0
  427. package/dist/core/asyncapi/merge/components.js +92 -0
  428. package/dist/core/asyncapi/merge/components.js.map +1 -0
  429. package/dist/core/asyncapi/merge/error.js +38 -0
  430. package/dist/core/asyncapi/merge/error.js.map +1 -0
  431. package/dist/core/asyncapi/merge/markers.js +290 -0
  432. package/dist/core/asyncapi/merge/markers.js.map +1 -0
  433. package/dist/core/asyncapi/merge/merge.js +195 -0
  434. package/dist/core/asyncapi/merge/merge.js.map +1 -0
  435. package/dist/core/asyncapi/merge/pin.js +83 -0
  436. package/dist/core/asyncapi/merge/pin.js.map +1 -0
  437. package/dist/core/asyncapi/model.js +11 -0
  438. package/dist/core/asyncapi/model.js.map +1 -0
  439. package/dist/core/asyncapi/producers.js +50 -0
  440. package/dist/core/asyncapi/producers.js.map +1 -0
  441. package/dist/core/asyncapi/read.js +263 -0
  442. package/dist/core/asyncapi/read.js.map +1 -0
  443. package/dist/core/brief/brief.js +285 -0
  444. package/dist/core/brief/brief.js.map +1 -0
  445. package/dist/core/brief/checks.js +385 -0
  446. package/dist/core/brief/checks.js.map +1 -0
  447. package/dist/core/brief/landscape.js +273 -0
  448. package/dist/core/brief/landscape.js.map +1 -0
  449. package/dist/core/brief/map/extend.js +84 -0
  450. package/dist/core/brief/map/extend.js.map +1 -0
  451. package/dist/core/brief/map/owed.js +266 -0
  452. package/dist/core/brief/map/owed.js.map +1 -0
  453. package/dist/core/brief/targets.js +304 -0
  454. package/dist/core/brief/targets.js.map +1 -0
  455. package/dist/core/brief/unchecked.js +58 -0
  456. package/dist/core/brief/unchecked.js.map +1 -0
  457. package/dist/core/c4/arch.js +190 -0
  458. package/dist/core/c4/arch.js.map +1 -0
  459. package/dist/core/c4/direction/direction.js +114 -0
  460. package/dist/core/c4/direction/direction.js.map +1 -0
  461. package/dist/core/c4/likec4.js +243 -0
  462. package/dist/core/c4/likec4.js.map +1 -0
  463. package/dist/core/c4/locate/unlocated.js +150 -0
  464. package/dist/core/c4/locate/unlocated.js.map +1 -0
  465. package/dist/core/c4/parsed/deployment.js +160 -0
  466. package/dist/core/c4/parsed/deployment.js.map +1 -0
  467. package/dist/core/c4/parsed/dynamic-views.js +132 -0
  468. package/dist/core/c4/parsed/dynamic-views.js.map +1 -0
  469. package/dist/core/c4/parsed/specification.js +78 -0
  470. package/dist/core/c4/parsed/specification.js.map +1 -0
  471. package/dist/core/c4/parsed/values.js +110 -0
  472. package/dist/core/c4/parsed/values.js.map +1 -0
  473. package/dist/core/c4/parsed/view-ids.js +113 -0
  474. package/dist/core/c4/parsed/view-ids.js.map +1 -0
  475. package/dist/core/c4/prefetch/fleet.js +134 -0
  476. package/dist/core/c4/prefetch/fleet.js.map +1 -0
  477. package/dist/core/c4/project/architecture.js +161 -0
  478. package/dist/core/c4/project/architecture.js.map +1 -0
  479. package/dist/core/c4/project/batch.js +140 -0
  480. package/dist/core/c4/project/batch.js.map +1 -0
  481. package/dist/core/c4/project/documents.js +89 -0
  482. package/dist/core/c4/project/documents.js.map +1 -0
  483. package/dist/core/c4/project/load.js +219 -0
  484. package/dist/core/c4/project/load.js.map +1 -0
  485. package/dist/core/c4/project/staged.js +277 -0
  486. package/dist/core/c4/project/staged.js.map +1 -0
  487. package/dist/core/c4/resolve/attested.js +0 -0
  488. package/dist/core/c4/resolve/attested.js.map +1 -0
  489. package/dist/core/c4/resolve/external.js +51 -0
  490. package/dist/core/c4/resolve/external.js.map +1 -0
  491. package/dist/core/c4/resolve/service.js +174 -0
  492. package/dist/core/c4/resolve/service.js.map +1 -0
  493. package/dist/core/c4/resolve/steps.js +290 -0
  494. package/dist/core/c4/resolve/steps.js.map +1 -0
  495. package/dist/core/c4/resolve/systems.js +154 -0
  496. package/dist/core/c4/resolve/systems.js.map +1 -0
  497. package/dist/core/c4/root-project/exclude.js +352 -0
  498. package/dist/core/c4/root-project/exclude.js.map +1 -0
  499. package/dist/core/c4/seed/fleet-file.js +201 -0
  500. package/dist/core/c4/seed/fleet-file.js.map +1 -0
  501. package/dist/core/c4/seed/items.js +91 -0
  502. package/dist/core/c4/seed/items.js.map +1 -0
  503. package/dist/core/c4/seed/stamp.js +48 -0
  504. package/dist/core/c4/seed/stamp.js.map +1 -0
  505. package/dist/core/c4/seed/template.js +173 -0
  506. package/dist/core/c4/seed/template.js.map +1 -0
  507. package/dist/core/c4/service-model/created/models.js +96 -0
  508. package/dist/core/c4/service-model/created/models.js.map +1 -0
  509. package/dist/core/c4/service-model/documents.js +47 -0
  510. package/dist/core/c4/service-model/documents.js.map +1 -0
  511. package/dist/core/c4/service-model/fleet/extending.js +82 -0
  512. package/dist/core/c4/service-model/fleet/extending.js.map +1 -0
  513. package/dist/core/c4/service-model/load.js +165 -0
  514. package/dist/core/c4/service-model/load.js.map +1 -0
  515. package/dist/core/c4/service-model/renderer.js +128 -0
  516. package/dist/core/c4/service-model/renderer.js.map +1 -0
  517. package/dist/core/c4/service-model/shape.js +106 -0
  518. package/dist/core/c4/service-model/shape.js.map +1 -0
  519. package/dist/core/c4/service-model/slice.js +188 -0
  520. package/dist/core/c4/service-model/slice.js.map +1 -0
  521. package/dist/core/c4/source-mask.js +369 -0
  522. package/dist/core/c4/source-mask.js.map +1 -0
  523. package/dist/core/c4/source-scan.js +308 -0
  524. package/dist/core/c4/source-scan.js.map +1 -0
  525. package/dist/core/c4/splice/authored-source.js +167 -0
  526. package/dist/core/c4/splice/authored-source.js.map +1 -0
  527. package/dist/core/c4/splice/contract.js +30 -0
  528. package/dist/core/c4/splice/contract.js.map +1 -0
  529. package/dist/core/c4/splice/delta-blocks.js +126 -0
  530. package/dist/core/c4/splice/delta-blocks.js.map +1 -0
  531. package/dist/core/c4/splice/identity/declared.js +87 -0
  532. package/dist/core/c4/splice/identity/declared.js.map +1 -0
  533. package/dist/core/c4/splice/identity/edges.js +73 -0
  534. package/dist/core/c4/splice/identity/edges.js.map +1 -0
  535. package/dist/core/c4/splice/identity/existing.js +80 -0
  536. package/dist/core/c4/splice/identity/existing.js.map +1 -0
  537. package/dist/core/c4/splice/identity/interior.js +80 -0
  538. package/dist/core/c4/splice/identity/interior.js.map +1 -0
  539. package/dist/core/c4/splice/identity/owner.js +50 -0
  540. package/dist/core/c4/splice/identity/owner.js.map +1 -0
  541. package/dist/core/c4/splice/landscape-merge.js +337 -0
  542. package/dist/core/c4/splice/landscape-merge.js.map +1 -0
  543. package/dist/core/c4/splice/model/merge.js +151 -0
  544. package/dist/core/c4/splice/model/merge.js.map +1 -0
  545. package/dist/core/c4/splice/placement.js +298 -0
  546. package/dist/core/c4/splice/placement.js.map +1 -0
  547. package/dist/core/c4/splice/text/spot.js +131 -0
  548. package/dist/core/c4/splice/text/spot.js.map +1 -0
  549. package/dist/core/c4/workspace.js +166 -0
  550. package/dist/core/c4/workspace.js.map +1 -0
  551. package/dist/core/capabilities/authoring/notes.js +141 -0
  552. package/dist/core/capabilities/authoring/notes.js.map +1 -0
  553. package/dist/core/capabilities/capabilities.js +124 -0
  554. package/dist/core/capabilities/capabilities.js.map +1 -0
  555. package/dist/core/capabilities/delta/doc.js +47 -0
  556. package/dist/core/capabilities/delta/doc.js.map +1 -0
  557. package/dist/core/capabilities/delta/overlay.js +129 -0
  558. package/dist/core/capabilities/delta/overlay.js.map +1 -0
  559. package/dist/core/capabilities/delta/summary.js +57 -0
  560. package/dist/core/capabilities/delta/summary.js.map +1 -0
  561. package/dist/core/capabilities/delta/tree.js +43 -0
  562. package/dist/core/capabilities/delta/tree.js.map +1 -0
  563. package/dist/core/capabilities/delta/uncovered.js +222 -0
  564. package/dist/core/capabilities/delta/uncovered.js.map +1 -0
  565. package/dist/core/capabilities/findings.js +338 -0
  566. package/dist/core/capabilities/findings.js.map +1 -0
  567. package/dist/core/capabilities/realizes/findings.js +174 -0
  568. package/dist/core/capabilities/realizes/findings.js.map +1 -0
  569. package/dist/core/capabilities/realizes/join.js +123 -0
  570. package/dist/core/capabilities/realizes/join.js.map +1 -0
  571. package/dist/core/capabilities/rollup.js +205 -0
  572. package/dist/core/capabilities/rollup.js.map +1 -0
  573. package/dist/core/capabilities/tree.js +104 -0
  574. package/dist/core/capabilities/tree.js.map +1 -0
  575. package/dist/core/capabilities/usecase-join.js +267 -0
  576. package/dist/core/capabilities/usecase-join.js.map +1 -0
  577. package/dist/core/coherence/authoring/scaffold.js +185 -0
  578. package/dist/core/coherence/authoring/scaffold.js.map +1 -0
  579. package/dist/core/coherence/authoring/sentinels.js +75 -0
  580. package/dist/core/coherence/authoring/sentinels.js.map +1 -0
  581. package/dist/core/coherence/calls/called.js +52 -0
  582. package/dist/core/coherence/calls/called.js.map +1 -0
  583. package/dist/core/coherence/coherence.js +332 -0
  584. package/dist/core/coherence/coherence.js.map +1 -0
  585. package/dist/core/coherence/consumed/operations.js +70 -0
  586. package/dist/core/coherence/consumed/operations.js.map +1 -0
  587. package/dist/core/coherence/consumed/refusal.js +38 -0
  588. package/dist/core/coherence/consumed/refusal.js.map +1 -0
  589. package/dist/core/coherence/covers/health.js +85 -0
  590. package/dist/core/coherence/covers/health.js.map +1 -0
  591. package/dist/core/coherence/declared.js +295 -0
  592. package/dist/core/coherence/declared.js.map +1 -0
  593. package/dist/core/coherence/events/declared.js +191 -0
  594. package/dist/core/coherence/events/declared.js.map +1 -0
  595. package/dist/core/coherence/events/events.js +335 -0
  596. package/dist/core/coherence/events/events.js.map +1 -0
  597. package/dist/core/coherence/events/grades.js +189 -0
  598. package/dist/core/coherence/events/grades.js.map +1 -0
  599. package/dist/core/coherence/events/lookups.js +63 -0
  600. package/dist/core/coherence/events/lookups.js.map +1 -0
  601. package/dist/core/coherence/events/produced.js +100 -0
  602. package/dist/core/coherence/events/produced.js.map +1 -0
  603. package/dist/core/coherence/living.js +198 -0
  604. package/dist/core/coherence/living.js.map +1 -0
  605. package/dist/core/coherence/lookups.js +95 -0
  606. package/dist/core/coherence/lookups.js.map +1 -0
  607. package/dist/core/coherence/pending.js +39 -0
  608. package/dist/core/coherence/pending.js.map +1 -0
  609. package/dist/core/coherence/retired/archived.js +285 -0
  610. package/dist/core/coherence/retired/archived.js.map +1 -0
  611. package/dist/core/coherence/retired/event-pair.js +62 -0
  612. package/dist/core/coherence/retired/event-pair.js.map +1 -0
  613. package/dist/core/coherence/retired/merged.js +79 -0
  614. package/dist/core/coherence/retired/merged.js.map +1 -0
  615. package/dist/core/coherence/retired/retirement.js +49 -0
  616. package/dist/core/coherence/retired/retirement.js.map +1 -0
  617. package/dist/core/coherence/retired/revival/arrivals.js +131 -0
  618. package/dist/core/coherence/retired/revival/arrivals.js.map +1 -0
  619. package/dist/core/coherence/retired/revival/revived.js +297 -0
  620. package/dist/core/coherence/retired/revival/revived.js.map +1 -0
  621. package/dist/core/conflict-markers.js +60 -0
  622. package/dist/core/conflict-markers.js.map +1 -0
  623. package/dist/core/consumers/after.js +113 -0
  624. package/dist/core/consumers/after.js.map +1 -0
  625. package/dist/core/consumers/consumers.js +296 -0
  626. package/dist/core/consumers/consumers.js.map +1 -0
  627. package/dist/core/consumers/current.js +211 -0
  628. package/dist/core/consumers/current.js.map +1 -0
  629. package/dist/core/consumers/scan.js +46 -0
  630. package/dist/core/consumers/scan.js.map +1 -0
  631. package/dist/core/consumers/state.js +27 -0
  632. package/dist/core/consumers/state.js.map +1 -0
  633. package/dist/core/delta/claims.js +73 -0
  634. package/dist/core/delta/claims.js.map +1 -0
  635. package/dist/core/delta/delta.js +341 -0
  636. package/dist/core/delta/delta.js.map +1 -0
  637. package/dist/core/delta/document.js +177 -0
  638. package/dist/core/delta/document.js.map +1 -0
  639. package/dist/core/delta/scope.js +48 -0
  640. package/dist/core/delta/scope.js.map +1 -0
  641. package/dist/core/delta/select.js +237 -0
  642. package/dist/core/delta/select.js.map +1 -0
  643. package/dist/core/dependencies/dependencies.js +141 -0
  644. package/dist/core/dependencies/dependencies.js.map +1 -0
  645. package/dist/core/dependencies/facts.js +165 -0
  646. package/dist/core/dependencies/facts.js.map +1 -0
  647. package/dist/core/dependencies/fanin.js +88 -0
  648. package/dist/core/dependencies/fanin.js.map +1 -0
  649. package/dist/core/dependencies/graph.js +106 -0
  650. package/dist/core/dependencies/graph.js.map +1 -0
  651. package/dist/core/deployment/delta.js +191 -0
  652. package/dist/core/deployment/delta.js.map +1 -0
  653. package/dist/core/deployment/objects.js +145 -0
  654. package/dist/core/deployment/objects.js.map +1 -0
  655. package/dist/core/diff/base-git.js +230 -0
  656. package/dist/core/diff/base-git.js.map +1 -0
  657. package/dist/core/diff/base-state.js +237 -0
  658. package/dist/core/diff/base-state.js.map +1 -0
  659. package/dist/core/diff/joins.js +136 -0
  660. package/dist/core/diff/joins.js.map +1 -0
  661. package/dist/core/diff/scope/changed-paths.js +204 -0
  662. package/dist/core/diff/scope/changed-paths.js.map +1 -0
  663. package/dist/core/diff/scope/edges.js +82 -0
  664. package/dist/core/diff/scope/edges.js.map +1 -0
  665. package/dist/core/diff/semantic.js +312 -0
  666. package/dist/core/diff/semantic.js.map +1 -0
  667. package/dist/core/docs.js +37 -85
  668. package/dist/core/docs.js.map +1 -1
  669. package/dist/core/doctor/agents.js +238 -0
  670. package/dist/core/doctor/agents.js.map +1 -0
  671. package/dist/core/doctor/config.js +139 -0
  672. package/dist/core/doctor/config.js.map +1 -0
  673. package/dist/core/doctor/doctor.js +355 -0
  674. package/dist/core/doctor/doctor.js.map +1 -0
  675. package/dist/core/doctor/report.js +13 -0
  676. package/dist/core/doctor/report.js.map +1 -0
  677. package/dist/core/doctor/reports/scan.js +242 -0
  678. package/dist/core/doctor/reports/scan.js.map +1 -0
  679. package/dist/core/doctor/residue.js +110 -0
  680. package/dist/core/doctor/residue.js.map +1 -0
  681. package/dist/core/document/apply.js +224 -0
  682. package/dist/core/document/apply.js.map +1 -0
  683. package/dist/core/{frontmatter.js → document/frontmatter.js} +103 -2
  684. package/dist/core/document/frontmatter.js.map +1 -0
  685. package/dist/core/document/grammar/directives.js +143 -0
  686. package/dist/core/document/grammar/directives.js.map +1 -0
  687. package/dist/core/document/parse.js +286 -0
  688. package/dist/core/document/parse.js.map +1 -0
  689. package/dist/core/document/scenarios.js +238 -0
  690. package/dist/core/document/scenarios.js.map +1 -0
  691. package/dist/core/document/spec.js +234 -0
  692. package/dist/core/document/spec.js.map +1 -0
  693. package/dist/core/{config.js → envelope/config.js} +89 -18
  694. package/dist/core/envelope/config.js.map +1 -0
  695. package/dist/core/envelope/json.js +209 -0
  696. package/dist/core/envelope/json.js.map +1 -0
  697. package/dist/core/{version.js → envelope/version.js} +3 -3
  698. package/dist/core/envelope/version.js.map +1 -0
  699. package/dist/core/explain/families.js +180 -0
  700. package/dist/core/explain/families.js.map +1 -0
  701. package/dist/core/explain/fix-tables.js +178 -0
  702. package/dist/core/explain/fix-tables.js.map +1 -0
  703. package/dist/core/explain/lookup.js +194 -0
  704. package/dist/core/explain/lookup.js.map +1 -0
  705. package/dist/core/explain/refusals.js +49 -0
  706. package/dist/core/explain/refusals.js.map +1 -0
  707. package/dist/core/explain/terms/documents.js +227 -0
  708. package/dist/core/explain/terms/documents.js.map +1 -0
  709. package/dist/core/explain/terms/done-check.js +144 -0
  710. package/dist/core/explain/terms/done-check.js.map +1 -0
  711. package/dist/core/explain/terms/entry.js +14 -0
  712. package/dist/core/explain/terms/entry.js.map +1 -0
  713. package/dist/core/explain/terms/stages.js +71 -0
  714. package/dist/core/explain/terms/stages.js.map +1 -0
  715. package/dist/core/explain/terms/tasks.js +97 -0
  716. package/dist/core/explain/terms/tasks.js.map +1 -0
  717. package/dist/core/explain/terms.js +103 -0
  718. package/dist/core/explain/terms.js.map +1 -0
  719. package/dist/core/explore/describe.js +105 -0
  720. package/dist/core/explore/describe.js.map +1 -0
  721. package/dist/core/explore/explore.js +204 -0
  722. package/dist/core/explore/explore.js.map +1 -0
  723. package/dist/core/fleet-context.js +174 -146
  724. package/dist/core/fleet-context.js.map +1 -1
  725. package/dist/core/gate/checks.js +208 -0
  726. package/dist/core/gate/checks.js.map +1 -0
  727. package/dist/core/gate/partners.js +246 -0
  728. package/dist/core/gate/partners.js.map +1 -0
  729. package/dist/core/gate/report.js +47 -0
  730. package/dist/core/gate/report.js.map +1 -0
  731. package/dist/core/gate/verification.js +176 -0
  732. package/dist/core/gate/verification.js.map +1 -0
  733. package/dist/core/gherkin/digest.js +60 -0
  734. package/dist/core/gherkin/digest.js.map +1 -0
  735. package/dist/core/gherkin/emit.js +177 -0
  736. package/dist/core/gherkin/emit.js.map +1 -0
  737. package/dist/core/gherkin/read.js +76 -0
  738. package/dist/core/gherkin/read.js.map +1 -0
  739. package/dist/core/gherkin/stale.js +210 -0
  740. package/dist/core/gherkin/stale.js.map +1 -0
  741. package/dist/core/gherkin/stamp.js +77 -0
  742. package/dist/core/gherkin/stamp.js.map +1 -0
  743. package/dist/core/gherkin/steps/catalogue.js +154 -0
  744. package/dist/core/gherkin/steps/catalogue.js.map +1 -0
  745. package/dist/core/gherkin/steps/inventory.js +98 -0
  746. package/dist/core/gherkin/steps/inventory.js.map +1 -0
  747. package/dist/core/gherkin/steps/phrase.js +72 -0
  748. package/dist/core/gherkin/steps/phrase.js.map +1 -0
  749. package/dist/core/glossary/delta.js +109 -0
  750. package/dist/core/glossary/delta.js.map +1 -0
  751. package/dist/core/glossary/tree.js +73 -0
  752. package/dist/core/glossary/tree.js.map +1 -0
  753. package/dist/core/{concurrency.js → kernel/concurrency.js} +19 -0
  754. package/dist/core/kernel/concurrency.js.map +1 -0
  755. package/dist/core/{document-bytes.js → kernel/document-bytes.js} +1 -1
  756. package/dist/core/kernel/document-bytes.js.map +1 -0
  757. package/dist/core/kernel/fences.js +42 -0
  758. package/dist/core/kernel/fences.js.map +1 -0
  759. package/dist/core/kernel/ids/capability.js +72 -0
  760. package/dist/core/kernel/ids/capability.js.map +1 -0
  761. package/dist/core/kernel/ids/dirs.js +33 -0
  762. package/dist/core/kernel/ids/dirs.js.map +1 -0
  763. package/dist/core/kernel/ids/feature.js +75 -0
  764. package/dist/core/kernel/ids/feature.js.map +1 -0
  765. package/dist/core/kernel/ids/fqn/ancestors.js +65 -0
  766. package/dist/core/kernel/ids/fqn/ancestors.js.map +1 -0
  767. package/dist/core/kernel/ids/service.js +156 -0
  768. package/dist/core/kernel/ids/service.js.map +1 -0
  769. package/dist/core/kernel/ids/subsystem.js +63 -0
  770. package/dist/core/kernel/ids/subsystem.js.map +1 -0
  771. package/dist/core/{path-safety.js → kernel/path-safety.js} +56 -4
  772. package/dist/core/kernel/path-safety.js.map +1 -0
  773. package/dist/core/{records.js → kernel/records.js} +11 -0
  774. package/dist/core/kernel/records.js.map +1 -0
  775. package/dist/core/links/backlinks.js +66 -0
  776. package/dist/core/links/backlinks.js.map +1 -0
  777. package/dist/core/links/case.js +74 -0
  778. package/dist/core/links/case.js.map +1 -0
  779. package/dist/core/links/corpus.js +118 -0
  780. package/dist/core/links/corpus.js.map +1 -0
  781. package/dist/core/links/findings.js +110 -0
  782. package/dist/core/links/findings.js.map +1 -0
  783. package/dist/core/links/parse.js +265 -0
  784. package/dist/core/links/parse.js.map +1 -0
  785. package/dist/core/mcp/argv.js +212 -0
  786. package/dist/core/mcp/argv.js.map +1 -0
  787. package/dist/core/mcp/author-tools.js +73 -0
  788. package/dist/core/mcp/author-tools.js.map +1 -0
  789. package/dist/core/mcp/framing.js +46 -0
  790. package/dist/core/mcp/framing.js.map +1 -0
  791. package/dist/core/mcp/protocol.js +280 -0
  792. package/dist/core/mcp/protocol.js.map +1 -0
  793. package/dist/core/mcp/tools.js +324 -0
  794. package/dist/core/mcp/tools.js.map +1 -0
  795. package/dist/core/obligations/obligations.js +106 -0
  796. package/dist/core/obligations/obligations.js.map +1 -0
  797. package/dist/core/openapi/baseline/gate.js +207 -0
  798. package/dist/core/openapi/baseline/gate.js.map +1 -0
  799. package/dist/core/openapi/baseline/plan.js +142 -0
  800. package/dist/core/openapi/baseline/plan.js.map +1 -0
  801. package/dist/core/openapi/baseline/record.js +174 -0
  802. package/dist/core/openapi/baseline/record.js.map +1 -0
  803. package/dist/core/openapi/contract-text.js +33 -0
  804. package/dist/core/openapi/contract-text.js.map +1 -0
  805. package/dist/core/openapi/contract-tree.js +301 -0
  806. package/dist/core/openapi/contract-tree.js.map +1 -0
  807. package/dist/core/openapi/depth.js +136 -0
  808. package/dist/core/openapi/depth.js.map +1 -0
  809. package/dist/core/openapi/digest.js +239 -0
  810. package/dist/core/openapi/digest.js.map +1 -0
  811. package/dist/core/{openapi.js → openapi/doc.js} +54 -108
  812. package/dist/core/openapi/doc.js.map +1 -0
  813. package/dist/core/openapi/merge/components.js +199 -0
  814. package/dist/core/openapi/merge/components.js.map +1 -0
  815. package/dist/core/openapi/merge/error.js +16 -0
  816. package/dist/core/openapi/merge/error.js.map +1 -0
  817. package/dist/core/openapi/merge/markers.js +204 -0
  818. package/dist/core/openapi/merge/markers.js.map +1 -0
  819. package/dist/core/openapi/merge/merge.js +232 -0
  820. package/dist/core/openapi/merge/merge.js.map +1 -0
  821. package/dist/core/openapi/merge/pin.js +110 -0
  822. package/dist/core/openapi/merge/pin.js.map +1 -0
  823. package/dist/core/openspec/decide/capabilities.js +244 -0
  824. package/dist/core/openspec/decide/capabilities.js.map +1 -0
  825. package/dist/core/openspec/decide/dispositions.js +63 -0
  826. package/dist/core/openspec/decide/dispositions.js.map +1 -0
  827. package/dist/core/openspec/decide/renames.js +179 -0
  828. package/dist/core/openspec/decide/renames.js.map +1 -0
  829. package/dist/core/openspec/decide/verdict.js +84 -0
  830. package/dist/core/openspec/decide/verdict.js.map +1 -0
  831. package/dist/core/openspec/inventory.js +220 -0
  832. package/dist/core/openspec/inventory.js.map +1 -0
  833. package/dist/core/openspec/model/mapping.js +78 -0
  834. package/dist/core/openspec/model/mapping.js.map +1 -0
  835. package/dist/core/openspec/model/model.js +70 -0
  836. package/dist/core/openspec/model/model.js.map +1 -0
  837. package/dist/core/openspec/scan/changes.js +241 -0
  838. package/dist/core/openspec/scan/changes.js.map +1 -0
  839. package/dist/core/openspec/scan/config.js +191 -0
  840. package/dist/core/openspec/scan/config.js.map +1 -0
  841. package/dist/core/openspec/scan/shape.js +304 -0
  842. package/dist/core/openspec/scan/shape.js.map +1 -0
  843. package/dist/core/openspec/scan/walk.js +116 -0
  844. package/dist/core/openspec/scan/walk.js.map +1 -0
  845. package/dist/core/openspec/scan/workspace.js +71 -0
  846. package/dist/core/openspec/scan/workspace.js.map +1 -0
  847. package/dist/core/owners/codeowners.js +141 -0
  848. package/dist/core/owners/codeowners.js.map +1 -0
  849. package/dist/core/pack/features.js +120 -0
  850. package/dist/core/pack/features.js.map +1 -0
  851. package/dist/core/pack/joins.js +112 -0
  852. package/dist/core/pack/joins.js.map +1 -0
  853. package/dist/core/pack/living.js +157 -0
  854. package/dist/core/pack/living.js.map +1 -0
  855. package/dist/core/pack/pack.js +120 -0
  856. package/dist/core/pack/pack.js.map +1 -0
  857. package/dist/core/permissions/permissions.js +87 -0
  858. package/dist/core/permissions/permissions.js.map +1 -0
  859. package/dist/core/projection/api.js +84 -0
  860. package/dist/core/projection/api.js.map +1 -0
  861. package/dist/core/projection/arch-slice.js +63 -0
  862. package/dist/core/projection/arch-slice.js.map +1 -0
  863. package/dist/core/projection/events.js +34 -0
  864. package/dist/core/projection/events.js.map +1 -0
  865. package/dist/core/projection/introduced.js +14 -0
  866. package/dist/core/projection/introduced.js.map +1 -0
  867. package/dist/core/provenance/findings.js +244 -0
  868. package/dist/core/provenance/findings.js.map +1 -0
  869. package/dist/core/provenance/git.js +201 -0
  870. package/dist/core/provenance/git.js.map +1 -0
  871. package/dist/core/provenance/gitq/moves.js +139 -0
  872. package/dist/core/provenance/gitq/moves.js.map +1 -0
  873. package/dist/core/provenance/gitq/vouched-ancestor.js +179 -0
  874. package/dist/core/provenance/gitq/vouched-ancestor.js.map +1 -0
  875. package/dist/core/provenance/sample/scope.js +238 -0
  876. package/dist/core/provenance/sample/scope.js.map +1 -0
  877. package/dist/core/provenance/sample/sections.js +61 -0
  878. package/dist/core/provenance/sample/sections.js.map +1 -0
  879. package/dist/core/provenance/sources.js +280 -0
  880. package/dist/core/provenance/sources.js.map +1 -0
  881. package/dist/core/provenance/stamp.js +220 -0
  882. package/dist/core/provenance/stamp.js.map +1 -0
  883. package/dist/core/provenance/walk.js +157 -0
  884. package/dist/core/provenance/walk.js.map +1 -0
  885. package/dist/core/repo/authored/paths.js +210 -0
  886. package/dist/core/repo/authored/paths.js.map +1 -0
  887. package/dist/core/repo/entries.js +126 -0
  888. package/dist/core/repo/entries.js.map +1 -0
  889. package/dist/core/repo/paths.js +322 -0
  890. package/dist/core/repo/paths.js.map +1 -0
  891. package/dist/core/repo/repo.js +308 -0
  892. package/dist/core/repo/repo.js.map +1 -0
  893. package/dist/core/repo/service-target.js +153 -0
  894. package/dist/core/repo/service-target.js.map +1 -0
  895. package/dist/core/repo/state.js +58 -0
  896. package/dist/core/repo/state.js.map +1 -0
  897. package/dist/core/repo/tree/find.js +61 -0
  898. package/dist/core/repo/tree/find.js.map +1 -0
  899. package/dist/core/repo/tree/fs.js +90 -0
  900. package/dist/core/repo/tree/fs.js.map +1 -0
  901. package/dist/core/repo/tree/marker.js +61 -0
  902. package/dist/core/repo/tree/marker.js.map +1 -0
  903. package/dist/core/repo/tree/render/body.js +258 -0
  904. package/dist/core/repo/tree/render/body.js.map +1 -0
  905. package/dist/core/repo/tree/render/projects.js +182 -0
  906. package/dist/core/repo/tree/render/projects.js.map +1 -0
  907. package/dist/core/repo/tree/render/service/header.js +125 -0
  908. package/dist/core/repo/tree/render/service/header.js.map +1 -0
  909. package/dist/core/repo/tree/render/service/peers.js +28 -0
  910. package/dist/core/repo/tree/render/service/peers.js.map +1 -0
  911. package/dist/core/repo/tree/render/service/view-id.js +67 -0
  912. package/dist/core/repo/tree/render/service/view-id.js.map +1 -0
  913. package/dist/core/repo/tree/render/service/views.js +78 -0
  914. package/dist/core/repo/tree/render/service/views.js.map +1 -0
  915. package/dist/core/repo/tree/render/stale.js +42 -0
  916. package/dist/core/repo/tree/render/stale.js.map +1 -0
  917. package/dist/core/repo/tree/render/text.js +84 -0
  918. package/dist/core/repo/tree/render/text.js.map +1 -0
  919. package/dist/core/repo/tree/render/views.js +293 -0
  920. package/dist/core/repo/tree/render/views.js.map +1 -0
  921. package/dist/core/repo/tree/walk.js +255 -0
  922. package/dist/core/repo/tree/walk.js.map +1 -0
  923. package/dist/core/results.js +146 -14
  924. package/dist/core/results.js.map +1 -1
  925. package/dist/core/scaffold/landscape.js +239 -0
  926. package/dist/core/scaffold/landscape.js.map +1 -0
  927. package/dist/core/scaffold/legacy.js +271 -0
  928. package/dist/core/scaffold/legacy.js.map +1 -0
  929. package/dist/core/scaffold/readme.js +84 -0
  930. package/dist/core/scaffold/readme.js.map +1 -0
  931. package/dist/core/staging/commit.js +252 -0
  932. package/dist/core/staging/commit.js.map +1 -0
  933. package/dist/core/staging/interrupted.js +96 -0
  934. package/dist/core/staging/interrupted.js.map +1 -0
  935. package/dist/core/staging/lock.js +268 -0
  936. package/dist/core/staging/lock.js.map +1 -0
  937. package/dist/core/staging/recovery/finding.js +35 -0
  938. package/dist/core/staging/recovery/finding.js.map +1 -0
  939. package/dist/core/staging/recovery/intent.js +95 -0
  940. package/dist/core/staging/recovery/intent.js.map +1 -0
  941. package/dist/core/staging/recovery/recover.js +204 -0
  942. package/dist/core/staging/recovery/recover.js.map +1 -0
  943. package/dist/core/staging/recovery/residue.js +62 -0
  944. package/dist/core/staging/recovery/residue.js.map +1 -0
  945. package/dist/core/staging/snapshot/manifest.js +188 -0
  946. package/dist/core/staging/snapshot/manifest.js.map +1 -0
  947. package/dist/core/staging/snapshot/snapshot.js +196 -0
  948. package/dist/core/staging/snapshot/snapshot.js.map +1 -0
  949. package/dist/core/staging/txn/forward.js +181 -0
  950. package/dist/core/staging/txn/forward.js.map +1 -0
  951. package/dist/core/staging/txn/journal.js +139 -0
  952. package/dist/core/staging/txn/journal.js.map +1 -0
  953. package/dist/core/staging/txn/transaction.js +75 -0
  954. package/dist/core/staging/txn/transaction.js.map +1 -0
  955. package/dist/core/staging/writes.js +113 -0
  956. package/dist/core/staging/writes.js.map +1 -0
  957. package/dist/core/status/actions/execution.js +60 -0
  958. package/dist/core/status/actions/execution.js.map +1 -0
  959. package/dist/core/status/contracts.js +126 -0
  960. package/dist/core/status/contracts.js.map +1 -0
  961. package/dist/core/status/feature/artifacts.js +196 -0
  962. package/dist/core/status/feature/artifacts.js.map +1 -0
  963. package/dist/core/status/feature/feature.js +214 -0
  964. package/dist/core/status/feature/feature.js.map +1 -0
  965. package/dist/core/status/feature/next.js +163 -0
  966. package/dist/core/status/feature/next.js.map +1 -0
  967. package/dist/core/status/feature/state.js +21 -0
  968. package/dist/core/status/feature/state.js.map +1 -0
  969. package/dist/core/status/feature/words.js +96 -0
  970. package/dist/core/status/feature/words.js.map +1 -0
  971. package/dist/core/status/fleet/fleet.js +216 -0
  972. package/dist/core/status/fleet/fleet.js.map +1 -0
  973. package/dist/core/status/fleet/next.js +302 -0
  974. package/dist/core/status/fleet/next.js.map +1 -0
  975. package/dist/core/status/interrupted.js +97 -0
  976. package/dist/core/status/interrupted.js.map +1 -0
  977. package/dist/core/status/report.js +31 -0
  978. package/dist/core/status/report.js.map +1 -0
  979. package/dist/core/status/scan.js +41 -0
  980. package/dist/core/status/scan.js.map +1 -0
  981. package/dist/core/status/verification.js +216 -0
  982. package/dist/core/status/verification.js.map +1 -0
  983. package/dist/core/tasks/packet.js +199 -0
  984. package/dist/core/tasks/packet.js.map +1 -0
  985. package/dist/core/tasks/record.js +43 -0
  986. package/dist/core/tasks/record.js.map +1 -0
  987. package/dist/core/tasks/sources.js +181 -0
  988. package/dist/core/tasks/sources.js.map +1 -0
  989. package/dist/core/tasks/stamps.js +76 -0
  990. package/dist/core/tasks/stamps.js.map +1 -0
  991. package/dist/core/tasks/unit.js +0 -0
  992. package/dist/core/tasks/unit.js.map +1 -0
  993. package/dist/core/usecases/capability.js +166 -0
  994. package/dist/core/usecases/capability.js.map +1 -0
  995. package/dist/core/usecases/delta/claims.js +140 -0
  996. package/dist/core/usecases/delta/claims.js.map +1 -0
  997. package/dist/core/usecases/delta/flows.js +101 -0
  998. package/dist/core/usecases/delta/flows.js.map +1 -0
  999. package/dist/core/usecases/delta/modified.js +315 -0
  1000. package/dist/core/usecases/delta/modified.js.map +1 -0
  1001. package/dist/core/usecases/delta/overlay.js +76 -0
  1002. package/dist/core/usecases/delta/overlay.js.map +1 -0
  1003. package/dist/core/usecases/fleet.js +296 -0
  1004. package/dist/core/usecases/fleet.js.map +1 -0
  1005. package/dist/core/usecases/grade/capability-tag.js +93 -0
  1006. package/dist/core/usecases/grade/capability-tag.js.map +1 -0
  1007. package/dist/core/usecases/grade/feature.js +88 -0
  1008. package/dist/core/usecases/grade/feature.js.map +1 -0
  1009. package/dist/core/usecases/grade/requirement-tag.js +94 -0
  1010. package/dist/core/usecases/grade/requirement-tag.js.map +1 -0
  1011. package/dist/core/usecases/grade/steps.js +266 -0
  1012. package/dist/core/usecases/grade/steps.js.map +1 -0
  1013. package/dist/core/usecases/grade/usecases.js +112 -0
  1014. package/dist/core/usecases/grade/usecases.js.map +1 -0
  1015. package/dist/core/usecases/operations.js +123 -0
  1016. package/dist/core/usecases/operations.js.map +1 -0
  1017. package/dist/core/usecases/place.js +44 -0
  1018. package/dist/core/usecases/place.js.map +1 -0
  1019. package/dist/core/usecases/service/exclude.js +119 -0
  1020. package/dist/core/usecases/service/exclude.js.map +1 -0
  1021. package/dist/core/usecases/service/flows.js +164 -0
  1022. package/dist/core/usecases/service/flows.js.map +1 -0
  1023. package/dist/core/usecases/suites/participants.js +83 -0
  1024. package/dist/core/usecases/suites/participants.js.map +1 -0
  1025. package/dist/core/usecases/suites/suites.js +45 -0
  1026. package/dist/core/usecases/suites/suites.js.map +1 -0
  1027. package/dist/core/usecases/touch.js +101 -0
  1028. package/dist/core/usecases/touch.js.map +1 -0
  1029. package/dist/core/verify/answers.js +180 -0
  1030. package/dist/core/verify/answers.js.map +1 -0
  1031. package/dist/core/verify/build.js +170 -0
  1032. package/dist/core/verify/build.js.map +1 -0
  1033. package/dist/core/verify/checklist.js +259 -0
  1034. package/dist/core/verify/checklist.js.map +1 -0
  1035. package/dist/core/verify/claims/identity.js +61 -0
  1036. package/dist/core/verify/claims/identity.js.map +1 -0
  1037. package/dist/core/verify/cross/diff.js +97 -0
  1038. package/dist/core/verify/cross/diff.js.map +1 -0
  1039. package/dist/core/verify/evidence/contract.js +169 -0
  1040. package/dist/core/verify/evidence/contract.js.map +1 -0
  1041. package/dist/core/verify/location.js +67 -0
  1042. package/dist/core/verify/location.js.map +1 -0
  1043. package/dist/core/verify/pins/lint.js +158 -0
  1044. package/dist/core/verify/pins/lint.js.map +1 -0
  1045. package/dist/core/verify/pins/pin.js +95 -0
  1046. package/dist/core/verify/pins/pin.js.map +1 -0
  1047. package/dist/core/verify/read/file.js +224 -0
  1048. package/dist/core/verify/read/file.js.map +1 -0
  1049. package/dist/core/verify/read/shape.js +169 -0
  1050. package/dist/core/verify/read/shape.js.map +1 -0
  1051. package/dist/core/verify/read/union.js +105 -0
  1052. package/dist/core/verify/read/union.js.map +1 -0
  1053. package/dist/core/verify/record.js +165 -0
  1054. package/dist/core/verify/record.js.map +1 -0
  1055. package/dist/core/verify/store/commit.js +99 -0
  1056. package/dist/core/verify/store/commit.js.map +1 -0
  1057. package/dist/core/verify/store/render.js +61 -0
  1058. package/dist/core/verify/store/render.js.map +1 -0
  1059. package/dist/core/vocabulary/health.js +91 -0
  1060. package/dist/core/vocabulary/health.js.map +1 -0
  1061. package/dist/core/vocabulary/issue.js +59 -0
  1062. package/dist/core/vocabulary/issue.js.map +1 -0
  1063. package/dist/core/vocabulary/maturity.js +216 -0
  1064. package/dist/core/vocabulary/maturity.js.map +1 -0
  1065. package/dist/core/vocabulary/report.js +90 -0
  1066. package/dist/core/vocabulary/report.js.map +1 -0
  1067. package/dist/core/vocabulary/steps.js +266 -0
  1068. package/dist/core/vocabulary/steps.js.map +1 -0
  1069. package/dist/core/workspace/discover.js +239 -0
  1070. package/dist/core/workspace/discover.js.map +1 -0
  1071. package/dist/core/workspace/render.js +52 -0
  1072. package/dist/core/workspace/render.js.map +1 -0
  1073. package/examples/README.md +232 -0
  1074. package/examples/docs/architecture/adrs/0001-transactional-outbox.md +33 -0
  1075. package/examples/docs/architecture/capabilities.yaml +31 -0
  1076. package/examples/docs/architecture/landscape.likec4 +336 -0
  1077. package/examples/docs/architecture/obligations.yaml +23 -0
  1078. package/examples/docs/architecture/permissions.yaml +50 -0
  1079. package/examples/docs/architecture/services.likec4 +70 -0
  1080. package/examples/docs/architecture/subsystems.likec4 +18 -0
  1081. package/examples/docs/architecture/usecases/order-notification.likec4 +74 -0
  1082. package/examples/docs/capabilities/checkout/spec.md +55 -0
  1083. package/examples/docs/capabilities/identity/tokens/spec.md +42 -0
  1084. package/examples/docs/capabilities/order-notifications/spec.md +43 -0
  1085. package/examples/docs/features/FEAT-101-payment-splitting/adrs/0001-dedicated-split-service.md +18 -0
  1086. package/examples/docs/features/FEAT-101-payment-splitting/delta.likec4 +94 -0
  1087. package/examples/docs/features/FEAT-101-payment-splitting/intent.md +44 -0
  1088. package/examples/docs/features/FEAT-101-payment-splitting/specs/checkout-web/spec.md +21 -0
  1089. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-service/asyncapi.yaml +132 -0
  1090. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-service/spec.md +36 -0
  1091. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/arch.spec.md +40 -0
  1092. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/openapi.yaml +116 -0
  1093. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/spec.md +55 -0
  1094. package/examples/docs/features/FEAT-112-retire-order-v1/intent.md +35 -0
  1095. package/examples/docs/features/FEAT-112-retire-order-v1/specs/order-service/openapi.yaml +31 -0
  1096. package/examples/docs/features/FEAT-112-retire-order-v1/specs/order-service/spec.md +17 -0
  1097. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/architecture/landscape.likec4 +253 -0
  1098. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/services/order-service/spec.md +121 -0
  1099. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/services/payment-service/openapi.yaml +111 -0
  1100. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/services/payment-service/spec.md +58 -0
  1101. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/manifest.json +32 -0
  1102. package/examples/docs/features/archive/FEAT-088-refunds/adrs/0001-refunds-stay-in-payment-service.md +26 -0
  1103. package/examples/docs/features/archive/FEAT-088-refunds/delta.likec4 +28 -0
  1104. package/examples/docs/features/archive/FEAT-088-refunds/intent.md +26 -0
  1105. package/examples/docs/features/archive/FEAT-088-refunds/specs/order-service/spec.md +37 -0
  1106. package/examples/docs/features/archive/FEAT-088-refunds/specs/payment-service/openapi.yaml +73 -0
  1107. package/examples/docs/features/archive/FEAT-088-refunds/specs/payment-service/spec.md +23 -0
  1108. package/examples/docs/features/archive/FEAT-088-refunds/verification.yaml +76 -0
  1109. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/architecture/landscape.likec4 +275 -0
  1110. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/payment-service/asyncapi.yaml +96 -0
  1111. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/payment-service/spec.md +82 -0
  1112. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/platform/notification-service/asyncapi.yaml +164 -0
  1113. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/platform/notification-service/spec.md +91 -0
  1114. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/manifest.json +46 -0
  1115. package/examples/docs/features/archive/FEAT-120-refund-notification/delta.likec4 +36 -0
  1116. package/examples/docs/features/archive/FEAT-120-refund-notification/intent.md +22 -0
  1117. package/examples/docs/features/archive/FEAT-120-refund-notification/scenario-report.json +10 -0
  1118. package/examples/docs/features/archive/FEAT-120-refund-notification/specs/notification-service/asyncapi.yaml +208 -0
  1119. package/examples/docs/features/archive/FEAT-120-refund-notification/specs/notification-service/spec.md +24 -0
  1120. package/examples/docs/features/archive/FEAT-120-refund-notification/specs/payment-service/asyncapi.yaml +137 -0
  1121. package/examples/docs/features/archive/FEAT-120-refund-notification/specs/payment-service/spec.md +31 -0
  1122. package/examples/docs/features/archive/FEAT-120-refund-notification/verification.yaml +84 -0
  1123. package/examples/docs/glossary/order.md +15 -0
  1124. package/examples/docs/glossary/payments/authorization.md +14 -0
  1125. package/examples/docs/likec4.config.json +8 -0
  1126. package/examples/docs/loam.json +3 -0
  1127. package/examples/docs/services/checkout-web/model.likec4 +92 -0
  1128. package/examples/docs/services/checkout-web/spec.md +91 -0
  1129. package/examples/docs/services/checkout-web/ui/pages/checkout.page.yaml +40 -0
  1130. package/examples/docs/services/checkout-web/ui/pages/order-status.page.yaml +24 -0
  1131. package/examples/docs/services/checkout-web/ui/pages/split-payment.page.yaml +26 -0
  1132. package/examples/docs/services/order-service/adrs/0001-orchestrated-order-lifecycle.md +52 -0
  1133. package/examples/docs/services/order-service/arch.spec.md +134 -0
  1134. package/examples/docs/services/order-service/asyncapi.yaml +109 -0
  1135. package/examples/docs/services/order-service/health.yaml +57 -0
  1136. package/examples/docs/services/order-service/model.likec4 +126 -0
  1137. package/examples/docs/services/order-service/openapi.yaml +257 -0
  1138. package/examples/docs/services/order-service/runbook.md +62 -0
  1139. package/examples/docs/services/order-service/spec.md +134 -0
  1140. package/examples/docs/services/payment-service/adrs/0001-payments-outbox.md +18 -0
  1141. package/examples/docs/services/payment-service/adrs/0002-idempotency-keys-on-authorization.md +27 -0
  1142. package/examples/docs/services/payment-service/arch.spec.md +76 -0
  1143. package/examples/docs/services/payment-service/asyncapi.yaml +130 -0
  1144. package/examples/docs/services/payment-service/health.yaml +39 -0
  1145. package/examples/docs/services/payment-service/model.likec4 +68 -0
  1146. package/examples/docs/services/payment-service/openapi.yaml +151 -0
  1147. package/examples/docs/services/payment-service/runbook.md +37 -0
  1148. package/examples/docs/services/payment-service/spec.md +88 -0
  1149. package/examples/docs/services/platform/identity-service/adrs/0001-token-introspection-over-local-validation.md +60 -0
  1150. package/examples/docs/services/platform/identity-service/arch.spec.md +120 -0
  1151. package/examples/docs/services/platform/identity-service/health.yaml +70 -0
  1152. package/examples/docs/services/platform/identity-service/model.likec4 +81 -0
  1153. package/examples/docs/services/platform/identity-service/openapi.yaml +197 -0
  1154. package/examples/docs/services/platform/identity-service/runbook.md +95 -0
  1155. package/examples/docs/services/platform/identity-service/spec.md +119 -0
  1156. package/examples/docs/services/platform/notification-service/asyncapi.yaml +200 -0
  1157. package/examples/docs/services/platform/notification-service/health.yaml +40 -0
  1158. package/examples/docs/services/platform/notification-service/model.likec4 +97 -0
  1159. package/examples/docs/services/platform/notification-service/runbook.md +48 -0
  1160. package/examples/docs/services/platform/notification-service/spec.md +112 -0
  1161. package/examples/docs/services/platform/subsystem.yaml +2 -0
  1162. package/examples/fleet.yaml +57 -0
  1163. package/package.json +19 -6
  1164. package/dist/commands/adopt.js +0 -240
  1165. package/dist/commands/adopt.js.map +0 -1
  1166. package/dist/commands/archive.js +0 -1313
  1167. package/dist/commands/archive.js.map +0 -1
  1168. package/dist/commands/delta.js +0 -388
  1169. package/dist/commands/delta.js.map +0 -1
  1170. package/dist/commands/docs-repo-gate.js.map +0 -1
  1171. package/dist/commands/format.js +0 -17
  1172. package/dist/commands/format.js.map +0 -1
  1173. package/dist/commands/gherkin.js +0 -309
  1174. package/dist/commands/gherkin.js.map +0 -1
  1175. package/dist/commands/init.js.map +0 -1
  1176. package/dist/commands/list.js +0 -295
  1177. package/dist/commands/list.js.map +0 -1
  1178. package/dist/commands/migrate-openspec.js +0 -950
  1179. package/dist/commands/migrate-openspec.js.map +0 -1
  1180. package/dist/commands/new.js +0 -413
  1181. package/dist/commands/new.js.map +0 -1
  1182. package/dist/commands/rebase.js +0 -356
  1183. package/dist/commands/rebase.js.map +0 -1
  1184. package/dist/commands/show.js +0 -320
  1185. package/dist/commands/show.js.map +0 -1
  1186. package/dist/commands/status.js +0 -262
  1187. package/dist/commands/status.js.map +0 -1
  1188. package/dist/commands/unarchive.js +0 -317
  1189. package/dist/commands/unarchive.js.map +0 -1
  1190. package/dist/commands/validate.js +0 -1773
  1191. package/dist/commands/validate.js.map +0 -1
  1192. package/dist/commands/verify.js +0 -775
  1193. package/dist/commands/verify.js.map +0 -1
  1194. package/dist/commands/vouch.js +0 -421
  1195. package/dist/commands/vouch.js.map +0 -1
  1196. package/dist/core/agent.js +0 -2173
  1197. package/dist/core/agent.js.map +0 -1
  1198. package/dist/core/agents-stamp.js.map +0 -1
  1199. package/dist/core/arch.js +0 -130
  1200. package/dist/core/arch.js.map +0 -1
  1201. package/dist/core/asyncapi.js +0 -253
  1202. package/dist/core/asyncapi.js.map +0 -1
  1203. package/dist/core/brief.js +0 -755
  1204. package/dist/core/brief.js.map +0 -1
  1205. package/dist/core/coherence.js +0 -577
  1206. package/dist/core/coherence.js.map +0 -1
  1207. package/dist/core/concurrency.js.map +0 -1
  1208. package/dist/core/config.js.map +0 -1
  1209. package/dist/core/delta.js +0 -476
  1210. package/dist/core/delta.js.map +0 -1
  1211. package/dist/core/dependencies.js +0 -356
  1212. package/dist/core/dependencies.js.map +0 -1
  1213. package/dist/core/doctor.js +0 -596
  1214. package/dist/core/doctor.js.map +0 -1
  1215. package/dist/core/document-bytes.js.map +0 -1
  1216. package/dist/core/explore.js +0 -225
  1217. package/dist/core/explore.js.map +0 -1
  1218. package/dist/core/frontmatter.js.map +0 -1
  1219. package/dist/core/gherkin.js +0 -463
  1220. package/dist/core/gherkin.js.map +0 -1
  1221. package/dist/core/health.js +0 -67
  1222. package/dist/core/health.js.map +0 -1
  1223. package/dist/core/ids.js +0 -122
  1224. package/dist/core/ids.js.map +0 -1
  1225. package/dist/core/issue.js +0 -9
  1226. package/dist/core/issue.js.map +0 -1
  1227. package/dist/core/json.js +0 -74
  1228. package/dist/core/json.js.map +0 -1
  1229. package/dist/core/likec4.js +0 -489
  1230. package/dist/core/likec4.js.map +0 -1
  1231. package/dist/core/maturity.js +0 -66
  1232. package/dist/core/maturity.js.map +0 -1
  1233. package/dist/core/openapi-merge.js +0 -552
  1234. package/dist/core/openapi-merge.js.map +0 -1
  1235. package/dist/core/openapi.js.map +0 -1
  1236. package/dist/core/openspec-inventory.js +0 -1440
  1237. package/dist/core/openspec-inventory.js.map +0 -1
  1238. package/dist/core/path-safety.js.map +0 -1
  1239. package/dist/core/provenance.js +0 -787
  1240. package/dist/core/provenance.js.map +0 -1
  1241. package/dist/core/records.js.map +0 -1
  1242. package/dist/core/repo.js +0 -438
  1243. package/dist/core/repo.js.map +0 -1
  1244. package/dist/core/report.js +0 -47
  1245. package/dist/core/report.js.map +0 -1
  1246. package/dist/core/spec.js +0 -505
  1247. package/dist/core/spec.js.map +0 -1
  1248. package/dist/core/staging.js +0 -890
  1249. package/dist/core/staging.js.map +0 -1
  1250. package/dist/core/status.js +0 -1132
  1251. package/dist/core/status.js.map +0 -1
  1252. package/dist/core/steps.js +0 -72
  1253. package/dist/core/steps.js.map +0 -1
  1254. package/dist/core/verify.js +0 -807
  1255. package/dist/core/verify.js.map +0 -1
  1256. package/dist/core/version.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalogue.js","sourceRoot":"","sources":["../../../../src/core/gherkin/steps/catalogue.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The step catalogue: which phrases somebody has DECIDED the suite defines.\n *\n * ## The decision this file records, because it was the open question\n *\n * `./inventory.ts` answers how many definitions a suite needs. It stops there on\n * purpose — no file, no finding, no stable code — and the gap it leaves is the\n * next ARTIFACT, not the next warning: a team reads the report, writes the glue\n * by hand, and nothing anywhere records which phrases now have definitions, so\n * the report is recomputed from scratch every time instead of diffed against a\n * decision somebody made.\n *\n * The catalogue is **AUTHORED**, not emitted, and it lives in the DOCS repo at\n * `services/<svc>/steps.yaml`. Four things decided it:\n *\n * - It is a DECISION, not an observation. loam does not read code and must\n * never present a derived thing as truth (the non-goal is written down); what\n * a team can say is \"these are the phrases we have agreed to define\", and\n * that sentence is an authored document by construction. An emitted\n * catalogue would have to be derived from a step registry loam cannot read.\n * - `loam steps` NEEDS NO SERVICE REPO to stand in — that is its own stated\n * design, and it reads the living specs rather than the emitted `.feature`\n * files precisely so it answers the same way in a repo that has never run\n * `loam gherkin`. A catalogue in the service repo would make the comparison\n * require one, which is a different command.\n * - The shape rule the glossary and capability trees already settled: an entry\n * with prose gets a file, an entry WITHOUT prose stays a line in YAML. A\n * catalogue entry is a phrase and nothing else, so it is a line in YAML — the\n * same side of that rule `architecture/capabilities.yaml` and\n * `permissions.yaml` sit on.\n * - Nothing generated may land inside `<gherkinDir>/loam/`, which `loam\n * gherkin` owns and overwrites wholesale. Living in the docs repo satisfies\n * that by construction rather than by a rule somebody has to remember.\n *\n * SERVICE-SCOPED, beside `health.yaml`, because a step registry belongs to one\n * suite and a suite belongs to one service. A fleet-level catalogue would claim\n * one registry across services that do not share a test runner.\n *\n * ## What it does NOT do, and this is the other half of the decision\n *\n * **It gains no stable code, and `loam validate` never reads it.** A phrase\n * written but not catalogued is a work-list row, not a breach: writing a spec\n * ahead of the glue is the normal order, and a check that fires on it is the\n * kind a fleet turns off — at which point the real findings beside it are turned\n * off too. The near-duplicate groups stay a report for the same reason. So this\n * axis costs one document kind and zero codes, and everything it produces is\n * columns in `loam steps`.\n *\n * **It claims nothing about whether the glue exists.** A catalogued phrase is a\n * phrase somebody said they would define; loam cannot see a step registry and\n * does not pretend to. The two columns are named for what they actually mean —\n * written-not-catalogued and catalogued-not-written — and neither says \"missing\n * definition\".\n *\n * ## The grammar\n *\n * ```yaml\n * steps:\n * - a payment of 100.00\n * - Given it is split 60/40\n * ```\n *\n * A list of step TEXTS, not of keys. The key is loam's own spelling — `{n}`,\n * `{s}`, `{p}` collapse, keyword stripped (`./phrase.ts`) — and asking an author\n * to write it would make an internal normalisation a hand-typed contract, where\n * one wrong brace silently catalogues nothing. So an entry is written the way a\n * step is written, with or without its keyword, and loam keys it the same way it\n * keys the written steps it is being compared against. Two entries that collapse\n * onto one key are reported as such rather than merged: that is the author\n * cataloguing one definition twice, which is exactly what the near-duplicate\n * report exists to surface.\n */\nimport { existsSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport { parse as parseYaml } from \"yaml\";\nimport { isRecord } from \"../../kernel/records.js\";\nimport { compareIds } from \"../../repo/entries.js\";\nimport { phraseOf } from \"./phrase.js\";\nimport { type StepInventory } from \"./inventory.js\";\n\n/** One catalogued phrase: what the author wrote, and the key loam derived from it. */\nexport interface CatalogueEntry {\n /** The entry exactly as `steps.yaml` spells it. */\n text: string;\n /** The normalized phrase — the same key `./inventory.ts` gives a written step. */\n key: string;\n}\n\n/** What `services/<svc>/steps.yaml` says, or the honest refusal to say. */\nexport interface StepCatalogue {\n /** False when the service has no `steps.yaml` — which is every service until one opts in. */\n present: boolean;\n /**\n * Why the file could not be read, when it exists and does not parse as the\n * grammar above. A REASON rather than a boolean, because the report prints it:\n * \"could not look\" is only useful if it says what stopped it.\n */\n unreadable?: string;\n /** The catalogued entries, in the order the file lists them. */\n entries: CatalogueEntry[];\n}\n\nconst ABSENT: StepCatalogue = { present: false, entries: [] };\n\n/**\n * Read one service's catalogue.\n *\n * A missing file is silence, not an error: the axis's opt-in is the file's\n * existence, exactly as `capabilities/`'s is a directory's. Anything present and\n * unparseable is `unreadable` with the reason — never an empty catalogue, which\n * would report every written phrase as uncatalogued and read as a work-list\n * somebody has to do.\n */\nexport async function readStepCatalogue(path: string): Promise<StepCatalogue> {\n if (!existsSync(path)) return ABSENT;\n let doc: unknown;\n try {\n doc = parseYaml(await readFile(path, \"utf8\"));\n } catch (e) {\n return { present: true, entries: [], unreadable: e instanceof Error ? e.message : String(e) };\n }\n if (doc === null || doc === undefined) return { present: true, entries: [] };\n if (!isRecord(doc)) return { present: true, entries: [], unreadable: \"the document is not a mapping\" };\n const block = doc[\"steps\"];\n if (block === undefined) return { present: true, entries: [] };\n if (!Array.isArray(block)) {\n return { present: true, entries: [], unreadable: \"`steps` is not a list of step texts\" };\n }\n const entries: CatalogueEntry[] = [];\n for (const item of block) {\n // A non-string entry refuses the whole file rather than being skipped. A\n // skipped entry is a phrase silently absent from the catalogue, which prints\n // as \"written but not catalogued\" — a work-list row invented by a shape\n // error, which is the wrong answer this fails closed to avoid.\n if (typeof item !== \"string\") {\n return { present: true, entries: [], unreadable: \"every `steps` entry must be a step text (a string)\" };\n }\n entries.push({ text: item, key: phraseOf(item).key });\n }\n return { present: true, entries };\n}\n\n/** The two lists a report needs, plus the entries an author catalogued twice. */\nexport interface CatalogueComparison {\n /** Written phrase keys the catalogue does not list, most-used first — the work-list. */\n uncatalogued: string[];\n /** Catalogued keys nothing in the living specs writes — a definition with nothing to match. */\n unwritten: string[];\n /** Keys two or more catalogue entries collapse onto, with every spelling. */\n duplicated: Array<{ key: string; texts: string[] }>;\n}\n\n/**\n * Written phrases against catalogued ones.\n *\n * ORDER IS THE INVENTORY'S for `uncatalogued` — `inv.phrases` is already sorted\n * count-descending then key-ascending, so the work-list comes out with the\n * phrase that pays back most first, and stays diffable. `unwritten` and\n * `duplicated` have no count to sort on and are sorted by key.\n *\n * The catalogue's own `present`/`unreadable` state is NOT consulted here: this\n * is the comparison, and whether it was worth making is the caller's question.\n * Handing it an unreadable catalogue would produce a full `uncatalogued` list\n * that reads exactly like a real work-list, which is why the caller checks first.\n */\nexport function compareToCatalogue(inv: StepInventory, catalogue: StepCatalogue): CatalogueComparison {\n const catalogued = new Set(catalogue.entries.map((e) => e.key));\n const written = new Set(inv.phrases.map((p) => p.key));\n const bySpelling = new Map<string, string[]>();\n for (const entry of catalogue.entries) {\n const texts = bySpelling.get(entry.key) ?? [];\n texts.push(entry.text);\n bySpelling.set(entry.key, texts);\n }\n return {\n uncatalogued: inv.phrases.filter((p) => !catalogued.has(p.key)).map((p) => p.key),\n unwritten: [...catalogued].filter((key) => !written.has(key)).sort(compareIds),\n duplicated: [...bySpelling]\n .filter(([, texts]) => texts.length > 1)\n .map(([key, texts]) => ({ key, texts }))\n .sort((a, b) => compareIds(a.key, b.key)),\n };\n}\n"]}
@@ -0,0 +1,98 @@
1
+ /**
2
+ * The step-phrase inventory: how many DEFINITIONS a service's suite actually
3
+ * needs, and which written steps collapse onto each one.
4
+ *
5
+ * ## What this is for
6
+ *
7
+ * Generated `.feature` files are only a suite if somebody writes the glue, and
8
+ * the glue is where a generated suite dies: the step text is free prose from a
9
+ * spec bullet, so the same precondition gets three spellings across three
10
+ * requirements and the registry grows without bound until people quietly go
11
+ * back to hand-written tests. Nothing in loam could previously say how bad that
12
+ * was, which meant nobody could tell a suite that needs forty definitions from
13
+ * one that needs four hundred.
14
+ *
15
+ * Measured on a real twelve-scenario component-test file, 324 written steps
16
+ * collapse to 97 phrases, and 34 of those cover 82% of every step — so the
17
+ * report is not an audit, it is the work-list a team writes glue from, and the
18
+ * draft of any step catalogue that comes later.
19
+ *
20
+ * ## What it deliberately is NOT
21
+ *
22
+ * It emits no finding and no stable code. A near-duplicate is a judgement about
23
+ * writing, and a phrase-similarity WARNING is the kind of check a fleet turns
24
+ * off — at which point the real findings beside it are turned off too. It reads
25
+ * the LIVING specs rather than the emitted files, so it answers the same way in
26
+ * a repo that has never run `loam gherkin` and needs no service repo to stand
27
+ * in.
28
+ */
29
+ import { scenarioGherkin } from "../../vocabulary/steps.js";
30
+ import {} from "../../document/spec.js";
31
+ import { keywordOf, phraseOf } from "./phrase.js";
32
+ /**
33
+ * Count the phrases across both axes of one service.
34
+ *
35
+ * REMOVED requirements are skipped, exactly as every other scenario check skips
36
+ * them: a step nobody will run is not glue anybody owes.
37
+ *
38
+ * Ordering is count-descending then key-ascending, and that second key is what
39
+ * makes the report diffable — two phrases used once each must not swap places
40
+ * between runs because a Map happened to iterate differently.
41
+ */
42
+ export function stepInventory(axes) {
43
+ const byKey = new Map();
44
+ const families = new Map();
45
+ let steps = 0;
46
+ for (const { axis, reqs } of axes) {
47
+ for (const r of reqs) {
48
+ if (r.kind === "REMOVED")
49
+ continue;
50
+ for (const s of r.scenarios) {
51
+ for (const st of scenarioGherkin(s.lines).steps) {
52
+ steps += 1;
53
+ const { key, family } = phraseOf(st.text);
54
+ const row = byKey.get(key) ?? { key, count: 0, keywords: [], uses: [] };
55
+ row.count += 1;
56
+ const kw = keywordOf(st.text);
57
+ if (kw.length > 0 && !row.keywords.includes(kw))
58
+ row.keywords.push(kw);
59
+ row.uses.push({ requirement: r.name, scenario: s.name, axis, text: st.text });
60
+ byKey.set(key, row);
61
+ const seen = families.get(family) ?? new Set();
62
+ seen.add(key);
63
+ families.set(family, seen);
64
+ }
65
+ }
66
+ }
67
+ }
68
+ const phrases = [...byKey.values()]
69
+ .map((row) => ({ ...row, keywords: [...row.keywords].sort() }))
70
+ .sort((a, b) => b.count - a.count || (a.key < b.key ? -1 : a.key > b.key ? 1 : 0));
71
+ const nearDuplicates = [...families.entries()]
72
+ .filter(([, keys]) => keys.size > 1)
73
+ .map(([family, keys]) => ({ family, keys: [...keys].sort() }))
74
+ .sort((a, b) => (a.family < b.family ? -1 : a.family > b.family ? 1 : 0));
75
+ return { steps, phrases, nearDuplicates };
76
+ }
77
+ /**
78
+ * How many phrases cover `share` of every written step — the one number that
79
+ * says whether the glue is a morning's work or a quarter's.
80
+ *
81
+ * Returns zero for an empty suite rather than dividing by it, because "0 of 0
82
+ * steps" is the honest reading of a service that has written no scenarios yet.
83
+ */
84
+ export function coveringPhrases(inv, share = 0.8) {
85
+ if (inv.steps === 0)
86
+ return 0;
87
+ const target = inv.steps * share;
88
+ let running = 0;
89
+ let n = 0;
90
+ for (const row of inv.phrases) {
91
+ if (running >= target)
92
+ break;
93
+ running += row.count;
94
+ n += 1;
95
+ }
96
+ return n;
97
+ }
98
+ //# sourceMappingURL=inventory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inventory.js","sourceRoot":"","sources":["../../../../src/core/gherkin/steps/inventory.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The step-phrase inventory: how many DEFINITIONS a service's suite actually\n * needs, and which written steps collapse onto each one.\n *\n * ## What this is for\n *\n * Generated `.feature` files are only a suite if somebody writes the glue, and\n * the glue is where a generated suite dies: the step text is free prose from a\n * spec bullet, so the same precondition gets three spellings across three\n * requirements and the registry grows without bound until people quietly go\n * back to hand-written tests. Nothing in loam could previously say how bad that\n * was, which meant nobody could tell a suite that needs forty definitions from\n * one that needs four hundred.\n *\n * Measured on a real twelve-scenario component-test file, 324 written steps\n * collapse to 97 phrases, and 34 of those cover 82% of every step — so the\n * report is not an audit, it is the work-list a team writes glue from, and the\n * draft of any step catalogue that comes later.\n *\n * ## What it deliberately is NOT\n *\n * It emits no finding and no stable code. A near-duplicate is a judgement about\n * writing, and a phrase-similarity WARNING is the kind of check a fleet turns\n * off — at which point the real findings beside it are turned off too. It reads\n * the LIVING specs rather than the emitted files, so it answers the same way in\n * a repo that has never run `loam gherkin` and needs no service repo to stand\n * in.\n */\nimport { scenarioGherkin } from \"../../vocabulary/steps.js\";\nimport { type Requirement } from \"../../document/spec.js\";\nimport { keywordOf, phraseOf } from \"./phrase.js\";\n\n/** Where one written step lives, for the reader who wants to go and look. */\nexport interface PhraseUse {\n requirement: string;\n scenario: string;\n /** \"business\" or \"arch\" — the two spec files are two namespaces everywhere else too. */\n axis: string;\n /** The step exactly as the spec writes it, keyword included. */\n text: string;\n}\n\nexport interface PhraseRow {\n /** The normalized phrase — one step definition serves every use under it. */\n key: string;\n /** How many written steps collapse onto this key. */\n count: number;\n /** The Gherkin keywords this phrase appears under, sorted — a runner resolves them as one. */\n keywords: string[];\n uses: PhraseUse[];\n}\n\n/** Phrases that share a family and not a key: two definitions where one was probably meant. */\nexport interface NearDuplicates {\n family: string;\n keys: string[];\n}\n\nexport interface StepInventory {\n /** Total written steps across every scenario of both axes. */\n steps: number;\n /** Distinct phrases, most-used first, then alphabetically so the report is stable. */\n phrases: PhraseRow[];\n nearDuplicates: NearDuplicates[];\n}\n\n/** One spec file's requirements, with the axis label the whole product speaks. */\nexport interface InventoryAxis {\n axis: string;\n reqs: Requirement[];\n}\n\n/**\n * Count the phrases across both axes of one service.\n *\n * REMOVED requirements are skipped, exactly as every other scenario check skips\n * them: a step nobody will run is not glue anybody owes.\n *\n * Ordering is count-descending then key-ascending, and that second key is what\n * makes the report diffable — two phrases used once each must not swap places\n * between runs because a Map happened to iterate differently.\n */\nexport function stepInventory(axes: readonly InventoryAxis[]): StepInventory {\n const byKey = new Map<string, PhraseRow>();\n const families = new Map<string, Set<string>>();\n let steps = 0;\n for (const { axis, reqs } of axes) {\n for (const r of reqs) {\n if (r.kind === \"REMOVED\") continue;\n for (const s of r.scenarios) {\n for (const st of scenarioGherkin(s.lines).steps) {\n steps += 1;\n const { key, family } = phraseOf(st.text);\n const row = byKey.get(key) ?? { key, count: 0, keywords: [], uses: [] };\n row.count += 1;\n const kw = keywordOf(st.text);\n if (kw.length > 0 && !row.keywords.includes(kw)) row.keywords.push(kw);\n row.uses.push({ requirement: r.name, scenario: s.name, axis, text: st.text });\n byKey.set(key, row);\n const seen = families.get(family) ?? new Set<string>();\n seen.add(key);\n families.set(family, seen);\n }\n }\n }\n }\n const phrases = [...byKey.values()]\n .map((row) => ({ ...row, keywords: [...row.keywords].sort() }))\n .sort((a, b) => b.count - a.count || (a.key < b.key ? -1 : a.key > b.key ? 1 : 0));\n const nearDuplicates = [...families.entries()]\n .filter(([, keys]) => keys.size > 1)\n .map(([family, keys]) => ({ family, keys: [...keys].sort() }))\n .sort((a, b) => (a.family < b.family ? -1 : a.family > b.family ? 1 : 0));\n return { steps, phrases, nearDuplicates };\n}\n\n/**\n * How many phrases cover `share` of every written step — the one number that\n * says whether the glue is a morning's work or a quarter's.\n *\n * Returns zero for an empty suite rather than dividing by it, because \"0 of 0\n * steps\" is the honest reading of a service that has written no scenarios yet.\n */\nexport function coveringPhrases(inv: StepInventory, share = 0.8): number {\n if (inv.steps === 0) return 0;\n const target = inv.steps * share;\n let running = 0;\n let n = 0;\n for (const row of inv.phrases) {\n if (running >= target) break;\n running += row.count;\n n += 1;\n }\n return n;\n}\n"]}
@@ -0,0 +1,72 @@
1
+ /**
2
+ * The PHRASE KEY: what makes two written steps the same step definition.
3
+ *
4
+ * `loam steps` counts by this key, so the moment it ships the recipe is a
5
+ * contract — a team writes glue against the groups it reports, and a key that
6
+ * drifts re-partitions their whole registry. `test/steps-inventory.test.ts`
7
+ * pins it case by case for that reason.
8
+ *
9
+ * ## Why the keyword is dropped
10
+ *
11
+ * Every mainstream runner resolves Given/When/Then/And/But against ONE registry
12
+ * of patterns, so `Given the ledger is open` and `And the ledger is open` are
13
+ * one definition and must count as one row. Keeping the keyword would split
14
+ * every continued step from the step it continues, and the number the whole
15
+ * report exists to give — how many definitions does this suite need — would be
16
+ * wrong in the direction that flatters it.
17
+ *
18
+ * ## Why literals collapse and prose does not
19
+ *
20
+ * A quoted string, an angle-bracket placeholder and a bare number are what a
21
+ * step definition captures as an ARGUMENT; everything else is what it matches
22
+ * on. Collapsing exactly those three is therefore not a heuristic about
23
+ * similarity — it is the same partition the runner will make when the patterns
24
+ * are written. Nothing here measures edit distance: `core/repo/entries.ts`
25
+ * already records that verdict for close-id suggestions, and a third private
26
+ * copy of that function would be the drift it warns about.
27
+ */
28
+ const KEYWORD_RE = /^(given|when|then|and|but)\s+/i;
29
+ /**
30
+ * A subordinate clause that explains WHY, which a step definition never
31
+ * matches on separately: `validation branch "x" passes because the window is
32
+ * open` is the same definition as `validation branch "x" passes`, with the
33
+ * reason baked into the pattern. Reported as a near-duplicate rather than
34
+ * merged, because the fix — move the reason into the scenario description — is
35
+ * the author's to make.
36
+ */
37
+ const RATIONALE_RE = /\s+(because|while|since|unless|so that)\s+.*$/i;
38
+ const LEADING_ARTICLE_RE = /^(the|a|an)\s+/i;
39
+ /** `Given a payment of 100.00 for "<tier>"` -> key `a payment of {n} for {s}`. */
40
+ export function phraseOf(stepText) {
41
+ const key = stepText
42
+ .replace(KEYWORD_RE, "")
43
+ // A QUOTED placeholder is still a placeholder — `"<tier>"` is the outline's
44
+ // parameter, and letting the string rule reach it first would collapse the
45
+ // whole token to {s} and hide that the step is parameterized at all.
46
+ .replace(/(["'`])<[^<>\s]+>\1/g, "{p}")
47
+ .replace(/<[^<>\s]+>/g, "{p}")
48
+ .replace(/"[^"]*"/g, "{s}")
49
+ .replace(/'[^']*'/g, "{s}")
50
+ .replace(/`[^`]*`/g, "{s}")
51
+ // A number only when it stands alone: `v1` and `oauth2` are part of a name,
52
+ // and collapsing them would merge two steps that match different patterns.
53
+ .replace(/(?<![\w.])\d+(?:\.\d+)?(?![\w.])/g, "{n}")
54
+ .replace(/\s+/g, " ")
55
+ .trim();
56
+ const family = key
57
+ .replace(RATIONALE_RE, "")
58
+ .replace(LEADING_ARTICLE_RE, "")
59
+ .replace(/[.,;:]+$/, "")
60
+ .replace(/\s+/g, " ")
61
+ .trim();
62
+ return { key, family };
63
+ }
64
+ /** The canonical keyword of a written step line, for reporting which ones a phrase appears under. */
65
+ export function keywordOf(stepText) {
66
+ const m = KEYWORD_RE.exec(stepText);
67
+ if (!m)
68
+ return "";
69
+ const w = m[1].toLowerCase();
70
+ return w[0].toUpperCase() + w.slice(1);
71
+ }
72
+ //# sourceMappingURL=phrase.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"phrase.js","sourceRoot":"","sources":["../../../../src/core/gherkin/steps/phrase.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,MAAM,UAAU,GAAG,gCAAgC,CAAC;AAEpD;;;;;;;GAOG;AACH,MAAM,YAAY,GAAG,gDAAgD,CAAC;AAEtE,MAAM,kBAAkB,GAAG,iBAAiB,CAAC;AAa7C,kFAAkF;AAClF,MAAM,UAAU,QAAQ,CAAC,QAAgB;IACvC,MAAM,GAAG,GAAG,QAAQ;SACjB,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC;QACxB,4EAA4E;QAC5E,2EAA2E;QAC3E,qEAAqE;SACpE,OAAO,CAAC,sBAAsB,EAAE,KAAK,CAAC;SACtC,OAAO,CAAC,aAAa,EAAE,KAAK,CAAC;SAC7B,OAAO,CAAC,UAAU,EAAE,KAAK,CAAC;SAC1B,OAAO,CAAC,UAAU,EAAE,KAAK,CAAC;SAC1B,OAAO,CAAC,UAAU,EAAE,KAAK,CAAC;QAC3B,4EAA4E;QAC5E,2EAA2E;SAC1E,OAAO,CAAC,mCAAmC,EAAE,KAAK,CAAC;SACnD,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;SACpB,IAAI,EAAE,CAAC;IACV,MAAM,MAAM,GAAG,GAAG;SACf,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC;SACzB,OAAO,CAAC,kBAAkB,EAAE,EAAE,CAAC;SAC/B,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC;SACvB,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;SACpB,IAAI,EAAE,CAAC;IACV,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC;AACzB,CAAC;AAED,qGAAqG;AACrG,MAAM,UAAU,SAAS,CAAC,QAAgB;IACxC,MAAM,CAAC,GAAG,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACpC,IAAI,CAAC,CAAC;QAAE,OAAO,EAAE,CAAC;IAClB,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAE,CAAC,WAAW,EAAE,CAAC;IAC9B,OAAO,CAAC,CAAC,CAAC,CAAE,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAC1C,CAAC","sourcesContent":["/**\n * The PHRASE KEY: what makes two written steps the same step definition.\n *\n * `loam steps` counts by this key, so the moment it ships the recipe is a\n * contract — a team writes glue against the groups it reports, and a key that\n * drifts re-partitions their whole registry. `test/steps-inventory.test.ts`\n * pins it case by case for that reason.\n *\n * ## Why the keyword is dropped\n *\n * Every mainstream runner resolves Given/When/Then/And/But against ONE registry\n * of patterns, so `Given the ledger is open` and `And the ledger is open` are\n * one definition and must count as one row. Keeping the keyword would split\n * every continued step from the step it continues, and the number the whole\n * report exists to give — how many definitions does this suite need — would be\n * wrong in the direction that flatters it.\n *\n * ## Why literals collapse and prose does not\n *\n * A quoted string, an angle-bracket placeholder and a bare number are what a\n * step definition captures as an ARGUMENT; everything else is what it matches\n * on. Collapsing exactly those three is therefore not a heuristic about\n * similarity — it is the same partition the runner will make when the patterns\n * are written. Nothing here measures edit distance: `core/repo/entries.ts`\n * already records that verdict for close-id suggestions, and a third private\n * copy of that function would be the drift it warns about.\n */\n\nconst KEYWORD_RE = /^(given|when|then|and|but)\\s+/i;\n\n/**\n * A subordinate clause that explains WHY, which a step definition never\n * matches on separately: `validation branch \"x\" passes because the window is\n * open` is the same definition as `validation branch \"x\" passes`, with the\n * reason baked into the pattern. Reported as a near-duplicate rather than\n * merged, because the fix — move the reason into the scenario description — is\n * the author's to make.\n */\nconst RATIONALE_RE = /\\s+(because|while|since|unless|so that)\\s+.*$/i;\n\nconst LEADING_ARTICLE_RE = /^(the|a|an)\\s+/i;\n\nexport interface Phrase {\n /** Two steps sharing this need ONE step definition. */\n key: string;\n /**\n * The looser key that gathers near-duplicates: the same phrase with a leading\n * article or a trailing rationale clause. Steps sharing a family but not a key\n * are two definitions where the author probably meant one.\n */\n family: string;\n}\n\n/** `Given a payment of 100.00 for \"<tier>\"` -> key `a payment of {n} for {s}`. */\nexport function phraseOf(stepText: string): Phrase {\n const key = stepText\n .replace(KEYWORD_RE, \"\")\n // A QUOTED placeholder is still a placeholder — `\"<tier>\"` is the outline's\n // parameter, and letting the string rule reach it first would collapse the\n // whole token to {s} and hide that the step is parameterized at all.\n .replace(/([\"'`])<[^<>\\s]+>\\1/g, \"{p}\")\n .replace(/<[^<>\\s]+>/g, \"{p}\")\n .replace(/\"[^\"]*\"/g, \"{s}\")\n .replace(/'[^']*'/g, \"{s}\")\n .replace(/`[^`]*`/g, \"{s}\")\n // A number only when it stands alone: `v1` and `oauth2` are part of a name,\n // and collapsing them would merge two steps that match different patterns.\n .replace(/(?<![\\w.])\\d+(?:\\.\\d+)?(?![\\w.])/g, \"{n}\")\n .replace(/\\s+/g, \" \")\n .trim();\n const family = key\n .replace(RATIONALE_RE, \"\")\n .replace(LEADING_ARTICLE_RE, \"\")\n .replace(/[.,;:]+$/, \"\")\n .replace(/\\s+/g, \" \")\n .trim();\n return { key, family };\n}\n\n/** The canonical keyword of a written step line, for reporting which ones a phrase appears under. */\nexport function keywordOf(stepText: string): string {\n const m = KEYWORD_RE.exec(stepText);\n if (!m) return \"\";\n const w = m[1]!.toLowerCase();\n return w[0]!.toUpperCase() + w.slice(1);\n}\n"]}
@@ -0,0 +1,109 @@
1
+ /**
2
+ * A feature's own glossary deltas: `features/<FEAT>/glossary/<term>.md`.
3
+ *
4
+ * A change that needs a new word brings the word with it. The archive copies the
5
+ * definition into `glossary/`, `loam unarchive` takes it back out with
6
+ * everything else the feature landed, and until then the term is visible in
7
+ * review beside the requirements that use it — which is the whole reason this
8
+ * route exists rather than "remember to edit the glossary too".
9
+ *
10
+ * CREATE-ONLY, and this is the axis's one real design decision rather than an
11
+ * unfinished half. A feature-local capability document is a DELTA — `## ADDED
12
+ * Requirements`, `Requirement-ID:` identity, `Based-On:` pins — because it
13
+ * merges INTO a living document and two features editing one requirement would
14
+ * otherwise silently overwrite each other. A term has none of that: the file is
15
+ * one definition, the merge is a whole-file copy, and there is nothing to merge
16
+ * partially. So rewriting a living definition through a feature would be a
17
+ * silent whole-file replacement with no pin to collide on, where editing
18
+ * `glossary/<term>.md` directly in the same pull request produces an ordinary
19
+ * git conflict that a human resolves. `glossary.term-exists` refuses the first
20
+ * and points at the second.
21
+ *
22
+ * TWO FEATURES INTRODUCING THE SAME WORD is the case that makes the refusal
23
+ * load-bearing rather than pedantic: whichever archives first creates the living
24
+ * definition, and the second is told — loudly, before it merges — that the word
25
+ * now exists and its own file is the one to delete.
26
+ *
27
+ * ONE CALL for the walk, because it is already written: `readGlossary`
28
+ * implements the file-is-a-term rule, the `README.md` exclusion, the nesting and
29
+ * the symlink guard over any root. A second walk for the feature side would be
30
+ * two implementations free to disagree about what a term is.
31
+ */
32
+ import { existsSync } from "node:fs";
33
+ import { join, resolve } from "node:path";
34
+ import { featureGlossaryDir, glossaryDir } from "../repo/authored/paths.js";
35
+ import {} from "../vocabulary/issue.js";
36
+ import { readGlossary } from "./tree.js";
37
+ /**
38
+ * The definitions one feature carries, ordered by id.
39
+ *
40
+ * `present: false` — and zero readdirs — when the feature has no `glossary/`
41
+ * directory, which is every feature in a fleet that has not adopted the axis.
42
+ * That short-circuit is `readGlossary`'s own `existsSync` and it is the whole
43
+ * cost such a fleet pays.
44
+ */
45
+ export function featureGlossary(featureDir) {
46
+ return readGlossary(featureGlossaryDir(featureDir));
47
+ }
48
+ /**
49
+ * Where each of this feature's terms WILL live once the archive merges — the
50
+ * overlay a feature's own documents are allowed to cite.
51
+ *
52
+ * A feature that introduces a word may cite it at its future living path
53
+ * (`../../glossary/order.md` from `intent.md`), because that is where the link
54
+ * points once the feature ships. So while a feature is in flight,
55
+ * `link.unresolved` treats these paths as resolved — the same overlay the
56
+ * capability axis needed for `Realizes:`, and for the same reason: an index
57
+ * built from the LIVING tree alone refuses the feature's own headline flow.
58
+ * Citing the term at its path INSIDE the feature is the other legal spelling,
59
+ * and it no longer rots on the day the feature lands: archive re-points every
60
+ * merged link into the feature at the file's new home
61
+ * (`commands/archive/plan/document/links.ts`).
62
+ */
63
+ export async function featureGlossaryOverlay(docsDir, featureDir) {
64
+ const glossary = await featureGlossary(featureDir);
65
+ return new Set(glossary.terms.map((t) => resolve(livingTermPath(docsDir, t.id))));
66
+ }
67
+ /**
68
+ * `glossary.term-exists` — a term this feature introduces that the living
69
+ * glossary already defines.
70
+ *
71
+ * An ERROR and never a warning-that-gates: unlike `capability.uncovered`, there
72
+ * is no legal reading of it. The merge would replace an authored definition
73
+ * with another one, and no `--approve` makes that a different act than it is.
74
+ * The fix is in the message and is the one a reviewer would give anyway.
75
+ */
76
+ export async function glossaryDeltaIssues(docsDir, featureDir) {
77
+ const glossary = await featureGlossary(featureDir);
78
+ if (!glossary.present)
79
+ return [];
80
+ return glossary.terms
81
+ .filter((term) => existsSync(livingTermPath(docsDir, term.id)))
82
+ .map((term) => ({
83
+ severity: "error",
84
+ code: "glossary.term-exists",
85
+ subject: term.id,
86
+ message: `glossary/${term.id}.md already exists, so this feature's definition of '${term.id}' would replace an authored one wholesale — ` +
87
+ "a feature-local glossary document INTRODUCES a term, it does not rewrite one. " +
88
+ `Delete features/<FEAT>/glossary/${term.id}.md and edit glossary/${term.id}.md directly in this same change, ` +
89
+ "where git produces an ordinary conflict if somebody else is editing it too.",
90
+ }));
91
+ }
92
+ /**
93
+ * The LIVING path a feature-local term id addresses. Spelled here because three
94
+ * readers need it — the refusal above, the overlay, and the archive merge — and
95
+ * a reader that resolved it differently would refuse a term the merge then
96
+ * created anyway.
97
+ *
98
+ * The id is joined un-split, which `node:path` normalizes: `join(dir, "a/b")`
99
+ * and `join(dir, "a", "b")` are the same string. What holds this join is
100
+ * PROVENANCE, exactly as it holds `livingCapabilityPaths` — every id here came
101
+ * out of a `readGlossary` walk, where each component is a `readdir` entry name
102
+ * and therefore a directory or file that exists. No caller takes one from argv;
103
+ * the day one does, it needs the treatment `core/kernel/ids/capability.ts` gave
104
+ * the same hazard one axis over.
105
+ */
106
+ export function livingTermPath(docsDir, id) {
107
+ return join(glossaryDir(docsDir), `${id}.md`);
108
+ }
109
+ //# sourceMappingURL=delta.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delta.js","sourceRoot":"","sources":["../../../src/core/glossary/delta.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAC5E,OAAO,EAAc,MAAM,wBAAwB,CAAC;AAEpD,OAAO,EAAE,YAAY,EAAiB,MAAM,WAAW,CAAC;AAExD;;;;;;;GAOG;AACH,MAAM,UAAU,eAAe,CAAC,UAAsB;IACpD,OAAO,YAAY,CAAC,kBAAkB,CAAC,UAAU,CAAC,CAAC,CAAC;AACtD,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAAC,OAAgB,EAAE,UAAsB;IACnF,MAAM,QAAQ,GAAG,MAAM,eAAe,CAAC,UAAU,CAAC,CAAC;IACnD,OAAO,IAAI,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;AACpF,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,OAAgB,EAAE,UAAsB;IAChF,MAAM,QAAQ,GAAG,MAAM,eAAe,CAAC,UAAU,CAAC,CAAC;IACnD,IAAI,CAAC,QAAQ,CAAC,OAAO;QAAE,OAAO,EAAE,CAAC;IACjC,OAAO,QAAQ,CAAC,KAAK;SAClB,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,UAAU,CAAC,cAAc,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;SAC9D,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACd,QAAQ,EAAE,OAAgB;QAC1B,IAAI,EAAE,sBAA+B;QACrC,OAAO,EAAE,IAAI,CAAC,EAAE;QAChB,OAAO,EACL,YAAY,IAAI,CAAC,EAAE,wDAAwD,IAAI,CAAC,EAAE,8CAA8C;YAChI,gFAAgF;YAChF,mCAAmC,IAAI,CAAC,EAAE,yBAAyB,IAAI,CAAC,EAAE,oCAAoC;YAC9G,6EAA6E;KAChF,CAAC,CAAC,CAAC;AACR,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,cAAc,CAAC,OAAgB,EAAE,EAAU;IACzD,OAAO,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;AAChD,CAAC","sourcesContent":["/**\n * A feature's own glossary deltas: `features/<FEAT>/glossary/<term>.md`.\n *\n * A change that needs a new word brings the word with it. The archive copies the\n * definition into `glossary/`, `loam unarchive` takes it back out with\n * everything else the feature landed, and until then the term is visible in\n * review beside the requirements that use it — which is the whole reason this\n * route exists rather than \"remember to edit the glossary too\".\n *\n * CREATE-ONLY, and this is the axis's one real design decision rather than an\n * unfinished half. A feature-local capability document is a DELTA — `## ADDED\n * Requirements`, `Requirement-ID:` identity, `Based-On:` pins — because it\n * merges INTO a living document and two features editing one requirement would\n * otherwise silently overwrite each other. A term has none of that: the file is\n * one definition, the merge is a whole-file copy, and there is nothing to merge\n * partially. So rewriting a living definition through a feature would be a\n * silent whole-file replacement with no pin to collide on, where editing\n * `glossary/<term>.md` directly in the same pull request produces an ordinary\n * git conflict that a human resolves. `glossary.term-exists` refuses the first\n * and points at the second.\n *\n * TWO FEATURES INTRODUCING THE SAME WORD is the case that makes the refusal\n * load-bearing rather than pedantic: whichever archives first creates the living\n * definition, and the second is told — loudly, before it merges — that the word\n * now exists and its own file is the one to delete.\n *\n * ONE CALL for the walk, because it is already written: `readGlossary`\n * implements the file-is-a-term rule, the `README.md` exclusion, the nesting and\n * the symlink guard over any root. A second walk for the feature side would be\n * two implementations free to disagree about what a term is.\n */\nimport { existsSync } from \"node:fs\";\nimport { join, resolve } from \"node:path\";\nimport { featureGlossaryDir, glossaryDir } from \"../repo/authored/paths.js\";\nimport { type Issue } from \"../vocabulary/issue.js\";\nimport type { DocsDir, FeatureDir } from \"../kernel/ids/dirs.js\";\nimport { readGlossary, type Glossary } from \"./tree.js\";\n\n/**\n * The definitions one feature carries, ordered by id.\n *\n * `present: false` — and zero readdirs — when the feature has no `glossary/`\n * directory, which is every feature in a fleet that has not adopted the axis.\n * That short-circuit is `readGlossary`'s own `existsSync` and it is the whole\n * cost such a fleet pays.\n */\nexport function featureGlossary(featureDir: FeatureDir): Promise<Glossary> {\n return readGlossary(featureGlossaryDir(featureDir));\n}\n\n/**\n * Where each of this feature's terms WILL live once the archive merges — the\n * overlay a feature's own documents are allowed to cite.\n *\n * A feature that introduces a word may cite it at its future living path\n * (`../../glossary/order.md` from `intent.md`), because that is where the link\n * points once the feature ships. So while a feature is in flight,\n * `link.unresolved` treats these paths as resolved — the same overlay the\n * capability axis needed for `Realizes:`, and for the same reason: an index\n * built from the LIVING tree alone refuses the feature's own headline flow.\n * Citing the term at its path INSIDE the feature is the other legal spelling,\n * and it no longer rots on the day the feature lands: archive re-points every\n * merged link into the feature at the file's new home\n * (`commands/archive/plan/document/links.ts`).\n */\nexport async function featureGlossaryOverlay(docsDir: DocsDir, featureDir: FeatureDir): Promise<Set<string>> {\n const glossary = await featureGlossary(featureDir);\n return new Set(glossary.terms.map((t) => resolve(livingTermPath(docsDir, t.id))));\n}\n\n/**\n * `glossary.term-exists` — a term this feature introduces that the living\n * glossary already defines.\n *\n * An ERROR and never a warning-that-gates: unlike `capability.uncovered`, there\n * is no legal reading of it. The merge would replace an authored definition\n * with another one, and no `--approve` makes that a different act than it is.\n * The fix is in the message and is the one a reviewer would give anyway.\n */\nexport async function glossaryDeltaIssues(docsDir: DocsDir, featureDir: FeatureDir): Promise<Issue[]> {\n const glossary = await featureGlossary(featureDir);\n if (!glossary.present) return [];\n return glossary.terms\n .filter((term) => existsSync(livingTermPath(docsDir, term.id)))\n .map((term) => ({\n severity: \"error\" as const,\n code: \"glossary.term-exists\" as const,\n subject: term.id,\n message:\n `glossary/${term.id}.md already exists, so this feature's definition of '${term.id}' would replace an authored one wholesale — ` +\n \"a feature-local glossary document INTRODUCES a term, it does not rewrite one. \" +\n `Delete features/<FEAT>/glossary/${term.id}.md and edit glossary/${term.id}.md directly in this same change, ` +\n \"where git produces an ordinary conflict if somebody else is editing it too.\",\n }));\n}\n\n/**\n * The LIVING path a feature-local term id addresses. Spelled here because three\n * readers need it — the refusal above, the overlay, and the archive merge — and\n * a reader that resolved it differently would refuse a term the merge then\n * created anyway.\n *\n * The id is joined un-split, which `node:path` normalizes: `join(dir, \"a/b\")`\n * and `join(dir, \"a\", \"b\")` are the same string. What holds this join is\n * PROVENANCE, exactly as it holds `livingCapabilityPaths` — every id here came\n * out of a `readGlossary` walk, where each component is a `readdir` entry name\n * and therefore a directory or file that exists. No caller takes one from argv;\n * the day one does, it needs the treatment `core/kernel/ids/capability.ts` gave\n * the same hazard one axis over.\n */\nexport function livingTermPath(docsDir: DocsDir, id: string): string {\n return join(glossaryDir(docsDir), `${id}.md`);\n}\n"]}
@@ -0,0 +1,73 @@
1
+ /**
2
+ * The glossary tree: `glossary/<term>.md`, and the rule that a markdown file
3
+ * under it IS a declared term.
4
+ *
5
+ * WHY A TREE AND NOT A YAML VOCABULARY, at length in `repo/authored/paths.ts`'s
6
+ * `glossaryDir`: a single vocabulary file at fleet scale is unworkable, and a
7
+ * second list is the drift `loam init`'s removed service manifest was removed
8
+ * for. A term is prose — that is what a definition is — so by this codebase's
9
+ * own rule it gets a file.
10
+ *
11
+ * PRESENCE CLASSIFIES, one tree over from `capabilities/`: a `.md` file is a
12
+ * term, a directory is a group the walk descends through. There is no
13
+ * "half-created term" state to name, which is why this walk emits nothing like
14
+ * `capability.doc-missing`: creating a term is writing one file, and an empty
15
+ * grouping directory declares nothing and claims nothing.
16
+ *
17
+ * `README.md` IS NOT A TERM, and it is the one name excluded. A glossary big
18
+ * enough to want an index page is normal, and reporting that page as a word
19
+ * nobody uses would make the axis's only warning fire on the document that
20
+ * explains the axis. Excluded by name rather than by a marker field: the
21
+ * alternative is frontmatter nobody would remember to write.
22
+ *
23
+ * The walk reads directories only and never opens a file. What is IN a term
24
+ * document is prose for a human, and the one thing loam reads from it — the
25
+ * links it writes — is read by `core/links/`, where every other document's are.
26
+ */
27
+ import { existsSync } from "node:fs";
28
+ import { readdir } from "node:fs/promises";
29
+ import { join } from "node:path";
30
+ import { compareIds } from "../repo/entries.js";
31
+ import { entryIs, markDescended } from "../repo/tree/fs.js";
32
+ /** The one filename under `glossary/` that is not a term. */
33
+ const INDEX_PAGE = "README.md";
34
+ /**
35
+ * Read the tree under `root` (`glossaryDir(docsDir)`).
36
+ *
37
+ * A fleet is expected to hold tens to low hundreds of these — a domain's
38
+ * vocabulary, not its data — so the cost is one `readdir` per directory and the
39
+ * walk's expense is a non-question. The symlink-cycle guard is the one
40
+ * `core/repo/tree/walk.ts` and the capability walk both carry
41
+ * (`core/repo/tree/fs.ts`'s `markDescended`), and for the same reason:
42
+ * `entryIs` follows symlinks on purpose, and a followed cycle without a
43
+ * visited set recurses until the stack ends.
44
+ */
45
+ export async function readGlossary(root) {
46
+ if (!existsSync(root))
47
+ return { present: false, terms: [] };
48
+ const state = { terms: [], visited: new Set() };
49
+ await visit({ dir: root, chain: [] }, state);
50
+ state.terms.sort((a, b) => compareIds(a.id, b.id));
51
+ return { present: true, terms: state.terms };
52
+ }
53
+ /** Collect the terms in one directory and walk what is beneath it. */
54
+ async function visit(spot, state) {
55
+ if (!markDescended(spot.dir, state.visited))
56
+ return;
57
+ const entries = (await readdir(spot.dir, { withFileTypes: true })).filter((e) => !e.name.startsWith("."));
58
+ for (const entry of entries.filter((e) => e.name.endsWith(".md")).sort((a, b) => compareIds(a.name, b.name))) {
59
+ if (entry.name === INDEX_PAGE || !entryIs(spot.dir, entry, "file"))
60
+ continue;
61
+ state.terms.push({
62
+ id: [...spot.chain, entry.name.slice(0, -".md".length)].join("/"),
63
+ path: join(spot.dir, entry.name),
64
+ });
65
+ }
66
+ // Sequential, not Promise.all: the visited set is shared mutable state and
67
+ // the walk's correctness under symlinks rests on a child being marked before
68
+ // its sibling asks. These trees are tens of directories at most.
69
+ for (const child of entries.filter((e) => entryIs(spot.dir, e, "dir")).map((e) => e.name).sort()) {
70
+ await visit({ dir: join(spot.dir, child), chain: [...spot.chain, child] }, state);
71
+ }
72
+ }
73
+ //# sourceMappingURL=tree.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tree.js","sourceRoot":"","sources":["../../../src/core/glossary/tree.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The glossary tree: `glossary/<term>.md`, and the rule that a markdown file\n * under it IS a declared term.\n *\n * WHY A TREE AND NOT A YAML VOCABULARY, at length in `repo/authored/paths.ts`'s\n * `glossaryDir`: a single vocabulary file at fleet scale is unworkable, and a\n * second list is the drift `loam init`'s removed service manifest was removed\n * for. A term is prose — that is what a definition is — so by this codebase's\n * own rule it gets a file.\n *\n * PRESENCE CLASSIFIES, one tree over from `capabilities/`: a `.md` file is a\n * term, a directory is a group the walk descends through. There is no\n * \"half-created term\" state to name, which is why this walk emits nothing like\n * `capability.doc-missing`: creating a term is writing one file, and an empty\n * grouping directory declares nothing and claims nothing.\n *\n * `README.md` IS NOT A TERM, and it is the one name excluded. A glossary big\n * enough to want an index page is normal, and reporting that page as a word\n * nobody uses would make the axis's only warning fire on the document that\n * explains the axis. Excluded by name rather than by a marker field: the\n * alternative is frontmatter nobody would remember to write.\n *\n * The walk reads directories only and never opens a file. What is IN a term\n * document is prose for a human, and the one thing loam reads from it — the\n * links it writes — is read by `core/links/`, where every other document's are.\n */\nimport { existsSync } from \"node:fs\";\nimport { readdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { compareIds } from \"../repo/entries.js\";\nimport { entryIs, markDescended } from \"../repo/tree/fs.js\";\n\n/** The one filename under `glossary/` that is not a term. */\nconst INDEX_PAGE = \"README.md\";\n\n/** One defined term: what it is called, and where its definition is. */\nexport interface GlossaryTerm {\n /** The path from `glossary/` to the file, without `.md` — `order`, or `payments/order`. */\n id: string;\n /** Absolute path of the definition. */\n path: string;\n}\n\nexport interface Glossary {\n /**\n * False when `glossary/` does not exist. The directory's existence is the\n * axis's opt-in, so a fleet without one produces nothing here — not an empty\n * glossary, which would read as \"the terms went missing\" to anything counting.\n */\n present: boolean;\n /** Every term found, at any depth, ordered by id. */\n terms: GlossaryTerm[];\n}\n\n/** One directory the walk is looking at: where it is, and how it was reached. */\ninterface Spot {\n dir: string;\n /** Directory names between `glossary/` and this one, outermost first. */\n chain: string[];\n}\n\ninterface WalkState {\n terms: GlossaryTerm[];\n /** Realpaths already descended into — the symlink-cycle guard. */\n visited: Set<string>;\n}\n\n/**\n * Read the tree under `root` (`glossaryDir(docsDir)`).\n *\n * A fleet is expected to hold tens to low hundreds of these — a domain's\n * vocabulary, not its data — so the cost is one `readdir` per directory and the\n * walk's expense is a non-question. The symlink-cycle guard is the one\n * `core/repo/tree/walk.ts` and the capability walk both carry\n * (`core/repo/tree/fs.ts`'s `markDescended`), and for the same reason:\n * `entryIs` follows symlinks on purpose, and a followed cycle without a\n * visited set recurses until the stack ends.\n */\nexport async function readGlossary(root: string): Promise<Glossary> {\n if (!existsSync(root)) return { present: false, terms: [] };\n const state: WalkState = { terms: [], visited: new Set() };\n await visit({ dir: root, chain: [] }, state);\n state.terms.sort((a, b) => compareIds(a.id, b.id));\n return { present: true, terms: state.terms };\n}\n\n/** Collect the terms in one directory and walk what is beneath it. */\nasync function visit(spot: Spot, state: WalkState): Promise<void> {\n if (!markDescended(spot.dir, state.visited)) return;\n const entries = (await readdir(spot.dir, { withFileTypes: true })).filter((e) => !e.name.startsWith(\".\"));\n for (const entry of entries.filter((e) => e.name.endsWith(\".md\")).sort((a, b) => compareIds(a.name, b.name))) {\n if (entry.name === INDEX_PAGE || !entryIs(spot.dir, entry, \"file\")) continue;\n state.terms.push({\n id: [...spot.chain, entry.name.slice(0, -\".md\".length)].join(\"/\"),\n path: join(spot.dir, entry.name),\n });\n }\n // Sequential, not Promise.all: the visited set is shared mutable state and\n // the walk's correctness under symlinks rests on a child being marked before\n // its sibling asks. These trees are tens of directories at most.\n for (const child of entries.filter((e) => entryIs(spot.dir, e, \"dir\")).map((e) => e.name).sort()) {\n await visit({ dir: join(spot.dir, child), chain: [...spot.chain, child] }, state);\n }\n}\n"]}
@@ -7,6 +7,16 @@
7
7
  * either opens all of them — on a big fleet that is not a faster run, it is a
8
8
  * bigger one. The cap and the ordering guarantee travel together because a
9
9
  * caller that wants the first cannot afford to lose the second.
10
+ *
11
+ * The third answer to "how much may happen at once" is `memo`: the same read
12
+ * asked for twice in one invocation happens once, both askers sharing the one
13
+ * in-flight promise. It lives here, in a leaf, because both read indexes —
14
+ * `core/fleet-context.ts` and the service-model memos it owns
15
+ * (`core/c4/prefetch/fleet.ts`) — spell every cache they keep with it, and
16
+ * neither should own the other's idiom. The read index could borrow it from
17
+ * the package it already imports, but then a rule about caching in general
18
+ * would live inside the LikeC4 adapter, and the next memo outside `c4/` would
19
+ * have to import that adapter to obey it.
10
20
  */
11
21
  import { cpus } from "node:os";
12
22
  /**
@@ -48,4 +58,13 @@ export async function inOrder(items, work) {
48
58
  }));
49
59
  return out;
50
60
  }
61
+ /** One in-flight promise per key, created on first ask — the memo idiom, once. */
62
+ export function memo(store, k, make) {
63
+ let pending = store.get(k);
64
+ if (pending === undefined) {
65
+ pending = make();
66
+ store.set(k, pending);
67
+ }
68
+ return pending;
69
+ }
51
70
  //# sourceMappingURL=concurrency.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"concurrency.js","sourceRoot":"","sources":["../../../src/core/kernel/concurrency.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAE/B;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC;AAE1E;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAC3B,KAAmB,EACnB,IAA6B;IAE7B,MAAM,GAAG,GAAQ,EAAE,CAAC;IACpB,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,kBAAkB,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAC3D,MAAM,OAAO,CAAC,GAAG,CACf,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,KAAK,IAAI,EAAE;QACzC,KAAK,IAAI,CAAC,GAAG,IAAI,EAAE,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,GAAG,IAAI,EAAE;YAAE,GAAG,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC,CAAC;IACpF,CAAC,CAAC,CACH,CAAC;IACF,OAAO,GAAG,CAAC;AACb,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,IAAI,CAAI,KAA8B,EAAE,CAAS,EAAE,IAAsB;IACvF,IAAI,OAAO,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAC3B,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,OAAO,GAAG,IAAI,EAAE,CAAC;QACjB,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IACxB,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC","sourcesContent":["/**\n * How much of loam may happen at once, and in what order the answers come back.\n *\n * One rule, because there is one resource being rationed: a LikeC4/Langium\n * workspace. `validate --all` opens one per service and per feature, the\n * dependency graph opens one per feature, and an unbounded `Promise.all` over\n * either opens all of them — on a big fleet that is not a faster run, it is a\n * bigger one. The cap and the ordering guarantee travel together because a\n * caller that wants the first cannot afford to lose the second.\n *\n * The third answer to \"how much may happen at once\" is `memo`: the same read\n * asked for twice in one invocation happens once, both askers sharing the one\n * in-flight promise. It lives here, in a leaf, because both read indexes —\n * `core/fleet-context.ts` and the service-model memos it owns\n * (`core/c4/prefetch/fleet.ts`) — spell every cache they keep with it, and\n * neither should own the other's idiom. The read index could borrow it from\n * the package it already imports, but then a rule about caching in general\n * would live inside the LikeC4 adapter, and the next memo outside `c4/` would\n * have to import that adapter to obey it.\n */\nimport { cpus } from \"node:os\";\n\n/**\n * How many units of work may be in flight at once.\n *\n * Capped as well as scaled: each in-flight unit holds a whole LikeC4/Langium\n * workspace, so a 64-core box would open sixty-four of them at once and buy\n * memory pressure rather than throughput (peak RSS on an 80-service fleet:\n * 385 MB serial, ~500 MB pooled). That measurement is the entire justification\n * for the cap, and it is why the cap lives with the work rather than inside one\n * command: `loam dependencies` and the fleet form of `loam status` fan out over\n * the same workspaces `validate --all` does, and used to do it uncapped.\n *\n * Do not quote a speedup for this. The measured cost is CPU inside the Langium\n * parse, which one thread cannot divide however the loop is shaped; what the\n * pool overlaps is the I/O half — the spec, contract and health reads around\n * each parse. On an 80-service fleet it measures as a wash (11–13 s either way,\n * on a box that was itself loaded). The number that moves these commands is\n * workspaces per run, not awaits per loop.\n */\nexport const TARGET_CONCURRENCY = Math.max(1, Math.min(cpus().length, 8));\n\n/**\n * Run `work` over `items` with a bounded number in flight, returning the\n * results in INPUT order.\n *\n * The order is the contract, not an accident: the text report and the `--json`\n * envelope are diffed between runs and between machines, so a concurrent run\n * has to be byte-identical to the serial one for the same input. That is why\n * results are written by index — nothing is appended as it finishes, and a slow\n * item cannot reorder the fleet around it.\n */\nexport async function inOrder<T, R>(\n items: readonly T[],\n work: (item: T) => Promise<R>,\n): Promise<R[]> {\n const out: R[] = [];\n let next = 0;\n const workers = Math.min(TARGET_CONCURRENCY, items.length);\n await Promise.all(\n Array.from({ length: workers }, async () => {\n for (let i = next++; i < items.length; i = next++) out[i] = await work(items[i]!);\n }),\n );\n return out;\n}\n\n/** One in-flight promise per key, created on first ask — the memo idiom, once. */\nexport function memo<T>(store: Map<string, Promise<T>>, k: string, make: () => Promise<T>): Promise<T> {\n let pending = store.get(k);\n if (pending === undefined) {\n pending = make();\n store.set(k, pending);\n }\n return pending;\n}\n"]}
@@ -5,7 +5,7 @@
5
5
  * the frontmatter reader, the requirement parser, the fleet-wide read index and
6
6
  * three commands that read a single file directly. It lived beside the read
7
7
  * index, so each of those imported the whole index (and through it repo.ts,
8
- * openapi.ts and spec.ts) to reach a dozen lines of decoding, and several of
8
+ * openapi/doc.ts and document/spec.ts) to reach a dozen lines of decoding, and several of
9
9
  * them closed an import cycle doing it. A leaf whose only dependency is
10
10
  * `node:buffer` costs nothing to import and can be reached from anywhere.
11
11
  */
@@ -0,0 +1 @@
1
+ {"version":3,"file":"document-bytes.js","sourceRoot":"","sources":["../../../src/core/kernel/document-bytes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC;;;;;;;;;;;;;;GAcG;AACH,MAAM,OAAO,oBAAqB,SAAQ,KAAK;IAIlC,IAAI;IAHG,IAAI,GAAG,sBAAsB,CAAC;IAEhD,YACW,IAAY,EACrB,MAAc;QAEd,KAAK,CACH,GAAG,IAAI,mCAAmC,MAAM,6DAA6D;YAC3G,+GAA+G;YAC/G,8GAA8G;YAC9G,2DAA2D,CAC9D,CAAC;oBARO,IAAI;IASf,CAAC;CACF;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,cAAc,CAAC,KAAa,EAAE,IAAY;IACxD,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC;QAAE,MAAM,IAAI,oBAAoB,CAAC,IAAI,EAAE,0CAA0C,CAAC,CAAC;IACrG,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IACpC,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,oBAAoB,CAC5B,IAAI,EACJ,iHAAiH,CAClH,CAAC;IACJ,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC","sourcesContent":["/**\n * Decode the bytes of a document loam is about to parse, or refuse naming it.\n *\n * The rule belongs to every module that turns a markdown artifact into text —\n * the frontmatter reader, the requirement parser, the fleet-wide read index and\n * three commands that read a single file directly. It lived beside the read\n * index, so each of those imported the whole index (and through it repo.ts,\n * openapi/doc.ts and document/spec.ts) to reach a dozen lines of decoding, and several of\n * them closed an import cycle doing it. A leaf whose only dependency is\n * `node:buffer` costs nothing to import and can be reached from anywhere.\n */\nimport { isUtf8 } from \"node:buffer\";\n\n/**\n * A document loam was about to parse that is not UTF-8 text.\n *\n * Thrown rather than returned, and named as the file rather than as an empty\n * document, because every parser in the codebase reads \"no requirements, no\n * frontmatter\" as a legitimate state — a fresh baseline looks exactly like it.\n * A `spec.md` saved as UTF-16 (PowerShell's `>` writes UTF-16LE by default)\n * therefore validated green, with every requirement in it invisible.\n *\n * `path` is spelled the way Node spells it on an ErrnoException so that\n * validate's per-target guard names the file without knowing this type; the\n * write path makes the same two tests for the same reasons (staging.ts's\n * `decodeUtf8`), and its messages differ only in saying what a rewrite would\n * additionally destroy, which is not what a reader needs to hear.\n */\nexport class NotUtf8DocumentError extends Error {\n override readonly name = \"NotUtf8DocumentError\";\n\n constructor(\n readonly path: string,\n reason: string,\n ) {\n super(\n `${path} is not a UTF-8 text document — ${reason}. Read as UTF-8 its requirements, frontmatter and headings ` +\n `all come out absent rather than wrong, so the file grades as an empty baseline instead of an unreadable one. ` +\n `Nothing here was checked. Re-save it as UTF-8 (PowerShell's \\`>\\` and \\`Out-File\\` write UTF-16 unless told ` +\n `otherwise: use \\`Out-File -Encoding utf8\\`), then re-run.`,\n );\n }\n}\n\n/**\n * Decode a document loam is about to parse, or refuse naming it.\n *\n * Two tests, because one is not enough. `isUtf8` catches the byte sequences\n * that cannot be UTF-8 at all — which is what a byte-order mark makes UTF-16\n * into, and PowerShell writes one. Without a BOM, UTF-16LE of ASCII is a\n * sequence of valid UTF-8 bytes: every other byte is NUL, which decodes to\n * U+0000 and nothing complains. That file parsed as zero requirements and no\n * frontmatter, and validated green. A NUL in a markdown document loam owns has\n * no legitimate spelling, so it is the second test.\n */\nexport function decodeDocument(bytes: Buffer, path: string): string {\n if (!isUtf8(bytes)) throw new NotUtf8DocumentError(path, \"its bytes are not a valid UTF-8 sequence\");\n const text = bytes.toString(\"utf8\");\n if (text.includes(\"\\u0000\")) {\n throw new NotUtf8DocumentError(\n path,\n \"it holds NUL characters, which no markdown document does — almost always UTF-16 saved without a byte-order mark\",\n );\n }\n return text;\n}\n"]}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Track ``` / ~~~ fences line by line — the one rule every markdown walk in the
3
+ * product has to agree on about what is structure and what is quoted text.
4
+ *
5
+ * It lived in `core/document/parse.ts` while that file was its only writer and
6
+ * `core/provenance/sample/sections.ts` its only borrower. It moved here when the
7
+ * fourth reader arrived and could not reach it: `core/vocabulary/steps.ts` needs
8
+ * the same rule to stop a pipe table inside a fenced payload from being hoisted
9
+ * out as a scenario's `Examples`, and `core/document/` already imports
10
+ * `core/vocabulary/` (through `document/scenarios.ts`), so an import the other
11
+ * way would close a package cycle the graph check forbids. AGENTS.md names this
12
+ * move explicitly: when a helper you need lives in a module heavier than the
13
+ * helper, move the helper out rather than importing the weight.
14
+ *
15
+ * `core/kernel/` is where it lands because it is the one package below every
16
+ * other — it imports nothing from `core/` at all, so nobody can create a cycle
17
+ * by depending on it.
18
+ *
19
+ * Returns true while the line is fenced content — INCLUDING the fence marker
20
+ * itself. Callers that need the markers back (an emitter reading a docstring out
21
+ * of a body, rather than a heading walk skipping over one) must track the
22
+ * transition themselves; this predicate deliberately answers one question.
23
+ *
24
+ * A closing marker must match the opener's character, so a ``` block quoting a
25
+ * ~~~ line stays open, which is what the markdown spec says and what stops a
26
+ * payload containing fence characters from ending its own block early.
27
+ */
28
+ export function fenceTracker() {
29
+ let fence = null;
30
+ return (line) => {
31
+ const m = /^\s*(```|~~~)/.exec(line);
32
+ if (m) {
33
+ if (fence === null)
34
+ fence = m[1];
35
+ else if (fence === m[1])
36
+ fence = null;
37
+ return true;
38
+ }
39
+ return fence !== null;
40
+ };
41
+ }
42
+ //# sourceMappingURL=fences.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fences.js","sourceRoot":"","sources":["../../../src/core/kernel/fences.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,UAAU,YAAY;IAC1B,IAAI,KAAK,GAAkB,IAAI,CAAC;IAChC,OAAO,CAAC,IAAI,EAAE,EAAE;QACd,MAAM,CAAC,GAAG,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrC,IAAI,CAAC,EAAE,CAAC;YACN,IAAI,KAAK,KAAK,IAAI;gBAAE,KAAK,GAAG,CAAC,CAAC,CAAC,CAAE,CAAC;iBAC7B,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,CAAE;gBAAE,KAAK,GAAG,IAAI,CAAC;YACvC,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,KAAK,KAAK,IAAI,CAAC;IACxB,CAAC,CAAC;AACJ,CAAC","sourcesContent":["/**\n * Track ``` / ~~~ fences line by line — the one rule every markdown walk in the\n * product has to agree on about what is structure and what is quoted text.\n *\n * It lived in `core/document/parse.ts` while that file was its only writer and\n * `core/provenance/sample/sections.ts` its only borrower. It moved here when the\n * fourth reader arrived and could not reach it: `core/vocabulary/steps.ts` needs\n * the same rule to stop a pipe table inside a fenced payload from being hoisted\n * out as a scenario's `Examples`, and `core/document/` already imports\n * `core/vocabulary/` (through `document/scenarios.ts`), so an import the other\n * way would close a package cycle the graph check forbids. AGENTS.md names this\n * move explicitly: when a helper you need lives in a module heavier than the\n * helper, move the helper out rather than importing the weight.\n *\n * `core/kernel/` is where it lands because it is the one package below every\n * other — it imports nothing from `core/` at all, so nobody can create a cycle\n * by depending on it.\n *\n * Returns true while the line is fenced content — INCLUDING the fence marker\n * itself. Callers that need the markers back (an emitter reading a docstring out\n * of a body, rather than a heading walk skipping over one) must track the\n * transition themselves; this predicate deliberately answers one question.\n *\n * A closing marker must match the opener's character, so a ``` block quoting a\n * ~~~ line stays open, which is what the markdown spec says and what stops a\n * payload containing fence characters from ending its own block early.\n */\nexport function fenceTracker(): (line: string) => boolean {\n let fence: string | null = null;\n return (line) => {\n const m = /^\\s*(```|~~~)/.exec(line);\n if (m) {\n if (fence === null) fence = m[1]!;\n else if (fence === m[1]!) fence = null;\n return true;\n }\n return fence !== null;\n };\n}\n"]}