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

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 (1026) hide show
  1. package/CHANGELOG.md +2548 -86
  2. package/COMPARISON.md +80 -63
  3. package/CONTRIBUTING.md +84 -0
  4. package/MIGRATING-from-OpenSpec.md +213 -54
  5. package/QUICKSTART.md +125 -0
  6. package/README.md +450 -150
  7. package/ROADMAP.md +494 -0
  8. package/SCHEMA.md +2355 -256
  9. package/SECURITY.md +21 -3
  10. package/WORKFLOW.md +701 -0
  11. package/dist/cli.js +113 -19
  12. package/dist/cli.js.map +1 -1
  13. package/dist/commands/adopt/adopt.js +209 -0
  14. package/dist/commands/adopt/adopt.js.map +1 -0
  15. package/dist/commands/adopt/render.js +268 -0
  16. package/dist/commands/adopt/render.js.map +1 -0
  17. package/dist/commands/archive/archive.js +77 -0
  18. package/dist/commands/archive/archive.js.map +1 -0
  19. package/dist/commands/archive/plan/contracts/asyncapi.js +178 -0
  20. package/dist/commands/archive/plan/contracts/asyncapi.js.map +1 -0
  21. package/dist/commands/archive/plan/contracts/openapi.js +159 -0
  22. package/dist/commands/archive/plan/contracts/openapi.js.map +1 -0
  23. package/dist/commands/archive/plan/gate.js +317 -0
  24. package/dist/commands/archive/plan/gate.js.map +1 -0
  25. package/dist/commands/archive/plan/landscape.js +161 -0
  26. package/dist/commands/archive/plan/landscape.js.map +1 -0
  27. package/dist/commands/archive/plan/refusal.js +111 -0
  28. package/dist/commands/archive/plan/refusal.js.map +1 -0
  29. package/dist/commands/archive/plan/specs.js +237 -0
  30. package/dist/commands/archive/plan/specs.js.map +1 -0
  31. package/dist/commands/archive/plan/state.js +27 -0
  32. package/dist/commands/archive/plan/state.js.map +1 -0
  33. package/dist/commands/archive/run.js +251 -0
  34. package/dist/commands/archive/run.js.map +1 -0
  35. package/dist/commands/context/context.js +99 -0
  36. package/dist/commands/context/context.js.map +1 -0
  37. package/dist/commands/context/print.js +283 -0
  38. package/dist/commands/context/print.js.map +1 -0
  39. package/dist/commands/delta/delta.js +279 -0
  40. package/dist/commands/delta/delta.js.map +1 -0
  41. package/dist/commands/delta/print.js +205 -0
  42. package/dist/commands/delta/print.js.map +1 -0
  43. package/dist/commands/dependencies.js +9 -7
  44. package/dist/commands/dependencies.js.map +1 -1
  45. package/dist/commands/diff/diff.js +93 -0
  46. package/dist/commands/diff/diff.js.map +1 -0
  47. package/dist/commands/diff/print.js +38 -0
  48. package/dist/commands/diff/print.js.map +1 -0
  49. package/dist/commands/doctor.js +5 -4
  50. package/dist/commands/doctor.js.map +1 -1
  51. package/dist/commands/explain/explain.js +151 -0
  52. package/dist/commands/explain/explain.js.map +1 -0
  53. package/dist/commands/explore.js +29 -24
  54. package/dist/commands/explore.js.map +1 -1
  55. package/dist/commands/gate/gate.js +115 -0
  56. package/dist/commands/gate/gate.js.map +1 -0
  57. package/dist/commands/gate/print.js +54 -0
  58. package/dist/commands/gate/print.js.map +1 -0
  59. package/dist/commands/gherkin/commit.js +146 -0
  60. package/dist/commands/gherkin/commit.js.map +1 -0
  61. package/dist/commands/gherkin/gherkin.js +246 -0
  62. package/dist/commands/gherkin/gherkin.js.map +1 -0
  63. package/dist/commands/gherkin/reconcile.js +149 -0
  64. package/dist/commands/gherkin/reconcile.js.map +1 -0
  65. package/dist/commands/gherkin/render.js +77 -0
  66. package/dist/commands/gherkin/render.js.map +1 -0
  67. package/dist/commands/init/example.js +204 -0
  68. package/dist/commands/init/example.js.map +1 -0
  69. package/dist/commands/init/first-hour.js +28 -0
  70. package/dist/commands/init/first-hour.js.map +1 -0
  71. package/dist/commands/{init.js → init/init.js} +146 -71
  72. package/dist/commands/init/init.js.map +1 -0
  73. package/dist/commands/init/mcp.js +131 -0
  74. package/dist/commands/init/mcp.js.map +1 -0
  75. package/dist/commands/init/options.js +78 -0
  76. package/dist/commands/init/options.js.map +1 -0
  77. package/dist/commands/instructions.js +72 -14
  78. package/dist/commands/instructions.js.map +1 -1
  79. package/dist/commands/list/campaign/campaign.js +65 -0
  80. package/dist/commands/list/campaign/campaign.js.map +1 -0
  81. package/dist/commands/list/campaign/owners.js +65 -0
  82. package/dist/commands/list/campaign/owners.js.map +1 -0
  83. package/dist/commands/list/json.js +157 -0
  84. package/dist/commands/list/json.js.map +1 -0
  85. package/dist/commands/list/list.js +343 -0
  86. package/dist/commands/list/list.js.map +1 -0
  87. package/dist/commands/list/print.js +301 -0
  88. package/dist/commands/list/print.js.map +1 -0
  89. package/dist/commands/list/review.js +120 -0
  90. package/dist/commands/list/review.js.map +1 -0
  91. package/dist/commands/list/views.js +105 -0
  92. package/dist/commands/list/views.js.map +1 -0
  93. package/dist/commands/mcp/dispatch.js +183 -0
  94. package/dist/commands/mcp/dispatch.js.map +1 -0
  95. package/dist/commands/mcp/mcp.js +34 -0
  96. package/dist/commands/mcp/mcp.js.map +1 -0
  97. package/dist/commands/mcp/serve.js +55 -0
  98. package/dist/commands/mcp/serve.js.map +1 -0
  99. package/dist/commands/migrate-openspec/materialize/active.js +170 -0
  100. package/dist/commands/migrate-openspec/materialize/active.js.map +1 -0
  101. package/dist/commands/migrate-openspec/materialize/feature.js +41 -0
  102. package/dist/commands/migrate-openspec/materialize/feature.js.map +1 -0
  103. package/dist/commands/migrate-openspec/materialize/living.js +62 -0
  104. package/dist/commands/migrate-openspec/materialize/living.js.map +1 -0
  105. package/dist/commands/migrate-openspec/materialize/stage.js +142 -0
  106. package/dist/commands/migrate-openspec/materialize/stage.js.map +1 -0
  107. package/dist/commands/migrate-openspec/materialize/target.js +219 -0
  108. package/dist/commands/migrate-openspec/materialize/target.js.map +1 -0
  109. package/dist/commands/migrate-openspec/migrate-openspec.js +142 -0
  110. package/dist/commands/migrate-openspec/migrate-openspec.js.map +1 -0
  111. package/dist/commands/migrate-openspec/openspec/decisions.js +91 -0
  112. package/dist/commands/migrate-openspec/openspec/decisions.js.map +1 -0
  113. package/dist/commands/migrate-openspec/openspec/error.js +19 -0
  114. package/dist/commands/migrate-openspec/openspec/error.js.map +1 -0
  115. package/dist/commands/migrate-openspec/openspec/mapping.js +170 -0
  116. package/dist/commands/migrate-openspec/openspec/mapping.js.map +1 -0
  117. package/dist/commands/migrate-openspec/openspec/paths.js +43 -0
  118. package/dist/commands/migrate-openspec/openspec/paths.js.map +1 -0
  119. package/dist/commands/migrate-openspec/openspec/read.js +49 -0
  120. package/dist/commands/migrate-openspec/openspec/read.js.map +1 -0
  121. package/dist/commands/migrate-openspec/print.js +89 -0
  122. package/dist/commands/migrate-openspec/print.js.map +1 -0
  123. package/dist/commands/new/commit.js +76 -0
  124. package/dist/commands/new/commit.js.map +1 -0
  125. package/dist/commands/new/new.js +283 -0
  126. package/dist/commands/new/new.js.map +1 -0
  127. package/dist/commands/new/templates.js +355 -0
  128. package/dist/commands/new/templates.js.map +1 -0
  129. package/dist/commands/open.js +203 -0
  130. package/dist/commands/open.js.map +1 -0
  131. package/dist/commands/policy/format.js +152 -0
  132. package/dist/commands/policy/format.js.map +1 -0
  133. package/dist/commands/{docs-repo-gate.js → policy/gate.js} +11 -11
  134. package/dist/commands/policy/gate.js.map +1 -0
  135. package/dist/commands/rebase/edit.js +106 -0
  136. package/dist/commands/rebase/edit.js.map +1 -0
  137. package/dist/commands/rebase/living.js +185 -0
  138. package/dist/commands/rebase/living.js.map +1 -0
  139. package/dist/commands/rebase/plan.js +245 -0
  140. package/dist/commands/rebase/plan.js.map +1 -0
  141. package/dist/commands/rebase/rebase.js +275 -0
  142. package/dist/commands/rebase/rebase.js.map +1 -0
  143. package/dist/commands/seed/commit.js +192 -0
  144. package/dist/commands/seed/commit.js.map +1 -0
  145. package/dist/commands/seed/plan.js +133 -0
  146. package/dist/commands/seed/plan.js.map +1 -0
  147. package/dist/commands/seed/seed.js +172 -0
  148. package/dist/commands/seed/seed.js.map +1 -0
  149. package/dist/commands/show/feature.js +178 -0
  150. package/dist/commands/show/feature.js.map +1 -0
  151. package/dist/commands/show/marks.js +24 -0
  152. package/dist/commands/show/marks.js.map +1 -0
  153. package/dist/commands/{show.js → show/service.js} +63 -152
  154. package/dist/commands/show/service.js.map +1 -0
  155. package/dist/commands/show/show.js +77 -0
  156. package/dist/commands/show/show.js.map +1 -0
  157. package/dist/commands/status/json.js +45 -0
  158. package/dist/commands/status/json.js.map +1 -0
  159. package/dist/commands/status/print.js +157 -0
  160. package/dist/commands/status/print.js.map +1 -0
  161. package/dist/commands/status/status.js +119 -0
  162. package/dist/commands/status/status.js.map +1 -0
  163. package/dist/commands/steps/steps.js +189 -0
  164. package/dist/commands/steps/steps.js.map +1 -0
  165. package/dist/commands/subsystem/edit.js +192 -0
  166. package/dist/commands/subsystem/edit.js.map +1 -0
  167. package/dist/commands/subsystem/move.js +265 -0
  168. package/dist/commands/subsystem/move.js.map +1 -0
  169. package/dist/commands/subsystem/query.js +115 -0
  170. package/dist/commands/subsystem/query.js.map +1 -0
  171. package/dist/commands/subsystem/subsystem.js +101 -0
  172. package/dist/commands/subsystem/subsystem.js.map +1 -0
  173. package/dist/commands/subsystem/sync.js +103 -0
  174. package/dist/commands/subsystem/sync.js.map +1 -0
  175. package/dist/commands/subsystem/txn/txn.js +94 -0
  176. package/dist/commands/subsystem/txn/txn.js.map +1 -0
  177. package/dist/commands/subsystem/txn/views.js +70 -0
  178. package/dist/commands/subsystem/txn/views.js.map +1 -0
  179. package/dist/commands/unarchive/manifest.js +160 -0
  180. package/dist/commands/unarchive/manifest.js.map +1 -0
  181. package/dist/commands/{unarchive.js → unarchive/restore.js} +47 -160
  182. package/dist/commands/unarchive/restore.js.map +1 -0
  183. package/dist/commands/unarchive/unarchive.js +67 -0
  184. package/dist/commands/unarchive/unarchive.js.map +1 -0
  185. package/dist/commands/validate/arch-coverage.js +194 -0
  186. package/dist/commands/validate/arch-coverage.js.map +1 -0
  187. package/dist/commands/validate/checks/fleet-shape.js +296 -0
  188. package/dist/commands/validate/checks/fleet-shape.js.map +1 -0
  189. package/dist/commands/validate/checks/health-deps.js +55 -0
  190. package/dist/commands/validate/checks/health-deps.js.map +1 -0
  191. package/dist/commands/validate/checks/requirements.js +254 -0
  192. package/dist/commands/validate/checks/requirements.js.map +1 -0
  193. package/dist/commands/validate/checks/sources.js +76 -0
  194. package/dist/commands/validate/checks/sources.js.map +1 -0
  195. package/dist/commands/validate/checks/vocabulary.js +31 -0
  196. package/dist/commands/validate/checks/vocabulary.js.map +1 -0
  197. package/dist/commands/validate/feature.js +216 -0
  198. package/dist/commands/validate/feature.js.map +1 -0
  199. package/dist/commands/validate/fleet/census.js +69 -0
  200. package/dist/commands/validate/fleet/census.js.map +1 -0
  201. package/dist/commands/validate/fleet/kind-tags.js +39 -0
  202. package/dist/commands/validate/fleet/kind-tags.js.map +1 -0
  203. package/dist/commands/validate/fleet/landscape.js +353 -0
  204. package/dist/commands/validate/fleet/landscape.js.map +1 -0
  205. package/dist/commands/validate/fleet/load.js +52 -0
  206. package/dist/commands/validate/fleet/load.js.map +1 -0
  207. package/dist/commands/validate/fleet/obligations.js +236 -0
  208. package/dist/commands/validate/fleet/obligations.js.map +1 -0
  209. package/dist/commands/validate/fleet/scorecard/adoption.js +102 -0
  210. package/dist/commands/validate/fleet/scorecard/adoption.js.map +1 -0
  211. package/dist/commands/validate/fleet/scorecard/contracts.js +98 -0
  212. package/dist/commands/validate/fleet/scorecard/contracts.js.map +1 -0
  213. package/dist/commands/validate/fleet/scorecard/print.js +63 -0
  214. package/dist/commands/validate/fleet/scorecard/print.js.map +1 -0
  215. package/dist/commands/validate/fleet/scorecard/scorecard.js +156 -0
  216. package/dist/commands/validate/fleet/scorecard/scorecard.js.map +1 -0
  217. package/dist/commands/validate/fleet/usecases/capability-tag.js +94 -0
  218. package/dist/commands/validate/fleet/usecases/capability-tag.js.map +1 -0
  219. package/dist/commands/validate/fleet/usecases/place.js +13 -0
  220. package/dist/commands/validate/fleet/usecases/place.js.map +1 -0
  221. package/dist/commands/validate/fleet/usecases/requirement-tag.js +95 -0
  222. package/dist/commands/validate/fleet/usecases/requirement-tag.js.map +1 -0
  223. package/dist/commands/validate/fleet/usecases/steps.js +197 -0
  224. package/dist/commands/validate/fleet/usecases/steps.js.map +1 -0
  225. package/dist/commands/validate/fleet/usecases/usecases.js +99 -0
  226. package/dist/commands/validate/fleet/usecases/usecases.js.map +1 -0
  227. package/dist/commands/validate/fleet/views/ids.js +40 -0
  228. package/dist/commands/validate/fleet/views/ids.js.map +1 -0
  229. package/dist/commands/validate/fleet/views/stale.js +59 -0
  230. package/dist/commands/validate/fleet/views/stale.js.map +1 -0
  231. package/dist/commands/validate/links/corpus.js +92 -0
  232. package/dist/commands/validate/links/corpus.js.map +1 -0
  233. package/dist/commands/validate/links/glossary.js +75 -0
  234. package/dist/commands/validate/links/glossary.js.map +1 -0
  235. package/dist/commands/validate/report.js +269 -0
  236. package/dist/commands/validate/report.js.map +1 -0
  237. package/dist/commands/validate/service/api.js +338 -0
  238. package/dist/commands/validate/service/api.js.map +1 -0
  239. package/dist/commands/validate/service/events/events.js +219 -0
  240. package/dist/commands/validate/service/events/events.js.map +1 -0
  241. package/dist/commands/validate/service/events/message-producers.js +77 -0
  242. package/dist/commands/validate/service/events/message-producers.js.map +1 -0
  243. package/dist/commands/validate/service/evidence-pins.js +131 -0
  244. package/dist/commands/validate/service/evidence-pins.js.map +1 -0
  245. package/dist/commands/validate/service/service.js +250 -0
  246. package/dist/commands/validate/service/service.js.map +1 -0
  247. package/dist/commands/validate/service/specs.js +219 -0
  248. package/dist/commands/validate/service/specs.js.map +1 -0
  249. package/dist/commands/validate/service/spine.js +113 -0
  250. package/dist/commands/validate/service/spine.js.map +1 -0
  251. package/dist/commands/validate/validate.js +338 -0
  252. package/dist/commands/validate/validate.js.map +1 -0
  253. package/dist/commands/verify/cross/diff.js +182 -0
  254. package/dist/commands/verify/cross/diff.js.map +1 -0
  255. package/dist/commands/verify/evidence/contract.js +32 -0
  256. package/dist/commands/verify/evidence/contract.js.map +1 -0
  257. package/dist/commands/verify/evidence/pins.js +52 -0
  258. package/dist/commands/verify/evidence/pins.js.map +1 -0
  259. package/dist/commands/verify/evidence/read.js +72 -0
  260. package/dist/commands/verify/evidence/read.js.map +1 -0
  261. package/dist/commands/verify/frozen.js +241 -0
  262. package/dist/commands/verify/frozen.js.map +1 -0
  263. package/dist/commands/verify/record.js +226 -0
  264. package/dist/commands/verify/record.js.map +1 -0
  265. package/dist/commands/verify/report.js +223 -0
  266. package/dist/commands/verify/report.js.map +1 -0
  267. package/dist/commands/verify/results.js +246 -0
  268. package/dist/commands/verify/results.js.map +1 -0
  269. package/dist/commands/verify/verify.js +217 -0
  270. package/dist/commands/verify/verify.js.map +1 -0
  271. package/dist/commands/vouch/contract.js +11 -0
  272. package/dist/commands/vouch/contract.js.map +1 -0
  273. package/dist/commands/vouch/pack/contract.js +2 -0
  274. package/dist/commands/vouch/pack/contract.js.map +1 -0
  275. package/dist/commands/vouch/pack/pack.js +266 -0
  276. package/dist/commands/vouch/pack/pack.js.map +1 -0
  277. package/dist/commands/vouch/pack/print.js +271 -0
  278. package/dist/commands/vouch/pack/print.js.map +1 -0
  279. package/dist/commands/vouch/pack/sections.js +142 -0
  280. package/dist/commands/vouch/pack/sections.js.map +1 -0
  281. package/dist/commands/vouch/prompt/confirm.js +46 -0
  282. package/dist/commands/vouch/prompt/confirm.js.map +1 -0
  283. package/dist/commands/vouch/report.js +101 -0
  284. package/dist/commands/vouch/report.js.map +1 -0
  285. package/dist/commands/vouch/run.js +285 -0
  286. package/dist/commands/vouch/run.js.map +1 -0
  287. package/dist/commands/vouch/sample/plan.js +125 -0
  288. package/dist/commands/vouch/sample/plan.js.map +1 -0
  289. package/dist/commands/vouch/sample/print.js +109 -0
  290. package/dist/commands/vouch/sample/print.js.map +1 -0
  291. package/dist/commands/vouch/vet/verify.js +123 -0
  292. package/dist/commands/vouch/vet/verify.js.map +1 -0
  293. package/dist/commands/vouch/vouch.js +176 -0
  294. package/dist/commands/vouch/vouch.js.map +1 -0
  295. package/dist/core/agent/agents-md/artifacts.js +220 -0
  296. package/dist/core/agent/agents-md/artifacts.js.map +1 -0
  297. package/dist/core/agent/agents-md/command-map.js +324 -0
  298. package/dist/core/agent/agents-md/command-map.js.map +1 -0
  299. package/dist/core/agent/agents-md/cycle.js +165 -0
  300. package/dist/core/agent/agents-md/cycle.js.map +1 -0
  301. package/dist/core/agent/agents-md/map/explain.js +34 -0
  302. package/dist/core/agent/agents-md/map/explain.js.map +1 -0
  303. package/dist/core/agent/agents-md/map/lenses/context.js +41 -0
  304. package/dist/core/agent/agents-md/map/lenses/context.js.map +1 -0
  305. package/dist/core/agent/agents-md/map/lenses/diff.js +46 -0
  306. package/dist/core/agent/agents-md/map/lenses/diff.js.map +1 -0
  307. package/dist/core/agent/agents-md/map/lenses/gate.js +57 -0
  308. package/dist/core/agent/agents-md/map/lenses/gate.js.map +1 -0
  309. package/dist/core/agent/agents-md/map/mcp.js +41 -0
  310. package/dist/core/agent/agents-md/map/mcp.js.map +1 -0
  311. package/dist/core/agent/agents-md/map/status.js +62 -0
  312. package/dist/core/agent/agents-md/map/status.js.map +1 -0
  313. package/dist/core/agent/agents-md/map/subsystem.js +32 -0
  314. package/dist/core/agent/agents-md/map/subsystem.js.map +1 -0
  315. package/dist/core/agent/agents-md/map/usecases.js +60 -0
  316. package/dist/core/agent/agents-md/map/usecases.js.map +1 -0
  317. package/dist/core/agent/agents-md/refusals.js +246 -0
  318. package/dist/core/agent/agents-md/refusals.js.map +1 -0
  319. package/dist/core/agent/agents-md/shipped/archive-gate.js +98 -0
  320. package/dist/core/agent/agents-md/shipped/archive-gate.js.map +1 -0
  321. package/dist/core/agent/agents-md/spine.js +40 -0
  322. package/dist/core/agent/agents-md/spine.js.map +1 -0
  323. package/dist/core/agent/agents-md.js +170 -0
  324. package/dist/core/agent/agents-md.js.map +1 -0
  325. package/dist/core/{agents-stamp.js → agent/agents-stamp.js} +50 -0
  326. package/dist/core/agent/agents-stamp.js.map +1 -0
  327. package/dist/core/agent/contract.js +2 -0
  328. package/dist/core/agent/contract.js.map +1 -0
  329. package/dist/core/agent/protocol.js +193 -0
  330. package/dist/core/agent/protocol.js.map +1 -0
  331. package/dist/core/agent/scaffold.js +259 -0
  332. package/dist/core/agent/scaffold.js.map +1 -0
  333. package/dist/core/agent/support/report.js +103 -0
  334. package/dist/core/agent/support/report.js.map +1 -0
  335. package/dist/core/agent/tools/dialects.js +150 -0
  336. package/dist/core/agent/tools/dialects.js.map +1 -0
  337. package/dist/core/agent/tools/registry.js +228 -0
  338. package/dist/core/agent/tools/registry.js.map +1 -0
  339. package/dist/core/agent/workflows/adopt.js +133 -0
  340. package/dist/core/agent/workflows/adopt.js.map +1 -0
  341. package/dist/core/agent/workflows/check.js +334 -0
  342. package/dist/core/agent/workflows/check.js.map +1 -0
  343. package/dist/core/agent/workflows/closing.js +262 -0
  344. package/dist/core/agent/workflows/closing.js.map +1 -0
  345. package/dist/core/agent/workflows/feature.js +105 -0
  346. package/dist/core/agent/workflows/feature.js.map +1 -0
  347. package/dist/core/agent/workflows/implement.js +105 -0
  348. package/dist/core/agent/workflows/implement.js.map +1 -0
  349. package/dist/core/agent/workflows/reference/authoring.js +209 -0
  350. package/dist/core/agent/workflows/reference/authoring.js.map +1 -0
  351. package/dist/core/agent/workflows/reference/codes.js +65 -0
  352. package/dist/core/agent/workflows/reference/codes.js.map +1 -0
  353. package/dist/core/agent/workflows/reference/done-check.js +188 -0
  354. package/dist/core/agent/workflows/reference/done-check.js.map +1 -0
  355. package/dist/core/agent/workflows/reference/reference.js +16 -0
  356. package/dist/core/agent/workflows/reference/reference.js.map +1 -0
  357. package/dist/core/agent/workflows/reference/spine.js +297 -0
  358. package/dist/core/agent/workflows/reference/spine.js.map +1 -0
  359. package/dist/core/asyncapi/baseline/plan.js +110 -0
  360. package/dist/core/asyncapi/baseline/plan.js.map +1 -0
  361. package/dist/core/asyncapi/baseline/surfaces.js +54 -0
  362. package/dist/core/asyncapi/baseline/surfaces.js.map +1 -0
  363. package/dist/core/asyncapi/depth.js +164 -0
  364. package/dist/core/asyncapi/depth.js.map +1 -0
  365. package/dist/core/asyncapi/digest.js +141 -0
  366. package/dist/core/asyncapi/digest.js.map +1 -0
  367. package/dist/core/asyncapi/merge/components.js +91 -0
  368. package/dist/core/asyncapi/merge/components.js.map +1 -0
  369. package/dist/core/asyncapi/merge/error.js +33 -0
  370. package/dist/core/asyncapi/merge/error.js.map +1 -0
  371. package/dist/core/asyncapi/merge/markers.js +308 -0
  372. package/dist/core/asyncapi/merge/markers.js.map +1 -0
  373. package/dist/core/asyncapi/merge/merge.js +215 -0
  374. package/dist/core/asyncapi/merge/merge.js.map +1 -0
  375. package/dist/core/asyncapi/merge/pin.js +107 -0
  376. package/dist/core/asyncapi/merge/pin.js.map +1 -0
  377. package/dist/core/asyncapi/model.js +11 -0
  378. package/dist/core/asyncapi/model.js.map +1 -0
  379. package/dist/core/asyncapi/producers.js +50 -0
  380. package/dist/core/asyncapi/producers.js.map +1 -0
  381. package/dist/core/{asyncapi.js → asyncapi/read.js} +95 -109
  382. package/dist/core/asyncapi/read.js.map +1 -0
  383. package/dist/core/brief/brief.js +225 -0
  384. package/dist/core/brief/brief.js.map +1 -0
  385. package/dist/core/brief/checks.js +250 -0
  386. package/dist/core/brief/checks.js.map +1 -0
  387. package/dist/core/brief/landscape.js +194 -0
  388. package/dist/core/brief/landscape.js.map +1 -0
  389. package/dist/core/brief/targets.js +226 -0
  390. package/dist/core/brief/targets.js.map +1 -0
  391. package/dist/core/brief/unchecked.js +47 -0
  392. package/dist/core/brief/unchecked.js.map +1 -0
  393. package/dist/core/c4/arch.js +282 -0
  394. package/dist/core/c4/arch.js.map +1 -0
  395. package/dist/core/c4/likec4.js +88 -0
  396. package/dist/core/c4/likec4.js.map +1 -0
  397. package/dist/core/c4/parsed/dynamic-views.js +132 -0
  398. package/dist/core/c4/parsed/dynamic-views.js.map +1 -0
  399. package/dist/core/c4/parsed/specification.js +78 -0
  400. package/dist/core/c4/parsed/specification.js.map +1 -0
  401. package/dist/core/c4/parsed/values.js +57 -0
  402. package/dist/core/c4/parsed/values.js.map +1 -0
  403. package/dist/core/c4/parsed/view-ids.js +75 -0
  404. package/dist/core/c4/parsed/view-ids.js.map +1 -0
  405. package/dist/core/c4/project/architecture.js +45 -0
  406. package/dist/core/c4/project/architecture.js.map +1 -0
  407. package/dist/core/c4/project/documents.js +58 -0
  408. package/dist/core/c4/project/documents.js.map +1 -0
  409. package/dist/core/c4/project/load.js +183 -0
  410. package/dist/core/c4/project/load.js.map +1 -0
  411. package/dist/core/c4/resolve/service.js +113 -0
  412. package/dist/core/c4/resolve/service.js.map +1 -0
  413. package/dist/core/c4/seed/fleet-file.js +201 -0
  414. package/dist/core/c4/seed/fleet-file.js.map +1 -0
  415. package/dist/core/c4/seed/items.js +91 -0
  416. package/dist/core/c4/seed/items.js.map +1 -0
  417. package/dist/core/c4/seed/stamp.js +48 -0
  418. package/dist/core/c4/seed/stamp.js.map +1 -0
  419. package/dist/core/c4/seed/template.js +109 -0
  420. package/dist/core/c4/seed/template.js.map +1 -0
  421. package/dist/core/c4/source-mask.js +82 -0
  422. package/dist/core/c4/source-mask.js.map +1 -0
  423. package/dist/core/c4/source-scan.js +227 -0
  424. package/dist/core/c4/source-scan.js.map +1 -0
  425. package/dist/core/c4/splice/authored-source.js +101 -0
  426. package/dist/core/c4/splice/authored-source.js.map +1 -0
  427. package/dist/core/c4/splice/contract.js +10 -0
  428. package/dist/core/c4/splice/contract.js.map +1 -0
  429. package/dist/core/c4/splice/delta-blocks.js +126 -0
  430. package/dist/core/c4/splice/delta-blocks.js.map +1 -0
  431. package/dist/core/c4/splice/identity/edges.js +36 -0
  432. package/dist/core/c4/splice/identity/edges.js.map +1 -0
  433. package/dist/core/c4/splice/landscape-merge.js +269 -0
  434. package/dist/core/c4/splice/landscape-merge.js.map +1 -0
  435. package/dist/core/c4/splice/placement.js +194 -0
  436. package/dist/core/c4/splice/placement.js.map +1 -0
  437. package/dist/core/c4/workspace.js +172 -0
  438. package/dist/core/c4/workspace.js.map +1 -0
  439. package/dist/core/capabilities/authoring/notes.js +141 -0
  440. package/dist/core/capabilities/authoring/notes.js.map +1 -0
  441. package/dist/core/capabilities/capabilities.js +124 -0
  442. package/dist/core/capabilities/capabilities.js.map +1 -0
  443. package/dist/core/capabilities/delta/doc.js +50 -0
  444. package/dist/core/capabilities/delta/doc.js.map +1 -0
  445. package/dist/core/capabilities/delta/overlay.js +129 -0
  446. package/dist/core/capabilities/delta/overlay.js.map +1 -0
  447. package/dist/core/capabilities/delta/summary.js +57 -0
  448. package/dist/core/capabilities/delta/summary.js.map +1 -0
  449. package/dist/core/capabilities/delta/tree.js +43 -0
  450. package/dist/core/capabilities/delta/tree.js.map +1 -0
  451. package/dist/core/capabilities/delta/uncovered.js +222 -0
  452. package/dist/core/capabilities/delta/uncovered.js.map +1 -0
  453. package/dist/core/capabilities/findings.js +342 -0
  454. package/dist/core/capabilities/findings.js.map +1 -0
  455. package/dist/core/capabilities/realizes/findings.js +181 -0
  456. package/dist/core/capabilities/realizes/findings.js.map +1 -0
  457. package/dist/core/capabilities/realizes/join.js +143 -0
  458. package/dist/core/capabilities/realizes/join.js.map +1 -0
  459. package/dist/core/capabilities/rollup.js +199 -0
  460. package/dist/core/capabilities/rollup.js.map +1 -0
  461. package/dist/core/capabilities/tree.js +126 -0
  462. package/dist/core/capabilities/tree.js.map +1 -0
  463. package/dist/core/capabilities/usecase-join.js +277 -0
  464. package/dist/core/capabilities/usecase-join.js.map +1 -0
  465. package/dist/core/coherence/authoring/scaffold.js +177 -0
  466. package/dist/core/coherence/authoring/scaffold.js.map +1 -0
  467. package/dist/core/coherence/authoring/sentinels.js +74 -0
  468. package/dist/core/coherence/authoring/sentinels.js.map +1 -0
  469. package/dist/core/coherence/coherence.js +251 -0
  470. package/dist/core/coherence/coherence.js.map +1 -0
  471. package/dist/core/coherence/declared.js +269 -0
  472. package/dist/core/coherence/declared.js.map +1 -0
  473. package/dist/core/coherence/events/declared.js +206 -0
  474. package/dist/core/coherence/events/declared.js.map +1 -0
  475. package/dist/core/coherence/events/events.js +204 -0
  476. package/dist/core/coherence/events/events.js.map +1 -0
  477. package/dist/core/coherence/events/grades.js +166 -0
  478. package/dist/core/coherence/events/grades.js.map +1 -0
  479. package/dist/core/coherence/events/lookups.js +122 -0
  480. package/dist/core/coherence/events/lookups.js.map +1 -0
  481. package/dist/core/coherence/events/merged.js +40 -0
  482. package/dist/core/coherence/events/merged.js.map +1 -0
  483. package/dist/core/coherence/living.js +198 -0
  484. package/dist/core/coherence/living.js.map +1 -0
  485. package/dist/core/coherence/lookups.js +155 -0
  486. package/dist/core/coherence/lookups.js.map +1 -0
  487. package/dist/core/coherence/pending.js +39 -0
  488. package/dist/core/coherence/pending.js.map +1 -0
  489. package/dist/core/conflict-markers.js +60 -0
  490. package/dist/core/conflict-markers.js.map +1 -0
  491. package/dist/core/delta/claims.js +73 -0
  492. package/dist/core/delta/claims.js.map +1 -0
  493. package/dist/core/delta/delta.js +296 -0
  494. package/dist/core/delta/delta.js.map +1 -0
  495. package/dist/core/delta/document.js +177 -0
  496. package/dist/core/delta/document.js.map +1 -0
  497. package/dist/core/delta/scope.js +48 -0
  498. package/dist/core/delta/scope.js.map +1 -0
  499. package/dist/core/delta/select.js +237 -0
  500. package/dist/core/delta/select.js.map +1 -0
  501. package/dist/core/dependencies/dependencies.js +141 -0
  502. package/dist/core/dependencies/dependencies.js.map +1 -0
  503. package/dist/core/dependencies/facts.js +165 -0
  504. package/dist/core/dependencies/facts.js.map +1 -0
  505. package/dist/core/dependencies/fanin.js +88 -0
  506. package/dist/core/dependencies/fanin.js.map +1 -0
  507. package/dist/core/dependencies/graph.js +106 -0
  508. package/dist/core/dependencies/graph.js.map +1 -0
  509. package/dist/core/diff/base-git.js +148 -0
  510. package/dist/core/diff/base-git.js.map +1 -0
  511. package/dist/core/diff/base-state.js +209 -0
  512. package/dist/core/diff/base-state.js.map +1 -0
  513. package/dist/core/diff/current-state.js +96 -0
  514. package/dist/core/diff/current-state.js.map +1 -0
  515. package/dist/core/diff/scope/changed-paths.js +188 -0
  516. package/dist/core/diff/scope/changed-paths.js.map +1 -0
  517. package/dist/core/diff/semantic.js +243 -0
  518. package/dist/core/diff/semantic.js.map +1 -0
  519. package/dist/core/diff/victims.js +247 -0
  520. package/dist/core/diff/victims.js.map +1 -0
  521. package/dist/core/docs.js +7 -64
  522. package/dist/core/docs.js.map +1 -1
  523. package/dist/core/doctor/agents.js +222 -0
  524. package/dist/core/doctor/agents.js.map +1 -0
  525. package/dist/core/doctor/config.js +135 -0
  526. package/dist/core/doctor/config.js.map +1 -0
  527. package/dist/core/doctor/doctor.js +275 -0
  528. package/dist/core/doctor/doctor.js.map +1 -0
  529. package/dist/core/doctor/report.js +13 -0
  530. package/dist/core/doctor/report.js.map +1 -0
  531. package/dist/core/doctor/residue.js +110 -0
  532. package/dist/core/doctor/residue.js.map +1 -0
  533. package/dist/core/document/apply.js +77 -0
  534. package/dist/core/document/apply.js.map +1 -0
  535. package/dist/core/{frontmatter.js → document/frontmatter.js} +48 -2
  536. package/dist/core/document/frontmatter.js.map +1 -0
  537. package/dist/core/document/grammar/directives.js +143 -0
  538. package/dist/core/document/grammar/directives.js.map +1 -0
  539. package/dist/core/document/parse.js +263 -0
  540. package/dist/core/document/parse.js.map +1 -0
  541. package/dist/core/document/scenarios.js +221 -0
  542. package/dist/core/document/scenarios.js.map +1 -0
  543. package/dist/core/document/spec.js +241 -0
  544. package/dist/core/document/spec.js.map +1 -0
  545. package/dist/core/{config.js → envelope/config.js} +79 -18
  546. package/dist/core/envelope/config.js.map +1 -0
  547. package/dist/core/envelope/json.js +175 -0
  548. package/dist/core/envelope/json.js.map +1 -0
  549. package/dist/core/{version.js → envelope/version.js} +3 -3
  550. package/dist/core/envelope/version.js.map +1 -0
  551. package/dist/core/explain/families.js +175 -0
  552. package/dist/core/explain/families.js.map +1 -0
  553. package/dist/core/explain/fix-tables.js +178 -0
  554. package/dist/core/explain/fix-tables.js.map +1 -0
  555. package/dist/core/explain/lookup.js +181 -0
  556. package/dist/core/explain/lookup.js.map +1 -0
  557. package/dist/core/explain/refusals.js +49 -0
  558. package/dist/core/explain/refusals.js.map +1 -0
  559. package/dist/core/explain/terms.js +144 -0
  560. package/dist/core/explain/terms.js.map +1 -0
  561. package/dist/core/explore/describe.js +105 -0
  562. package/dist/core/explore/describe.js.map +1 -0
  563. package/dist/core/{explore.js → explore/explore.js} +50 -101
  564. package/dist/core/explore/explore.js.map +1 -0
  565. package/dist/core/fleet-context.js +120 -78
  566. package/dist/core/fleet-context.js.map +1 -1
  567. package/dist/core/gate/checks.js +201 -0
  568. package/dist/core/gate/checks.js.map +1 -0
  569. package/dist/core/gate/partners.js +205 -0
  570. package/dist/core/gate/partners.js.map +1 -0
  571. package/dist/core/gate/report.js +47 -0
  572. package/dist/core/gate/report.js.map +1 -0
  573. package/dist/core/gate/verification.js +113 -0
  574. package/dist/core/gate/verification.js.map +1 -0
  575. package/dist/core/gherkin/digest.js +60 -0
  576. package/dist/core/gherkin/digest.js.map +1 -0
  577. package/dist/core/gherkin/emit.js +177 -0
  578. package/dist/core/gherkin/emit.js.map +1 -0
  579. package/dist/core/gherkin/read.js +76 -0
  580. package/dist/core/gherkin/read.js.map +1 -0
  581. package/dist/core/gherkin/stale.js +234 -0
  582. package/dist/core/gherkin/stale.js.map +1 -0
  583. package/dist/core/gherkin/stamp.js +77 -0
  584. package/dist/core/gherkin/stamp.js.map +1 -0
  585. package/dist/core/gherkin/steps/catalogue.js +154 -0
  586. package/dist/core/gherkin/steps/catalogue.js.map +1 -0
  587. package/dist/core/gherkin/steps/inventory.js +98 -0
  588. package/dist/core/gherkin/steps/inventory.js.map +1 -0
  589. package/dist/core/gherkin/steps/phrase.js +72 -0
  590. package/dist/core/gherkin/steps/phrase.js.map +1 -0
  591. package/dist/core/glossary/delta.js +106 -0
  592. package/dist/core/glossary/delta.js.map +1 -0
  593. package/dist/core/glossary/tree.js +86 -0
  594. package/dist/core/glossary/tree.js.map +1 -0
  595. package/dist/core/kernel/concurrency.js.map +1 -0
  596. package/dist/core/{document-bytes.js → kernel/document-bytes.js} +1 -1
  597. package/dist/core/kernel/document-bytes.js.map +1 -0
  598. package/dist/core/kernel/fences.js +42 -0
  599. package/dist/core/kernel/fences.js.map +1 -0
  600. package/dist/core/kernel/ids/capability.js +72 -0
  601. package/dist/core/kernel/ids/capability.js.map +1 -0
  602. package/dist/core/kernel/ids/dirs.js +33 -0
  603. package/dist/core/kernel/ids/dirs.js.map +1 -0
  604. package/dist/core/kernel/ids/feature.js +75 -0
  605. package/dist/core/kernel/ids/feature.js.map +1 -0
  606. package/dist/core/kernel/ids/service.js +156 -0
  607. package/dist/core/kernel/ids/service.js.map +1 -0
  608. package/dist/core/kernel/ids/subsystem.js +63 -0
  609. package/dist/core/kernel/ids/subsystem.js.map +1 -0
  610. package/dist/core/{path-safety.js → kernel/path-safety.js} +18 -4
  611. package/dist/core/kernel/path-safety.js.map +1 -0
  612. package/dist/core/kernel/records.js.map +1 -0
  613. package/dist/core/links/backlinks.js +68 -0
  614. package/dist/core/links/backlinks.js.map +1 -0
  615. package/dist/core/links/case.js +74 -0
  616. package/dist/core/links/case.js.map +1 -0
  617. package/dist/core/links/corpus.js +104 -0
  618. package/dist/core/links/corpus.js.map +1 -0
  619. package/dist/core/links/findings.js +110 -0
  620. package/dist/core/links/findings.js.map +1 -0
  621. package/dist/core/links/parse.js +236 -0
  622. package/dist/core/links/parse.js.map +1 -0
  623. package/dist/core/mcp/argv.js +111 -0
  624. package/dist/core/mcp/argv.js.map +1 -0
  625. package/dist/core/mcp/author-tools.js +72 -0
  626. package/dist/core/mcp/author-tools.js.map +1 -0
  627. package/dist/core/mcp/framing.js +46 -0
  628. package/dist/core/mcp/framing.js.map +1 -0
  629. package/dist/core/mcp/protocol.js +280 -0
  630. package/dist/core/mcp/protocol.js.map +1 -0
  631. package/dist/core/mcp/tools.js +314 -0
  632. package/dist/core/mcp/tools.js.map +1 -0
  633. package/dist/core/obligations/obligations.js +106 -0
  634. package/dist/core/obligations/obligations.js.map +1 -0
  635. package/dist/core/openapi/baseline/gate.js +166 -0
  636. package/dist/core/openapi/baseline/gate.js.map +1 -0
  637. package/dist/core/openapi/baseline/plan.js +112 -0
  638. package/dist/core/openapi/baseline/plan.js.map +1 -0
  639. package/dist/core/openapi/baseline/record.js +175 -0
  640. package/dist/core/openapi/baseline/record.js.map +1 -0
  641. package/dist/core/openapi/depth.js +122 -0
  642. package/dist/core/openapi/depth.js.map +1 -0
  643. package/dist/core/openapi/digest.js +189 -0
  644. package/dist/core/openapi/digest.js.map +1 -0
  645. package/dist/core/{openapi.js → openapi/doc.js} +44 -106
  646. package/dist/core/openapi/doc.js.map +1 -0
  647. package/dist/core/openapi/merge/components.js +234 -0
  648. package/dist/core/openapi/merge/components.js.map +1 -0
  649. package/dist/core/openapi/merge/error.js +26 -0
  650. package/dist/core/openapi/merge/error.js.map +1 -0
  651. package/dist/core/openapi/merge/markers.js +208 -0
  652. package/dist/core/openapi/merge/markers.js.map +1 -0
  653. package/dist/core/openapi/merge/merge.js +256 -0
  654. package/dist/core/openapi/merge/merge.js.map +1 -0
  655. package/dist/core/openapi/merge/pin.js +128 -0
  656. package/dist/core/openapi/merge/pin.js.map +1 -0
  657. package/dist/core/openspec/decide/capabilities.js +244 -0
  658. package/dist/core/openspec/decide/capabilities.js.map +1 -0
  659. package/dist/core/openspec/decide/dispositions.js +63 -0
  660. package/dist/core/openspec/decide/dispositions.js.map +1 -0
  661. package/dist/core/openspec/decide/renames.js +179 -0
  662. package/dist/core/openspec/decide/renames.js.map +1 -0
  663. package/dist/core/openspec/decide/verdict.js +84 -0
  664. package/dist/core/openspec/decide/verdict.js.map +1 -0
  665. package/dist/core/openspec/inventory.js +221 -0
  666. package/dist/core/openspec/inventory.js.map +1 -0
  667. package/dist/core/openspec/model/mapping.js +76 -0
  668. package/dist/core/openspec/model/mapping.js.map +1 -0
  669. package/dist/core/openspec/model/model.js +65 -0
  670. package/dist/core/openspec/model/model.js.map +1 -0
  671. package/dist/core/openspec/scan/changes.js +235 -0
  672. package/dist/core/openspec/scan/changes.js.map +1 -0
  673. package/dist/core/openspec/scan/config.js +200 -0
  674. package/dist/core/openspec/scan/config.js.map +1 -0
  675. package/dist/core/openspec/scan/shape.js +260 -0
  676. package/dist/core/openspec/scan/shape.js.map +1 -0
  677. package/dist/core/openspec/scan/walk.js +133 -0
  678. package/dist/core/openspec/scan/walk.js.map +1 -0
  679. package/dist/core/openspec/scan/workspace.js +71 -0
  680. package/dist/core/openspec/scan/workspace.js.map +1 -0
  681. package/dist/core/owners/codeowners.js +141 -0
  682. package/dist/core/owners/codeowners.js.map +1 -0
  683. package/dist/core/pack/features.js +120 -0
  684. package/dist/core/pack/features.js.map +1 -0
  685. package/dist/core/pack/joins.js +112 -0
  686. package/dist/core/pack/joins.js.map +1 -0
  687. package/dist/core/pack/living.js +118 -0
  688. package/dist/core/pack/living.js.map +1 -0
  689. package/dist/core/pack/pack.js +76 -0
  690. package/dist/core/pack/pack.js.map +1 -0
  691. package/dist/core/permissions/permissions.js +87 -0
  692. package/dist/core/permissions/permissions.js.map +1 -0
  693. package/dist/core/projection/api.js +84 -0
  694. package/dist/core/projection/api.js.map +1 -0
  695. package/dist/core/projection/arch-slice.js +63 -0
  696. package/dist/core/projection/arch-slice.js.map +1 -0
  697. package/dist/core/projection/events.js +34 -0
  698. package/dist/core/projection/events.js.map +1 -0
  699. package/dist/core/provenance/findings.js +208 -0
  700. package/dist/core/provenance/findings.js.map +1 -0
  701. package/dist/core/provenance/git.js +225 -0
  702. package/dist/core/provenance/git.js.map +1 -0
  703. package/dist/core/provenance/gitq/moves.js +182 -0
  704. package/dist/core/provenance/gitq/moves.js.map +1 -0
  705. package/dist/core/provenance/gitq/vouched-ancestor.js +179 -0
  706. package/dist/core/provenance/gitq/vouched-ancestor.js.map +1 -0
  707. package/dist/core/provenance/sample/scope.js +238 -0
  708. package/dist/core/provenance/sample/scope.js.map +1 -0
  709. package/dist/core/provenance/sample/sections.js +61 -0
  710. package/dist/core/provenance/sample/sections.js.map +1 -0
  711. package/dist/core/provenance/sources.js +263 -0
  712. package/dist/core/provenance/sources.js.map +1 -0
  713. package/dist/core/provenance/stamp.js +232 -0
  714. package/dist/core/provenance/stamp.js.map +1 -0
  715. package/dist/core/provenance/walk.js +157 -0
  716. package/dist/core/provenance/walk.js.map +1 -0
  717. package/dist/core/repo/authored/paths.js +192 -0
  718. package/dist/core/repo/authored/paths.js.map +1 -0
  719. package/dist/core/repo/entries.js +126 -0
  720. package/dist/core/repo/entries.js.map +1 -0
  721. package/dist/core/repo/paths.js +236 -0
  722. package/dist/core/repo/paths.js.map +1 -0
  723. package/dist/core/repo/repo.js +248 -0
  724. package/dist/core/repo/repo.js.map +1 -0
  725. package/dist/core/repo/service-target.js +153 -0
  726. package/dist/core/repo/service-target.js.map +1 -0
  727. package/dist/core/repo/state.js +58 -0
  728. package/dist/core/repo/state.js.map +1 -0
  729. package/dist/core/repo/tree/find.js +52 -0
  730. package/dist/core/repo/tree/find.js.map +1 -0
  731. package/dist/core/repo/tree/fs.js +64 -0
  732. package/dist/core/repo/tree/fs.js.map +1 -0
  733. package/dist/core/repo/tree/marker.js +61 -0
  734. package/dist/core/repo/tree/marker.js.map +1 -0
  735. package/dist/core/repo/tree/views.js +172 -0
  736. package/dist/core/repo/tree/views.js.map +1 -0
  737. package/dist/core/repo/tree/walk.js +234 -0
  738. package/dist/core/repo/tree/walk.js.map +1 -0
  739. package/dist/core/results.js +99 -2
  740. package/dist/core/results.js.map +1 -1
  741. package/dist/core/scaffold/landscape.js +131 -0
  742. package/dist/core/scaffold/landscape.js.map +1 -0
  743. package/dist/core/scaffold/readme.js +84 -0
  744. package/dist/core/scaffold/readme.js.map +1 -0
  745. package/dist/core/staging/commit.js +241 -0
  746. package/dist/core/staging/commit.js.map +1 -0
  747. package/dist/core/staging/interrupted.js +96 -0
  748. package/dist/core/staging/interrupted.js.map +1 -0
  749. package/dist/core/staging/lock.js +206 -0
  750. package/dist/core/staging/lock.js.map +1 -0
  751. package/dist/core/staging/recovery/finding.js +35 -0
  752. package/dist/core/staging/recovery/finding.js.map +1 -0
  753. package/dist/core/staging/recovery/intent.js +98 -0
  754. package/dist/core/staging/recovery/intent.js.map +1 -0
  755. package/dist/core/staging/recovery/recover.js +126 -0
  756. package/dist/core/staging/recovery/recover.js.map +1 -0
  757. package/dist/core/staging/recovery/residue.js +62 -0
  758. package/dist/core/staging/recovery/residue.js.map +1 -0
  759. package/dist/core/staging/snapshot.js +202 -0
  760. package/dist/core/staging/snapshot.js.map +1 -0
  761. package/dist/core/staging/txn/forward.js +171 -0
  762. package/dist/core/staging/txn/forward.js.map +1 -0
  763. package/dist/core/staging/txn/journal.js +139 -0
  764. package/dist/core/staging/txn/journal.js.map +1 -0
  765. package/dist/core/staging/txn/transaction.js +75 -0
  766. package/dist/core/staging/txn/transaction.js.map +1 -0
  767. package/dist/core/staging/writes.js +113 -0
  768. package/dist/core/staging/writes.js.map +1 -0
  769. package/dist/core/status/actions/execution.js +49 -0
  770. package/dist/core/status/actions/execution.js.map +1 -0
  771. package/dist/core/status/contracts.js +102 -0
  772. package/dist/core/status/contracts.js.map +1 -0
  773. package/dist/core/status/feature/artifacts.js +171 -0
  774. package/dist/core/status/feature/artifacts.js.map +1 -0
  775. package/dist/core/status/feature/feature.js +207 -0
  776. package/dist/core/status/feature/feature.js.map +1 -0
  777. package/dist/core/status/feature/next.js +150 -0
  778. package/dist/core/status/feature/next.js.map +1 -0
  779. package/dist/core/status/feature/state.js +21 -0
  780. package/dist/core/status/feature/state.js.map +1 -0
  781. package/dist/core/status/fleet/fleet.js +187 -0
  782. package/dist/core/status/fleet/fleet.js.map +1 -0
  783. package/dist/core/status/fleet/next.js +207 -0
  784. package/dist/core/status/fleet/next.js.map +1 -0
  785. package/dist/core/status/interrupted.js +97 -0
  786. package/dist/core/status/interrupted.js.map +1 -0
  787. package/dist/core/status/report.js +31 -0
  788. package/dist/core/status/report.js.map +1 -0
  789. package/dist/core/status/scan.js +41 -0
  790. package/dist/core/status/scan.js.map +1 -0
  791. package/dist/core/status/verification.js +201 -0
  792. package/dist/core/status/verification.js.map +1 -0
  793. package/dist/core/usecases/capability.js +169 -0
  794. package/dist/core/usecases/capability.js.map +1 -0
  795. package/dist/core/usecases/delta/claims.js +116 -0
  796. package/dist/core/usecases/delta/claims.js.map +1 -0
  797. package/dist/core/usecases/delta/flows.js +103 -0
  798. package/dist/core/usecases/delta/flows.js.map +1 -0
  799. package/dist/core/usecases/delta/overlay.js +235 -0
  800. package/dist/core/usecases/delta/overlay.js.map +1 -0
  801. package/dist/core/usecases/fleet.js +137 -0
  802. package/dist/core/usecases/fleet.js.map +1 -0
  803. package/dist/core/usecases/operations.js +111 -0
  804. package/dist/core/usecases/operations.js.map +1 -0
  805. package/dist/core/usecases/place.js +44 -0
  806. package/dist/core/usecases/place.js.map +1 -0
  807. package/dist/core/usecases/touch.js +101 -0
  808. package/dist/core/usecases/touch.js.map +1 -0
  809. package/dist/core/verify/answers.js +173 -0
  810. package/dist/core/verify/answers.js.map +1 -0
  811. package/dist/core/verify/build.js +150 -0
  812. package/dist/core/verify/build.js.map +1 -0
  813. package/dist/core/verify/checklist.js +201 -0
  814. package/dist/core/verify/checklist.js.map +1 -0
  815. package/dist/core/verify/claims/identity.js +61 -0
  816. package/dist/core/verify/claims/identity.js.map +1 -0
  817. package/dist/core/verify/cross/diff.js +97 -0
  818. package/dist/core/verify/cross/diff.js.map +1 -0
  819. package/dist/core/verify/evidence/contract.js +169 -0
  820. package/dist/core/verify/evidence/contract.js.map +1 -0
  821. package/dist/core/verify/file.js +257 -0
  822. package/dist/core/verify/file.js.map +1 -0
  823. package/dist/core/verify/pins/lint.js +157 -0
  824. package/dist/core/verify/pins/lint.js.map +1 -0
  825. package/dist/core/verify/pins/pin.js +95 -0
  826. package/dist/core/verify/pins/pin.js.map +1 -0
  827. package/dist/core/verify/record.js +142 -0
  828. package/dist/core/verify/record.js.map +1 -0
  829. package/dist/core/verify/store/commit.js +89 -0
  830. package/dist/core/verify/store/commit.js.map +1 -0
  831. package/dist/core/verify/store/render.js +57 -0
  832. package/dist/core/verify/store/render.js.map +1 -0
  833. package/dist/core/vocabulary/health.js +91 -0
  834. package/dist/core/vocabulary/health.js.map +1 -0
  835. package/dist/core/vocabulary/issue.js +55 -0
  836. package/dist/core/vocabulary/issue.js.map +1 -0
  837. package/dist/core/vocabulary/maturity.js +145 -0
  838. package/dist/core/vocabulary/maturity.js.map +1 -0
  839. package/dist/core/{report.js → vocabulary/report.js} +30 -2
  840. package/dist/core/vocabulary/report.js.map +1 -0
  841. package/dist/core/vocabulary/steps.js +266 -0
  842. package/dist/core/vocabulary/steps.js.map +1 -0
  843. package/dist/core/workspace/discover.js +239 -0
  844. package/dist/core/workspace/discover.js.map +1 -0
  845. package/dist/core/workspace/render.js +52 -0
  846. package/dist/core/workspace/render.js.map +1 -0
  847. package/examples/README.md +189 -0
  848. package/examples/docs/architecture/adrs/0001-transactional-outbox.md +33 -0
  849. package/examples/docs/architecture/capabilities.yaml +31 -0
  850. package/examples/docs/architecture/landscape.likec4 +280 -0
  851. package/examples/docs/architecture/obligations.yaml +23 -0
  852. package/examples/docs/architecture/permissions.yaml +50 -0
  853. package/examples/docs/architecture/subsystems.likec4 +11 -0
  854. package/examples/docs/architecture/usecases/order-notification.likec4 +65 -0
  855. package/examples/docs/capabilities/checkout/spec.md +55 -0
  856. package/examples/docs/capabilities/identity/tokens/spec.md +42 -0
  857. package/examples/docs/capabilities/order-notifications/spec.md +43 -0
  858. package/examples/docs/features/FEAT-101-payment-splitting/adrs/0001-dedicated-split-service.md +18 -0
  859. package/examples/docs/features/FEAT-101-payment-splitting/delta.likec4 +94 -0
  860. package/examples/docs/features/FEAT-101-payment-splitting/intent.md +44 -0
  861. package/examples/docs/features/FEAT-101-payment-splitting/specs/checkout-web/spec.md +21 -0
  862. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-service/asyncapi.yaml +129 -0
  863. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-service/spec.md +36 -0
  864. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/arch.spec.md +40 -0
  865. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/openapi.yaml +116 -0
  866. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/spec.md +55 -0
  867. package/examples/docs/features/FEAT-112-retire-order-v1/intent.md +35 -0
  868. package/examples/docs/features/FEAT-112-retire-order-v1/specs/order-service/openapi.yaml +28 -0
  869. package/examples/docs/features/FEAT-112-retire-order-v1/specs/order-service/spec.md +17 -0
  870. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/architecture/landscape.likec4 +253 -0
  871. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/services/order-service/spec.md +121 -0
  872. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/services/payment-service/openapi.yaml +111 -0
  873. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/services/payment-service/spec.md +58 -0
  874. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/manifest.json +32 -0
  875. package/examples/docs/features/archive/FEAT-088-refunds/adrs/0001-refunds-stay-in-payment-service.md +26 -0
  876. package/examples/docs/features/archive/FEAT-088-refunds/delta.likec4 +28 -0
  877. package/examples/docs/features/archive/FEAT-088-refunds/intent.md +26 -0
  878. package/examples/docs/features/archive/FEAT-088-refunds/specs/order-service/spec.md +37 -0
  879. package/examples/docs/features/archive/FEAT-088-refunds/specs/payment-service/openapi.yaml +70 -0
  880. package/examples/docs/features/archive/FEAT-088-refunds/specs/payment-service/spec.md +23 -0
  881. package/examples/docs/features/archive/FEAT-088-refunds/verification.yaml +76 -0
  882. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/architecture/landscape.likec4 +275 -0
  883. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/payment-service/asyncapi.yaml +96 -0
  884. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/payment-service/spec.md +82 -0
  885. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/platform/notification-service/asyncapi.yaml +164 -0
  886. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/platform/notification-service/spec.md +91 -0
  887. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/manifest.json +46 -0
  888. package/examples/docs/features/archive/FEAT-120-refund-notification/delta.likec4 +36 -0
  889. package/examples/docs/features/archive/FEAT-120-refund-notification/intent.md +22 -0
  890. package/examples/docs/features/archive/FEAT-120-refund-notification/scenario-report.json +10 -0
  891. package/examples/docs/features/archive/FEAT-120-refund-notification/specs/notification-service/asyncapi.yaml +208 -0
  892. package/examples/docs/features/archive/FEAT-120-refund-notification/specs/notification-service/spec.md +24 -0
  893. package/examples/docs/features/archive/FEAT-120-refund-notification/specs/payment-service/asyncapi.yaml +137 -0
  894. package/examples/docs/features/archive/FEAT-120-refund-notification/specs/payment-service/spec.md +31 -0
  895. package/examples/docs/features/archive/FEAT-120-refund-notification/verification.yaml +84 -0
  896. package/examples/docs/glossary/order.md +15 -0
  897. package/examples/docs/glossary/payments/authorization.md +14 -0
  898. package/examples/docs/likec4.config.json +9 -0
  899. package/examples/docs/loam.json +3 -0
  900. package/examples/docs/services/checkout-web/model.likec4 +109 -0
  901. package/examples/docs/services/checkout-web/spec.md +91 -0
  902. package/examples/docs/services/checkout-web/ui/pages/checkout.page.yaml +40 -0
  903. package/examples/docs/services/checkout-web/ui/pages/order-status.page.yaml +24 -0
  904. package/examples/docs/services/checkout-web/ui/pages/split-payment.page.yaml +26 -0
  905. package/examples/docs/services/order-service/adrs/0001-orchestrated-order-lifecycle.md +52 -0
  906. package/examples/docs/services/order-service/arch.spec.md +127 -0
  907. package/examples/docs/services/order-service/asyncapi.yaml +108 -0
  908. package/examples/docs/services/order-service/health.yaml +57 -0
  909. package/examples/docs/services/order-service/model.likec4 +138 -0
  910. package/examples/docs/services/order-service/openapi.yaml +257 -0
  911. package/examples/docs/services/order-service/runbook.md +62 -0
  912. package/examples/docs/services/order-service/spec.md +134 -0
  913. package/examples/docs/services/payment-service/adrs/0001-payments-outbox.md +18 -0
  914. package/examples/docs/services/payment-service/adrs/0002-idempotency-keys-on-authorization.md +27 -0
  915. package/examples/docs/services/payment-service/arch.spec.md +73 -0
  916. package/examples/docs/services/payment-service/asyncapi.yaml +130 -0
  917. package/examples/docs/services/payment-service/health.yaml +39 -0
  918. package/examples/docs/services/payment-service/model.likec4 +67 -0
  919. package/examples/docs/services/payment-service/openapi.yaml +151 -0
  920. package/examples/docs/services/payment-service/runbook.md +37 -0
  921. package/examples/docs/services/payment-service/spec.md +88 -0
  922. package/examples/docs/services/platform/identity-service/adrs/0001-token-introspection-over-local-validation.md +60 -0
  923. package/examples/docs/services/platform/identity-service/arch.spec.md +117 -0
  924. package/examples/docs/services/platform/identity-service/health.yaml +70 -0
  925. package/examples/docs/services/platform/identity-service/model.likec4 +83 -0
  926. package/examples/docs/services/platform/identity-service/openapi.yaml +197 -0
  927. package/examples/docs/services/platform/identity-service/runbook.md +95 -0
  928. package/examples/docs/services/platform/identity-service/spec.md +119 -0
  929. package/examples/docs/services/platform/notification-service/asyncapi.yaml +199 -0
  930. package/examples/docs/services/platform/notification-service/health.yaml +35 -0
  931. package/examples/docs/services/platform/notification-service/model.likec4 +118 -0
  932. package/examples/docs/services/platform/notification-service/runbook.md +48 -0
  933. package/examples/docs/services/platform/notification-service/spec.md +112 -0
  934. package/examples/docs/services/platform/subsystem.yaml +2 -0
  935. package/examples/fleet.yaml +57 -0
  936. package/package.json +19 -6
  937. package/dist/commands/adopt.js +0 -240
  938. package/dist/commands/adopt.js.map +0 -1
  939. package/dist/commands/archive.js +0 -1313
  940. package/dist/commands/archive.js.map +0 -1
  941. package/dist/commands/delta.js +0 -388
  942. package/dist/commands/delta.js.map +0 -1
  943. package/dist/commands/docs-repo-gate.js.map +0 -1
  944. package/dist/commands/format.js +0 -17
  945. package/dist/commands/format.js.map +0 -1
  946. package/dist/commands/gherkin.js +0 -309
  947. package/dist/commands/gherkin.js.map +0 -1
  948. package/dist/commands/init.js.map +0 -1
  949. package/dist/commands/list.js +0 -295
  950. package/dist/commands/list.js.map +0 -1
  951. package/dist/commands/migrate-openspec.js +0 -950
  952. package/dist/commands/migrate-openspec.js.map +0 -1
  953. package/dist/commands/new.js +0 -413
  954. package/dist/commands/new.js.map +0 -1
  955. package/dist/commands/rebase.js +0 -356
  956. package/dist/commands/rebase.js.map +0 -1
  957. package/dist/commands/show.js.map +0 -1
  958. package/dist/commands/status.js +0 -262
  959. package/dist/commands/status.js.map +0 -1
  960. package/dist/commands/unarchive.js.map +0 -1
  961. package/dist/commands/validate.js +0 -1773
  962. package/dist/commands/validate.js.map +0 -1
  963. package/dist/commands/verify.js +0 -775
  964. package/dist/commands/verify.js.map +0 -1
  965. package/dist/commands/vouch.js +0 -421
  966. package/dist/commands/vouch.js.map +0 -1
  967. package/dist/core/agent.js +0 -2173
  968. package/dist/core/agent.js.map +0 -1
  969. package/dist/core/agents-stamp.js.map +0 -1
  970. package/dist/core/arch.js +0 -130
  971. package/dist/core/arch.js.map +0 -1
  972. package/dist/core/asyncapi.js.map +0 -1
  973. package/dist/core/brief.js +0 -755
  974. package/dist/core/brief.js.map +0 -1
  975. package/dist/core/coherence.js +0 -577
  976. package/dist/core/coherence.js.map +0 -1
  977. package/dist/core/concurrency.js.map +0 -1
  978. package/dist/core/config.js.map +0 -1
  979. package/dist/core/delta.js +0 -476
  980. package/dist/core/delta.js.map +0 -1
  981. package/dist/core/dependencies.js +0 -356
  982. package/dist/core/dependencies.js.map +0 -1
  983. package/dist/core/doctor.js +0 -596
  984. package/dist/core/doctor.js.map +0 -1
  985. package/dist/core/document-bytes.js.map +0 -1
  986. package/dist/core/explore.js.map +0 -1
  987. package/dist/core/frontmatter.js.map +0 -1
  988. package/dist/core/gherkin.js +0 -463
  989. package/dist/core/gherkin.js.map +0 -1
  990. package/dist/core/health.js +0 -67
  991. package/dist/core/health.js.map +0 -1
  992. package/dist/core/ids.js +0 -122
  993. package/dist/core/ids.js.map +0 -1
  994. package/dist/core/issue.js +0 -9
  995. package/dist/core/issue.js.map +0 -1
  996. package/dist/core/json.js +0 -74
  997. package/dist/core/json.js.map +0 -1
  998. package/dist/core/likec4.js +0 -489
  999. package/dist/core/likec4.js.map +0 -1
  1000. package/dist/core/maturity.js +0 -66
  1001. package/dist/core/maturity.js.map +0 -1
  1002. package/dist/core/openapi-merge.js +0 -552
  1003. package/dist/core/openapi-merge.js.map +0 -1
  1004. package/dist/core/openapi.js.map +0 -1
  1005. package/dist/core/openspec-inventory.js +0 -1440
  1006. package/dist/core/openspec-inventory.js.map +0 -1
  1007. package/dist/core/path-safety.js.map +0 -1
  1008. package/dist/core/provenance.js +0 -787
  1009. package/dist/core/provenance.js.map +0 -1
  1010. package/dist/core/records.js.map +0 -1
  1011. package/dist/core/repo.js +0 -438
  1012. package/dist/core/repo.js.map +0 -1
  1013. package/dist/core/report.js.map +0 -1
  1014. package/dist/core/spec.js +0 -505
  1015. package/dist/core/spec.js.map +0 -1
  1016. package/dist/core/staging.js +0 -890
  1017. package/dist/core/staging.js.map +0 -1
  1018. package/dist/core/status.js +0 -1132
  1019. package/dist/core/status.js.map +0 -1
  1020. package/dist/core/steps.js +0 -72
  1021. package/dist/core/steps.js.map +0 -1
  1022. package/dist/core/verify.js +0 -807
  1023. package/dist/core/verify.js.map +0 -1
  1024. package/dist/core/version.js.map +0 -1
  1025. /package/dist/core/{concurrency.js → kernel/concurrency.js} +0 -0
  1026. /package/dist/core/{records.js → kernel/records.js} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"living.js","sourceRoot":"","sources":["../../../src/core/coherence/living.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * What the merge would do to the LIVING documents.\n *\n * The refusals `loam archive` makes about the world a feature is about to be\n * merged INTO — as opposed to the feature's own three axes agreeing, which is\n * coherence.ts's question: a per-service delta addressed to a service that\n * exists nowhere, a `specs/<svc>/` directory whose NAME could never be a\n * service id, and git conflict markers in a living document the merge would\n * rewrite. `validate` and `status` read the same functions, so the gates\n * cannot drift into disagreeing about what they refuse.\n */\nimport { existsSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport { loadFile, type LoadedDoc } from \"../c4/likec4.js\";\nimport { elementService } from \"../c4/resolve/service.js\";\nimport { closeIds } from \"../c4/arch.js\";\nimport { serviceIdProblem, type PathableService } from \"../kernel/ids/service.js\";\nimport { repoPath } from \"../envelope/json.js\";\nimport type { Finding } from \"../vocabulary/report.js\";\nimport { featurePaths, landscapePath, SPEC_AXES } from \"../repo/paths.js\";\nimport { livingCapabilityPaths } from \"../repo/authored/paths.js\";\nimport { docsRepoState } from \"../repo/state.js\";\nimport { featureSpecServices, listServices } from \"../repo/repo.js\";\nimport { enumeratedServices, locateServicePaths } from \"../repo/service-target.js\";\nimport type { DocsDir, FeatureDir } from \"../kernel/ids/dirs.js\";\nimport { documentConflictFinding, landscapeConflictFinding } from \"../conflict-markers.js\";\nimport type { FleetContext } from \"../fleet-context.js\";\n\n\n/* ------------------------------------------------------------------ */\n/* What the merge would do to the LIVING documents */\n/* ------------------------------------------------------------------ */\n\n/**\n * Per-service deltas addressed to a service that exists nowhere: no\n * `services/<svc>/`, and nothing in this feature's own tagged delta introducing\n * one.\n *\n * `validate` grades this (`delta.service-unknown`); `archive` is where it costs\n * something, because `specs/<svc>/` is what the merge MATERIALISES\n * `services/<svc>/` from — one wrong character in `--touches` and the fleet\n * acquires a living service nobody meant to adopt, under a banner saying the\n * living docs are complete. Both gates read this function so they cannot drift\n * into disagreeing about which service ids are real; the `code:` literal lives\n * here, once, where the drift collector sees it.\n *\n * A delta that did not parse proves nothing either way — whether it introduces\n * the service is exactly what nobody can read — so the question is suspended\n * there rather than answered by guessing. `delta.invalid` is that file's\n * finding, and coherence already makes it.\n *\n * `services/<svc>/` is asked for directly rather than through the enumeration:\n * a feature may be graded in a docs repo with no `services/` at all (repo.ts\n * takes the same position), where enumerating is a refusal, not an answer.\n */\nexport async function unknownDeltaServices(\n docsDir: DocsDir,\n featureDir: FeatureDir,\n featureId: string,\n loaded: { preloadedDelta?: LoadedDoc; context?: FleetContext } = {},\n): Promise<Finding[]> {\n const { preloadedDelta, context } = loaded;\n const deltaPath = featurePaths(featureDir).delta;\n let delta: LoadedDoc | undefined;\n if (existsSync(deltaPath)) {\n delta = preloadedDelta ?? (context === undefined ? await loadFile(deltaPath) : await context.loadLikeC4(deltaPath));\n }\n if (delta !== undefined && delta.errors.length > 0) return [];\n\n const introduces: ReadonlySet<string> = new Set(\n (delta?.elements ?? []).filter((e) => e.tags.includes(featureId)).map(elementService),\n );\n // Enumeration MEMBERSHIP, not an existsSync of services/<svc>/ at the root:\n // a service filed into a subsystem exists wherever the tree walk found it,\n // and the root probe would grade it unknown. `enumeratedServices` swallows\n // an unenumerable services/ to [] on purpose — this also runs under archive\n // in repos validate --feature tolerates (no services/ at all), where every\n // probe would have found nothing there anyway.\n const known: ReadonlySet<string> = new Set((await enumeratedServices(docsDir, context)).map((s) => s.id));\n const unknown = (await featureSpecServices(featureDir, context)).filter(\n (svc) => !known.has(svc) && !introduces.has(svc),\n );\n if (unknown.length === 0) return [];\n\n // The near-miss hint, on the same rule `service.unknown` uses — a typo is\n // only diagnosable against the ids that DO exist.\n const closeTo =\n docsRepoState(docsDir).kind === \"ok\" ? (await listServices(docsDir, context)).map((s) => s.id) : [];\n return unknown.map((svc) => deltaServiceUnknownFinding(svc, closeTo));\n}\n\n/**\n * The finding itself, for the two gates that reach this conclusion by different\n * routes.\n *\n * `archive` gets there through `unknownDeltaServices` above; `validate` gets\n * there through its own enumeration, because it suspends the question on an\n * unreadable delta rather than returning early on it, and that difference is\n * deliberate. What must NOT differ is the sentence: the two were spelled out\n * word for word in two files, so a reworded hint in one of them would have made\n * `loam validate` and `loam archive` describe the same typo differently, on the\n * same code, in the same repo.\n *\n * `knownIds` is the fleet's real service ids — already enumerated by the caller,\n * which is also the caller's chance to skip the enumeration entirely when there\n * is nothing to diagnose.\n */\nexport function deltaServiceUnknownFinding(svc: string, knownIds: string[]): Finding {\n const close = closeIds(svc, knownIds);\n return {\n severity: \"error\",\n code: \"delta.service-unknown\",\n subject: svc,\n message:\n `specs/${svc}/ addresses a service that does not exist: there is no services/${svc}/ and this feature's ` +\n `delta.likec4 does not introduce one — archiving would create it out of the typo.` +\n (close.length > 0 ? ` Did you mean: ${close.join(\", \")}?` : \" `loam list services` shows what exists.\"),\n };\n}\n\n/**\n * Per-service deltas whose DIRECTORY NAME is not a legal service id at all.\n *\n * `specs/<svc>/` is caller-controlled path input exactly as `--service` is:\n * `featureSpecServices` returns whatever `readdir` found, and nothing between\n * that readdir and the archive merge ever asked the id grammar about it. So\n * `specs/Payment Service/` validated green — \"requirements covered\", even,\n * because a tagged element whose TITLE matched the directory counted as\n * introducing the service — and `loam archive` then materialised\n * `services/Payment Service/`: a directory `service.id-invalid` calls an error\n * on the very next `validate --all`, and one no loam command can address or\n * re-create. Both gates read this function for `unknownDeltaServices`' reason:\n * validate and archive must refuse the same directory with the same sentence.\n *\n * NOT suppressed by what the delta introduces, and NOT suspended on\n * `delta.invalid`: the name is illegal whatever the architecture axis says,\n * because the name itself is what becomes the path.\n */\nexport async function invalidSpecServiceFindings(\n featureDir: FeatureDir,\n context?: FleetContext,\n): Promise<Finding[]> {\n const out: Finding[] = [];\n for (const svc of await featureSpecServices(featureDir, context)) {\n const problem = serviceIdProblem(svc, \"specs/ directory name\");\n if (problem === null) continue;\n out.push({\n severity: \"error\",\n code: \"delta.service-id-invalid\",\n subject: svc,\n message:\n `specs/${svc}/ — ${problem} ` +\n `\\`loam archive\\` materialises services/${svc}/ from this directory name, and that directory is one ` +\n `no loam command can address afterwards (\\`service.id-invalid\\`). Rename the specs/ directory to a legal id.`,\n });\n }\n return out;\n}\n\n/**\n * Git conflict markers in the LIVING documents a merge of this feature would\n * rewrite: each touched service's requirement files, and the fleet map.\n *\n * The rule and the sentence are conflict-markers's — one spelling of the breach,\n * wherever it is found. What this adds is the SET: the documents `archive`\n * rewrites. A conflicted `services/<svc>/spec.md` parses as prose, so every\n * check upstream of the merge reads it as a valid document with some odd\n * headings in it; the rewrite then drops whichever marker lines fall inside the\n * requirements run it owns, and a conflict anyone could see becomes a file\n * nobody can tell is wrong. For a shared docs repo that a fleet lands in\n * through PRs, that is the default failure and not an edge.\n *\n * `openapi.yaml` is deliberately absent: markers make it unparseable, so the\n * YAML reader already refuses it by name and a second finding would only say\n * the same thing later.\n *\n * `capabilities` is the same question on the business corpus, and it is not\n * optional politeness: a living `capabilities/<id>/spec.md` the feature's\n * capability delta merges into is rewritten by exactly the same\n * `rewriteRequirementsRun`, so a conflicted one loses its marker lines exactly\n * the same way. Passed in rather than walked here because the caller has\n * already read the feature's delta tree and this function must not decide which\n * documents a merge touches.\n *\n * IDS, not the `CapabilityDoc` records the caller holds, and that is a guard\n * rather than a preference: a `CapabilityDoc` from a feature's delta walk\n * carries `spec` and `dir` pointing at the FEATURE'S copy, and the document\n * this function is about is the LIVING one. Taking the whole record would leave\n * `doc.spec` in scope here — the wrong file, one property access away.\n */\nexport async function livingMergeConflicts(\n docsDir: DocsDir,\n services: readonly PathableService[],\n capabilities: readonly string[],\n context?: FleetContext,\n): Promise<Finding[]> {\n const out: Finding[] = [];\n const read = async (path: string): Promise<string> =>\n context === undefined ? readFile(path, \"utf8\") : context.readText(path);\n\n for (const svc of services) {\n const paths = await locateServicePaths(docsDir, svc, context);\n for (const axis of SPEC_AXES) {\n const path = paths[axis.key];\n if (!existsSync(path)) continue;\n const finding = documentConflictFinding(repoPath(docsDir, path), svc, await read(path));\n if (finding !== null) out.push(finding);\n }\n }\n\n for (const id of capabilities) {\n const path = livingCapabilityPaths(docsDir, id).spec;\n if (!existsSync(path)) continue;\n const finding = documentConflictFinding(repoPath(docsDir, path), id, await read(path));\n if (finding !== null) out.push(finding);\n }\n\n const landscape = landscapePath(docsDir);\n if (existsSync(landscape)) {\n const finding = landscapeConflictFinding(repoPath(docsDir, landscape), await read(landscape));\n if (finding !== null) out.push(finding);\n }\n return out;\n}\n"]}
