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

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 (1036) hide show
  1. package/CHANGELOG.md +2635 -86
  2. package/COMPARISON.md +80 -63
  3. package/CONTRIBUTING.md +84 -0
  4. package/MIGRATING-from-OpenSpec.md +213 -54
  5. package/QUICKSTART.md +125 -0
  6. package/README.md +450 -150
  7. package/ROADMAP.md +599 -0
  8. package/SCHEMA.md +2355 -256
  9. package/SECURITY.md +21 -3
  10. package/WORKFLOW.md +701 -0
  11. package/dist/cli.js +113 -19
  12. package/dist/cli.js.map +1 -1
  13. package/dist/commands/adopt/adopt.js +209 -0
  14. package/dist/commands/adopt/adopt.js.map +1 -0
  15. package/dist/commands/adopt/render.js +268 -0
  16. package/dist/commands/adopt/render.js.map +1 -0
  17. package/dist/commands/archive/archive.js +77 -0
  18. package/dist/commands/archive/archive.js.map +1 -0
  19. package/dist/commands/archive/plan/contracts/asyncapi.js +178 -0
  20. package/dist/commands/archive/plan/contracts/asyncapi.js.map +1 -0
  21. package/dist/commands/archive/plan/contracts/openapi.js +159 -0
  22. package/dist/commands/archive/plan/contracts/openapi.js.map +1 -0
  23. package/dist/commands/archive/plan/gate.js +323 -0
  24. package/dist/commands/archive/plan/gate.js.map +1 -0
  25. package/dist/commands/archive/plan/landscape.js +180 -0
  26. package/dist/commands/archive/plan/landscape.js.map +1 -0
  27. package/dist/commands/archive/plan/refusal.js +111 -0
  28. package/dist/commands/archive/plan/refusal.js.map +1 -0
  29. package/dist/commands/archive/plan/specs.js +237 -0
  30. package/dist/commands/archive/plan/specs.js.map +1 -0
  31. package/dist/commands/archive/plan/state.js +27 -0
  32. package/dist/commands/archive/plan/state.js.map +1 -0
  33. package/dist/commands/archive/run.js +252 -0
  34. package/dist/commands/archive/run.js.map +1 -0
  35. package/dist/commands/context/context.js +99 -0
  36. package/dist/commands/context/context.js.map +1 -0
  37. package/dist/commands/context/print.js +283 -0
  38. package/dist/commands/context/print.js.map +1 -0
  39. package/dist/commands/delta/delta.js +279 -0
  40. package/dist/commands/delta/delta.js.map +1 -0
  41. package/dist/commands/delta/print.js +205 -0
  42. package/dist/commands/delta/print.js.map +1 -0
  43. package/dist/commands/dependencies.js +9 -7
  44. package/dist/commands/dependencies.js.map +1 -1
  45. package/dist/commands/diff/diff.js +93 -0
  46. package/dist/commands/diff/diff.js.map +1 -0
  47. package/dist/commands/diff/print.js +38 -0
  48. package/dist/commands/diff/print.js.map +1 -0
  49. package/dist/commands/doctor.js +5 -4
  50. package/dist/commands/doctor.js.map +1 -1
  51. package/dist/commands/explain/explain.js +151 -0
  52. package/dist/commands/explain/explain.js.map +1 -0
  53. package/dist/commands/explore.js +29 -24
  54. package/dist/commands/explore.js.map +1 -1
  55. package/dist/commands/gate/gate.js +115 -0
  56. package/dist/commands/gate/gate.js.map +1 -0
  57. package/dist/commands/gate/print.js +54 -0
  58. package/dist/commands/gate/print.js.map +1 -0
  59. package/dist/commands/gherkin/commit.js +146 -0
  60. package/dist/commands/gherkin/commit.js.map +1 -0
  61. package/dist/commands/gherkin/gherkin.js +246 -0
  62. package/dist/commands/gherkin/gherkin.js.map +1 -0
  63. package/dist/commands/gherkin/reconcile.js +149 -0
  64. package/dist/commands/gherkin/reconcile.js.map +1 -0
  65. package/dist/commands/gherkin/render.js +77 -0
  66. package/dist/commands/gherkin/render.js.map +1 -0
  67. package/dist/commands/init/example.js +204 -0
  68. package/dist/commands/init/example.js.map +1 -0
  69. package/dist/commands/init/first-hour.js +28 -0
  70. package/dist/commands/init/first-hour.js.map +1 -0
  71. package/dist/commands/{init.js → init/init.js} +146 -71
  72. package/dist/commands/init/init.js.map +1 -0
  73. package/dist/commands/init/mcp.js +131 -0
  74. package/dist/commands/init/mcp.js.map +1 -0
  75. package/dist/commands/init/options.js +78 -0
  76. package/dist/commands/init/options.js.map +1 -0
  77. package/dist/commands/instructions.js +72 -14
  78. package/dist/commands/instructions.js.map +1 -1
  79. package/dist/commands/list/campaign/campaign.js +65 -0
  80. package/dist/commands/list/campaign/campaign.js.map +1 -0
  81. package/dist/commands/list/campaign/owners.js +65 -0
  82. package/dist/commands/list/campaign/owners.js.map +1 -0
  83. package/dist/commands/list/json.js +157 -0
  84. package/dist/commands/list/json.js.map +1 -0
  85. package/dist/commands/list/list.js +343 -0
  86. package/dist/commands/list/list.js.map +1 -0
  87. package/dist/commands/list/print.js +301 -0
  88. package/dist/commands/list/print.js.map +1 -0
  89. package/dist/commands/list/review.js +120 -0
  90. package/dist/commands/list/review.js.map +1 -0
  91. package/dist/commands/list/views.js +105 -0
  92. package/dist/commands/list/views.js.map +1 -0
  93. package/dist/commands/mcp/dispatch.js +183 -0
  94. package/dist/commands/mcp/dispatch.js.map +1 -0
  95. package/dist/commands/mcp/mcp.js +34 -0
  96. package/dist/commands/mcp/mcp.js.map +1 -0
  97. package/dist/commands/mcp/serve.js +55 -0
  98. package/dist/commands/mcp/serve.js.map +1 -0
  99. package/dist/commands/migrate-openspec/materialize/active.js +170 -0
  100. package/dist/commands/migrate-openspec/materialize/active.js.map +1 -0
  101. package/dist/commands/migrate-openspec/materialize/feature.js +41 -0
  102. package/dist/commands/migrate-openspec/materialize/feature.js.map +1 -0
  103. package/dist/commands/migrate-openspec/materialize/living.js +62 -0
  104. package/dist/commands/migrate-openspec/materialize/living.js.map +1 -0
  105. package/dist/commands/migrate-openspec/materialize/stage.js +142 -0
  106. package/dist/commands/migrate-openspec/materialize/stage.js.map +1 -0
  107. package/dist/commands/migrate-openspec/materialize/target.js +219 -0
  108. package/dist/commands/migrate-openspec/materialize/target.js.map +1 -0
  109. package/dist/commands/migrate-openspec/migrate-openspec.js +142 -0
  110. package/dist/commands/migrate-openspec/migrate-openspec.js.map +1 -0
  111. package/dist/commands/migrate-openspec/openspec/decisions.js +91 -0
  112. package/dist/commands/migrate-openspec/openspec/decisions.js.map +1 -0
  113. package/dist/commands/migrate-openspec/openspec/error.js +19 -0
  114. package/dist/commands/migrate-openspec/openspec/error.js.map +1 -0
  115. package/dist/commands/migrate-openspec/openspec/mapping.js +170 -0
  116. package/dist/commands/migrate-openspec/openspec/mapping.js.map +1 -0
  117. package/dist/commands/migrate-openspec/openspec/paths.js +43 -0
  118. package/dist/commands/migrate-openspec/openspec/paths.js.map +1 -0
  119. package/dist/commands/migrate-openspec/openspec/read.js +49 -0
  120. package/dist/commands/migrate-openspec/openspec/read.js.map +1 -0
  121. package/dist/commands/migrate-openspec/print.js +89 -0
  122. package/dist/commands/migrate-openspec/print.js.map +1 -0
  123. package/dist/commands/new/commit.js +76 -0
  124. package/dist/commands/new/commit.js.map +1 -0
  125. package/dist/commands/new/new.js +283 -0
  126. package/dist/commands/new/new.js.map +1 -0
  127. package/dist/commands/new/templates.js +355 -0
  128. package/dist/commands/new/templates.js.map +1 -0
  129. package/dist/commands/open.js +203 -0
  130. package/dist/commands/open.js.map +1 -0
  131. package/dist/commands/policy/format.js +152 -0
  132. package/dist/commands/policy/format.js.map +1 -0
  133. package/dist/commands/{docs-repo-gate.js → policy/gate.js} +11 -11
  134. package/dist/commands/policy/gate.js.map +1 -0
  135. package/dist/commands/rebase/edit.js +106 -0
  136. package/dist/commands/rebase/edit.js.map +1 -0
  137. package/dist/commands/rebase/living.js +185 -0
  138. package/dist/commands/rebase/living.js.map +1 -0
  139. package/dist/commands/rebase/plan.js +245 -0
  140. package/dist/commands/rebase/plan.js.map +1 -0
  141. package/dist/commands/rebase/rebase.js +275 -0
  142. package/dist/commands/rebase/rebase.js.map +1 -0
  143. package/dist/commands/seed/commit.js +192 -0
  144. package/dist/commands/seed/commit.js.map +1 -0
  145. package/dist/commands/seed/plan.js +133 -0
  146. package/dist/commands/seed/plan.js.map +1 -0
  147. package/dist/commands/seed/seed.js +172 -0
  148. package/dist/commands/seed/seed.js.map +1 -0
  149. package/dist/commands/show/feature.js +178 -0
  150. package/dist/commands/show/feature.js.map +1 -0
  151. package/dist/commands/show/marks.js +24 -0
  152. package/dist/commands/show/marks.js.map +1 -0
  153. package/dist/commands/{show.js → show/service.js} +63 -152
  154. package/dist/commands/show/service.js.map +1 -0
  155. package/dist/commands/show/show.js +77 -0
  156. package/dist/commands/show/show.js.map +1 -0
  157. package/dist/commands/status/json.js +45 -0
  158. package/dist/commands/status/json.js.map +1 -0
  159. package/dist/commands/status/print.js +157 -0
  160. package/dist/commands/status/print.js.map +1 -0
  161. package/dist/commands/status/status.js +119 -0
  162. package/dist/commands/status/status.js.map +1 -0
  163. package/dist/commands/steps/steps.js +189 -0
  164. package/dist/commands/steps/steps.js.map +1 -0
  165. package/dist/commands/subsystem/edit.js +192 -0
  166. package/dist/commands/subsystem/edit.js.map +1 -0
  167. package/dist/commands/subsystem/move.js +265 -0
  168. package/dist/commands/subsystem/move.js.map +1 -0
  169. package/dist/commands/subsystem/query.js +115 -0
  170. package/dist/commands/subsystem/query.js.map +1 -0
  171. package/dist/commands/subsystem/subsystem.js +101 -0
  172. package/dist/commands/subsystem/subsystem.js.map +1 -0
  173. package/dist/commands/subsystem/sync.js +103 -0
  174. package/dist/commands/subsystem/sync.js.map +1 -0
  175. package/dist/commands/subsystem/txn/txn.js +94 -0
  176. package/dist/commands/subsystem/txn/txn.js.map +1 -0
  177. package/dist/commands/subsystem/txn/views.js +70 -0
  178. package/dist/commands/subsystem/txn/views.js.map +1 -0
  179. package/dist/commands/unarchive/manifest.js +160 -0
  180. package/dist/commands/unarchive/manifest.js.map +1 -0
  181. package/dist/commands/{unarchive.js → unarchive/restore.js} +47 -160
  182. package/dist/commands/unarchive/restore.js.map +1 -0
  183. package/dist/commands/unarchive/unarchive.js +67 -0
  184. package/dist/commands/unarchive/unarchive.js.map +1 -0
  185. package/dist/commands/validate/arch-coverage.js +204 -0
  186. package/dist/commands/validate/arch-coverage.js.map +1 -0
  187. package/dist/commands/validate/checks/fleet-shape.js +296 -0
  188. package/dist/commands/validate/checks/fleet-shape.js.map +1 -0
  189. package/dist/commands/validate/checks/health-deps.js +55 -0
  190. package/dist/commands/validate/checks/health-deps.js.map +1 -0
  191. package/dist/commands/validate/checks/requirements.js +254 -0
  192. package/dist/commands/validate/checks/requirements.js.map +1 -0
  193. package/dist/commands/validate/checks/sources.js +76 -0
  194. package/dist/commands/validate/checks/sources.js.map +1 -0
  195. package/dist/commands/validate/checks/vocabulary.js +31 -0
  196. package/dist/commands/validate/checks/vocabulary.js.map +1 -0
  197. package/dist/commands/validate/feature.js +216 -0
  198. package/dist/commands/validate/feature.js.map +1 -0
  199. package/dist/commands/validate/fleet/census.js +69 -0
  200. package/dist/commands/validate/fleet/census.js.map +1 -0
  201. package/dist/commands/validate/fleet/kind-tags.js +39 -0
  202. package/dist/commands/validate/fleet/kind-tags.js.map +1 -0
  203. package/dist/commands/validate/fleet/landscape.js +353 -0
  204. package/dist/commands/validate/fleet/landscape.js.map +1 -0
  205. package/dist/commands/validate/fleet/load.js +52 -0
  206. package/dist/commands/validate/fleet/load.js.map +1 -0
  207. package/dist/commands/validate/fleet/obligations.js +270 -0
  208. package/dist/commands/validate/fleet/obligations.js.map +1 -0
  209. package/dist/commands/validate/fleet/scorecard/adoption.js +102 -0
  210. package/dist/commands/validate/fleet/scorecard/adoption.js.map +1 -0
  211. package/dist/commands/validate/fleet/scorecard/contracts.js +98 -0
  212. package/dist/commands/validate/fleet/scorecard/contracts.js.map +1 -0
  213. package/dist/commands/validate/fleet/scorecard/print.js +63 -0
  214. package/dist/commands/validate/fleet/scorecard/print.js.map +1 -0
  215. package/dist/commands/validate/fleet/scorecard/scorecard.js +156 -0
  216. package/dist/commands/validate/fleet/scorecard/scorecard.js.map +1 -0
  217. package/dist/commands/validate/fleet/usecases/capability-tag.js +94 -0
  218. package/dist/commands/validate/fleet/usecases/capability-tag.js.map +1 -0
  219. package/dist/commands/validate/fleet/usecases/place.js +13 -0
  220. package/dist/commands/validate/fleet/usecases/place.js.map +1 -0
  221. package/dist/commands/validate/fleet/usecases/requirement-tag.js +95 -0
  222. package/dist/commands/validate/fleet/usecases/requirement-tag.js.map +1 -0
  223. package/dist/commands/validate/fleet/usecases/steps.js +197 -0
  224. package/dist/commands/validate/fleet/usecases/steps.js.map +1 -0
  225. package/dist/commands/validate/fleet/usecases/usecases.js +99 -0
  226. package/dist/commands/validate/fleet/usecases/usecases.js.map +1 -0
  227. package/dist/commands/validate/fleet/views/ids.js +40 -0
  228. package/dist/commands/validate/fleet/views/ids.js.map +1 -0
  229. package/dist/commands/validate/fleet/views/stale.js +59 -0
  230. package/dist/commands/validate/fleet/views/stale.js.map +1 -0
  231. package/dist/commands/validate/links/corpus.js +92 -0
  232. package/dist/commands/validate/links/corpus.js.map +1 -0
  233. package/dist/commands/validate/links/glossary.js +75 -0
  234. package/dist/commands/validate/links/glossary.js.map +1 -0
  235. package/dist/commands/validate/report.js +269 -0
  236. package/dist/commands/validate/report.js.map +1 -0
  237. package/dist/commands/validate/service/api.js +338 -0
  238. package/dist/commands/validate/service/api.js.map +1 -0
  239. package/dist/commands/validate/service/events/events.js +219 -0
  240. package/dist/commands/validate/service/events/events.js.map +1 -0
  241. package/dist/commands/validate/service/events/message-producers.js +77 -0
  242. package/dist/commands/validate/service/events/message-producers.js.map +1 -0
  243. package/dist/commands/validate/service/evidence-pins.js +131 -0
  244. package/dist/commands/validate/service/evidence-pins.js.map +1 -0
  245. package/dist/commands/validate/service/service.js +251 -0
  246. package/dist/commands/validate/service/service.js.map +1 -0
  247. package/dist/commands/validate/service/specs.js +251 -0
  248. package/dist/commands/validate/service/specs.js.map +1 -0
  249. package/dist/commands/validate/service/spine.js +113 -0
  250. package/dist/commands/validate/service/spine.js.map +1 -0
  251. package/dist/commands/validate/validate.js +338 -0
  252. package/dist/commands/validate/validate.js.map +1 -0
  253. package/dist/commands/verify/cross/diff.js +182 -0
  254. package/dist/commands/verify/cross/diff.js.map +1 -0
  255. package/dist/commands/verify/evidence/contract.js +32 -0
  256. package/dist/commands/verify/evidence/contract.js.map +1 -0
  257. package/dist/commands/verify/evidence/pins.js +52 -0
  258. package/dist/commands/verify/evidence/pins.js.map +1 -0
  259. package/dist/commands/verify/evidence/read.js +72 -0
  260. package/dist/commands/verify/evidence/read.js.map +1 -0
  261. package/dist/commands/verify/frozen.js +241 -0
  262. package/dist/commands/verify/frozen.js.map +1 -0
  263. package/dist/commands/verify/record.js +226 -0
  264. package/dist/commands/verify/record.js.map +1 -0
  265. package/dist/commands/verify/report.js +223 -0
  266. package/dist/commands/verify/report.js.map +1 -0
  267. package/dist/commands/verify/results.js +246 -0
  268. package/dist/commands/verify/results.js.map +1 -0
  269. package/dist/commands/verify/verify.js +217 -0
  270. package/dist/commands/verify/verify.js.map +1 -0
  271. package/dist/commands/vouch/contract.js +11 -0
  272. package/dist/commands/vouch/contract.js.map +1 -0
  273. package/dist/commands/vouch/pack/contract.js +2 -0
  274. package/dist/commands/vouch/pack/contract.js.map +1 -0
  275. package/dist/commands/vouch/pack/pack.js +266 -0
  276. package/dist/commands/vouch/pack/pack.js.map +1 -0
  277. package/dist/commands/vouch/pack/print.js +271 -0
  278. package/dist/commands/vouch/pack/print.js.map +1 -0
  279. package/dist/commands/vouch/pack/sections.js +142 -0
  280. package/dist/commands/vouch/pack/sections.js.map +1 -0
  281. package/dist/commands/vouch/prompt/confirm.js +46 -0
  282. package/dist/commands/vouch/prompt/confirm.js.map +1 -0
  283. package/dist/commands/vouch/report.js +101 -0
  284. package/dist/commands/vouch/report.js.map +1 -0
  285. package/dist/commands/vouch/run.js +285 -0
  286. package/dist/commands/vouch/run.js.map +1 -0
  287. package/dist/commands/vouch/sample/plan.js +125 -0
  288. package/dist/commands/vouch/sample/plan.js.map +1 -0
  289. package/dist/commands/vouch/sample/print.js +109 -0
  290. package/dist/commands/vouch/sample/print.js.map +1 -0
  291. package/dist/commands/vouch/vet/verify.js +123 -0
  292. package/dist/commands/vouch/vet/verify.js.map +1 -0
  293. package/dist/commands/vouch/vouch.js +176 -0
  294. package/dist/commands/vouch/vouch.js.map +1 -0
  295. package/dist/core/agent/agents-md/artifacts.js +220 -0
  296. package/dist/core/agent/agents-md/artifacts.js.map +1 -0
  297. package/dist/core/agent/agents-md/command-map.js +324 -0
  298. package/dist/core/agent/agents-md/command-map.js.map +1 -0
  299. package/dist/core/agent/agents-md/cycle.js +165 -0
  300. package/dist/core/agent/agents-md/cycle.js.map +1 -0
  301. package/dist/core/agent/agents-md/map/explain.js +34 -0
  302. package/dist/core/agent/agents-md/map/explain.js.map +1 -0
  303. package/dist/core/agent/agents-md/map/lenses/context.js +41 -0
  304. package/dist/core/agent/agents-md/map/lenses/context.js.map +1 -0
  305. package/dist/core/agent/agents-md/map/lenses/diff.js +46 -0
  306. package/dist/core/agent/agents-md/map/lenses/diff.js.map +1 -0
  307. package/dist/core/agent/agents-md/map/lenses/gate.js +57 -0
  308. package/dist/core/agent/agents-md/map/lenses/gate.js.map +1 -0
  309. package/dist/core/agent/agents-md/map/mcp.js +41 -0
  310. package/dist/core/agent/agents-md/map/mcp.js.map +1 -0
  311. package/dist/core/agent/agents-md/map/status.js +62 -0
  312. package/dist/core/agent/agents-md/map/status.js.map +1 -0
  313. package/dist/core/agent/agents-md/map/subsystem.js +32 -0
  314. package/dist/core/agent/agents-md/map/subsystem.js.map +1 -0
  315. package/dist/core/agent/agents-md/map/usecases.js +60 -0
  316. package/dist/core/agent/agents-md/map/usecases.js.map +1 -0
  317. package/dist/core/agent/agents-md/refusals.js +246 -0
  318. package/dist/core/agent/agents-md/refusals.js.map +1 -0
  319. package/dist/core/agent/agents-md/shipped/archive-gate.js +98 -0
  320. package/dist/core/agent/agents-md/shipped/archive-gate.js.map +1 -0
  321. package/dist/core/agent/agents-md/spine.js +40 -0
  322. package/dist/core/agent/agents-md/spine.js.map +1 -0
  323. package/dist/core/agent/agents-md.js +170 -0
  324. package/dist/core/agent/agents-md.js.map +1 -0
  325. package/dist/core/{agents-stamp.js → agent/agents-stamp.js} +50 -0
  326. package/dist/core/agent/agents-stamp.js.map +1 -0
  327. package/dist/core/agent/contract.js +2 -0
  328. package/dist/core/agent/contract.js.map +1 -0
  329. package/dist/core/agent/protocol.js +193 -0
  330. package/dist/core/agent/protocol.js.map +1 -0
  331. package/dist/core/agent/scaffold.js +259 -0
  332. package/dist/core/agent/scaffold.js.map +1 -0
  333. package/dist/core/agent/support/report.js +103 -0
  334. package/dist/core/agent/support/report.js.map +1 -0
  335. package/dist/core/agent/tools/dialects.js +150 -0
  336. package/dist/core/agent/tools/dialects.js.map +1 -0
  337. package/dist/core/agent/tools/registry.js +228 -0
  338. package/dist/core/agent/tools/registry.js.map +1 -0
  339. package/dist/core/agent/workflows/adopt.js +133 -0
  340. package/dist/core/agent/workflows/adopt.js.map +1 -0
  341. package/dist/core/agent/workflows/check.js +337 -0
  342. package/dist/core/agent/workflows/check.js.map +1 -0
  343. package/dist/core/agent/workflows/closing.js +262 -0
  344. package/dist/core/agent/workflows/closing.js.map +1 -0
  345. package/dist/core/agent/workflows/feature.js +105 -0
  346. package/dist/core/agent/workflows/feature.js.map +1 -0
  347. package/dist/core/agent/workflows/implement.js +105 -0
  348. package/dist/core/agent/workflows/implement.js.map +1 -0
  349. package/dist/core/agent/workflows/reference/authoring.js +209 -0
  350. package/dist/core/agent/workflows/reference/authoring.js.map +1 -0
  351. package/dist/core/agent/workflows/reference/codes.js +65 -0
  352. package/dist/core/agent/workflows/reference/codes.js.map +1 -0
  353. package/dist/core/agent/workflows/reference/done-check.js +188 -0
  354. package/dist/core/agent/workflows/reference/done-check.js.map +1 -0
  355. package/dist/core/agent/workflows/reference/reference.js +16 -0
  356. package/dist/core/agent/workflows/reference/reference.js.map +1 -0
  357. package/dist/core/agent/workflows/reference/spine.js +297 -0
  358. package/dist/core/agent/workflows/reference/spine.js.map +1 -0
  359. package/dist/core/asyncapi/baseline/plan.js +110 -0
  360. package/dist/core/asyncapi/baseline/plan.js.map +1 -0
  361. package/dist/core/asyncapi/baseline/surfaces.js +54 -0
  362. package/dist/core/asyncapi/baseline/surfaces.js.map +1 -0
  363. package/dist/core/asyncapi/depth.js +164 -0
  364. package/dist/core/asyncapi/depth.js.map +1 -0
  365. package/dist/core/asyncapi/digest.js +141 -0
  366. package/dist/core/asyncapi/digest.js.map +1 -0
  367. package/dist/core/asyncapi/merge/components.js +91 -0
  368. package/dist/core/asyncapi/merge/components.js.map +1 -0
  369. package/dist/core/asyncapi/merge/error.js +33 -0
  370. package/dist/core/asyncapi/merge/error.js.map +1 -0
  371. package/dist/core/asyncapi/merge/markers.js +308 -0
  372. package/dist/core/asyncapi/merge/markers.js.map +1 -0
  373. package/dist/core/asyncapi/merge/merge.js +215 -0
  374. package/dist/core/asyncapi/merge/merge.js.map +1 -0
  375. package/dist/core/asyncapi/merge/pin.js +107 -0
  376. package/dist/core/asyncapi/merge/pin.js.map +1 -0
  377. package/dist/core/asyncapi/model.js +11 -0
  378. package/dist/core/asyncapi/model.js.map +1 -0
  379. package/dist/core/asyncapi/producers.js +50 -0
  380. package/dist/core/asyncapi/producers.js.map +1 -0
  381. package/dist/core/{asyncapi.js → asyncapi/read.js} +95 -109
  382. package/dist/core/asyncapi/read.js.map +1 -0
  383. package/dist/core/brief/brief.js +225 -0
  384. package/dist/core/brief/brief.js.map +1 -0
  385. package/dist/core/brief/checks.js +250 -0
  386. package/dist/core/brief/checks.js.map +1 -0
  387. package/dist/core/brief/landscape.js +194 -0
  388. package/dist/core/brief/landscape.js.map +1 -0
  389. package/dist/core/brief/targets.js +226 -0
  390. package/dist/core/brief/targets.js.map +1 -0
  391. package/dist/core/brief/unchecked.js +48 -0
  392. package/dist/core/brief/unchecked.js.map +1 -0
  393. package/dist/core/c4/arch.js +174 -0
  394. package/dist/core/c4/arch.js.map +1 -0
  395. package/dist/core/c4/likec4.js +90 -0
  396. package/dist/core/c4/likec4.js.map +1 -0
  397. package/dist/core/c4/parsed/deployment.js +158 -0
  398. package/dist/core/c4/parsed/deployment.js.map +1 -0
  399. package/dist/core/c4/parsed/dynamic-views.js +132 -0
  400. package/dist/core/c4/parsed/dynamic-views.js.map +1 -0
  401. package/dist/core/c4/parsed/specification.js +78 -0
  402. package/dist/core/c4/parsed/specification.js.map +1 -0
  403. package/dist/core/c4/parsed/values.js +57 -0
  404. package/dist/core/c4/parsed/values.js.map +1 -0
  405. package/dist/core/c4/parsed/view-ids.js +75 -0
  406. package/dist/core/c4/parsed/view-ids.js.map +1 -0
  407. package/dist/core/c4/project/architecture.js +45 -0
  408. package/dist/core/c4/project/architecture.js.map +1 -0
  409. package/dist/core/c4/project/documents.js +58 -0
  410. package/dist/core/c4/project/documents.js.map +1 -0
  411. package/dist/core/c4/project/load.js +187 -0
  412. package/dist/core/c4/project/load.js.map +1 -0
  413. package/dist/core/c4/project/staged.js +220 -0
  414. package/dist/core/c4/project/staged.js.map +1 -0
  415. package/dist/core/c4/resolve/service.js +159 -0
  416. package/dist/core/c4/resolve/service.js.map +1 -0
  417. package/dist/core/c4/resolve/steps.js +144 -0
  418. package/dist/core/c4/resolve/steps.js.map +1 -0
  419. package/dist/core/c4/seed/fleet-file.js +201 -0
  420. package/dist/core/c4/seed/fleet-file.js.map +1 -0
  421. package/dist/core/c4/seed/items.js +91 -0
  422. package/dist/core/c4/seed/items.js.map +1 -0
  423. package/dist/core/c4/seed/stamp.js +48 -0
  424. package/dist/core/c4/seed/stamp.js.map +1 -0
  425. package/dist/core/c4/seed/template.js +109 -0
  426. package/dist/core/c4/seed/template.js.map +1 -0
  427. package/dist/core/c4/source-mask.js +82 -0
  428. package/dist/core/c4/source-mask.js.map +1 -0
  429. package/dist/core/c4/source-scan.js +227 -0
  430. package/dist/core/c4/source-scan.js.map +1 -0
  431. package/dist/core/c4/splice/authored-source.js +101 -0
  432. package/dist/core/c4/splice/authored-source.js.map +1 -0
  433. package/dist/core/c4/splice/contract.js +10 -0
  434. package/dist/core/c4/splice/contract.js.map +1 -0
  435. package/dist/core/c4/splice/delta-blocks.js +139 -0
  436. package/dist/core/c4/splice/delta-blocks.js.map +1 -0
  437. package/dist/core/c4/splice/identity/edges.js +36 -0
  438. package/dist/core/c4/splice/identity/edges.js.map +1 -0
  439. package/dist/core/c4/splice/landscape-merge.js +269 -0
  440. package/dist/core/c4/splice/landscape-merge.js.map +1 -0
  441. package/dist/core/c4/splice/placement.js +194 -0
  442. package/dist/core/c4/splice/placement.js.map +1 -0
  443. package/dist/core/c4/workspace.js +174 -0
  444. package/dist/core/c4/workspace.js.map +1 -0
  445. package/dist/core/capabilities/authoring/notes.js +141 -0
  446. package/dist/core/capabilities/authoring/notes.js.map +1 -0
  447. package/dist/core/capabilities/capabilities.js +124 -0
  448. package/dist/core/capabilities/capabilities.js.map +1 -0
  449. package/dist/core/capabilities/delta/doc.js +50 -0
  450. package/dist/core/capabilities/delta/doc.js.map +1 -0
  451. package/dist/core/capabilities/delta/overlay.js +129 -0
  452. package/dist/core/capabilities/delta/overlay.js.map +1 -0
  453. package/dist/core/capabilities/delta/summary.js +57 -0
  454. package/dist/core/capabilities/delta/summary.js.map +1 -0
  455. package/dist/core/capabilities/delta/tree.js +43 -0
  456. package/dist/core/capabilities/delta/tree.js.map +1 -0
  457. package/dist/core/capabilities/delta/uncovered.js +222 -0
  458. package/dist/core/capabilities/delta/uncovered.js.map +1 -0
  459. package/dist/core/capabilities/findings.js +342 -0
  460. package/dist/core/capabilities/findings.js.map +1 -0
  461. package/dist/core/capabilities/realizes/findings.js +181 -0
  462. package/dist/core/capabilities/realizes/findings.js.map +1 -0
  463. package/dist/core/capabilities/realizes/join.js +143 -0
  464. package/dist/core/capabilities/realizes/join.js.map +1 -0
  465. package/dist/core/capabilities/rollup.js +199 -0
  466. package/dist/core/capabilities/rollup.js.map +1 -0
  467. package/dist/core/capabilities/tree.js +126 -0
  468. package/dist/core/capabilities/tree.js.map +1 -0
  469. package/dist/core/capabilities/usecase-join.js +277 -0
  470. package/dist/core/capabilities/usecase-join.js.map +1 -0
  471. package/dist/core/coherence/authoring/scaffold.js +177 -0
  472. package/dist/core/coherence/authoring/scaffold.js.map +1 -0
  473. package/dist/core/coherence/authoring/sentinels.js +74 -0
  474. package/dist/core/coherence/authoring/sentinels.js.map +1 -0
  475. package/dist/core/coherence/coherence.js +287 -0
  476. package/dist/core/coherence/coherence.js.map +1 -0
  477. package/dist/core/coherence/declared.js +269 -0
  478. package/dist/core/coherence/declared.js.map +1 -0
  479. package/dist/core/coherence/events/declared.js +206 -0
  480. package/dist/core/coherence/events/declared.js.map +1 -0
  481. package/dist/core/coherence/events/events.js +204 -0
  482. package/dist/core/coherence/events/events.js.map +1 -0
  483. package/dist/core/coherence/events/grades.js +166 -0
  484. package/dist/core/coherence/events/grades.js.map +1 -0
  485. package/dist/core/coherence/events/lookups.js +122 -0
  486. package/dist/core/coherence/events/lookups.js.map +1 -0
  487. package/dist/core/coherence/events/merged.js +40 -0
  488. package/dist/core/coherence/events/merged.js.map +1 -0
  489. package/dist/core/coherence/living.js +198 -0
  490. package/dist/core/coherence/living.js.map +1 -0
  491. package/dist/core/coherence/lookups.js +155 -0
  492. package/dist/core/coherence/lookups.js.map +1 -0
  493. package/dist/core/coherence/pending.js +39 -0
  494. package/dist/core/coherence/pending.js.map +1 -0
  495. package/dist/core/conflict-markers.js +60 -0
  496. package/dist/core/conflict-markers.js.map +1 -0
  497. package/dist/core/delta/claims.js +73 -0
  498. package/dist/core/delta/claims.js.map +1 -0
  499. package/dist/core/delta/delta.js +296 -0
  500. package/dist/core/delta/delta.js.map +1 -0
  501. package/dist/core/delta/document.js +177 -0
  502. package/dist/core/delta/document.js.map +1 -0
  503. package/dist/core/delta/scope.js +48 -0
  504. package/dist/core/delta/scope.js.map +1 -0
  505. package/dist/core/delta/select.js +237 -0
  506. package/dist/core/delta/select.js.map +1 -0
  507. package/dist/core/dependencies/dependencies.js +141 -0
  508. package/dist/core/dependencies/dependencies.js.map +1 -0
  509. package/dist/core/dependencies/facts.js +165 -0
  510. package/dist/core/dependencies/facts.js.map +1 -0
  511. package/dist/core/dependencies/fanin.js +88 -0
  512. package/dist/core/dependencies/fanin.js.map +1 -0
  513. package/dist/core/dependencies/graph.js +106 -0
  514. package/dist/core/dependencies/graph.js.map +1 -0
  515. package/dist/core/deployment/delta.js +188 -0
  516. package/dist/core/deployment/delta.js.map +1 -0
  517. package/dist/core/deployment/objects.js +145 -0
  518. package/dist/core/deployment/objects.js.map +1 -0
  519. package/dist/core/diff/base-git.js +148 -0
  520. package/dist/core/diff/base-git.js.map +1 -0
  521. package/dist/core/diff/base-state.js +209 -0
  522. package/dist/core/diff/base-state.js.map +1 -0
  523. package/dist/core/diff/current-state.js +96 -0
  524. package/dist/core/diff/current-state.js.map +1 -0
  525. package/dist/core/diff/scope/changed-paths.js +188 -0
  526. package/dist/core/diff/scope/changed-paths.js.map +1 -0
  527. package/dist/core/diff/semantic.js +243 -0
  528. package/dist/core/diff/semantic.js.map +1 -0
  529. package/dist/core/diff/victims.js +247 -0
  530. package/dist/core/diff/victims.js.map +1 -0
  531. package/dist/core/docs.js +7 -64
  532. package/dist/core/docs.js.map +1 -1
  533. package/dist/core/doctor/agents.js +222 -0
  534. package/dist/core/doctor/agents.js.map +1 -0
  535. package/dist/core/doctor/config.js +135 -0
  536. package/dist/core/doctor/config.js.map +1 -0
  537. package/dist/core/doctor/doctor.js +275 -0
  538. package/dist/core/doctor/doctor.js.map +1 -0
  539. package/dist/core/doctor/report.js +13 -0
  540. package/dist/core/doctor/report.js.map +1 -0
  541. package/dist/core/doctor/residue.js +110 -0
  542. package/dist/core/doctor/residue.js.map +1 -0
  543. package/dist/core/document/apply.js +77 -0
  544. package/dist/core/document/apply.js.map +1 -0
  545. package/dist/core/{frontmatter.js → document/frontmatter.js} +48 -2
  546. package/dist/core/document/frontmatter.js.map +1 -0
  547. package/dist/core/document/grammar/directives.js +143 -0
  548. package/dist/core/document/grammar/directives.js.map +1 -0
  549. package/dist/core/document/parse.js +263 -0
  550. package/dist/core/document/parse.js.map +1 -0
  551. package/dist/core/document/scenarios.js +221 -0
  552. package/dist/core/document/scenarios.js.map +1 -0
  553. package/dist/core/document/spec.js +241 -0
  554. package/dist/core/document/spec.js.map +1 -0
  555. package/dist/core/{config.js → envelope/config.js} +79 -18
  556. package/dist/core/envelope/config.js.map +1 -0
  557. package/dist/core/envelope/json.js +175 -0
  558. package/dist/core/envelope/json.js.map +1 -0
  559. package/dist/core/{version.js → envelope/version.js} +3 -3
  560. package/dist/core/envelope/version.js.map +1 -0
  561. package/dist/core/explain/families.js +175 -0
  562. package/dist/core/explain/families.js.map +1 -0
  563. package/dist/core/explain/fix-tables.js +178 -0
  564. package/dist/core/explain/fix-tables.js.map +1 -0
  565. package/dist/core/explain/lookup.js +181 -0
  566. package/dist/core/explain/lookup.js.map +1 -0
  567. package/dist/core/explain/refusals.js +49 -0
  568. package/dist/core/explain/refusals.js.map +1 -0
  569. package/dist/core/explain/terms.js +144 -0
  570. package/dist/core/explain/terms.js.map +1 -0
  571. package/dist/core/explore/describe.js +105 -0
  572. package/dist/core/explore/describe.js.map +1 -0
  573. package/dist/core/{explore.js → explore/explore.js} +50 -101
  574. package/dist/core/explore/explore.js.map +1 -0
  575. package/dist/core/fleet-context.js +120 -78
  576. package/dist/core/fleet-context.js.map +1 -1
  577. package/dist/core/gate/checks.js +201 -0
  578. package/dist/core/gate/checks.js.map +1 -0
  579. package/dist/core/gate/partners.js +205 -0
  580. package/dist/core/gate/partners.js.map +1 -0
  581. package/dist/core/gate/report.js +47 -0
  582. package/dist/core/gate/report.js.map +1 -0
  583. package/dist/core/gate/verification.js +113 -0
  584. package/dist/core/gate/verification.js.map +1 -0
  585. package/dist/core/gherkin/digest.js +60 -0
  586. package/dist/core/gherkin/digest.js.map +1 -0
  587. package/dist/core/gherkin/emit.js +177 -0
  588. package/dist/core/gherkin/emit.js.map +1 -0
  589. package/dist/core/gherkin/read.js +76 -0
  590. package/dist/core/gherkin/read.js.map +1 -0
  591. package/dist/core/gherkin/stale.js +234 -0
  592. package/dist/core/gherkin/stale.js.map +1 -0
  593. package/dist/core/gherkin/stamp.js +77 -0
  594. package/dist/core/gherkin/stamp.js.map +1 -0
  595. package/dist/core/gherkin/steps/catalogue.js +154 -0
  596. package/dist/core/gherkin/steps/catalogue.js.map +1 -0
  597. package/dist/core/gherkin/steps/inventory.js +98 -0
  598. package/dist/core/gherkin/steps/inventory.js.map +1 -0
  599. package/dist/core/gherkin/steps/phrase.js +72 -0
  600. package/dist/core/gherkin/steps/phrase.js.map +1 -0
  601. package/dist/core/glossary/delta.js +106 -0
  602. package/dist/core/glossary/delta.js.map +1 -0
  603. package/dist/core/glossary/tree.js +86 -0
  604. package/dist/core/glossary/tree.js.map +1 -0
  605. package/dist/core/kernel/concurrency.js.map +1 -0
  606. package/dist/core/{document-bytes.js → kernel/document-bytes.js} +1 -1
  607. package/dist/core/kernel/document-bytes.js.map +1 -0
  608. package/dist/core/kernel/fences.js +42 -0
  609. package/dist/core/kernel/fences.js.map +1 -0
  610. package/dist/core/kernel/ids/capability.js +72 -0
  611. package/dist/core/kernel/ids/capability.js.map +1 -0
  612. package/dist/core/kernel/ids/dirs.js +33 -0
  613. package/dist/core/kernel/ids/dirs.js.map +1 -0
  614. package/dist/core/kernel/ids/feature.js +75 -0
  615. package/dist/core/kernel/ids/feature.js.map +1 -0
  616. package/dist/core/kernel/ids/service.js +156 -0
  617. package/dist/core/kernel/ids/service.js.map +1 -0
  618. package/dist/core/kernel/ids/subsystem.js +63 -0
  619. package/dist/core/kernel/ids/subsystem.js.map +1 -0
  620. package/dist/core/{path-safety.js → kernel/path-safety.js} +18 -4
  621. package/dist/core/kernel/path-safety.js.map +1 -0
  622. package/dist/core/kernel/records.js.map +1 -0
  623. package/dist/core/links/backlinks.js +68 -0
  624. package/dist/core/links/backlinks.js.map +1 -0
  625. package/dist/core/links/case.js +74 -0
  626. package/dist/core/links/case.js.map +1 -0
  627. package/dist/core/links/corpus.js +104 -0
  628. package/dist/core/links/corpus.js.map +1 -0
  629. package/dist/core/links/findings.js +110 -0
  630. package/dist/core/links/findings.js.map +1 -0
  631. package/dist/core/links/parse.js +236 -0
  632. package/dist/core/links/parse.js.map +1 -0
  633. package/dist/core/mcp/argv.js +111 -0
  634. package/dist/core/mcp/argv.js.map +1 -0
  635. package/dist/core/mcp/author-tools.js +72 -0
  636. package/dist/core/mcp/author-tools.js.map +1 -0
  637. package/dist/core/mcp/framing.js +46 -0
  638. package/dist/core/mcp/framing.js.map +1 -0
  639. package/dist/core/mcp/protocol.js +280 -0
  640. package/dist/core/mcp/protocol.js.map +1 -0
  641. package/dist/core/mcp/tools.js +314 -0
  642. package/dist/core/mcp/tools.js.map +1 -0
  643. package/dist/core/obligations/obligations.js +106 -0
  644. package/dist/core/obligations/obligations.js.map +1 -0
  645. package/dist/core/openapi/baseline/gate.js +166 -0
  646. package/dist/core/openapi/baseline/gate.js.map +1 -0
  647. package/dist/core/openapi/baseline/plan.js +112 -0
  648. package/dist/core/openapi/baseline/plan.js.map +1 -0
  649. package/dist/core/openapi/baseline/record.js +175 -0
  650. package/dist/core/openapi/baseline/record.js.map +1 -0
  651. package/dist/core/openapi/depth.js +122 -0
  652. package/dist/core/openapi/depth.js.map +1 -0
  653. package/dist/core/openapi/digest.js +189 -0
  654. package/dist/core/openapi/digest.js.map +1 -0
  655. package/dist/core/{openapi.js → openapi/doc.js} +44 -106
  656. package/dist/core/openapi/doc.js.map +1 -0
  657. package/dist/core/openapi/merge/components.js +234 -0
  658. package/dist/core/openapi/merge/components.js.map +1 -0
  659. package/dist/core/openapi/merge/error.js +26 -0
  660. package/dist/core/openapi/merge/error.js.map +1 -0
  661. package/dist/core/openapi/merge/markers.js +208 -0
  662. package/dist/core/openapi/merge/markers.js.map +1 -0
  663. package/dist/core/openapi/merge/merge.js +256 -0
  664. package/dist/core/openapi/merge/merge.js.map +1 -0
  665. package/dist/core/openapi/merge/pin.js +128 -0
  666. package/dist/core/openapi/merge/pin.js.map +1 -0
  667. package/dist/core/openspec/decide/capabilities.js +244 -0
  668. package/dist/core/openspec/decide/capabilities.js.map +1 -0
  669. package/dist/core/openspec/decide/dispositions.js +63 -0
  670. package/dist/core/openspec/decide/dispositions.js.map +1 -0
  671. package/dist/core/openspec/decide/renames.js +179 -0
  672. package/dist/core/openspec/decide/renames.js.map +1 -0
  673. package/dist/core/openspec/decide/verdict.js +84 -0
  674. package/dist/core/openspec/decide/verdict.js.map +1 -0
  675. package/dist/core/openspec/inventory.js +221 -0
  676. package/dist/core/openspec/inventory.js.map +1 -0
  677. package/dist/core/openspec/model/mapping.js +76 -0
  678. package/dist/core/openspec/model/mapping.js.map +1 -0
  679. package/dist/core/openspec/model/model.js +65 -0
  680. package/dist/core/openspec/model/model.js.map +1 -0
  681. package/dist/core/openspec/scan/changes.js +235 -0
  682. package/dist/core/openspec/scan/changes.js.map +1 -0
  683. package/dist/core/openspec/scan/config.js +200 -0
  684. package/dist/core/openspec/scan/config.js.map +1 -0
  685. package/dist/core/openspec/scan/shape.js +260 -0
  686. package/dist/core/openspec/scan/shape.js.map +1 -0
  687. package/dist/core/openspec/scan/walk.js +133 -0
  688. package/dist/core/openspec/scan/walk.js.map +1 -0
  689. package/dist/core/openspec/scan/workspace.js +71 -0
  690. package/dist/core/openspec/scan/workspace.js.map +1 -0
  691. package/dist/core/owners/codeowners.js +141 -0
  692. package/dist/core/owners/codeowners.js.map +1 -0
  693. package/dist/core/pack/features.js +120 -0
  694. package/dist/core/pack/features.js.map +1 -0
  695. package/dist/core/pack/joins.js +112 -0
  696. package/dist/core/pack/joins.js.map +1 -0
  697. package/dist/core/pack/living.js +137 -0
  698. package/dist/core/pack/living.js.map +1 -0
  699. package/dist/core/pack/pack.js +76 -0
  700. package/dist/core/pack/pack.js.map +1 -0
  701. package/dist/core/permissions/permissions.js +87 -0
  702. package/dist/core/permissions/permissions.js.map +1 -0
  703. package/dist/core/projection/api.js +84 -0
  704. package/dist/core/projection/api.js.map +1 -0
  705. package/dist/core/projection/arch-slice.js +63 -0
  706. package/dist/core/projection/arch-slice.js.map +1 -0
  707. package/dist/core/projection/events.js +34 -0
  708. package/dist/core/projection/events.js.map +1 -0
  709. package/dist/core/provenance/findings.js +208 -0
  710. package/dist/core/provenance/findings.js.map +1 -0
  711. package/dist/core/provenance/git.js +225 -0
  712. package/dist/core/provenance/git.js.map +1 -0
  713. package/dist/core/provenance/gitq/moves.js +182 -0
  714. package/dist/core/provenance/gitq/moves.js.map +1 -0
  715. package/dist/core/provenance/gitq/vouched-ancestor.js +179 -0
  716. package/dist/core/provenance/gitq/vouched-ancestor.js.map +1 -0
  717. package/dist/core/provenance/sample/scope.js +238 -0
  718. package/dist/core/provenance/sample/scope.js.map +1 -0
  719. package/dist/core/provenance/sample/sections.js +61 -0
  720. package/dist/core/provenance/sample/sections.js.map +1 -0
  721. package/dist/core/provenance/sources.js +263 -0
  722. package/dist/core/provenance/sources.js.map +1 -0
  723. package/dist/core/provenance/stamp.js +232 -0
  724. package/dist/core/provenance/stamp.js.map +1 -0
  725. package/dist/core/provenance/walk.js +157 -0
  726. package/dist/core/provenance/walk.js.map +1 -0
  727. package/dist/core/repo/authored/paths.js +210 -0
  728. package/dist/core/repo/authored/paths.js.map +1 -0
  729. package/dist/core/repo/entries.js +126 -0
  730. package/dist/core/repo/entries.js.map +1 -0
  731. package/dist/core/repo/paths.js +277 -0
  732. package/dist/core/repo/paths.js.map +1 -0
  733. package/dist/core/repo/repo.js +248 -0
  734. package/dist/core/repo/repo.js.map +1 -0
  735. package/dist/core/repo/service-target.js +153 -0
  736. package/dist/core/repo/service-target.js.map +1 -0
  737. package/dist/core/repo/state.js +58 -0
  738. package/dist/core/repo/state.js.map +1 -0
  739. package/dist/core/repo/tree/find.js +52 -0
  740. package/dist/core/repo/tree/find.js.map +1 -0
  741. package/dist/core/repo/tree/fs.js +64 -0
  742. package/dist/core/repo/tree/fs.js.map +1 -0
  743. package/dist/core/repo/tree/marker.js +61 -0
  744. package/dist/core/repo/tree/marker.js.map +1 -0
  745. package/dist/core/repo/tree/views.js +172 -0
  746. package/dist/core/repo/tree/views.js.map +1 -0
  747. package/dist/core/repo/tree/walk.js +234 -0
  748. package/dist/core/repo/tree/walk.js.map +1 -0
  749. package/dist/core/results.js +99 -2
  750. package/dist/core/results.js.map +1 -1
  751. package/dist/core/scaffold/landscape.js +131 -0
  752. package/dist/core/scaffold/landscape.js.map +1 -0
  753. package/dist/core/scaffold/readme.js +84 -0
  754. package/dist/core/scaffold/readme.js.map +1 -0
  755. package/dist/core/staging/commit.js +241 -0
  756. package/dist/core/staging/commit.js.map +1 -0
  757. package/dist/core/staging/interrupted.js +96 -0
  758. package/dist/core/staging/interrupted.js.map +1 -0
  759. package/dist/core/staging/lock.js +206 -0
  760. package/dist/core/staging/lock.js.map +1 -0
  761. package/dist/core/staging/recovery/finding.js +35 -0
  762. package/dist/core/staging/recovery/finding.js.map +1 -0
  763. package/dist/core/staging/recovery/intent.js +98 -0
  764. package/dist/core/staging/recovery/intent.js.map +1 -0
  765. package/dist/core/staging/recovery/recover.js +126 -0
  766. package/dist/core/staging/recovery/recover.js.map +1 -0
  767. package/dist/core/staging/recovery/residue.js +62 -0
  768. package/dist/core/staging/recovery/residue.js.map +1 -0
  769. package/dist/core/staging/snapshot.js +202 -0
  770. package/dist/core/staging/snapshot.js.map +1 -0
  771. package/dist/core/staging/txn/forward.js +171 -0
  772. package/dist/core/staging/txn/forward.js.map +1 -0
  773. package/dist/core/staging/txn/journal.js +139 -0
  774. package/dist/core/staging/txn/journal.js.map +1 -0
  775. package/dist/core/staging/txn/transaction.js +75 -0
  776. package/dist/core/staging/txn/transaction.js.map +1 -0
  777. package/dist/core/staging/writes.js +113 -0
  778. package/dist/core/staging/writes.js.map +1 -0
  779. package/dist/core/status/actions/execution.js +49 -0
  780. package/dist/core/status/actions/execution.js.map +1 -0
  781. package/dist/core/status/contracts.js +102 -0
  782. package/dist/core/status/contracts.js.map +1 -0
  783. package/dist/core/status/feature/artifacts.js +196 -0
  784. package/dist/core/status/feature/artifacts.js.map +1 -0
  785. package/dist/core/status/feature/feature.js +207 -0
  786. package/dist/core/status/feature/feature.js.map +1 -0
  787. package/dist/core/status/feature/next.js +150 -0
  788. package/dist/core/status/feature/next.js.map +1 -0
  789. package/dist/core/status/feature/state.js +21 -0
  790. package/dist/core/status/feature/state.js.map +1 -0
  791. package/dist/core/status/fleet/fleet.js +197 -0
  792. package/dist/core/status/fleet/fleet.js.map +1 -0
  793. package/dist/core/status/fleet/next.js +207 -0
  794. package/dist/core/status/fleet/next.js.map +1 -0
  795. package/dist/core/status/interrupted.js +97 -0
  796. package/dist/core/status/interrupted.js.map +1 -0
  797. package/dist/core/status/report.js +31 -0
  798. package/dist/core/status/report.js.map +1 -0
  799. package/dist/core/status/scan.js +41 -0
  800. package/dist/core/status/scan.js.map +1 -0
  801. package/dist/core/status/verification.js +201 -0
  802. package/dist/core/status/verification.js.map +1 -0
  803. package/dist/core/usecases/capability.js +169 -0
  804. package/dist/core/usecases/capability.js.map +1 -0
  805. package/dist/core/usecases/delta/claims.js +116 -0
  806. package/dist/core/usecases/delta/claims.js.map +1 -0
  807. package/dist/core/usecases/delta/flows.js +103 -0
  808. package/dist/core/usecases/delta/flows.js.map +1 -0
  809. package/dist/core/usecases/delta/overlay.js +72 -0
  810. package/dist/core/usecases/delta/overlay.js.map +1 -0
  811. package/dist/core/usecases/fleet.js +137 -0
  812. package/dist/core/usecases/fleet.js.map +1 -0
  813. package/dist/core/usecases/operations.js +111 -0
  814. package/dist/core/usecases/operations.js.map +1 -0
  815. package/dist/core/usecases/place.js +44 -0
  816. package/dist/core/usecases/place.js.map +1 -0
  817. package/dist/core/usecases/touch.js +101 -0
  818. package/dist/core/usecases/touch.js.map +1 -0
  819. package/dist/core/verify/answers.js +173 -0
  820. package/dist/core/verify/answers.js.map +1 -0
  821. package/dist/core/verify/build.js +150 -0
  822. package/dist/core/verify/build.js.map +1 -0
  823. package/dist/core/verify/checklist.js +201 -0
  824. package/dist/core/verify/checklist.js.map +1 -0
  825. package/dist/core/verify/claims/identity.js +61 -0
  826. package/dist/core/verify/claims/identity.js.map +1 -0
  827. package/dist/core/verify/cross/diff.js +97 -0
  828. package/dist/core/verify/cross/diff.js.map +1 -0
  829. package/dist/core/verify/evidence/contract.js +169 -0
  830. package/dist/core/verify/evidence/contract.js.map +1 -0
  831. package/dist/core/verify/file.js +257 -0
  832. package/dist/core/verify/file.js.map +1 -0
  833. package/dist/core/verify/pins/lint.js +157 -0
  834. package/dist/core/verify/pins/lint.js.map +1 -0
  835. package/dist/core/verify/pins/pin.js +95 -0
  836. package/dist/core/verify/pins/pin.js.map +1 -0
  837. package/dist/core/verify/record.js +142 -0
  838. package/dist/core/verify/record.js.map +1 -0
  839. package/dist/core/verify/store/commit.js +89 -0
  840. package/dist/core/verify/store/commit.js.map +1 -0
  841. package/dist/core/verify/store/render.js +57 -0
  842. package/dist/core/verify/store/render.js.map +1 -0
  843. package/dist/core/vocabulary/health.js +91 -0
  844. package/dist/core/vocabulary/health.js.map +1 -0
  845. package/dist/core/vocabulary/issue.js +58 -0
  846. package/dist/core/vocabulary/issue.js.map +1 -0
  847. package/dist/core/vocabulary/maturity.js +145 -0
  848. package/dist/core/vocabulary/maturity.js.map +1 -0
  849. package/dist/core/{report.js → vocabulary/report.js} +30 -2
  850. package/dist/core/vocabulary/report.js.map +1 -0
  851. package/dist/core/vocabulary/steps.js +266 -0
  852. package/dist/core/vocabulary/steps.js.map +1 -0
  853. package/dist/core/workspace/discover.js +239 -0
  854. package/dist/core/workspace/discover.js.map +1 -0
  855. package/dist/core/workspace/render.js +52 -0
  856. package/dist/core/workspace/render.js.map +1 -0
  857. package/examples/README.md +189 -0
  858. package/examples/docs/architecture/adrs/0001-transactional-outbox.md +33 -0
  859. package/examples/docs/architecture/capabilities.yaml +31 -0
  860. package/examples/docs/architecture/landscape.likec4 +280 -0
  861. package/examples/docs/architecture/obligations.yaml +23 -0
  862. package/examples/docs/architecture/permissions.yaml +50 -0
  863. package/examples/docs/architecture/subsystems.likec4 +11 -0
  864. package/examples/docs/architecture/usecases/order-notification.likec4 +65 -0
  865. package/examples/docs/capabilities/checkout/spec.md +55 -0
  866. package/examples/docs/capabilities/identity/tokens/spec.md +42 -0
  867. package/examples/docs/capabilities/order-notifications/spec.md +43 -0
  868. package/examples/docs/features/FEAT-101-payment-splitting/adrs/0001-dedicated-split-service.md +18 -0
  869. package/examples/docs/features/FEAT-101-payment-splitting/delta.likec4 +94 -0
  870. package/examples/docs/features/FEAT-101-payment-splitting/intent.md +44 -0
  871. package/examples/docs/features/FEAT-101-payment-splitting/specs/checkout-web/spec.md +21 -0
  872. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-service/asyncapi.yaml +129 -0
  873. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-service/spec.md +36 -0
  874. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/arch.spec.md +40 -0
  875. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/openapi.yaml +116 -0
  876. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/spec.md +55 -0
  877. package/examples/docs/features/FEAT-112-retire-order-v1/intent.md +35 -0
  878. package/examples/docs/features/FEAT-112-retire-order-v1/specs/order-service/openapi.yaml +28 -0
  879. package/examples/docs/features/FEAT-112-retire-order-v1/specs/order-service/spec.md +17 -0
  880. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/architecture/landscape.likec4 +253 -0
  881. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/services/order-service/spec.md +121 -0
  882. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/services/payment-service/openapi.yaml +111 -0
  883. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/services/payment-service/spec.md +58 -0
  884. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/manifest.json +32 -0
  885. package/examples/docs/features/archive/FEAT-088-refunds/adrs/0001-refunds-stay-in-payment-service.md +26 -0
  886. package/examples/docs/features/archive/FEAT-088-refunds/delta.likec4 +28 -0
  887. package/examples/docs/features/archive/FEAT-088-refunds/intent.md +26 -0
  888. package/examples/docs/features/archive/FEAT-088-refunds/specs/order-service/spec.md +37 -0
  889. package/examples/docs/features/archive/FEAT-088-refunds/specs/payment-service/openapi.yaml +70 -0
  890. package/examples/docs/features/archive/FEAT-088-refunds/specs/payment-service/spec.md +23 -0
  891. package/examples/docs/features/archive/FEAT-088-refunds/verification.yaml +76 -0
  892. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/architecture/landscape.likec4 +275 -0
  893. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/payment-service/asyncapi.yaml +96 -0
  894. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/payment-service/spec.md +82 -0
  895. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/platform/notification-service/asyncapi.yaml +164 -0
  896. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/platform/notification-service/spec.md +91 -0
  897. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/manifest.json +46 -0
  898. package/examples/docs/features/archive/FEAT-120-refund-notification/delta.likec4 +36 -0
  899. package/examples/docs/features/archive/FEAT-120-refund-notification/intent.md +22 -0
  900. package/examples/docs/features/archive/FEAT-120-refund-notification/scenario-report.json +10 -0
  901. package/examples/docs/features/archive/FEAT-120-refund-notification/specs/notification-service/asyncapi.yaml +208 -0
  902. package/examples/docs/features/archive/FEAT-120-refund-notification/specs/notification-service/spec.md +24 -0
  903. package/examples/docs/features/archive/FEAT-120-refund-notification/specs/payment-service/asyncapi.yaml +137 -0
  904. package/examples/docs/features/archive/FEAT-120-refund-notification/specs/payment-service/spec.md +31 -0
  905. package/examples/docs/features/archive/FEAT-120-refund-notification/verification.yaml +84 -0
  906. package/examples/docs/glossary/order.md +15 -0
  907. package/examples/docs/glossary/payments/authorization.md +14 -0
  908. package/examples/docs/likec4.config.json +9 -0
  909. package/examples/docs/loam.json +3 -0
  910. package/examples/docs/services/checkout-web/model.likec4 +109 -0
  911. package/examples/docs/services/checkout-web/spec.md +91 -0
  912. package/examples/docs/services/checkout-web/ui/pages/checkout.page.yaml +40 -0
  913. package/examples/docs/services/checkout-web/ui/pages/order-status.page.yaml +24 -0
  914. package/examples/docs/services/checkout-web/ui/pages/split-payment.page.yaml +26 -0
  915. package/examples/docs/services/order-service/adrs/0001-orchestrated-order-lifecycle.md +52 -0
  916. package/examples/docs/services/order-service/arch.spec.md +127 -0
  917. package/examples/docs/services/order-service/asyncapi.yaml +108 -0
  918. package/examples/docs/services/order-service/health.yaml +57 -0
  919. package/examples/docs/services/order-service/model.likec4 +138 -0
  920. package/examples/docs/services/order-service/openapi.yaml +257 -0
  921. package/examples/docs/services/order-service/runbook.md +62 -0
  922. package/examples/docs/services/order-service/spec.md +134 -0
  923. package/examples/docs/services/payment-service/adrs/0001-payments-outbox.md +18 -0
  924. package/examples/docs/services/payment-service/adrs/0002-idempotency-keys-on-authorization.md +27 -0
  925. package/examples/docs/services/payment-service/arch.spec.md +73 -0
  926. package/examples/docs/services/payment-service/asyncapi.yaml +130 -0
  927. package/examples/docs/services/payment-service/health.yaml +39 -0
  928. package/examples/docs/services/payment-service/model.likec4 +67 -0
  929. package/examples/docs/services/payment-service/openapi.yaml +151 -0
  930. package/examples/docs/services/payment-service/runbook.md +37 -0
  931. package/examples/docs/services/payment-service/spec.md +88 -0
  932. package/examples/docs/services/platform/identity-service/adrs/0001-token-introspection-over-local-validation.md +60 -0
  933. package/examples/docs/services/platform/identity-service/arch.spec.md +117 -0
  934. package/examples/docs/services/platform/identity-service/health.yaml +70 -0
  935. package/examples/docs/services/platform/identity-service/model.likec4 +83 -0
  936. package/examples/docs/services/platform/identity-service/openapi.yaml +197 -0
  937. package/examples/docs/services/platform/identity-service/runbook.md +95 -0
  938. package/examples/docs/services/platform/identity-service/spec.md +119 -0
  939. package/examples/docs/services/platform/notification-service/asyncapi.yaml +199 -0
  940. package/examples/docs/services/platform/notification-service/health.yaml +35 -0
  941. package/examples/docs/services/platform/notification-service/model.likec4 +118 -0
  942. package/examples/docs/services/platform/notification-service/runbook.md +48 -0
  943. package/examples/docs/services/platform/notification-service/spec.md +112 -0
  944. package/examples/docs/services/platform/subsystem.yaml +2 -0
  945. package/examples/fleet.yaml +57 -0
  946. package/package.json +19 -6
  947. package/dist/commands/adopt.js +0 -240
  948. package/dist/commands/adopt.js.map +0 -1
  949. package/dist/commands/archive.js +0 -1313
  950. package/dist/commands/archive.js.map +0 -1
  951. package/dist/commands/delta.js +0 -388
  952. package/dist/commands/delta.js.map +0 -1
  953. package/dist/commands/docs-repo-gate.js.map +0 -1
  954. package/dist/commands/format.js +0 -17
  955. package/dist/commands/format.js.map +0 -1
  956. package/dist/commands/gherkin.js +0 -309
  957. package/dist/commands/gherkin.js.map +0 -1
  958. package/dist/commands/init.js.map +0 -1
  959. package/dist/commands/list.js +0 -295
  960. package/dist/commands/list.js.map +0 -1
  961. package/dist/commands/migrate-openspec.js +0 -950
  962. package/dist/commands/migrate-openspec.js.map +0 -1
  963. package/dist/commands/new.js +0 -413
  964. package/dist/commands/new.js.map +0 -1
  965. package/dist/commands/rebase.js +0 -356
  966. package/dist/commands/rebase.js.map +0 -1
  967. package/dist/commands/show.js.map +0 -1
  968. package/dist/commands/status.js +0 -262
  969. package/dist/commands/status.js.map +0 -1
  970. package/dist/commands/unarchive.js.map +0 -1
  971. package/dist/commands/validate.js +0 -1773
  972. package/dist/commands/validate.js.map +0 -1
  973. package/dist/commands/verify.js +0 -775
  974. package/dist/commands/verify.js.map +0 -1
  975. package/dist/commands/vouch.js +0 -421
  976. package/dist/commands/vouch.js.map +0 -1
  977. package/dist/core/agent.js +0 -2173
  978. package/dist/core/agent.js.map +0 -1
  979. package/dist/core/agents-stamp.js.map +0 -1
  980. package/dist/core/arch.js +0 -130
  981. package/dist/core/arch.js.map +0 -1
  982. package/dist/core/asyncapi.js.map +0 -1
  983. package/dist/core/brief.js +0 -755
  984. package/dist/core/brief.js.map +0 -1
  985. package/dist/core/coherence.js +0 -577
  986. package/dist/core/coherence.js.map +0 -1
  987. package/dist/core/concurrency.js.map +0 -1
  988. package/dist/core/config.js.map +0 -1
  989. package/dist/core/delta.js +0 -476
  990. package/dist/core/delta.js.map +0 -1
  991. package/dist/core/dependencies.js +0 -356
  992. package/dist/core/dependencies.js.map +0 -1
  993. package/dist/core/doctor.js +0 -596
  994. package/dist/core/doctor.js.map +0 -1
  995. package/dist/core/document-bytes.js.map +0 -1
  996. package/dist/core/explore.js.map +0 -1
  997. package/dist/core/frontmatter.js.map +0 -1
  998. package/dist/core/gherkin.js +0 -463
  999. package/dist/core/gherkin.js.map +0 -1
  1000. package/dist/core/health.js +0 -67
  1001. package/dist/core/health.js.map +0 -1
  1002. package/dist/core/ids.js +0 -122
  1003. package/dist/core/ids.js.map +0 -1
  1004. package/dist/core/issue.js +0 -9
  1005. package/dist/core/issue.js.map +0 -1
  1006. package/dist/core/json.js +0 -74
  1007. package/dist/core/json.js.map +0 -1
  1008. package/dist/core/likec4.js +0 -489
  1009. package/dist/core/likec4.js.map +0 -1
  1010. package/dist/core/maturity.js +0 -66
  1011. package/dist/core/maturity.js.map +0 -1
  1012. package/dist/core/openapi-merge.js +0 -552
  1013. package/dist/core/openapi-merge.js.map +0 -1
  1014. package/dist/core/openapi.js.map +0 -1
  1015. package/dist/core/openspec-inventory.js +0 -1440
  1016. package/dist/core/openspec-inventory.js.map +0 -1
  1017. package/dist/core/path-safety.js.map +0 -1
  1018. package/dist/core/provenance.js +0 -787
  1019. package/dist/core/provenance.js.map +0 -1
  1020. package/dist/core/records.js.map +0 -1
  1021. package/dist/core/repo.js +0 -438
  1022. package/dist/core/repo.js.map +0 -1
  1023. package/dist/core/report.js.map +0 -1
  1024. package/dist/core/spec.js +0 -505
  1025. package/dist/core/spec.js.map +0 -1
  1026. package/dist/core/staging.js +0 -890
  1027. package/dist/core/staging.js.map +0 -1
  1028. package/dist/core/status.js +0 -1132
  1029. package/dist/core/status.js.map +0 -1
  1030. package/dist/core/steps.js +0 -72
  1031. package/dist/core/steps.js.map +0 -1
  1032. package/dist/core/verify.js +0 -807
  1033. package/dist/core/verify.js.map +0 -1
  1034. package/dist/core/version.js.map +0 -1
  1035. /package/dist/core/{concurrency.js → kernel/concurrency.js} +0 -0
  1036. /package/dist/core/{records.js → kernel/records.js} +0 -0
