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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1256) hide show
  1. package/CHANGELOG.md +5992 -82
  2. package/COMPARISON.md +168 -63
  3. package/CONTRIBUTING.md +121 -0
  4. package/MIGRATING-from-OpenSpec.md +238 -55
  5. package/QUICKSTART.md +302 -0
  6. package/README.md +653 -144
  7. package/ROADMAP.md +1035 -0
  8. package/SCHEMA.md +3916 -263
  9. package/SECURITY.md +21 -3
  10. package/WORKFLOW.md +927 -0
  11. package/dist/cli.js +133 -21
  12. package/dist/cli.js.map +1 -1
  13. package/dist/commands/adopt/adopt.js +204 -0
  14. package/dist/commands/adopt/adopt.js.map +1 -0
  15. package/dist/commands/adopt/render.js +309 -0
  16. package/dist/commands/adopt/render.js.map +1 -0
  17. package/dist/commands/archive/archive.js +74 -0
  18. package/dist/commands/archive/archive.js.map +1 -0
  19. package/dist/commands/archive/closing.js +42 -0
  20. package/dist/commands/archive/closing.js.map +1 -0
  21. package/dist/commands/archive/plan/contracts/asyncapi.js +172 -0
  22. package/dist/commands/archive/plan/contracts/asyncapi.js.map +1 -0
  23. package/dist/commands/archive/plan/contracts/consumers.js +56 -0
  24. package/dist/commands/archive/plan/contracts/consumers.js.map +1 -0
  25. package/dist/commands/archive/plan/contracts/openapi.js +193 -0
  26. package/dist/commands/archive/plan/contracts/openapi.js.map +1 -0
  27. package/dist/commands/archive/plan/contracts/verdict-lines.js +103 -0
  28. package/dist/commands/archive/plan/contracts/verdict-lines.js.map +1 -0
  29. package/dist/commands/archive/plan/document/head.js +151 -0
  30. package/dist/commands/archive/plan/document/head.js.map +1 -0
  31. package/dist/commands/archive/plan/document/links.js +284 -0
  32. package/dist/commands/archive/plan/document/links.js.map +1 -0
  33. package/dist/commands/archive/plan/document/run.js +136 -0
  34. package/dist/commands/archive/plan/document/run.js.map +1 -0
  35. package/dist/commands/archive/plan/gate.js +319 -0
  36. package/dist/commands/archive/plan/gate.js.map +1 -0
  37. package/dist/commands/archive/plan/landscape.js +298 -0
  38. package/dist/commands/archive/plan/landscape.js.map +1 -0
  39. package/dist/commands/archive/plan/model/extending.js +85 -0
  40. package/dist/commands/archive/plan/model/extending.js.map +1 -0
  41. package/dist/commands/archive/plan/refusal.js +106 -0
  42. package/dist/commands/archive/plan/refusal.js.map +1 -0
  43. package/dist/commands/archive/plan/specs.js +318 -0
  44. package/dist/commands/archive/plan/specs.js.map +1 -0
  45. package/dist/commands/archive/plan/state.js +30 -0
  46. package/dist/commands/archive/plan/state.js.map +1 -0
  47. package/dist/commands/archive/run.js +355 -0
  48. package/dist/commands/archive/run.js.map +1 -0
  49. package/dist/commands/archive/shipped.js +49 -0
  50. package/dist/commands/archive/shipped.js.map +1 -0
  51. package/dist/commands/context/context.js +166 -0
  52. package/dist/commands/context/context.js.map +1 -0
  53. package/dist/commands/context/print.js +305 -0
  54. package/dist/commands/context/print.js.map +1 -0
  55. package/dist/commands/delta/delta.js +367 -0
  56. package/dist/commands/delta/delta.js.map +1 -0
  57. package/dist/commands/delta/print.js +221 -0
  58. package/dist/commands/delta/print.js.map +1 -0
  59. package/dist/commands/dependencies.js +6 -8
  60. package/dist/commands/dependencies.js.map +1 -1
  61. package/dist/commands/diff/diff.js +86 -0
  62. package/dist/commands/diff/diff.js.map +1 -0
  63. package/dist/commands/diff/print.js +38 -0
  64. package/dist/commands/diff/print.js.map +1 -0
  65. package/dist/commands/doctor.js +65 -5
  66. package/dist/commands/doctor.js.map +1 -1
  67. package/dist/commands/explain/explain.js +227 -0
  68. package/dist/commands/explain/explain.js.map +1 -0
  69. package/dist/commands/explore.js +39 -28
  70. package/dist/commands/explore.js.map +1 -1
  71. package/dist/commands/gate/gate.js +152 -0
  72. package/dist/commands/gate/gate.js.map +1 -0
  73. package/dist/commands/gate/print.js +66 -0
  74. package/dist/commands/gate/print.js.map +1 -0
  75. package/dist/commands/gherkin/commit.js +105 -0
  76. package/dist/commands/gherkin/commit.js.map +1 -0
  77. package/dist/commands/gherkin/gherkin.js +262 -0
  78. package/dist/commands/gherkin/gherkin.js.map +1 -0
  79. package/dist/commands/gherkin/reconcile.js +146 -0
  80. package/dist/commands/gherkin/reconcile.js.map +1 -0
  81. package/dist/commands/gherkin/render.js +77 -0
  82. package/dist/commands/gherkin/render.js.map +1 -0
  83. package/dist/commands/init/example.js +204 -0
  84. package/dist/commands/init/example.js.map +1 -0
  85. package/dist/commands/init/first-hour.js +72 -0
  86. package/dist/commands/init/first-hour.js.map +1 -0
  87. package/dist/commands/{init.js → init/init.js} +142 -71
  88. package/dist/commands/init/init.js.map +1 -0
  89. package/dist/commands/init/mcp.js +131 -0
  90. package/dist/commands/init/mcp.js.map +1 -0
  91. package/dist/commands/init/options.js +78 -0
  92. package/dist/commands/init/options.js.map +1 -0
  93. package/dist/commands/instructions.js +72 -14
  94. package/dist/commands/instructions.js.map +1 -1
  95. package/dist/commands/list/campaign/campaign.js +63 -0
  96. package/dist/commands/list/campaign/campaign.js.map +1 -0
  97. package/dist/commands/list/campaign/owners.js +65 -0
  98. package/dist/commands/list/campaign/owners.js.map +1 -0
  99. package/dist/commands/list/json.js +155 -0
  100. package/dist/commands/list/json.js.map +1 -0
  101. package/dist/commands/list/list.js +358 -0
  102. package/dist/commands/list/list.js.map +1 -0
  103. package/dist/commands/list/print.js +344 -0
  104. package/dist/commands/list/print.js.map +1 -0
  105. package/dist/commands/list/review.js +120 -0
  106. package/dist/commands/list/review.js.map +1 -0
  107. package/dist/commands/list/suites/suites.js +140 -0
  108. package/dist/commands/list/suites/suites.js.map +1 -0
  109. package/dist/commands/list/views.js +108 -0
  110. package/dist/commands/list/views.js.map +1 -0
  111. package/dist/commands/mcp/dispatch.js +238 -0
  112. package/dist/commands/mcp/dispatch.js.map +1 -0
  113. package/dist/commands/mcp/mcp.js +75 -0
  114. package/dist/commands/mcp/mcp.js.map +1 -0
  115. package/dist/commands/mcp/serve.js +55 -0
  116. package/dist/commands/mcp/serve.js.map +1 -0
  117. package/dist/commands/migrate-openspec/materialize/active.js +175 -0
  118. package/dist/commands/migrate-openspec/materialize/active.js.map +1 -0
  119. package/dist/commands/migrate-openspec/materialize/feature.js +41 -0
  120. package/dist/commands/migrate-openspec/materialize/feature.js.map +1 -0
  121. package/dist/commands/migrate-openspec/materialize/living.js +62 -0
  122. package/dist/commands/migrate-openspec/materialize/living.js.map +1 -0
  123. package/dist/commands/migrate-openspec/materialize/stage.js +143 -0
  124. package/dist/commands/migrate-openspec/materialize/stage.js.map +1 -0
  125. package/dist/commands/migrate-openspec/materialize/target.js +219 -0
  126. package/dist/commands/migrate-openspec/materialize/target.js.map +1 -0
  127. package/dist/commands/migrate-openspec/migrate-openspec.js +142 -0
  128. package/dist/commands/migrate-openspec/migrate-openspec.js.map +1 -0
  129. package/dist/commands/migrate-openspec/openspec/decisions.js +86 -0
  130. package/dist/commands/migrate-openspec/openspec/decisions.js.map +1 -0
  131. package/dist/commands/migrate-openspec/openspec/error.js +18 -0
  132. package/dist/commands/migrate-openspec/openspec/error.js.map +1 -0
  133. package/dist/commands/migrate-openspec/openspec/mapping.js +162 -0
  134. package/dist/commands/migrate-openspec/openspec/mapping.js.map +1 -0
  135. package/dist/commands/migrate-openspec/openspec/paths.js +40 -0
  136. package/dist/commands/migrate-openspec/openspec/paths.js.map +1 -0
  137. package/dist/commands/migrate-openspec/openspec/read.js +49 -0
  138. package/dist/commands/migrate-openspec/openspec/read.js.map +1 -0
  139. package/dist/commands/migrate-openspec/print.js +89 -0
  140. package/dist/commands/migrate-openspec/print.js.map +1 -0
  141. package/dist/commands/new/capability-template.js +118 -0
  142. package/dist/commands/new/capability-template.js.map +1 -0
  143. package/dist/commands/new/commit.js +62 -0
  144. package/dist/commands/new/commit.js.map +1 -0
  145. package/dist/commands/new/modifies.js +206 -0
  146. package/dist/commands/new/modifies.js.map +1 -0
  147. package/dist/commands/new/new.js +328 -0
  148. package/dist/commands/new/new.js.map +1 -0
  149. package/dist/commands/new/templates.js +279 -0
  150. package/dist/commands/new/templates.js.map +1 -0
  151. package/dist/commands/open.js +199 -0
  152. package/dist/commands/open.js.map +1 -0
  153. package/dist/commands/policy/format.js +152 -0
  154. package/dist/commands/policy/format.js.map +1 -0
  155. package/dist/commands/{docs-repo-gate.js → policy/gate.js} +38 -11
  156. package/dist/commands/policy/gate.js.map +1 -0
  157. package/dist/commands/rebase/edit.js +106 -0
  158. package/dist/commands/rebase/edit.js.map +1 -0
  159. package/dist/commands/rebase/living.js +185 -0
  160. package/dist/commands/rebase/living.js.map +1 -0
  161. package/dist/commands/rebase/plan.js +245 -0
  162. package/dist/commands/rebase/plan.js.map +1 -0
  163. package/dist/commands/rebase/rebase.js +300 -0
  164. package/dist/commands/rebase/rebase.js.map +1 -0
  165. package/dist/commands/seed/commit.js +221 -0
  166. package/dist/commands/seed/commit.js.map +1 -0
  167. package/dist/commands/seed/plan.js +278 -0
  168. package/dist/commands/seed/plan.js.map +1 -0
  169. package/dist/commands/seed/seed.js +174 -0
  170. package/dist/commands/seed/seed.js.map +1 -0
  171. package/dist/commands/show/feature.js +182 -0
  172. package/dist/commands/show/feature.js.map +1 -0
  173. package/dist/commands/show/introduced.js +157 -0
  174. package/dist/commands/show/introduced.js.map +1 -0
  175. package/dist/commands/show/marks.js +53 -0
  176. package/dist/commands/show/marks.js.map +1 -0
  177. package/dist/commands/show/service.js +239 -0
  178. package/dist/commands/show/service.js.map +1 -0
  179. package/dist/commands/show/show.js +87 -0
  180. package/dist/commands/show/show.js.map +1 -0
  181. package/dist/commands/status/fleet-next.js +90 -0
  182. package/dist/commands/status/fleet-next.js.map +1 -0
  183. package/dist/commands/status/json.js +47 -0
  184. package/dist/commands/status/json.js.map +1 -0
  185. package/dist/commands/status/print.js +209 -0
  186. package/dist/commands/status/print.js.map +1 -0
  187. package/dist/commands/status/status.js +115 -0
  188. package/dist/commands/status/status.js.map +1 -0
  189. package/dist/commands/steps/steps.js +269 -0
  190. package/dist/commands/steps/steps.js.map +1 -0
  191. package/dist/commands/subsystem/edit.js +192 -0
  192. package/dist/commands/subsystem/edit.js.map +1 -0
  193. package/dist/commands/subsystem/move.js +325 -0
  194. package/dist/commands/subsystem/move.js.map +1 -0
  195. package/dist/commands/subsystem/query.js +113 -0
  196. package/dist/commands/subsystem/query.js.map +1 -0
  197. package/dist/commands/subsystem/subsystem.js +98 -0
  198. package/dist/commands/subsystem/subsystem.js.map +1 -0
  199. package/dist/commands/subsystem/sync.js +318 -0
  200. package/dist/commands/subsystem/sync.js.map +1 -0
  201. package/dist/commands/subsystem/txn/exclude.js +132 -0
  202. package/dist/commands/subsystem/txn/exclude.js.map +1 -0
  203. package/dist/commands/subsystem/txn/links.js +128 -0
  204. package/dist/commands/subsystem/txn/links.js.map +1 -0
  205. package/dist/commands/subsystem/txn/report.js +174 -0
  206. package/dist/commands/subsystem/txn/report.js.map +1 -0
  207. package/dist/commands/subsystem/txn/txn.js +196 -0
  208. package/dist/commands/subsystem/txn/txn.js.map +1 -0
  209. package/dist/commands/subsystem/txn/views.js +249 -0
  210. package/dist/commands/subsystem/txn/views.js.map +1 -0
  211. package/dist/commands/tasks/actions.js +107 -0
  212. package/dist/commands/tasks/actions.js.map +1 -0
  213. package/dist/commands/tasks/render.js +253 -0
  214. package/dist/commands/tasks/render.js.map +1 -0
  215. package/dist/commands/tasks/tasks.js +119 -0
  216. package/dist/commands/tasks/tasks.js.map +1 -0
  217. package/dist/commands/unarchive/manifest.js +176 -0
  218. package/dist/commands/unarchive/manifest.js.map +1 -0
  219. package/dist/commands/unarchive/restore.js +254 -0
  220. package/dist/commands/unarchive/restore.js.map +1 -0
  221. package/dist/commands/unarchive/unarchive.js +59 -0
  222. package/dist/commands/unarchive/unarchive.js.map +1 -0
  223. package/dist/commands/validate/arch-coverage.js +245 -0
  224. package/dist/commands/validate/arch-coverage.js.map +1 -0
  225. package/dist/commands/validate/checks/fleet-shape.js +204 -0
  226. package/dist/commands/validate/checks/fleet-shape.js.map +1 -0
  227. package/dist/commands/validate/checks/health-deps.js +58 -0
  228. package/dist/commands/validate/checks/health-deps.js.map +1 -0
  229. package/dist/commands/validate/checks/introduced.js +102 -0
  230. package/dist/commands/validate/checks/introduced.js.map +1 -0
  231. package/dist/commands/validate/checks/requirements.js +264 -0
  232. package/dist/commands/validate/checks/requirements.js.map +1 -0
  233. package/dist/commands/validate/checks/sources.js +85 -0
  234. package/dist/commands/validate/checks/sources.js.map +1 -0
  235. package/dist/commands/validate/coverage/covers-after.js +105 -0
  236. package/dist/commands/validate/coverage/covers-after.js.map +1 -0
  237. package/dist/commands/validate/feature.js +222 -0
  238. package/dist/commands/validate/feature.js.map +1 -0
  239. package/dist/commands/validate/fleet/census.js +93 -0
  240. package/dist/commands/validate/fleet/census.js.map +1 -0
  241. package/dist/commands/validate/fleet/kind-tags.js +39 -0
  242. package/dist/commands/validate/fleet/kind-tags.js.map +1 -0
  243. package/dist/commands/validate/fleet/landscape.js +371 -0
  244. package/dist/commands/validate/fleet/landscape.js.map +1 -0
  245. package/dist/commands/validate/fleet/load.js +118 -0
  246. package/dist/commands/validate/fleet/load.js.map +1 -0
  247. package/dist/commands/validate/fleet/map/attest.js +98 -0
  248. package/dist/commands/validate/fleet/map/attest.js.map +1 -0
  249. package/dist/commands/validate/fleet/map/bindings.js +107 -0
  250. package/dist/commands/validate/fleet/map/bindings.js.map +1 -0
  251. package/dist/commands/validate/fleet/map/consumers.js +244 -0
  252. package/dist/commands/validate/fleet/map/consumers.js.map +1 -0
  253. package/dist/commands/validate/fleet/map/isolation.js +116 -0
  254. package/dist/commands/validate/fleet/map/isolation.js.map +1 -0
  255. package/dist/commands/validate/fleet/map/usecases.js +54 -0
  256. package/dist/commands/validate/fleet/map/usecases.js.map +1 -0
  257. package/dist/commands/validate/fleet/obligations.js +266 -0
  258. package/dist/commands/validate/fleet/obligations.js.map +1 -0
  259. package/dist/commands/validate/fleet/scorecard/adoption.js +102 -0
  260. package/dist/commands/validate/fleet/scorecard/adoption.js.map +1 -0
  261. package/dist/commands/validate/fleet/scorecard/contracts.js +98 -0
  262. package/dist/commands/validate/fleet/scorecard/contracts.js.map +1 -0
  263. package/dist/commands/validate/fleet/scorecard/print.js +71 -0
  264. package/dist/commands/validate/fleet/scorecard/print.js.map +1 -0
  265. package/dist/commands/validate/fleet/scorecard/scorecard.js +162 -0
  266. package/dist/commands/validate/fleet/scorecard/scorecard.js.map +1 -0
  267. package/dist/commands/validate/fleet/usecases/place.js +13 -0
  268. package/dist/commands/validate/fleet/usecases/place.js.map +1 -0
  269. package/dist/commands/validate/fleet/views/fleet-project.js +217 -0
  270. package/dist/commands/validate/fleet/views/fleet-project.js.map +1 -0
  271. package/dist/commands/validate/fleet/views/ids.js +75 -0
  272. package/dist/commands/validate/fleet/views/ids.js.map +1 -0
  273. package/dist/commands/validate/fleet/views/projects.js +278 -0
  274. package/dist/commands/validate/fleet/views/projects.js.map +1 -0
  275. package/dist/commands/validate/fleet/views/root-documents.js +83 -0
  276. package/dist/commands/validate/fleet/views/root-documents.js.map +1 -0
  277. package/dist/commands/validate/fleet/views/stale.js +52 -0
  278. package/dist/commands/validate/fleet/views/stale.js.map +1 -0
  279. package/dist/commands/validate/links/corpus.js +89 -0
  280. package/dist/commands/validate/links/corpus.js.map +1 -0
  281. package/dist/commands/validate/links/glossary.js +75 -0
  282. package/dist/commands/validate/links/glossary.js.map +1 -0
  283. package/dist/commands/validate/render/repeats.js +63 -0
  284. package/dist/commands/validate/render/repeats.js.map +1 -0
  285. package/dist/commands/validate/render/rollups.js +115 -0
  286. package/dist/commands/validate/render/rollups.js.map +1 -0
  287. package/dist/commands/validate/render/text.js +199 -0
  288. package/dist/commands/validate/render/text.js.map +1 -0
  289. package/dist/commands/validate/report.js +145 -0
  290. package/dist/commands/validate/report.js.map +1 -0
  291. package/dist/commands/validate/scope.js +113 -0
  292. package/dist/commands/validate/scope.js.map +1 -0
  293. package/dist/commands/validate/service/api.js +252 -0
  294. package/dist/commands/validate/service/api.js.map +1 -0
  295. package/dist/commands/validate/service/contracts/generated.js +134 -0
  296. package/dist/commands/validate/service/contracts/generated.js.map +1 -0
  297. package/dist/commands/validate/service/events/events.js +241 -0
  298. package/dist/commands/validate/service/events/events.js.map +1 -0
  299. package/dist/commands/validate/service/events/message-producers.js +77 -0
  300. package/dist/commands/validate/service/events/message-producers.js.map +1 -0
  301. package/dist/commands/validate/service/evidence-pins.js +177 -0
  302. package/dist/commands/validate/service/evidence-pins.js.map +1 -0
  303. package/dist/commands/validate/service/model/diverged.js +226 -0
  304. package/dist/commands/validate/service/model/diverged.js.map +1 -0
  305. package/dist/commands/validate/service/model/grade.js +163 -0
  306. package/dist/commands/validate/service/model/grade.js.map +1 -0
  307. package/dist/commands/validate/service/service.js +310 -0
  308. package/dist/commands/validate/service/service.js.map +1 -0
  309. package/dist/commands/validate/service/specs.js +279 -0
  310. package/dist/commands/validate/service/specs.js.map +1 -0
  311. package/dist/commands/validate/service/spine.js +148 -0
  312. package/dist/commands/validate/service/spine.js.map +1 -0
  313. package/dist/commands/validate/service/usecases/tags.js +113 -0
  314. package/dist/commands/validate/service/usecases/tags.js.map +1 -0
  315. package/dist/commands/validate/service/usecases/usecases.js +209 -0
  316. package/dist/commands/validate/service/usecases/usecases.js.map +1 -0
  317. package/dist/commands/validate/validate.js +363 -0
  318. package/dist/commands/validate/validate.js.map +1 -0
  319. package/dist/commands/verify/cross/diff.js +178 -0
  320. package/dist/commands/verify/cross/diff.js.map +1 -0
  321. package/dist/commands/verify/evidence/contract.js +32 -0
  322. package/dist/commands/verify/evidence/contract.js.map +1 -0
  323. package/dist/commands/verify/evidence/pins.js +52 -0
  324. package/dist/commands/verify/evidence/pins.js.map +1 -0
  325. package/dist/commands/verify/evidence/read.js +81 -0
  326. package/dist/commands/verify/evidence/read.js.map +1 -0
  327. package/dist/commands/verify/frozen.js +263 -0
  328. package/dist/commands/verify/frozen.js.map +1 -0
  329. package/dist/commands/verify/record.js +278 -0
  330. package/dist/commands/verify/record.js.map +1 -0
  331. package/dist/commands/verify/report.js +206 -0
  332. package/dist/commands/verify/report.js.map +1 -0
  333. package/dist/commands/verify/results.js +328 -0
  334. package/dist/commands/verify/results.js.map +1 -0
  335. package/dist/commands/verify/verify.js +220 -0
  336. package/dist/commands/verify/verify.js.map +1 -0
  337. package/dist/commands/vouch/contract.js +11 -0
  338. package/dist/commands/vouch/contract.js.map +1 -0
  339. package/dist/commands/vouch/pack/contract.js +2 -0
  340. package/dist/commands/vouch/pack/contract.js.map +1 -0
  341. package/dist/commands/vouch/pack/pack.js +266 -0
  342. package/dist/commands/vouch/pack/pack.js.map +1 -0
  343. package/dist/commands/vouch/pack/print.js +266 -0
  344. package/dist/commands/vouch/pack/print.js.map +1 -0
  345. package/dist/commands/vouch/pack/sections.js +141 -0
  346. package/dist/commands/vouch/pack/sections.js.map +1 -0
  347. package/dist/commands/vouch/prompt/confirm.js +46 -0
  348. package/dist/commands/vouch/prompt/confirm.js.map +1 -0
  349. package/dist/commands/vouch/report.js +101 -0
  350. package/dist/commands/vouch/report.js.map +1 -0
  351. package/dist/commands/vouch/run.js +230 -0
  352. package/dist/commands/vouch/run.js.map +1 -0
  353. package/dist/commands/vouch/sample/plan.js +111 -0
  354. package/dist/commands/vouch/sample/plan.js.map +1 -0
  355. package/dist/commands/vouch/sample/print.js +109 -0
  356. package/dist/commands/vouch/sample/print.js.map +1 -0
  357. package/dist/commands/vouch/vet/verify.js +155 -0
  358. package/dist/commands/vouch/vet/verify.js.map +1 -0
  359. package/dist/commands/vouch/vouch.js +169 -0
  360. package/dist/commands/vouch/vouch.js.map +1 -0
  361. package/dist/core/agent/agents-md/command-map.js +299 -0
  362. package/dist/core/agent/agents-md/command-map.js.map +1 -0
  363. package/dist/core/agent/agents-md/map/explain.js +46 -0
  364. package/dist/core/agent/agents-md/map/explain.js.map +1 -0
  365. package/dist/core/agent/agents-md/map/lenses/context.js +50 -0
  366. package/dist/core/agent/agents-md/map/lenses/context.js.map +1 -0
  367. package/dist/core/agent/agents-md/map/lenses/diff.js +59 -0
  368. package/dist/core/agent/agents-md/map/lenses/diff.js.map +1 -0
  369. package/dist/core/agent/agents-md/map/lenses/gate.js +65 -0
  370. package/dist/core/agent/agents-md/map/lenses/gate.js.map +1 -0
  371. package/dist/core/agent/agents-md/map/mcp.js +44 -0
  372. package/dist/core/agent/agents-md/map/mcp.js.map +1 -0
  373. package/dist/core/agent/agents-md/map/status.js +78 -0
  374. package/dist/core/agent/agents-md/map/status.js.map +1 -0
  375. package/dist/core/agent/agents-md/map/subsystem.js +104 -0
  376. package/dist/core/agent/agents-md/map/subsystem.js.map +1 -0
  377. package/dist/core/agent/agents-md/map/usecases.js +138 -0
  378. package/dist/core/agent/agents-md/map/usecases.js.map +1 -0
  379. package/dist/core/agent/agents-md/refusals.js +273 -0
  380. package/dist/core/agent/agents-md/refusals.js.map +1 -0
  381. package/dist/core/agent/agents-md.js +203 -0
  382. package/dist/core/agent/agents-md.js.map +1 -0
  383. package/dist/core/{agents-stamp.js → agent/agents-stamp.js} +60 -0
  384. package/dist/core/agent/agents-stamp.js.map +1 -0
  385. package/dist/core/agent/contract.js +2 -0
  386. package/dist/core/agent/contract.js.map +1 -0
  387. package/dist/core/agent/protocol.js +193 -0
  388. package/dist/core/agent/protocol.js.map +1 -0
  389. package/dist/core/agent/scaffold.js +254 -0
  390. package/dist/core/agent/scaffold.js.map +1 -0
  391. package/dist/core/agent/support/report.js +144 -0
  392. package/dist/core/agent/support/report.js.map +1 -0
  393. package/dist/core/agent/tools/dialects.js +151 -0
  394. package/dist/core/agent/tools/dialects.js.map +1 -0
  395. package/dist/core/agent/tools/registry.js +193 -0
  396. package/dist/core/agent/tools/registry.js.map +1 -0
  397. package/dist/core/agent/workflows/adopt.js +280 -0
  398. package/dist/core/agent/workflows/adopt.js.map +1 -0
  399. package/dist/core/agent/workflows/check.js +373 -0
  400. package/dist/core/agent/workflows/check.js.map +1 -0
  401. package/dist/core/agent/workflows/closing.js +323 -0
  402. package/dist/core/agent/workflows/closing.js.map +1 -0
  403. package/dist/core/agent/workflows/feature.js +220 -0
  404. package/dist/core/agent/workflows/feature.js.map +1 -0
  405. package/dist/core/agent/workflows/implement.js +188 -0
  406. package/dist/core/agent/workflows/implement.js.map +1 -0
  407. package/dist/core/agent/workflows/reference/authoring.js +311 -0
  408. package/dist/core/agent/workflows/reference/authoring.js.map +1 -0
  409. package/dist/core/agent/workflows/reference/codes.js +67 -0
  410. package/dist/core/agent/workflows/reference/codes.js.map +1 -0
  411. package/dist/core/agent/workflows/reference/done-check.js +210 -0
  412. package/dist/core/agent/workflows/reference/done-check.js.map +1 -0
  413. package/dist/core/agent/workflows/reference/drawing/drawing.js +253 -0
  414. package/dist/core/agent/workflows/reference/drawing/drawing.js.map +1 -0
  415. package/dist/core/agent/workflows/reference/reference.js +19 -0
  416. package/dist/core/agent/workflows/reference/reference.js.map +1 -0
  417. package/dist/core/agent/workflows/reference/spine.js +338 -0
  418. package/dist/core/agent/workflows/reference/spine.js.map +1 -0
  419. package/dist/core/asyncapi/baseline/plan.js +43 -0
  420. package/dist/core/asyncapi/baseline/plan.js.map +1 -0
  421. package/dist/core/asyncapi/baseline/surfaces.js +54 -0
  422. package/dist/core/asyncapi/baseline/surfaces.js.map +1 -0
  423. package/dist/core/asyncapi/depth.js +164 -0
  424. package/dist/core/asyncapi/depth.js.map +1 -0
  425. package/dist/core/asyncapi/digest.js +146 -0
  426. package/dist/core/asyncapi/digest.js.map +1 -0
  427. package/dist/core/asyncapi/merge/components.js +92 -0
  428. package/dist/core/asyncapi/merge/components.js.map +1 -0
  429. package/dist/core/asyncapi/merge/error.js +38 -0
  430. package/dist/core/asyncapi/merge/error.js.map +1 -0
  431. package/dist/core/asyncapi/merge/markers.js +290 -0
  432. package/dist/core/asyncapi/merge/markers.js.map +1 -0
  433. package/dist/core/asyncapi/merge/merge.js +195 -0
  434. package/dist/core/asyncapi/merge/merge.js.map +1 -0
  435. package/dist/core/asyncapi/merge/pin.js +83 -0
  436. package/dist/core/asyncapi/merge/pin.js.map +1 -0
  437. package/dist/core/asyncapi/model.js +11 -0
  438. package/dist/core/asyncapi/model.js.map +1 -0
  439. package/dist/core/asyncapi/producers.js +50 -0
  440. package/dist/core/asyncapi/producers.js.map +1 -0
  441. package/dist/core/asyncapi/read.js +263 -0
  442. package/dist/core/asyncapi/read.js.map +1 -0
  443. package/dist/core/brief/brief.js +285 -0
  444. package/dist/core/brief/brief.js.map +1 -0
  445. package/dist/core/brief/checks.js +385 -0
  446. package/dist/core/brief/checks.js.map +1 -0
  447. package/dist/core/brief/landscape.js +273 -0
  448. package/dist/core/brief/landscape.js.map +1 -0
  449. package/dist/core/brief/map/extend.js +84 -0
  450. package/dist/core/brief/map/extend.js.map +1 -0
  451. package/dist/core/brief/map/owed.js +266 -0
  452. package/dist/core/brief/map/owed.js.map +1 -0
  453. package/dist/core/brief/targets.js +304 -0
  454. package/dist/core/brief/targets.js.map +1 -0
  455. package/dist/core/brief/unchecked.js +58 -0
  456. package/dist/core/brief/unchecked.js.map +1 -0
  457. package/dist/core/c4/arch.js +190 -0
  458. package/dist/core/c4/arch.js.map +1 -0
  459. package/dist/core/c4/direction/direction.js +114 -0
  460. package/dist/core/c4/direction/direction.js.map +1 -0
  461. package/dist/core/c4/likec4.js +243 -0
  462. package/dist/core/c4/likec4.js.map +1 -0
  463. package/dist/core/c4/locate/unlocated.js +150 -0
  464. package/dist/core/c4/locate/unlocated.js.map +1 -0
  465. package/dist/core/c4/parsed/deployment.js +160 -0
  466. package/dist/core/c4/parsed/deployment.js.map +1 -0
  467. package/dist/core/c4/parsed/dynamic-views.js +132 -0
  468. package/dist/core/c4/parsed/dynamic-views.js.map +1 -0
  469. package/dist/core/c4/parsed/specification.js +78 -0
  470. package/dist/core/c4/parsed/specification.js.map +1 -0
  471. package/dist/core/c4/parsed/values.js +110 -0
  472. package/dist/core/c4/parsed/values.js.map +1 -0
  473. package/dist/core/c4/parsed/view-ids.js +113 -0
  474. package/dist/core/c4/parsed/view-ids.js.map +1 -0
  475. package/dist/core/c4/prefetch/fleet.js +134 -0
  476. package/dist/core/c4/prefetch/fleet.js.map +1 -0
  477. package/dist/core/c4/project/architecture.js +161 -0
  478. package/dist/core/c4/project/architecture.js.map +1 -0
  479. package/dist/core/c4/project/batch.js +140 -0
  480. package/dist/core/c4/project/batch.js.map +1 -0
  481. package/dist/core/c4/project/documents.js +89 -0
  482. package/dist/core/c4/project/documents.js.map +1 -0
  483. package/dist/core/c4/project/load.js +219 -0
  484. package/dist/core/c4/project/load.js.map +1 -0
  485. package/dist/core/c4/project/staged.js +277 -0
  486. package/dist/core/c4/project/staged.js.map +1 -0
  487. package/dist/core/c4/resolve/attested.js +0 -0
  488. package/dist/core/c4/resolve/attested.js.map +1 -0
  489. package/dist/core/c4/resolve/external.js +51 -0
  490. package/dist/core/c4/resolve/external.js.map +1 -0
  491. package/dist/core/c4/resolve/service.js +174 -0
  492. package/dist/core/c4/resolve/service.js.map +1 -0
  493. package/dist/core/c4/resolve/steps.js +290 -0
  494. package/dist/core/c4/resolve/steps.js.map +1 -0
  495. package/dist/core/c4/resolve/systems.js +154 -0
  496. package/dist/core/c4/resolve/systems.js.map +1 -0
  497. package/dist/core/c4/root-project/exclude.js +352 -0
  498. package/dist/core/c4/root-project/exclude.js.map +1 -0
  499. package/dist/core/c4/seed/fleet-file.js +201 -0
  500. package/dist/core/c4/seed/fleet-file.js.map +1 -0
  501. package/dist/core/c4/seed/items.js +91 -0
  502. package/dist/core/c4/seed/items.js.map +1 -0
  503. package/dist/core/c4/seed/stamp.js +48 -0
  504. package/dist/core/c4/seed/stamp.js.map +1 -0
  505. package/dist/core/c4/seed/template.js +173 -0
  506. package/dist/core/c4/seed/template.js.map +1 -0
  507. package/dist/core/c4/service-model/created/models.js +96 -0
  508. package/dist/core/c4/service-model/created/models.js.map +1 -0
  509. package/dist/core/c4/service-model/documents.js +47 -0
  510. package/dist/core/c4/service-model/documents.js.map +1 -0
  511. package/dist/core/c4/service-model/fleet/extending.js +82 -0
  512. package/dist/core/c4/service-model/fleet/extending.js.map +1 -0
  513. package/dist/core/c4/service-model/load.js +165 -0
  514. package/dist/core/c4/service-model/load.js.map +1 -0
  515. package/dist/core/c4/service-model/renderer.js +128 -0
  516. package/dist/core/c4/service-model/renderer.js.map +1 -0
  517. package/dist/core/c4/service-model/shape.js +106 -0
  518. package/dist/core/c4/service-model/shape.js.map +1 -0
  519. package/dist/core/c4/service-model/slice.js +188 -0
  520. package/dist/core/c4/service-model/slice.js.map +1 -0
  521. package/dist/core/c4/source-mask.js +369 -0
  522. package/dist/core/c4/source-mask.js.map +1 -0
  523. package/dist/core/c4/source-scan.js +308 -0
  524. package/dist/core/c4/source-scan.js.map +1 -0
  525. package/dist/core/c4/splice/authored-source.js +167 -0
  526. package/dist/core/c4/splice/authored-source.js.map +1 -0
  527. package/dist/core/c4/splice/contract.js +30 -0
  528. package/dist/core/c4/splice/contract.js.map +1 -0
  529. package/dist/core/c4/splice/delta-blocks.js +126 -0
  530. package/dist/core/c4/splice/delta-blocks.js.map +1 -0
  531. package/dist/core/c4/splice/identity/declared.js +87 -0
  532. package/dist/core/c4/splice/identity/declared.js.map +1 -0
  533. package/dist/core/c4/splice/identity/edges.js +73 -0
  534. package/dist/core/c4/splice/identity/edges.js.map +1 -0
  535. package/dist/core/c4/splice/identity/existing.js +80 -0
  536. package/dist/core/c4/splice/identity/existing.js.map +1 -0
  537. package/dist/core/c4/splice/identity/interior.js +80 -0
  538. package/dist/core/c4/splice/identity/interior.js.map +1 -0
  539. package/dist/core/c4/splice/identity/owner.js +50 -0
  540. package/dist/core/c4/splice/identity/owner.js.map +1 -0
  541. package/dist/core/c4/splice/landscape-merge.js +337 -0
  542. package/dist/core/c4/splice/landscape-merge.js.map +1 -0
  543. package/dist/core/c4/splice/model/merge.js +151 -0
  544. package/dist/core/c4/splice/model/merge.js.map +1 -0
  545. package/dist/core/c4/splice/placement.js +298 -0
  546. package/dist/core/c4/splice/placement.js.map +1 -0
  547. package/dist/core/c4/splice/text/spot.js +131 -0
  548. package/dist/core/c4/splice/text/spot.js.map +1 -0
  549. package/dist/core/c4/workspace.js +166 -0
  550. package/dist/core/c4/workspace.js.map +1 -0
  551. package/dist/core/capabilities/authoring/notes.js +141 -0
  552. package/dist/core/capabilities/authoring/notes.js.map +1 -0
  553. package/dist/core/capabilities/capabilities.js +124 -0
  554. package/dist/core/capabilities/capabilities.js.map +1 -0
  555. package/dist/core/capabilities/delta/doc.js +47 -0
  556. package/dist/core/capabilities/delta/doc.js.map +1 -0
  557. package/dist/core/capabilities/delta/overlay.js +129 -0
  558. package/dist/core/capabilities/delta/overlay.js.map +1 -0
  559. package/dist/core/capabilities/delta/summary.js +57 -0
  560. package/dist/core/capabilities/delta/summary.js.map +1 -0
  561. package/dist/core/capabilities/delta/tree.js +43 -0
  562. package/dist/core/capabilities/delta/tree.js.map +1 -0
  563. package/dist/core/capabilities/delta/uncovered.js +222 -0
  564. package/dist/core/capabilities/delta/uncovered.js.map +1 -0
  565. package/dist/core/capabilities/findings.js +338 -0
  566. package/dist/core/capabilities/findings.js.map +1 -0
  567. package/dist/core/capabilities/realizes/findings.js +174 -0
  568. package/dist/core/capabilities/realizes/findings.js.map +1 -0
  569. package/dist/core/capabilities/realizes/join.js +123 -0
  570. package/dist/core/capabilities/realizes/join.js.map +1 -0
  571. package/dist/core/capabilities/rollup.js +205 -0
  572. package/dist/core/capabilities/rollup.js.map +1 -0
  573. package/dist/core/capabilities/tree.js +104 -0
  574. package/dist/core/capabilities/tree.js.map +1 -0
  575. package/dist/core/capabilities/usecase-join.js +267 -0
  576. package/dist/core/capabilities/usecase-join.js.map +1 -0
  577. package/dist/core/coherence/authoring/scaffold.js +185 -0
  578. package/dist/core/coherence/authoring/scaffold.js.map +1 -0
  579. package/dist/core/coherence/authoring/sentinels.js +75 -0
  580. package/dist/core/coherence/authoring/sentinels.js.map +1 -0
  581. package/dist/core/coherence/calls/called.js +52 -0
  582. package/dist/core/coherence/calls/called.js.map +1 -0
  583. package/dist/core/coherence/coherence.js +332 -0
  584. package/dist/core/coherence/coherence.js.map +1 -0
  585. package/dist/core/coherence/consumed/operations.js +70 -0
  586. package/dist/core/coherence/consumed/operations.js.map +1 -0
  587. package/dist/core/coherence/consumed/refusal.js +38 -0
  588. package/dist/core/coherence/consumed/refusal.js.map +1 -0
  589. package/dist/core/coherence/covers/health.js +85 -0
  590. package/dist/core/coherence/covers/health.js.map +1 -0
  591. package/dist/core/coherence/declared.js +295 -0
  592. package/dist/core/coherence/declared.js.map +1 -0
  593. package/dist/core/coherence/events/declared.js +191 -0
  594. package/dist/core/coherence/events/declared.js.map +1 -0
  595. package/dist/core/coherence/events/events.js +335 -0
  596. package/dist/core/coherence/events/events.js.map +1 -0
  597. package/dist/core/coherence/events/grades.js +189 -0
  598. package/dist/core/coherence/events/grades.js.map +1 -0
  599. package/dist/core/coherence/events/lookups.js +63 -0
  600. package/dist/core/coherence/events/lookups.js.map +1 -0
  601. package/dist/core/coherence/events/produced.js +100 -0
  602. package/dist/core/coherence/events/produced.js.map +1 -0
  603. package/dist/core/coherence/living.js +198 -0
  604. package/dist/core/coherence/living.js.map +1 -0
  605. package/dist/core/coherence/lookups.js +95 -0
  606. package/dist/core/coherence/lookups.js.map +1 -0
  607. package/dist/core/coherence/pending.js +39 -0
  608. package/dist/core/coherence/pending.js.map +1 -0
  609. package/dist/core/coherence/retired/archived.js +285 -0
  610. package/dist/core/coherence/retired/archived.js.map +1 -0
  611. package/dist/core/coherence/retired/event-pair.js +62 -0
  612. package/dist/core/coherence/retired/event-pair.js.map +1 -0
  613. package/dist/core/coherence/retired/merged.js +79 -0
  614. package/dist/core/coherence/retired/merged.js.map +1 -0
  615. package/dist/core/coherence/retired/retirement.js +49 -0
  616. package/dist/core/coherence/retired/retirement.js.map +1 -0
  617. package/dist/core/coherence/retired/revival/arrivals.js +131 -0
  618. package/dist/core/coherence/retired/revival/arrivals.js.map +1 -0
  619. package/dist/core/coherence/retired/revival/revived.js +297 -0
  620. package/dist/core/coherence/retired/revival/revived.js.map +1 -0
  621. package/dist/core/conflict-markers.js +60 -0
  622. package/dist/core/conflict-markers.js.map +1 -0
  623. package/dist/core/consumers/after.js +113 -0
  624. package/dist/core/consumers/after.js.map +1 -0
  625. package/dist/core/consumers/consumers.js +296 -0
  626. package/dist/core/consumers/consumers.js.map +1 -0
  627. package/dist/core/consumers/current.js +211 -0
  628. package/dist/core/consumers/current.js.map +1 -0
  629. package/dist/core/consumers/scan.js +46 -0
  630. package/dist/core/consumers/scan.js.map +1 -0
  631. package/dist/core/consumers/state.js +27 -0
  632. package/dist/core/consumers/state.js.map +1 -0
  633. package/dist/core/delta/claims.js +73 -0
  634. package/dist/core/delta/claims.js.map +1 -0
  635. package/dist/core/delta/delta.js +341 -0
  636. package/dist/core/delta/delta.js.map +1 -0
  637. package/dist/core/delta/document.js +177 -0
  638. package/dist/core/delta/document.js.map +1 -0
  639. package/dist/core/delta/scope.js +48 -0
  640. package/dist/core/delta/scope.js.map +1 -0
  641. package/dist/core/delta/select.js +237 -0
  642. package/dist/core/delta/select.js.map +1 -0
  643. package/dist/core/dependencies/dependencies.js +141 -0
  644. package/dist/core/dependencies/dependencies.js.map +1 -0
  645. package/dist/core/dependencies/facts.js +165 -0
  646. package/dist/core/dependencies/facts.js.map +1 -0
  647. package/dist/core/dependencies/fanin.js +88 -0
  648. package/dist/core/dependencies/fanin.js.map +1 -0
  649. package/dist/core/dependencies/graph.js +106 -0
  650. package/dist/core/dependencies/graph.js.map +1 -0
  651. package/dist/core/deployment/delta.js +191 -0
  652. package/dist/core/deployment/delta.js.map +1 -0
  653. package/dist/core/deployment/objects.js +145 -0
  654. package/dist/core/deployment/objects.js.map +1 -0
  655. package/dist/core/diff/base-git.js +230 -0
  656. package/dist/core/diff/base-git.js.map +1 -0
  657. package/dist/core/diff/base-state.js +237 -0
  658. package/dist/core/diff/base-state.js.map +1 -0
  659. package/dist/core/diff/joins.js +136 -0
  660. package/dist/core/diff/joins.js.map +1 -0
  661. package/dist/core/diff/scope/changed-paths.js +204 -0
  662. package/dist/core/diff/scope/changed-paths.js.map +1 -0
  663. package/dist/core/diff/scope/edges.js +82 -0
  664. package/dist/core/diff/scope/edges.js.map +1 -0
  665. package/dist/core/diff/semantic.js +312 -0
  666. package/dist/core/diff/semantic.js.map +1 -0
  667. package/dist/core/docs.js +37 -85
  668. package/dist/core/docs.js.map +1 -1
  669. package/dist/core/doctor/agents.js +238 -0
  670. package/dist/core/doctor/agents.js.map +1 -0
  671. package/dist/core/doctor/config.js +139 -0
  672. package/dist/core/doctor/config.js.map +1 -0
  673. package/dist/core/doctor/doctor.js +355 -0
  674. package/dist/core/doctor/doctor.js.map +1 -0
  675. package/dist/core/doctor/report.js +13 -0
  676. package/dist/core/doctor/report.js.map +1 -0
  677. package/dist/core/doctor/reports/scan.js +242 -0
  678. package/dist/core/doctor/reports/scan.js.map +1 -0
  679. package/dist/core/doctor/residue.js +110 -0
  680. package/dist/core/doctor/residue.js.map +1 -0
  681. package/dist/core/document/apply.js +224 -0
  682. package/dist/core/document/apply.js.map +1 -0
  683. package/dist/core/{frontmatter.js → document/frontmatter.js} +103 -2
  684. package/dist/core/document/frontmatter.js.map +1 -0
  685. package/dist/core/document/grammar/directives.js +143 -0
  686. package/dist/core/document/grammar/directives.js.map +1 -0
  687. package/dist/core/document/parse.js +286 -0
  688. package/dist/core/document/parse.js.map +1 -0
  689. package/dist/core/document/scenarios.js +238 -0
  690. package/dist/core/document/scenarios.js.map +1 -0
  691. package/dist/core/document/spec.js +234 -0
  692. package/dist/core/document/spec.js.map +1 -0
  693. package/dist/core/{config.js → envelope/config.js} +89 -18
  694. package/dist/core/envelope/config.js.map +1 -0
  695. package/dist/core/envelope/json.js +209 -0
  696. package/dist/core/envelope/json.js.map +1 -0
  697. package/dist/core/{version.js → envelope/version.js} +3 -3
  698. package/dist/core/envelope/version.js.map +1 -0
  699. package/dist/core/explain/families.js +180 -0
  700. package/dist/core/explain/families.js.map +1 -0
  701. package/dist/core/explain/fix-tables.js +178 -0
  702. package/dist/core/explain/fix-tables.js.map +1 -0
  703. package/dist/core/explain/lookup.js +194 -0
  704. package/dist/core/explain/lookup.js.map +1 -0
  705. package/dist/core/explain/refusals.js +49 -0
  706. package/dist/core/explain/refusals.js.map +1 -0
  707. package/dist/core/explain/terms/documents.js +227 -0
  708. package/dist/core/explain/terms/documents.js.map +1 -0
  709. package/dist/core/explain/terms/done-check.js +144 -0
  710. package/dist/core/explain/terms/done-check.js.map +1 -0
  711. package/dist/core/explain/terms/entry.js +14 -0
  712. package/dist/core/explain/terms/entry.js.map +1 -0
  713. package/dist/core/explain/terms/stages.js +71 -0
  714. package/dist/core/explain/terms/stages.js.map +1 -0
  715. package/dist/core/explain/terms/tasks.js +97 -0
  716. package/dist/core/explain/terms/tasks.js.map +1 -0
  717. package/dist/core/explain/terms.js +103 -0
  718. package/dist/core/explain/terms.js.map +1 -0
  719. package/dist/core/explore/describe.js +105 -0
  720. package/dist/core/explore/describe.js.map +1 -0
  721. package/dist/core/explore/explore.js +204 -0
  722. package/dist/core/explore/explore.js.map +1 -0
  723. package/dist/core/fleet-context.js +174 -146
  724. package/dist/core/fleet-context.js.map +1 -1
  725. package/dist/core/gate/checks.js +208 -0
  726. package/dist/core/gate/checks.js.map +1 -0
  727. package/dist/core/gate/partners.js +246 -0
  728. package/dist/core/gate/partners.js.map +1 -0
  729. package/dist/core/gate/report.js +47 -0
  730. package/dist/core/gate/report.js.map +1 -0
  731. package/dist/core/gate/verification.js +176 -0
  732. package/dist/core/gate/verification.js.map +1 -0
  733. package/dist/core/gherkin/digest.js +60 -0
  734. package/dist/core/gherkin/digest.js.map +1 -0
  735. package/dist/core/gherkin/emit.js +177 -0
  736. package/dist/core/gherkin/emit.js.map +1 -0
  737. package/dist/core/gherkin/read.js +76 -0
  738. package/dist/core/gherkin/read.js.map +1 -0
  739. package/dist/core/gherkin/stale.js +210 -0
  740. package/dist/core/gherkin/stale.js.map +1 -0
  741. package/dist/core/gherkin/stamp.js +77 -0
  742. package/dist/core/gherkin/stamp.js.map +1 -0
  743. package/dist/core/gherkin/steps/catalogue.js +154 -0
  744. package/dist/core/gherkin/steps/catalogue.js.map +1 -0
  745. package/dist/core/gherkin/steps/inventory.js +98 -0
  746. package/dist/core/gherkin/steps/inventory.js.map +1 -0
  747. package/dist/core/gherkin/steps/phrase.js +72 -0
  748. package/dist/core/gherkin/steps/phrase.js.map +1 -0
  749. package/dist/core/glossary/delta.js +109 -0
  750. package/dist/core/glossary/delta.js.map +1 -0
  751. package/dist/core/glossary/tree.js +73 -0
  752. package/dist/core/glossary/tree.js.map +1 -0
  753. package/dist/core/{concurrency.js → kernel/concurrency.js} +19 -0
  754. package/dist/core/kernel/concurrency.js.map +1 -0
  755. package/dist/core/{document-bytes.js → kernel/document-bytes.js} +1 -1
  756. package/dist/core/kernel/document-bytes.js.map +1 -0
  757. package/dist/core/kernel/fences.js +42 -0
  758. package/dist/core/kernel/fences.js.map +1 -0
  759. package/dist/core/kernel/ids/capability.js +72 -0
  760. package/dist/core/kernel/ids/capability.js.map +1 -0
  761. package/dist/core/kernel/ids/dirs.js +33 -0
  762. package/dist/core/kernel/ids/dirs.js.map +1 -0
  763. package/dist/core/kernel/ids/feature.js +75 -0
  764. package/dist/core/kernel/ids/feature.js.map +1 -0
  765. package/dist/core/kernel/ids/fqn/ancestors.js +65 -0
  766. package/dist/core/kernel/ids/fqn/ancestors.js.map +1 -0
  767. package/dist/core/kernel/ids/service.js +156 -0
  768. package/dist/core/kernel/ids/service.js.map +1 -0
  769. package/dist/core/kernel/ids/subsystem.js +63 -0
  770. package/dist/core/kernel/ids/subsystem.js.map +1 -0
  771. package/dist/core/{path-safety.js → kernel/path-safety.js} +56 -4
  772. package/dist/core/kernel/path-safety.js.map +1 -0
  773. package/dist/core/{records.js → kernel/records.js} +11 -0
  774. package/dist/core/kernel/records.js.map +1 -0
  775. package/dist/core/links/backlinks.js +66 -0
  776. package/dist/core/links/backlinks.js.map +1 -0
  777. package/dist/core/links/case.js +74 -0
  778. package/dist/core/links/case.js.map +1 -0
  779. package/dist/core/links/corpus.js +118 -0
  780. package/dist/core/links/corpus.js.map +1 -0
  781. package/dist/core/links/findings.js +110 -0
  782. package/dist/core/links/findings.js.map +1 -0
  783. package/dist/core/links/parse.js +265 -0
  784. package/dist/core/links/parse.js.map +1 -0
  785. package/dist/core/mcp/argv.js +212 -0
  786. package/dist/core/mcp/argv.js.map +1 -0
  787. package/dist/core/mcp/author-tools.js +73 -0
  788. package/dist/core/mcp/author-tools.js.map +1 -0
  789. package/dist/core/mcp/framing.js +46 -0
  790. package/dist/core/mcp/framing.js.map +1 -0
  791. package/dist/core/mcp/protocol.js +280 -0
  792. package/dist/core/mcp/protocol.js.map +1 -0
  793. package/dist/core/mcp/tools.js +324 -0
  794. package/dist/core/mcp/tools.js.map +1 -0
  795. package/dist/core/obligations/obligations.js +106 -0
  796. package/dist/core/obligations/obligations.js.map +1 -0
  797. package/dist/core/openapi/baseline/gate.js +207 -0
  798. package/dist/core/openapi/baseline/gate.js.map +1 -0
  799. package/dist/core/openapi/baseline/plan.js +142 -0
  800. package/dist/core/openapi/baseline/plan.js.map +1 -0
  801. package/dist/core/openapi/baseline/record.js +174 -0
  802. package/dist/core/openapi/baseline/record.js.map +1 -0
  803. package/dist/core/openapi/contract-text.js +33 -0
  804. package/dist/core/openapi/contract-text.js.map +1 -0
  805. package/dist/core/openapi/contract-tree.js +301 -0
  806. package/dist/core/openapi/contract-tree.js.map +1 -0
  807. package/dist/core/openapi/depth.js +136 -0
  808. package/dist/core/openapi/depth.js.map +1 -0
  809. package/dist/core/openapi/digest.js +239 -0
  810. package/dist/core/openapi/digest.js.map +1 -0
  811. package/dist/core/{openapi.js → openapi/doc.js} +54 -108
  812. package/dist/core/openapi/doc.js.map +1 -0
  813. package/dist/core/openapi/merge/components.js +199 -0
  814. package/dist/core/openapi/merge/components.js.map +1 -0
  815. package/dist/core/openapi/merge/error.js +16 -0
  816. package/dist/core/openapi/merge/error.js.map +1 -0
  817. package/dist/core/openapi/merge/markers.js +204 -0
  818. package/dist/core/openapi/merge/markers.js.map +1 -0
  819. package/dist/core/openapi/merge/merge.js +232 -0
  820. package/dist/core/openapi/merge/merge.js.map +1 -0
  821. package/dist/core/openapi/merge/pin.js +110 -0
  822. package/dist/core/openapi/merge/pin.js.map +1 -0
  823. package/dist/core/openspec/decide/capabilities.js +244 -0
  824. package/dist/core/openspec/decide/capabilities.js.map +1 -0
  825. package/dist/core/openspec/decide/dispositions.js +63 -0
  826. package/dist/core/openspec/decide/dispositions.js.map +1 -0
  827. package/dist/core/openspec/decide/renames.js +179 -0
  828. package/dist/core/openspec/decide/renames.js.map +1 -0
  829. package/dist/core/openspec/decide/verdict.js +84 -0
  830. package/dist/core/openspec/decide/verdict.js.map +1 -0
  831. package/dist/core/openspec/inventory.js +220 -0
  832. package/dist/core/openspec/inventory.js.map +1 -0
  833. package/dist/core/openspec/model/mapping.js +78 -0
  834. package/dist/core/openspec/model/mapping.js.map +1 -0
  835. package/dist/core/openspec/model/model.js +70 -0
  836. package/dist/core/openspec/model/model.js.map +1 -0
  837. package/dist/core/openspec/scan/changes.js +241 -0
  838. package/dist/core/openspec/scan/changes.js.map +1 -0
  839. package/dist/core/openspec/scan/config.js +191 -0
  840. package/dist/core/openspec/scan/config.js.map +1 -0
  841. package/dist/core/openspec/scan/shape.js +304 -0
  842. package/dist/core/openspec/scan/shape.js.map +1 -0
  843. package/dist/core/openspec/scan/walk.js +116 -0
  844. package/dist/core/openspec/scan/walk.js.map +1 -0
  845. package/dist/core/openspec/scan/workspace.js +71 -0
  846. package/dist/core/openspec/scan/workspace.js.map +1 -0
  847. package/dist/core/owners/codeowners.js +141 -0
  848. package/dist/core/owners/codeowners.js.map +1 -0
  849. package/dist/core/pack/features.js +120 -0
  850. package/dist/core/pack/features.js.map +1 -0
  851. package/dist/core/pack/joins.js +112 -0
  852. package/dist/core/pack/joins.js.map +1 -0
  853. package/dist/core/pack/living.js +157 -0
  854. package/dist/core/pack/living.js.map +1 -0
  855. package/dist/core/pack/pack.js +120 -0
  856. package/dist/core/pack/pack.js.map +1 -0
  857. package/dist/core/permissions/permissions.js +87 -0
  858. package/dist/core/permissions/permissions.js.map +1 -0
  859. package/dist/core/projection/api.js +84 -0
  860. package/dist/core/projection/api.js.map +1 -0
  861. package/dist/core/projection/arch-slice.js +63 -0
  862. package/dist/core/projection/arch-slice.js.map +1 -0
  863. package/dist/core/projection/events.js +34 -0
  864. package/dist/core/projection/events.js.map +1 -0
  865. package/dist/core/projection/introduced.js +14 -0
  866. package/dist/core/projection/introduced.js.map +1 -0
  867. package/dist/core/provenance/findings.js +244 -0
  868. package/dist/core/provenance/findings.js.map +1 -0
  869. package/dist/core/provenance/git.js +201 -0
  870. package/dist/core/provenance/git.js.map +1 -0
  871. package/dist/core/provenance/gitq/moves.js +139 -0
  872. package/dist/core/provenance/gitq/moves.js.map +1 -0
  873. package/dist/core/provenance/gitq/vouched-ancestor.js +179 -0
  874. package/dist/core/provenance/gitq/vouched-ancestor.js.map +1 -0
  875. package/dist/core/provenance/sample/scope.js +238 -0
  876. package/dist/core/provenance/sample/scope.js.map +1 -0
  877. package/dist/core/provenance/sample/sections.js +61 -0
  878. package/dist/core/provenance/sample/sections.js.map +1 -0
  879. package/dist/core/provenance/sources.js +280 -0
  880. package/dist/core/provenance/sources.js.map +1 -0
  881. package/dist/core/provenance/stamp.js +220 -0
  882. package/dist/core/provenance/stamp.js.map +1 -0
  883. package/dist/core/provenance/walk.js +157 -0
  884. package/dist/core/provenance/walk.js.map +1 -0
  885. package/dist/core/repo/authored/paths.js +210 -0
  886. package/dist/core/repo/authored/paths.js.map +1 -0
  887. package/dist/core/repo/entries.js +126 -0
  888. package/dist/core/repo/entries.js.map +1 -0
  889. package/dist/core/repo/paths.js +322 -0
  890. package/dist/core/repo/paths.js.map +1 -0
  891. package/dist/core/repo/repo.js +308 -0
  892. package/dist/core/repo/repo.js.map +1 -0
  893. package/dist/core/repo/service-target.js +153 -0
  894. package/dist/core/repo/service-target.js.map +1 -0
  895. package/dist/core/repo/state.js +58 -0
  896. package/dist/core/repo/state.js.map +1 -0
  897. package/dist/core/repo/tree/find.js +61 -0
  898. package/dist/core/repo/tree/find.js.map +1 -0
  899. package/dist/core/repo/tree/fs.js +90 -0
  900. package/dist/core/repo/tree/fs.js.map +1 -0
  901. package/dist/core/repo/tree/marker.js +61 -0
  902. package/dist/core/repo/tree/marker.js.map +1 -0
  903. package/dist/core/repo/tree/render/body.js +258 -0
  904. package/dist/core/repo/tree/render/body.js.map +1 -0
  905. package/dist/core/repo/tree/render/projects.js +182 -0
  906. package/dist/core/repo/tree/render/projects.js.map +1 -0
  907. package/dist/core/repo/tree/render/service/header.js +125 -0
  908. package/dist/core/repo/tree/render/service/header.js.map +1 -0
  909. package/dist/core/repo/tree/render/service/peers.js +28 -0
  910. package/dist/core/repo/tree/render/service/peers.js.map +1 -0
  911. package/dist/core/repo/tree/render/service/view-id.js +67 -0
  912. package/dist/core/repo/tree/render/service/view-id.js.map +1 -0
  913. package/dist/core/repo/tree/render/service/views.js +78 -0
  914. package/dist/core/repo/tree/render/service/views.js.map +1 -0
  915. package/dist/core/repo/tree/render/stale.js +42 -0
  916. package/dist/core/repo/tree/render/stale.js.map +1 -0
  917. package/dist/core/repo/tree/render/text.js +84 -0
  918. package/dist/core/repo/tree/render/text.js.map +1 -0
  919. package/dist/core/repo/tree/render/views.js +293 -0
  920. package/dist/core/repo/tree/render/views.js.map +1 -0
  921. package/dist/core/repo/tree/walk.js +255 -0
  922. package/dist/core/repo/tree/walk.js.map +1 -0
  923. package/dist/core/results.js +146 -14
  924. package/dist/core/results.js.map +1 -1
  925. package/dist/core/scaffold/landscape.js +239 -0
  926. package/dist/core/scaffold/landscape.js.map +1 -0
  927. package/dist/core/scaffold/legacy.js +271 -0
  928. package/dist/core/scaffold/legacy.js.map +1 -0
  929. package/dist/core/scaffold/readme.js +84 -0
  930. package/dist/core/scaffold/readme.js.map +1 -0
  931. package/dist/core/staging/commit.js +252 -0
  932. package/dist/core/staging/commit.js.map +1 -0
  933. package/dist/core/staging/interrupted.js +96 -0
  934. package/dist/core/staging/interrupted.js.map +1 -0
  935. package/dist/core/staging/lock.js +268 -0
  936. package/dist/core/staging/lock.js.map +1 -0
  937. package/dist/core/staging/recovery/finding.js +35 -0
  938. package/dist/core/staging/recovery/finding.js.map +1 -0
  939. package/dist/core/staging/recovery/intent.js +95 -0
  940. package/dist/core/staging/recovery/intent.js.map +1 -0
  941. package/dist/core/staging/recovery/recover.js +204 -0
  942. package/dist/core/staging/recovery/recover.js.map +1 -0
  943. package/dist/core/staging/recovery/residue.js +62 -0
  944. package/dist/core/staging/recovery/residue.js.map +1 -0
  945. package/dist/core/staging/snapshot/manifest.js +188 -0
  946. package/dist/core/staging/snapshot/manifest.js.map +1 -0
  947. package/dist/core/staging/snapshot/snapshot.js +196 -0
  948. package/dist/core/staging/snapshot/snapshot.js.map +1 -0
  949. package/dist/core/staging/txn/forward.js +181 -0
  950. package/dist/core/staging/txn/forward.js.map +1 -0
  951. package/dist/core/staging/txn/journal.js +139 -0
  952. package/dist/core/staging/txn/journal.js.map +1 -0
  953. package/dist/core/staging/txn/transaction.js +75 -0
  954. package/dist/core/staging/txn/transaction.js.map +1 -0
  955. package/dist/core/staging/writes.js +113 -0
  956. package/dist/core/staging/writes.js.map +1 -0
  957. package/dist/core/status/actions/execution.js +60 -0
  958. package/dist/core/status/actions/execution.js.map +1 -0
  959. package/dist/core/status/contracts.js +126 -0
  960. package/dist/core/status/contracts.js.map +1 -0
  961. package/dist/core/status/feature/artifacts.js +196 -0
  962. package/dist/core/status/feature/artifacts.js.map +1 -0
  963. package/dist/core/status/feature/feature.js +214 -0
  964. package/dist/core/status/feature/feature.js.map +1 -0
  965. package/dist/core/status/feature/next.js +163 -0
  966. package/dist/core/status/feature/next.js.map +1 -0
  967. package/dist/core/status/feature/state.js +21 -0
  968. package/dist/core/status/feature/state.js.map +1 -0
  969. package/dist/core/status/feature/words.js +96 -0
  970. package/dist/core/status/feature/words.js.map +1 -0
  971. package/dist/core/status/fleet/fleet.js +216 -0
  972. package/dist/core/status/fleet/fleet.js.map +1 -0
  973. package/dist/core/status/fleet/next.js +302 -0
  974. package/dist/core/status/fleet/next.js.map +1 -0
  975. package/dist/core/status/interrupted.js +97 -0
  976. package/dist/core/status/interrupted.js.map +1 -0
  977. package/dist/core/status/report.js +31 -0
  978. package/dist/core/status/report.js.map +1 -0
  979. package/dist/core/status/scan.js +41 -0
  980. package/dist/core/status/scan.js.map +1 -0
  981. package/dist/core/status/verification.js +216 -0
  982. package/dist/core/status/verification.js.map +1 -0
  983. package/dist/core/tasks/packet.js +199 -0
  984. package/dist/core/tasks/packet.js.map +1 -0
  985. package/dist/core/tasks/record.js +43 -0
  986. package/dist/core/tasks/record.js.map +1 -0
  987. package/dist/core/tasks/sources.js +181 -0
  988. package/dist/core/tasks/sources.js.map +1 -0
  989. package/dist/core/tasks/stamps.js +76 -0
  990. package/dist/core/tasks/stamps.js.map +1 -0
  991. package/dist/core/tasks/unit.js +0 -0
  992. package/dist/core/tasks/unit.js.map +1 -0
  993. package/dist/core/usecases/capability.js +166 -0
  994. package/dist/core/usecases/capability.js.map +1 -0
  995. package/dist/core/usecases/delta/claims.js +140 -0
  996. package/dist/core/usecases/delta/claims.js.map +1 -0
  997. package/dist/core/usecases/delta/flows.js +101 -0
  998. package/dist/core/usecases/delta/flows.js.map +1 -0
  999. package/dist/core/usecases/delta/modified.js +315 -0
  1000. package/dist/core/usecases/delta/modified.js.map +1 -0
  1001. package/dist/core/usecases/delta/overlay.js +76 -0
  1002. package/dist/core/usecases/delta/overlay.js.map +1 -0
  1003. package/dist/core/usecases/fleet.js +296 -0
  1004. package/dist/core/usecases/fleet.js.map +1 -0
  1005. package/dist/core/usecases/grade/capability-tag.js +93 -0
  1006. package/dist/core/usecases/grade/capability-tag.js.map +1 -0
  1007. package/dist/core/usecases/grade/feature.js +88 -0
  1008. package/dist/core/usecases/grade/feature.js.map +1 -0
  1009. package/dist/core/usecases/grade/requirement-tag.js +94 -0
  1010. package/dist/core/usecases/grade/requirement-tag.js.map +1 -0
  1011. package/dist/core/usecases/grade/steps.js +266 -0
  1012. package/dist/core/usecases/grade/steps.js.map +1 -0
  1013. package/dist/core/usecases/grade/usecases.js +112 -0
  1014. package/dist/core/usecases/grade/usecases.js.map +1 -0
  1015. package/dist/core/usecases/operations.js +123 -0
  1016. package/dist/core/usecases/operations.js.map +1 -0
  1017. package/dist/core/usecases/place.js +44 -0
  1018. package/dist/core/usecases/place.js.map +1 -0
  1019. package/dist/core/usecases/service/exclude.js +119 -0
  1020. package/dist/core/usecases/service/exclude.js.map +1 -0
  1021. package/dist/core/usecases/service/flows.js +164 -0
  1022. package/dist/core/usecases/service/flows.js.map +1 -0
  1023. package/dist/core/usecases/suites/participants.js +83 -0
  1024. package/dist/core/usecases/suites/participants.js.map +1 -0
  1025. package/dist/core/usecases/suites/suites.js +45 -0
  1026. package/dist/core/usecases/suites/suites.js.map +1 -0
  1027. package/dist/core/usecases/touch.js +101 -0
  1028. package/dist/core/usecases/touch.js.map +1 -0
  1029. package/dist/core/verify/answers.js +180 -0
  1030. package/dist/core/verify/answers.js.map +1 -0
  1031. package/dist/core/verify/build.js +170 -0
  1032. package/dist/core/verify/build.js.map +1 -0
  1033. package/dist/core/verify/checklist.js +259 -0
  1034. package/dist/core/verify/checklist.js.map +1 -0
  1035. package/dist/core/verify/claims/identity.js +61 -0
  1036. package/dist/core/verify/claims/identity.js.map +1 -0
  1037. package/dist/core/verify/cross/diff.js +97 -0
  1038. package/dist/core/verify/cross/diff.js.map +1 -0
  1039. package/dist/core/verify/evidence/contract.js +169 -0
  1040. package/dist/core/verify/evidence/contract.js.map +1 -0
  1041. package/dist/core/verify/location.js +67 -0
  1042. package/dist/core/verify/location.js.map +1 -0
  1043. package/dist/core/verify/pins/lint.js +158 -0
  1044. package/dist/core/verify/pins/lint.js.map +1 -0
  1045. package/dist/core/verify/pins/pin.js +95 -0
  1046. package/dist/core/verify/pins/pin.js.map +1 -0
  1047. package/dist/core/verify/read/file.js +224 -0
  1048. package/dist/core/verify/read/file.js.map +1 -0
  1049. package/dist/core/verify/read/shape.js +169 -0
  1050. package/dist/core/verify/read/shape.js.map +1 -0
  1051. package/dist/core/verify/read/union.js +105 -0
  1052. package/dist/core/verify/read/union.js.map +1 -0
  1053. package/dist/core/verify/record.js +165 -0
  1054. package/dist/core/verify/record.js.map +1 -0
  1055. package/dist/core/verify/store/commit.js +99 -0
  1056. package/dist/core/verify/store/commit.js.map +1 -0
  1057. package/dist/core/verify/store/render.js +61 -0
  1058. package/dist/core/verify/store/render.js.map +1 -0
  1059. package/dist/core/vocabulary/health.js +91 -0
  1060. package/dist/core/vocabulary/health.js.map +1 -0
  1061. package/dist/core/vocabulary/issue.js +59 -0
  1062. package/dist/core/vocabulary/issue.js.map +1 -0
  1063. package/dist/core/vocabulary/maturity.js +216 -0
  1064. package/dist/core/vocabulary/maturity.js.map +1 -0
  1065. package/dist/core/vocabulary/report.js +90 -0
  1066. package/dist/core/vocabulary/report.js.map +1 -0
  1067. package/dist/core/vocabulary/steps.js +266 -0
  1068. package/dist/core/vocabulary/steps.js.map +1 -0
  1069. package/dist/core/workspace/discover.js +239 -0
  1070. package/dist/core/workspace/discover.js.map +1 -0
  1071. package/dist/core/workspace/render.js +52 -0
  1072. package/dist/core/workspace/render.js.map +1 -0
  1073. package/examples/README.md +232 -0
  1074. package/examples/docs/architecture/adrs/0001-transactional-outbox.md +33 -0
  1075. package/examples/docs/architecture/capabilities.yaml +31 -0
  1076. package/examples/docs/architecture/landscape.likec4 +336 -0
  1077. package/examples/docs/architecture/obligations.yaml +23 -0
  1078. package/examples/docs/architecture/permissions.yaml +50 -0
  1079. package/examples/docs/architecture/services.likec4 +70 -0
  1080. package/examples/docs/architecture/subsystems.likec4 +18 -0
  1081. package/examples/docs/architecture/usecases/order-notification.likec4 +74 -0
  1082. package/examples/docs/capabilities/checkout/spec.md +55 -0
  1083. package/examples/docs/capabilities/identity/tokens/spec.md +42 -0
  1084. package/examples/docs/capabilities/order-notifications/spec.md +43 -0
  1085. package/examples/docs/features/FEAT-101-payment-splitting/adrs/0001-dedicated-split-service.md +18 -0
  1086. package/examples/docs/features/FEAT-101-payment-splitting/delta.likec4 +94 -0
  1087. package/examples/docs/features/FEAT-101-payment-splitting/intent.md +44 -0
  1088. package/examples/docs/features/FEAT-101-payment-splitting/specs/checkout-web/spec.md +21 -0
  1089. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-service/asyncapi.yaml +132 -0
  1090. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-service/spec.md +36 -0
  1091. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/arch.spec.md +40 -0
  1092. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/openapi.yaml +116 -0
  1093. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/spec.md +55 -0
  1094. package/examples/docs/features/FEAT-112-retire-order-v1/intent.md +35 -0
  1095. package/examples/docs/features/FEAT-112-retire-order-v1/specs/order-service/openapi.yaml +31 -0
  1096. package/examples/docs/features/FEAT-112-retire-order-v1/specs/order-service/spec.md +17 -0
  1097. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/architecture/landscape.likec4 +253 -0
  1098. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/services/order-service/spec.md +121 -0
  1099. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/services/payment-service/openapi.yaml +111 -0
  1100. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/services/payment-service/spec.md +58 -0
  1101. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/manifest.json +32 -0
  1102. package/examples/docs/features/archive/FEAT-088-refunds/adrs/0001-refunds-stay-in-payment-service.md +26 -0
  1103. package/examples/docs/features/archive/FEAT-088-refunds/delta.likec4 +28 -0
  1104. package/examples/docs/features/archive/FEAT-088-refunds/intent.md +26 -0
  1105. package/examples/docs/features/archive/FEAT-088-refunds/specs/order-service/spec.md +37 -0
  1106. package/examples/docs/features/archive/FEAT-088-refunds/specs/payment-service/openapi.yaml +73 -0
  1107. package/examples/docs/features/archive/FEAT-088-refunds/specs/payment-service/spec.md +23 -0
  1108. package/examples/docs/features/archive/FEAT-088-refunds/verification.yaml +76 -0
  1109. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/architecture/landscape.likec4 +275 -0
  1110. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/payment-service/asyncapi.yaml +96 -0
  1111. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/payment-service/spec.md +82 -0
  1112. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/platform/notification-service/asyncapi.yaml +164 -0
  1113. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/platform/notification-service/spec.md +91 -0
  1114. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/manifest.json +46 -0
  1115. package/examples/docs/features/archive/FEAT-120-refund-notification/delta.likec4 +36 -0
  1116. package/examples/docs/features/archive/FEAT-120-refund-notification/intent.md +22 -0
  1117. package/examples/docs/features/archive/FEAT-120-refund-notification/scenario-report.json +10 -0
  1118. package/examples/docs/features/archive/FEAT-120-refund-notification/specs/notification-service/asyncapi.yaml +208 -0
  1119. package/examples/docs/features/archive/FEAT-120-refund-notification/specs/notification-service/spec.md +24 -0
  1120. package/examples/docs/features/archive/FEAT-120-refund-notification/specs/payment-service/asyncapi.yaml +137 -0
  1121. package/examples/docs/features/archive/FEAT-120-refund-notification/specs/payment-service/spec.md +31 -0
  1122. package/examples/docs/features/archive/FEAT-120-refund-notification/verification.yaml +84 -0
  1123. package/examples/docs/glossary/order.md +15 -0
  1124. package/examples/docs/glossary/payments/authorization.md +14 -0
  1125. package/examples/docs/likec4.config.json +8 -0
  1126. package/examples/docs/loam.json +3 -0
  1127. package/examples/docs/services/checkout-web/model.likec4 +92 -0
  1128. package/examples/docs/services/checkout-web/spec.md +91 -0
  1129. package/examples/docs/services/checkout-web/ui/pages/checkout.page.yaml +40 -0
  1130. package/examples/docs/services/checkout-web/ui/pages/order-status.page.yaml +24 -0
  1131. package/examples/docs/services/checkout-web/ui/pages/split-payment.page.yaml +26 -0
  1132. package/examples/docs/services/order-service/adrs/0001-orchestrated-order-lifecycle.md +52 -0
  1133. package/examples/docs/services/order-service/arch.spec.md +134 -0
  1134. package/examples/docs/services/order-service/asyncapi.yaml +109 -0
  1135. package/examples/docs/services/order-service/health.yaml +57 -0
  1136. package/examples/docs/services/order-service/model.likec4 +126 -0
  1137. package/examples/docs/services/order-service/openapi.yaml +257 -0
  1138. package/examples/docs/services/order-service/runbook.md +62 -0
  1139. package/examples/docs/services/order-service/spec.md +134 -0
  1140. package/examples/docs/services/payment-service/adrs/0001-payments-outbox.md +18 -0
  1141. package/examples/docs/services/payment-service/adrs/0002-idempotency-keys-on-authorization.md +27 -0
  1142. package/examples/docs/services/payment-service/arch.spec.md +76 -0
  1143. package/examples/docs/services/payment-service/asyncapi.yaml +130 -0
  1144. package/examples/docs/services/payment-service/health.yaml +39 -0
  1145. package/examples/docs/services/payment-service/model.likec4 +68 -0
  1146. package/examples/docs/services/payment-service/openapi.yaml +151 -0
  1147. package/examples/docs/services/payment-service/runbook.md +37 -0
  1148. package/examples/docs/services/payment-service/spec.md +88 -0
  1149. package/examples/docs/services/platform/identity-service/adrs/0001-token-introspection-over-local-validation.md +60 -0
  1150. package/examples/docs/services/platform/identity-service/arch.spec.md +120 -0
  1151. package/examples/docs/services/platform/identity-service/health.yaml +70 -0
  1152. package/examples/docs/services/platform/identity-service/model.likec4 +81 -0
  1153. package/examples/docs/services/platform/identity-service/openapi.yaml +197 -0
  1154. package/examples/docs/services/platform/identity-service/runbook.md +95 -0
  1155. package/examples/docs/services/platform/identity-service/spec.md +119 -0
  1156. package/examples/docs/services/platform/notification-service/asyncapi.yaml +200 -0
  1157. package/examples/docs/services/platform/notification-service/health.yaml +40 -0
  1158. package/examples/docs/services/platform/notification-service/model.likec4 +97 -0
  1159. package/examples/docs/services/platform/notification-service/runbook.md +48 -0
  1160. package/examples/docs/services/platform/notification-service/spec.md +112 -0
  1161. package/examples/docs/services/platform/subsystem.yaml +2 -0
  1162. package/examples/fleet.yaml +57 -0
  1163. package/package.json +19 -6
  1164. package/dist/commands/adopt.js +0 -240
  1165. package/dist/commands/adopt.js.map +0 -1
  1166. package/dist/commands/archive.js +0 -1313
  1167. package/dist/commands/archive.js.map +0 -1
  1168. package/dist/commands/delta.js +0 -388
  1169. package/dist/commands/delta.js.map +0 -1
  1170. package/dist/commands/docs-repo-gate.js.map +0 -1
  1171. package/dist/commands/format.js +0 -17
  1172. package/dist/commands/format.js.map +0 -1
  1173. package/dist/commands/gherkin.js +0 -309
  1174. package/dist/commands/gherkin.js.map +0 -1
  1175. package/dist/commands/init.js.map +0 -1
  1176. package/dist/commands/list.js +0 -295
  1177. package/dist/commands/list.js.map +0 -1
  1178. package/dist/commands/migrate-openspec.js +0 -950
  1179. package/dist/commands/migrate-openspec.js.map +0 -1
  1180. package/dist/commands/new.js +0 -413
  1181. package/dist/commands/new.js.map +0 -1
  1182. package/dist/commands/rebase.js +0 -356
  1183. package/dist/commands/rebase.js.map +0 -1
  1184. package/dist/commands/show.js +0 -320
  1185. package/dist/commands/show.js.map +0 -1
  1186. package/dist/commands/status.js +0 -262
  1187. package/dist/commands/status.js.map +0 -1
  1188. package/dist/commands/unarchive.js +0 -317
  1189. package/dist/commands/unarchive.js.map +0 -1
  1190. package/dist/commands/validate.js +0 -1773
  1191. package/dist/commands/validate.js.map +0 -1
  1192. package/dist/commands/verify.js +0 -775
  1193. package/dist/commands/verify.js.map +0 -1
  1194. package/dist/commands/vouch.js +0 -421
  1195. package/dist/commands/vouch.js.map +0 -1
  1196. package/dist/core/agent.js +0 -2173
  1197. package/dist/core/agent.js.map +0 -1
  1198. package/dist/core/agents-stamp.js.map +0 -1
  1199. package/dist/core/arch.js +0 -130
  1200. package/dist/core/arch.js.map +0 -1
  1201. package/dist/core/asyncapi.js +0 -253
  1202. package/dist/core/asyncapi.js.map +0 -1
  1203. package/dist/core/brief.js +0 -755
  1204. package/dist/core/brief.js.map +0 -1
  1205. package/dist/core/coherence.js +0 -577
  1206. package/dist/core/coherence.js.map +0 -1
  1207. package/dist/core/concurrency.js.map +0 -1
  1208. package/dist/core/config.js.map +0 -1
  1209. package/dist/core/delta.js +0 -476
  1210. package/dist/core/delta.js.map +0 -1
  1211. package/dist/core/dependencies.js +0 -356
  1212. package/dist/core/dependencies.js.map +0 -1
  1213. package/dist/core/doctor.js +0 -596
  1214. package/dist/core/doctor.js.map +0 -1
  1215. package/dist/core/document-bytes.js.map +0 -1
  1216. package/dist/core/explore.js +0 -225
  1217. package/dist/core/explore.js.map +0 -1
  1218. package/dist/core/frontmatter.js.map +0 -1
  1219. package/dist/core/gherkin.js +0 -463
  1220. package/dist/core/gherkin.js.map +0 -1
  1221. package/dist/core/health.js +0 -67
  1222. package/dist/core/health.js.map +0 -1
  1223. package/dist/core/ids.js +0 -122
  1224. package/dist/core/ids.js.map +0 -1
  1225. package/dist/core/issue.js +0 -9
  1226. package/dist/core/issue.js.map +0 -1
  1227. package/dist/core/json.js +0 -74
  1228. package/dist/core/json.js.map +0 -1
  1229. package/dist/core/likec4.js +0 -489
  1230. package/dist/core/likec4.js.map +0 -1
  1231. package/dist/core/maturity.js +0 -66
  1232. package/dist/core/maturity.js.map +0 -1
  1233. package/dist/core/openapi-merge.js +0 -552
  1234. package/dist/core/openapi-merge.js.map +0 -1
  1235. package/dist/core/openapi.js.map +0 -1
  1236. package/dist/core/openspec-inventory.js +0 -1440
  1237. package/dist/core/openspec-inventory.js.map +0 -1
  1238. package/dist/core/path-safety.js.map +0 -1
  1239. package/dist/core/provenance.js +0 -787
  1240. package/dist/core/provenance.js.map +0 -1
  1241. package/dist/core/records.js.map +0 -1
  1242. package/dist/core/repo.js +0 -438
  1243. package/dist/core/repo.js.map +0 -1
  1244. package/dist/core/report.js +0 -47
  1245. package/dist/core/report.js.map +0 -1
  1246. package/dist/core/spec.js +0 -505
  1247. package/dist/core/spec.js.map +0 -1
  1248. package/dist/core/staging.js +0 -890
  1249. package/dist/core/staging.js.map +0 -1
  1250. package/dist/core/status.js +0 -1132
  1251. package/dist/core/status.js.map +0 -1
  1252. package/dist/core/steps.js +0 -72
  1253. package/dist/core/steps.js.map +0 -1
  1254. package/dist/core/verify.js +0 -807
  1255. package/dist/core/verify.js.map +0 -1
  1256. package/dist/core/version.js.map +0 -1
