@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,341 @@
1
+ /**
2
+ * Does the diff apply to the thing it claims to change?
3
+ *
4
+ * A requirement delta is a diff against a living spec, and nothing used to check
5
+ * that it lands. Every failure mode here is silent today: MODIFIED of a
6
+ * requirement that does not exist is merged as a creation, ADDED of one that
7
+ * does exist REPLACES it (scenarios and all) while the author believes they are
8
+ * adding, and a heading that nearly matches the delta grammar parses as plain
9
+ * prose so archive merges nothing at all and says nothing about it.
10
+ *
11
+ * The last of those has a legal-looking cousin: a requirement under an ordinary
12
+ * prose heading (`## Behavior`, `## Error Handling`) is BASE too, and BASE never
13
+ * merges. Upstream OpenSpec deltas are written that way, so the answer is to name
14
+ * what will be lost rather than to start merging prose sections.
15
+ *
16
+ * These run inside the archive gate, because the merge is where the damage lands.
17
+ *
18
+ * TWO CORPORA, ONE ALGEBRA. A feature's delta documents live in two places —
19
+ * `specs/<svc>/{spec,arch.spec}.md` against the service tree, and
20
+ * `capabilities/<id>/spec.md` against the authored business tree — and every
21
+ * grade about a DOCUMENT and its living counterpart applies to both verbatim,
22
+ * with the capability id in `subject` where a service id would be. That is not
23
+ * a coincidence to exploit but the reason the business corpus was given deltas
24
+ * at all: a capability document is a requirements document, so the diff that
25
+ * changes one has exactly the same ways of not landing. A second implementation
26
+ * would be a second set of answers to `delta.added-duplicate`.
27
+ *
28
+ * The exception is the four CROSS-FEATURE warnings — `delta.added-conflict`,
29
+ * `delta.modified-conflict`, `delta.modified-pending`, `delta.removed-pending`
30
+ * — which ask what OTHER features in flight claim. `./claims.ts` indexes the
31
+ * service corpus only and states why; on the business axis those four are
32
+ * silent, which is a missing warning and never a wrong answer.
33
+ *
34
+ * This module is only the walk: which documents get read, in what order, and how
35
+ * each is handed a `DeltaScope`. The checks themselves are in `./document.ts`
36
+ * (a document against itself) and `./select.ts` (the delta against the living
37
+ * text). Their order is load-bearing and stays here, where it can be read in one
38
+ * screen.
39
+ */
40
+ import { existsSync } from "node:fs";
41
+ import { readFile } from "node:fs/promises";
42
+ import { relative } from "node:path";
43
+ import { FleetContext } from "../fleet-context.js";
44
+ import { parseRequirements, readRequirementsDocument } from "../document/parse.js";
45
+ import {} from "../document/spec.js";
46
+ import { featureSpecPaths, SPEC_AXES } from "../repo/paths.js";
47
+ import { featureUseCasesDir, livingCapabilityPaths } from "../repo/authored/paths.js";
48
+ import { readCapabilityVocabulary } from "../capabilities/capabilities.js";
49
+ import { extendingModels } from "../c4/service-model/fleet/extending.js";
50
+ import { flowCoverage } from "../usecases/delta/claims.js";
51
+ import { changedPromiseFlowIssues } from "../usecases/delta/modified.js";
52
+ import { enumeratedServiceIds, locateServicePaths } from "../repo/service-target.js";
53
+ import { featureSpecServices } from "../repo/repo.js";
54
+ import { capabilityDocIssues } from "../capabilities/delta/doc.js";
55
+ import { featureCapabilityDeltas } from "../capabilities/delta/tree.js";
56
+ import { removedRealizedIssues, uncoveredIssues, } from "../capabilities/delta/uncovered.js";
57
+ import {} from "../vocabulary/issue.js";
58
+ import { claimLookup } from "./claims.js";
59
+ import { deltaDocumentIssues, livingDocumentIssues } from "./document.js";
60
+ import { indexLiving } from "./scope.js";
61
+ import { selectionIssues } from "./select.js";
62
+ /**
63
+ * The business corpus's ONE axis. A capability document carries the promise and
64
+ * nothing else — there is no `arch.spec.md` beside it, because "how it is
65
+ * built" is precisely the altitude a capability requirement may not describe
66
+ * (`capability.requirement-service-scoped` is that rule). It has no `key`
67
+ * because it indexes no `ServicePaths`, which is why `DeltaScope.axis` is the
68
+ * narrower `DeltaAxis` and not `SpecAxis`.
69
+ */
70
+ const CAPABILITY_AXIS = { file: "spec.md" };
71
+ export async function deltaShapeIssues(docsDir, featureDir, featureId, context) {
72
+ const issues = [];
73
+ const services = await featureSpecServices(featureDir, context);
74
+ // One `existsSync` for a feature that carries no capability delta, which is
75
+ // every feature in a fleet that has not adopted the business axis.
76
+ const capabilities = context === undefined ? await featureCapabilityDeltas(featureDir) : await context.featureCapabilityDeltas(featureDir);
77
+ // The flows this feature brings, and one `existsSync` for a feature that
78
+ // brings none — which is every feature in a fleet that has not adopted the
79
+ // axis. The directory, not the documents: what is needed here is whether to
80
+ // pay for the overlay at all, and the walk that lists them happens once,
81
+ // inside it.
82
+ const hasFlows = existsSync(featureUseCasesDir(featureDir));
83
+ // The early return must ask about EVERY corpus. Asking only about services
84
+ // meant a capability-only feature — a business change with no service touched
85
+ // yet, which is exactly what an analyst writes first — was graded by nothing
86
+ // and archived whatever its delta said; asking only about those two would do
87
+ // the same to a feature whose whole content is a cross-service flow, which is
88
+ // the shape an architect answers an analyst with.
89
+ if (services.length === 0 && capabilities.docs.length === 0 && !hasFlows)
90
+ return issues;
91
+ // What OTHER features in flight claim. Only built when a claim has to be
92
+ // checked — the common case never pays for the scan.
93
+ const reads = {
94
+ claims: claimLookup(docsDir, featureId, context),
95
+ ...(context === undefined ? {} : { context }),
96
+ };
97
+ // The two corpora's parsed requirements, kept as the walk produces them so
98
+ // the `Realizes:` join below can be taken without re-reading a byte. That
99
+ // join is the one question neither corpus can answer alone — which service
100
+ // requirement keeps which business promise — and this is the only place in
101
+ // loam where both sides are already open (`capabilities/delta/uncovered.ts`
102
+ // holds the rules; nothing here decides anything).
103
+ const serviceDeltas = [];
104
+ const capabilityDeltas = [];
105
+ // Each service axis beside its living document, for the one question that
106
+ // needs both: which living flow claims a requirement this feature changes.
107
+ const servicePairs = [];
108
+ // Both requirement-carrying files per service run the same checks — one code
109
+ // path parameterized by filename, the merge's own factoring. `where` names
110
+ // the arch file in messages so a finding cannot be chased into the wrong
111
+ // document; spec.md keeps its historical spelling.
112
+ for (const service of services) {
113
+ for (const axis of SPEC_AXES) {
114
+ const specPath = featureSpecPaths(featureDir, service)[axis.key];
115
+ if (!existsSync(specPath))
116
+ continue;
117
+ const scope = {
118
+ kind: "service",
119
+ subject: service,
120
+ axis,
121
+ featureId,
122
+ docsDir,
123
+ specPath,
124
+ where: axis.key === "spec" ? service : `${service} (arch.spec.md)`,
125
+ // How the axis's living document is named in messages — spec.md keeps
126
+ // the historical "living spec", the arch axis says which file it means.
127
+ livingDoc: axis.key === "spec" ? "living spec" : "living arch.spec.md",
128
+ };
129
+ const graded = await gradeDelta(scope, (await locateServicePaths(docsDir, service, context))[axis.key], reads);
130
+ issues.push(...graded.issues);
131
+ serviceDeltas.push({ service, file: axis.file, reqs: graded.reqs });
132
+ const paths = () => locateServicePaths(docsDir, service, context);
133
+ servicePairs.push({ id: service, axis: axis.key, reqs: graded.reqs, living: graded.living.all, paths });
134
+ }
135
+ }
136
+ for (const doc of capabilities.docs) {
137
+ const scope = {
138
+ kind: "capability",
139
+ subject: doc.id,
140
+ axis: CAPABILITY_AXIS,
141
+ featureId,
142
+ docsDir,
143
+ specPath: doc.spec,
144
+ // `capability <id>`, not `capabilities/<id>` — the second reads as the
145
+ // LIVING directory, and every message this labels is about the FEATURE's
146
+ // delta of it. Sending an author to edit the wrong one of two files with
147
+ // the same name is the whole reason `where` and `livingDoc` are separate.
148
+ where: `capability ${doc.id}`,
149
+ livingDoc: `living capabilities/${doc.id}/spec.md`,
150
+ };
151
+ // Absent is a real and ordinary answer on this axis: the first feature to
152
+ // mention a capability is what creates its living document, so the whole
153
+ // delta grades against `[]` and every requirement in it is legitimately an
154
+ // addition.
155
+ const graded = await gradeDelta(scope, livingCapabilityPaths(docsDir, doc.id).spec, reads);
156
+ issues.push(...graded.issues);
157
+ // The document's own three rules, on the requirements this delta would
158
+ // MERGE — before the merge, where the author can still fix them. See
159
+ // `capabilities/delta/doc.ts` for why grading only the living copy leaves a
160
+ // hole straight through the altitude rule.
161
+ issues.push(...capabilityDocIssues(graded.reqs, {
162
+ where: relative(docsDir, doc.spec).split(/[\\/]/).join("/"),
163
+ subject: doc.id,
164
+ }));
165
+ capabilityDeltas.push({ id: doc.id, reqs: graded.reqs, living: graded.living.all });
166
+ }
167
+ // The other carrier of a promise, read once and only when this feature
168
+ // actually brings a flow: the `dynamic view`s under `features/<FEAT>/usecases/`,
169
+ // parsed over the map this feature's own merge would leave behind
170
+ // (`core/usecases/delta/overlay.ts`).
171
+ // A feature with no `usecases/` directory is a REAL empty answer, not an
172
+ // ungraded one: there is no flow, so "no flow keeps this" is true and the
173
+ // message may say it.
174
+ const flows = hasFlows
175
+ ? await flowCoverage({
176
+ docsDir,
177
+ featureDir,
178
+ featureId,
179
+ capabilities: capabilityDeltas,
180
+ // Read HERE, through the invocation's index, because this module holds
181
+ // it and `core/usecases/` does not — every other read in this walk does
182
+ // the same, and `core/repo/service-target.ts` prices a fleet
183
+ // enumeration per call at ~13 ms on a 120-service fleet.
184
+ vocabulary: context === undefined ? await readCapabilityVocabulary(docsDir) : await context.capabilities(docsDir),
185
+ // The fleet the merge leaves: each `specs/<svc>/` of this feature becomes a
186
+ // `services/<svc>/`, so a hop into a service it introduces resolves to that
187
+ // service in the grade, as it will under the next `validate --all`.
188
+ known: new Set([...(await enumeratedServiceIds(docsDir, context)), ...services]),
189
+ // Decoded or refused by name (`readRequirementsDocument`), never `readFile`'s
190
+ // utf8 — a UTF-16 capability document would read as no requirements and
191
+ // convict every flow naming it.
192
+ read: async (path) => (context === undefined ? parseRequirements(await readRequirementsDocument(path)) : await context.readRequirements(path)),
193
+ // A function rather than the context itself: one memoised LikeC4 read
194
+ // does not justify an edge from `core/usecases/` to `fleet-context`, and
195
+ // the edge would push that package up a DAG level for nothing.
196
+ ...(context === undefined ? {} : { load: (path) => context.loadLikeC4(path) }),
197
+ // The fleet's extending models, for the merge preview the overlay
198
+ // grades against — read HERE for `vocabulary`'s reason exactly, and as
199
+ // a thunk so the walk pays for it only when a flow is really there.
200
+ // Without it the preview is the pre-routing map and `usecase.flow-invalid`
201
+ // fails open on the one shape it exists for: a hop into
202
+ // `<service-fqn>.<container>`, which the archive routes into that
203
+ // service's own model (verification 2026-09-04, review F8).
204
+ models: () => extendingModels(docsDir, context),
205
+ })
206
+ : { promises: { kind: "read", kept: [] }, issues: [] };
207
+ const kept = flows.promises;
208
+ if (kept.kind === "unreadable") {
209
+ // ERROR, and the archive gate's own `NEVER_OVERRIDABLE` keeps `--approve`
210
+ // off it. This is the refusal that stops a flow being copied into
211
+ // `architecture/` and the NEXT reader's `loam validate --all` carrying the
212
+ // failure — including the case the overlay exists for, a hop naming an
213
+ // element the merge does not land. Mechanical, so it is not loam's judgement
214
+ // to override.
215
+ issues.push({
216
+ severity: "error",
217
+ code: "usecase.flow-invalid",
218
+ subject: featureId,
219
+ // The opening sentence does NOT say whose file is at fault, and that is
220
+ // deliberate: the corpus this reads is the feature's flows PLUS the living
221
+ // `architecture/` documents they are drawn over, so the failing path can
222
+ // be a living one — a landscape that no longer parses, a use case somebody
223
+ // else wrote. Every message carries its own path, so a reader can place
224
+ // it; an opening line that blamed `usecases/` would send them to the wrong
225
+ // file first.
226
+ message: `this feature's flows could not be graded against the map its own merge would leave behind, so the archive ` +
227
+ `would land an architecture/ nothing has checked. The corpus is the feature's usecases/ AND the living ` +
228
+ `architecture/ documents they are drawn over, so the fault may be in either — each message names its file. ` +
229
+ `${kept.errors.length} problem(s): ${kept.errors.join("; ")}`,
230
+ });
231
+ }
232
+ // And the flows that DID read, graded as `validate --all` grades them once
233
+ // living: every hop against the post-merge map, every `#cap-`/`#req-` tag
234
+ // against the vocabulary and requirements the merge leaves
235
+ // (`core/usecases/grade/feature.ts`). Before this, a hop nothing backs and a
236
+ // `#req-` tag nothing resolves archived clean and turned the fleet red.
237
+ issues.push(...flows.issues);
238
+ // The `Realizes:` join, both directions, over documents this walk has already
239
+ // parsed. Skipped entirely when the feature carries no capability delta,
240
+ // which is every feature in a fleet that has not adopted the business axis —
241
+ // and the removal half asks for the living corpus only when something is
242
+ // actually retired, so even an adopting fleet pays the fleet-wide read on the
243
+ // features that earn it.
244
+ if (capabilityDeltas.length > 0) {
245
+ // The three arms travel as three, and flattening two of them to `[]` is
246
+ // the one thing this must not do: `capability.uncovered` says in words that
247
+ // no flow keeps the promise, so handing it an empty list for a corpus loam
248
+ // could not read or could not resolve makes it assert a negative it never
249
+ // evaluated — and gate on it. `claims.ts`'s header states the rule; this is
250
+ // where a caller could break it.
251
+ issues.push(...uncoveredIssues(capabilityDeltas, serviceDeltas, kept.kind === "read"
252
+ ? { graded: true, kept: kept.kept }
253
+ : { graded: false, why: kept.kind === "ungraded" ? kept.why : kept.errors.join("; ") }));
254
+ issues.push(...(await removedRealizedIssues({
255
+ capabilities: capabilityDeltas,
256
+ deltas: serviceDeltas,
257
+ living: () => livingRealizers(docsDir, context),
258
+ })));
259
+ }
260
+ // The living flows whose `#req-` tag claims a promise this feature rewrites or
261
+ // retires (`core/usecases/delta/modified.ts`). Asked only when a requirement is
262
+ // MODIFIED or REMOVED, on either corpus, so no other feature reads a flow for it.
263
+ if ([...capabilityDeltas, ...servicePairs].some((doc) => doc.reqs.some((r) => r.kind === "MODIFIED" || r.kind === "REMOVED"))) {
264
+ const ctx = context ?? new FleetContext();
265
+ issues.push(...(await changedPromiseFlowIssues({
266
+ docsDir,
267
+ capabilities: capabilityDeltas,
268
+ services: servicePairs,
269
+ vocabulary: await ctx.capabilities(docsDir),
270
+ known: new Set(await enumeratedServiceIds(docsDir, ctx)),
271
+ serviceModel: (paths) => ctx.serviceModel(docsDir, paths),
272
+ architecture: () => ctx.architecture(docsDir),
273
+ readRequirements: (path) => ctx.readRequirements(path),
274
+ })));
275
+ }
276
+ return issues;
277
+ }
278
+ /**
279
+ * Every LIVING service requirements document in the fleet, for the one question
280
+ * that has to ask about services this feature never mentions: does anything out
281
+ * there still realize a capability requirement this feature retires?
282
+ *
283
+ * The same shape and the same cost `openapi.remove-op-consumed` pays through
284
+ * the consumer index (`core/consumers/`) one axis over, and for the same reason — the merge
285
+ * deletes the promise while the `Realizes:` line stays, so the very next
286
+ * `validate --all` reports a breach on a repository whose author was never in
287
+ * this feature. Called behind a thunk (`removedRealizedIssues` invokes it only
288
+ * when something is retired), so a feature that removes nothing never runs it.
289
+ */
290
+ async function livingRealizers(docsDir, context) {
291
+ const out = [];
292
+ for (const service of await enumeratedServiceIds(docsDir, context)) {
293
+ const paths = await locateServicePaths(docsDir, service, context);
294
+ for (const axis of SPEC_AXES) {
295
+ const path = paths[axis.key];
296
+ if (!existsSync(path))
297
+ continue;
298
+ const reqs = context === undefined ? parseRequirements(await readFile(path, "utf8")) : await context.readRequirements(path);
299
+ out.push({ service, file: axis.file, reqs });
300
+ }
301
+ }
302
+ return out;
303
+ }
304
+ /**
305
+ * One delta document against one living document: the three passes, in the
306
+ * order that makes their messages readable.
307
+ *
308
+ * The order is load-bearing. `deltaDocumentIssues` settles what the delta says
309
+ * about itself, `livingDocumentIssues` settles whether the living text can be
310
+ * selected in at all, and only then does `selectionIssues` compare them — a pin
311
+ * the document pass already refused must not also be reported stale, which
312
+ * would send its author to `loam rebase` for a problem rebase does not fix.
313
+ *
314
+ * The parsed delta requirements come back with the issues because the capability
315
+ * corpus grades them a second way (`capabilityDocIssues`) and re-reading the
316
+ * file to do it would be a second parse of bytes already in hand — and, without
317
+ * a context, a second chance for the two passes to disagree about the document.
318
+ * The LIVING index rides back for the same reason once more: the removal
319
+ * direction of the `Realizes:` join has to resolve a REMOVED spelled by heading
320
+ * into the id it retires, and that id is a fact about the living document.
321
+ */
322
+ async function gradeDelta(scope, livingPath, reads) {
323
+ const { claims, context } = reads;
324
+ const raw = context === undefined ? await readFile(scope.specPath, "utf8") : await context.readText(scope.specPath);
325
+ const reqs = context === undefined ? parseRequirements(raw) : await context.readRequirements(scope.specPath);
326
+ const living = indexLiving(!existsSync(livingPath)
327
+ ? []
328
+ : context === undefined
329
+ ? parseRequirements(await readFile(livingPath, "utf8"))
330
+ : await context.readRequirements(livingPath));
331
+ return {
332
+ reqs,
333
+ living,
334
+ issues: [
335
+ ...deltaDocumentIssues(scope, raw, reqs),
336
+ ...livingDocumentIssues(scope, living),
337
+ ...(await selectionIssues(scope, reqs, living, claims)),
338
+ ],
339
+ };
340
+ }
341
+ //# sourceMappingURL=delta.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delta.js","sourceRoot":"","sources":["../../../src/core/delta/delta.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Does the diff apply to the thing it claims to change?\n *\n * A requirement delta is a diff against a living spec, and nothing used to check\n * that it lands. Every failure mode here is silent today: MODIFIED of a\n * requirement that does not exist is merged as a creation, ADDED of one that\n * does exist REPLACES it (scenarios and all) while the author believes they are\n * adding, and a heading that nearly matches the delta grammar parses as plain\n * prose so archive merges nothing at all and says nothing about it.\n *\n * The last of those has a legal-looking cousin: a requirement under an ordinary\n * prose heading (`## Behavior`, `## Error Handling`) is BASE too, and BASE never\n * merges. Upstream OpenSpec deltas are written that way, so the answer is to name\n * what will be lost rather than to start merging prose sections.\n *\n * These run inside the archive gate, because the merge is where the damage lands.\n *\n * TWO CORPORA, ONE ALGEBRA. A feature's delta documents live in two places —\n * `specs/<svc>/{spec,arch.spec}.md` against the service tree, and\n * `capabilities/<id>/spec.md` against the authored business tree — and every\n * grade about a DOCUMENT and its living counterpart applies to both verbatim,\n * with the capability id in `subject` where a service id would be. That is not\n * a coincidence to exploit but the reason the business corpus was given deltas\n * at all: a capability document is a requirements document, so the diff that\n * changes one has exactly the same ways of not landing. A second implementation\n * would be a second set of answers to `delta.added-duplicate`.\n *\n * The exception is the four CROSS-FEATURE warnings — `delta.added-conflict`,\n * `delta.modified-conflict`, `delta.modified-pending`, `delta.removed-pending`\n * — which ask what OTHER features in flight claim. `./claims.ts` indexes the\n * service corpus only and states why; on the business axis those four are\n * silent, which is a missing warning and never a wrong answer.\n *\n * This module is only the walk: which documents get read, in what order, and how\n * each is handed a `DeltaScope`. The checks themselves are in `./document.ts`\n * (a document against itself) and `./select.ts` (the delta against the living\n * text). Their order is load-bearing and stays here, where it can be read in one\n * screen.\n */\nimport { existsSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport { relative } from \"node:path\";\nimport { FleetContext } from \"../fleet-context.js\";\nimport { parseRequirements, readRequirementsDocument } from \"../document/parse.js\";\nimport { type Requirement } from \"../document/spec.js\";\nimport { featureSpecPaths, SPEC_AXES } from \"../repo/paths.js\";\nimport { featureUseCasesDir, livingCapabilityPaths } from \"../repo/authored/paths.js\";\nimport { readCapabilityVocabulary } from \"../capabilities/capabilities.js\";\nimport { extendingModels } from \"../c4/service-model/fleet/extending.js\";\n\nimport { flowCoverage, type FlowPromises } from \"../usecases/delta/claims.js\";\nimport { changedPromiseFlowIssues, type ServiceDeltaPair } from \"../usecases/delta/modified.js\";\nimport { enumeratedServiceIds, locateServicePaths } from \"../repo/service-target.js\";\nimport { featureSpecServices } from \"../repo/repo.js\";\nimport { capabilityDocIssues } from \"../capabilities/delta/doc.js\";\nimport { featureCapabilityDeltas } from \"../capabilities/delta/tree.js\";\nimport {\n removedRealizedIssues,\n uncoveredIssues,\n type CapabilityDeltaDoc,\n type RealizingDoc,\n} from \"../capabilities/delta/uncovered.js\";\nimport { type Issue } from \"../vocabulary/issue.js\";\nimport { claimLookup, type ClaimLookup } from \"./claims.js\";\nimport { deltaDocumentIssues, livingDocumentIssues } from \"./document.js\";\nimport { indexLiving, type DeltaScope, type LivingIndex } from \"./scope.js\";\nimport { selectionIssues } from \"./select.js\";\nimport type { DocsDir, FeatureDir } from \"../kernel/ids/dirs.js\";\n\n/**\n * The business corpus's ONE axis. A capability document carries the promise and\n * nothing else — there is no `arch.spec.md` beside it, because \"how it is\n * built\" is precisely the altitude a capability requirement may not describe\n * (`capability.requirement-service-scoped` is that rule). It has no `key`\n * because it indexes no `ServicePaths`, which is why `DeltaScope.axis` is the\n * narrower `DeltaAxis` and not `SpecAxis`.\n */\nconst CAPABILITY_AXIS = { file: \"spec.md\" };\n\n/**\n * What every document in one feature's walk shares.\n *\n * A record rather than two more parameters because both values are about the\n * WALK and not about the document being graded — `gradeDelta` would otherwise\n * read as a four-argument function whose last two arguments never vary within\n * a run, which is how the next value gets added as a fifth.\n */\ninterface DeltaReads {\n /** What OTHER features in flight claim — lazy, so the common case never scans. */\n claims: ClaimLookup;\n /** The invocation's read index, when the caller threaded one. */\n context?: FleetContext;\n}\n\nexport async function deltaShapeIssues(\n docsDir: DocsDir,\n featureDir: FeatureDir,\n featureId: string,\n context?: FleetContext,\n): Promise<Issue[]> {\n const issues: Issue[] = [];\n const services = await featureSpecServices(featureDir, context);\n // One `existsSync` for a feature that carries no capability delta, which is\n // every feature in a fleet that has not adopted the business axis.\n const capabilities =\n context === undefined ? await featureCapabilityDeltas(featureDir) : await context.featureCapabilityDeltas(featureDir);\n // The flows this feature brings, and one `existsSync` for a feature that\n // brings none — which is every feature in a fleet that has not adopted the\n // axis. The directory, not the documents: what is needed here is whether to\n // pay for the overlay at all, and the walk that lists them happens once,\n // inside it.\n const hasFlows = existsSync(featureUseCasesDir(featureDir));\n // The early return must ask about EVERY corpus. Asking only about services\n // meant a capability-only feature — a business change with no service touched\n // yet, which is exactly what an analyst writes first — was graded by nothing\n // and archived whatever its delta said; asking only about those two would do\n // the same to a feature whose whole content is a cross-service flow, which is\n // the shape an architect answers an analyst with.\n if (services.length === 0 && capabilities.docs.length === 0 && !hasFlows) return issues;\n\n // What OTHER features in flight claim. Only built when a claim has to be\n // checked — the common case never pays for the scan.\n const reads: DeltaReads = {\n claims: claimLookup(docsDir, featureId, context),\n ...(context === undefined ? {} : { context }),\n };\n\n // The two corpora's parsed requirements, kept as the walk produces them so\n // the `Realizes:` join below can be taken without re-reading a byte. That\n // join is the one question neither corpus can answer alone — which service\n // requirement keeps which business promise — and this is the only place in\n // loam where both sides are already open (`capabilities/delta/uncovered.ts`\n // holds the rules; nothing here decides anything).\n const serviceDeltas: RealizingDoc[] = [];\n const capabilityDeltas: CapabilityDeltaDoc[] = [];\n // Each service axis beside its living document, for the one question that\n // needs both: which living flow claims a requirement this feature changes.\n const servicePairs: ServiceDeltaPair[] = [];\n\n // Both requirement-carrying files per service run the same checks — one code\n // path parameterized by filename, the merge's own factoring. `where` names\n // the arch file in messages so a finding cannot be chased into the wrong\n // document; spec.md keeps its historical spelling.\n for (const service of services) {\n for (const axis of SPEC_AXES) {\n const specPath = featureSpecPaths(featureDir, service)[axis.key];\n if (!existsSync(specPath)) continue;\n const scope: DeltaScope = {\n kind: \"service\",\n subject: service,\n axis,\n featureId,\n docsDir,\n specPath,\n where: axis.key === \"spec\" ? service : `${service} (arch.spec.md)`,\n // How the axis's living document is named in messages — spec.md keeps\n // the historical \"living spec\", the arch axis says which file it means.\n livingDoc: axis.key === \"spec\" ? \"living spec\" : \"living arch.spec.md\",\n };\n const graded = await gradeDelta(scope, (await locateServicePaths(docsDir, service, context))[axis.key], reads);\n issues.push(...graded.issues);\n serviceDeltas.push({ service, file: axis.file, reqs: graded.reqs });\n const paths = (): ReturnType<typeof locateServicePaths> => locateServicePaths(docsDir, service, context);\n servicePairs.push({ id: service, axis: axis.key, reqs: graded.reqs, living: graded.living.all, paths });\n }\n }\n\n for (const doc of capabilities.docs) {\n const scope: DeltaScope = {\n kind: \"capability\",\n subject: doc.id,\n axis: CAPABILITY_AXIS,\n featureId,\n docsDir,\n specPath: doc.spec,\n // `capability <id>`, not `capabilities/<id>` — the second reads as the\n // LIVING directory, and every message this labels is about the FEATURE's\n // delta of it. Sending an author to edit the wrong one of two files with\n // the same name is the whole reason `where` and `livingDoc` are separate.\n where: `capability ${doc.id}`,\n livingDoc: `living capabilities/${doc.id}/spec.md`,\n };\n // Absent is a real and ordinary answer on this axis: the first feature to\n // mention a capability is what creates its living document, so the whole\n // delta grades against `[]` and every requirement in it is legitimately an\n // addition.\n const graded = await gradeDelta(scope, livingCapabilityPaths(docsDir, doc.id).spec, reads);\n issues.push(...graded.issues);\n // The document's own three rules, on the requirements this delta would\n // MERGE — before the merge, where the author can still fix them. See\n // `capabilities/delta/doc.ts` for why grading only the living copy leaves a\n // hole straight through the altitude rule.\n issues.push(\n ...capabilityDocIssues(graded.reqs, {\n where: relative(docsDir, doc.spec).split(/[\\\\/]/).join(\"/\"),\n subject: doc.id,\n }),\n );\n capabilityDeltas.push({ id: doc.id, reqs: graded.reqs, living: graded.living.all });\n }\n\n // The other carrier of a promise, read once and only when this feature\n // actually brings a flow: the `dynamic view`s under `features/<FEAT>/usecases/`,\n // parsed over the map this feature's own merge would leave behind\n // (`core/usecases/delta/overlay.ts`).\n // A feature with no `usecases/` directory is a REAL empty answer, not an\n // ungraded one: there is no flow, so \"no flow keeps this\" is true and the\n // message may say it.\n const flows: { promises: FlowPromises; issues: Issue[] } = hasFlows\n ? await flowCoverage({\n docsDir,\n featureDir,\n featureId,\n capabilities: capabilityDeltas,\n // Read HERE, through the invocation's index, because this module holds\n // it and `core/usecases/` does not — every other read in this walk does\n // the same, and `core/repo/service-target.ts` prices a fleet\n // enumeration per call at ~13 ms on a 120-service fleet.\n vocabulary: context === undefined ? await readCapabilityVocabulary(docsDir) : await context.capabilities(docsDir),\n // The fleet the merge leaves: each `specs/<svc>/` of this feature becomes a\n // `services/<svc>/`, so a hop into a service it introduces resolves to that\n // service in the grade, as it will under the next `validate --all`.\n known: new Set([...(await enumeratedServiceIds(docsDir, context)), ...services]),\n // Decoded or refused by name (`readRequirementsDocument`), never `readFile`'s\n // utf8 — a UTF-16 capability document would read as no requirements and\n // convict every flow naming it.\n read: async (path) => (context === undefined ? parseRequirements(await readRequirementsDocument(path)) : await context.readRequirements(path)),\n // A function rather than the context itself: one memoised LikeC4 read\n // does not justify an edge from `core/usecases/` to `fleet-context`, and\n // the edge would push that package up a DAG level for nothing.\n ...(context === undefined ? {} : { load: (path: string) => context.loadLikeC4(path) }),\n // The fleet's extending models, for the merge preview the overlay\n // grades against — read HERE for `vocabulary`'s reason exactly, and as\n // a thunk so the walk pays for it only when a flow is really there.\n // Without it the preview is the pre-routing map and `usecase.flow-invalid`\n // fails open on the one shape it exists for: a hop into\n // `<service-fqn>.<container>`, which the archive routes into that\n // service's own model (verification 2026-09-04, review F8).\n models: () => extendingModels(docsDir, context),\n })\n : { promises: { kind: \"read\", kept: [] }, issues: [] };\n const kept = flows.promises;\n if (kept.kind === \"unreadable\") {\n // ERROR, and the archive gate's own `NEVER_OVERRIDABLE` keeps `--approve`\n // off it. This is the refusal that stops a flow being copied into\n // `architecture/` and the NEXT reader's `loam validate --all` carrying the\n // failure — including the case the overlay exists for, a hop naming an\n // element the merge does not land. Mechanical, so it is not loam's judgement\n // to override.\n issues.push({\n severity: \"error\",\n code: \"usecase.flow-invalid\",\n subject: featureId,\n // The opening sentence does NOT say whose file is at fault, and that is\n // deliberate: the corpus this reads is the feature's flows PLUS the living\n // `architecture/` documents they are drawn over, so the failing path can\n // be a living one — a landscape that no longer parses, a use case somebody\n // else wrote. Every message carries its own path, so a reader can place\n // it; an opening line that blamed `usecases/` would send them to the wrong\n // file first.\n message:\n `this feature's flows could not be graded against the map its own merge would leave behind, so the archive ` +\n `would land an architecture/ nothing has checked. The corpus is the feature's usecases/ AND the living ` +\n `architecture/ documents they are drawn over, so the fault may be in either — each message names its file. ` +\n `${kept.errors.length} problem(s): ${kept.errors.join(\"; \")}`,\n });\n }\n // And the flows that DID read, graded as `validate --all` grades them once\n // living: every hop against the post-merge map, every `#cap-`/`#req-` tag\n // against the vocabulary and requirements the merge leaves\n // (`core/usecases/grade/feature.ts`). Before this, a hop nothing backs and a\n // `#req-` tag nothing resolves archived clean and turned the fleet red.\n issues.push(...flows.issues);\n\n // The `Realizes:` join, both directions, over documents this walk has already\n // parsed. Skipped entirely when the feature carries no capability delta,\n // which is every feature in a fleet that has not adopted the business axis —\n // and the removal half asks for the living corpus only when something is\n // actually retired, so even an adopting fleet pays the fleet-wide read on the\n // features that earn it.\n if (capabilityDeltas.length > 0) {\n // The three arms travel as three, and flattening two of them to `[]` is\n // the one thing this must not do: `capability.uncovered` says in words that\n // no flow keeps the promise, so handing it an empty list for a corpus loam\n // could not read or could not resolve makes it assert a negative it never\n // evaluated — and gate on it. `claims.ts`'s header states the rule; this is\n // where a caller could break it.\n issues.push(\n ...uncoveredIssues(\n capabilityDeltas,\n serviceDeltas,\n kept.kind === \"read\"\n ? { graded: true, kept: kept.kept }\n : { graded: false, why: kept.kind === \"ungraded\" ? kept.why : kept.errors.join(\"; \") },\n ),\n );\n issues.push(\n ...(await removedRealizedIssues({\n capabilities: capabilityDeltas,\n deltas: serviceDeltas,\n living: () => livingRealizers(docsDir, context),\n })),\n );\n }\n\n // The living flows whose `#req-` tag claims a promise this feature rewrites or\n // retires (`core/usecases/delta/modified.ts`). Asked only when a requirement is\n // MODIFIED or REMOVED, on either corpus, so no other feature reads a flow for it.\n if ([...capabilityDeltas, ...servicePairs].some((doc) => doc.reqs.some((r) => r.kind === \"MODIFIED\" || r.kind === \"REMOVED\"))) {\n const ctx = context ?? new FleetContext();\n issues.push(\n ...(await changedPromiseFlowIssues({\n docsDir,\n capabilities: capabilityDeltas,\n services: servicePairs,\n vocabulary: await ctx.capabilities(docsDir),\n known: new Set(await enumeratedServiceIds(docsDir, ctx)),\n serviceModel: (paths) => ctx.serviceModel(docsDir, paths),\n architecture: () => ctx.architecture(docsDir),\n readRequirements: (path) => ctx.readRequirements(path),\n })),\n );\n }\n\n return issues;\n}\n\n/**\n * Every LIVING service requirements document in the fleet, for the one question\n * that has to ask about services this feature never mentions: does anything out\n * there still realize a capability requirement this feature retires?\n *\n * The same shape and the same cost `openapi.remove-op-consumed` pays through\n * the consumer index (`core/consumers/`) one axis over, and for the same reason — the merge\n * deletes the promise while the `Realizes:` line stays, so the very next\n * `validate --all` reports a breach on a repository whose author was never in\n * this feature. Called behind a thunk (`removedRealizedIssues` invokes it only\n * when something is retired), so a feature that removes nothing never runs it.\n */\nasync function livingRealizers(docsDir: DocsDir, context?: FleetContext): Promise<RealizingDoc[]> {\n const out: RealizingDoc[] = [];\n for (const service of await enumeratedServiceIds(docsDir, context)) {\n const paths = await locateServicePaths(docsDir, service, context);\n for (const axis of SPEC_AXES) {\n const path = paths[axis.key];\n if (!existsSync(path)) continue;\n const reqs =\n context === undefined ? parseRequirements(await readFile(path, \"utf8\")) : await context.readRequirements(path);\n out.push({ service, file: axis.file, reqs });\n }\n }\n return out;\n}\n\n/**\n * One delta document against one living document: the three passes, in the\n * order that makes their messages readable.\n *\n * The order is load-bearing. `deltaDocumentIssues` settles what the delta says\n * about itself, `livingDocumentIssues` settles whether the living text can be\n * selected in at all, and only then does `selectionIssues` compare them — a pin\n * the document pass already refused must not also be reported stale, which\n * would send its author to `loam rebase` for a problem rebase does not fix.\n *\n * The parsed delta requirements come back with the issues because the capability\n * corpus grades them a second way (`capabilityDocIssues`) and re-reading the\n * file to do it would be a second parse of bytes already in hand — and, without\n * a context, a second chance for the two passes to disagree about the document.\n * The LIVING index rides back for the same reason once more: the removal\n * direction of the `Realizes:` join has to resolve a REMOVED spelled by heading\n * into the id it retires, and that id is a fact about the living document.\n */\nasync function gradeDelta(\n scope: DeltaScope,\n livingPath: string,\n reads: DeltaReads,\n): Promise<{ issues: Issue[]; reqs: Requirement[]; living: LivingIndex }> {\n const { claims, context } = reads;\n const raw = context === undefined ? await readFile(scope.specPath, \"utf8\") : await context.readText(scope.specPath);\n const reqs = context === undefined ? parseRequirements(raw) : await context.readRequirements(scope.specPath);\n const living = indexLiving(\n !existsSync(livingPath)\n ? []\n : context === undefined\n ? parseRequirements(await readFile(livingPath, \"utf8\"))\n : await context.readRequirements(livingPath),\n );\n return {\n reqs,\n living,\n issues: [\n ...deltaDocumentIssues(scope, raw, reqs),\n ...livingDocumentIssues(scope, living),\n ...(await selectionIssues(scope, reqs, living, claims)),\n ],\n };\n}\n"]}
@@ -0,0 +1,177 @@
1
+ /**
2
+ * What a requirements document says about ITSELF — graded before anything is
3
+ * compared against another document.
4
+ *
5
+ * Both the delta and the living spec come through here, because the failures are
6
+ * the same class: a heading that nearly matches the delta grammar, an identity
7
+ * declared twice or shared by two requirements, a `Based-On:` nobody can
8
+ * evaluate. Settling them first is what lets `./select.ts` assume the two
9
+ * documents are at least internally answerable — a pin the document pass already
10
+ * refused must not also be reported stale, which would send its author to
11
+ * `loam rebase` for a problem rebase does not fix.
12
+ */
13
+ import { relative } from "node:path";
14
+ import {} from "../vocabulary/issue.js";
15
+ import { sectionHeadings } from "../document/parse.js";
16
+ import { basedOnDeclarations, KIND_RE, REQUIREMENT_DIGEST_LENGTH, REQUIREMENT_DIGEST_RE, requirementIdProblems, } from "../document/spec.js";
17
+ import {} from "./scope.js";
18
+ /**
19
+ * `## <word> Requirement(s)` — the shape an author reaches for. Anything matching
20
+ * this but not the real grammar is a near miss: `## ADDED Requirement` (singular),
21
+ * `## NEW Requirements`, `## ADDED Requirements:`. A bare `## Requirements` is not
22
+ * a near miss — quoting the living state inside a delta is legal.
23
+ */
24
+ const NEAR_SECTION_RE = /^##\s+[A-Za-z]+\s+Requirements?\s*:?\s*$/i;
25
+ /**
26
+ * OpenSpec's fourth delta operation. NEAR_SECTION_RE already catches it, but the
27
+ * generic advice would mislead: a RENAMED body is FROM/TO backtick bullets, not
28
+ * `### Requirement:` headings, so it parses to zero requirements and even the
29
+ * whole-file check below has nothing to count — the heading is the only place to
30
+ * stop it. Rename semantics stay unimplemented (the corpus never uses them); the
31
+ * error says what to write instead.
32
+ */
33
+ const RENAMED_SECTION_RE = /^##\s+RENAMED\s+Requirements?\s*:?\s*$/i;
34
+ // The one non-delta heading whose requirements are SUPPOSED not to merge — a
35
+ // delta quoting the living state for context — is `## Requirements`, matched by
36
+ // the shared isRequirementsHeading (spec.ts): the same definition that fixes
37
+ // archive's rewrite boundary, so "legal to quote" and "where the merge writes"
38
+ // cannot drift apart. Every other heading — `## Behavior`, `## Error Handling`,
39
+ // `## Notes` — leaves its requirements as BASE, which the merge skips, so the
40
+ // author wrote a change that will never land.
41
+ /** Everything wrong with the DELTA document on its own terms. */
42
+ export function deltaDocumentIssues(scope, raw, reqs) {
43
+ const { docsDir, subject, specPath, where } = scope;
44
+ const issues = [];
45
+ for (const heading of sectionHeadings(raw)) {
46
+ if (KIND_RE.test(heading.text) || !NEAR_SECTION_RE.test(heading.text))
47
+ continue;
48
+ issues.push({
49
+ severity: "error",
50
+ code: "delta.unknown-section",
51
+ subject,
52
+ message: RENAMED_SECTION_RE.test(heading.text)
53
+ ? `${where}: '${heading.text}' (line ${heading.line}) is OpenSpec rename syntax, which loam does not merge — carry one stable Requirement-ID through a MODIFIED requirement, or express a legacy rename as a REMOVED requirement plus an ADDED one; otherwise the rename happens to nothing`
54
+ : `${where}: '${heading.text}' (line ${heading.line}) is not a delta section — use '## ADDED Requirements', '## MODIFIED Requirements' or '## REMOVED Requirements', or everything under it merges as nothing`,
55
+ });
56
+ }
57
+ for (const problem of requirementIdProblems(reqs)) {
58
+ if (problem.kind === "invalid") {
59
+ issues.push({
60
+ severity: "error",
61
+ code: "delta.requirement-id-invalid",
62
+ subject,
63
+ message: `${where}: requirement '${problem.requirement}' has invalid Requirement-ID '${problem.value}' — use 1-128 characters matching [A-Za-z][A-Za-z0-9._-]*`,
64
+ });
65
+ }
66
+ else if (problem.kind === "repeated") {
67
+ issues.push({
68
+ severity: "error",
69
+ code: "delta.requirement-id-repeated",
70
+ subject,
71
+ message: `${where}: requirement '${problem.requirement}' declares Requirement-ID ${problem.values.length} times — identity must be declared exactly once`,
72
+ });
73
+ }
74
+ else {
75
+ issues.push({
76
+ severity: "error",
77
+ code: "delta.requirement-id-duplicate",
78
+ subject,
79
+ message: `${where}: Requirement-ID '${problem.id}' is shared by ${problem.requirements.map((name) => `'${name}'`).join(", ")} — one ID may identify only one requirement`,
80
+ });
81
+ }
82
+ }
83
+ // The `Based-On:` pin as a DOCUMENT question, settled before anything is
84
+ // compared against the living spec: a value that is not a digest, or two
85
+ // of them on one requirement, is a pin nobody can evaluate — and a pin
86
+ // that silently protects nothing is worse than no pin at all, because its
87
+ // author believes they are covered. ADDED is refused for the same reason
88
+ // rather than ignored: a requirement with no living version cannot have
89
+ // been written against one, so the line is a misunderstanding today and a
90
+ // digest-shaped lie on the day someone turns it into a MODIFIED.
91
+ for (const r of reqs) {
92
+ const declared = basedOnDeclarations(r);
93
+ if (declared.length > 1) {
94
+ issues.push({
95
+ severity: "error",
96
+ code: "delta.baseline-invalid",
97
+ subject,
98
+ message: `${where}: requirement '${r.name}' declares Based-On ${declared.length} times — a delta is written against exactly one living version`,
99
+ });
100
+ continue;
101
+ }
102
+ const pin = declared[0];
103
+ if (pin === undefined)
104
+ continue;
105
+ if (!REQUIREMENT_DIGEST_RE.test(pin)) {
106
+ issues.push({
107
+ severity: "error",
108
+ code: "delta.baseline-invalid",
109
+ subject,
110
+ message: `${where}: requirement '${r.name}' has invalid Based-On '${pin}' — expected ${REQUIREMENT_DIGEST_LENGTH} lowercase hex characters, as \`loam rebase\` writes them`,
111
+ });
112
+ }
113
+ else if (r.kind === "ADDED") {
114
+ issues.push({
115
+ severity: "error",
116
+ code: "delta.baseline-invalid",
117
+ subject,
118
+ message: `${where}: ADDED requirement '${r.name}' carries Based-On '${pin}', but an added requirement has no living version to be based on — drop the line, or make it MODIFIED`,
119
+ });
120
+ }
121
+ }
122
+ // The whole-file version of the near-miss check, and the one that cannot be
123
+ // dodged: NEAR_SECTION_RE only recognizes single-word misses (`## NEW
124
+ // Requirements`), so `## NEWLY ADDED Requirements` — or requirements under a
125
+ // prose heading, or under no heading at all — still parses everything as BASE
126
+ // and archive merges nothing, silently. Same failure class as the BOM incident
127
+ // (see spec.ts). A file that MIXES delta sections with quoted BASE requirements
128
+ // is legal authoring; a file with requirements and no delta kind anywhere is a
129
+ // delta that would do nothing, which cannot be what its author meant.
130
+ if (reqs.length > 0 && reqs.every((r) => r.kind === "BASE")) {
131
+ const rel = relative(docsDir, specPath).split(/[\\/]/).join("/");
132
+ issues.push({
133
+ severity: "error",
134
+ code: "delta.no-delta-sections",
135
+ subject,
136
+ message: `${subject}: ${rel} contains ${reqs.length} requirement(s) but no '## ADDED|MODIFIED|REMOVED Requirements' section — this delta would merge nothing`,
137
+ });
138
+ }
139
+ return issues;
140
+ }
141
+ /** Everything wrong with the LIVING document that stops a delta selecting in it. */
142
+ export function livingDocumentIssues(scope, living) {
143
+ const { subject, where, livingDoc } = scope;
144
+ const issues = [];
145
+ for (const problem of requirementIdProblems(living.all)) {
146
+ issues.push({
147
+ severity: "error",
148
+ code: "delta.living-requirement-id-invalid",
149
+ subject,
150
+ message: problem.kind === "invalid"
151
+ ? `${where}: the ${livingDoc} requirement '${problem.requirement}' has invalid Requirement-ID '${problem.value}', so this delta cannot select it safely`
152
+ : problem.kind === "repeated"
153
+ ? `${where}: the ${livingDoc} requirement '${problem.requirement}' declares Requirement-ID more than once, so this delta cannot select it safely`
154
+ : `${where}: the ${livingDoc} shares Requirement-ID '${problem.id}' across ${problem.requirements.map((name) => `'${name}'`).join(", ")}, so this delta cannot select one safely`,
155
+ });
156
+ }
157
+ // Two living requirements under one heading make the delta algebra
158
+ // disagree with itself on the SAME input: MODIFIED replaces the first
159
+ // match (findIndex) while REMOVED deletes every match (filter). So one
160
+ // delta edits one of the twins and leaves the other, and the next one
161
+ // deletes both — and neither outcome is what an author reading the
162
+ // living document could have predicted. Gating rather than advisory,
163
+ // because there is no reading of the delta that makes the merge correct;
164
+ // the fix is in the living document, and it is one rename.
165
+ for (const [name, twins] of living.byName) {
166
+ if (twins.length < 2)
167
+ continue;
168
+ issues.push({
169
+ severity: "error",
170
+ code: "delta.living-duplicate-requirement",
171
+ subject,
172
+ message: `${where}: the ${livingDoc} declares ${twins.length} requirements named '${name}' — MODIFIED would rewrite only the first and REMOVED would delete both, so no delta applies to it predictably. Give them distinct names (or distinct Requirement-IDs and headings) first.`,
173
+ });
174
+ }
175
+ return issues;
176
+ }
177
+ //# sourceMappingURL=document.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"document.js","sourceRoot":"","sources":["../../../src/core/delta/document.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * What a requirements document says about ITSELF — graded before anything is\n * compared against another document.\n *\n * Both the delta and the living spec come through here, because the failures are\n * the same class: a heading that nearly matches the delta grammar, an identity\n * declared twice or shared by two requirements, a `Based-On:` nobody can\n * evaluate. Settling them first is what lets `./select.ts` assume the two\n * documents are at least internally answerable — a pin the document pass already\n * refused must not also be reported stale, which would send its author to\n * `loam rebase` for a problem rebase does not fix.\n */\nimport { relative } from \"node:path\";\nimport { type Issue } from \"../vocabulary/issue.js\";\nimport { sectionHeadings } from \"../document/parse.js\";\nimport {\n basedOnDeclarations,\n KIND_RE,\n REQUIREMENT_DIGEST_LENGTH,\n REQUIREMENT_DIGEST_RE,\n requirementIdProblems,\n type Requirement,\n} from \"../document/spec.js\";\nimport { type DeltaScope, type LivingIndex } from \"./scope.js\";\n\n/**\n * `## <word> Requirement(s)` — the shape an author reaches for. Anything matching\n * this but not the real grammar is a near miss: `## ADDED Requirement` (singular),\n * `## NEW Requirements`, `## ADDED Requirements:`. A bare `## Requirements` is not\n * a near miss — quoting the living state inside a delta is legal.\n */\nconst NEAR_SECTION_RE = /^##\\s+[A-Za-z]+\\s+Requirements?\\s*:?\\s*$/i;\n\n/**\n * OpenSpec's fourth delta operation. NEAR_SECTION_RE already catches it, but the\n * generic advice would mislead: a RENAMED body is FROM/TO backtick bullets, not\n * `### Requirement:` headings, so it parses to zero requirements and even the\n * whole-file check below has nothing to count — the heading is the only place to\n * stop it. Rename semantics stay unimplemented (the corpus never uses them); the\n * error says what to write instead.\n */\nconst RENAMED_SECTION_RE = /^##\\s+RENAMED\\s+Requirements?\\s*:?\\s*$/i;\n\n// The one non-delta heading whose requirements are SUPPOSED not to merge — a\n// delta quoting the living state for context — is `## Requirements`, matched by\n// the shared isRequirementsHeading (spec.ts): the same definition that fixes\n// archive's rewrite boundary, so \"legal to quote\" and \"where the merge writes\"\n// cannot drift apart. Every other heading — `## Behavior`, `## Error Handling`,\n// `## Notes` — leaves its requirements as BASE, which the merge skips, so the\n// author wrote a change that will never land.\n\n/** Everything wrong with the DELTA document on its own terms. */\nexport function deltaDocumentIssues(scope: DeltaScope, raw: string, reqs: Requirement[]): Issue[] {\n const { docsDir, subject, specPath, where } = scope;\n const issues: Issue[] = [];\n for (const heading of sectionHeadings(raw)) {\n if (KIND_RE.test(heading.text) || !NEAR_SECTION_RE.test(heading.text)) continue;\n issues.push({\n severity: \"error\",\n code: \"delta.unknown-section\",\n subject,\n message: RENAMED_SECTION_RE.test(heading.text)\n ? `${where}: '${heading.text}' (line ${heading.line}) is OpenSpec rename syntax, which loam does not merge — carry one stable Requirement-ID through a MODIFIED requirement, or express a legacy rename as a REMOVED requirement plus an ADDED one; otherwise the rename happens to nothing`\n : `${where}: '${heading.text}' (line ${heading.line}) is not a delta section — use '## ADDED Requirements', '## MODIFIED Requirements' or '## REMOVED Requirements', or everything under it merges as nothing`,\n });\n }\n\n for (const problem of requirementIdProblems(reqs)) {\n if (problem.kind === \"invalid\") {\n issues.push({\n severity: \"error\",\n code: \"delta.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 } else if (problem.kind === \"repeated\") {\n issues.push({\n severity: \"error\",\n code: \"delta.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 } else {\n issues.push({\n severity: \"error\",\n code: \"delta.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 // The `Based-On:` pin as a DOCUMENT question, settled before anything is\n // compared against the living spec: a value that is not a digest, or two\n // of them on one requirement, is a pin nobody can evaluate — and a pin\n // that silently protects nothing is worse than no pin at all, because its\n // author believes they are covered. ADDED is refused for the same reason\n // rather than ignored: a requirement with no living version cannot have\n // been written against one, so the line is a misunderstanding today and a\n // digest-shaped lie on the day someone turns it into a MODIFIED.\n for (const r of reqs) {\n const declared = basedOnDeclarations(r);\n if (declared.length > 1) {\n issues.push({\n severity: \"error\",\n code: \"delta.baseline-invalid\",\n subject,\n message: `${where}: requirement '${r.name}' declares Based-On ${declared.length} times — a delta is written against exactly one living version`,\n });\n continue;\n }\n const pin = declared[0];\n if (pin === undefined) continue;\n if (!REQUIREMENT_DIGEST_RE.test(pin)) {\n issues.push({\n severity: \"error\",\n code: \"delta.baseline-invalid\",\n subject,\n message: `${where}: requirement '${r.name}' has invalid Based-On '${pin}' — expected ${REQUIREMENT_DIGEST_LENGTH} lowercase hex characters, as \\`loam rebase\\` writes them`,\n });\n } else if (r.kind === \"ADDED\") {\n issues.push({\n severity: \"error\",\n code: \"delta.baseline-invalid\",\n subject,\n message: `${where}: ADDED requirement '${r.name}' carries Based-On '${pin}', but an added requirement has no living version to be based on — drop the line, or make it MODIFIED`,\n });\n }\n }\n\n // The whole-file version of the near-miss check, and the one that cannot be\n // dodged: NEAR_SECTION_RE only recognizes single-word misses (`## NEW\n // Requirements`), so `## NEWLY ADDED Requirements` — or requirements under a\n // prose heading, or under no heading at all — still parses everything as BASE\n // and archive merges nothing, silently. Same failure class as the BOM incident\n // (see spec.ts). A file that MIXES delta sections with quoted BASE requirements\n // is legal authoring; a file with requirements and no delta kind anywhere is a\n // delta that would do nothing, which cannot be what its author meant.\n if (reqs.length > 0 && reqs.every((r) => r.kind === \"BASE\")) {\n const rel = relative(docsDir, specPath).split(/[\\\\/]/).join(\"/\");\n issues.push({\n severity: \"error\",\n code: \"delta.no-delta-sections\",\n subject,\n message: `${subject}: ${rel} contains ${reqs.length} requirement(s) but no '## ADDED|MODIFIED|REMOVED Requirements' section — this delta would merge nothing`,\n });\n }\n return issues;\n}\n\n/** Everything wrong with the LIVING document that stops a delta selecting in it. */\nexport function livingDocumentIssues(scope: DeltaScope, living: LivingIndex): Issue[] {\n const { subject, where, livingDoc } = scope;\n const issues: Issue[] = [];\n for (const problem of requirementIdProblems(living.all)) {\n issues.push({\n severity: \"error\",\n code: \"delta.living-requirement-id-invalid\",\n subject,\n message:\n problem.kind === \"invalid\"\n ? `${where}: the ${livingDoc} requirement '${problem.requirement}' has invalid Requirement-ID '${problem.value}', so this delta cannot select it safely`\n : problem.kind === \"repeated\"\n ? `${where}: the ${livingDoc} requirement '${problem.requirement}' declares Requirement-ID more than once, so this delta cannot select it safely`\n : `${where}: the ${livingDoc} shares Requirement-ID '${problem.id}' across ${problem.requirements.map((name) => `'${name}'`).join(\", \")}, so this delta cannot select one safely`,\n });\n }\n\n // Two living requirements under one heading make the delta algebra\n // disagree with itself on the SAME input: MODIFIED replaces the first\n // match (findIndex) while REMOVED deletes every match (filter). So one\n // delta edits one of the twins and leaves the other, and the next one\n // deletes both — and neither outcome is what an author reading the\n // living document could have predicted. Gating rather than advisory,\n // because there is no reading of the delta that makes the merge correct;\n // the fix is in the living document, and it is one rename.\n for (const [name, twins] of living.byName) {\n if (twins.length < 2) continue;\n issues.push({\n severity: \"error\",\n code: \"delta.living-duplicate-requirement\",\n subject,\n message: `${where}: the ${livingDoc} declares ${twins.length} requirements named '${name}' — MODIFIED would rewrite only the first and REMOVED would delete both, so no delta applies to it predictably. Give them distinct names (or distinct Requirement-IDs and headings) first.`,\n });\n }\n return issues;\n}\n"]}