@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,102 @@
1
+ /**
2
+ * A service an active feature INTRODUCES, as `loam validate` meets it — named
3
+ * by the repository's own binding, or named on the command line.
4
+ *
5
+ * Until the feature archives, such a service's only documents are the
6
+ * feature's `specs/<service>/`: `services/` learns the name at the merge
7
+ * (`core/projection/introduced.ts`, the one answer to "introduces" every
8
+ * command reads). `validate` looked only under `services/`, so in that
9
+ * service's own repository a bare `loam validate` refused with
10
+ * `service.unknown` and "Did you mean: payment-service?" — it read the newest
11
+ * service in the fleet as a typo, while `loam status` and `loam doctor` in the
12
+ * same repository named the feature that introduces it.
13
+ *
14
+ * Two readings, two answers:
15
+ *
16
+ * the binding (a bare `loam validate`) → the introducing features are
17
+ * validated in the service's place. They hold every document the service
18
+ * has, so theirs is the grade there is to give, and it is `--feature`'s
19
+ * grade target for target — never a slice of it, which would be a green
20
+ * over whatever the slice left out. The run says first which features it
21
+ * validated and why, in `show`'s words for the same fact, so a reader never
22
+ * takes a feature's findings for the service's own.
23
+ * a name (`--service <id>`, the positional) → still a service target, which
24
+ * does not exist, so still `service.unknown` at error: `--service` forces
25
+ * the service reading by contract. Only the prose changes — it names the
26
+ * feature and the command that validates its documents, where it used to
27
+ * offer the nearest living id as the correction.
28
+ *
29
+ * A name nothing introduces keeps the near-miss refusal, byte for byte.
30
+ */
31
+ import { closeIds } from "../../../core/c4/arch.js";
32
+ import { introducingFeatures } from "../../../core/projection/introduced.js";
33
+ import { listServices } from "../../../core/repo/repo.js";
34
+ /**
35
+ * The features a bare run validates in place of the bound service — or null
36
+ * when the binding names a living service, or a name nothing introduces, and
37
+ * the run grades it as a service (`service.unknown` and all) exactly as before.
38
+ */
39
+ export async function introducedBinding(docsDir, resolved, fleet) {
40
+ // An enumerated directory is living. `introducingFeatures` would say so too,
41
+ // after reading every feature to learn it.
42
+ if (resolved.dir !== undefined)
43
+ return null;
44
+ const features = await introducingFeatures(docsDir, resolved.id, fleet);
45
+ return features.length === 0 ? null : { service: resolved.id, features };
46
+ }
47
+ /**
48
+ * The two lines a bare run prints above the report: the first is `loam show
49
+ * <service>`'s header for the same state, the second says what was validated
50
+ * instead and why those features.
51
+ */
52
+ export function introducedLead({ service, features }) {
53
+ const ids = features.map((f) => f.id);
54
+ const several = ids.length > 1;
55
+ const listed = several ? `${ids.slice(0, -1).join(", ")} and ${ids.slice(-1).join("")}` : ids.join("");
56
+ return [
57
+ `${service} introduced by ${ids.join(", ")} (in flight) — not in the living docs until ${several ? "one of them" : "it"} archives`,
58
+ ` validating ${listed} instead: ${several ? "their" : "its"} specs/${service}/ are this service's documents until then`,
59
+ ];
60
+ }
61
+ /**
62
+ * The `--json` payload's `boundService`: why `targets` holds features and no
63
+ * service. The keys are `show`'s and `steps`' for the same fact — `living:
64
+ * false` and `introducedBy` — so a consumer that reads one reads them all.
65
+ */
66
+ export function introducedJson({ service, features }) {
67
+ return { id: service, living: false, introducedBy: features.map((f) => f.id) };
68
+ }
69
+ /**
70
+ * `service.unknown`: no directory under `services/` answers to the name. The
71
+ * hint depends on why. A feature in flight introduces it → name the feature
72
+ * and the command that validates its documents, in `loam doctor`'s words for
73
+ * the same state. Something close is living → the near-miss, which is what
74
+ * makes a typo diagnosable. Neither → where to look. Never `loam adopt`, in any
75
+ * branch: adopting a typo would document the misspelling, and adopting an
76
+ * introduced service would write `services/<id>/` ahead of the merge.
77
+ */
78
+ export async function unknownServiceFinding(docsDir, service, treePath, fleet) {
79
+ const ids = (await introducingFeatures(docsDir, service, fleet)).map((f) => f.id);
80
+ const [lead, ...others] = ids;
81
+ if (lead !== undefined) {
82
+ const several = others.length > 0;
83
+ return {
84
+ severity: "error",
85
+ code: "service.unknown",
86
+ message: `No service directory at ${treePath}: ${lead} introduces it${several ? ` (so does ${others.join(", ")})` : ""}, ` +
87
+ `and it is not in the living docs until ${several ? "one of them" : lead} archives. Until then its documents are ` +
88
+ `${several ? `the specs/${service}/ of ${ids.join(", ")}` : `${lead}'s specs/${service}/`} — run ` +
89
+ `\`loam validate --feature ${lead}\`${several ? `, and likewise for ${others.join(", ")},` : ""} to validate them.`,
90
+ };
91
+ }
92
+ const close = closeIds(service, (await listServices(docsDir, fleet)).map((s) => s.id));
93
+ return {
94
+ severity: "error",
95
+ code: "service.unknown",
96
+ message: `No service directory at ${treePath}.` +
97
+ (close.length > 0
98
+ ? ` Did you mean: ${close.join(", ")}?`
99
+ : " `loam list services` shows what exists."),
100
+ };
101
+ }
102
+ //# sourceMappingURL=introduced.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"introduced.js","sourceRoot":"","sources":["../../../../src/commands/validate/checks/introduced.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * A service an active feature INTRODUCES, as `loam validate` meets it — named\n * by the repository's own binding, or named on the command line.\n *\n * Until the feature archives, such a service's only documents are the\n * feature's `specs/<service>/`: `services/` learns the name at the merge\n * (`core/projection/introduced.ts`, the one answer to \"introduces\" every\n * command reads). `validate` looked only under `services/`, so in that\n * service's own repository a bare `loam validate` refused with\n * `service.unknown` and \"Did you mean: payment-service?\" — it read the newest\n * service in the fleet as a typo, while `loam status` and `loam doctor` in the\n * same repository named the feature that introduces it.\n *\n * Two readings, two answers:\n *\n * the binding (a bare `loam validate`) → the introducing features are\n * validated in the service's place. They hold every document the service\n * has, so theirs is the grade there is to give, and it is `--feature`'s\n * grade target for target — never a slice of it, which would be a green\n * over whatever the slice left out. The run says first which features it\n * validated and why, in `show`'s words for the same fact, so a reader never\n * takes a feature's findings for the service's own.\n * a name (`--service <id>`, the positional) → still a service target, which\n * does not exist, so still `service.unknown` at error: `--service` forces\n * the service reading by contract. Only the prose changes — it names the\n * feature and the command that validates its documents, where it used to\n * offer the nearest living id as the correction.\n *\n * A name nothing introduces keeps the near-miss refusal, byte for byte.\n */\nimport { closeIds } from \"../../../core/c4/arch.js\";\nimport type { FleetContext } from \"../../../core/fleet-context.js\";\nimport type { DocsDir } from \"../../../core/kernel/ids/dirs.js\";\nimport { introducingFeatures } from \"../../../core/projection/introduced.js\";\nimport type { FeatureEntry } from \"../../../core/repo/entries.js\";\nimport { listServices } from \"../../../core/repo/repo.js\";\nimport type { ServiceTarget } from \"../../../core/repo/service-target.js\";\nimport type { Finding } from \"../../../core/vocabulary/report.js\";\n\n/** A bound service a bare run validates through the features that introduce it. */\nexport interface IntroducedBinding {\n /** The service loam.json names. */\n service: string;\n /** `introducingFeatures`' answer, ordered by id — never empty. */\n features: FeatureEntry[];\n}\n\n/**\n * The features a bare run validates in place of the bound service — or null\n * when the binding names a living service, or a name nothing introduces, and\n * the run grades it as a service (`service.unknown` and all) exactly as before.\n */\nexport async function introducedBinding(\n docsDir: DocsDir,\n resolved: Extract<ServiceTarget, { ok: true }>,\n fleet: FleetContext,\n): Promise<IntroducedBinding | null> {\n // An enumerated directory is living. `introducingFeatures` would say so too,\n // after reading every feature to learn it.\n if (resolved.dir !== undefined) return null;\n const features = await introducingFeatures(docsDir, resolved.id, fleet);\n return features.length === 0 ? null : { service: resolved.id, features };\n}\n\n/**\n * The two lines a bare run prints above the report: the first is `loam show\n * <service>`'s header for the same state, the second says what was validated\n * instead and why those features.\n */\nexport function introducedLead({ service, features }: IntroducedBinding): string[] {\n const ids = features.map((f) => f.id);\n const several = ids.length > 1;\n const listed = several ? `${ids.slice(0, -1).join(\", \")} and ${ids.slice(-1).join(\"\")}` : ids.join(\"\");\n return [\n `${service} introduced by ${ids.join(\", \")} (in flight) — not in the living docs until ${several ? \"one of them\" : \"it\"} archives`,\n ` validating ${listed} instead: ${several ? \"their\" : \"its\"} specs/${service}/ are this service's documents until then`,\n ];\n}\n\n/**\n * The `--json` payload's `boundService`: why `targets` holds features and no\n * service. The keys are `show`'s and `steps`' for the same fact — `living:\n * false` and `introducedBy` — so a consumer that reads one reads them all.\n */\nexport function introducedJson({ service, features }: IntroducedBinding): {\n id: string;\n living: false;\n introducedBy: string[];\n} {\n return { id: service, living: false, introducedBy: features.map((f) => f.id) };\n}\n\n/**\n * `service.unknown`: no directory under `services/` answers to the name. The\n * hint depends on why. A feature in flight introduces it → name the feature\n * and the command that validates its documents, in `loam doctor`'s words for\n * the same state. Something close is living → the near-miss, which is what\n * makes a typo diagnosable. Neither → where to look. Never `loam adopt`, in any\n * branch: adopting a typo would document the misspelling, and adopting an\n * introduced service would write `services/<id>/` ahead of the merge.\n */\nexport async function unknownServiceFinding(\n docsDir: DocsDir,\n service: string,\n treePath: string,\n fleet: FleetContext,\n): Promise<Finding> {\n const ids = (await introducingFeatures(docsDir, service, fleet)).map((f) => f.id);\n const [lead, ...others] = ids;\n if (lead !== undefined) {\n const several = others.length > 0;\n return {\n severity: \"error\",\n code: \"service.unknown\",\n message:\n `No service directory at ${treePath}: ${lead} introduces it${several ? ` (so does ${others.join(\", \")})` : \"\"}, ` +\n `and it is not in the living docs until ${several ? \"one of them\" : lead} archives. Until then its documents are ` +\n `${several ? `the specs/${service}/ of ${ids.join(\", \")}` : `${lead}'s specs/${service}/`} — run ` +\n `\\`loam validate --feature ${lead}\\`${several ? `, and likewise for ${others.join(\", \")},` : \"\"} to validate them.`,\n };\n }\n const close = closeIds(service, (await listServices(docsDir, fleet)).map((s) => s.id));\n return {\n severity: \"error\",\n code: \"service.unknown\",\n message:\n `No service directory at ${treePath}.` +\n (close.length > 0\n ? ` Did you mean: ${close.join(\", \")}?`\n : \" `loam list services` shows what exists.\"),\n };\n}\n"]}
@@ -0,0 +1,264 @@
1
+ /**
2
+ * What a requirement document owes, checked the same way wherever it lives.
3
+ *
4
+ * The same `### Requirement:` grammar is authored in four places — a service's
5
+ * spec.md and arch.spec.md, and a feature's per-service deltas of both — and
6
+ * every breach below carries from a delta into the living document through the
7
+ * archive merge. So the checks are one set called from both target kinds
8
+ * (`service/` and `feature/`): grading a delta more leniently than the file it
9
+ * is about to become is how a defect acquires a signature saying it was
10
+ * reviewed.
11
+ *
12
+ * None of these read the filesystem and none of them print — they take parsed
13
+ * requirements and answer in findings.
14
+ */
15
+ import {} from "../../../core/vocabulary/report.js";
16
+ import { assertionlessFindings, examplesFindings, missingScenariosFinding, requirementsMissingScenarios, steplessFindings, } from "../../../core/document/scenarios.js";
17
+ import { requirementIdProblems } from "../../../core/document/spec.js";
18
+ import { closeIds, coversCandidates, entryResolves, parseCoversEntry, } from "../../../core/c4/arch.js";
19
+ import {} from "../../../core/permissions/permissions.js";
20
+ import {} from "../../../core/openapi/doc.js";
21
+ /** The parsed Covers entries of every requirement that will live (REMOVED covers nothing). */
22
+ export function coversEntries(reqs) {
23
+ return reqs.filter((r) => r.kind !== "REMOVED").flatMap((r) => r.covers.map(parseCoversEntry));
24
+ }
25
+ /**
26
+ * `spec.duplicate-requirement` — two `### Requirement:` blocks with one name in
27
+ * one LIVING document. Nothing else catches it, and the merge algebra
28
+ * (applyRequirementDelta) matches by name and edits only the FIRST match: a
29
+ * later archive rewrites one copy and the other survives as a stale snapshot
30
+ * of whatever the requirement used to say. Per file on purpose — spec.md and
31
+ * arch.spec.md are separate requirement namespaces (their merges never cross
32
+ * files), so one name appearing in both is legal and unflagged.
33
+ */
34
+ export function duplicateRequirementFindings(reqs, where, subject) {
35
+ const counts = new Map();
36
+ for (const r of reqs)
37
+ counts.set(r.name, (counts.get(r.name) ?? 0) + 1);
38
+ return [...counts]
39
+ .filter(([, n]) => n > 1)
40
+ .map(([name, n]) => ({
41
+ severity: "error",
42
+ code: "spec.duplicate-requirement",
43
+ subject,
44
+ message: `${where}: requirement '${name}' is defined ${n} times — a merge edits only the first, every other copy lives on stale; keep exactly one`,
45
+ }));
46
+ }
47
+ /** Stable IDs are optional, but once authored they must select exactly one requirement. */
48
+ export function requirementIdFindings(reqs, where, subject) {
49
+ return requirementIdProblems(reqs).map((problem) => {
50
+ if (problem.kind === "invalid") {
51
+ return {
52
+ severity: "error",
53
+ code: "spec.requirement-id-invalid",
54
+ subject,
55
+ message: `${where}: requirement '${problem.requirement}' has invalid Requirement-ID '${problem.value}' — use 1-128 characters matching [A-Za-z][A-Za-z0-9._-]*`,
56
+ };
57
+ }
58
+ if (problem.kind === "repeated") {
59
+ return {
60
+ severity: "error",
61
+ code: "spec.requirement-id-repeated",
62
+ subject,
63
+ message: `${where}: requirement '${problem.requirement}' declares Requirement-ID ${problem.values.length} times — identity must be declared exactly once`,
64
+ };
65
+ }
66
+ return {
67
+ severity: "error",
68
+ code: "spec.requirement-id-duplicate",
69
+ subject,
70
+ message: `${where}: Requirement-ID '${problem.id}' is shared by ${problem.requirements.map((name) => `'${name}'`).join(", ")} — one ID may identify only one requirement`,
71
+ };
72
+ });
73
+ }
74
+ /**
75
+ * The two list lines of the requirement grammar, exactly as core/document/spec.ts spells
76
+ * them (mirrored here, not exported from there, because the parser's grammar is
77
+ * its own; a drift shows up as this check counting differently than the parser
78
+ * assigns). A SECOND matching line in one requirement body REPLACES the first —
79
+ * assignment, not append, the documented keep-last quirk — so the author's
80
+ * "long list in two lines" pattern silently loses its first line.
81
+ */
82
+ const OPERATIONS_LINE_RE = /^\s*Operations?:\s*(.+?)\s*$/i;
83
+ const COVERS_LINE_RE = /^\s*Covers?:\s*(.+?)\s*$/i;
84
+ /**
85
+ * `spec.repeated-operations` / `spec.repeated-covers` — warn on the silent
86
+ * loss, keep the keep-last semantics (changing them would re-read every spec
87
+ * in the fleet). Scenario bodies never count: the parser only assigns from the
88
+ * requirement's own body lines, and `Requirement.text` is exactly those.
89
+ * REMOVED requirements are exempt the way coversEntries exempts them — content
90
+ * on its way out obliges nothing.
91
+ */
92
+ export function repeatedListLineFindings(reqs, where, subject) {
93
+ const out = [];
94
+ for (const r of reqs) {
95
+ if (r.kind === "REMOVED")
96
+ continue;
97
+ for (const { re, label, code } of [
98
+ { re: OPERATIONS_LINE_RE, label: "Operations:", code: "spec.repeated-operations" },
99
+ { re: COVERS_LINE_RE, label: "Covers:", code: "spec.repeated-covers" },
100
+ ]) {
101
+ const n = r.text.filter((line) => re.test(line)).length;
102
+ if (n < 2)
103
+ continue;
104
+ out.push({
105
+ severity: "warn",
106
+ code,
107
+ subject,
108
+ message: `${where}: requirement '${r.name}' has ${n} '${label}' lines — the last REPLACES the others (assignment, not append), the earlier list is silently lost; merge them into one comma-separated line`,
109
+ });
110
+ }
111
+ }
112
+ return out;
113
+ }
114
+ export function coversUnknownFindings(reqs, target, scope, healthUnreadable = false) {
115
+ const { where, subject } = target;
116
+ const out = [];
117
+ for (const r of reqs) {
118
+ if (r.kind === "REMOVED")
119
+ continue;
120
+ for (const raw of r.covers) {
121
+ const entry = parseCoversEntry(raw);
122
+ if (healthUnreadable && (entry.form === "alert" || entry.form === "sli"))
123
+ continue;
124
+ if (entryResolves(entry, scope))
125
+ continue;
126
+ const close = coversCandidates(entry, scope);
127
+ out.push({
128
+ severity: "warn",
129
+ code: "covers.unknown",
130
+ subject,
131
+ message: `${where}: requirement '${r.name}' — Covers: '${raw}' resolves to nothing` +
132
+ (close.length > 0
133
+ ? `. Did you mean: ${close.join(", ")}?`
134
+ : " in the model, the landscape or health.yaml"),
135
+ });
136
+ }
137
+ }
138
+ return out;
139
+ }
140
+ /**
141
+ * `permissions.unknown` — the typo guard on the `Requires:` line, and an ERROR
142
+ * where its `Covers:` sibling is a warning.
143
+ *
144
+ * The two differ because what they promise differs. `Covers:` is advisory end
145
+ * to end: a wrong id costs its author the coverage they wrote the line for and
146
+ * nothing else. `Requires:` names authorization the service actually enforces,
147
+ * and the failure it guards is the one an unaided reader cannot see — an
148
+ * invented permission reads exactly like a real one, in the requirement, in the
149
+ * generated scenario, and in the test somebody then writes against it. Its
150
+ * grade is `Operations:`', not `Covers:`'.
151
+ *
152
+ * Silent on ONE case only: an unreadable vocabulary, where
153
+ * `permissions.invalid` is the honest finding and grading every entry against a
154
+ * file nobody could parse is the false cascade `healthUnreadable` exists to
155
+ * stop one axis over. A MISSING vocabulary is not that case — the `Requires:`
156
+ * line is itself the opt-in, and a line that resolves against nothing while
157
+ * reading like a join is the failure this whole axis exists to prevent.
158
+ */
159
+ export function requiresUnknownFindings(reqs, target, vocabulary) {
160
+ const { where, subject } = target;
161
+ if (vocabulary.invalid !== undefined)
162
+ return [];
163
+ const known = [...vocabulary.byId.keys()];
164
+ const out = [];
165
+ for (const r of reqs) {
166
+ if (r.kind === "REMOVED")
167
+ continue;
168
+ for (const raw of r.requires) {
169
+ if (vocabulary.byId.has(raw))
170
+ continue;
171
+ const close = closeIds(raw, known);
172
+ out.push({
173
+ severity: "error",
174
+ code: "permissions.unknown",
175
+ subject,
176
+ message: `${where}: requirement '${r.name}' — Requires: '${raw}' is not declared in architecture/permissions.yaml` +
177
+ (!vocabulary.present
178
+ ? ", which does not exist. The `Requires:` line is the opt-in: create the fleet vocabulary with this permission under its subject kind, or drop the line"
179
+ : close.length > 0
180
+ ? `. Did you mean: ${close.join(", ")}?`
181
+ : ". Entries are '<subject>/<permission>'; declare it there, or fix the spelling"),
182
+ });
183
+ }
184
+ }
185
+ return out;
186
+ }
187
+ /**
188
+ * `api.response-ungoverned` — a declared 4xx/5xx response no scenario reaches.
189
+ *
190
+ * The gap this closes is the one a whole adoption can fall into: `api.ungoverned`
191
+ * grades OPERATIONS against requirements, so an endpoint with one happy-path
192
+ * requirement and twelve declared failure codes is fully governed by every
193
+ * check loam had. The refusals are where a service's decision layer surfaces —
194
+ * a permission denied, a field combination rejected, a state that forbids the
195
+ * transition — and the contract is the only artifact in the corpus that already
196
+ * enumerates them.
197
+ *
198
+ * A scenario "reaches" a code when the code appears as a standalone number
199
+ * anywhere in its body, `Examples` rows included — which is why this arrived
200
+ * with outline support and not before: a status column is exactly where a
201
+ * matrix puts its codes, and before it those rows were prose in a description.
202
+ * The match is textual and therefore generous by design. It answers "did
203
+ * anybody write this case down", not "is this scenario correct", and the
204
+ * failure it is built to catch is the code nobody mentioned at all. Warn, like
205
+ * its sibling: a service may legitimately declare a code its scenarios describe
206
+ * in words, and an error would teach authors to paste numbers into prose.
207
+ *
208
+ * Operations no requirement governs are skipped: `api.ungoverned` already
209
+ * names those, and reporting each of their codes as well is one defect
210
+ * counted twice.
211
+ */
212
+ export function responseGovernanceFindings(service, ops, livingReqs) {
213
+ const ungoverned = [];
214
+ for (const op of ops) {
215
+ if (op.failureCodes.length === 0)
216
+ continue;
217
+ const governing = livingReqs.filter((r) => r.kind !== "REMOVED" && r.operations.includes(op.id));
218
+ if (governing.length === 0)
219
+ continue;
220
+ const body = governing.flatMap((r) => r.scenarios.flatMap((s) => s.lines)).join("\n");
221
+ const missing = op.failureCodes.filter((code) => !new RegExp(`(?<!\\d)${code}(?!\\d)`).test(body));
222
+ if (missing.length > 0)
223
+ ungoverned.push(`${op.id}: ${missing.join(", ")}`);
224
+ }
225
+ if (ungoverned.length === 0)
226
+ return [];
227
+ return [
228
+ {
229
+ severity: "warn",
230
+ code: "api.response-ungoverned",
231
+ subject: service,
232
+ message: `${service}: ${ungoverned.length} operation(s) declare a failure response no scenario reaches — write the refusal as a scenario, or as a row in one`,
233
+ details: ungoverned,
234
+ },
235
+ ];
236
+ }
237
+ export function coverageFinding(label, reqs) {
238
+ const missing = requirementsMissingScenarios(reqs);
239
+ if (missing.length === 0) {
240
+ return {
241
+ severity: "ok",
242
+ code: "requirements.covered",
243
+ message: `${label} covered (${reqs.length} requirement${reqs.length === 1 ? "" : "s"}, all with scenarios)`,
244
+ };
245
+ }
246
+ return { ...missingScenariosFinding(label, missing), text: { detailPrefix: "- " } };
247
+ }
248
+ /**
249
+ * The scenario-shape run of the battery every requirement document gets, in
250
+ * report order — stepless, assertionless, examples — spelled once for the four
251
+ * documents the header names, so they cannot drift apart. What differs between
252
+ * the four stays at each call site: a delta's coverage finding carries its
253
+ * service as `subject`, a living spec.md with no requirements reports
254
+ * `spec.no-requirements` in coverage's place, and duplicate names and
255
+ * requirement ids are graded on LIVING documents (`duplicateRequirementFindings`).
256
+ */
257
+ export function scenarioShapeFindings(label, subject, reqs) {
258
+ return [
259
+ ...steplessFindings(label, subject, reqs),
260
+ ...assertionlessFindings(label, subject, reqs),
261
+ ...examplesFindings(label, subject, reqs),
262
+ ];
263
+ }
264
+ //# sourceMappingURL=requirements.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"requirements.js","sourceRoot":"","sources":["../../../../src/commands/validate/checks/requirements.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * What a requirement document owes, checked the same way wherever it lives.\n *\n * The same `### Requirement:` grammar is authored in four places — a service's\n * spec.md and arch.spec.md, and a feature's per-service deltas of both — and\n * every breach below carries from a delta into the living document through the\n * archive merge. So the checks are one set called from both target kinds\n * (`service/` and `feature/`): grading a delta more leniently than the file it\n * is about to become is how a defect acquires a signature saying it was\n * reviewed.\n *\n * None of these read the filesystem and none of them print — they take parsed\n * requirements and answer in findings.\n */\nimport { type Finding } from \"../../../core/vocabulary/report.js\";\nimport {\n assertionlessFindings,\n examplesFindings,\n missingScenariosFinding,\n requirementsMissingScenarios,\n steplessFindings,\n} from \"../../../core/document/scenarios.js\";\nimport { requirementIdProblems, type Requirement } from \"../../../core/document/spec.js\";\nimport {\n closeIds,\n coversCandidates,\n entryResolves,\n parseCoversEntry,\n type CoverageScope,\n type CoversEntry,\n} from \"../../../core/c4/arch.js\";\nimport { type Vocabulary } from \"../../../core/permissions/permissions.js\";\nimport { type Operation } from \"../../../core/openapi/doc.js\";\n\n/** The parsed Covers entries of every requirement that will live (REMOVED covers nothing). */\nexport function coversEntries(reqs: Requirement[]): CoversEntry[] {\n return reqs.filter((r) => r.kind !== \"REMOVED\").flatMap((r) => r.covers.map(parseCoversEntry));\n}\n\n/**\n * `spec.duplicate-requirement` — two `### Requirement:` blocks with one name in\n * one LIVING document. Nothing else catches it, and the merge algebra\n * (applyRequirementDelta) matches by name and edits only the FIRST match: a\n * later archive rewrites one copy and the other survives as a stale snapshot\n * of whatever the requirement used to say. Per file on purpose — spec.md and\n * arch.spec.md are separate requirement namespaces (their merges never cross\n * files), so one name appearing in both is legal and unflagged.\n */\nexport function duplicateRequirementFindings(reqs: Requirement[], where: string, subject: string): Finding[] {\n const counts = new Map<string, number>();\n for (const r of reqs) counts.set(r.name, (counts.get(r.name) ?? 0) + 1);\n return [...counts]\n .filter(([, n]) => n > 1)\n .map(([name, n]) => ({\n severity: \"error\" as const,\n code: \"spec.duplicate-requirement\",\n subject,\n message: `${where}: requirement '${name}' is defined ${n} times — a merge edits only the first, every other copy lives on stale; keep exactly one`,\n }));\n}\n\n/** Stable IDs are optional, but once authored they must select exactly one requirement. */\nexport function requirementIdFindings(reqs: Requirement[], where: string, subject: string): Finding[] {\n return requirementIdProblems(reqs).map((problem) => {\n if (problem.kind === \"invalid\") {\n return {\n severity: \"error\" as const,\n code: \"spec.requirement-id-invalid\",\n subject,\n message: `${where}: requirement '${problem.requirement}' has invalid Requirement-ID '${problem.value}' — use 1-128 characters matching [A-Za-z][A-Za-z0-9._-]*`,\n };\n }\n if (problem.kind === \"repeated\") {\n return {\n severity: \"error\" as const,\n code: \"spec.requirement-id-repeated\",\n subject,\n message: `${where}: requirement '${problem.requirement}' declares Requirement-ID ${problem.values.length} times — identity must be declared exactly once`,\n };\n }\n return {\n severity: \"error\" as const,\n code: \"spec.requirement-id-duplicate\",\n subject,\n message: `${where}: Requirement-ID '${problem.id}' is shared by ${problem.requirements.map((name) => `'${name}'`).join(\", \")} — one ID may identify only one requirement`,\n };\n });\n}\n\n/**\n * The two list lines of the requirement grammar, exactly as core/document/spec.ts spells\n * them (mirrored here, not exported from there, because the parser's grammar is\n * its own; a drift shows up as this check counting differently than the parser\n * assigns). A SECOND matching line in one requirement body REPLACES the first —\n * assignment, not append, the documented keep-last quirk — so the author's\n * \"long list in two lines\" pattern silently loses its first line.\n */\nconst OPERATIONS_LINE_RE = /^\\s*Operations?:\\s*(.+?)\\s*$/i;\nconst COVERS_LINE_RE = /^\\s*Covers?:\\s*(.+?)\\s*$/i;\n\n/**\n * `spec.repeated-operations` / `spec.repeated-covers` — warn on the silent\n * loss, keep the keep-last semantics (changing them would re-read every spec\n * in the fleet). Scenario bodies never count: the parser only assigns from the\n * requirement's own body lines, and `Requirement.text` is exactly those.\n * REMOVED requirements are exempt the way coversEntries exempts them — content\n * on its way out obliges nothing.\n */\nexport function repeatedListLineFindings(reqs: Requirement[], where: string, subject: string): Finding[] {\n const out: Finding[] = [];\n for (const r of reqs) {\n if (r.kind === \"REMOVED\") continue;\n for (const { re, label, code } of [\n { re: OPERATIONS_LINE_RE, label: \"Operations:\", code: \"spec.repeated-operations\" },\n { re: COVERS_LINE_RE, label: \"Covers:\", code: \"spec.repeated-covers\" },\n ]) {\n const n = r.text.filter((line) => re.test(line)).length;\n if (n < 2) continue;\n out.push({\n severity: \"warn\",\n code,\n subject,\n message: `${where}: requirement '${r.name}' has ${n} '${label}' lines — the last REPLACES the others (assignment, not append), the earlier list is silently lost; merge them into one comma-separated line`,\n });\n }\n }\n return out;\n}\n\n/**\n * `covers.unknown` — the typo guard on the Covers: line. Warn, not error: the\n * axis is advisory end to end, and a wrong id already costs its author the\n * coverage they wrote the line for. The hint offers only real ids (closeIds's\n * rule), and says where resolution looked when there is nothing close.\n * `healthUnreadable` mutes the alert:/sli: forms only: against a health.yaml\n * nobody could read, \"did you mean\" is a false diagnosis of a typo —\n * health.invalid (emitted by the service target) is the honest one.\n */\n/** Which document is being graded, and under whose name the finding is filed. */\nexport interface CoverageTarget {\n where: string;\n subject: string;\n}\n\nexport function coversUnknownFindings(\n reqs: Requirement[],\n target: CoverageTarget,\n scope: CoverageScope,\n healthUnreadable = false,\n): Finding[] {\n const { where, subject } = target;\n const out: Finding[] = [];\n for (const r of reqs) {\n if (r.kind === \"REMOVED\") continue;\n for (const raw of r.covers) {\n const entry = parseCoversEntry(raw);\n if (healthUnreadable && (entry.form === \"alert\" || entry.form === \"sli\")) continue;\n if (entryResolves(entry, scope)) continue;\n const close = coversCandidates(entry, scope);\n out.push({\n severity: \"warn\",\n code: \"covers.unknown\",\n subject,\n message:\n `${where}: requirement '${r.name}' — Covers: '${raw}' resolves to nothing` +\n (close.length > 0\n ? `. Did you mean: ${close.join(\", \")}?`\n : \" in the model, the landscape or health.yaml\"),\n });\n }\n }\n return out;\n}\n\n/**\n * `permissions.unknown` — the typo guard on the `Requires:` line, and an ERROR\n * where its `Covers:` sibling is a warning.\n *\n * The two differ because what they promise differs. `Covers:` is advisory end\n * to end: a wrong id costs its author the coverage they wrote the line for and\n * nothing else. `Requires:` names authorization the service actually enforces,\n * and the failure it guards is the one an unaided reader cannot see — an\n * invented permission reads exactly like a real one, in the requirement, in the\n * generated scenario, and in the test somebody then writes against it. Its\n * grade is `Operations:`', not `Covers:`'.\n *\n * Silent on ONE case only: an unreadable vocabulary, where\n * `permissions.invalid` is the honest finding and grading every entry against a\n * file nobody could parse is the false cascade `healthUnreadable` exists to\n * stop one axis over. A MISSING vocabulary is not that case — the `Requires:`\n * line is itself the opt-in, and a line that resolves against nothing while\n * reading like a join is the failure this whole axis exists to prevent.\n */\nexport function requiresUnknownFindings(\n reqs: Requirement[],\n target: CoverageTarget,\n vocabulary: Vocabulary,\n): Finding[] {\n const { where, subject } = target;\n if (vocabulary.invalid !== undefined) return [];\n const known = [...vocabulary.byId.keys()];\n const out: Finding[] = [];\n for (const r of reqs) {\n if (r.kind === \"REMOVED\") continue;\n for (const raw of r.requires) {\n if (vocabulary.byId.has(raw)) continue;\n const close = closeIds(raw, known);\n out.push({\n severity: \"error\",\n code: \"permissions.unknown\",\n subject,\n message:\n `${where}: requirement '${r.name}' — Requires: '${raw}' is not declared in architecture/permissions.yaml` +\n (!vocabulary.present\n ? \", which does not exist. The `Requires:` line is the opt-in: create the fleet vocabulary with this permission under its subject kind, or drop the line\"\n : close.length > 0\n ? `. Did you mean: ${close.join(\", \")}?`\n : \". Entries are '<subject>/<permission>'; declare it there, or fix the spelling\"),\n });\n }\n }\n return out;\n}\n\n/**\n * `api.response-ungoverned` — a declared 4xx/5xx response no scenario reaches.\n *\n * The gap this closes is the one a whole adoption can fall into: `api.ungoverned`\n * grades OPERATIONS against requirements, so an endpoint with one happy-path\n * requirement and twelve declared failure codes is fully governed by every\n * check loam had. The refusals are where a service's decision layer surfaces —\n * a permission denied, a field combination rejected, a state that forbids the\n * transition — and the contract is the only artifact in the corpus that already\n * enumerates them.\n *\n * A scenario \"reaches\" a code when the code appears as a standalone number\n * anywhere in its body, `Examples` rows included — which is why this arrived\n * with outline support and not before: a status column is exactly where a\n * matrix puts its codes, and before it those rows were prose in a description.\n * The match is textual and therefore generous by design. It answers \"did\n * anybody write this case down\", not \"is this scenario correct\", and the\n * failure it is built to catch is the code nobody mentioned at all. Warn, like\n * its sibling: a service may legitimately declare a code its scenarios describe\n * in words, and an error would teach authors to paste numbers into prose.\n *\n * Operations no requirement governs are skipped: `api.ungoverned` already\n * names those, and reporting each of their codes as well is one defect\n * counted twice.\n */\nexport function responseGovernanceFindings(\n service: string,\n ops: Operation[],\n livingReqs: Requirement[],\n): Finding[] {\n const ungoverned: string[] = [];\n for (const op of ops) {\n if (op.failureCodes.length === 0) continue;\n const governing = livingReqs.filter((r) => r.kind !== \"REMOVED\" && r.operations.includes(op.id));\n if (governing.length === 0) continue;\n const body = governing.flatMap((r) => r.scenarios.flatMap((s) => s.lines)).join(\"\\n\");\n const missing = op.failureCodes.filter((code) => !new RegExp(`(?<!\\\\d)${code}(?!\\\\d)`).test(body));\n if (missing.length > 0) ungoverned.push(`${op.id}: ${missing.join(\", \")}`);\n }\n if (ungoverned.length === 0) return [];\n return [\n {\n severity: \"warn\",\n code: \"api.response-ungoverned\",\n subject: service,\n message: `${service}: ${ungoverned.length} operation(s) declare a failure response no scenario reaches — write the refusal as a scenario, or as a row in one`,\n details: ungoverned,\n },\n ];\n}\n\nexport function coverageFinding(label: string, reqs: Requirement[]): Finding {\n const missing = requirementsMissingScenarios(reqs);\n if (missing.length === 0) {\n return {\n severity: \"ok\",\n code: \"requirements.covered\",\n message: `${label} covered (${reqs.length} requirement${reqs.length === 1 ? \"\" : \"s\"}, all with scenarios)`,\n };\n }\n return { ...missingScenariosFinding(label, missing), text: { detailPrefix: \"- \" } };\n}\n\n/**\n * The scenario-shape run of the battery every requirement document gets, in\n * report order — stepless, assertionless, examples — spelled once for the four\n * documents the header names, so they cannot drift apart. What differs between\n * the four stays at each call site: a delta's coverage finding carries its\n * service as `subject`, a living spec.md with no requirements reports\n * `spec.no-requirements` in coverage's place, and duplicate names and\n * requirement ids are graded on LIVING documents (`duplicateRequirementFindings`).\n */\nexport function scenarioShapeFindings(label: string, subject: string, reqs: Requirement[]): Finding[] {\n return [\n ...steplessFindings(label, subject, reqs),\n ...assertionlessFindings(label, subject, reqs),\n ...examplesFindings(label, subject, reqs),\n ];\n}\n"]}
@@ -0,0 +1,85 @@
1
+ import { existsSync } from "node:fs";
2
+ import {} from "../../../core/kernel/ids/service.js";
3
+ import { SPEC_AXES } from "../../../core/repo/paths.js";
4
+ import { locateServicePaths } from "../../../core/repo/service-target.js";
5
+ import { listField, readFrontmatter } from "../../../core/document/frontmatter.js";
6
+ import {} from "../../../core/vocabulary/report.js";
7
+ import { missingSources, patternSources, unsafeSources } from "../../../core/provenance/sources.js";
8
+ import { emptySourcesMessage, expandSourceFiles } from "../../../core/provenance/stamp.js";
9
+ /**
10
+ * The two things a `sources` list can be that `serviceProvenance` cannot say.
11
+ *
12
+ * `sources.unverifiable-from-here` — the spec names sources and loam is NOT in
13
+ * that service's repository, so every sources check (existence, digest,
14
+ * staleness) is skipped. serviceProvenance returns an empty list in that case
15
+ * and the silence read as "checked and fine". It used to be counted only under
16
+ * `--all` and printed as one rollup line, which meant `validate --service X`
17
+ * run from the docs repo — the single most common way anyone looks at one
18
+ * service — reported nothing at all about its own blind spot. Severity `ok`,
19
+ * deliberately: nothing is WRONG with the docs, the check simply cannot run
20
+ * here, and grading it a warning would make a fully documented fleet
21
+ * permanently yellow and `--strict` permanently red in the docs repo's CI.
22
+ *
23
+ * `sources.empty` — the paths exist, and expand to no files at all: an empty
24
+ * directory, or a tree the repository itself ignores. A digest over nothing
25
+ * never changes, so the stamp would read as current forever. `loam vouch`
26
+ * already refuses to stamp it; until now `validate` said nothing, so an author
27
+ * got a green run followed by a refusal, two commands contradicting each other
28
+ * about one document. The sentence comes from `emptySourcesMessage`, the same
29
+ * definition vouch refuses with, under the label vouch uses.
30
+ */
31
+ export async function sourceScopeFindings(docsDir, service, repoDir, fleet) {
32
+ const paths = await locateServicePaths(docsDir, service, fleet);
33
+ const out = [];
34
+ // The axis pair is SPEC_AXES', not this function's: `serviceProvenance` grades
35
+ // the same two files from the same list, and a scope check that walked a
36
+ // shorter list than the grading would go quiet on the axis it forgot.
37
+ for (const { path, file } of SPEC_AXES.map((axis) => ({ path: paths[axis.key], file: axis.file }))) {
38
+ if (!existsSync(path))
39
+ continue;
40
+ const sources = listField(await readFrontmatter(path), "sources");
41
+ if (sources.length === 0)
42
+ continue;
43
+ // vouch's own labelling: a bare service id for spec.md, qualified for the
44
+ // arch axis. The refusal and the finding must be the same sentence.
45
+ const label = file === "spec.md" ? service : `${service}: ${file}`;
46
+ if (repoDir === undefined) {
47
+ // A literal, as at the rollup's counting site (../report.ts), and for
48
+ // the reason given there: the stable-code collector reads only literal
49
+ // `code:` slots. This used to be a shared constant, which kept the two
50
+ // spellings equal but hid the emission itself from the collector — the
51
+ // code was guarded only because the rollup's text marker spelled it.
52
+ //
53
+ // `ok` still, but never PRINTED as ✓: the check above did not run, and
54
+ // a check mark beside "nothing here can resolve them" read as a pass.
55
+ // The hint changes the glyph and nothing a machine or an exit code reads.
56
+ out.push({
57
+ severity: "ok",
58
+ code: "sources.unverifiable-from-here",
59
+ subject: service,
60
+ message: `${label}: ${sources.length} source(s) declared, but this is not ${service}'s repository — nothing here can resolve them. Run \`loam validate --service ${service}\` from inside it.`,
61
+ text: { marker: "not-checked" },
62
+ });
63
+ continue;
64
+ }
65
+ // Every other shape of broken list is serviceProvenance's to grade, and
66
+ // grading them twice would send an author fixing one thing from two
67
+ // findings. "Covers no files" is only meaningful once the paths are real.
68
+ if (patternSources(sources).length > 0 ||
69
+ unsafeSources(repoDir, sources).length > 0 ||
70
+ missingSources(repoDir, sources).length > 0) {
71
+ continue;
72
+ }
73
+ const expansion = await expandSourceFiles(repoDir, sources, label);
74
+ if (expansion.files.length > 0)
75
+ continue;
76
+ out.push({
77
+ severity: "warn",
78
+ code: "sources.empty",
79
+ subject: service,
80
+ message: expansion.empty ?? emptySourcesMessage(label, sources),
81
+ });
82
+ }
83
+ return out;
84
+ }
85
+ //# sourceMappingURL=sources.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sources.js","sourceRoot":"","sources":["../../../../src/commands/validate/checks/sources.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync } from \"node:fs\";\nimport { type PathableService } from \"../../../core/kernel/ids/service.js\";\nimport { SPEC_AXES } from \"../../../core/repo/paths.js\";\nimport type { FleetContext } from \"../../../core/fleet-context.js\";\nimport { locateServicePaths } from \"../../../core/repo/service-target.js\";\nimport { listField, readFrontmatter } from \"../../../core/document/frontmatter.js\";\nimport { type Finding } from \"../../../core/vocabulary/report.js\";\nimport { missingSources, patternSources, unsafeSources } from \"../../../core/provenance/sources.js\";\nimport { emptySourcesMessage, expandSourceFiles } from \"../../../core/provenance/stamp.js\";\nimport type { DocsDir } from \"../../../core/kernel/ids/dirs.js\";\n\n/**\n * The two things a `sources` list can be that `serviceProvenance` cannot say.\n *\n * `sources.unverifiable-from-here` — the spec names sources and loam is NOT in\n * that service's repository, so every sources check (existence, digest,\n * staleness) is skipped. serviceProvenance returns an empty list in that case\n * and the silence read as \"checked and fine\". It used to be counted only under\n * `--all` and printed as one rollup line, which meant `validate --service X`\n * run from the docs repo — the single most common way anyone looks at one\n * service — reported nothing at all about its own blind spot. Severity `ok`,\n * deliberately: nothing is WRONG with the docs, the check simply cannot run\n * here, and grading it a warning would make a fully documented fleet\n * permanently yellow and `--strict` permanently red in the docs repo's CI.\n *\n * `sources.empty` — the paths exist, and expand to no files at all: an empty\n * directory, or a tree the repository itself ignores. A digest over nothing\n * never changes, so the stamp would read as current forever. `loam vouch`\n * already refuses to stamp it; until now `validate` said nothing, so an author\n * got a green run followed by a refusal, two commands contradicting each other\n * about one document. The sentence comes from `emptySourcesMessage`, the same\n * definition vouch refuses with, under the label vouch uses.\n */\nexport async function sourceScopeFindings(\n docsDir: DocsDir,\n service: PathableService,\n repoDir: string | undefined,\n fleet: FleetContext,\n): Promise<Finding[]> {\n const paths = await locateServicePaths(docsDir, service, fleet);\n const out: Finding[] = [];\n // The axis pair is SPEC_AXES', not this function's: `serviceProvenance` grades\n // the same two files from the same list, and a scope check that walked a\n // shorter list than the grading would go quiet on the axis it forgot.\n for (const { path, file } of SPEC_AXES.map((axis) => ({ path: paths[axis.key], file: axis.file }))) {\n if (!existsSync(path)) continue;\n const sources = listField(await readFrontmatter(path), \"sources\");\n if (sources.length === 0) continue;\n // vouch's own labelling: a bare service id for spec.md, qualified for the\n // arch axis. The refusal and the finding must be the same sentence.\n const label = file === \"spec.md\" ? service : `${service}: ${file}`;\n if (repoDir === undefined) {\n // A literal, as at the rollup's counting site (../report.ts), and for\n // the reason given there: the stable-code collector reads only literal\n // `code:` slots. This used to be a shared constant, which kept the two\n // spellings equal but hid the emission itself from the collector — the\n // code was guarded only because the rollup's text marker spelled it.\n //\n // `ok` still, but never PRINTED as ✓: the check above did not run, and\n // a check mark beside \"nothing here can resolve them\" read as a pass.\n // The hint changes the glyph and nothing a machine or an exit code reads.\n out.push({\n severity: \"ok\",\n code: \"sources.unverifiable-from-here\",\n subject: service,\n message: `${label}: ${sources.length} source(s) declared, but this is not ${service}'s repository — nothing here can resolve them. Run \\`loam validate --service ${service}\\` from inside it.`,\n text: { marker: \"not-checked\" },\n });\n continue;\n }\n // Every other shape of broken list is serviceProvenance's to grade, and\n // grading them twice would send an author fixing one thing from two\n // findings. \"Covers no files\" is only meaningful once the paths are real.\n if (\n patternSources(sources).length > 0 ||\n unsafeSources(repoDir, sources).length > 0 ||\n missingSources(repoDir, sources).length > 0\n ) {\n continue;\n }\n const expansion = await expandSourceFiles(repoDir, sources, label);\n if (expansion.files.length > 0) continue;\n out.push({\n severity: \"warn\",\n code: \"sources.empty\",\n subject: service,\n message: expansion.empty ?? emptySourcesMessage(label, sources),\n });\n }\n return out;\n}\n"]}