@@ -0,0 +1,105 @@
1
+ /**
2
+ * What the list actually reads: one row per service, one verification cell per
3
+ * feature.
4
+ *
5
+ * Both are gathered before anything is printed or serialized, because the same
6
+ * numbers appear in `--json` and in the worklist footer — a footer computed
7
+ * from a second read is a footer that can contradict the rows above it.
8
+ */
9
+ import { existsSync } from "node:fs";
10
+ import { loadFile } from "../../core/c4/likec4.js";
11
+ import { serviceResolver } from "../../core/c4/resolve/service.js";
12
+ import { maturityGaps, serviceMaturity, } from "../../core/vocabulary/maturity.js";
13
+ import {} from "../../core/repo/entries.js";
14
+ import { landscapePath, servicePathsAt } from "../../core/repo/paths.js";
15
+ import { featureChecklist } from "../../core/verify/checklist.js";
16
+ import { readVerification } from "../../core/verify/file.js";
17
+ import {} from "../../core/verify/answers.js";
18
+ import { confirmedProvenance, tallyRecord, verificationVerdict, } from "../../core/verify/record.js";
19
+ /**
20
+ * Read the living landscape ONCE and decide, per service, whether an API is
21
+ * expected of it. `serviceResolver` is handed the real service ids so an edge
22
+ * drawn into a modelled container (`paymentService.api`) counts for the service
23
+ * that owns it — the same resolution `validate` uses, so the two commands
24
+ * cannot disagree about who is called.
25
+ */
26
+ export async function serviceViews(docsDir, services, boundService, preloaded) {
27
+ const known = new Set(services.map((s) => s.id));
28
+ const lp = landscapePath(docsDir);
29
+ // `preloaded` is the landscape a caller already holds — `undefined` means
30
+ // "load it if it exists", null "there is none", the convention
31
+ // validateService's own `preloaded` follows. The fleet scorecard hands in
32
+ // the batch-parsed doc because a healthy `validate --all` must spin ZERO
33
+ // per-document workspaces (test/validate-batch-fallback.test.ts counts
34
+ // them), and a second parse of a document that run already holds was the
35
+ // exact per-path cost the batch loader exists to retire.
36
+ const land = preloaded !== undefined ? preloaded : existsSync(lp) ? await loadFile(lp) : null;
37
+ const called = new Set();
38
+ // Positive evidence only: with no landscape, or one that does not parse, we
39
+ // know nothing about who is called and every service is assumed to have an
40
+ // API — the conservative direction, because claiming a service needs no
41
+ // contract is how a real one goes undocumented. This is the SAME rule
42
+ // `landscapeEvidence` (core/vocabulary/maturity.ts) spells per service for
43
+ // explore and the context pack — derived fleet-wide here in one pass (one
44
+ // `called` set for every service) because calling the per-service partition
45
+ // from this loop would re-walk the whole relationship list once per
46
+ // service. If the rule moves, both spellings move.
47
+ const proven = land !== null && land.errors.length === 0;
48
+ if (proven) {
49
+ const svcOf = serviceResolver(land.elements, known);
50
+ for (const r of land.relationships) {
51
+ if (r.op !== undefined)
52
+ called.add(svcOf(r.target));
53
+ }
54
+ }
55
+ return services.map((entry) => {
56
+ const archSpec = existsSync(servicePathsAt(entry.dir).archSpec);
57
+ const apiExpected = !proven || called.has(entry.id);
58
+ const view = {
59
+ entry,
60
+ archSpec,
61
+ apiExpected,
62
+ unverifiableFromHere: entry.sources.declared && boundService !== entry.id,
63
+ };
64
+ const missing = maturityGaps(view);
65
+ return { ...view, maturity: serviceMaturity(view), missing };
66
+ });
67
+ }
68
+ /**
69
+ * The verification column. `readVerification` is one file read; the checklist
70
+ * is derived only when there is a record to judge — on a fleet-sized repo most
71
+ * features have none, and deriving N checklists to print N dashes is the cost
72
+ * that would get this column dropped.
73
+ *
74
+ * An archived feature's record is frozen history (see `core/verify/record.ts`): archive
75
+ * merged the feature's operations into the living openapi, so a re-derived
76
+ * checklist can only mismatch — the record is reported as recorded, never
77
+ * judged stale.
78
+ */
79
+ export async function featureVerification(docsDir, f) {
80
+ const v = await readVerification(f.dir);
81
+ if (v === null)
82
+ return null;
83
+ const stale = f.archived
84
+ ? false
85
+ : (await featureChecklist(docsDir, f.dir, f.id)).digest !== v.checklist;
86
+ const tally = tallyRecord(v);
87
+ return {
88
+ state: stale ? "stale" : "recorded",
89
+ recorded: v.recorded,
90
+ verdict: verificationVerdict(tally, stale),
91
+ confirmed: tally.confirmed,
92
+ claims: tally.claims,
93
+ attested: tally.attested,
94
+ answered: confirmedProvenance(v.claims),
95
+ };
96
+ }
97
+ /* ------------------------------------------------------------------ */
98
+ /* Text */
99
+ /* ------------------------------------------------------------------ */
100
+ /**
101
+ * Fixed-width presence flags. `a` and `A` are deliberately the same letter in
102
+ * two cases: the arch spec and the API are the two things a reader most often
103
+ * mistakes for each other, and one is lowercase because it is optional.
104
+ */
105
+ //# sourceMappingURL=views.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"views.js","sourceRoot":"","sources":["../../../src/commands/list/views.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * What the list actually reads: one row per service, one verification cell per\n * feature.\n *\n * Both are gathered before anything is printed or serialized, because the same\n * numbers appear in `--json` and in the worklist footer — a footer computed\n * from a second read is a footer that can contradict the rows above it.\n */\nimport { existsSync } from \"node:fs\";\nimport { loadFile, type LoadedDoc } from \"../../core/c4/likec4.js\";\nimport { serviceResolver } from \"../../core/c4/resolve/service.js\";\nimport {\n maturityGaps,\n serviceMaturity,\n type Maturity,\n type MaturityInput,\n} from \"../../core/vocabulary/maturity.js\";\nimport { type FeatureEntry, type ServiceEntry } from \"../../core/repo/entries.js\";\nimport { landscapePath, servicePathsAt } from \"../../core/repo/paths.js\";\nimport { featureChecklist } from \"../../core/verify/checklist.js\";\nimport { readVerification } from \"../../core/verify/file.js\";\nimport { type AnsweredBy } from \"../../core/verify/answers.js\";\nimport {\n confirmedProvenance,\n tallyRecord,\n type VerificationVerdict,\n verificationVerdict,\n} from \"../../core/verify/record.js\";\nimport type { DocsDir } from \"../../core/kernel/ids/dirs.js\";\n\nexport interface ServiceView extends MaturityInput {\n /** True when this service's `sources` can only be resolved from its own repo. */\n unverifiableFromHere: boolean;\n maturity: Maturity;\n /** What stands between this service and the next rung, in fix order. */\n missing: string[];\n}\n\n/**\n * Read the living landscape ONCE and decide, per service, whether an API is\n * expected of it. `serviceResolver` is handed the real service ids so an edge\n * drawn into a modelled container (`paymentService.api`) counts for the service\n * that owns it — the same resolution `validate` uses, so the two commands\n * cannot disagree about who is called.\n */\nexport async function serviceViews(\n docsDir: DocsDir,\n services: ServiceEntry[],\n boundService: string | undefined,\n preloaded?: LoadedDoc | null,\n): Promise<ServiceView[]> {\n const known = new Set(services.map((s) => s.id));\n const lp = landscapePath(docsDir);\n // `preloaded` is the landscape a caller already holds — `undefined` means\n // \"load it if it exists\", null \"there is none\", the convention\n // validateService's own `preloaded` follows. The fleet scorecard hands in\n // the batch-parsed doc because a healthy `validate --all` must spin ZERO\n // per-document workspaces (test/validate-batch-fallback.test.ts counts\n // them), and a second parse of a document that run already holds was the\n // exact per-path cost the batch loader exists to retire.\n const land = preloaded !== undefined ? preloaded : existsSync(lp) ? await loadFile(lp) : null;\n const called = new Set<string>();\n // Positive evidence only: with no landscape, or one that does not parse, we\n // know nothing about who is called and every service is assumed to have an\n // API — the conservative direction, because claiming a service needs no\n // contract is how a real one goes undocumented. This is the SAME rule\n // `landscapeEvidence` (core/vocabulary/maturity.ts) spells per service for\n // explore and the context pack — derived fleet-wide here in one pass (one\n // `called` set for every service) because calling the per-service partition\n // from this loop would re-walk the whole relationship list once per\n // service. If the rule moves, both spellings move.\n const proven = land !== null && land.errors.length === 0;\n if (proven) {\n const svcOf = serviceResolver(land.elements, known);\n for (const r of land.relationships) {\n if (r.op !== undefined) called.add(svcOf(r.target));\n }\n }\n\n return services.map((entry) => {\n const archSpec = existsSync(servicePathsAt(entry.dir).archSpec);\n const apiExpected = !proven || called.has(entry.id);\n const view = {\n entry,\n archSpec,\n apiExpected,\n unverifiableFromHere: entry.sources.declared && boundService !== entry.id,\n };\n const missing = maturityGaps(view);\n return { ...view, maturity: serviceMaturity(view), missing };\n });\n}\n\n/* ------------------------------------------------------------------ */\n/* JSON */\n/* ------------------------------------------------------------------ */\n\nexport interface VerificationCell {\n state: \"recorded\" | \"stale\";\n /** The day the record was written. */\n recorded: string;\n /**\n * `verify --json`'s own three-valued verdict, through `verificationVerdict` —\n * not a fourth opinion computed here. `attested` is the one this column got\n * wrong: a scenario confirmed on an agent's word printed as `11/11` under a\n * heading that said `verified`, and `list --json` is how the fleet is graded.\n */\n verdict: VerificationVerdict;\n /** Both counts are `tallyRecord`'s — the record's `claims[]`, never its `summary:` block. */\n confirmed: number;\n claims: number;\n /** Of the confirmed, the scenario claims on an agent's word (`attestedClaims`). */\n attested: number;\n /**\n * Of the confirmed, one count per `answered_by` value (`confirmedProvenance`), every key\n * present. A different question from `attested` above, which is why both are here: `attested`\n * asks only about `scenario.tested` because that is what the verdict turns on, while this asks\n * who answered EVERY kind — and reading the first as if it were the second is how the fleet\n * scorecard credited agent-answered permission and operation claims to a test runner.\n */\n answered: Record<AnsweredBy, number>;\n}\n\n/**\n * The verification column. `readVerification` is one file read; the checklist\n * is derived only when there is a record to judge — on a fleet-sized repo most\n * features have none, and deriving N checklists to print N dashes is the cost\n * that would get this column dropped.\n *\n * An archived feature's record is frozen history (see `core/verify/record.ts`): archive\n * merged the feature's operations into the living openapi, so a re-derived\n * checklist can only mismatch — the record is reported as recorded, never\n * judged stale.\n */\nexport async function featureVerification(\n docsDir: DocsDir,\n f: FeatureEntry,\n): Promise<VerificationCell | null> {\n const v = await readVerification(f.dir);\n if (v === null) return null;\n const stale = f.archived\n ? false\n : (await featureChecklist(docsDir, f.dir, f.id)).digest !== v.checklist;\n const tally = tallyRecord(v);\n return {\n state: stale ? \"stale\" : \"recorded\",\n recorded: v.recorded,\n verdict: verificationVerdict(tally, stale),\n confirmed: tally.confirmed,\n claims: tally.claims,\n attested: tally.attested,\n answered: confirmedProvenance(v.claims),\n };\n}\n\n/* ------------------------------------------------------------------ */\n/* Text */\n/* ------------------------------------------------------------------ */\n\n/**\n * Fixed-width presence flags. `a` and `A` are deliberately the same letter in\n * two cases: the arch spec and the API are the two things a reader most often\n * mistakes for each other, and one is lowercase because it is optional.\n */\n"]}
@@ -0,0 +1,183 @@
1
+ /**
2
+ * In-process dispatch for one MCP tool call: build a fresh commander program
3
+ * holding only the commands the selected tool table exposes, run the argv through
4
+ * it, and hand back what the CLI would have printed.
5
+ *
6
+ * This is the proven harness pattern (test/helpers/harness.ts runLoamNow)
7
+ * moved to the commands layer, minus the chdir: the server's own cwd IS the
8
+ * workdir, so every call resolves loam.json exactly as the CLI would in that
9
+ * directory — the server serves ONE repository, the one it started in, and
10
+ * never changes directory. In-process rather than a child per call because a
11
+ * child re-pays LikeC4/Langium startup on every validate, and because in dev
12
+ * there is no built binary to exec.
13
+ *
14
+ * The capture is process-global (console, exitCode), which is safe under
15
+ * exactly one condition the serve loop guarantees: calls are strictly
16
+ * sequential — each one is awaited to completion before the next frame is
17
+ * read — and `parseAsync` resolves only after the action has fully run (the
18
+ * entire test suite rests on that same guarantee). Nothing here may be
19
+ * module-level state: two serve sessions in one process (the tests do this)
20
+ * must not see each other.
21
+ *
22
+ * NOTE for test/agents.test.ts's scan: registration happens through the
23
+ * imported register functions; this module must never contain the literal
24
+ * dot-command-paren call, comments included, or the CLI surface count breaks.
25
+ */
26
+ import { Command, CommanderError } from "commander";
27
+ import { format } from "node:util";
28
+ import { emitJsonError } from "../../core/envelope/json.js";
29
+ import { registerValidate } from "../validate/validate.js";
30
+ import { registerStatus } from "../status/status.js";
31
+ import { registerList } from "../list/list.js";
32
+ import { registerShow } from "../show/show.js";
33
+ import { registerDelta } from "../delta/delta.js";
34
+ import { registerDiff } from "../diff/diff.js";
35
+ import { registerExplore } from "../explore.js";
36
+ import { registerDependencies } from "../dependencies.js";
37
+ import { registerDoctor } from "../doctor.js";
38
+ import { registerContext } from "../context/context.js";
39
+ import { registerGate } from "../gate/gate.js";
40
+ import { registerExplain } from "../explain/explain.js";
41
+ import { registerInstructions } from "../instructions.js";
42
+ import { registerSteps } from "../steps/steps.js";
43
+ import { registerNew } from "../new/new.js";
44
+ import { registerRebase } from "../rebase/rebase.js";
45
+ import { registerGherkin } from "../gherkin/gherkin.js";
46
+ import { registerArchive } from "../archive/archive.js";
47
+ /**
48
+ * Every console method Node's Console writes to STDOUT — the protocol stream,
49
+ * where one stray line corrupts the transport. Hooking only `log` was the
50
+ * reviewed defect here: a `console.info` in any command, or in a dependency a
51
+ * command loads, would have written straight into the client's frame stream
52
+ * with every suite green. `warn`/`error` go to stderr, captured for the
53
+ * server log rather than the wire.
54
+ */
55
+ const STDOUT_METHODS = [
56
+ "log", "info", "debug", "dir", "dirxml", "table",
57
+ "group", "groupCollapsed", "groupEnd", "count", "countReset", "timeLog", "timeEnd",
58
+ ];
59
+ const STDERR_METHODS = ["warn", "error"];
60
+ /**
61
+ * Replace the console methods named above with sink writers; the returned
62
+ * function restores every original. Captured output is `format(...)`ed, so
63
+ * `table`/`group` lose their layout — acceptable on purpose: the invariant
64
+ * bought here is that their BYTES stay off the protocol stream, not that
65
+ * their rendering survives.
66
+ */
67
+ export function captureConsole(sinks) {
68
+ const target = console;
69
+ const writer = (sink) => (...parts) => {
70
+ sink.push(format(...parts));
71
+ };
72
+ const toStdout = writer(sinks.stdout);
73
+ const toStderr = writer(sinks.stderr);
74
+ const original = new Map();
75
+ for (const [names, replacement] of [
76
+ [STDOUT_METHODS, toStdout],
77
+ [STDERR_METHODS, toStderr],
78
+ ]) {
79
+ for (const name of names) {
80
+ // A method absent on this Node build has nothing to capture — and
81
+ // nothing to restore, so it must not enter the map either.
82
+ if (typeof target[name] !== "function")
83
+ continue;
84
+ original.set(name, target[name]);
85
+ target[name] = replacement;
86
+ }
87
+ }
88
+ return () => {
89
+ for (const [name, method] of original)
90
+ target[name] = method;
91
+ };
92
+ }
93
+ /** Commander output codes whose printed output is the point, not a usage failure. */
94
+ const PASS_THROUGH = new Set(["commander.help", "commander.helpDisplayed", "commander.version"]);
95
+ /**
96
+ * The scoped program, output routed into `sinks`. configureOutput and
97
+ * exitOverride are set BEFORE the register calls on purpose: commander copies
98
+ * inherited settings onto a subcommand when it is created, so settings applied
99
+ * after registration would leave every subcommand writing to the real stdout —
100
+ * which for an MCP server is the protocol stream.
101
+ */
102
+ function readProgram(sinks, authoring = false) {
103
+ const program = new Command();
104
+ program.name("loam");
105
+ program.exitOverride();
106
+ program.configureOutput({
107
+ writeOut: (text) => sinks.stdout.push(text),
108
+ writeErr: (text) => sinks.stderr.push(text),
109
+ });
110
+ registerValidate(program);
111
+ registerStatus(program);
112
+ registerList(program);
113
+ registerShow(program);
114
+ registerDelta(program);
115
+ registerDiff(program);
116
+ registerExplore(program);
117
+ registerDependencies(program);
118
+ registerDoctor(program);
119
+ registerContext(program);
120
+ registerGate(program);
121
+ registerExplain(program);
122
+ // The two that read no config at all. They are here for the same reason they
123
+ // are in MCP_TOOLS: an agent meets `instructions` and `steps` BEFORE the
124
+ // repository is wired, and every generated skill's first line points at
125
+ // `loam instructions <workflow>`. This list and MCP_TOOLS are two copies of
126
+ // one roster, and nothing counted them against each other until a tool
127
+ // advertised in `tools/list` and absent here answered a `tools/call` with
128
+ // `unknown command 'instructions'` — an envelope that reads as the caller's
129
+ // mistake. `test/mcp-serve.test.ts` now calls every advertised tool.
130
+ registerInstructions(program);
131
+ registerSteps(program);
132
+ if (authoring) {
133
+ registerNew(program);
134
+ registerRebase(program);
135
+ registerGherkin(program);
136
+ registerArchive(program);
137
+ }
138
+ return program;
139
+ }
140
+ /**
141
+ * Run one tool argv. Never throws: whatever goes wrong becomes an envelope in
142
+ * `stdout` with `code` 1, so the serve loop's answer to THIS call is the only
143
+ * thing affected — one bad call must never take the server down, and a
144
+ * memoised rejection cannot exist because nothing here outlives the call.
145
+ */
146
+ export async function runToolArgv(argv, authoring = false) {
147
+ const sinks = { stdout: [], stderr: [] };
148
+ const previousExitCode = process.exitCode;
149
+ const restoreConsole = captureConsole(sinks);
150
+ process.exitCode = undefined;
151
+ try {
152
+ await readProgram(sinks, authoring).parseAsync(["node", "loam", ...argv]);
153
+ }
154
+ catch (err) {
155
+ if (err instanceof CommanderError) {
156
+ if (PASS_THROUGH.has(err.code)) {
157
+ // Unreachable through the tool schemas (the argv builder refuses every
158
+ // '-'-prefixed string, so --help/--version cannot arrive), kept for the
159
+ // day it is not: the output already sits in the sinks; keep its code.
160
+ if (process.exitCode === undefined)
161
+ process.exitCode = err.exitCode;
162
+ }
163
+ else {
164
+ // The same envelope cli.ts's catch emits for a usage error, so an MCP
165
+ // caller still receives machine-readable JSON, not a bare exception.
166
+ emitJsonError("invalid-option", err.message.replace(/^error: /, ""));
167
+ }
168
+ }
169
+ else {
170
+ // An unexpected throw from a command action: the CLI's own catch-all
171
+ // (`internal`) — the one code with no stable meaning, carried so the
172
+ // caller gets an envelope rather than a dead call.
173
+ emitJsonError("internal", err instanceof Error ? err.message : String(err));
174
+ }
175
+ }
176
+ finally {
177
+ restoreConsole();
178
+ }
179
+ const code = typeof process.exitCode === "number" ? process.exitCode : 0;
180
+ process.exitCode = previousExitCode;
181
+ return { stdout: sinks.stdout.join("\n"), stderr: sinks.stderr.join("\n"), code };
182
+ }
183
+ //# sourceMappingURL=dispatch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dispatch.js","sourceRoot":"","sources":["../../../src/commands/mcp/dispatch.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * In-process dispatch for one MCP tool call: build a fresh commander program\n * holding only the commands the selected tool table exposes, run the argv through\n * it, and hand back what the CLI would have printed.\n *\n * This is the proven harness pattern (test/helpers/harness.ts runLoamNow)\n * moved to the commands layer, minus the chdir: the server's own cwd IS the\n * workdir, so every call resolves loam.json exactly as the CLI would in that\n * directory — the server serves ONE repository, the one it started in, and\n * never changes directory. In-process rather than a child per call because a\n * child re-pays LikeC4/Langium startup on every validate, and because in dev\n * there is no built binary to exec.\n *\n * The capture is process-global (console, exitCode), which is safe under\n * exactly one condition the serve loop guarantees: calls are strictly\n * sequential — each one is awaited to completion before the next frame is\n * read — and `parseAsync` resolves only after the action has fully run (the\n * entire test suite rests on that same guarantee). Nothing here may be\n * module-level state: two serve sessions in one process (the tests do this)\n * must not see each other.\n *\n * NOTE for test/agents.test.ts's scan: registration happens through the\n * imported register functions; this module must never contain the literal\n * dot-command-paren call, comments included, or the CLI surface count breaks.\n */\nimport { Command, CommanderError } from \"commander\";\nimport { format } from \"node:util\";\nimport { emitJsonError } from \"../../core/envelope/json.js\";\nimport { registerValidate } from \"../validate/validate.js\";\nimport { registerStatus } from \"../status/status.js\";\nimport { registerList } from \"../list/list.js\";\nimport { registerShow } from \"../show/show.js\";\nimport { registerDelta } from \"../delta/delta.js\";\nimport { registerDiff } from \"../diff/diff.js\";\nimport { registerExplore } from \"../explore.js\";\nimport { registerDependencies } from \"../dependencies.js\";\nimport { registerDoctor } from \"../doctor.js\";\nimport { registerContext } from \"../context/context.js\";\nimport { registerGate } from \"../gate/gate.js\";\nimport { registerExplain } from \"../explain/explain.js\";\nimport { registerInstructions } from \"../instructions.js\";\nimport { registerSteps } from \"../steps/steps.js\";\nimport { registerNew } from \"../new/new.js\";\nimport { registerRebase } from \"../rebase/rebase.js\";\nimport { registerGherkin } from \"../gherkin/gherkin.js\";\nimport { registerArchive } from \"../archive/archive.js\";\n\nexport interface DispatchResult {\n readonly stdout: string;\n readonly stderr: string;\n readonly code: number;\n}\n\n/** Console sinks for one dispatch — a value, not module state, so calls cannot share buffers. */\nexport interface Sinks {\n readonly stdout: string[];\n readonly stderr: string[];\n}\n\n/**\n * Every console method Node's Console writes to STDOUT — the protocol stream,\n * where one stray line corrupts the transport. Hooking only `log` was the\n * reviewed defect here: a `console.info` in any command, or in a dependency a\n * command loads, would have written straight into the client's frame stream\n * with every suite green. `warn`/`error` go to stderr, captured for the\n * server log rather than the wire.\n */\nconst STDOUT_METHODS = [\n \"log\", \"info\", \"debug\", \"dir\", \"dirxml\", \"table\",\n \"group\", \"groupCollapsed\", \"groupEnd\", \"count\", \"countReset\", \"timeLog\", \"timeEnd\",\n] as const;\nconst STDERR_METHODS = [\"warn\", \"error\"] as const;\n\n/**\n * Replace the console methods named above with sink writers; the returned\n * function restores every original. Captured output is `format(...)`ed, so\n * `table`/`group` lose their layout — acceptable on purpose: the invariant\n * bought here is that their BYTES stay off the protocol stream, not that\n * their rendering survives.\n */\nexport function captureConsole(sinks: Sinks): () => void {\n const target = console as unknown as Record<string, unknown>;\n const writer = (sink: string[]) => (...parts: unknown[]): void => {\n sink.push(format(...parts));\n };\n const toStdout = writer(sinks.stdout);\n const toStderr = writer(sinks.stderr);\n const original = new Map<string, unknown>();\n for (const [names, replacement] of [\n [STDOUT_METHODS, toStdout],\n [STDERR_METHODS, toStderr],\n ] as const) {\n for (const name of names) {\n // A method absent on this Node build has nothing to capture — and\n // nothing to restore, so it must not enter the map either.\n if (typeof target[name] !== \"function\") continue;\n original.set(name, target[name]);\n target[name] = replacement;\n }\n }\n return () => {\n for (const [name, method] of original) target[name] = method;\n };\n}\n\n/** Commander output codes whose printed output is the point, not a usage failure. */\nconst PASS_THROUGH = new Set([\"commander.help\", \"commander.helpDisplayed\", \"commander.version\"]);\n\n/**\n * The scoped program, output routed into `sinks`. configureOutput and\n * exitOverride are set BEFORE the register calls on purpose: commander copies\n * inherited settings onto a subcommand when it is created, so settings applied\n * after registration would leave every subcommand writing to the real stdout —\n * which for an MCP server is the protocol stream.\n */\nfunction readProgram(sinks: Sinks, authoring = false): Command {\n const program = new Command();\n program.name(\"loam\");\n program.exitOverride();\n program.configureOutput({\n writeOut: (text) => sinks.stdout.push(text),\n writeErr: (text) => sinks.stderr.push(text),\n });\n registerValidate(program);\n registerStatus(program);\n registerList(program);\n registerShow(program);\n registerDelta(program);\n registerDiff(program);\n registerExplore(program);\n registerDependencies(program);\n registerDoctor(program);\n registerContext(program);\n registerGate(program);\n registerExplain(program);\n // The two that read no config at all. They are here for the same reason they\n // are in MCP_TOOLS: an agent meets `instructions` and `steps` BEFORE the\n // repository is wired, and every generated skill's first line points at\n // `loam instructions <workflow>`. This list and MCP_TOOLS are two copies of\n // one roster, and nothing counted them against each other until a tool\n // advertised in `tools/list` and absent here answered a `tools/call` with\n // `unknown command 'instructions'` — an envelope that reads as the caller's\n // mistake. `test/mcp-serve.test.ts` now calls every advertised tool.\n registerInstructions(program);\n registerSteps(program);\n if (authoring) {\n registerNew(program);\n registerRebase(program);\n registerGherkin(program);\n registerArchive(program);\n }\n return program;\n}\n\n/**\n * Run one tool argv. Never throws: whatever goes wrong becomes an envelope in\n * `stdout` with `code` 1, so the serve loop's answer to THIS call is the only\n * thing affected — one bad call must never take the server down, and a\n * memoised rejection cannot exist because nothing here outlives the call.\n */\nexport async function runToolArgv(\n argv: readonly string[],\n authoring = false,\n): Promise<DispatchResult> {\n const sinks: Sinks = { stdout: [], stderr: [] };\n const previousExitCode = process.exitCode;\n const restoreConsole = captureConsole(sinks);\n process.exitCode = undefined;\n try {\n await readProgram(sinks, authoring).parseAsync([\"node\", \"loam\", ...argv]);\n } catch (err) {\n if (err instanceof CommanderError) {\n if (PASS_THROUGH.has(err.code)) {\n // Unreachable through the tool schemas (the argv builder refuses every\n // '-'-prefixed string, so --help/--version cannot arrive), kept for the\n // day it is not: the output already sits in the sinks; keep its code.\n if (process.exitCode === undefined) process.exitCode = err.exitCode;\n } else {\n // The same envelope cli.ts's catch emits for a usage error, so an MCP\n // caller still receives machine-readable JSON, not a bare exception.\n emitJsonError(\"invalid-option\", err.message.replace(/^error: /, \"\"));\n }\n } else {\n // An unexpected throw from a command action: the CLI's own catch-all\n // (`internal`) — the one code with no stable meaning, carried so the\n // caller gets an envelope rather than a dead call.\n emitJsonError(\"internal\", err instanceof Error ? err.message : String(err));\n }\n } finally {\n restoreConsole();\n }\n const code = typeof process.exitCode === \"number\" ? process.exitCode : 0;\n process.exitCode = previousExitCode;\n return { stdout: sinks.stdout.join(\"\\n\"), stderr: sinks.stderr.join(\"\\n\"), code };\n}\n"]}
@@ -0,0 +1,34 @@
1
+ import { runToolArgv } from "./dispatch.js";
2
+ import { serve } from "./serve.js";
3
+ import { MCP_TOOLS } from "../../core/mcp/tools.js";
4
+ import { MCP_AUTHOR_TOOLS } from "../../core/mcp/author-tools.js";
5
+ export function registerMcp(program) {
6
+ program
7
+ .command("mcp")
8
+ .description("Serve loam commands as MCP tools over stdio (JSON-RPC 2.0)")
9
+ .option("--author", "opt in to safe authoring tools; vouch and committing archive stay excluded")
10
+ // Declared for the uniform surface every command owes (`--json` is
11
+ // mandatory, test/agents.test.ts), and it is not inert: it governs the one
12
+ // pre-loop surface this command has — a usage error like `loam mcp --bogus`
13
+ // aborts before the action runs, and cli.ts's catch reads raw argv to
14
+ // decide whether that refusal is an envelope. Once the loop runs, stdout
15
+ // is JSON-RPC frames either way; there is no human rendering to switch off.
16
+ .option("--json", "emit the machine contract instead of the human view")
17
+ .action(async (opts) => {
18
+ // No docs-repo gate at startup, deliberately (the add-command preamble
19
+ // decision): a launch-time refusal would print a non-JSON-RPC line into
20
+ // the client's protocol stream and kill the handshake with nothing a
21
+ // client can parse. Every tool call flows through the same command path
22
+ // the CLI uses, so a missing or broken loam.json arrives as the ordinary
23
+ // `no-config`/`config-invalid` envelope in a tool result — readable, and
24
+ // actionable, by the agent on the other end. The server serves the
25
+ // repository it was started in (each call resolves loam.json through
26
+ // process.cwd()) and never changes directory.
27
+ const tools = opts.author ? [...MCP_TOOLS, ...MCP_AUTHOR_TOOLS] : MCP_TOOLS;
28
+ const run = opts.author
29
+ ? (argv) => runToolArgv(argv, true)
30
+ : runToolArgv;
31
+ await serve({ input: process.stdin, output: process.stdout, log: process.stderr }, run, tools);
32
+ });
33
+ }
34
+ //# sourceMappingURL=mcp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp.js","sourceRoot":"","sources":["../../../src/commands/mcp/mcp.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAMlE,MAAM,UAAU,WAAW,CAAC,OAAgB;IAC1C,OAAO;SACJ,OAAO,CAAC,KAAK,CAAC;SACd,WAAW,CAAC,4DAA4D,CAAC;SACzE,MAAM,CAAC,UAAU,EAAE,4EAA4E,CAAC;QACjG,mEAAmE;QACnE,2EAA2E;QAC3E,4EAA4E;QAC5E,sEAAsE;QACtE,yEAAyE;QACzE,4EAA4E;SAC3E,MAAM,CAAC,QAAQ,EAAE,qDAAqD,CAAC;SACvE,MAAM,CAAC,KAAK,EAAE,IAAgB,EAAE,EAAE;QACjC,uEAAuE;QACvE,wEAAwE;QACxE,qEAAqE;QACrE,wEAAwE;QACxE,yEAAyE;QACzE,yEAAyE;QACzE,mEAAmE;QACnE,qEAAqE;QACrE,8CAA8C;QAC9C,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,SAAS,EAAE,GAAG,gBAAgB,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAC5E,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM;YACrB,CAAC,CAAC,CAAC,IAAuB,EAAE,EAAE,CAAC,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC;YACtD,CAAC,CAAC,WAAW,CAAC;QAChB,MAAM,KAAK,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,GAAG,EAAE,OAAO,CAAC,MAAM,EAAE,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;IACjG,CAAC,CAAC,CAAC;AACP,CAAC","sourcesContent":["/**\n * `loam mcp` — serve the read surface, plus bounded writers under `--author`.\n *\n * The action wires the real stdio triple into the serve loop and waits for\n * stdin EOF; everything with a decision in it lives in `./serve.ts`,\n * `./dispatch.ts` and `src/core/mcp/`. This module carries the one command\n * registration of the package (test/agents.test.ts counts registrations by\n * their literal spelling, so the sibling modules must never spell one).\n */\nimport type { Command } from \"commander\";\nimport { runToolArgv } from \"./dispatch.js\";\nimport { serve } from \"./serve.js\";\nimport { MCP_TOOLS } from \"../../core/mcp/tools.js\";\nimport { MCP_AUTHOR_TOOLS } from \"../../core/mcp/author-tools.js\";\n\ninterface McpOptions {\n author?: boolean;\n}\n\nexport function registerMcp(program: Command): void {\n program\n .command(\"mcp\")\n .description(\"Serve loam commands as MCP tools over stdio (JSON-RPC 2.0)\")\n .option(\"--author\", \"opt in to safe authoring tools; vouch and committing archive stay excluded\")\n // Declared for the uniform surface every command owes (`--json` is\n // mandatory, test/agents.test.ts), and it is not inert: it governs the one\n // pre-loop surface this command has — a usage error like `loam mcp --bogus`\n // aborts before the action runs, and cli.ts's catch reads raw argv to\n // decide whether that refusal is an envelope. Once the loop runs, stdout\n // is JSON-RPC frames either way; there is no human rendering to switch off.\n .option(\"--json\", \"emit the machine contract instead of the human view\")\n .action(async (opts: McpOptions) => {\n // No docs-repo gate at startup, deliberately (the add-command preamble\n // decision): a launch-time refusal would print a non-JSON-RPC line into\n // the client's protocol stream and kill the handshake with nothing a\n // client can parse. Every tool call flows through the same command path\n // the CLI uses, so a missing or broken loam.json arrives as the ordinary\n // `no-config`/`config-invalid` envelope in a tool result — readable, and\n // actionable, by the agent on the other end. The server serves the\n // repository it was started in (each call resolves loam.json through\n // process.cwd()) and never changes directory.\n const tools = opts.author ? [...MCP_TOOLS, ...MCP_AUTHOR_TOOLS] : MCP_TOOLS;\n const run = opts.author\n ? (argv: readonly string[]) => runToolArgv(argv, true)\n : runToolArgv;\n await serve({ input: process.stdin, output: process.stdout, log: process.stderr }, run, tools);\n });\n}\n"]}
@@ -0,0 +1,55 @@
1
+ import { frame, splitFrames } from "../../core/mcp/framing.js";
2
+ import { INTERNAL_ERROR, errorResponse, resultResponse, routeLine, toolReply, } from "../../core/mcp/protocol.js";
3
+ import { MCP_TOOLS } from "../../core/mcp/tools.js";
4
+ export async function serve(io, runTool, tools = MCP_TOOLS) {
5
+ // One startup line, to stderr only — a client is entitled to a stdout that
6
+ // has never carried anything but frames, from the very first byte.
7
+ io.log.write(`loam mcp: serving ${process.cwd()} over stdio\n`);
8
+ // Decode at the stream, not per chunk: a UTF-8 code point split across two
9
+ // chunks would corrupt if each chunk were stringified on its own.
10
+ io.input.setEncoding("utf8");
11
+ let rest = "";
12
+ for await (const chunk of io.input) {
13
+ const split = splitFrames(rest + String(chunk));
14
+ rest = split.rest;
15
+ for (const line of split.lines)
16
+ await handleLine(line, io, runTool, tools);
17
+ }
18
+ // A final frame the client sent without a trailing newline is still a frame:
19
+ // EOF terminates it exactly as the delimiter would have.
20
+ if (rest.trim() !== "")
21
+ await handleLine(rest, io, runTool, tools);
22
+ }
23
+ async function handleLine(line, io, runTool, tools) {
24
+ const outcome = routeLine(line, tools);
25
+ if (outcome.kind === "ignore")
26
+ return;
27
+ if (outcome.kind === "reply") {
28
+ io.output.write(frame(outcome.response));
29
+ return;
30
+ }
31
+ await handleCall(outcome, io, runTool);
32
+ }
33
+ /** One tools/call, contained: whatever this call does, the loop survives it. */
34
+ async function handleCall(call, io, runTool) {
35
+ try {
36
+ const run = await runTool(call.argv);
37
+ if (run.stderr.trim() !== "") {
38
+ // A command's diagnostics are server-side logging, never protocol bytes.
39
+ io.log.write(`loam mcp: ${call.toolName} stderr: ${run.stderr.trim()}\n`);
40
+ }
41
+ const reply = toolReply(run);
42
+ io.output.write(frame(reply.kind === "result"
43
+ ? resultResponse(call.id, reply.result)
44
+ : errorResponse(call.id, reply.code, reply.message)));
45
+ }
46
+ catch (err) {
47
+ // The dispatcher already converts everything it can into an envelope, so
48
+ // reaching here means the failure was outside it (or in the wrapping
49
+ // itself). It becomes a JSON-RPC error for THIS id — the caller learns
50
+ // which call died, with the reason — and the loop reads the next frame.
51
+ const detail = err instanceof Error ? err.message : String(err);
52
+ io.output.write(frame(errorResponse(call.id, INTERNAL_ERROR, `${call.toolName} failed: ${detail}`)));
53
+ }
54
+ }
55
+ //# sourceMappingURL=serve.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serve.js","sourceRoot":"","sources":["../../../src/commands/mcp/serve.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The MCP stdio loop: read newline-delimited JSON-RPC frames from `input`,\n * answer on `output`, log on `log`. Streams are injected so the tests drive\n * a whole session in-process with PassThrough pairs; `loam mcp` passes the\n * real stdio triple.\n *\n * Two invariants everything else leans on:\n *\n * - `output` carries protocol frames and NOTHING else — every byte goes\n * through `frame()`. Command output cannot leak here: the dispatcher hooks\n * console and commander's own writers, and no command in src/ writes to\n * process.stdout directly (verified at implementation time; the dispatcher\n * comment records the guarantee it needs). Logging — the startup line, a\n * tool's captured stderr — goes to `log`, which MCP permits.\n *\n * - Frames are handled STRICTLY SEQUENTIALLY: each one is awaited before the\n * next is looked at. This is not an optimization opportunity — the\n * dispatcher's console capture is process-global, so two overlapping calls\n * would interleave their captured output into each other's envelopes.\n *\n * The loop ends when `input` ends: per the MCP stdio lifecycle the client\n * closes stdin to shut the server down, so EOF resolves this promise, the\n * action resolves, and cli.ts — the only process-exit decider — lets the\n * process drain to exit 0. No signal handling, no exit call here.\n */\nimport type { Readable, Writable } from \"node:stream\";\nimport { frame, splitFrames } from \"../../core/mcp/framing.js\";\nimport {\n INTERNAL_ERROR,\n errorResponse,\n resultResponse,\n routeLine,\n toolReply,\n} from \"../../core/mcp/protocol.js\";\nimport type { RouteOutcome } from \"../../core/mcp/protocol.js\";\nimport type { DispatchResult } from \"./dispatch.js\";\nimport { MCP_TOOLS, type McpTool } from \"../../core/mcp/tools.js\";\n\nexport interface ServeIo {\n readonly input: Readable;\n readonly output: Writable;\n readonly log: Writable;\n}\n\n/** The dispatcher, as a parameter: serve() stays testable with a stub and owns no registration. */\nexport type ToolRunner = (argv: readonly string[]) => Promise<DispatchResult>;\n\nexport async function serve(\n io: ServeIo,\n runTool: ToolRunner,\n tools: readonly McpTool[] = MCP_TOOLS,\n): Promise<void> {\n // One startup line, to stderr only — a client is entitled to a stdout that\n // has never carried anything but frames, from the very first byte.\n io.log.write(`loam mcp: serving ${process.cwd()} over stdio\\n`);\n // Decode at the stream, not per chunk: a UTF-8 code point split across two\n // chunks would corrupt if each chunk were stringified on its own.\n io.input.setEncoding(\"utf8\");\n let rest = \"\";\n for await (const chunk of io.input) {\n const split = splitFrames(rest + String(chunk));\n rest = split.rest;\n for (const line of split.lines) await handleLine(line, io, runTool, tools);\n }\n // A final frame the client sent without a trailing newline is still a frame:\n // EOF terminates it exactly as the delimiter would have.\n if (rest.trim() !== \"\") await handleLine(rest, io, runTool, tools);\n}\n\nasync function handleLine(\n line: string,\n io: ServeIo,\n runTool: ToolRunner,\n tools: readonly McpTool[],\n): Promise<void> {\n const outcome: RouteOutcome = routeLine(line, tools);\n if (outcome.kind === \"ignore\") return;\n if (outcome.kind === \"reply\") {\n io.output.write(frame(outcome.response));\n return;\n }\n await handleCall(outcome, io, runTool);\n}\n\n/** One tools/call, contained: whatever this call does, the loop survives it. */\nasync function handleCall(\n call: Extract<RouteOutcome, { kind: \"call\" }>,\n io: ServeIo,\n runTool: ToolRunner,\n): Promise<void> {\n try {\n const run = await runTool(call.argv);\n if (run.stderr.trim() !== \"\") {\n // A command's diagnostics are server-side logging, never protocol bytes.\n io.log.write(`loam mcp: ${call.toolName} stderr: ${run.stderr.trim()}\\n`);\n }\n const reply = toolReply(run);\n io.output.write(frame(\n reply.kind === \"result\"\n ? resultResponse(call.id, reply.result)\n : errorResponse(call.id, reply.code, reply.message),\n ));\n } catch (err) {\n // The dispatcher already converts everything it can into an envelope, so\n // reaching here means the failure was outside it (or in the wrapping\n // itself). It becomes a JSON-RPC error for THIS id — the caller learns\n // which call died, with the reason — and the loop reads the next frame.\n const detail = err instanceof Error ? err.message : String(err);\n io.output.write(frame(errorResponse(call.id, INTERNAL_ERROR, `${call.toolName} failed: ${detail}`)));\n }\n}\n"]}
@@ -0,0 +1,170 @@
1
+ /**
2
+ * Each active OpenSpec change as a staged loam feature: its intent, the
3
+ * authored artifacts a disposition kept, a verbatim copy of the source change
4
+ * tree, and one delta `spec.md` per service its requirements routed to.
5
+ *
6
+ * This is the phase that resolves RENAMED pairs, and the reason it is the
7
+ * longest: a rename is the only place where the living corpus, the delta and
8
+ * the human's identity decision all have to agree, and every disagreement
9
+ * between them is a refusal rather than a guess. `./feature.js` holds the file
10
+ * shapes this emits; `./living.js` is the same corpus read for the other half.
11
+ */
12
+ import { join } from "node:path";
13
+ import { parseRequirements } from "../../../core/document/parse.js";
14
+ import {} from "../../../core/document/spec.js";
15
+ import { ownValue } from "../../../core/kernel/records.js";
16
+ import {} from "../../../core/openspec/model/mapping.js";
17
+ import { isOpenSpecArtifactDisposition } from "../../../core/openspec/model/model.js";
18
+ import { planWrite } from "../../../core/staging/writes.js";
19
+ import { selectedServices } from "../openspec/decisions.js";
20
+ import { OpenSpecCommandError } from "../openspec/error.js";
21
+ import { safeArtifactRelative } from "../openspec/paths.js";
22
+ import { readSourceArtifact } from "../openspec/read.js";
23
+ import { featureSlug, migrationFrontmatter, renderAuthoredBundle, serializeDeltaRequirements, } from "./feature.js";
24
+ import { assertMaterializedRequirementIds, requirementWithCapability } from "./stage.js";
25
+ export async function materializeActiveChanges(inventory, mapping, target, livingByCapability) {
26
+ const writes = [];
27
+ const inventoryArtifactsByPath = new Map(inventory.artifacts.map((artifact) => [artifact.path, artifact]));
28
+ for (const change of inventory.changes.active) {
29
+ const decision = inventory.changeDecisions.find((item) => item.change === change.id);
30
+ const feature = ownValue(mapping.changes, change.id)?.feature ?? null;
31
+ if (decision === undefined || feature === null)
32
+ continue; // readiness prevents this on --apply
33
+ const featureDir = join(target, "features", `${feature}-${featureSlug(decision.title, change.id)}`);
34
+ // Preserve the complete authored source change tree, including metadata,
35
+ // rename syntax, custom artifacts, and original delta section ordering.
36
+ for (const artifactPath of change.artifacts) {
37
+ const segments = safeArtifactRelative(artifactPath, `changes/${change.id}/`, `OpenSpec change '${change.id}'`);
38
+ writes.push(planWrite(join(featureDir, "legacy", "openspec", ...segments), await readSourceArtifact(inventory.root, artifactPath)));
39
+ }
40
+ const authored = [];
41
+ for (const artifactDecision of inventory.artifactDecisions) {
42
+ const artifact = inventoryArtifactsByPath.get(artifactDecision.path);
43
+ if (artifact?.changeId !== change.id)
44
+ continue;
45
+ const disposition = ownValue(mapping.artifacts, artifactDecision.path);
46
+ if (disposition === undefined)
47
+ continue; // readiness prevents this on --apply
48
+ // The mapping holds the authored string; everything below compares it
49
+ // against disposition literals, so this is where the value has to become
50
+ // one of them or stop being routed. `mapping.invalid-artifact-disposition`
51
+ // already refuses an unknown one, so readiness prevents this too — but a
52
+ // silent skip is the right failure for a value nothing here can act on.
53
+ if (!isOpenSpecArtifactDisposition(disposition))
54
+ continue;
55
+ authored.push({
56
+ path: artifactDecision.path,
57
+ kind: artifactDecision.kind,
58
+ disposition,
59
+ raw: await readSourceArtifact(inventory.root, artifactDecision.path),
60
+ });
61
+ }
62
+ const convertedProposals = authored.filter((artifact) => artifact.kind === "proposal" && artifact.disposition === "convert-to-intent");
63
+ const retainedProposals = authored.filter((artifact) => artifact.kind === "proposal" && artifact.disposition !== "convert-to-intent");
64
+ const intentBody = convertedProposals.length > 0
65
+ ? renderAuthoredBundle("## Migrated OpenSpec proposal", convertedProposals)
66
+ : "No proposal was converted into this intent. Review the retained OpenSpec artifacts and migration-plan.json before promotion.\n";
67
+ writes.push(planWrite(join(featureDir, "intent.md"), `${migrationFrontmatter(feature, decision.title)}\n\n# ${decision.title}\n\n<!-- Staged from OpenSpec change '${change.id}'. This feature is deliberately not validation-green yet. -->\n\n${intentBody}`));
68
+ if (retainedProposals.length > 0) {
69
+ writes.push(planWrite(join(featureDir, "legacy", "proposal.md"), renderAuthoredBundle("# Retained OpenSpec proposal", retainedProposals)));
70
+ }
71
+ const tasks = authored.filter((artifact) => artifact.kind === "tasks");
72
+ if (tasks.length > 0) {
73
+ writes.push(planWrite(join(featureDir, "legacy", "tasks.md"), renderAuthoredBundle("# OpenSpec task checklist", tasks)));
74
+ }
75
+ const reviewedDesigns = authored.filter((artifact) => artifact.kind === "change-design" && artifact.disposition === "review-as-feature-adr");
76
+ if (reviewedDesigns.length > 0) {
77
+ writes.push(planWrite(join(featureDir, "adrs", "openspec-design.md"), renderAuthoredBundle("# OpenSpec design (review required)", reviewedDesigns)));
78
+ }
79
+ const retainedDesigns = authored.filter((artifact) => artifact.kind === "change-design" && artifact.disposition !== "review-as-feature-adr");
80
+ if (retainedDesigns.length > 0) {
81
+ writes.push(planWrite(join(featureDir, "legacy", "design.md"), renderAuthoredBundle("# Retained OpenSpec design", retainedDesigns)));
82
+ }
83
+ if (change.metadata.skipSpecs)
84
+ continue;
85
+ const deltaByService = new Map();
86
+ const changeRenames = inventory.renamed.filter((item) => item.scope === "active" && item.changeId === change.id);
87
+ const materializedRenameKeys = new Set();
88
+ const addDelta = (service, requirement, origin) => {
89
+ const existing = deltaByService.get(service) ?? [];
90
+ const collision = existing.find((item) => item.name === requirement.name
91
+ || (item.id !== undefined && requirement.id !== undefined && item.id === requirement.id));
92
+ if (collision !== undefined) {
93
+ const identity = requirement.id === undefined ? requirement.name : requirement.id;
94
+ throw new OpenSpecCommandError("invalid-option", `Active change '${change.id}' produces colliding requirement '${identity}' in service '${service}' while materializing ${origin}.`);
95
+ }
96
+ existing.push(requirement);
97
+ deltaByService.set(service, existing);
98
+ };
99
+ for (const spec of change.specs) {
100
+ const requirements = parseRequirements(await readSourceArtifact(inventory.root, spec.path))
101
+ .filter((requirement) => requirement.kind !== "BASE");
102
+ for (const parsed of requirements) {
103
+ const matchingRenames = changeRenames.filter((rename) => rename.capability === spec.capability
104
+ && rename.from !== null
105
+ && rename.to !== null
106
+ && (parsed.name === rename.from || parsed.name === rename.to));
107
+ if (matchingRenames.length > 1) {
108
+ throw new OpenSpecCommandError("invalid-option", `Active change '${change.id}' requirement '${parsed.name}' matches multiple RENAMED pairs.`);
109
+ }
110
+ const rename = matchingRenames[0];
111
+ let requirement = parsed;
112
+ let routingName = parsed.name;
113
+ if (rename !== undefined && rename.from !== null && rename.to !== null && rename.requirementId !== null) {
114
+ if (parsed.kind !== "MODIFIED") {
115
+ throw new OpenSpecCommandError("invalid-option", `Active change '${change.id}' combines RENAMED '${rename.from}' → '${rename.to}' with ${parsed.kind} '${parsed.name}'; review the conflicting delta before --apply.`);
116
+ }
117
+ if (parsed.id !== undefined && parsed.id !== rename.requirementId) {
118
+ throw new OpenSpecCommandError("invalid-option", `Active change '${change.id}' MODIFIED requirement '${parsed.name}' has Requirement-ID '${parsed.id}', but its RENAMED source resolves to '${rename.requirementId}'.`);
119
+ }
120
+ const annotation = `OpenSpec-Living-Source: ${rename.capability} :: ${rename.from}`;
121
+ requirement = {
122
+ ...parsed,
123
+ id: rename.requirementId,
124
+ name: rename.to,
125
+ text: parsed.text.includes(annotation) ? parsed.text : [...parsed.text, "", annotation],
126
+ section: "## MODIFIED Requirements",
127
+ };
128
+ routingName = rename.from;
129
+ materializedRenameKeys.add(rename.key);
130
+ }
131
+ // Every delta kind uniformly: REMOVED is harmless (every check exempts
132
+ // it), and a MODIFIED body MUST carry the line or its wholesale
133
+ // replace would strip the one the living side was staged with.
134
+ const withCapability = requirementWithCapability(requirement, spec.capability);
135
+ for (const service of selectedServices(mapping, spec.capability, routingName)) {
136
+ addDelta(service, withCapability, spec.path);
137
+ }
138
+ }
139
+ }
140
+ for (const rename of changeRenames) {
141
+ if (materializedRenameKeys.has(rename.key))
142
+ continue;
143
+ if (rename.from === null || rename.to === null || rename.requirementId === null)
144
+ continue;
145
+ const source = (livingByCapability.get(rename.capability) ?? [])
146
+ .filter((requirement) => requirement.name === rename.from)[0];
147
+ if (source === undefined)
148
+ continue; // readiness prevents this on --apply
149
+ const annotation = `OpenSpec-Living-Source: ${rename.capability} :: ${rename.from}`;
150
+ const text = source.text.includes(annotation) ? source.text : [...source.text, "", annotation];
151
+ const modified = {
152
+ ...source,
153
+ kind: "MODIFIED",
154
+ id: rename.requirementId,
155
+ name: rename.to,
156
+ text,
157
+ section: "## MODIFIED Requirements",
158
+ };
159
+ for (const service of selectedServices(mapping, rename.capability, rename.from)) {
160
+ addDelta(service, requirementWithCapability(modified, rename.capability), rename.path);
161
+ }
162
+ }
163
+ for (const [service, requirements] of [...deltaByService].sort(([a], [b]) => a.localeCompare(b))) {
164
+ assertMaterializedRequirementIds(`Active change '${change.id}' mapped to service '${service}'`, requirements);
165
+ writes.push(planWrite(join(featureDir, "specs", service, "spec.md"), serializeDeltaRequirements(requirements)));
166
+ }
167
+ }
168
+ return writes;
169
+ }
170
+ //# sourceMappingURL=active.js.map