@@ -0,0 +1,143 @@
1
+ /**
2
+ * Every refusal that stands between a finished migration plan and the disk.
3
+ *
4
+ * Three questions, one module because all three are answered at the same
5
+ * moment and none of them may be skipped: may the target hold these bytes at
6
+ * all (it must be empty, not a symlink, outside the OpenSpec source and outside
7
+ * any live loam fleet), do two planned writes claim one path once portable
8
+ * case/Unicode folding is applied, and would the requirements about to be
9
+ * serialized still parse as a loam spec.
10
+ *
11
+ * They sit beside the writers rather than under `../openspec/` because they
12
+ * grade the *output*: `../openspec/paths.ts` holds the path arithmetic they are
13
+ * built from, and knows nothing about a plan.
14
+ */
15
+ import { existsSync } from "node:fs";
16
+ import { lstat, readFile, readdir, realpath, stat } from "node:fs/promises";
17
+ import { dirname, join, resolve } from "node:path";
18
+ import { findConfigPath, parseConfig } from "../../../core/envelope/config.js";
19
+ import { docsDirOf } from "../../../core/kernel/ids/dirs.js";
20
+ import { CAPABILITY_LINE_RE, requirementIdProblems } from "../../../core/document/spec.js";
21
+ import { decodeDocument } from "../../../core/kernel/document-bytes.js";
22
+ import { isPathInside } from "../../../core/kernel/path-safety.js";
23
+ import {} from "../../../core/openspec/model/model.js";
24
+ import {} from "../../../core/staging/writes.js";
25
+ import { OpenSpecCommandError } from "../openspec/error.js";
26
+ import { canonicalForCreate } from "../openspec/paths.js";
27
+ /**
28
+ * The other half of "never writes into … live loam docs". Overlap with the
29
+ * OpenSpec source was the only thing checked, so `--target <docs>/features` on a
30
+ * fresh fleet passed and put phantom features into every `loam list`.
31
+ *
32
+ * The line is the docs tree, not the repository: every enumerating command reads
33
+ * `<docsDir>/services` and `<docsDir>/features`, so a target under docsDir joins
34
+ * the live fleet, while a sibling of it is merely a directory. A config that
35
+ * governs the target but cannot be parsed is refused too — an unreadable
36
+ * docsDir cannot be shown to be somewhere else.
37
+ */
38
+ async function assertOutsideLoamDocs(stage) {
39
+ const canonicalStage = await canonicalForCreate(stage);
40
+ const governing = findConfigPath(canonicalStage);
41
+ if (governing !== null) {
42
+ const docsDir = await governingDocsDir(governing);
43
+ if (docsDir === null || isPathInside(docsDir, canonicalStage)) {
44
+ throw new OpenSpecCommandError("invalid-option", `Refusing to stage a migration inside the live loam docs ${docsDir ?? `governed by ${governing}`}: ${stage}. Migrate into a standalone directory and cut over after review.`);
45
+ }
46
+ }
47
+ // A docs repo checked out without its loam.json — the landscape is the file
48
+ // no docs repo is without, and `loam init` scaffolds it before anything else.
49
+ for (let dir = canonicalStage;; dir = dirname(dir)) {
50
+ if (existsSync(join(dir, "architecture", "landscape.likec4"))) {
51
+ throw new OpenSpecCommandError("invalid-option", `Refusing to stage a migration inside a loam docs repository: ${join(dir, "architecture", "landscape.likec4")} is above ${stage}. Migrate into a standalone directory and cut over after review.`);
52
+ }
53
+ if (dirname(dir) === dir)
54
+ return;
55
+ }
56
+ }
57
+ /**
58
+ * Canonical docsDir of the config at `path`, or null when it cannot be read —
59
+ * including "read as UTF-8 it would have said something else", which is why the
60
+ * bytes go through `decodeDocument`. Null is the conservative answer here: the
61
+ * caller refuses to stage rather than accept a docsDir it cannot establish.
62
+ */
63
+ async function governingDocsDir(path) {
64
+ try {
65
+ // Re-branded after canonicalization: the path came out of `parseConfig`
66
+ // already resolved (a `DocsDir`), and `canonicalForCreate` only follows
67
+ // symlinks — same root, same provenance, canonical spelling.
68
+ return docsDirOf(await canonicalForCreate(parseConfig(decodeDocument(await readFile(path), path), dirname(path)).docsDir));
69
+ }
70
+ catch {
71
+ return null;
72
+ }
73
+ }
74
+ export async function assertEmptyNonOverlappingStage(inventory, stage) {
75
+ const canonicalStage = await canonicalForCreate(stage);
76
+ const canonicalSource = await realpath(inventory.inputRoot);
77
+ if (isPathInside(canonicalSource, canonicalStage) || isPathInside(canonicalStage, canonicalSource)) {
78
+ throw new OpenSpecCommandError("invalid-option", `Staging directory must not overlap the OpenSpec source workspace: ${stage}`);
79
+ }
80
+ await assertOutsideLoamDocs(stage);
81
+ try {
82
+ if ((await lstat(stage)).isSymbolicLink()) {
83
+ throw new OpenSpecCommandError("invalid-option", `Staging target must not be a symbolic link: ${stage}`);
84
+ }
85
+ }
86
+ catch (error) {
87
+ if (error instanceof OpenSpecCommandError)
88
+ throw error;
89
+ const code = typeof error === "object" && error !== null && "code" in error ? error.code : null;
90
+ if (code !== "ENOENT")
91
+ throw error;
92
+ }
93
+ if (!existsSync(stage))
94
+ return;
95
+ const info = await stat(stage);
96
+ if (!info.isDirectory() || (await readdir(stage)).length > 0) {
97
+ throw new OpenSpecCommandError("already-exists", `Staging target must be absent or an empty directory: ${stage}`);
98
+ }
99
+ }
100
+ export function assertDistinctPlannedPaths(writes) {
101
+ const writePaths = new Map();
102
+ for (const write of writes) {
103
+ const collisionKey = resolve(write.path).normalize("NFC").toLowerCase();
104
+ const existing = writePaths.get(collisionKey);
105
+ if (existing !== undefined) {
106
+ throw new OpenSpecCommandError("invalid-option", `Migration paths '${existing}' and '${write.path}' collide after portable case/Unicode normalization; refine mappings before apply.`);
107
+ }
108
+ writePaths.set(collisionKey, write.path);
109
+ }
110
+ }
111
+ /**
112
+ * The requirement with a `Capability: <id>` body line — the join that keeps
113
+ * the source capability's identity on every requirement it routed, instead of
114
+ * dissolving it into service files and leaving the id only in legacy/. The
115
+ * serializeRequirements Requirement-ID pattern: never a second line when the
116
+ * author already wrote one (a rare but legal delta authored against a loam
117
+ * target), and appended after the body the way active.ts appends its
118
+ * OpenSpec-Living-Source annotation, so a MODIFIED requirement's wholesale
119
+ * replace carries the line into the living document rather than stripping it.
120
+ */
121
+ export function requirementWithCapability(requirement, capabilityId) {
122
+ if (requirement.text.some((line) => CAPABILITY_LINE_RE.test(line)))
123
+ return requirement;
124
+ const line = `Capability: ${capabilityId}`;
125
+ return {
126
+ ...requirement,
127
+ capabilities: [capabilityId],
128
+ text: requirement.text.length === 0 ? [line] : [...requirement.text, "", line],
129
+ };
130
+ }
131
+ export function assertMaterializedRequirementIds(where, requirements) {
132
+ const problems = requirementIdProblems(requirements);
133
+ if (problems.length === 0)
134
+ return;
135
+ const first = problems[0];
136
+ const detail = first.kind === "invalid"
137
+ ? `requirement '${first.requirement}' has invalid Requirement-ID '${first.value}'`
138
+ : first.kind === "repeated"
139
+ ? `requirement '${first.requirement}' declares Requirement-ID ${first.values.length} times`
140
+ : `Requirement-ID '${first.id}' is shared by ${first.requirements.map((name) => `'${name}'`).join(", ")}`;
141
+ throw new OpenSpecCommandError("invalid-option", `${where} would materialize an invalid loam spec: ${detail}. Repair the source or refine routing before apply.`);
142
+ }
143
+ //# sourceMappingURL=stage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stage.js","sourceRoot":"","sources":["../../../../src/commands/migrate-openspec/materialize/stage.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Every refusal that stands between a finished migration plan and the disk.\n *\n * Three questions, one module because all three are answered at the same\n * moment and none of them may be skipped: may the target hold these bytes at\n * all (it must be empty, not a symlink, outside the OpenSpec source and outside\n * any live loam fleet), do two planned writes claim one path once portable\n * case/Unicode folding is applied, and would the requirements about to be\n * serialized still parse as a loam spec.\n *\n * They sit beside the writers rather than under `../openspec/` because they\n * grade the *output*: `../openspec/paths.ts` holds the path arithmetic they are\n * built from, and knows nothing about a plan.\n */\nimport { existsSync } from \"node:fs\";\nimport { lstat, readFile, readdir, realpath, stat } from \"node:fs/promises\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { findConfigPath, parseConfig } from \"../../../core/envelope/config.js\";\nimport { docsDirOf, type DocsDir } from \"../../../core/kernel/ids/dirs.js\";\nimport { CAPABILITY_LINE_RE, requirementIdProblems, type Requirement } from \"../../../core/document/spec.js\";\nimport { decodeDocument } from \"../../../core/kernel/document-bytes.js\";\nimport { isPathInside } from \"../../../core/kernel/path-safety.js\";\nimport { type OpenSpecInventory } from \"../../../core/openspec/model/model.js\";\nimport { type PlannedWrite } from \"../../../core/staging/writes.js\";\nimport { OpenSpecCommandError } from \"../openspec/error.js\";\nimport { canonicalForCreate } from \"../openspec/paths.js\";\n\n/**\n * The other half of \"never writes into … live loam docs\". Overlap with the\n * OpenSpec source was the only thing checked, so `--target <docs>/features` on a\n * fresh fleet passed and put phantom features into every `loam list`.\n *\n * The line is the docs tree, not the repository: every enumerating command reads\n * `<docsDir>/services` and `<docsDir>/features`, so a target under docsDir joins\n * the live fleet, while a sibling of it is merely a directory. A config that\n * governs the target but cannot be parsed is refused too — an unreadable\n * docsDir cannot be shown to be somewhere else.\n */\nasync function assertOutsideLoamDocs(stage: string): Promise<void> {\n const canonicalStage = await canonicalForCreate(stage);\n const governing = findConfigPath(canonicalStage);\n if (governing !== null) {\n const docsDir = await governingDocsDir(governing);\n if (docsDir === null || isPathInside(docsDir, canonicalStage)) {\n throw new OpenSpecCommandError(\n \"invalid-option\",\n `Refusing to stage a migration inside the live loam docs ${docsDir ?? `governed by ${governing}`}: ${stage}. Migrate into a standalone directory and cut over after review.`,\n );\n }\n }\n // A docs repo checked out without its loam.json — the landscape is the file\n // no docs repo is without, and `loam init` scaffolds it before anything else.\n for (let dir = canonicalStage; ; dir = dirname(dir)) {\n if (existsSync(join(dir, \"architecture\", \"landscape.likec4\"))) {\n throw new OpenSpecCommandError(\n \"invalid-option\",\n `Refusing to stage a migration inside a loam docs repository: ${join(dir, \"architecture\", \"landscape.likec4\")} is above ${stage}. Migrate into a standalone directory and cut over after review.`,\n );\n }\n if (dirname(dir) === dir) return;\n }\n}\n\n/**\n * Canonical docsDir of the config at `path`, or null when it cannot be read —\n * including \"read as UTF-8 it would have said something else\", which is why the\n * bytes go through `decodeDocument`. Null is the conservative answer here: the\n * caller refuses to stage rather than accept a docsDir it cannot establish.\n */\nasync function governingDocsDir(path: string): Promise<DocsDir | null> {\n try {\n // Re-branded after canonicalization: the path came out of `parseConfig`\n // already resolved (a `DocsDir`), and `canonicalForCreate` only follows\n // symlinks — same root, same provenance, canonical spelling.\n return docsDirOf(await canonicalForCreate(\n parseConfig(decodeDocument(await readFile(path), path), dirname(path)).docsDir,\n ));\n } catch {\n return null;\n }\n}\n\nexport async function assertEmptyNonOverlappingStage(inventory: OpenSpecInventory, stage: string): Promise<void> {\n const canonicalStage = await canonicalForCreate(stage);\n const canonicalSource = await realpath(inventory.inputRoot);\n if (isPathInside(canonicalSource, canonicalStage) || isPathInside(canonicalStage, canonicalSource)) {\n throw new OpenSpecCommandError(\n \"invalid-option\",\n `Staging directory must not overlap the OpenSpec source workspace: ${stage}`,\n );\n }\n await assertOutsideLoamDocs(stage);\n try {\n if ((await lstat(stage)).isSymbolicLink()) {\n throw new OpenSpecCommandError(\n \"invalid-option\",\n `Staging target must not be a symbolic link: ${stage}`,\n );\n }\n } catch (error) {\n if (error instanceof OpenSpecCommandError) throw error;\n const code = typeof error === \"object\" && error !== null && \"code\" in error ? error.code : null;\n if (code !== \"ENOENT\") throw error;\n }\n if (!existsSync(stage)) return;\n const info = await stat(stage);\n if (!info.isDirectory() || (await readdir(stage)).length > 0) {\n throw new OpenSpecCommandError(\"already-exists\", `Staging target must be absent or an empty directory: ${stage}`);\n }\n}\n\nexport function assertDistinctPlannedPaths(writes: PlannedWrite[]): void {\n const writePaths = new Map<string, string>();\n for (const write of writes) {\n const collisionKey = resolve(write.path).normalize(\"NFC\").toLowerCase();\n const existing = writePaths.get(collisionKey);\n if (existing !== undefined) {\n throw new OpenSpecCommandError(\n \"invalid-option\",\n `Migration paths '${existing}' and '${write.path}' collide after portable case/Unicode normalization; refine mappings before apply.`,\n );\n }\n writePaths.set(collisionKey, write.path);\n }\n}\n\n/**\n * The requirement with a `Capability: <id>` body line — the join that keeps\n * the source capability's identity on every requirement it routed, instead of\n * dissolving it into service files and leaving the id only in legacy/. The\n * serializeRequirements Requirement-ID pattern: never a second line when the\n * author already wrote one (a rare but legal delta authored against a loam\n * target), and appended after the body the way active.ts appends its\n * OpenSpec-Living-Source annotation, so a MODIFIED requirement's wholesale\n * replace carries the line into the living document rather than stripping it.\n */\nexport function requirementWithCapability(requirement: Requirement, capabilityId: string): Requirement {\n if (requirement.text.some((line) => CAPABILITY_LINE_RE.test(line))) return requirement;\n const line = `Capability: ${capabilityId}`;\n return {\n ...requirement,\n capabilities: [capabilityId],\n text: requirement.text.length === 0 ? [line] : [...requirement.text, \"\", line],\n };\n}\n\nexport function assertMaterializedRequirementIds(where: string, requirements: Requirement[]): void {\n const problems = requirementIdProblems(requirements);\n if (problems.length === 0) return;\n const first = problems[0]!;\n const detail = first.kind === \"invalid\"\n ? `requirement '${first.requirement}' has invalid Requirement-ID '${first.value}'`\n : first.kind === \"repeated\"\n ? `requirement '${first.requirement}' declares Requirement-ID ${first.values.length} times`\n : `Requirement-ID '${first.id}' is shared by ${first.requirements.map((name) => `'${name}'`).join(\", \")}`;\n throw new OpenSpecCommandError(\n \"invalid-option\",\n `${where} would materialize an invalid loam spec: ${detail}. Repair the source or refine routing before apply.`,\n );\n}\n"]}
@@ -0,0 +1,219 @@
1
+ /**
2
+ * The staged target: plan every byte first, then land them all or none.
3
+ *
4
+ * The two halves are one module because they are one transaction. Planning
5
+ * reads the whole source corpus, so `writeMigrationTarget` re-hashes it
6
+ * afterwards and refuses a snapshot that moved mid-flight; the plan then
7
+ * becomes an exclusive staged write set that rolls back as a unit. Splitting
8
+ * the planner from the writer would put that re-hash on one side of a module
9
+ * boundary and the reads it guards on the other.
10
+ */
11
+ import { mkdir } from "node:fs/promises";
12
+ import { join } from "node:path";
13
+ import { stringify as stringifyYaml } from "yaml";
14
+ import { openspecRequirements } from "../../../core/openspec/scan/shape.js";
15
+ import {} from "../../../core/document/spec.js";
16
+ import { DOCS_SUBDIRS, docsRepoFiles } from "../../../core/docs.js";
17
+ import { compareIds } from "../../../core/repo/entries.js";
18
+ import { ownValue } from "../../../core/kernel/records.js";
19
+ import { inventoryOpenSpec } from "../../../core/openspec/inventory.js";
20
+ import {} from "../../../core/openspec/model/mapping.js";
21
+ import {} from "../../../core/openspec/model/model.js";
22
+ import { rollbackError, rollbackStaged, stageWrites, swapStaged } from "../../../core/staging/commit.js";
23
+ import { planWrite } from "../../../core/staging/writes.js";
24
+ import { normalizedMapping } from "../openspec/decisions.js";
25
+ import { OpenSpecCommandError } from "../openspec/error.js";
26
+ import { safeArtifactRelative } from "../openspec/paths.js";
27
+ import { readSourceArtifact } from "../openspec/read.js";
28
+ import { materializeActiveChanges } from "./active.js";
29
+ import { materializeLivingSpecs } from "./living.js";
30
+ import { assertDistinctPlannedPaths, assertEmptyNonOverlappingStage } from "./stage.js";
31
+ export async function planMigrationWrites(inventory, mapping, target) {
32
+ // One reading of the living corpus for both materializers. They each read and
33
+ // parsed the whole of it independently, which is twice the work and, worse,
34
+ // two readings: a rename resolved against one of them was written beside a
35
+ // living spec built from the other.
36
+ const livingByCapability = new Map();
37
+ for (const capability of inventory.living.capabilities) {
38
+ livingByCapability.set(capability.id, openspecRequirements(await readSourceArtifact(inventory.root, capability.files[0])));
39
+ }
40
+ const livingWrites = await materializeLivingSpecs(inventory, mapping, target, livingByCapability);
41
+ const vocabulary = capabilitiesVocabularyWrite(inventory, target);
42
+ if (vocabulary !== null)
43
+ livingWrites.push(vocabulary);
44
+ const activeWrites = await materializeActiveChanges(inventory, mapping, target, livingByCapability);
45
+ const legacyWrites = await copyLivingTree(inventory, target);
46
+ assertDistinctPlannedPaths([...livingWrites, ...activeWrites, ...legacyWrites]);
47
+ return { livingWrites, activeWrites, legacyWrites };
48
+ }
49
+ /**
50
+ * The staged fleet's capability vocabulary: the union of living and
51
+ * active-horizon capability ids, each declared with an EMPTY body — no
52
+ * description is invented, because the authored `## Purpose` prose stays
53
+ * verbatim under legacy/ (the no-prose-moves rule), and an empty mapping is a
54
+ * legal declaration. Keys sorted with compareIds over an insertion-ordered
55
+ * object, so the bytes are machine-independent; nested ids stay one flat key
56
+ * (`payments/refunds`), never collapsed. Null when the corpus names no
57
+ * capability at all — an empty vocabulary FILE would opt the staged fleet into
58
+ * an axis it has nothing to say on. assertDistinctPlannedPaths guards the path
59
+ * against every other planned write; the docs scaffold does not write it.
60
+ */
61
+ function capabilitiesVocabularyWrite(inventory, target) {
62
+ const ids = new Set(inventory.living.capabilities.map((capability) => capability.id));
63
+ for (const change of inventory.changes.active) {
64
+ for (const spec of change.specs)
65
+ ids.add(spec.capability);
66
+ }
67
+ if (ids.size === 0)
68
+ return null;
69
+ const capabilities = Object.fromEntries([...ids].sort(compareIds).map((id) => [id, {}]));
70
+ return planWrite(join(target, "architecture", "capabilities.yaml"), "# Declared by `loam migrate-openspec`: every living and active-horizon OpenSpec\n" +
71
+ "# capability id, so capability identity survives migration as a checkable name\n" +
72
+ "# (each routed requirement carries a matching `Capability:` line). Descriptions\n" +
73
+ "# are deliberately absent — the authored Purpose prose is verbatim under\n" +
74
+ "# legacy/openspec/specs/, and no prose moves.\n" +
75
+ stringifyYaml({ capabilities }, { lineWidth: 0 }));
76
+ }
77
+ /**
78
+ * The living tree, byte for byte, the way each change tree already gets
79
+ * `legacy/openspec/`.
80
+ *
81
+ * `materializeLivingSpecs` emits frontmatter plus serialized requirements, so
82
+ * everything a living spec holds AROUND its requirements has nowhere to land:
83
+ * `## Purpose`, prose between `## Requirements` and the first requirement, and
84
+ * the whole of `specs/<capability>/design.md` — which the summary counts under
85
+ * `review-as-service-adr` while FOLLOW-UP.md tells the migrator to review prose
86
+ * that had been written nowhere. (Prose inside a requirement body survives
87
+ * serialization and is not the subject here.)
88
+ */
89
+ async function copyLivingTree(inventory, target) {
90
+ const writes = [];
91
+ for (const artifact of inventory.artifacts) {
92
+ if (artifact.scope !== "living")
93
+ continue;
94
+ const segments = safeArtifactRelative(artifact.path, "specs/", "The OpenSpec living tree");
95
+ writes.push(planWrite(join(target, "legacy", "openspec", "specs", ...segments), await readSourceArtifact(inventory.root, artifact.path)));
96
+ }
97
+ return writes;
98
+ }
99
+ export async function writeMigrationTarget(inventory, mapping, target, planned) {
100
+ await assertEmptyNonOverlappingStage(inventory, target);
101
+ // All migration content was read while planning. Re-hash after those reads so
102
+ // a source edit between audit and materialization cannot produce a mixed snapshot.
103
+ const refreshed = await inventoryOpenSpec(inventory.inputRoot, { mapping });
104
+ if (!refreshed.ready || refreshed.inventoryDigest !== inventory.inventoryDigest) {
105
+ throw new OpenSpecCommandError("invalid-option", "OpenSpec source changed while the migration plan was being materialized; re-audit and review a new mapping.");
106
+ }
107
+ const followUpBlockers = [
108
+ "Model every staged service in architecture/landscape.likec4 and bind it with metadata { service '<id>' }; the scaffolded landscape is deliberately empty.",
109
+ "Add each service model.likec4 and OpenAPI contract; migrated requirements have no Operations/Covers links yet unless authored upstream.",
110
+ "Set truthful sources from each service repository, validate, and have a human run loam vouch; staged specs remain status: draft.",
111
+ ...(inventory.changes.active.length === 0
112
+ ? []
113
+ : [
114
+ `Review ${inventory.changes.active.length} staged feature(s), add their LikeC4/OpenAPI deltas, and resolve any retained or manual-review OpenSpec artifacts recorded in migration-plan.json.`,
115
+ // OpenSpec has no equivalent of `Based-On:`, so every migrated
116
+ // MODIFIED/REMOVED requirement arrives unpinned (`delta.baseline-missing`,
117
+ // a warning that GATES archive — unpinned is the shape that reverts
118
+ // someone else's landed change). The corpus is not stranded: one
119
+ // rebase per staged feature pins everything, which is exactly the
120
+ // step this line asks for.
121
+ "Run `loam rebase <FEAT>` per staged feature: OpenSpec deltas carry no Based-On, so no MODIFIED/REMOVED requirement is pinned to the living text it was written against.",
122
+ ]),
123
+ "Review config context/rules, Stores/references, custom schemas, and every artifact disposition in migration-plan.json.",
124
+ "Review the verbatim OpenSpec living tree under legacy/openspec/specs/: Purpose prose, section prose, and capability design.md have no loam equivalent and were copied, not converted.",
125
+ // The cutover was undocumented, which is how a staged target that cannot
126
+ // answer `loam validate` reads as finished work. Naming the two halves —
127
+ // what is fleet content and what is review residue — is the whole procedure.
128
+ "Cut over only once `loam validate --all` here is green: services/ and features/ are the fleet content, while legacy/, mapping.yaml, migration-plan.json, FOLLOW-UP.md, and this repository's own loam.json/AGENTS.md are review residue that does not move.",
129
+ ];
130
+ const plan = {
131
+ version: 1,
132
+ generatedBy: "loam migrate-openspec",
133
+ source: { inputRoot: inventory.inputRoot, root: inventory.root },
134
+ baselines: inventory.baselines,
135
+ readiness: inventory.readiness,
136
+ mapping: normalizedMapping(inventory, mapping),
137
+ living: inventory.living,
138
+ activeChanges: inventory.changes.active,
139
+ archiveDiagnostics: inventory.archiveDiagnostics,
140
+ artifactDisposition: inventory.artifacts.map((artifact) => ({
141
+ ...artifact,
142
+ disposition: ownValue(mapping.artifacts, artifact.path) ?? artifact.disposition,
143
+ selectedDisposition: ownValue(mapping.artifacts, artifact.path) ?? null,
144
+ })),
145
+ followUpBlockers,
146
+ note: "Staged migration docs only. Living specs and mapped active changes were materialized without changing the OpenSpec source or live loam docs. The result is intentionally not expected to validate green until the listed architecture, API, provenance, and review work is completed.",
147
+ };
148
+ const writes = [
149
+ planWrite(join(target, "migration-plan.json"), `${JSON.stringify(plan, null, 2)}\n`),
150
+ planWrite(join(target, "mapping.yaml"), stringifyYaml(normalizedMapping(inventory, mapping), { lineWidth: 0 })),
151
+ planWrite(join(target, "FOLLOW-UP.md"), renderFollowUp(followUpBlockers)),
152
+ ...docsRepoScaffold(target),
153
+ ...planned.livingWrites,
154
+ ...planned.activeWrites,
155
+ ...planned.legacyWrites,
156
+ ];
157
+ assertDistinctPlannedPaths(writes);
158
+ for (const write of writes)
159
+ write.exclusive = true;
160
+ const staged = await stageWrites(writes);
161
+ if (staged.some((item) => item.before !== null)) {
162
+ await rollbackStaged(staged);
163
+ throw new OpenSpecCommandError("already-exists", "Staging target changed after its emptiness check; refusing to overwrite a concurrently created file.");
164
+ }
165
+ try {
166
+ await swapStaged(staged);
167
+ }
168
+ catch (error) {
169
+ const failures = await rollbackStaged(staged);
170
+ const code = typeof error === "object" && error !== null && "code" in error ? error.code : null;
171
+ if (code === "EEXIST" && failures.length === 0) {
172
+ throw new OpenSpecCommandError("already-exists", "Staging target changed during apply; the migration was rolled back without overwriting the concurrent file.");
173
+ }
174
+ throw rollbackError(error, failures);
175
+ }
176
+ // The skeleton `loam init` lays down, after the content that fills it. A docs
177
+ // repo is recognised by `services/` plus AGENTS.md, and until now `services/`
178
+ // existed only if some capability happened to route there: migrate a corpus
179
+ // whose requirements all live under `changes/` — legitimate, and the shape a
180
+ // greenfield OpenSpec workspace has — and the target came out with no
181
+ // `services/` at all, so `loam init --docs <target> --service <id>` answered
182
+ // "not a docs repo" and every read command refused it as `services-missing`.
183
+ // Empty directories, created after the swap so a rolled-back apply leaves the
184
+ // target as empty as it found it.
185
+ for (const dir of DOCS_SUBDIRS)
186
+ await mkdir(join(target, dir), { recursive: true });
187
+ return { directory: target, files: writes.map((write) => write.path), followUpBlockers };
188
+ }
189
+ /**
190
+ * The staged target is a real docs repo, not a folder of markdown.
191
+ *
192
+ * FOLLOW-UP.md tells the migrator to validate, rebase and vouch against this
193
+ * directory, and every one of those commands resolves its fleet from loam.json:
194
+ * without these three files none of the instructions it gives can be executed,
195
+ * and the reviewer has no way to see what is still missing. The landscape is
196
+ * laid down EMPTY for the same reason `loam init` lays it down empty — an absent
197
+ * landscape silences every cross-service check, and a generated one would be a
198
+ * guess presented as the map. Each staged service then shows up as exactly one
199
+ * `landscape.service-unmodelled` error, which is the first follow-up item.
200
+ *
201
+ * The bytes come from `docs.ts`, so this IS the repo `loam init` makes rather
202
+ * than a lookalike. Only the landscape's opening comment differs, and it differs
203
+ * through a parameter: the migrator needs to be told why their map is empty,
204
+ * and everything after that sentence is advice that does not depend on how the
205
+ * repo was created.
206
+ */
207
+ function docsRepoScaffold(target) {
208
+ return docsRepoFiles({
209
+ landscapePreamble: "// Fleet map for a staged OpenSpec migration. It arrives EMPTY because\n"
210
+ + "// OpenSpec has no topology: loam has nothing to read here and will not\n"
211
+ + "// guess \"who calls whom\" into the source of truth. Every services/<id>/\n"
212
+ + "// staged beside this file needs an element and a binding below — until\n"
213
+ + "// then each one is a `landscape.service-unmodelled` error.",
214
+ }).map(([rel, content]) => planWrite(join(target, rel), content));
215
+ }
216
+ function renderFollowUp(blockers) {
217
+ return `# Staged OpenSpec migration: required follow-up\n\nThis target contains migrated living requirements, mapped active feature deltas, preserved source artifacts, and a review plan. It is deliberately not presented as a fully valid loam fleet. Complete every item before moving it into live docs.\n\n${blockers.map((item) => `- [ ] ${item}`).join("\n")}\n`;
218
+ }
219
+ //# sourceMappingURL=target.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"target.js","sourceRoot":"","sources":["../../../../src/commands/migrate-openspec/materialize/target.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The staged target: plan every byte first, then land them all or none.\n *\n * The two halves are one module because they are one transaction. Planning\n * reads the whole source corpus, so `writeMigrationTarget` re-hashes it\n * afterwards and refuses a snapshot that moved mid-flight; the plan then\n * becomes an exclusive staged write set that rolls back as a unit. Splitting\n * the planner from the writer would put that re-hash on one side of a module\n * boundary and the reads it guards on the other.\n */\nimport { mkdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { stringify as stringifyYaml } from \"yaml\";\nimport { openspecRequirements } from \"../../../core/openspec/scan/shape.js\";\nimport { type Requirement } from \"../../../core/document/spec.js\";\nimport { DOCS_SUBDIRS, docsRepoFiles } from \"../../../core/docs.js\";\nimport { compareIds } from \"../../../core/repo/entries.js\";\nimport { ownValue } from \"../../../core/kernel/records.js\";\nimport { inventoryOpenSpec } from \"../../../core/openspec/inventory.js\";\nimport { type OpenSpecMapping } from \"../../../core/openspec/model/mapping.js\";\nimport { type OpenSpecInventory } from \"../../../core/openspec/model/model.js\";\nimport { rollbackError, rollbackStaged, stageWrites, swapStaged } from \"../../../core/staging/commit.js\";\nimport { planWrite, type PlannedWrite } from \"../../../core/staging/writes.js\";\nimport { normalizedMapping } from \"../openspec/decisions.js\";\nimport { OpenSpecCommandError } from \"../openspec/error.js\";\nimport { safeArtifactRelative } from \"../openspec/paths.js\";\nimport { readSourceArtifact } from \"../openspec/read.js\";\nimport { materializeActiveChanges } from \"./active.js\";\nimport { materializeLivingSpecs } from \"./living.js\";\nimport { assertDistinctPlannedPaths, assertEmptyNonOverlappingStage } from \"./stage.js\";\n\nexport async function planMigrationWrites(\n inventory: OpenSpecInventory,\n mapping: OpenSpecMapping,\n target: string,\n): Promise<{ livingWrites: PlannedWrite[]; activeWrites: PlannedWrite[]; legacyWrites: PlannedWrite[] }> {\n // One reading of the living corpus for both materializers. They each read and\n // parsed the whole of it independently, which is twice the work and, worse,\n // two readings: a rename resolved against one of them was written beside a\n // living spec built from the other.\n const livingByCapability = new Map<string, Requirement[]>();\n for (const capability of inventory.living.capabilities) {\n livingByCapability.set(\n capability.id,\n openspecRequirements(await readSourceArtifact(inventory.root, capability.files[0]!)),\n );\n }\n const livingWrites = await materializeLivingSpecs(inventory, mapping, target, livingByCapability);\n const vocabulary = capabilitiesVocabularyWrite(inventory, target);\n if (vocabulary !== null) livingWrites.push(vocabulary);\n const activeWrites = await materializeActiveChanges(inventory, mapping, target, livingByCapability);\n const legacyWrites = await copyLivingTree(inventory, target);\n assertDistinctPlannedPaths([...livingWrites, ...activeWrites, ...legacyWrites]);\n return { livingWrites, activeWrites, legacyWrites };\n}\n\n/**\n * The staged fleet's capability vocabulary: the union of living and\n * active-horizon capability ids, each declared with an EMPTY body — no\n * description is invented, because the authored `## Purpose` prose stays\n * verbatim under legacy/ (the no-prose-moves rule), and an empty mapping is a\n * legal declaration. Keys sorted with compareIds over an insertion-ordered\n * object, so the bytes are machine-independent; nested ids stay one flat key\n * (`payments/refunds`), never collapsed. Null when the corpus names no\n * capability at all — an empty vocabulary FILE would opt the staged fleet into\n * an axis it has nothing to say on. assertDistinctPlannedPaths guards the path\n * against every other planned write; the docs scaffold does not write it.\n */\nfunction capabilitiesVocabularyWrite(inventory: OpenSpecInventory, target: string): PlannedWrite | null {\n const ids = new Set<string>(inventory.living.capabilities.map((capability) => capability.id));\n for (const change of inventory.changes.active) {\n for (const spec of change.specs) ids.add(spec.capability);\n }\n if (ids.size === 0) return null;\n const capabilities = Object.fromEntries([...ids].sort(compareIds).map((id) => [id, {}]));\n return planWrite(\n join(target, \"architecture\", \"capabilities.yaml\"),\n \"# Declared by `loam migrate-openspec`: every living and active-horizon OpenSpec\\n\" +\n \"# capability id, so capability identity survives migration as a checkable name\\n\" +\n \"# (each routed requirement carries a matching `Capability:` line). Descriptions\\n\" +\n \"# are deliberately absent — the authored Purpose prose is verbatim under\\n\" +\n \"# legacy/openspec/specs/, and no prose moves.\\n\" +\n stringifyYaml({ capabilities }, { lineWidth: 0 }),\n );\n}\n\n/**\n * The living tree, byte for byte, the way each change tree already gets\n * `legacy/openspec/`.\n *\n * `materializeLivingSpecs` emits frontmatter plus serialized requirements, so\n * everything a living spec holds AROUND its requirements has nowhere to land:\n * `## Purpose`, prose between `## Requirements` and the first requirement, and\n * the whole of `specs/<capability>/design.md` — which the summary counts under\n * `review-as-service-adr` while FOLLOW-UP.md tells the migrator to review prose\n * that had been written nowhere. (Prose inside a requirement body survives\n * serialization and is not the subject here.)\n */\nasync function copyLivingTree(inventory: OpenSpecInventory, target: string): Promise<PlannedWrite[]> {\n const writes: PlannedWrite[] = [];\n for (const artifact of inventory.artifacts) {\n if (artifact.scope !== \"living\") continue;\n const segments = safeArtifactRelative(artifact.path, \"specs/\", \"The OpenSpec living tree\");\n writes.push(planWrite(\n join(target, \"legacy\", \"openspec\", \"specs\", ...segments),\n await readSourceArtifact(inventory.root, artifact.path),\n ));\n }\n return writes;\n}\n\nexport async function writeMigrationTarget(\n inventory: OpenSpecInventory,\n mapping: OpenSpecMapping,\n target: string,\n planned: { livingWrites: PlannedWrite[]; activeWrites: PlannedWrite[]; legacyWrites: PlannedWrite[] },\n): Promise<{ directory: string; files: string[]; followUpBlockers: string[] }> {\n await assertEmptyNonOverlappingStage(inventory, target);\n // All migration content was read while planning. Re-hash after those reads so\n // a source edit between audit and materialization cannot produce a mixed snapshot.\n const refreshed = await inventoryOpenSpec(inventory.inputRoot, { mapping });\n if (!refreshed.ready || refreshed.inventoryDigest !== inventory.inventoryDigest) {\n throw new OpenSpecCommandError(\n \"invalid-option\",\n \"OpenSpec source changed while the migration plan was being materialized; re-audit and review a new mapping.\",\n );\n }\n const followUpBlockers = [\n \"Model every staged service in architecture/landscape.likec4 and bind it with metadata { service '<id>' }; the scaffolded landscape is deliberately empty.\",\n \"Add each service model.likec4 and OpenAPI contract; migrated requirements have no Operations/Covers links yet unless authored upstream.\",\n \"Set truthful sources from each service repository, validate, and have a human run loam vouch; staged specs remain status: draft.\",\n ...(inventory.changes.active.length === 0\n ? []\n : [\n `Review ${inventory.changes.active.length} staged feature(s), add their LikeC4/OpenAPI deltas, and resolve any retained or manual-review OpenSpec artifacts recorded in migration-plan.json.`,\n // OpenSpec has no equivalent of `Based-On:`, so every migrated\n // MODIFIED/REMOVED requirement arrives unpinned (`delta.baseline-missing`,\n // a warning that GATES archive — unpinned is the shape that reverts\n // someone else's landed change). The corpus is not stranded: one\n // rebase per staged feature pins everything, which is exactly the\n // step this line asks for.\n \"Run `loam rebase <FEAT>` per staged feature: OpenSpec deltas carry no Based-On, so no MODIFIED/REMOVED requirement is pinned to the living text it was written against.\",\n ]),\n \"Review config context/rules, Stores/references, custom schemas, and every artifact disposition in migration-plan.json.\",\n \"Review the verbatim OpenSpec living tree under legacy/openspec/specs/: Purpose prose, section prose, and capability design.md have no loam equivalent and were copied, not converted.\",\n // The cutover was undocumented, which is how a staged target that cannot\n // answer `loam validate` reads as finished work. Naming the two halves —\n // what is fleet content and what is review residue — is the whole procedure.\n \"Cut over only once `loam validate --all` here is green: services/ and features/ are the fleet content, while legacy/, mapping.yaml, migration-plan.json, FOLLOW-UP.md, and this repository's own loam.json/AGENTS.md are review residue that does not move.\",\n ];\n const plan = {\n version: 1,\n generatedBy: \"loam migrate-openspec\",\n source: { inputRoot: inventory.inputRoot, root: inventory.root },\n baselines: inventory.baselines,\n readiness: inventory.readiness,\n mapping: normalizedMapping(inventory, mapping),\n living: inventory.living,\n activeChanges: inventory.changes.active,\n archiveDiagnostics: inventory.archiveDiagnostics,\n artifactDisposition: inventory.artifacts.map((artifact) => ({\n ...artifact,\n disposition: ownValue(mapping.artifacts, artifact.path) ?? artifact.disposition,\n selectedDisposition: ownValue(mapping.artifacts, artifact.path) ?? null,\n })),\n followUpBlockers,\n note: \"Staged migration docs only. Living specs and mapped active changes were materialized without changing the OpenSpec source or live loam docs. The result is intentionally not expected to validate green until the listed architecture, API, provenance, and review work is completed.\",\n };\n const writes: PlannedWrite[] = [\n planWrite(join(target, \"migration-plan.json\"), `${JSON.stringify(plan, null, 2)}\\n`),\n planWrite(join(target, \"mapping.yaml\"), stringifyYaml(normalizedMapping(inventory, mapping), { lineWidth: 0 })),\n planWrite(join(target, \"FOLLOW-UP.md\"), renderFollowUp(followUpBlockers)),\n ...docsRepoScaffold(target),\n ...planned.livingWrites,\n ...planned.activeWrites,\n ...planned.legacyWrites,\n ];\n assertDistinctPlannedPaths(writes);\n for (const write of writes) write.exclusive = true;\n const staged = await stageWrites(writes);\n if (staged.some((item) => item.before !== null)) {\n await rollbackStaged(staged);\n throw new OpenSpecCommandError(\n \"already-exists\",\n \"Staging target changed after its emptiness check; refusing to overwrite a concurrently created file.\",\n );\n }\n try {\n await swapStaged(staged);\n } catch (error) {\n const failures = await rollbackStaged(staged);\n const code = typeof error === \"object\" && error !== null && \"code\" in error ? error.code : null;\n if (code === \"EEXIST\" && failures.length === 0) {\n throw new OpenSpecCommandError(\n \"already-exists\",\n \"Staging target changed during apply; the migration was rolled back without overwriting the concurrent file.\",\n );\n }\n throw rollbackError(error, failures);\n }\n // The skeleton `loam init` lays down, after the content that fills it. A docs\n // repo is recognised by `services/` plus AGENTS.md, and until now `services/`\n // existed only if some capability happened to route there: migrate a corpus\n // whose requirements all live under `changes/` — legitimate, and the shape a\n // greenfield OpenSpec workspace has — and the target came out with no\n // `services/` at all, so `loam init --docs <target> --service <id>` answered\n // \"not a docs repo\" and every read command refused it as `services-missing`.\n // Empty directories, created after the swap so a rolled-back apply leaves the\n // target as empty as it found it.\n for (const dir of DOCS_SUBDIRS) await mkdir(join(target, dir), { recursive: true });\n return { directory: target, files: writes.map((write) => write.path), followUpBlockers };\n}\n\n/**\n * The staged target is a real docs repo, not a folder of markdown.\n *\n * FOLLOW-UP.md tells the migrator to validate, rebase and vouch against this\n * directory, and every one of those commands resolves its fleet from loam.json:\n * without these three files none of the instructions it gives can be executed,\n * and the reviewer has no way to see what is still missing. The landscape is\n * laid down EMPTY for the same reason `loam init` lays it down empty — an absent\n * landscape silences every cross-service check, and a generated one would be a\n * guess presented as the map. Each staged service then shows up as exactly one\n * `landscape.service-unmodelled` error, which is the first follow-up item.\n *\n * The bytes come from `docs.ts`, so this IS the repo `loam init` makes rather\n * than a lookalike. Only the landscape's opening comment differs, and it differs\n * through a parameter: the migrator needs to be told why their map is empty,\n * and everything after that sentence is advice that does not depend on how the\n * repo was created.\n */\nfunction docsRepoScaffold(target: string): PlannedWrite[] {\n return docsRepoFiles({\n landscapePreamble: \"// Fleet map for a staged OpenSpec migration. It arrives EMPTY because\\n\"\n + \"// OpenSpec has no topology: loam has nothing to read here and will not\\n\"\n + \"// guess \\\"who calls whom\\\" into the source of truth. Every services/<id>/\\n\"\n + \"// staged beside this file needs an element and a binding below — until\\n\"\n + \"// then each one is a `landscape.service-unmodelled` error.\",\n }).map(([rel, content]) => planWrite(join(target, rel), content));\n}\n\nfunction renderFollowUp(blockers: string[]): string {\n return `# Staged OpenSpec migration: required follow-up\\n\\nThis target contains migrated living requirements, mapped active feature deltas, preserved source artifacts, and a review plan. It is deliberately not presented as a fully valid loam fleet. Complete every item before moving it into live docs.\\n\\n${blockers.map((item) => `- [ ] ${item}`).join(\"\\n\")}\\n`;\n}\n"]}
@@ -0,0 +1,142 @@
1
+ /**
2
+ * The two verbs of the OpenSpec on-ramp, and nothing else.
3
+ *
4
+ * They are one module because they are two halves of one procedure and share
5
+ * the failure mapping below: `audit-openspec` reads a workspace and offers the
6
+ * decision skeleton, `migrate-openspec` takes that skeleton back filled in and
7
+ * — only with `--apply` — materializes a staged target. Finding
8
+ * incompatibilities is a successful audit, so exit status is decided here and
9
+ * only here; every phase under `./openspec/` and `./materialize/` refuses by
10
+ * throwing `OpenSpecCommandError` and never touches `process.exitCode`.
11
+ */
12
+ import { dirname, join, resolve } from "node:path";
13
+ import { fail, emitJson } from "../../core/envelope/json.js";
14
+ import { inventoryOpenSpec } from "../../core/openspec/inventory.js";
15
+ import { createOpenSpecMappingSkeleton } from "../../core/openspec/model/mapping.js";
16
+ import { OpenSpecRootError } from "../../core/openspec/model/model.js";
17
+ import { writeMappingSkeleton } from "./openspec/decisions.js";
18
+ import { OpenSpecCommandError } from "./openspec/error.js";
19
+ import { readMapping } from "./openspec/mapping.js";
20
+ import { planMigrationWrites, writeMigrationTarget } from "./materialize/target.js";
21
+ import { printInventory } from "./print.js";
22
+ /** Registers the read-only audit and the separate, mapping-driven migration planner. */
23
+ export function registerMigrateOpenSpec(program) {
24
+ program
25
+ .command("audit-openspec")
26
+ .argument("<root>", "OpenSpec root, Store checkout, or workspace containing openspec/")
27
+ .description("Audit an OpenSpec workspace without treating human mapping decisions as command failure")
28
+ .option("--write-mapping <path>", "write a non-overwriting, digest-bound decision skeleton outside the source workspace")
29
+ .option("--json", "emit the machine contract instead of the human view")
30
+ .action(async (root, opts) => {
31
+ const json = opts.json === true;
32
+ try {
33
+ const inventory = await inventoryOpenSpec(root);
34
+ const skeleton = createOpenSpecMappingSkeleton(inventory);
35
+ const mappingWritten = opts.writeMapping === undefined
36
+ ? null
37
+ : await writeMappingSkeleton(inventory, opts.writeMapping, skeleton);
38
+ if (json) {
39
+ emitJson({
40
+ command: "audit-openspec",
41
+ readOnly: mappingWritten === null,
42
+ mappingWritten,
43
+ mappingSkeleton: skeleton,
44
+ ...inventory,
45
+ });
46
+ }
47
+ else {
48
+ printInventory(inventory, "audit");
49
+ if (mappingWritten !== null)
50
+ console.log(`\n mapping skeleton ${mappingWritten}`);
51
+ else
52
+ console.log("\n read-only audit: no files were created or changed");
53
+ }
54
+ // Finding incompatibilities is a successful audit result. Root/YAML/IO
55
+ // failures still exit 1 through the catch below; migration readiness has
56
+ // its own boolean and migrate-openspec exit status.
57
+ }
58
+ catch (error) {
59
+ reportCommandError(json, error);
60
+ }
61
+ });
62
+ program
63
+ .command("migrate-openspec")
64
+ .argument("<root>", "OpenSpec root, Store checkout, or workspace containing openspec/")
65
+ .description("Validate explicit migration mappings and optionally materialize staged migration docs")
66
+ .option("--map <path>", "YAML mapping created from `audit-openspec --write-mapping`")
67
+ .option("--mapping <path>", "deprecated alias for --map")
68
+ .option("--apply", "materialize staged migration docs; dry-run is the default")
69
+ .option("--target <directory>", "empty standalone target for --apply; never writes into the OpenSpec source or live loam docs")
70
+ .option("--json", "emit the machine contract instead of the human view")
71
+ .action(async (root, opts) => {
72
+ const json = opts.json === true;
73
+ try {
74
+ if (opts.map !== undefined && opts.mapping !== undefined) {
75
+ throw new OpenSpecCommandError("invalid-option", "Pass --map or its deprecated --mapping alias, not both.");
76
+ }
77
+ const mapArg = opts.map ?? opts.mapping;
78
+ if (mapArg === undefined) {
79
+ throw new OpenSpecCommandError("invalid-option", "migrate-openspec requires --map <path>; run `loam audit-openspec <root> --write-mapping <path>` first.");
80
+ }
81
+ if (opts.apply === true && opts.target === undefined) {
82
+ throw new OpenSpecCommandError("invalid-option", "--apply requires an explicit --target <empty-directory>.");
83
+ }
84
+ if (opts.apply !== true && opts.target !== undefined) {
85
+ throw new OpenSpecCommandError("invalid-option", "--target only has effect with explicit --apply.");
86
+ }
87
+ const mappingPath = resolve(mapArg);
88
+ const mapping = await readMapping(mappingPath);
89
+ // Re-audit the source at the point of use. inventoryOpenSpec compares
90
+ // the fresh digest and canonical root to the binding in the mapping.
91
+ const inventory = await inventoryOpenSpec(root, { mapping });
92
+ const target = opts.apply === true
93
+ ? resolve(opts.target)
94
+ : join(dirname(mappingPath), ".loam-openspec-dry-run-target");
95
+ const planned = inventory.ready
96
+ ? await planMigrationWrites(inventory, mapping, target)
97
+ : null;
98
+ let applied = null;
99
+ if (opts.apply === true) {
100
+ if (!inventory.ready || planned === null) {
101
+ throw new OpenSpecCommandError("invalid-option", "Migration cannot be applied until living/active shapes, capability mappings, change-to-feature decisions, active RENAMED identities, authored artifact dispositions, and source digest binding are resolved.");
102
+ }
103
+ applied = await writeMigrationTarget(inventory, mapping, target, planned);
104
+ }
105
+ if (json) {
106
+ emitJson({
107
+ command: "migrate-openspec",
108
+ dryRun: applied === null,
109
+ mappingPath,
110
+ applied,
111
+ ...inventory,
112
+ });
113
+ }
114
+ else {
115
+ printInventory(inventory, "migration");
116
+ if (applied === null)
117
+ console.log("\n dry-run: no files were created or changed");
118
+ else {
119
+ console.log(`\n staged migration docs ${applied.directory}`);
120
+ console.log(` follow-up blockers ${applied.followUpBlockers.length} (see FOLLOW-UP.md)`);
121
+ }
122
+ }
123
+ if (!inventory.ready)
124
+ process.exitCode = 1;
125
+ }
126
+ catch (error) {
127
+ reportCommandError(json, error);
128
+ }
129
+ });
130
+ }
131
+ function reportCommandError(json, error) {
132
+ if (error instanceof OpenSpecRootError) {
133
+ fail(json, "unknown-target", error.message);
134
+ return;
135
+ }
136
+ if (error instanceof OpenSpecCommandError) {
137
+ fail(json, error.code, error.message);
138
+ return;
139
+ }
140
+ throw error;
141
+ }
142
+ //# sourceMappingURL=migrate-openspec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrate-openspec.js","sourceRoot":"","sources":["../../../src/commands/migrate-openspec/migrate-openspec.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The two verbs of the OpenSpec on-ramp, and nothing else.\n *\n * They are one module because they are two halves of one procedure and share\n * the failure mapping below: `audit-openspec` reads a workspace and offers the\n * decision skeleton, `migrate-openspec` takes that skeleton back filled in and\n * — only with `--apply` — materializes a staged target. Finding\n * incompatibilities is a successful audit, so exit status is decided here and\n * only here; every phase under `./openspec/` and `./materialize/` refuses by\n * throwing `OpenSpecCommandError` and never touches `process.exitCode`.\n */\nimport { dirname, join, resolve } from \"node:path\";\nimport type { Command } from \"commander\";\nimport { fail, emitJson } from \"../../core/envelope/json.js\";\nimport { inventoryOpenSpec } from \"../../core/openspec/inventory.js\";\nimport { createOpenSpecMappingSkeleton } from \"../../core/openspec/model/mapping.js\";\nimport { OpenSpecRootError } from \"../../core/openspec/model/model.js\";\nimport { writeMappingSkeleton } from \"./openspec/decisions.js\";\nimport { OpenSpecCommandError } from \"./openspec/error.js\";\nimport { readMapping } from \"./openspec/mapping.js\";\nimport { planMigrationWrites, writeMigrationTarget } from \"./materialize/target.js\";\nimport { printInventory } from \"./print.js\";\n\ninterface AuditOpenSpecOptions {\n json?: boolean;\n writeMapping?: string;\n}\n\ninterface MigrateOpenSpecOptions {\n json?: boolean;\n map?: string;\n mapping?: string;\n apply?: boolean;\n target?: string;\n}\n\n/** Registers the read-only audit and the separate, mapping-driven migration planner. */\nexport function registerMigrateOpenSpec(program: Command): void {\n program\n .command(\"audit-openspec\")\n .argument(\"<root>\", \"OpenSpec root, Store checkout, or workspace containing openspec/\")\n .description(\"Audit an OpenSpec workspace without treating human mapping decisions as command failure\")\n .option(\"--write-mapping <path>\", \"write a non-overwriting, digest-bound decision skeleton outside the source workspace\")\n .option(\"--json\", \"emit the machine contract instead of the human view\")\n .action(async (root: string, opts: AuditOpenSpecOptions) => {\n const json = opts.json === true;\n try {\n const inventory = await inventoryOpenSpec(root);\n const skeleton = createOpenSpecMappingSkeleton(inventory);\n const mappingWritten = opts.writeMapping === undefined\n ? null\n : await writeMappingSkeleton(inventory, opts.writeMapping, skeleton);\n if (json) {\n emitJson({\n command: \"audit-openspec\",\n readOnly: mappingWritten === null,\n mappingWritten,\n mappingSkeleton: skeleton,\n ...inventory,\n });\n } else {\n printInventory(inventory, \"audit\");\n if (mappingWritten !== null) console.log(`\\n mapping skeleton ${mappingWritten}`);\n else console.log(\"\\n read-only audit: no files were created or changed\");\n }\n // Finding incompatibilities is a successful audit result. Root/YAML/IO\n // failures still exit 1 through the catch below; migration readiness has\n // its own boolean and migrate-openspec exit status.\n } catch (error) {\n reportCommandError(json, error);\n }\n });\n\n program\n .command(\"migrate-openspec\")\n .argument(\"<root>\", \"OpenSpec root, Store checkout, or workspace containing openspec/\")\n .description(\"Validate explicit migration mappings and optionally materialize staged migration docs\")\n .option(\"--map <path>\", \"YAML mapping created from `audit-openspec --write-mapping`\")\n .option(\"--mapping <path>\", \"deprecated alias for --map\")\n .option(\"--apply\", \"materialize staged migration docs; dry-run is the default\")\n .option(\"--target <directory>\", \"empty standalone target for --apply; never writes into the OpenSpec source or live loam docs\")\n .option(\"--json\", \"emit the machine contract instead of the human view\")\n .action(async (root: string, opts: MigrateOpenSpecOptions) => {\n const json = opts.json === true;\n try {\n if (opts.map !== undefined && opts.mapping !== undefined) {\n throw new OpenSpecCommandError(\"invalid-option\", \"Pass --map or its deprecated --mapping alias, not both.\");\n }\n const mapArg = opts.map ?? opts.mapping;\n if (mapArg === undefined) {\n throw new OpenSpecCommandError(\n \"invalid-option\",\n \"migrate-openspec requires --map <path>; run `loam audit-openspec <root> --write-mapping <path>` first.\",\n );\n }\n if (opts.apply === true && opts.target === undefined) {\n throw new OpenSpecCommandError(\"invalid-option\", \"--apply requires an explicit --target <empty-directory>.\");\n }\n if (opts.apply !== true && opts.target !== undefined) {\n throw new OpenSpecCommandError(\"invalid-option\", \"--target only has effect with explicit --apply.\");\n }\n const mappingPath = resolve(mapArg);\n const mapping = await readMapping(mappingPath);\n // Re-audit the source at the point of use. inventoryOpenSpec compares\n // the fresh digest and canonical root to the binding in the mapping.\n const inventory = await inventoryOpenSpec(root, { mapping });\n const target = opts.apply === true\n ? resolve(opts.target!)\n : join(dirname(mappingPath), \".loam-openspec-dry-run-target\");\n const planned = inventory.ready\n ? await planMigrationWrites(inventory, mapping, target)\n : null;\n let applied: { directory: string; files: string[]; followUpBlockers: string[] } | null = null;\n if (opts.apply === true) {\n if (!inventory.ready || planned === null) {\n throw new OpenSpecCommandError(\n \"invalid-option\",\n \"Migration cannot be applied until living/active shapes, capability mappings, change-to-feature decisions, active RENAMED identities, authored artifact dispositions, and source digest binding are resolved.\",\n );\n }\n applied = await writeMigrationTarget(inventory, mapping, target, planned);\n }\n\n if (json) {\n emitJson({\n command: \"migrate-openspec\",\n dryRun: applied === null,\n mappingPath,\n applied,\n ...inventory,\n });\n } else {\n printInventory(inventory, \"migration\");\n if (applied === null) console.log(\"\\n dry-run: no files were created or changed\");\n else {\n console.log(`\\n staged migration docs ${applied.directory}`);\n console.log(` follow-up blockers ${applied.followUpBlockers.length} (see FOLLOW-UP.md)`);\n }\n }\n if (!inventory.ready) process.exitCode = 1;\n } catch (error) {\n reportCommandError(json, error);\n }\n });\n}\n\nfunction reportCommandError(json: boolean, error: unknown): void {\n if (error instanceof OpenSpecRootError) {\n fail(json, \"unknown-target\", error.message);\n return;\n }\n if (error instanceof OpenSpecCommandError) {\n fail(json, error.code, error.message);\n return;\n }\n throw error;\n}\n"]}