@@ -0,0 +1,155 @@
1
+ /**
2
+ * The questions the coherence checks ask lazily, each behind a per-service or
3
+ * per-repo cache.
4
+ *
5
+ * All but one reach outside the delta — into a living spec, the fleet map, or
6
+ * another feature in flight — and those are expensive: the landscape is a full
7
+ * LikeC4 workspace spin-up, and the cross-feature scan is a walk of every
8
+ * active delta. The exception is `undeprecatedByFeature`, which reads the
9
+ * FEATURE's own openapi delta: it lives here anyway because it is the second
10
+ * half of the one question `deprecatedInLiving` opens — "is this op dying, and
11
+ * is this feature the resurrection?" — and splitting the pair across modules
12
+ * would leave each half's cache discipline unexplained by the other. A feature
13
+ * whose checks never need a lookup must not pay for it, which is why these are
14
+ * closures over a cache rather than arguments computed up front.
15
+ */
16
+ import { existsSync } from "node:fs";
17
+ import { readFile } from "node:fs/promises";
18
+ import { loadFile } from "../c4/likec4.js";
19
+ import { serviceResolver } from "../c4/resolve/service.js";
20
+ import {} from "../kernel/ids/service.js";
21
+ import { featureSpecPaths, landscapePath } from "../repo/paths.js";
22
+ import { operations } from "../openapi/doc.js";
23
+ import { enumeratedServiceIds, locateServicePaths } from "../repo/service-target.js";
24
+ import { activeOpAdditions } from "./pending.js";
25
+ import { parseRequirements } from "../document/parse.js";
26
+ import {} from "../document/spec.js";
27
+ import {} from "./declared.js";
28
+ export function coherenceLookups(scope, context) {
29
+ const { docsDir, featureDir, featureId } = scope;
30
+ const livingReqs = new Map();
31
+ const livingRequirements = async (service) => {
32
+ let reqs = livingReqs.get(service);
33
+ if (reqs === undefined) {
34
+ const p = (await locateServicePaths(docsDir, service, context)).spec;
35
+ reqs = existsSync(p)
36
+ ? context === undefined
37
+ ? parseRequirements(await readFile(p, "utf8"))
38
+ : await context.readRequirements(p)
39
+ : [];
40
+ livingReqs.set(service, reqs);
41
+ }
42
+ return reqs;
43
+ };
44
+ const governedByLivingSpec = async (service, op) => {
45
+ return (await livingRequirements(service)).some((r) => r.operations.includes(op));
46
+ };
47
+ // The enumerated fleet, read once and shared by both consumer scans below.
48
+ let serviceIds;
49
+ const enumeratedServices = async () => (serviceIds ??= await enumeratedServiceIds(docsDir, context));
50
+ // --- retiring an operation the fleet still calls ---
51
+ //
52
+ // A removal marker is checked against the living CONTRACT (does the slot
53
+ // exist) and the feature's own requirements (is the retirement governed).
54
+ // Neither question asks the one that matters to the other ninety-nine repos:
55
+ // is anybody still calling it? The living landscape is the fleet's own answer
56
+ // — an edge with `metadata { op }` is a consumer somebody drew — and another
57
+ // service's living requirements naming the operation are a second. Both are
58
+ // gating: the merge deletes the operation from the contract while the edge
59
+ // and the requirement stay, so the very next `validate --all` reports a
60
+ // broken contract on a repository whose author was never in this feature.
61
+ //
62
+ // Lazy on purpose: the landscape is a full LikeC4 workspace spin-up and the
63
+ // requirement scan reads every service's living spec, and a feature that
64
+ // removes nothing must pay for neither.
65
+ //
66
+ // `core/diff/victims.ts` carries a second copy of this join (an index over
67
+ // an already-read fleet — these closures are scoped to a DeltaScope and
68
+ // cannot serve it). The victim strings and scan rules are kept in step by
69
+ // hand; changing either module owes the other the same change, and a THIRD
70
+ // copy forces the shared extraction (docs/DESIGN.md rule 13).
71
+ let livingLandscape;
72
+ const edgeConsumers = async (service, op) => {
73
+ if (livingLandscape === undefined) {
74
+ const path = landscapePath(docsDir);
75
+ livingLandscape = existsSync(path)
76
+ ? context === undefined
77
+ ? await loadFile(path)
78
+ : await context.loadLikeC4(path)
79
+ : null;
80
+ }
81
+ // An unreadable landscape proves nothing either way; `landscape.invalid`
82
+ // is validate's finding to make, and inventing a removal refusal out of a
83
+ // parse error would point the author at the wrong file.
84
+ if (livingLandscape === null || livingLandscape.errors.length > 0)
85
+ return [];
86
+ // The enumerated fleet rides along so a landscape that models CONTAINERS
87
+ // stays visible: without it, an edge into `payment.api` resolves to a
88
+ // service called "api" that has never existed, the `=== service` join
89
+ // below finds nothing, and the one check standing between a removal and
90
+ // its last consumer answers "nobody calls it".
91
+ const resolve = serviceResolver(livingLandscape.elements, new Set(await enumeratedServices()));
92
+ return livingLandscape.relationships
93
+ .filter((r) => r.op === op && resolve(r.target) === service)
94
+ .map((r) => `edge ${resolve(r.source)} → ${resolve(r.target)}${r.title === undefined ? "" : ` ("${r.title}")`}`);
95
+ };
96
+ const requirementConsumers = async (service, op) => {
97
+ const others = (await enumeratedServices()).filter((id) => id !== service);
98
+ const out = [];
99
+ for (const other of others) {
100
+ for (const r of await livingRequirements(other)) {
101
+ if (r.operations.includes(op))
102
+ out.push(`${other}'s living requirement '${r.name}'`);
103
+ }
104
+ }
105
+ return out;
106
+ };
107
+ // What OTHER features in flight define, per (service, op). Cross-service work
108
+ // normally lands as feature A calling an op that in-flight feature B introduces;
109
+ // that is an ordering dependency, not a broken contract, and the requirements
110
+ // axis already grades the same shape as a warn (delta.modified-pending). Lazy
111
+ // like delta.ts's activeAdditions — the common case (op resolves) never pays
112
+ // for the fleet scan.
113
+ let inFlightOps = null;
114
+ const definedElsewhere = async (service, op) => {
115
+ inFlightOps ??= await activeOpAdditions(docsDir, featureId, context);
116
+ return inFlightOps.get(`${service} ${op}`);
117
+ };
118
+ // What the LIVING provider contracts mark `deprecated: true`, read lazily
119
+ // per service. Living only, on purpose: the feature's own openapi delta
120
+ // restates the full API, and the question here is whether the fleet as
121
+ // shipped is already retiring the op this feature starts leaning on.
122
+ const livingDeprecated = new Map();
123
+ const deprecatedInLiving = async (service, op) => {
124
+ let set = livingDeprecated.get(service);
125
+ if (!set) {
126
+ const list = await operations((await locateServicePaths(docsDir, service, context)).openapi, context);
127
+ set = new Set(list.filter((o) => o.deprecated).map((o) => o.id));
128
+ livingDeprecated.set(service, set);
129
+ }
130
+ return set.has(op);
131
+ };
132
+ // ...unless this feature IS the un-deprecation: an openapi delta that
133
+ // restates the op WITHOUT `deprecated: true` retires the flag on archive
134
+ // (the path-item overwrite is wholesale), so "prefer the replacement
135
+ // operation" would point the author away from the exact change they are
136
+ // shipping. A delta that restates the op still deprecated — or has no
137
+ // delta for the service at all — keeps the warning. The one lookup here
138
+ // that reads the delta's own files rather than the world outside it (the
139
+ // header says why it lives beside its living twin regardless).
140
+ const featureUndeprecated = new Map();
141
+ const undeprecatedByFeature = async (service, op) => {
142
+ let set = featureUndeprecated.get(service);
143
+ if (!set) {
144
+ const list = await operations(featureSpecPaths(featureDir, service).openapi, context);
145
+ set = new Set(list.filter((o) => !o.deprecated).map((o) => o.id));
146
+ featureUndeprecated.set(service, set);
147
+ }
148
+ return set.has(op);
149
+ };
150
+ return {
151
+ governedByLivingSpec, edgeConsumers, requirementConsumers, definedElsewhere,
152
+ deprecatedInLiving, undeprecatedByFeature,
153
+ };
154
+ }
155
+ //# sourceMappingURL=lookups.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lookups.js","sourceRoot":"","sources":["../../../src/core/coherence/lookups.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The questions the coherence checks ask lazily, each behind a per-service or\n * per-repo cache.\n *\n * All but one reach outside the delta — into a living spec, the fleet map, or\n * another feature in flight — and those are expensive: the landscape is a full\n * LikeC4 workspace spin-up, and the cross-feature scan is a walk of every\n * active delta. The exception is `undeprecatedByFeature`, which reads the\n * FEATURE's own openapi delta: it lives here anyway because it is the second\n * half of the one question `deprecatedInLiving` opens — \"is this op dying, and\n * is this feature the resurrection?\" — and splitting the pair across modules\n * would leave each half's cache discipline unexplained by the other. A feature\n * whose checks never need a lookup must not pay for it, which is why these are\n * closures over a cache rather than arguments computed up front.\n */\nimport { existsSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport { loadFile, type LoadedDoc } from \"../c4/likec4.js\";\nimport { serviceResolver } from \"../c4/resolve/service.js\";\nimport { type PathableService } from \"../kernel/ids/service.js\";\nimport { featureSpecPaths, landscapePath } from \"../repo/paths.js\";\nimport { operations } from \"../openapi/doc.js\";\nimport { enumeratedServiceIds, locateServicePaths } from \"../repo/service-target.js\";\nimport { activeOpAdditions } from \"./pending.js\";\nimport { parseRequirements } from \"../document/parse.js\";\nimport { type Requirement } from \"../document/spec.js\";\nimport type { FleetContext } from \"../fleet-context.js\";\nimport { type DeltaScope } from \"./declared.js\";\n\n/** What the checks may ask lazily — fleet questions, plus the deprecation pair. */\nexport interface Lookups {\n governedByLivingSpec(service: PathableService, op: string): Promise<boolean>;\n edgeConsumers(service: string, op: string): Promise<string[]>;\n requirementConsumers(service: string, op: string): Promise<string[]>;\n definedElsewhere(service: string, op: string): Promise<string | undefined>;\n deprecatedInLiving(service: PathableService, op: string): Promise<boolean>;\n undeprecatedByFeature(service: PathableService, op: string): Promise<boolean>;\n}\n\nexport function coherenceLookups(scope: DeltaScope, context?: FleetContext): Lookups {\n const { docsDir, featureDir, featureId } = scope;\n const livingReqs = new Map<string, Requirement[]>();\n const livingRequirements = async (service: PathableService): Promise<Requirement[]> => {\n let reqs = livingReqs.get(service);\n if (reqs === undefined) {\n const p = (await locateServicePaths(docsDir, service, context)).spec;\n reqs = existsSync(p)\n ? context === undefined\n ? parseRequirements(await readFile(p, \"utf8\"))\n : await context.readRequirements(p)\n : [];\n livingReqs.set(service, reqs);\n }\n return reqs;\n };\n const governedByLivingSpec = async (service: PathableService, op: string): Promise<boolean> => {\n return (await livingRequirements(service)).some((r) => r.operations.includes(op));\n };\n\n // The enumerated fleet, read once and shared by both consumer scans below.\n let serviceIds: PathableService[] | undefined;\n const enumeratedServices = async (): Promise<PathableService[]> =>\n (serviceIds ??= await enumeratedServiceIds(docsDir, context));\n\n // --- retiring an operation the fleet still calls ---\n //\n // A removal marker is checked against the living CONTRACT (does the slot\n // exist) and the feature's own requirements (is the retirement governed).\n // Neither question asks the one that matters to the other ninety-nine repos:\n // is anybody still calling it? The living landscape is the fleet's own answer\n // — an edge with `metadata { op }` is a consumer somebody drew — and another\n // service's living requirements naming the operation are a second. Both are\n // gating: the merge deletes the operation from the contract while the edge\n // and the requirement stay, so the very next `validate --all` reports a\n // broken contract on a repository whose author was never in this feature.\n //\n // Lazy on purpose: the landscape is a full LikeC4 workspace spin-up and the\n // requirement scan reads every service's living spec, and a feature that\n // removes nothing must pay for neither.\n //\n // `core/diff/victims.ts` carries a second copy of this join (an index over\n // an already-read fleet — these closures are scoped to a DeltaScope and\n // cannot serve it). The victim strings and scan rules are kept in step by\n // hand; changing either module owes the other the same change, and a THIRD\n // copy forces the shared extraction (docs/DESIGN.md rule 13).\n let livingLandscape: LoadedDoc | null | undefined;\n const edgeConsumers = async (service: string, op: string): Promise<string[]> => {\n if (livingLandscape === undefined) {\n const path = landscapePath(docsDir);\n livingLandscape = existsSync(path)\n ? context === undefined\n ? await loadFile(path)\n : await context.loadLikeC4(path)\n : null;\n }\n // An unreadable landscape proves nothing either way; `landscape.invalid`\n // is validate's finding to make, and inventing a removal refusal out of a\n // parse error would point the author at the wrong file.\n if (livingLandscape === null || livingLandscape.errors.length > 0) return [];\n // The enumerated fleet rides along so a landscape that models CONTAINERS\n // stays visible: without it, an edge into `payment.api` resolves to a\n // service called \"api\" that has never existed, the `=== service` join\n // below finds nothing, and the one check standing between a removal and\n // its last consumer answers \"nobody calls it\".\n const resolve = serviceResolver(livingLandscape.elements, new Set(await enumeratedServices()));\n return livingLandscape.relationships\n .filter((r) => r.op === op && resolve(r.target) === service)\n .map((r) => `edge ${resolve(r.source)} → ${resolve(r.target)}${r.title === undefined ? \"\" : ` (\"${r.title}\")`}`);\n };\n const requirementConsumers = async (service: string, op: string): Promise<string[]> => {\n const others = (await enumeratedServices()).filter((id) => id !== service);\n const out: string[] = [];\n for (const other of others) {\n for (const r of await livingRequirements(other)) {\n if (r.operations.includes(op)) out.push(`${other}'s living requirement '${r.name}'`);\n }\n }\n return out;\n };\n\n // What OTHER features in flight define, per (service, op). Cross-service work\n // normally lands as feature A calling an op that in-flight feature B introduces;\n // that is an ordering dependency, not a broken contract, and the requirements\n // axis already grades the same shape as a warn (delta.modified-pending). Lazy\n // like delta.ts's activeAdditions — the common case (op resolves) never pays\n // for the fleet scan.\n let inFlightOps: Map<string, string> | null = null;\n const definedElsewhere = async (service: string, op: string): Promise<string | undefined> => {\n inFlightOps ??= await activeOpAdditions(docsDir, featureId, context);\n return inFlightOps.get(`${service} ${op}`);\n };\n\n // What the LIVING provider contracts mark `deprecated: true`, read lazily\n // per service. Living only, on purpose: the feature's own openapi delta\n // restates the full API, and the question here is whether the fleet as\n // shipped is already retiring the op this feature starts leaning on.\n const livingDeprecated = new Map<string, Set<string>>();\n const deprecatedInLiving = async (service: PathableService, op: string): Promise<boolean> => {\n let set = livingDeprecated.get(service);\n if (!set) {\n const list = await operations((await locateServicePaths(docsDir, service, context)).openapi, context);\n set = new Set(list.filter((o) => o.deprecated).map((o) => o.id));\n livingDeprecated.set(service, set);\n }\n return set.has(op);\n };\n\n // ...unless this feature IS the un-deprecation: an openapi delta that\n // restates the op WITHOUT `deprecated: true` retires the flag on archive\n // (the path-item overwrite is wholesale), so \"prefer the replacement\n // operation\" would point the author away from the exact change they are\n // shipping. A delta that restates the op still deprecated — or has no\n // delta for the service at all — keeps the warning. The one lookup here\n // that reads the delta's own files rather than the world outside it (the\n // header says why it lives beside its living twin regardless).\n const featureUndeprecated = new Map<string, Set<string>>();\n const undeprecatedByFeature = async (service: PathableService, op: string): Promise<boolean> => {\n let set = featureUndeprecated.get(service);\n if (!set) {\n const list = await operations(featureSpecPaths(featureDir, service).openapi, context);\n set = new Set(list.filter((o) => !o.deprecated).map((o) => o.id));\n featureUndeprecated.set(service, set);\n }\n return set.has(op);\n };\n return {\n governedByLivingSpec, edgeConsumers, requirementConsumers, definedElsewhere,\n deprecatedInLiving, undeprecatedByFeature,\n };\n}\n"]}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * What OTHER features in flight already define — the answer that turns "broken
3
+ * contract" into "ordering dependency".
4
+ *
5
+ * Cross-service work normally lands as feature A consuming an operation that
6
+ * in-flight feature B introduces; grading that as `op-undefined` tells the
7
+ * author to fix a contract that is merely queued. coherence.ts downgrades to
8
+ * the `*-pending` warnings on this module's answer. It is the openapi mirror
9
+ * of delta.ts's `activeAdditions`, and lives beside its caller rather than in
10
+ * delta.ts only because that module is at its size ceiling and the two
11
+ * mirrors never share code — each reads a different axis's documents.
12
+ */
13
+ import { featureSpecPaths } from "../repo/paths.js";
14
+ import { listFeatures } from "../repo/repo.js";
15
+ import { operations } from "../openapi/doc.js";
16
+ /**
17
+ * (service, operationId) pairs other ACTIVE features' openapi deltas define,
18
+ * mapped to the feature id. Archived features are excluded: their ops are in
19
+ * the living openapi already or gone for good, and neither is "pending". First
20
+ * feature wins a clash — one name to archive first is enough to make progress.
21
+ */
22
+ export async function activeOpAdditions(docsDir, exclude, context) {
23
+ const map = new Map();
24
+ for (const feature of await listFeatures(docsDir, {}, context)) {
25
+ if (feature.id === exclude)
26
+ continue;
27
+ for (const service of feature.services) {
28
+ for (const op of await operations(featureSpecPaths(feature.dir, service).openapi, context)) {
29
+ if (op.remove)
30
+ continue;
31
+ const k = `${service} ${op.id}`;
32
+ if (!map.has(k))
33
+ map.set(k, feature.id);
34
+ }
35
+ }
36
+ }
37
+ return map;
38
+ }
39
+ //# sourceMappingURL=pending.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pending.js","sourceRoot":"","sources":["../../../src/core/coherence/pending.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAI/C;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,OAAgB,EAChB,OAAe,EACf,OAAsB;IAEtB,MAAM,GAAG,GAAG,IAAI,GAAG,EAAkB,CAAC;IACtC,KAAK,MAAM,OAAO,IAAI,MAAM,YAAY,CAAC,OAAO,EAAE,EAAE,EAAE,OAAO,CAAC,EAAE,CAAC;QAC/D,IAAI,OAAO,CAAC,EAAE,KAAK,OAAO;YAAE,SAAS;QACrC,KAAK,MAAM,OAAO,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;YACvC,KAAK,MAAM,EAAE,IAAI,MAAM,UAAU,CAAC,gBAAgB,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,CAAC;gBAC3F,IAAI,EAAE,CAAC,MAAM;oBAAE,SAAS;gBACxB,MAAM,CAAC,GAAG,GAAG,OAAO,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC;gBAChC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;oBAAE,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC;YAC1C,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC","sourcesContent":["/**\n * What OTHER features in flight already define — the answer that turns \"broken\n * contract\" into \"ordering dependency\".\n *\n * Cross-service work normally lands as feature A consuming an operation that\n * in-flight feature B introduces; grading that as `op-undefined` tells the\n * author to fix a contract that is merely queued. coherence.ts downgrades to\n * the `*-pending` warnings on this module's answer. It is the openapi mirror\n * of delta.ts's `activeAdditions`, and lives beside its caller rather than in\n * delta.ts only because that module is at its size ceiling and the two\n * mirrors never share code — each reads a different axis's documents.\n */\nimport { featureSpecPaths } from \"../repo/paths.js\";\nimport { listFeatures } from \"../repo/repo.js\";\nimport { operations } from \"../openapi/doc.js\";\nimport type { FleetContext } from \"../fleet-context.js\";\nimport type { DocsDir } from \"../kernel/ids/dirs.js\";\n\n/**\n * (service, operationId) pairs other ACTIVE features' openapi deltas define,\n * mapped to the feature id. Archived features are excluded: their ops are in\n * the living openapi already or gone for good, and neither is \"pending\". First\n * feature wins a clash — one name to archive first is enough to make progress.\n */\nexport async function activeOpAdditions(\n docsDir: DocsDir,\n exclude: string,\n context?: FleetContext,\n): Promise<Map<string, string>> {\n const map = new Map<string, string>();\n for (const feature of await listFeatures(docsDir, {}, context)) {\n if (feature.id === exclude) continue;\n for (const service of feature.services) {\n for (const op of await operations(featureSpecPaths(feature.dir, service).openapi, context)) {\n if (op.remove) continue;\n const k = `${service} ${op.id}`;\n if (!map.has(k)) map.set(k, feature.id);\n }\n }\n }\n return map;\n}\n"]}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * The three-way merge left its markers in the file — 1-based line numbers.
3
+ *
4
+ * The rule is `loam doctor`'s, verbatim, and it lives here now because doctor
5
+ * checked exactly one file (`architecture/landscape.likec4`) from a command
6
+ * that gates nothing. The same markers in a living `services/<svc>/spec.md`
7
+ * parse as prose: `loam validate --all` reported `valid: true`, and the next
8
+ * `loam archive` rewrote the requirements section and dropped the `=======`
9
+ * line with it, turning a conflict anyone can see into a document nobody can
10
+ * tell is wrong. For a shared docs repo where a fleet lands through PRs this is
11
+ * the DEFAULT failure, not an edge.
12
+ */
13
+ const CONFLICT_MARKERS = ["<<<<<<<", "=======", ">>>>>>>"];
14
+ export function conflictMarkerLines(source) {
15
+ const out = [];
16
+ source.split(/\r?\n/).forEach((line, i) => {
17
+ if (CONFLICT_MARKERS.some((m) => line.startsWith(m)))
18
+ out.push(i + 1);
19
+ });
20
+ return out;
21
+ }
22
+ /** One sentence for the breach, wherever it is found — doctor, validate, either axis. */
23
+ function conflictMessage(label, lines) {
24
+ return (`${label} still contains git conflict markers (line${lines.length === 1 ? "" : "s"} ${lines.join(", ")}) — ` +
25
+ `both sides of somebody's merge are in the file, so nothing it says is anyone's text. ` +
26
+ `Resolve the conflict before anything else: loam rewrites this document on archive, and a rewrite deletes ` +
27
+ `whichever marker lines fall inside the section it owns — a visible conflict becomes a silently malformed file.`);
28
+ }
29
+ /**
30
+ * The conflict-marker finding for a requirement document (living spec.md /
31
+ * arch.spec.md, or a feature's delta of one). Null when the text is clean.
32
+ *
33
+ * An error because the document is not valid — nobody wrote what it now says —
34
+ * and because the merge that would consume it is unsafe. It does not carry
35
+ * `gates`: that field is coherence's (issue.ts), and the archive gate has to
36
+ * ask this question itself.
37
+ */
38
+ export function documentConflictFinding(label, subject, text) {
39
+ const lines = conflictMarkerLines(text);
40
+ if (lines.length === 0)
41
+ return null;
42
+ return {
43
+ severity: "error",
44
+ code: "spec.merge-conflict",
45
+ subject,
46
+ message: conflictMessage(label, lines),
47
+ };
48
+ }
49
+ /** The same breach in the fleet map, where it costs every cross-service check at once. */
50
+ export function landscapeConflictFinding(label, text) {
51
+ const lines = conflictMarkerLines(text);
52
+ if (lines.length === 0)
53
+ return null;
54
+ return {
55
+ severity: "error",
56
+ code: "landscape.merge-conflict",
57
+ message: conflictMessage(label, lines),
58
+ };
59
+ }
60
+ //# sourceMappingURL=conflict-markers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conflict-markers.js","sourceRoot":"","sources":["../../src/core/conflict-markers.ts"],"names":[],"mappings":"AAYA;;;;;;;;;;;GAWG;AACH,MAAM,gBAAgB,GAAG,CAAC,SAAS,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;AAE3D,MAAM,UAAU,mBAAmB,CAAC,MAAc;IAChD,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE;QACxC,IAAI,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;YAAE,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACxE,CAAC,CAAC,CAAC;IACH,OAAO,GAAG,CAAC;AACb,CAAC;AAED,yFAAyF;AACzF,SAAS,eAAe,CAAC,KAAa,EAAE,KAAe;IACrD,OAAO,CACL,GAAG,KAAK,6CAA6C,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM;QAC5G,uFAAuF;QACvF,2GAA2G;QAC3G,gHAAgH,CACjH,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,uBAAuB,CAAC,KAAa,EAAE,OAAe,EAAE,IAAY;IAClF,MAAM,KAAK,GAAG,mBAAmB,CAAC,IAAI,CAAC,CAAC;IACxC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACpC,OAAO;QACL,QAAQ,EAAE,OAAO;QACjB,IAAI,EAAE,qBAAqB;QAC3B,OAAO;QACP,OAAO,EAAE,eAAe,CAAC,KAAK,EAAE,KAAK,CAAC;KACvC,CAAC;AACJ,CAAC;AAED,0FAA0F;AAC1F,MAAM,UAAU,wBAAwB,CAAC,KAAa,EAAE,IAAY;IAClE,MAAM,KAAK,GAAG,mBAAmB,CAAC,IAAI,CAAC,CAAC;IACxC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACpC,OAAO;QACL,QAAQ,EAAE,OAAO;QACjB,IAAI,EAAE,0BAA0B;QAChC,OAAO,EAAE,eAAe,CAAC,KAAK,EAAE,KAAK,CAAC;KACvC,CAAC;AACJ,CAAC","sourcesContent":["/**\n * Git conflict markers left in a document, and the findings they become.\n *\n * Split out of `fleet-context.ts` — the module that owes every READER the\n * check — because the rule itself is a leaf: doctor, validate's three target\n * kinds and coherence all grade marker breaches on text they already hold, and\n * none of them should have to import the whole read index (and the fleet it\n * pulls in behind it) to spell one line rule. The context keeps its\n * `conflictMarkers()` convenience over `readText`; the rule lives here.\n */\nimport type { Finding } from \"./vocabulary/report.js\";\n\n/**\n * The three-way merge left its markers in the file — 1-based line numbers.\n *\n * The rule is `loam doctor`'s, verbatim, and it lives here now because doctor\n * checked exactly one file (`architecture/landscape.likec4`) from a command\n * that gates nothing. The same markers in a living `services/<svc>/spec.md`\n * parse as prose: `loam validate --all` reported `valid: true`, and the next\n * `loam archive` rewrote the requirements section and dropped the `=======`\n * line with it, turning a conflict anyone can see into a document nobody can\n * tell is wrong. For a shared docs repo where a fleet lands through PRs this is\n * the DEFAULT failure, not an edge.\n */\nconst CONFLICT_MARKERS = [\"<<<<<<<\", \"=======\", \">>>>>>>\"];\n\nexport function conflictMarkerLines(source: string): number[] {\n const out: number[] = [];\n source.split(/\\r?\\n/).forEach((line, i) => {\n if (CONFLICT_MARKERS.some((m) => line.startsWith(m))) out.push(i + 1);\n });\n return out;\n}\n\n/** One sentence for the breach, wherever it is found — doctor, validate, either axis. */\nfunction conflictMessage(label: string, lines: number[]): string {\n return (\n `${label} still contains git conflict markers (line${lines.length === 1 ? \"\" : \"s\"} ${lines.join(\", \")}) — ` +\n `both sides of somebody's merge are in the file, so nothing it says is anyone's text. ` +\n `Resolve the conflict before anything else: loam rewrites this document on archive, and a rewrite deletes ` +\n `whichever marker lines fall inside the section it owns — a visible conflict becomes a silently malformed file.`\n );\n}\n\n/**\n * The conflict-marker finding for a requirement document (living spec.md /\n * arch.spec.md, or a feature's delta of one). Null when the text is clean.\n *\n * An error because the document is not valid — nobody wrote what it now says —\n * and because the merge that would consume it is unsafe. It does not carry\n * `gates`: that field is coherence's (issue.ts), and the archive gate has to\n * ask this question itself.\n */\nexport function documentConflictFinding(label: string, subject: string, text: string): Finding | null {\n const lines = conflictMarkerLines(text);\n if (lines.length === 0) return null;\n return {\n severity: \"error\",\n code: \"spec.merge-conflict\",\n subject,\n message: conflictMessage(label, lines),\n };\n}\n\n/** The same breach in the fleet map, where it costs every cross-service check at once. */\nexport function landscapeConflictFinding(label: string, text: string): Finding | null {\n const lines = conflictMarkerLines(text);\n if (lines.length === 0) return null;\n return {\n severity: \"error\",\n code: \"landscape.merge-conflict\",\n message: conflictMessage(label, lines),\n };\n}\n"]}
@@ -0,0 +1,73 @@
1
+ /**
2
+ * What OTHER features in flight claim, and the lazy lookup the checks use.
3
+ *
4
+ * The scan is built on first use and never twice: the common delta claims
5
+ * nothing another feature touches, and the fleet walk is the expensive part of
6
+ * this whole module. `ClaimLookup` is an interface rather than the maps
7
+ * themselves so `./select.ts` cannot see — and so cannot accidentally force —
8
+ * the scan it is deciding whether to need.
9
+ */
10
+ import { existsSync } from "node:fs";
11
+ import { readFile } from "node:fs/promises";
12
+ import {} from "../fleet-context.js";
13
+ import { parseRequirements } from "../document/parse.js";
14
+ import {} from "../document/spec.js";
15
+ import { featureSpecPaths, SPEC_AXES } from "../repo/paths.js";
16
+ import { listFeatures } from "../repo/repo.js";
17
+ import { key, requirementKey } from "./scope.js";
18
+ /**
19
+ * A lookup that runs the fleet scan at most once, on the first question asked.
20
+ * The common case never pays for it.
21
+ */
22
+ export function claimLookup(docsDir, featureId, context) {
23
+ let inFlight = null;
24
+ const ask = async (which, scope, requirement) => {
25
+ // Asked and answered without the scan: the index below holds SERVICE
26
+ // claims only, so every key a capability scope could build begins with a
27
+ // kind no row carries. Without this line a capability-only feature — an
28
+ // analyst's first act, touching no service at all — paid a full fleet walk
29
+ // plus a parse of every active feature's every delta document to reach an
30
+ // answer that is `undefined` by construction. Delete it on the day
31
+ // `activeClaims` indexes the business corpus too, and not before.
32
+ if (scope.kind !== "service")
33
+ return undefined;
34
+ inFlight ??= await activeClaims(docsDir, featureId, context);
35
+ const map = inFlight[which];
36
+ return map.get(key(scope, requirementKey(requirement)))
37
+ ?? map.get(key(scope, `name:${requirement.name}`));
38
+ };
39
+ return {
40
+ added: (scope, requirement) => ask("added", scope, requirement),
41
+ changed: (scope, requirement) => ask("changed", scope, requirement),
42
+ };
43
+ }
44
+ async function activeClaims(docsDir, exclude, context) {
45
+ const added = new Map();
46
+ const changed = new Map();
47
+ for (const feature of await listFeatures(docsDir, {}, context)) {
48
+ if (feature.id === exclude)
49
+ continue;
50
+ for (const service of feature.services) {
51
+ for (const axis of SPEC_AXES) {
52
+ const path = featureSpecPaths(feature.dir, service)[axis.key];
53
+ if (!existsSync(path))
54
+ continue;
55
+ const reqs = context === undefined
56
+ ? parseRequirements(await readFile(path, "utf8"))
57
+ : await context.readRequirements(path);
58
+ for (const r of reqs) {
59
+ const map = r.kind === "ADDED" ? added : r.kind === "MODIFIED" || r.kind === "REMOVED" ? changed : null;
60
+ if (map === null)
61
+ continue;
62
+ for (const identity of new Set([requirementKey(r), `name:${r.name}`])) {
63
+ const k = key({ kind: "service", subject: service, axis }, identity);
64
+ if (!map.has(k))
65
+ map.set(k, feature.id);
66
+ }
67
+ }
68
+ }
69
+ }
70
+ }
71
+ return { added, changed };
72
+ }
73
+ //# sourceMappingURL=claims.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claims.js","sourceRoot":"","sources":["../../../src/core/delta/claims.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * What OTHER features in flight claim, and the lazy lookup the checks use.\n *\n * The scan is built on first use and never twice: the common delta claims\n * nothing another feature touches, and the fleet walk is the expensive part of\n * this whole module. `ClaimLookup` is an interface rather than the maps\n * themselves so `./select.ts` cannot see — and so cannot accidentally force —\n * the scan it is deciding whether to need.\n */\nimport { existsSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport { type FleetContext } from \"../fleet-context.js\";\nimport { parseRequirements } from \"../document/parse.js\";\nimport { type Requirement } from \"../document/spec.js\";\nimport { featureSpecPaths, SPEC_AXES } from \"../repo/paths.js\";\nimport { listFeatures } from \"../repo/repo.js\";\nimport { key, requirementKey, type DeltaScope } from \"./scope.js\";\nimport type { DocsDir } from \"../kernel/ids/dirs.js\";\n\n/** Which other feature claims this requirement, if any — one question per index. */\nexport interface ClaimLookup {\n added(scope: DeltaScope, requirement: Pick<Requirement, \"id\" | \"name\">): Promise<string | undefined>;\n changed(scope: DeltaScope, requirement: Pick<Requirement, \"id\" | \"name\">): Promise<string | undefined>;\n}\n\n/**\n * A lookup that runs the fleet scan at most once, on the first question asked.\n * The common case never pays for it.\n */\nexport function claimLookup(docsDir: DocsDir, featureId: string, context?: FleetContext): ClaimLookup {\n let inFlight: ActiveClaims | null = null;\n const ask = async (\n which: keyof ActiveClaims,\n scope: DeltaScope,\n requirement: Pick<Requirement, \"id\" | \"name\">,\n ): Promise<string | undefined> => {\n // Asked and answered without the scan: the index below holds SERVICE\n // claims only, so every key a capability scope could build begins with a\n // kind no row carries. Without this line a capability-only feature — an\n // analyst's first act, touching no service at all — paid a full fleet walk\n // plus a parse of every active feature's every delta document to reach an\n // answer that is `undefined` by construction. Delete it on the day\n // `activeClaims` indexes the business corpus too, and not before.\n if (scope.kind !== \"service\") return undefined;\n inFlight ??= await activeClaims(docsDir, featureId, context);\n const map = inFlight[which];\n return map.get(key(scope, requirementKey(requirement)))\n ?? map.get(key(scope, `name:${requirement.name}`));\n };\n return {\n added: (scope, requirement) => ask(\"added\", scope, requirement),\n changed: (scope, requirement) => ask(\"changed\", scope, requirement),\n };\n}\n\n/**\n * What other ACTIVE features claim, per (kind, subject, axis, requirement):\n * what they ADD, and — separately — what they CHANGE or REMOVE. The two are\n * separate indexes because they mean opposite things to the reader: an addition\n * elsewhere explains why a MODIFIED target is missing today, a change elsewhere\n * warns that the target is contested. One scan builds both; scanning twice\n * would double the fleet walk for the same bytes.\n *\n * SERVICE CLAIMS ONLY, deliberately. A capability delta's questions therefore\n * always answer `undefined`, which suppresses four cross-feature warnings on\n * the business axis — `delta.added-conflict`, `delta.modified-conflict`,\n * `delta.modified-pending` and `delta.removed-pending`. Never a wrong answer,\n * only a missing warning, and the `kind` in the key is what keeps it missing\n * rather than wrong (a capability and a service sharing a name would otherwise\n * collide). `claimLookup` short-circuits on that kind rather than asking, so\n * the suppression costs nothing as well as saying nothing. Indexing the\n * capability axis too is one more walk in this same loop; it waits for the\n * fleet that reports the ordering, because a warning shipped speculatively is\n * a branch nobody needed.\n */\ninterface ActiveClaims {\n added: Map<string, string>;\n changed: Map<string, string>;\n}\n\nasync function activeClaims(\n docsDir: DocsDir,\n exclude: string,\n context?: FleetContext,\n): Promise<ActiveClaims> {\n const added = new Map<string, string>();\n const changed = new Map<string, string>();\n for (const feature of await listFeatures(docsDir, {}, context)) {\n if (feature.id === exclude) continue;\n for (const service of feature.services) {\n for (const axis of SPEC_AXES) {\n const path = featureSpecPaths(feature.dir, service)[axis.key];\n if (!existsSync(path)) continue;\n const reqs = context === undefined\n ? parseRequirements(await readFile(path, \"utf8\"))\n : await context.readRequirements(path);\n for (const r of reqs) {\n const map = r.kind === \"ADDED\" ? added : r.kind === \"MODIFIED\" || r.kind === \"REMOVED\" ? changed : null;\n if (map === null) continue;\n for (const identity of new Set([requirementKey(r), `name:${r.name}`])) {\n const k = key({ kind: \"service\", subject: service, axis }, identity);\n if (!map.has(k)) map.set(k, feature.id);\n }\n }\n }\n }\n }\n return { added, changed };\n}\n"]}