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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1256) hide show
  1. package/CHANGELOG.md +5992 -82
  2. package/COMPARISON.md +168 -63
  3. package/CONTRIBUTING.md +121 -0
  4. package/MIGRATING-from-OpenSpec.md +238 -55
  5. package/QUICKSTART.md +302 -0
  6. package/README.md +653 -144
  7. package/ROADMAP.md +1035 -0
  8. package/SCHEMA.md +3916 -263
  9. package/SECURITY.md +21 -3
  10. package/WORKFLOW.md +927 -0
  11. package/dist/cli.js +133 -21
  12. package/dist/cli.js.map +1 -1
  13. package/dist/commands/adopt/adopt.js +204 -0
  14. package/dist/commands/adopt/adopt.js.map +1 -0
  15. package/dist/commands/adopt/render.js +309 -0
  16. package/dist/commands/adopt/render.js.map +1 -0
  17. package/dist/commands/archive/archive.js +74 -0
  18. package/dist/commands/archive/archive.js.map +1 -0
  19. package/dist/commands/archive/closing.js +42 -0
  20. package/dist/commands/archive/closing.js.map +1 -0
  21. package/dist/commands/archive/plan/contracts/asyncapi.js +172 -0
  22. package/dist/commands/archive/plan/contracts/asyncapi.js.map +1 -0
  23. package/dist/commands/archive/plan/contracts/consumers.js +56 -0
  24. package/dist/commands/archive/plan/contracts/consumers.js.map +1 -0
  25. package/dist/commands/archive/plan/contracts/openapi.js +193 -0
  26. package/dist/commands/archive/plan/contracts/openapi.js.map +1 -0
  27. package/dist/commands/archive/plan/contracts/verdict-lines.js +103 -0
  28. package/dist/commands/archive/plan/contracts/verdict-lines.js.map +1 -0
  29. package/dist/commands/archive/plan/document/head.js +151 -0
  30. package/dist/commands/archive/plan/document/head.js.map +1 -0
  31. package/dist/commands/archive/plan/document/links.js +284 -0
  32. package/dist/commands/archive/plan/document/links.js.map +1 -0
  33. package/dist/commands/archive/plan/document/run.js +136 -0
  34. package/dist/commands/archive/plan/document/run.js.map +1 -0
  35. package/dist/commands/archive/plan/gate.js +319 -0
  36. package/dist/commands/archive/plan/gate.js.map +1 -0
  37. package/dist/commands/archive/plan/landscape.js +298 -0
  38. package/dist/commands/archive/plan/landscape.js.map +1 -0
  39. package/dist/commands/archive/plan/model/extending.js +85 -0
  40. package/dist/commands/archive/plan/model/extending.js.map +1 -0
  41. package/dist/commands/archive/plan/refusal.js +106 -0
  42. package/dist/commands/archive/plan/refusal.js.map +1 -0
  43. package/dist/commands/archive/plan/specs.js +318 -0
  44. package/dist/commands/archive/plan/specs.js.map +1 -0
  45. package/dist/commands/archive/plan/state.js +30 -0
  46. package/dist/commands/archive/plan/state.js.map +1 -0
  47. package/dist/commands/archive/run.js +355 -0
  48. package/dist/commands/archive/run.js.map +1 -0
  49. package/dist/commands/archive/shipped.js +49 -0
  50. package/dist/commands/archive/shipped.js.map +1 -0
  51. package/dist/commands/context/context.js +166 -0
  52. package/dist/commands/context/context.js.map +1 -0
  53. package/dist/commands/context/print.js +305 -0
  54. package/dist/commands/context/print.js.map +1 -0
  55. package/dist/commands/delta/delta.js +367 -0
  56. package/dist/commands/delta/delta.js.map +1 -0
  57. package/dist/commands/delta/print.js +221 -0
  58. package/dist/commands/delta/print.js.map +1 -0
  59. package/dist/commands/dependencies.js +6 -8
  60. package/dist/commands/dependencies.js.map +1 -1
  61. package/dist/commands/diff/diff.js +86 -0
  62. package/dist/commands/diff/diff.js.map +1 -0
  63. package/dist/commands/diff/print.js +38 -0
  64. package/dist/commands/diff/print.js.map +1 -0
  65. package/dist/commands/doctor.js +65 -5
  66. package/dist/commands/doctor.js.map +1 -1
  67. package/dist/commands/explain/explain.js +227 -0
  68. package/dist/commands/explain/explain.js.map +1 -0
  69. package/dist/commands/explore.js +39 -28
  70. package/dist/commands/explore.js.map +1 -1
  71. package/dist/commands/gate/gate.js +152 -0
  72. package/dist/commands/gate/gate.js.map +1 -0
  73. package/dist/commands/gate/print.js +66 -0
  74. package/dist/commands/gate/print.js.map +1 -0
  75. package/dist/commands/gherkin/commit.js +105 -0
  76. package/dist/commands/gherkin/commit.js.map +1 -0
  77. package/dist/commands/gherkin/gherkin.js +262 -0
  78. package/dist/commands/gherkin/gherkin.js.map +1 -0
  79. package/dist/commands/gherkin/reconcile.js +146 -0
  80. package/dist/commands/gherkin/reconcile.js.map +1 -0
  81. package/dist/commands/gherkin/render.js +77 -0
  82. package/dist/commands/gherkin/render.js.map +1 -0
  83. package/dist/commands/init/example.js +204 -0
  84. package/dist/commands/init/example.js.map +1 -0
  85. package/dist/commands/init/first-hour.js +72 -0
  86. package/dist/commands/init/first-hour.js.map +1 -0
  87. package/dist/commands/{init.js → init/init.js} +142 -71
  88. package/dist/commands/init/init.js.map +1 -0
  89. package/dist/commands/init/mcp.js +131 -0
  90. package/dist/commands/init/mcp.js.map +1 -0
  91. package/dist/commands/init/options.js +78 -0
  92. package/dist/commands/init/options.js.map +1 -0
  93. package/dist/commands/instructions.js +72 -14
  94. package/dist/commands/instructions.js.map +1 -1
  95. package/dist/commands/list/campaign/campaign.js +63 -0
  96. package/dist/commands/list/campaign/campaign.js.map +1 -0
  97. package/dist/commands/list/campaign/owners.js +65 -0
  98. package/dist/commands/list/campaign/owners.js.map +1 -0
  99. package/dist/commands/list/json.js +155 -0
  100. package/dist/commands/list/json.js.map +1 -0
  101. package/dist/commands/list/list.js +358 -0
  102. package/dist/commands/list/list.js.map +1 -0
  103. package/dist/commands/list/print.js +344 -0
  104. package/dist/commands/list/print.js.map +1 -0
  105. package/dist/commands/list/review.js +120 -0
  106. package/dist/commands/list/review.js.map +1 -0
  107. package/dist/commands/list/suites/suites.js +140 -0
  108. package/dist/commands/list/suites/suites.js.map +1 -0
  109. package/dist/commands/list/views.js +108 -0
  110. package/dist/commands/list/views.js.map +1 -0
  111. package/dist/commands/mcp/dispatch.js +238 -0
  112. package/dist/commands/mcp/dispatch.js.map +1 -0
  113. package/dist/commands/mcp/mcp.js +75 -0
  114. package/dist/commands/mcp/mcp.js.map +1 -0
  115. package/dist/commands/mcp/serve.js +55 -0
  116. package/dist/commands/mcp/serve.js.map +1 -0
  117. package/dist/commands/migrate-openspec/materialize/active.js +175 -0
  118. package/dist/commands/migrate-openspec/materialize/active.js.map +1 -0
  119. package/dist/commands/migrate-openspec/materialize/feature.js +41 -0
  120. package/dist/commands/migrate-openspec/materialize/feature.js.map +1 -0
  121. package/dist/commands/migrate-openspec/materialize/living.js +62 -0
  122. package/dist/commands/migrate-openspec/materialize/living.js.map +1 -0
  123. package/dist/commands/migrate-openspec/materialize/stage.js +143 -0
  124. package/dist/commands/migrate-openspec/materialize/stage.js.map +1 -0
  125. package/dist/commands/migrate-openspec/materialize/target.js +219 -0
  126. package/dist/commands/migrate-openspec/materialize/target.js.map +1 -0
  127. package/dist/commands/migrate-openspec/migrate-openspec.js +142 -0
  128. package/dist/commands/migrate-openspec/migrate-openspec.js.map +1 -0
  129. package/dist/commands/migrate-openspec/openspec/decisions.js +86 -0
  130. package/dist/commands/migrate-openspec/openspec/decisions.js.map +1 -0
  131. package/dist/commands/migrate-openspec/openspec/error.js +18 -0
  132. package/dist/commands/migrate-openspec/openspec/error.js.map +1 -0
  133. package/dist/commands/migrate-openspec/openspec/mapping.js +162 -0
  134. package/dist/commands/migrate-openspec/openspec/mapping.js.map +1 -0
  135. package/dist/commands/migrate-openspec/openspec/paths.js +40 -0
  136. package/dist/commands/migrate-openspec/openspec/paths.js.map +1 -0
  137. package/dist/commands/migrate-openspec/openspec/read.js +49 -0
  138. package/dist/commands/migrate-openspec/openspec/read.js.map +1 -0
  139. package/dist/commands/migrate-openspec/print.js +89 -0
  140. package/dist/commands/migrate-openspec/print.js.map +1 -0
  141. package/dist/commands/new/capability-template.js +118 -0
  142. package/dist/commands/new/capability-template.js.map +1 -0
  143. package/dist/commands/new/commit.js +62 -0
  144. package/dist/commands/new/commit.js.map +1 -0
  145. package/dist/commands/new/modifies.js +206 -0
  146. package/dist/commands/new/modifies.js.map +1 -0
  147. package/dist/commands/new/new.js +328 -0
  148. package/dist/commands/new/new.js.map +1 -0
  149. package/dist/commands/new/templates.js +279 -0
  150. package/dist/commands/new/templates.js.map +1 -0
  151. package/dist/commands/open.js +199 -0
  152. package/dist/commands/open.js.map +1 -0
  153. package/dist/commands/policy/format.js +152 -0
  154. package/dist/commands/policy/format.js.map +1 -0
  155. package/dist/commands/{docs-repo-gate.js → policy/gate.js} +38 -11
  156. package/dist/commands/policy/gate.js.map +1 -0
  157. package/dist/commands/rebase/edit.js +106 -0
  158. package/dist/commands/rebase/edit.js.map +1 -0
  159. package/dist/commands/rebase/living.js +185 -0
  160. package/dist/commands/rebase/living.js.map +1 -0
  161. package/dist/commands/rebase/plan.js +245 -0
  162. package/dist/commands/rebase/plan.js.map +1 -0
  163. package/dist/commands/rebase/rebase.js +300 -0
  164. package/dist/commands/rebase/rebase.js.map +1 -0
  165. package/dist/commands/seed/commit.js +221 -0
  166. package/dist/commands/seed/commit.js.map +1 -0
  167. package/dist/commands/seed/plan.js +278 -0
  168. package/dist/commands/seed/plan.js.map +1 -0
  169. package/dist/commands/seed/seed.js +174 -0
  170. package/dist/commands/seed/seed.js.map +1 -0
  171. package/dist/commands/show/feature.js +182 -0
  172. package/dist/commands/show/feature.js.map +1 -0
  173. package/dist/commands/show/introduced.js +157 -0
  174. package/dist/commands/show/introduced.js.map +1 -0
  175. package/dist/commands/show/marks.js +53 -0
  176. package/dist/commands/show/marks.js.map +1 -0
  177. package/dist/commands/show/service.js +239 -0
  178. package/dist/commands/show/service.js.map +1 -0
  179. package/dist/commands/show/show.js +87 -0
  180. package/dist/commands/show/show.js.map +1 -0
  181. package/dist/commands/status/fleet-next.js +90 -0
  182. package/dist/commands/status/fleet-next.js.map +1 -0
  183. package/dist/commands/status/json.js +47 -0
  184. package/dist/commands/status/json.js.map +1 -0
  185. package/dist/commands/status/print.js +209 -0
  186. package/dist/commands/status/print.js.map +1 -0
  187. package/dist/commands/status/status.js +115 -0
  188. package/dist/commands/status/status.js.map +1 -0
  189. package/dist/commands/steps/steps.js +269 -0
  190. package/dist/commands/steps/steps.js.map +1 -0
  191. package/dist/commands/subsystem/edit.js +192 -0
  192. package/dist/commands/subsystem/edit.js.map +1 -0
  193. package/dist/commands/subsystem/move.js +325 -0
  194. package/dist/commands/subsystem/move.js.map +1 -0
  195. package/dist/commands/subsystem/query.js +113 -0
  196. package/dist/commands/subsystem/query.js.map +1 -0
  197. package/dist/commands/subsystem/subsystem.js +98 -0
  198. package/dist/commands/subsystem/subsystem.js.map +1 -0
  199. package/dist/commands/subsystem/sync.js +318 -0
  200. package/dist/commands/subsystem/sync.js.map +1 -0
  201. package/dist/commands/subsystem/txn/exclude.js +132 -0
  202. package/dist/commands/subsystem/txn/exclude.js.map +1 -0
  203. package/dist/commands/subsystem/txn/links.js +128 -0
  204. package/dist/commands/subsystem/txn/links.js.map +1 -0
  205. package/dist/commands/subsystem/txn/report.js +174 -0
  206. package/dist/commands/subsystem/txn/report.js.map +1 -0
  207. package/dist/commands/subsystem/txn/txn.js +196 -0
  208. package/dist/commands/subsystem/txn/txn.js.map +1 -0
  209. package/dist/commands/subsystem/txn/views.js +249 -0
  210. package/dist/commands/subsystem/txn/views.js.map +1 -0
  211. package/dist/commands/tasks/actions.js +107 -0
  212. package/dist/commands/tasks/actions.js.map +1 -0
  213. package/dist/commands/tasks/render.js +253 -0
  214. package/dist/commands/tasks/render.js.map +1 -0
  215. package/dist/commands/tasks/tasks.js +119 -0
  216. package/dist/commands/tasks/tasks.js.map +1 -0
  217. package/dist/commands/unarchive/manifest.js +176 -0
  218. package/dist/commands/unarchive/manifest.js.map +1 -0
  219. package/dist/commands/unarchive/restore.js +254 -0
  220. package/dist/commands/unarchive/restore.js.map +1 -0
  221. package/dist/commands/unarchive/unarchive.js +59 -0
  222. package/dist/commands/unarchive/unarchive.js.map +1 -0
  223. package/dist/commands/validate/arch-coverage.js +245 -0
  224. package/dist/commands/validate/arch-coverage.js.map +1 -0
  225. package/dist/commands/validate/checks/fleet-shape.js +204 -0
  226. package/dist/commands/validate/checks/fleet-shape.js.map +1 -0
  227. package/dist/commands/validate/checks/health-deps.js +58 -0
  228. package/dist/commands/validate/checks/health-deps.js.map +1 -0
  229. package/dist/commands/validate/checks/introduced.js +102 -0
  230. package/dist/commands/validate/checks/introduced.js.map +1 -0
  231. package/dist/commands/validate/checks/requirements.js +264 -0
  232. package/dist/commands/validate/checks/requirements.js.map +1 -0
  233. package/dist/commands/validate/checks/sources.js +85 -0
  234. package/dist/commands/validate/checks/sources.js.map +1 -0
  235. package/dist/commands/validate/coverage/covers-after.js +105 -0
  236. package/dist/commands/validate/coverage/covers-after.js.map +1 -0
  237. package/dist/commands/validate/feature.js +222 -0
  238. package/dist/commands/validate/feature.js.map +1 -0
  239. package/dist/commands/validate/fleet/census.js +93 -0
  240. package/dist/commands/validate/fleet/census.js.map +1 -0
  241. package/dist/commands/validate/fleet/kind-tags.js +39 -0
  242. package/dist/commands/validate/fleet/kind-tags.js.map +1 -0
  243. package/dist/commands/validate/fleet/landscape.js +371 -0
  244. package/dist/commands/validate/fleet/landscape.js.map +1 -0
  245. package/dist/commands/validate/fleet/load.js +118 -0
  246. package/dist/commands/validate/fleet/load.js.map +1 -0
  247. package/dist/commands/validate/fleet/map/attest.js +98 -0
  248. package/dist/commands/validate/fleet/map/attest.js.map +1 -0
  249. package/dist/commands/validate/fleet/map/bindings.js +107 -0
  250. package/dist/commands/validate/fleet/map/bindings.js.map +1 -0
  251. package/dist/commands/validate/fleet/map/consumers.js +244 -0
  252. package/dist/commands/validate/fleet/map/consumers.js.map +1 -0
  253. package/dist/commands/validate/fleet/map/isolation.js +116 -0
  254. package/dist/commands/validate/fleet/map/isolation.js.map +1 -0
  255. package/dist/commands/validate/fleet/map/usecases.js +54 -0
  256. package/dist/commands/validate/fleet/map/usecases.js.map +1 -0
  257. package/dist/commands/validate/fleet/obligations.js +266 -0
  258. package/dist/commands/validate/fleet/obligations.js.map +1 -0
  259. package/dist/commands/validate/fleet/scorecard/adoption.js +102 -0
  260. package/dist/commands/validate/fleet/scorecard/adoption.js.map +1 -0
  261. package/dist/commands/validate/fleet/scorecard/contracts.js +98 -0
  262. package/dist/commands/validate/fleet/scorecard/contracts.js.map +1 -0
  263. package/dist/commands/validate/fleet/scorecard/print.js +71 -0
  264. package/dist/commands/validate/fleet/scorecard/print.js.map +1 -0
  265. package/dist/commands/validate/fleet/scorecard/scorecard.js +162 -0
  266. package/dist/commands/validate/fleet/scorecard/scorecard.js.map +1 -0
  267. package/dist/commands/validate/fleet/usecases/place.js +13 -0
  268. package/dist/commands/validate/fleet/usecases/place.js.map +1 -0
  269. package/dist/commands/validate/fleet/views/fleet-project.js +217 -0
  270. package/dist/commands/validate/fleet/views/fleet-project.js.map +1 -0
  271. package/dist/commands/validate/fleet/views/ids.js +75 -0
  272. package/dist/commands/validate/fleet/views/ids.js.map +1 -0
  273. package/dist/commands/validate/fleet/views/projects.js +278 -0
  274. package/dist/commands/validate/fleet/views/projects.js.map +1 -0
  275. package/dist/commands/validate/fleet/views/root-documents.js +83 -0
  276. package/dist/commands/validate/fleet/views/root-documents.js.map +1 -0
  277. package/dist/commands/validate/fleet/views/stale.js +52 -0
  278. package/dist/commands/validate/fleet/views/stale.js.map +1 -0
  279. package/dist/commands/validate/links/corpus.js +89 -0
  280. package/dist/commands/validate/links/corpus.js.map +1 -0
  281. package/dist/commands/validate/links/glossary.js +75 -0
  282. package/dist/commands/validate/links/glossary.js.map +1 -0
  283. package/dist/commands/validate/render/repeats.js +63 -0
  284. package/dist/commands/validate/render/repeats.js.map +1 -0
  285. package/dist/commands/validate/render/rollups.js +115 -0
  286. package/dist/commands/validate/render/rollups.js.map +1 -0
  287. package/dist/commands/validate/render/text.js +199 -0
  288. package/dist/commands/validate/render/text.js.map +1 -0
  289. package/dist/commands/validate/report.js +145 -0
  290. package/dist/commands/validate/report.js.map +1 -0
  291. package/dist/commands/validate/scope.js +113 -0
  292. package/dist/commands/validate/scope.js.map +1 -0
  293. package/dist/commands/validate/service/api.js +252 -0
  294. package/dist/commands/validate/service/api.js.map +1 -0
  295. package/dist/commands/validate/service/contracts/generated.js +134 -0
  296. package/dist/commands/validate/service/contracts/generated.js.map +1 -0
  297. package/dist/commands/validate/service/events/events.js +241 -0
  298. package/dist/commands/validate/service/events/events.js.map +1 -0
  299. package/dist/commands/validate/service/events/message-producers.js +77 -0
  300. package/dist/commands/validate/service/events/message-producers.js.map +1 -0
  301. package/dist/commands/validate/service/evidence-pins.js +177 -0
  302. package/dist/commands/validate/service/evidence-pins.js.map +1 -0
  303. package/dist/commands/validate/service/model/diverged.js +226 -0
  304. package/dist/commands/validate/service/model/diverged.js.map +1 -0
  305. package/dist/commands/validate/service/model/grade.js +163 -0
  306. package/dist/commands/validate/service/model/grade.js.map +1 -0
  307. package/dist/commands/validate/service/service.js +310 -0
  308. package/dist/commands/validate/service/service.js.map +1 -0
  309. package/dist/commands/validate/service/specs.js +279 -0
  310. package/dist/commands/validate/service/specs.js.map +1 -0
  311. package/dist/commands/validate/service/spine.js +148 -0
  312. package/dist/commands/validate/service/spine.js.map +1 -0
  313. package/dist/commands/validate/service/usecases/tags.js +113 -0
  314. package/dist/commands/validate/service/usecases/tags.js.map +1 -0
  315. package/dist/commands/validate/service/usecases/usecases.js +209 -0
  316. package/dist/commands/validate/service/usecases/usecases.js.map +1 -0
  317. package/dist/commands/validate/validate.js +363 -0
  318. package/dist/commands/validate/validate.js.map +1 -0
  319. package/dist/commands/verify/cross/diff.js +178 -0
  320. package/dist/commands/verify/cross/diff.js.map +1 -0
  321. package/dist/commands/verify/evidence/contract.js +32 -0
  322. package/dist/commands/verify/evidence/contract.js.map +1 -0
  323. package/dist/commands/verify/evidence/pins.js +52 -0
  324. package/dist/commands/verify/evidence/pins.js.map +1 -0
  325. package/dist/commands/verify/evidence/read.js +81 -0
  326. package/dist/commands/verify/evidence/read.js.map +1 -0
  327. package/dist/commands/verify/frozen.js +263 -0
  328. package/dist/commands/verify/frozen.js.map +1 -0
  329. package/dist/commands/verify/record.js +278 -0
  330. package/dist/commands/verify/record.js.map +1 -0
  331. package/dist/commands/verify/report.js +206 -0
  332. package/dist/commands/verify/report.js.map +1 -0
  333. package/dist/commands/verify/results.js +328 -0
  334. package/dist/commands/verify/results.js.map +1 -0
  335. package/dist/commands/verify/verify.js +220 -0
  336. package/dist/commands/verify/verify.js.map +1 -0
  337. package/dist/commands/vouch/contract.js +11 -0
  338. package/dist/commands/vouch/contract.js.map +1 -0
  339. package/dist/commands/vouch/pack/contract.js +2 -0
  340. package/dist/commands/vouch/pack/contract.js.map +1 -0
  341. package/dist/commands/vouch/pack/pack.js +266 -0
  342. package/dist/commands/vouch/pack/pack.js.map +1 -0
  343. package/dist/commands/vouch/pack/print.js +266 -0
  344. package/dist/commands/vouch/pack/print.js.map +1 -0
  345. package/dist/commands/vouch/pack/sections.js +141 -0
  346. package/dist/commands/vouch/pack/sections.js.map +1 -0
  347. package/dist/commands/vouch/prompt/confirm.js +46 -0
  348. package/dist/commands/vouch/prompt/confirm.js.map +1 -0
  349. package/dist/commands/vouch/report.js +101 -0
  350. package/dist/commands/vouch/report.js.map +1 -0
  351. package/dist/commands/vouch/run.js +230 -0
  352. package/dist/commands/vouch/run.js.map +1 -0
  353. package/dist/commands/vouch/sample/plan.js +111 -0
  354. package/dist/commands/vouch/sample/plan.js.map +1 -0
  355. package/dist/commands/vouch/sample/print.js +109 -0
  356. package/dist/commands/vouch/sample/print.js.map +1 -0
  357. package/dist/commands/vouch/vet/verify.js +155 -0
  358. package/dist/commands/vouch/vet/verify.js.map +1 -0
  359. package/dist/commands/vouch/vouch.js +169 -0
  360. package/dist/commands/vouch/vouch.js.map +1 -0
  361. package/dist/core/agent/agents-md/command-map.js +299 -0
  362. package/dist/core/agent/agents-md/command-map.js.map +1 -0
  363. package/dist/core/agent/agents-md/map/explain.js +46 -0
  364. package/dist/core/agent/agents-md/map/explain.js.map +1 -0
  365. package/dist/core/agent/agents-md/map/lenses/context.js +50 -0
  366. package/dist/core/agent/agents-md/map/lenses/context.js.map +1 -0
  367. package/dist/core/agent/agents-md/map/lenses/diff.js +59 -0
  368. package/dist/core/agent/agents-md/map/lenses/diff.js.map +1 -0
  369. package/dist/core/agent/agents-md/map/lenses/gate.js +65 -0
  370. package/dist/core/agent/agents-md/map/lenses/gate.js.map +1 -0
  371. package/dist/core/agent/agents-md/map/mcp.js +44 -0
  372. package/dist/core/agent/agents-md/map/mcp.js.map +1 -0
  373. package/dist/core/agent/agents-md/map/status.js +78 -0
  374. package/dist/core/agent/agents-md/map/status.js.map +1 -0
  375. package/dist/core/agent/agents-md/map/subsystem.js +104 -0
  376. package/dist/core/agent/agents-md/map/subsystem.js.map +1 -0
  377. package/dist/core/agent/agents-md/map/usecases.js +138 -0
  378. package/dist/core/agent/agents-md/map/usecases.js.map +1 -0
  379. package/dist/core/agent/agents-md/refusals.js +273 -0
  380. package/dist/core/agent/agents-md/refusals.js.map +1 -0
  381. package/dist/core/agent/agents-md.js +203 -0
  382. package/dist/core/agent/agents-md.js.map +1 -0
  383. package/dist/core/{agents-stamp.js → agent/agents-stamp.js} +60 -0
  384. package/dist/core/agent/agents-stamp.js.map +1 -0
  385. package/dist/core/agent/contract.js +2 -0
  386. package/dist/core/agent/contract.js.map +1 -0
  387. package/dist/core/agent/protocol.js +193 -0
  388. package/dist/core/agent/protocol.js.map +1 -0
  389. package/dist/core/agent/scaffold.js +254 -0
  390. package/dist/core/agent/scaffold.js.map +1 -0
  391. package/dist/core/agent/support/report.js +144 -0
  392. package/dist/core/agent/support/report.js.map +1 -0
  393. package/dist/core/agent/tools/dialects.js +151 -0
  394. package/dist/core/agent/tools/dialects.js.map +1 -0
  395. package/dist/core/agent/tools/registry.js +193 -0
  396. package/dist/core/agent/tools/registry.js.map +1 -0
  397. package/dist/core/agent/workflows/adopt.js +280 -0
  398. package/dist/core/agent/workflows/adopt.js.map +1 -0
  399. package/dist/core/agent/workflows/check.js +373 -0
  400. package/dist/core/agent/workflows/check.js.map +1 -0
  401. package/dist/core/agent/workflows/closing.js +323 -0
  402. package/dist/core/agent/workflows/closing.js.map +1 -0
  403. package/dist/core/agent/workflows/feature.js +220 -0
  404. package/dist/core/agent/workflows/feature.js.map +1 -0
  405. package/dist/core/agent/workflows/implement.js +188 -0
  406. package/dist/core/agent/workflows/implement.js.map +1 -0
  407. package/dist/core/agent/workflows/reference/authoring.js +311 -0
  408. package/dist/core/agent/workflows/reference/authoring.js.map +1 -0
  409. package/dist/core/agent/workflows/reference/codes.js +67 -0
  410. package/dist/core/agent/workflows/reference/codes.js.map +1 -0
  411. package/dist/core/agent/workflows/reference/done-check.js +210 -0
  412. package/dist/core/agent/workflows/reference/done-check.js.map +1 -0
  413. package/dist/core/agent/workflows/reference/drawing/drawing.js +253 -0
  414. package/dist/core/agent/workflows/reference/drawing/drawing.js.map +1 -0
  415. package/dist/core/agent/workflows/reference/reference.js +19 -0
  416. package/dist/core/agent/workflows/reference/reference.js.map +1 -0
  417. package/dist/core/agent/workflows/reference/spine.js +338 -0
  418. package/dist/core/agent/workflows/reference/spine.js.map +1 -0
  419. package/dist/core/asyncapi/baseline/plan.js +43 -0
  420. package/dist/core/asyncapi/baseline/plan.js.map +1 -0
  421. package/dist/core/asyncapi/baseline/surfaces.js +54 -0
  422. package/dist/core/asyncapi/baseline/surfaces.js.map +1 -0
  423. package/dist/core/asyncapi/depth.js +164 -0
  424. package/dist/core/asyncapi/depth.js.map +1 -0
  425. package/dist/core/asyncapi/digest.js +146 -0
  426. package/dist/core/asyncapi/digest.js.map +1 -0
  427. package/dist/core/asyncapi/merge/components.js +92 -0
  428. package/dist/core/asyncapi/merge/components.js.map +1 -0
  429. package/dist/core/asyncapi/merge/error.js +38 -0
  430. package/dist/core/asyncapi/merge/error.js.map +1 -0
  431. package/dist/core/asyncapi/merge/markers.js +290 -0
  432. package/dist/core/asyncapi/merge/markers.js.map +1 -0
  433. package/dist/core/asyncapi/merge/merge.js +195 -0
  434. package/dist/core/asyncapi/merge/merge.js.map +1 -0
  435. package/dist/core/asyncapi/merge/pin.js +83 -0
  436. package/dist/core/asyncapi/merge/pin.js.map +1 -0
  437. package/dist/core/asyncapi/model.js +11 -0
  438. package/dist/core/asyncapi/model.js.map +1 -0
  439. package/dist/core/asyncapi/producers.js +50 -0
  440. package/dist/core/asyncapi/producers.js.map +1 -0
  441. package/dist/core/asyncapi/read.js +263 -0
  442. package/dist/core/asyncapi/read.js.map +1 -0
  443. package/dist/core/brief/brief.js +285 -0
  444. package/dist/core/brief/brief.js.map +1 -0
  445. package/dist/core/brief/checks.js +385 -0
  446. package/dist/core/brief/checks.js.map +1 -0
  447. package/dist/core/brief/landscape.js +273 -0
  448. package/dist/core/brief/landscape.js.map +1 -0
  449. package/dist/core/brief/map/extend.js +84 -0
  450. package/dist/core/brief/map/extend.js.map +1 -0
  451. package/dist/core/brief/map/owed.js +266 -0
  452. package/dist/core/brief/map/owed.js.map +1 -0
  453. package/dist/core/brief/targets.js +304 -0
  454. package/dist/core/brief/targets.js.map +1 -0
  455. package/dist/core/brief/unchecked.js +58 -0
  456. package/dist/core/brief/unchecked.js.map +1 -0
  457. package/dist/core/c4/arch.js +190 -0
  458. package/dist/core/c4/arch.js.map +1 -0
  459. package/dist/core/c4/direction/direction.js +114 -0
  460. package/dist/core/c4/direction/direction.js.map +1 -0
  461. package/dist/core/c4/likec4.js +243 -0
  462. package/dist/core/c4/likec4.js.map +1 -0
  463. package/dist/core/c4/locate/unlocated.js +150 -0
  464. package/dist/core/c4/locate/unlocated.js.map +1 -0
  465. package/dist/core/c4/parsed/deployment.js +160 -0
  466. package/dist/core/c4/parsed/deployment.js.map +1 -0
  467. package/dist/core/c4/parsed/dynamic-views.js +132 -0
  468. package/dist/core/c4/parsed/dynamic-views.js.map +1 -0
  469. package/dist/core/c4/parsed/specification.js +78 -0
  470. package/dist/core/c4/parsed/specification.js.map +1 -0
  471. package/dist/core/c4/parsed/values.js +110 -0
  472. package/dist/core/c4/parsed/values.js.map +1 -0
  473. package/dist/core/c4/parsed/view-ids.js +113 -0
  474. package/dist/core/c4/parsed/view-ids.js.map +1 -0
  475. package/dist/core/c4/prefetch/fleet.js +134 -0
  476. package/dist/core/c4/prefetch/fleet.js.map +1 -0
  477. package/dist/core/c4/project/architecture.js +161 -0
  478. package/dist/core/c4/project/architecture.js.map +1 -0
  479. package/dist/core/c4/project/batch.js +140 -0
  480. package/dist/core/c4/project/batch.js.map +1 -0
  481. package/dist/core/c4/project/documents.js +89 -0
  482. package/dist/core/c4/project/documents.js.map +1 -0
  483. package/dist/core/c4/project/load.js +219 -0
  484. package/dist/core/c4/project/load.js.map +1 -0
  485. package/dist/core/c4/project/staged.js +277 -0
  486. package/dist/core/c4/project/staged.js.map +1 -0
  487. package/dist/core/c4/resolve/attested.js +0 -0
  488. package/dist/core/c4/resolve/attested.js.map +1 -0
  489. package/dist/core/c4/resolve/external.js +51 -0
  490. package/dist/core/c4/resolve/external.js.map +1 -0
  491. package/dist/core/c4/resolve/service.js +174 -0
  492. package/dist/core/c4/resolve/service.js.map +1 -0
  493. package/dist/core/c4/resolve/steps.js +290 -0
  494. package/dist/core/c4/resolve/steps.js.map +1 -0
  495. package/dist/core/c4/resolve/systems.js +154 -0
  496. package/dist/core/c4/resolve/systems.js.map +1 -0
  497. package/dist/core/c4/root-project/exclude.js +352 -0
  498. package/dist/core/c4/root-project/exclude.js.map +1 -0
  499. package/dist/core/c4/seed/fleet-file.js +201 -0
  500. package/dist/core/c4/seed/fleet-file.js.map +1 -0
  501. package/dist/core/c4/seed/items.js +91 -0
  502. package/dist/core/c4/seed/items.js.map +1 -0
  503. package/dist/core/c4/seed/stamp.js +48 -0
  504. package/dist/core/c4/seed/stamp.js.map +1 -0
  505. package/dist/core/c4/seed/template.js +173 -0
  506. package/dist/core/c4/seed/template.js.map +1 -0
  507. package/dist/core/c4/service-model/created/models.js +96 -0
  508. package/dist/core/c4/service-model/created/models.js.map +1 -0
  509. package/dist/core/c4/service-model/documents.js +47 -0
  510. package/dist/core/c4/service-model/documents.js.map +1 -0
  511. package/dist/core/c4/service-model/fleet/extending.js +82 -0
  512. package/dist/core/c4/service-model/fleet/extending.js.map +1 -0
  513. package/dist/core/c4/service-model/load.js +165 -0
  514. package/dist/core/c4/service-model/load.js.map +1 -0
  515. package/dist/core/c4/service-model/renderer.js +128 -0
  516. package/dist/core/c4/service-model/renderer.js.map +1 -0
  517. package/dist/core/c4/service-model/shape.js +106 -0
  518. package/dist/core/c4/service-model/shape.js.map +1 -0
  519. package/dist/core/c4/service-model/slice.js +188 -0
  520. package/dist/core/c4/service-model/slice.js.map +1 -0
  521. package/dist/core/c4/source-mask.js +369 -0
  522. package/dist/core/c4/source-mask.js.map +1 -0
  523. package/dist/core/c4/source-scan.js +308 -0
  524. package/dist/core/c4/source-scan.js.map +1 -0
  525. package/dist/core/c4/splice/authored-source.js +167 -0
  526. package/dist/core/c4/splice/authored-source.js.map +1 -0
  527. package/dist/core/c4/splice/contract.js +30 -0
  528. package/dist/core/c4/splice/contract.js.map +1 -0
  529. package/dist/core/c4/splice/delta-blocks.js +126 -0
  530. package/dist/core/c4/splice/delta-blocks.js.map +1 -0
  531. package/dist/core/c4/splice/identity/declared.js +87 -0
  532. package/dist/core/c4/splice/identity/declared.js.map +1 -0
  533. package/dist/core/c4/splice/identity/edges.js +73 -0
  534. package/dist/core/c4/splice/identity/edges.js.map +1 -0
  535. package/dist/core/c4/splice/identity/existing.js +80 -0
  536. package/dist/core/c4/splice/identity/existing.js.map +1 -0
  537. package/dist/core/c4/splice/identity/interior.js +80 -0
  538. package/dist/core/c4/splice/identity/interior.js.map +1 -0
  539. package/dist/core/c4/splice/identity/owner.js +50 -0
  540. package/dist/core/c4/splice/identity/owner.js.map +1 -0
  541. package/dist/core/c4/splice/landscape-merge.js +337 -0
  542. package/dist/core/c4/splice/landscape-merge.js.map +1 -0
  543. package/dist/core/c4/splice/model/merge.js +151 -0
  544. package/dist/core/c4/splice/model/merge.js.map +1 -0
  545. package/dist/core/c4/splice/placement.js +298 -0
  546. package/dist/core/c4/splice/placement.js.map +1 -0
  547. package/dist/core/c4/splice/text/spot.js +131 -0
  548. package/dist/core/c4/splice/text/spot.js.map +1 -0
  549. package/dist/core/c4/workspace.js +166 -0
  550. package/dist/core/c4/workspace.js.map +1 -0
  551. package/dist/core/capabilities/authoring/notes.js +141 -0
  552. package/dist/core/capabilities/authoring/notes.js.map +1 -0
  553. package/dist/core/capabilities/capabilities.js +124 -0
  554. package/dist/core/capabilities/capabilities.js.map +1 -0
  555. package/dist/core/capabilities/delta/doc.js +47 -0
  556. package/dist/core/capabilities/delta/doc.js.map +1 -0
  557. package/dist/core/capabilities/delta/overlay.js +129 -0
  558. package/dist/core/capabilities/delta/overlay.js.map +1 -0
  559. package/dist/core/capabilities/delta/summary.js +57 -0
  560. package/dist/core/capabilities/delta/summary.js.map +1 -0
  561. package/dist/core/capabilities/delta/tree.js +43 -0
  562. package/dist/core/capabilities/delta/tree.js.map +1 -0
  563. package/dist/core/capabilities/delta/uncovered.js +222 -0
  564. package/dist/core/capabilities/delta/uncovered.js.map +1 -0
  565. package/dist/core/capabilities/findings.js +338 -0
  566. package/dist/core/capabilities/findings.js.map +1 -0
  567. package/dist/core/capabilities/realizes/findings.js +174 -0
  568. package/dist/core/capabilities/realizes/findings.js.map +1 -0
  569. package/dist/core/capabilities/realizes/join.js +123 -0
  570. package/dist/core/capabilities/realizes/join.js.map +1 -0
  571. package/dist/core/capabilities/rollup.js +205 -0
  572. package/dist/core/capabilities/rollup.js.map +1 -0
  573. package/dist/core/capabilities/tree.js +104 -0
  574. package/dist/core/capabilities/tree.js.map +1 -0
  575. package/dist/core/capabilities/usecase-join.js +267 -0
  576. package/dist/core/capabilities/usecase-join.js.map +1 -0
  577. package/dist/core/coherence/authoring/scaffold.js +185 -0
  578. package/dist/core/coherence/authoring/scaffold.js.map +1 -0
  579. package/dist/core/coherence/authoring/sentinels.js +75 -0
  580. package/dist/core/coherence/authoring/sentinels.js.map +1 -0
  581. package/dist/core/coherence/calls/called.js +52 -0
  582. package/dist/core/coherence/calls/called.js.map +1 -0
  583. package/dist/core/coherence/coherence.js +332 -0
  584. package/dist/core/coherence/coherence.js.map +1 -0
  585. package/dist/core/coherence/consumed/operations.js +70 -0
  586. package/dist/core/coherence/consumed/operations.js.map +1 -0
  587. package/dist/core/coherence/consumed/refusal.js +38 -0
  588. package/dist/core/coherence/consumed/refusal.js.map +1 -0
  589. package/dist/core/coherence/covers/health.js +85 -0
  590. package/dist/core/coherence/covers/health.js.map +1 -0
  591. package/dist/core/coherence/declared.js +295 -0
  592. package/dist/core/coherence/declared.js.map +1 -0
  593. package/dist/core/coherence/events/declared.js +191 -0
  594. package/dist/core/coherence/events/declared.js.map +1 -0
  595. package/dist/core/coherence/events/events.js +335 -0
  596. package/dist/core/coherence/events/events.js.map +1 -0
  597. package/dist/core/coherence/events/grades.js +189 -0
  598. package/dist/core/coherence/events/grades.js.map +1 -0
  599. package/dist/core/coherence/events/lookups.js +63 -0
  600. package/dist/core/coherence/events/lookups.js.map +1 -0
  601. package/dist/core/coherence/events/produced.js +100 -0
  602. package/dist/core/coherence/events/produced.js.map +1 -0
  603. package/dist/core/coherence/living.js +198 -0
  604. package/dist/core/coherence/living.js.map +1 -0
  605. package/dist/core/coherence/lookups.js +95 -0
  606. package/dist/core/coherence/lookups.js.map +1 -0
  607. package/dist/core/coherence/pending.js +39 -0
  608. package/dist/core/coherence/pending.js.map +1 -0
  609. package/dist/core/coherence/retired/archived.js +285 -0
  610. package/dist/core/coherence/retired/archived.js.map +1 -0
  611. package/dist/core/coherence/retired/event-pair.js +62 -0
  612. package/dist/core/coherence/retired/event-pair.js.map +1 -0
  613. package/dist/core/coherence/retired/merged.js +79 -0
  614. package/dist/core/coherence/retired/merged.js.map +1 -0
  615. package/dist/core/coherence/retired/retirement.js +49 -0
  616. package/dist/core/coherence/retired/retirement.js.map +1 -0
  617. package/dist/core/coherence/retired/revival/arrivals.js +131 -0
  618. package/dist/core/coherence/retired/revival/arrivals.js.map +1 -0
  619. package/dist/core/coherence/retired/revival/revived.js +297 -0
  620. package/dist/core/coherence/retired/revival/revived.js.map +1 -0
  621. package/dist/core/conflict-markers.js +60 -0
  622. package/dist/core/conflict-markers.js.map +1 -0
  623. package/dist/core/consumers/after.js +113 -0
  624. package/dist/core/consumers/after.js.map +1 -0
  625. package/dist/core/consumers/consumers.js +296 -0
  626. package/dist/core/consumers/consumers.js.map +1 -0
  627. package/dist/core/consumers/current.js +211 -0
  628. package/dist/core/consumers/current.js.map +1 -0
  629. package/dist/core/consumers/scan.js +46 -0
  630. package/dist/core/consumers/scan.js.map +1 -0
  631. package/dist/core/consumers/state.js +27 -0
  632. package/dist/core/consumers/state.js.map +1 -0
  633. package/dist/core/delta/claims.js +73 -0
  634. package/dist/core/delta/claims.js.map +1 -0
  635. package/dist/core/delta/delta.js +341 -0
  636. package/dist/core/delta/delta.js.map +1 -0
  637. package/dist/core/delta/document.js +177 -0
  638. package/dist/core/delta/document.js.map +1 -0
  639. package/dist/core/delta/scope.js +48 -0
  640. package/dist/core/delta/scope.js.map +1 -0
  641. package/dist/core/delta/select.js +237 -0
  642. package/dist/core/delta/select.js.map +1 -0
  643. package/dist/core/dependencies/dependencies.js +141 -0
  644. package/dist/core/dependencies/dependencies.js.map +1 -0
  645. package/dist/core/dependencies/facts.js +165 -0
  646. package/dist/core/dependencies/facts.js.map +1 -0
  647. package/dist/core/dependencies/fanin.js +88 -0
  648. package/dist/core/dependencies/fanin.js.map +1 -0
  649. package/dist/core/dependencies/graph.js +106 -0
  650. package/dist/core/dependencies/graph.js.map +1 -0
  651. package/dist/core/deployment/delta.js +191 -0
  652. package/dist/core/deployment/delta.js.map +1 -0
  653. package/dist/core/deployment/objects.js +145 -0
  654. package/dist/core/deployment/objects.js.map +1 -0
  655. package/dist/core/diff/base-git.js +230 -0
  656. package/dist/core/diff/base-git.js.map +1 -0
  657. package/dist/core/diff/base-state.js +237 -0
  658. package/dist/core/diff/base-state.js.map +1 -0
  659. package/dist/core/diff/joins.js +136 -0
  660. package/dist/core/diff/joins.js.map +1 -0
  661. package/dist/core/diff/scope/changed-paths.js +204 -0
  662. package/dist/core/diff/scope/changed-paths.js.map +1 -0
  663. package/dist/core/diff/scope/edges.js +82 -0
  664. package/dist/core/diff/scope/edges.js.map +1 -0
  665. package/dist/core/diff/semantic.js +312 -0
  666. package/dist/core/diff/semantic.js.map +1 -0
  667. package/dist/core/docs.js +37 -85
  668. package/dist/core/docs.js.map +1 -1
  669. package/dist/core/doctor/agents.js +238 -0
  670. package/dist/core/doctor/agents.js.map +1 -0
  671. package/dist/core/doctor/config.js +139 -0
  672. package/dist/core/doctor/config.js.map +1 -0
  673. package/dist/core/doctor/doctor.js +355 -0
  674. package/dist/core/doctor/doctor.js.map +1 -0
  675. package/dist/core/doctor/report.js +13 -0
  676. package/dist/core/doctor/report.js.map +1 -0
  677. package/dist/core/doctor/reports/scan.js +242 -0
  678. package/dist/core/doctor/reports/scan.js.map +1 -0
  679. package/dist/core/doctor/residue.js +110 -0
  680. package/dist/core/doctor/residue.js.map +1 -0
  681. package/dist/core/document/apply.js +224 -0
  682. package/dist/core/document/apply.js.map +1 -0
  683. package/dist/core/{frontmatter.js → document/frontmatter.js} +103 -2
  684. package/dist/core/document/frontmatter.js.map +1 -0
  685. package/dist/core/document/grammar/directives.js +143 -0
  686. package/dist/core/document/grammar/directives.js.map +1 -0
  687. package/dist/core/document/parse.js +286 -0
  688. package/dist/core/document/parse.js.map +1 -0
  689. package/dist/core/document/scenarios.js +238 -0
  690. package/dist/core/document/scenarios.js.map +1 -0
  691. package/dist/core/document/spec.js +234 -0
  692. package/dist/core/document/spec.js.map +1 -0
  693. package/dist/core/{config.js → envelope/config.js} +89 -18
  694. package/dist/core/envelope/config.js.map +1 -0
  695. package/dist/core/envelope/json.js +209 -0
  696. package/dist/core/envelope/json.js.map +1 -0
  697. package/dist/core/{version.js → envelope/version.js} +3 -3
  698. package/dist/core/envelope/version.js.map +1 -0
  699. package/dist/core/explain/families.js +180 -0
  700. package/dist/core/explain/families.js.map +1 -0
  701. package/dist/core/explain/fix-tables.js +178 -0
  702. package/dist/core/explain/fix-tables.js.map +1 -0
  703. package/dist/core/explain/lookup.js +194 -0
  704. package/dist/core/explain/lookup.js.map +1 -0
  705. package/dist/core/explain/refusals.js +49 -0
  706. package/dist/core/explain/refusals.js.map +1 -0
  707. package/dist/core/explain/terms/documents.js +227 -0
  708. package/dist/core/explain/terms/documents.js.map +1 -0
  709. package/dist/core/explain/terms/done-check.js +144 -0
  710. package/dist/core/explain/terms/done-check.js.map +1 -0
  711. package/dist/core/explain/terms/entry.js +14 -0
  712. package/dist/core/explain/terms/entry.js.map +1 -0
  713. package/dist/core/explain/terms/stages.js +71 -0
  714. package/dist/core/explain/terms/stages.js.map +1 -0
  715. package/dist/core/explain/terms/tasks.js +97 -0
  716. package/dist/core/explain/terms/tasks.js.map +1 -0
  717. package/dist/core/explain/terms.js +103 -0
  718. package/dist/core/explain/terms.js.map +1 -0
  719. package/dist/core/explore/describe.js +105 -0
  720. package/dist/core/explore/describe.js.map +1 -0
  721. package/dist/core/explore/explore.js +204 -0
  722. package/dist/core/explore/explore.js.map +1 -0
  723. package/dist/core/fleet-context.js +174 -146
  724. package/dist/core/fleet-context.js.map +1 -1
  725. package/dist/core/gate/checks.js +208 -0
  726. package/dist/core/gate/checks.js.map +1 -0
  727. package/dist/core/gate/partners.js +246 -0
  728. package/dist/core/gate/partners.js.map +1 -0
  729. package/dist/core/gate/report.js +47 -0
  730. package/dist/core/gate/report.js.map +1 -0
  731. package/dist/core/gate/verification.js +176 -0
  732. package/dist/core/gate/verification.js.map +1 -0
  733. package/dist/core/gherkin/digest.js +60 -0
  734. package/dist/core/gherkin/digest.js.map +1 -0
  735. package/dist/core/gherkin/emit.js +177 -0
  736. package/dist/core/gherkin/emit.js.map +1 -0
  737. package/dist/core/gherkin/read.js +76 -0
  738. package/dist/core/gherkin/read.js.map +1 -0
  739. package/dist/core/gherkin/stale.js +210 -0
  740. package/dist/core/gherkin/stale.js.map +1 -0
  741. package/dist/core/gherkin/stamp.js +77 -0
  742. package/dist/core/gherkin/stamp.js.map +1 -0
  743. package/dist/core/gherkin/steps/catalogue.js +154 -0
  744. package/dist/core/gherkin/steps/catalogue.js.map +1 -0
  745. package/dist/core/gherkin/steps/inventory.js +98 -0
  746. package/dist/core/gherkin/steps/inventory.js.map +1 -0
  747. package/dist/core/gherkin/steps/phrase.js +72 -0
  748. package/dist/core/gherkin/steps/phrase.js.map +1 -0
  749. package/dist/core/glossary/delta.js +109 -0
  750. package/dist/core/glossary/delta.js.map +1 -0
  751. package/dist/core/glossary/tree.js +73 -0
  752. package/dist/core/glossary/tree.js.map +1 -0
  753. package/dist/core/{concurrency.js → kernel/concurrency.js} +19 -0
  754. package/dist/core/kernel/concurrency.js.map +1 -0
  755. package/dist/core/{document-bytes.js → kernel/document-bytes.js} +1 -1
  756. package/dist/core/kernel/document-bytes.js.map +1 -0
  757. package/dist/core/kernel/fences.js +42 -0
  758. package/dist/core/kernel/fences.js.map +1 -0
  759. package/dist/core/kernel/ids/capability.js +72 -0
  760. package/dist/core/kernel/ids/capability.js.map +1 -0
  761. package/dist/core/kernel/ids/dirs.js +33 -0
  762. package/dist/core/kernel/ids/dirs.js.map +1 -0
  763. package/dist/core/kernel/ids/feature.js +75 -0
  764. package/dist/core/kernel/ids/feature.js.map +1 -0
  765. package/dist/core/kernel/ids/fqn/ancestors.js +65 -0
  766. package/dist/core/kernel/ids/fqn/ancestors.js.map +1 -0
  767. package/dist/core/kernel/ids/service.js +156 -0
  768. package/dist/core/kernel/ids/service.js.map +1 -0
  769. package/dist/core/kernel/ids/subsystem.js +63 -0
  770. package/dist/core/kernel/ids/subsystem.js.map +1 -0
  771. package/dist/core/{path-safety.js → kernel/path-safety.js} +56 -4
  772. package/dist/core/kernel/path-safety.js.map +1 -0
  773. package/dist/core/{records.js → kernel/records.js} +11 -0
  774. package/dist/core/kernel/records.js.map +1 -0
  775. package/dist/core/links/backlinks.js +66 -0
  776. package/dist/core/links/backlinks.js.map +1 -0
  777. package/dist/core/links/case.js +74 -0
  778. package/dist/core/links/case.js.map +1 -0
  779. package/dist/core/links/corpus.js +118 -0
  780. package/dist/core/links/corpus.js.map +1 -0
  781. package/dist/core/links/findings.js +110 -0
  782. package/dist/core/links/findings.js.map +1 -0
  783. package/dist/core/links/parse.js +265 -0
  784. package/dist/core/links/parse.js.map +1 -0
  785. package/dist/core/mcp/argv.js +212 -0
  786. package/dist/core/mcp/argv.js.map +1 -0
  787. package/dist/core/mcp/author-tools.js +73 -0
  788. package/dist/core/mcp/author-tools.js.map +1 -0
  789. package/dist/core/mcp/framing.js +46 -0
  790. package/dist/core/mcp/framing.js.map +1 -0
  791. package/dist/core/mcp/protocol.js +280 -0
  792. package/dist/core/mcp/protocol.js.map +1 -0
  793. package/dist/core/mcp/tools.js +324 -0
  794. package/dist/core/mcp/tools.js.map +1 -0
  795. package/dist/core/obligations/obligations.js +106 -0
  796. package/dist/core/obligations/obligations.js.map +1 -0
  797. package/dist/core/openapi/baseline/gate.js +207 -0
  798. package/dist/core/openapi/baseline/gate.js.map +1 -0
  799. package/dist/core/openapi/baseline/plan.js +142 -0
  800. package/dist/core/openapi/baseline/plan.js.map +1 -0
  801. package/dist/core/openapi/baseline/record.js +174 -0
  802. package/dist/core/openapi/baseline/record.js.map +1 -0
  803. package/dist/core/openapi/contract-text.js +33 -0
  804. package/dist/core/openapi/contract-text.js.map +1 -0
  805. package/dist/core/openapi/contract-tree.js +301 -0
  806. package/dist/core/openapi/contract-tree.js.map +1 -0
  807. package/dist/core/openapi/depth.js +136 -0
  808. package/dist/core/openapi/depth.js.map +1 -0
  809. package/dist/core/openapi/digest.js +239 -0
  810. package/dist/core/openapi/digest.js.map +1 -0
  811. package/dist/core/{openapi.js → openapi/doc.js} +54 -108
  812. package/dist/core/openapi/doc.js.map +1 -0
  813. package/dist/core/openapi/merge/components.js +199 -0
  814. package/dist/core/openapi/merge/components.js.map +1 -0
  815. package/dist/core/openapi/merge/error.js +16 -0
  816. package/dist/core/openapi/merge/error.js.map +1 -0
  817. package/dist/core/openapi/merge/markers.js +204 -0
  818. package/dist/core/openapi/merge/markers.js.map +1 -0
  819. package/dist/core/openapi/merge/merge.js +232 -0
  820. package/dist/core/openapi/merge/merge.js.map +1 -0
  821. package/dist/core/openapi/merge/pin.js +110 -0
  822. package/dist/core/openapi/merge/pin.js.map +1 -0
  823. package/dist/core/openspec/decide/capabilities.js +244 -0
  824. package/dist/core/openspec/decide/capabilities.js.map +1 -0
  825. package/dist/core/openspec/decide/dispositions.js +63 -0
  826. package/dist/core/openspec/decide/dispositions.js.map +1 -0
  827. package/dist/core/openspec/decide/renames.js +179 -0
  828. package/dist/core/openspec/decide/renames.js.map +1 -0
  829. package/dist/core/openspec/decide/verdict.js +84 -0
  830. package/dist/core/openspec/decide/verdict.js.map +1 -0
  831. package/dist/core/openspec/inventory.js +220 -0
  832. package/dist/core/openspec/inventory.js.map +1 -0
  833. package/dist/core/openspec/model/mapping.js +78 -0
  834. package/dist/core/openspec/model/mapping.js.map +1 -0
  835. package/dist/core/openspec/model/model.js +70 -0
  836. package/dist/core/openspec/model/model.js.map +1 -0
  837. package/dist/core/openspec/scan/changes.js +241 -0
  838. package/dist/core/openspec/scan/changes.js.map +1 -0
  839. package/dist/core/openspec/scan/config.js +191 -0
  840. package/dist/core/openspec/scan/config.js.map +1 -0
  841. package/dist/core/openspec/scan/shape.js +304 -0
  842. package/dist/core/openspec/scan/shape.js.map +1 -0
  843. package/dist/core/openspec/scan/walk.js +116 -0
  844. package/dist/core/openspec/scan/walk.js.map +1 -0
  845. package/dist/core/openspec/scan/workspace.js +71 -0
  846. package/dist/core/openspec/scan/workspace.js.map +1 -0
  847. package/dist/core/owners/codeowners.js +141 -0
  848. package/dist/core/owners/codeowners.js.map +1 -0
  849. package/dist/core/pack/features.js +120 -0
  850. package/dist/core/pack/features.js.map +1 -0
  851. package/dist/core/pack/joins.js +112 -0
  852. package/dist/core/pack/joins.js.map +1 -0
  853. package/dist/core/pack/living.js +157 -0
  854. package/dist/core/pack/living.js.map +1 -0
  855. package/dist/core/pack/pack.js +120 -0
  856. package/dist/core/pack/pack.js.map +1 -0
  857. package/dist/core/permissions/permissions.js +87 -0
  858. package/dist/core/permissions/permissions.js.map +1 -0
  859. package/dist/core/projection/api.js +84 -0
  860. package/dist/core/projection/api.js.map +1 -0
  861. package/dist/core/projection/arch-slice.js +63 -0
  862. package/dist/core/projection/arch-slice.js.map +1 -0
  863. package/dist/core/projection/events.js +34 -0
  864. package/dist/core/projection/events.js.map +1 -0
  865. package/dist/core/projection/introduced.js +14 -0
  866. package/dist/core/projection/introduced.js.map +1 -0
  867. package/dist/core/provenance/findings.js +244 -0
  868. package/dist/core/provenance/findings.js.map +1 -0
  869. package/dist/core/provenance/git.js +201 -0
  870. package/dist/core/provenance/git.js.map +1 -0
  871. package/dist/core/provenance/gitq/moves.js +139 -0
  872. package/dist/core/provenance/gitq/moves.js.map +1 -0
  873. package/dist/core/provenance/gitq/vouched-ancestor.js +179 -0
  874. package/dist/core/provenance/gitq/vouched-ancestor.js.map +1 -0
  875. package/dist/core/provenance/sample/scope.js +238 -0
  876. package/dist/core/provenance/sample/scope.js.map +1 -0
  877. package/dist/core/provenance/sample/sections.js +61 -0
  878. package/dist/core/provenance/sample/sections.js.map +1 -0
  879. package/dist/core/provenance/sources.js +280 -0
  880. package/dist/core/provenance/sources.js.map +1 -0
  881. package/dist/core/provenance/stamp.js +220 -0
  882. package/dist/core/provenance/stamp.js.map +1 -0
  883. package/dist/core/provenance/walk.js +157 -0
  884. package/dist/core/provenance/walk.js.map +1 -0
  885. package/dist/core/repo/authored/paths.js +210 -0
  886. package/dist/core/repo/authored/paths.js.map +1 -0
  887. package/dist/core/repo/entries.js +126 -0
  888. package/dist/core/repo/entries.js.map +1 -0
  889. package/dist/core/repo/paths.js +322 -0
  890. package/dist/core/repo/paths.js.map +1 -0
  891. package/dist/core/repo/repo.js +308 -0
  892. package/dist/core/repo/repo.js.map +1 -0
  893. package/dist/core/repo/service-target.js +153 -0
  894. package/dist/core/repo/service-target.js.map +1 -0
  895. package/dist/core/repo/state.js +58 -0
  896. package/dist/core/repo/state.js.map +1 -0
  897. package/dist/core/repo/tree/find.js +61 -0
  898. package/dist/core/repo/tree/find.js.map +1 -0
  899. package/dist/core/repo/tree/fs.js +90 -0
  900. package/dist/core/repo/tree/fs.js.map +1 -0
  901. package/dist/core/repo/tree/marker.js +61 -0
  902. package/dist/core/repo/tree/marker.js.map +1 -0
  903. package/dist/core/repo/tree/render/body.js +258 -0
  904. package/dist/core/repo/tree/render/body.js.map +1 -0
  905. package/dist/core/repo/tree/render/projects.js +182 -0
  906. package/dist/core/repo/tree/render/projects.js.map +1 -0
  907. package/dist/core/repo/tree/render/service/header.js +125 -0
  908. package/dist/core/repo/tree/render/service/header.js.map +1 -0
  909. package/dist/core/repo/tree/render/service/peers.js +28 -0
  910. package/dist/core/repo/tree/render/service/peers.js.map +1 -0
  911. package/dist/core/repo/tree/render/service/view-id.js +67 -0
  912. package/dist/core/repo/tree/render/service/view-id.js.map +1 -0
  913. package/dist/core/repo/tree/render/service/views.js +78 -0
  914. package/dist/core/repo/tree/render/service/views.js.map +1 -0
  915. package/dist/core/repo/tree/render/stale.js +42 -0
  916. package/dist/core/repo/tree/render/stale.js.map +1 -0
  917. package/dist/core/repo/tree/render/text.js +84 -0
  918. package/dist/core/repo/tree/render/text.js.map +1 -0
  919. package/dist/core/repo/tree/render/views.js +293 -0
  920. package/dist/core/repo/tree/render/views.js.map +1 -0
  921. package/dist/core/repo/tree/walk.js +255 -0
  922. package/dist/core/repo/tree/walk.js.map +1 -0
  923. package/dist/core/results.js +146 -14
  924. package/dist/core/results.js.map +1 -1
  925. package/dist/core/scaffold/landscape.js +239 -0
  926. package/dist/core/scaffold/landscape.js.map +1 -0
  927. package/dist/core/scaffold/legacy.js +271 -0
  928. package/dist/core/scaffold/legacy.js.map +1 -0
  929. package/dist/core/scaffold/readme.js +84 -0
  930. package/dist/core/scaffold/readme.js.map +1 -0
  931. package/dist/core/staging/commit.js +252 -0
  932. package/dist/core/staging/commit.js.map +1 -0
  933. package/dist/core/staging/interrupted.js +96 -0
  934. package/dist/core/staging/interrupted.js.map +1 -0
  935. package/dist/core/staging/lock.js +268 -0
  936. package/dist/core/staging/lock.js.map +1 -0
  937. package/dist/core/staging/recovery/finding.js +35 -0
  938. package/dist/core/staging/recovery/finding.js.map +1 -0
  939. package/dist/core/staging/recovery/intent.js +95 -0
  940. package/dist/core/staging/recovery/intent.js.map +1 -0
  941. package/dist/core/staging/recovery/recover.js +204 -0
  942. package/dist/core/staging/recovery/recover.js.map +1 -0
  943. package/dist/core/staging/recovery/residue.js +62 -0
  944. package/dist/core/staging/recovery/residue.js.map +1 -0
  945. package/dist/core/staging/snapshot/manifest.js +188 -0
  946. package/dist/core/staging/snapshot/manifest.js.map +1 -0
  947. package/dist/core/staging/snapshot/snapshot.js +196 -0
  948. package/dist/core/staging/snapshot/snapshot.js.map +1 -0
  949. package/dist/core/staging/txn/forward.js +181 -0
  950. package/dist/core/staging/txn/forward.js.map +1 -0
  951. package/dist/core/staging/txn/journal.js +139 -0
  952. package/dist/core/staging/txn/journal.js.map +1 -0
  953. package/dist/core/staging/txn/transaction.js +75 -0
  954. package/dist/core/staging/txn/transaction.js.map +1 -0
  955. package/dist/core/staging/writes.js +113 -0
  956. package/dist/core/staging/writes.js.map +1 -0
  957. package/dist/core/status/actions/execution.js +60 -0
  958. package/dist/core/status/actions/execution.js.map +1 -0
  959. package/dist/core/status/contracts.js +126 -0
  960. package/dist/core/status/contracts.js.map +1 -0
  961. package/dist/core/status/feature/artifacts.js +196 -0
  962. package/dist/core/status/feature/artifacts.js.map +1 -0
  963. package/dist/core/status/feature/feature.js +214 -0
  964. package/dist/core/status/feature/feature.js.map +1 -0
  965. package/dist/core/status/feature/next.js +163 -0
  966. package/dist/core/status/feature/next.js.map +1 -0
  967. package/dist/core/status/feature/state.js +21 -0
  968. package/dist/core/status/feature/state.js.map +1 -0
  969. package/dist/core/status/feature/words.js +96 -0
  970. package/dist/core/status/feature/words.js.map +1 -0
  971. package/dist/core/status/fleet/fleet.js +216 -0
  972. package/dist/core/status/fleet/fleet.js.map +1 -0
  973. package/dist/core/status/fleet/next.js +302 -0
  974. package/dist/core/status/fleet/next.js.map +1 -0
  975. package/dist/core/status/interrupted.js +97 -0
  976. package/dist/core/status/interrupted.js.map +1 -0
  977. package/dist/core/status/report.js +31 -0
  978. package/dist/core/status/report.js.map +1 -0
  979. package/dist/core/status/scan.js +41 -0
  980. package/dist/core/status/scan.js.map +1 -0
  981. package/dist/core/status/verification.js +216 -0
  982. package/dist/core/status/verification.js.map +1 -0
  983. package/dist/core/tasks/packet.js +199 -0
  984. package/dist/core/tasks/packet.js.map +1 -0
  985. package/dist/core/tasks/record.js +43 -0
  986. package/dist/core/tasks/record.js.map +1 -0
  987. package/dist/core/tasks/sources.js +181 -0
  988. package/dist/core/tasks/sources.js.map +1 -0
  989. package/dist/core/tasks/stamps.js +76 -0
  990. package/dist/core/tasks/stamps.js.map +1 -0
  991. package/dist/core/tasks/unit.js +0 -0
  992. package/dist/core/tasks/unit.js.map +1 -0
  993. package/dist/core/usecases/capability.js +166 -0
  994. package/dist/core/usecases/capability.js.map +1 -0
  995. package/dist/core/usecases/delta/claims.js +140 -0
  996. package/dist/core/usecases/delta/claims.js.map +1 -0
  997. package/dist/core/usecases/delta/flows.js +101 -0
  998. package/dist/core/usecases/delta/flows.js.map +1 -0
  999. package/dist/core/usecases/delta/modified.js +315 -0
  1000. package/dist/core/usecases/delta/modified.js.map +1 -0
  1001. package/dist/core/usecases/delta/overlay.js +76 -0
  1002. package/dist/core/usecases/delta/overlay.js.map +1 -0
  1003. package/dist/core/usecases/fleet.js +296 -0
  1004. package/dist/core/usecases/fleet.js.map +1 -0
  1005. package/dist/core/usecases/grade/capability-tag.js +93 -0
  1006. package/dist/core/usecases/grade/capability-tag.js.map +1 -0
  1007. package/dist/core/usecases/grade/feature.js +88 -0
  1008. package/dist/core/usecases/grade/feature.js.map +1 -0
  1009. package/dist/core/usecases/grade/requirement-tag.js +94 -0
  1010. package/dist/core/usecases/grade/requirement-tag.js.map +1 -0
  1011. package/dist/core/usecases/grade/steps.js +266 -0
  1012. package/dist/core/usecases/grade/steps.js.map +1 -0
  1013. package/dist/core/usecases/grade/usecases.js +112 -0
  1014. package/dist/core/usecases/grade/usecases.js.map +1 -0
  1015. package/dist/core/usecases/operations.js +123 -0
  1016. package/dist/core/usecases/operations.js.map +1 -0
  1017. package/dist/core/usecases/place.js +44 -0
  1018. package/dist/core/usecases/place.js.map +1 -0
  1019. package/dist/core/usecases/service/exclude.js +119 -0
  1020. package/dist/core/usecases/service/exclude.js.map +1 -0
  1021. package/dist/core/usecases/service/flows.js +164 -0
  1022. package/dist/core/usecases/service/flows.js.map +1 -0
  1023. package/dist/core/usecases/suites/participants.js +83 -0
  1024. package/dist/core/usecases/suites/participants.js.map +1 -0
  1025. package/dist/core/usecases/suites/suites.js +45 -0
  1026. package/dist/core/usecases/suites/suites.js.map +1 -0
  1027. package/dist/core/usecases/touch.js +101 -0
  1028. package/dist/core/usecases/touch.js.map +1 -0
  1029. package/dist/core/verify/answers.js +180 -0
  1030. package/dist/core/verify/answers.js.map +1 -0
  1031. package/dist/core/verify/build.js +170 -0
  1032. package/dist/core/verify/build.js.map +1 -0
  1033. package/dist/core/verify/checklist.js +259 -0
  1034. package/dist/core/verify/checklist.js.map +1 -0
  1035. package/dist/core/verify/claims/identity.js +61 -0
  1036. package/dist/core/verify/claims/identity.js.map +1 -0
  1037. package/dist/core/verify/cross/diff.js +97 -0
  1038. package/dist/core/verify/cross/diff.js.map +1 -0
  1039. package/dist/core/verify/evidence/contract.js +169 -0
  1040. package/dist/core/verify/evidence/contract.js.map +1 -0
  1041. package/dist/core/verify/location.js +67 -0
  1042. package/dist/core/verify/location.js.map +1 -0
  1043. package/dist/core/verify/pins/lint.js +158 -0
  1044. package/dist/core/verify/pins/lint.js.map +1 -0
  1045. package/dist/core/verify/pins/pin.js +95 -0
  1046. package/dist/core/verify/pins/pin.js.map +1 -0
  1047. package/dist/core/verify/read/file.js +224 -0
  1048. package/dist/core/verify/read/file.js.map +1 -0
  1049. package/dist/core/verify/read/shape.js +169 -0
  1050. package/dist/core/verify/read/shape.js.map +1 -0
  1051. package/dist/core/verify/read/union.js +105 -0
  1052. package/dist/core/verify/read/union.js.map +1 -0
  1053. package/dist/core/verify/record.js +165 -0
  1054. package/dist/core/verify/record.js.map +1 -0
  1055. package/dist/core/verify/store/commit.js +99 -0
  1056. package/dist/core/verify/store/commit.js.map +1 -0
  1057. package/dist/core/verify/store/render.js +61 -0
  1058. package/dist/core/verify/store/render.js.map +1 -0
  1059. package/dist/core/vocabulary/health.js +91 -0
  1060. package/dist/core/vocabulary/health.js.map +1 -0
  1061. package/dist/core/vocabulary/issue.js +59 -0
  1062. package/dist/core/vocabulary/issue.js.map +1 -0
  1063. package/dist/core/vocabulary/maturity.js +216 -0
  1064. package/dist/core/vocabulary/maturity.js.map +1 -0
  1065. package/dist/core/vocabulary/report.js +90 -0
  1066. package/dist/core/vocabulary/report.js.map +1 -0
  1067. package/dist/core/vocabulary/steps.js +266 -0
  1068. package/dist/core/vocabulary/steps.js.map +1 -0
  1069. package/dist/core/workspace/discover.js +239 -0
  1070. package/dist/core/workspace/discover.js.map +1 -0
  1071. package/dist/core/workspace/render.js +52 -0
  1072. package/dist/core/workspace/render.js.map +1 -0
  1073. package/examples/README.md +232 -0
  1074. package/examples/docs/architecture/adrs/0001-transactional-outbox.md +33 -0
  1075. package/examples/docs/architecture/capabilities.yaml +31 -0
  1076. package/examples/docs/architecture/landscape.likec4 +336 -0
  1077. package/examples/docs/architecture/obligations.yaml +23 -0
  1078. package/examples/docs/architecture/permissions.yaml +50 -0
  1079. package/examples/docs/architecture/services.likec4 +70 -0
  1080. package/examples/docs/architecture/subsystems.likec4 +18 -0
  1081. package/examples/docs/architecture/usecases/order-notification.likec4 +74 -0
  1082. package/examples/docs/capabilities/checkout/spec.md +55 -0
  1083. package/examples/docs/capabilities/identity/tokens/spec.md +42 -0
  1084. package/examples/docs/capabilities/order-notifications/spec.md +43 -0
  1085. package/examples/docs/features/FEAT-101-payment-splitting/adrs/0001-dedicated-split-service.md +18 -0
  1086. package/examples/docs/features/FEAT-101-payment-splitting/delta.likec4 +94 -0
  1087. package/examples/docs/features/FEAT-101-payment-splitting/intent.md +44 -0
  1088. package/examples/docs/features/FEAT-101-payment-splitting/specs/checkout-web/spec.md +21 -0
  1089. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-service/asyncapi.yaml +132 -0
  1090. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-service/spec.md +36 -0
  1091. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/arch.spec.md +40 -0
  1092. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/openapi.yaml +116 -0
  1093. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/spec.md +55 -0
  1094. package/examples/docs/features/FEAT-112-retire-order-v1/intent.md +35 -0
  1095. package/examples/docs/features/FEAT-112-retire-order-v1/specs/order-service/openapi.yaml +31 -0
  1096. package/examples/docs/features/FEAT-112-retire-order-v1/specs/order-service/spec.md +17 -0
  1097. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/architecture/landscape.likec4 +253 -0
  1098. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/services/order-service/spec.md +121 -0
  1099. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/services/payment-service/openapi.yaml +111 -0
  1100. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/services/payment-service/spec.md +58 -0
  1101. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/manifest.json +32 -0
  1102. package/examples/docs/features/archive/FEAT-088-refunds/adrs/0001-refunds-stay-in-payment-service.md +26 -0
  1103. package/examples/docs/features/archive/FEAT-088-refunds/delta.likec4 +28 -0
  1104. package/examples/docs/features/archive/FEAT-088-refunds/intent.md +26 -0
  1105. package/examples/docs/features/archive/FEAT-088-refunds/specs/order-service/spec.md +37 -0
  1106. package/examples/docs/features/archive/FEAT-088-refunds/specs/payment-service/openapi.yaml +73 -0
  1107. package/examples/docs/features/archive/FEAT-088-refunds/specs/payment-service/spec.md +23 -0
  1108. package/examples/docs/features/archive/FEAT-088-refunds/verification.yaml +76 -0
  1109. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/architecture/landscape.likec4 +275 -0
  1110. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/payment-service/asyncapi.yaml +96 -0
  1111. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/payment-service/spec.md +82 -0
  1112. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/platform/notification-service/asyncapi.yaml +164 -0
  1113. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/platform/notification-service/spec.md +91 -0
  1114. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/manifest.json +46 -0
  1115. package/examples/docs/features/archive/FEAT-120-refund-notification/delta.likec4 +36 -0
  1116. package/examples/docs/features/archive/FEAT-120-refund-notification/intent.md +22 -0
  1117. package/examples/docs/features/archive/FEAT-120-refund-notification/scenario-report.json +10 -0
  1118. package/examples/docs/features/archive/FEAT-120-refund-notification/specs/notification-service/asyncapi.yaml +208 -0
  1119. package/examples/docs/features/archive/FEAT-120-refund-notification/specs/notification-service/spec.md +24 -0
  1120. package/examples/docs/features/archive/FEAT-120-refund-notification/specs/payment-service/asyncapi.yaml +137 -0
  1121. package/examples/docs/features/archive/FEAT-120-refund-notification/specs/payment-service/spec.md +31 -0
  1122. package/examples/docs/features/archive/FEAT-120-refund-notification/verification.yaml +84 -0
  1123. package/examples/docs/glossary/order.md +15 -0
  1124. package/examples/docs/glossary/payments/authorization.md +14 -0
  1125. package/examples/docs/likec4.config.json +8 -0
  1126. package/examples/docs/loam.json +3 -0
  1127. package/examples/docs/services/checkout-web/model.likec4 +92 -0
  1128. package/examples/docs/services/checkout-web/spec.md +91 -0
  1129. package/examples/docs/services/checkout-web/ui/pages/checkout.page.yaml +40 -0
  1130. package/examples/docs/services/checkout-web/ui/pages/order-status.page.yaml +24 -0
  1131. package/examples/docs/services/checkout-web/ui/pages/split-payment.page.yaml +26 -0
  1132. package/examples/docs/services/order-service/adrs/0001-orchestrated-order-lifecycle.md +52 -0
  1133. package/examples/docs/services/order-service/arch.spec.md +134 -0
  1134. package/examples/docs/services/order-service/asyncapi.yaml +109 -0
  1135. package/examples/docs/services/order-service/health.yaml +57 -0
  1136. package/examples/docs/services/order-service/model.likec4 +126 -0
  1137. package/examples/docs/services/order-service/openapi.yaml +257 -0
  1138. package/examples/docs/services/order-service/runbook.md +62 -0
  1139. package/examples/docs/services/order-service/spec.md +134 -0
  1140. package/examples/docs/services/payment-service/adrs/0001-payments-outbox.md +18 -0
  1141. package/examples/docs/services/payment-service/adrs/0002-idempotency-keys-on-authorization.md +27 -0
  1142. package/examples/docs/services/payment-service/arch.spec.md +76 -0
  1143. package/examples/docs/services/payment-service/asyncapi.yaml +130 -0
  1144. package/examples/docs/services/payment-service/health.yaml +39 -0
  1145. package/examples/docs/services/payment-service/model.likec4 +68 -0
  1146. package/examples/docs/services/payment-service/openapi.yaml +151 -0
  1147. package/examples/docs/services/payment-service/runbook.md +37 -0
  1148. package/examples/docs/services/payment-service/spec.md +88 -0
  1149. package/examples/docs/services/platform/identity-service/adrs/0001-token-introspection-over-local-validation.md +60 -0
  1150. package/examples/docs/services/platform/identity-service/arch.spec.md +120 -0
  1151. package/examples/docs/services/platform/identity-service/health.yaml +70 -0
  1152. package/examples/docs/services/platform/identity-service/model.likec4 +81 -0
  1153. package/examples/docs/services/platform/identity-service/openapi.yaml +197 -0
  1154. package/examples/docs/services/platform/identity-service/runbook.md +95 -0
  1155. package/examples/docs/services/platform/identity-service/spec.md +119 -0
  1156. package/examples/docs/services/platform/notification-service/asyncapi.yaml +200 -0
  1157. package/examples/docs/services/platform/notification-service/health.yaml +40 -0
  1158. package/examples/docs/services/platform/notification-service/model.likec4 +97 -0
  1159. package/examples/docs/services/platform/notification-service/runbook.md +48 -0
  1160. package/examples/docs/services/platform/notification-service/spec.md +112 -0
  1161. package/examples/docs/services/platform/subsystem.yaml +2 -0
  1162. package/examples/fleet.yaml +57 -0
  1163. package/package.json +19 -6
  1164. package/dist/commands/adopt.js +0 -240
  1165. package/dist/commands/adopt.js.map +0 -1
  1166. package/dist/commands/archive.js +0 -1313
  1167. package/dist/commands/archive.js.map +0 -1
  1168. package/dist/commands/delta.js +0 -388
  1169. package/dist/commands/delta.js.map +0 -1
  1170. package/dist/commands/docs-repo-gate.js.map +0 -1
  1171. package/dist/commands/format.js +0 -17
  1172. package/dist/commands/format.js.map +0 -1
  1173. package/dist/commands/gherkin.js +0 -309
  1174. package/dist/commands/gherkin.js.map +0 -1
  1175. package/dist/commands/init.js.map +0 -1
  1176. package/dist/commands/list.js +0 -295
  1177. package/dist/commands/list.js.map +0 -1
  1178. package/dist/commands/migrate-openspec.js +0 -950
  1179. package/dist/commands/migrate-openspec.js.map +0 -1
  1180. package/dist/commands/new.js +0 -413
  1181. package/dist/commands/new.js.map +0 -1
  1182. package/dist/commands/rebase.js +0 -356
  1183. package/dist/commands/rebase.js.map +0 -1
  1184. package/dist/commands/show.js +0 -320
  1185. package/dist/commands/show.js.map +0 -1
  1186. package/dist/commands/status.js +0 -262
  1187. package/dist/commands/status.js.map +0 -1
  1188. package/dist/commands/unarchive.js +0 -317
  1189. package/dist/commands/unarchive.js.map +0 -1
  1190. package/dist/commands/validate.js +0 -1773
  1191. package/dist/commands/validate.js.map +0 -1
  1192. package/dist/commands/verify.js +0 -775
  1193. package/dist/commands/verify.js.map +0 -1
  1194. package/dist/commands/vouch.js +0 -421
  1195. package/dist/commands/vouch.js.map +0 -1
  1196. package/dist/core/agent.js +0 -2173
  1197. package/dist/core/agent.js.map +0 -1
  1198. package/dist/core/agents-stamp.js.map +0 -1
  1199. package/dist/core/arch.js +0 -130
  1200. package/dist/core/arch.js.map +0 -1
  1201. package/dist/core/asyncapi.js +0 -253
  1202. package/dist/core/asyncapi.js.map +0 -1
  1203. package/dist/core/brief.js +0 -755
  1204. package/dist/core/brief.js.map +0 -1
  1205. package/dist/core/coherence.js +0 -577
  1206. package/dist/core/coherence.js.map +0 -1
  1207. package/dist/core/concurrency.js.map +0 -1
  1208. package/dist/core/config.js.map +0 -1
  1209. package/dist/core/delta.js +0 -476
  1210. package/dist/core/delta.js.map +0 -1
  1211. package/dist/core/dependencies.js +0 -356
  1212. package/dist/core/dependencies.js.map +0 -1
  1213. package/dist/core/doctor.js +0 -596
  1214. package/dist/core/doctor.js.map +0 -1
  1215. package/dist/core/document-bytes.js.map +0 -1
  1216. package/dist/core/explore.js +0 -225
  1217. package/dist/core/explore.js.map +0 -1
  1218. package/dist/core/frontmatter.js.map +0 -1
  1219. package/dist/core/gherkin.js +0 -463
  1220. package/dist/core/gherkin.js.map +0 -1
  1221. package/dist/core/health.js +0 -67
  1222. package/dist/core/health.js.map +0 -1
  1223. package/dist/core/ids.js +0 -122
  1224. package/dist/core/ids.js.map +0 -1
  1225. package/dist/core/issue.js +0 -9
  1226. package/dist/core/issue.js.map +0 -1
  1227. package/dist/core/json.js +0 -74
  1228. package/dist/core/json.js.map +0 -1
  1229. package/dist/core/likec4.js +0 -489
  1230. package/dist/core/likec4.js.map +0 -1
  1231. package/dist/core/maturity.js +0 -66
  1232. package/dist/core/maturity.js.map +0 -1
  1233. package/dist/core/openapi-merge.js +0 -552
  1234. package/dist/core/openapi-merge.js.map +0 -1
  1235. package/dist/core/openapi.js.map +0 -1
  1236. package/dist/core/openspec-inventory.js +0 -1440
  1237. package/dist/core/openspec-inventory.js.map +0 -1
  1238. package/dist/core/path-safety.js.map +0 -1
  1239. package/dist/core/provenance.js +0 -787
  1240. package/dist/core/provenance.js.map +0 -1
  1241. package/dist/core/records.js.map +0 -1
  1242. package/dist/core/repo.js +0 -438
  1243. package/dist/core/repo.js.map +0 -1
  1244. package/dist/core/report.js +0 -47
  1245. package/dist/core/report.js.map +0 -1
  1246. package/dist/core/spec.js +0 -505
  1247. package/dist/core/spec.js.map +0 -1
  1248. package/dist/core/staging.js +0 -890
  1249. package/dist/core/staging.js.map +0 -1
  1250. package/dist/core/status.js +0 -1132
  1251. package/dist/core/status.js.map +0 -1
  1252. package/dist/core/steps.js +0 -72
  1253. package/dist/core/steps.js.map +0 -1
  1254. package/dist/core/verify.js +0 -807
  1255. package/dist/core/verify.js.map +0 -1
  1256. package/dist/core/version.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subsystem.js","sourceRoot":"","sources":["../../../src/commands/subsystem/subsystem.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `loam subsystem <verb>` — the command surface over the tree under\n * `services/`.\n *\n * ONE registration with the verbs dispatched inside the action, deliberately\n * NOT Commander subcommands: test/agents.test.ts counts the literal\n * command-registration calls across src/commands/ and asserts the count\n * equals `buildProgram()`'s command list, so nested subcommands would\n * register as one command while counting as many literals — the guard would\n * fail in a way that reads as unrelated. (That same scan is why this comment\n * never spells the registration call with its parenthesis.) The option\n * superset is declared here once; the arity table below refuses a flag on a\n * verb that does not read it, because a silently ignored `--into` is a move\n * that did not happen.\n */\nimport type { Command } from \"commander\";\nimport { configOrRefuse, fail } from \"../../core/envelope/json.js\";\nimport { DocsRepoUnavailableError } from \"../../core/repo/state.js\";\nimport { docsRepoReady, reportDocsRepoError } from \"../policy/gate.js\";\nimport { runNew, runRm } from \"./edit.js\";\nimport { runMove, runRename } from \"./move.js\";\nimport { runHistory, runList } from \"./query.js\";\nimport { runSync } from \"./sync.js\";\n\nexport interface SubsystemOptions {\n into?: string;\n under?: string;\n title?: string;\n description?: string;\n owner?: string;\n json?: boolean;\n}\n\nconst VERBS = [\"new\", \"move\", \"rename\", \"rm\", \"list\", \"history\", \"sync\"] as const;\ntype Verb = (typeof VERBS)[number];\n\n/** How many names each verb takes, spelled once so the refusals agree with the dispatch. */\nconst NAMES: Record<Verb, { min: number; max: number; usage: string }> = {\n new: { min: 1, max: 1, usage: \"subsystem new <name> [--under <sub>] [--title <text>] [--description <text>] [--owner <name>]\" },\n move: { min: 1, max: Infinity, usage: \"subsystem move <name>... --into <sub|.>\" },\n rename: { min: 2, max: 2, usage: \"subsystem rename <old> <new>\" },\n rm: { min: 1, max: 1, usage: \"subsystem rm <name>\" },\n list: { min: 0, max: 0, usage: \"subsystem list\" },\n history: { min: 1, max: 1, usage: \"subsystem history <name>\" },\n sync: { min: 0, max: 0, usage: \"subsystem sync\" },\n};\n\n/** The flag/verb contradictions worth refusing: an ignored flag is a lie about what ran. */\nfunction flagMisuse(verb: Verb, opts: SubsystemOptions): string | null {\n if (opts.into !== undefined && verb !== \"move\") return `--into belongs to 'move' (${NAMES.move.usage}).`;\n if (opts.into === undefined && verb === \"move\") return `'move' needs a destination: ${NAMES.move.usage} ('.' unfiles).`;\n for (const [flag, value] of [\n [\"--under\", opts.under],\n [\"--title\", opts.title],\n [\"--description\", opts.description],\n [\"--owner\", opts.owner],\n ] as const) {\n if (value !== undefined && verb !== \"new\") return `${flag} belongs to 'new' (${NAMES.new.usage}).`;\n }\n return null;\n}\n\nexport function registerSubsystem(program: Command): void {\n program\n .command(\"subsystem\")\n .description(\"Manage the subsystem tree under services/ — the grouping no identity depends on\")\n .argument(\"<verb>\", VERBS.join(\" | \"))\n .argument(\"[names...]\", \"the subsystem or service names the verb applies to\")\n .option(\"--into <name>\", \"move: the destination subsystem, or '.' for the services/ root (unfiled)\")\n .option(\"--under <name>\", \"new: the parent subsystem (default: the services/ root)\")\n .option(\"--title <text>\", \"new: the subsystem's human title, kept in subsystem.yaml\")\n .option(\"--description <text>\", \"new: what the group is, kept in subsystem.yaml\")\n .option(\"--owner <name>\", \"new: who answers for the group, kept in subsystem.yaml\")\n .option(\"--json\", \"emit the machine contract instead of the human view\")\n .action(async (verb: string, names: string[], opts: SubsystemOptions) => {\n const json = opts.json === true;\n if (!(VERBS as readonly string[]).includes(verb)) {\n // The same code `list` gives a bad section: one mistake class, one code.\n fail(json, \"invalid-option\", `Unknown verb '${verb}'. Expected: ${VERBS.join(\" | \")}.`);\n return;\n }\n const arity = NAMES[verb as Verb];\n if (names.length < arity.min || names.length > arity.max) {\n fail(json, \"invalid-option\", `'${verb}' takes ${arity.min === arity.max ? arity.min : `${arity.min}+`} name(s): ${arity.usage}`);\n return;\n }\n const misuse = flagMisuse(verb as Verb, opts);\n if (misuse !== null) {\n fail(json, \"invalid-option\", misuse);\n return;\n }\n const config = await configOrRefuse(json);\n if (config === null) return;\n const { docsDir } = config;\n // \"services\": every verb reads or rewrites the tree that IS the fleet,\n // so a docsDir with no services/ is a refusal, never an empty answer.\n if (!docsRepoReady(json, docsDir, \"services\")) return;\n try {\n switch (verb as Verb) {\n case \"new\":\n return await runNew(docsDir, names[0]!, opts, json);\n case \"move\":\n return await runMove(docsDir, names, opts.into!, json);\n case \"rename\":\n return await runRename(docsDir, [names[0]!, names[1]!], json);\n case \"rm\":\n return await runRm(docsDir, names[0]!, json);\n case \"list\":\n return await runList(docsDir, json);\n case \"history\":\n return await runHistory(docsDir, names[0]!, json);\n case \"sync\":\n return await runSync(docsDir, json);\n }\n } catch (err) {\n if (!(err instanceof DocsRepoUnavailableError)) throw err;\n reportDocsRepoError(json, err);\n }\n });\n}\n"]}
@@ -0,0 +1,318 @@
1
+ /**
2
+ * `loam subsystem sync` — the writer of everything under the tree that exists
3
+ * only to be RENDERED, which is the renderer's reading of the tree twice over:
4
+ *
5
+ * - `architecture/subsystems.likec4`, the GENERATED views file. Recomputed from
6
+ * the tree on every run, compared, written when it differs, removed when the
7
+ * tree has no subsystems. One of the two repairs for `subsystem.views-stale`.
8
+ * Left exactly as it is when the `architecture/` project does not parse and
9
+ * the file already exists — `action: "blocked"`, below.
10
+ * - `architecture/services.likec4`, the OTHER generated views file: one
11
+ * overview view per service the map draws, so a reader can open a service and
12
+ * see what it touches. Same rules, same commit, same code when it drifts —
13
+ * which is what makes ONE `subsystem.views-stale` honest about two files, and
14
+ * why this command is named as the repair for both. Removed when NO service
15
+ * resolves to a map element, exactly as the subsystem file is removed when
16
+ * the tree has no subsystems. `serviceViews` is its `action`; `action` still
17
+ * means the subsystem file alone.
18
+ * - `services/<…>/<id>/likec4.config.json`, one LikeC4 project file beside
19
+ * every model that STANDS ALONE. Never compared, never rewritten. Created
20
+ * where a standalone model has none, and DELETED where an extending model has
21
+ * one: measured at the 1.59.2 pin, that nested project claims the model out of
22
+ * the root project and the fleet loses the service's interior
23
+ * (`core/repo/tree/render/projects.ts` carries the measurement). This is the
24
+ * repair `service.likec4-config-stray` has always named and, until now, did
25
+ * not perform.
26
+ * - the ROOT `likec4.config.json`'s `exclude` list, and ONLY that key. Derived
27
+ * from the shapes on disk on every run and rewritten when it differs, because
28
+ * the two shapes need opposite answers from it: a standalone model must be
29
+ * excluded (inside the root project every kind it declares is a duplicate)
30
+ * and an extending model must not be (the root project is the only place it
31
+ * parses). `planExclude` below states the gate that keeps an old repository
32
+ * untouched, and `core/c4/service-model/renderer.ts` states which half of the
33
+ * list is loam's and which is the team's. One entry loam did NOT write is
34
+ * taken anyway, and only this one: an entry naming a directory that HIDES an
35
+ * extending model — a subsystem-wide `services/platform/**` survived every
36
+ * sync while `service.model-excluded` named this command as the repair.
37
+ *
38
+ * NEITHER views file is written over a document loam did not write. Both are
39
+ * filenames loam RESERVES inside `architecture/`, a directory the team owns, and
40
+ * both are rewritten whole — so a repository that already kept a hand-authored
41
+ * diagram at one of those paths would have lost it, silently, on the first sync
42
+ * after the release that reserved the name. One predicate answers it for both
43
+ * (`readGeneratedFile`, off the file's own first line), the run reports
44
+ * `refused` for that file, writes nothing for it, and exits non-zero. A hand
45
+ * EDIT of a generated file is a different thing and is still repaired: it keeps
46
+ * the mark, so it is loam's file with wrong bytes in it, which is exactly what
47
+ * `subsystem.views-stale` says.
48
+ *
49
+ * THIS COMMAND IS NOT THE ONLY WRITER, and for a while it was the only one
50
+ * holding that line — reproduced, with a hand-authored
51
+ * `architecture/services.likec4` in the tree: `loam subsystem new platform`
52
+ * printed "architecture/services.likec4 updated" and destroyed it. The predicate
53
+ * and the refusal sentence therefore live below every writer
54
+ * (`core/repo/tree/render/service/header.ts`), and `./txn/txn.ts` and
55
+ * `../seed/plan.ts` ask the same question of the same two paths.
56
+ *
57
+ * WHAT DIFFERS IS THE POLICY, not the question, and the difference is the shape
58
+ * of the operation rather than a second opinion about ownership. Sync REPORTS
59
+ * `refused` for the one file and does the rest: nothing it writes depends on
60
+ * that file, every part of it is idempotent, and a run that also created a
61
+ * project file really did create it. A tree-changing verb and `seed` REFUSE
62
+ * WHOLE, because their generated file has to land in the same commit as the
63
+ * change to the tree — completing half of that is the very state the commit
64
+ * window exists never to leave between two commits, and `subsystem move` would
65
+ * additionally leave git-staged renames behind it.
66
+ *
67
+ * The rules differ because the files answer to different owners. The
68
+ * views files are a pure function of the tree and the committed landscape, so
69
+ * every byte of them is loam's and a hand edit is by definition stale. The
70
+ * project file's bytes are a function of the service id ALONE — the identity
71
+ * no verb ever changes — so nothing can make it stale, and the keys LikeC4
72
+ * lets a team add to it (`title`, styles, a contact) are the team's; a compare
73
+ * would fight them, and a rewrite would take them. `core/repo/tree/render/projects.ts`
74
+ * records the measurement behind the file and the naming rule; here, presence
75
+ * is the one question asked of it, through the SAME predicate `validate --all`
76
+ * grades with (`missingProjects`), so the grader can never name a gap this
77
+ * writer would not fill.
78
+ *
79
+ * Nothing under `services/` is written, and no `exclude` is recomputed, unless
80
+ * the ROOT `likec4.config.json` exists. Without it the tree is not a loadable
81
+ * workspace at all — every model would merge into one project and report every
82
+ * declaration as a duplicate — and a nested project beside a missing root is a
83
+ * promise about a renderer that cannot be opened. `loam doctor` prints the root
84
+ * file; sync says so and writes nothing for the services until it is there.
85
+ *
86
+ * Every write goes through the same lock + journaled transaction every docs
87
+ * writer uses (`commitStaged`), and both kinds land in ONE commit: a
88
+ * predecessor's interrupted commit is recovered first and a sync killed
89
+ * mid-swap is rolled forward by the next writer. Idempotent by construction:
90
+ * the expected views bytes are a pure function of the tree, and a project
91
+ * file, once present, is never a gap again — so a second run reports
92
+ * `current` and writes nothing.
93
+ *
94
+ * The expected views bytes come from `./txn/views.ts` — the same module every
95
+ * writer verb renders from, so sync and the transactions cannot disagree
96
+ * about what the file should say. The subsystem verbs' own commit window
97
+ * (`./txn/txn.ts`) does NOT write project files, and records why. What this run
98
+ * SAYS it did is `./txn/report.ts`: the third answer about the same three files,
99
+ * and the phase that is not part of the commit.
100
+ */
101
+ import { existsSync } from "node:fs";
102
+ import { resolve } from "node:path";
103
+ import { readModelShapes } from "../../core/c4/service-model/shape.js";
104
+ import { fail, repoPath } from "../../core/envelope/json.js";
105
+ import { LIKEC4_ROOT_PROJECT, rootProjectPath, serviceRenderPaths } from "../../core/repo/paths.js";
106
+ import { listFleetTree } from "../../core/repo/repo.js";
107
+ import { renderServiceProject, surveyProjects, } from "../../core/repo/tree/render/projects.js";
108
+ import { stageWrites } from "../../core/staging/commit.js";
109
+ import { LOCK_WAIT_MS } from "../../core/staging/lock.js";
110
+ import { openCommitWindow } from "../../core/staging/recovery/recover.js";
111
+ import { commitStaged } from "../../core/staging/txn/transaction.js";
112
+ import { planWrite } from "../../core/staging/writes.js";
113
+ import { readGeneratedFile } from "../../core/repo/tree/render/service/header.js";
114
+ import { NO_EXCLUDE, planExclude } from "./txn/exclude.js";
115
+ import { reportSync } from "./txn/report.js";
116
+ import { expectedViews, planGenerated } from "./txn/views.js";
117
+ export async function runSync(docsDir, json) {
118
+ // A predecessor's journal is recovered (or refused) before the tree is
119
+ // read: the views file itself may be the half-written one.
120
+ const opened = await openCommitWindow(docsDir, LOCK_WAIT_MS);
121
+ if (!opened.ok) {
122
+ fail(json, opened.code, opened.message);
123
+ return;
124
+ }
125
+ const { recovered } = opened;
126
+ try {
127
+ const tree = await listFleetTree(docsDir);
128
+ // BOTH generated files, from ONE read of the map — `./txn/views.ts` says why
129
+ // the pair is one answer and why the parsed document, never a literal, is
130
+ // what the per-service peer sets are computed from.
131
+ const expected = await expectedViews(docsDir, tree);
132
+ const views = await planFile(expected.subsystems, expected.known);
133
+ const services = await planFile(expected.services, expected.known);
134
+ // ONE read of every model's bytes for the whole run, and the same scan the
135
+ // grader uses: it decides which directories are owed a project file AND
136
+ // which the root project must exclude, and those are opposite answers for
137
+ // the two shapes (`core/repo/tree/render/projects.ts`).
138
+ const shapes = await readModelShapes(tree.services.map((svc) => serviceRenderPaths(svc.dir).model));
139
+ const plan = planProjects(docsDir, tree.services, shapes);
140
+ const exclude = plan.root ? await planExclude(docsDir, tree.services, plan.models) : NO_EXCLUDE;
141
+ // The plan IS the report: every gap is created and every stray removed in
142
+ // the one commit below, and the early return is the branch where both lists
143
+ // are empty.
144
+ const projects = () => ({
145
+ root: plan.root,
146
+ // SORTED BY PATH, which is what the contract says these keys hold and what
147
+ // the survey's own order is not: `surveyProjects` sorts by service id, so
148
+ // `services/svc-a/…` came out before `services/platform/svc-d/…` and a
149
+ // consumer told the list was "sorted" got an order no path sort produces
150
+ // (re-verification 2026-09-04, area C item 6). The text view prints the
151
+ // same array, so the two orders cannot drift apart.
152
+ created: plan.gaps.map((gap) => repoPath(docsDir, gap.path)).sort(),
153
+ removed: plan.strays.map((stray) => repoPath(docsDir, stray.path)).sort(),
154
+ current: plan.current,
155
+ modelled: plan.modelled,
156
+ exclude,
157
+ });
158
+ // `action` still describes `architecture/subsystems.likec4` ALONE — a run
159
+ // that only created project files, or only rewrote the per-service
160
+ // overviews, answers `current` for it, exactly as before either existed, so
161
+ // nothing reading the key sees a new meaning. The second generated file
162
+ // arrives as a key of its own (`serviceViews`), because a payload key's
163
+ // meaning is frozen and folding two files into one answer would lose which
164
+ // one moved — the only thing either sentence has to say.
165
+ const say = () => {
166
+ reportSync(json, {
167
+ action: views.action,
168
+ serviceViews: services.action,
169
+ subsystems: tree.subsystems.length,
170
+ recovered,
171
+ projects: projects(),
172
+ mapUnreadable: !expected.known,
173
+ });
174
+ // A REFUSAL MUST NOT READ AS A CLEAN RUN. The rest of the sync really did
175
+ // happen — the other generated file, the project files, the root
176
+ // `exclude` — so this is `loam doctor`'s and `loam validate`'s shape and
177
+ // not `fail()`'s: the whole report is emitted, and the exit code says the
178
+ // tree was not left in the state the command was asked to leave it in. A
179
+ // caller that runs `loam subsystem sync` in a hook or a CI step would
180
+ // otherwise be told nothing, forever, about a file it can never repair —
181
+ // and `loam validate --all` would go on reporting `subsystem.views-stale`
182
+ // for that path with this very command named as the fix.
183
+ if (views.action === "refused" || services.action === "refused")
184
+ process.exitCode = 1;
185
+ };
186
+ const generated = [views.write, services.write].filter((write) => write !== null);
187
+ if (generated.length === 0 && plan.gaps.length === 0 && plan.strays.length === 0 && exclude.write === null) {
188
+ say();
189
+ return;
190
+ }
191
+ const writes = [...generated];
192
+ // `planWrite` marks a non-existent target exclusive — a no-clobber create
193
+ // that fails EEXIST rather than replacing a file another writer landed in
194
+ // the same instant. That IS the create-only rule, enforced by the write
195
+ // path rather than by the `existsSync` the predicate already ran: a file
196
+ // that appears between the check and the swap is somebody's, and stays.
197
+ for (const gap of plan.gaps) {
198
+ writes.push(planWrite(gap.path, renderServiceProject(gap.service.id, LIKEC4_ROOT_PROJECT)));
199
+ }
200
+ // The one file this verb DELETES, and it rides the same journal as the rest,
201
+ // so a run killed mid-swap is rolled forward rather than half-done.
202
+ // `content: null` is the delete the views file already uses.
203
+ for (const stray of plan.strays)
204
+ writes.push({ path: stray.path, content: null });
205
+ // The root project's `exclude`, in the SAME transaction as the files it
206
+ // decides the fate of: a run that wrote the per-service projects and died
207
+ // before the exclude would leave a tree where the renderer loads a
208
+ // standalone model twice — once in the root project, where every kind it
209
+ // declares is a duplicate — which is worse than either end state.
210
+ if (exclude.write !== null)
211
+ writes.push(exclude.write);
212
+ // One lock, one journal, one commit for both kinds of file — a sync killed
213
+ // between the views swap and the project creates would otherwise leave a
214
+ // half-state no later run could tell from a team's deliberate deletion.
215
+ const staged = await stageWrites(writes);
216
+ const committed = await commitStaged({ root: docsDir, command: "subsystem", rerun: "loam subsystem sync", target: "subsystems" }, staged, "synced");
217
+ if (!committed.ok) {
218
+ fail(json, committed.code, committed.message);
219
+ return;
220
+ }
221
+ say();
222
+ }
223
+ finally {
224
+ await opened.release();
225
+ }
226
+ }
227
+ /**
228
+ * What this run will do to ONE generated file: the action to report, and the
229
+ * write to stage (or null for "leave it alone").
230
+ *
231
+ * ONE function for both generated files, because the rule is one rule and a
232
+ * second spelling of it would be a second chance for `subsystems.likec4` and
233
+ * `services.likec4` to answer differently about the same map. Past the two
234
+ * vetoes below, the compare is `planGenerated` (`./txn/views.ts`), the one the
235
+ * tree-changing verbs make too, which says why it is over CONTENT, not bytes.
236
+ *
237
+ * `blocked` is the map's veto and it is the whole reason `known` is threaded
238
+ * this far. The render cannot be trusted against a file that already exists when
239
+ * `architecture/` does not parse as one project: without the element join and
240
+ * the style census, `subsystems.likec4` is a title and a description — writing
241
+ * it would take the `include` lines, the boundary comment and the palette
242
+ * reference off a file whose only fault is a sibling document that does not
243
+ * parse — and `services.likec4` is NOTHING AT ALL, because every one of its
244
+ * views is gated on a service resolving to a map element, so the tolerant render
245
+ * would delete the whole file. An absent file is not protected: there is nothing
246
+ * to lose and a fleet being scaffolded must still get its first one.
247
+ *
248
+ * `refused` is the OTHER veto and it comes from the file rather than from the
249
+ * map: a file at one of these reserved paths that does not open with loam's mark
250
+ * was written by somebody, and this command writes both files whole. It is
251
+ * checked first, applies to both files through one predicate, and is the one
252
+ * answer here that makes the run exit non-zero — see `runSync`.
253
+ */
254
+ async function planFile(file, known) {
255
+ // ONE read for both questions — what the file says, and whose it is. The
256
+ // predicate and the reader live beside the mark itself
257
+ // (`core/repo/tree/render/service/header.ts`), below every writer of these two
258
+ // paths, because sync is one of FIVE and was for a while the only one holding
259
+ // the line.
260
+ const { text: actual, authored } = await readGeneratedFile(file.path);
261
+ // OWNERSHIP FIRST, before the map's veto and before the compare, because it is
262
+ // the one question whose wrong answer destroys work. Both of these are
263
+ // filenames loam RESERVES inside a directory the team owns, and every arm
264
+ // below writes the whole file or deletes it: a docs repo that already kept a
265
+ // hand-authored diagram at one of them would have lost it on the first sync
266
+ // after the upgrade that reserved the name, silently, breaking the promise the
267
+ // rest of the tree keeps (archive's verbatim splice: authored bytes stay
268
+ // authored). So the file is asked who wrote it. An EDIT of a generated file
269
+ // still carries the mark and is still loam's to repair — that is the whole
270
+ // point of `subsystem.views-stale` — and only a file that never carried it is
271
+ // somebody else's. Absent is not refused: there is nothing to lose.
272
+ if (authored)
273
+ return { action: "refused", write: null };
274
+ if (!known && actual !== null)
275
+ return { action: "blocked", write: null };
276
+ return planGenerated(file, actual);
277
+ }
278
+ /**
279
+ * What the project half of this run owes, from ONE predicate. `surveyProjects`
280
+ * is the shared spelling of "has a model, a legal id, and no file", and it
281
+ * hands back the sizes of the two domains it counted against — every model it
282
+ * walked, and the standalone models a file is owed for — so `current` is a
283
+ * subtraction rather than a second reading of the same two paths. A loop here
284
+ * re-spelling "has a model" was the drift the shared predicate exists to
285
+ * prevent, and it would have kept counting a directory the survey had
286
+ * skipped. Without the root file the gaps are real but stay unfilled —
287
+ * writing them would promise a renderer nobody can open — and `current` is 0
288
+ * because "already had a file" is only a fact about a workspace that exists.
289
+ */
290
+ function planProjects(docsDir, services, shapes) {
291
+ const root = existsSync(rootProjectPath(docsDir));
292
+ // A model that EXTENDS the map is owed no file, and the survey is where that
293
+ // is decided — one predicate for the writer and the grader, so `validate --all`
294
+ // can never name a gap this run would not fill. An unreadable model classifies
295
+ // as standalone (`readModelShapes`), which is the conservative arm: it gets a
296
+ // project file, which is what every model got before shapes existed.
297
+ const survey = surveyProjects(services, serviceRenderPaths, (model) => shapes.get(resolve(model)) !== "extending");
298
+ if (!root)
299
+ return { root, gaps: [], strays: [], current: 0, modelled: survey.modelled, models: survey.models };
300
+ return {
301
+ root,
302
+ gaps: survey.gaps,
303
+ // The removal is gated on the root file for the same reason the create is:
304
+ // without it the docs root is not a LikeC4 workspace, so nothing there is
305
+ // claiming anything out of a root project that does not exist, and deleting
306
+ // a team's file over a renderer nobody can open is a writer acting on a
307
+ // hazard it cannot see.
308
+ strays: survey.strays,
309
+ // Over the STANDALONE domain, which is the one `gaps` was drawn from: a
310
+ // model that extends the map is owed no file, so it can neither be a gap nor
311
+ // "already have one", and subtracting from `modelled` counted every
312
+ // extending model as the latter.
313
+ current: survey.standalone - survey.gaps.length,
314
+ modelled: survey.modelled,
315
+ models: survey.models,
316
+ };
317
+ }
318
+ //# sourceMappingURL=sync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync.js","sourceRoot":"","sources":["../../../src/commands/subsystem/sync.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `loam subsystem sync` — the writer of everything under the tree that exists\n * only to be RENDERED, which is the renderer's reading of the tree twice over:\n *\n * - `architecture/subsystems.likec4`, the GENERATED views file. Recomputed from\n * the tree on every run, compared, written when it differs, removed when the\n * tree has no subsystems. One of the two repairs for `subsystem.views-stale`.\n * Left exactly as it is when the `architecture/` project does not parse and\n * the file already exists — `action: \"blocked\"`, below.\n * - `architecture/services.likec4`, the OTHER generated views file: one\n * overview view per service the map draws, so a reader can open a service and\n * see what it touches. Same rules, same commit, same code when it drifts —\n * which is what makes ONE `subsystem.views-stale` honest about two files, and\n * why this command is named as the repair for both. Removed when NO service\n * resolves to a map element, exactly as the subsystem file is removed when\n * the tree has no subsystems. `serviceViews` is its `action`; `action` still\n * means the subsystem file alone.\n * - `services/<…>/<id>/likec4.config.json`, one LikeC4 project file beside\n * every model that STANDS ALONE. Never compared, never rewritten. Created\n * where a standalone model has none, and DELETED where an extending model has\n * one: measured at the 1.59.2 pin, that nested project claims the model out of\n * the root project and the fleet loses the service's interior\n * (`core/repo/tree/render/projects.ts` carries the measurement). This is the\n * repair `service.likec4-config-stray` has always named and, until now, did\n * not perform.\n * - the ROOT `likec4.config.json`'s `exclude` list, and ONLY that key. Derived\n * from the shapes on disk on every run and rewritten when it differs, because\n * the two shapes need opposite answers from it: a standalone model must be\n * excluded (inside the root project every kind it declares is a duplicate)\n * and an extending model must not be (the root project is the only place it\n * parses). `planExclude` below states the gate that keeps an old repository\n * untouched, and `core/c4/service-model/renderer.ts` states which half of the\n * list is loam's and which is the team's. One entry loam did NOT write is\n * taken anyway, and only this one: an entry naming a directory that HIDES an\n * extending model — a subsystem-wide `services/platform/**` survived every\n * sync while `service.model-excluded` named this command as the repair.\n *\n * NEITHER views file is written over a document loam did not write. Both are\n * filenames loam RESERVES inside `architecture/`, a directory the team owns, and\n * both are rewritten whole — so a repository that already kept a hand-authored\n * diagram at one of those paths would have lost it, silently, on the first sync\n * after the release that reserved the name. One predicate answers it for both\n * (`readGeneratedFile`, off the file's own first line), the run reports\n * `refused` for that file, writes nothing for it, and exits non-zero. A hand\n * EDIT of a generated file is a different thing and is still repaired: it keeps\n * the mark, so it is loam's file with wrong bytes in it, which is exactly what\n * `subsystem.views-stale` says.\n *\n * THIS COMMAND IS NOT THE ONLY WRITER, and for a while it was the only one\n * holding that line — reproduced, with a hand-authored\n * `architecture/services.likec4` in the tree: `loam subsystem new platform`\n * printed \"architecture/services.likec4 updated\" and destroyed it. The predicate\n * and the refusal sentence therefore live below every writer\n * (`core/repo/tree/render/service/header.ts`), and `./txn/txn.ts` and\n * `../seed/plan.ts` ask the same question of the same two paths.\n *\n * WHAT DIFFERS IS THE POLICY, not the question, and the difference is the shape\n * of the operation rather than a second opinion about ownership. Sync REPORTS\n * `refused` for the one file and does the rest: nothing it writes depends on\n * that file, every part of it is idempotent, and a run that also created a\n * project file really did create it. A tree-changing verb and `seed` REFUSE\n * WHOLE, because their generated file has to land in the same commit as the\n * change to the tree — completing half of that is the very state the commit\n * window exists never to leave between two commits, and `subsystem move` would\n * additionally leave git-staged renames behind it.\n *\n * The rules differ because the files answer to different owners. The\n * views files are a pure function of the tree and the committed landscape, so\n * every byte of them is loam's and a hand edit is by definition stale. The\n * project file's bytes are a function of the service id ALONE — the identity\n * no verb ever changes — so nothing can make it stale, and the keys LikeC4\n * lets a team add to it (`title`, styles, a contact) are the team's; a compare\n * would fight them, and a rewrite would take them. `core/repo/tree/render/projects.ts`\n * records the measurement behind the file and the naming rule; here, presence\n * is the one question asked of it, through the SAME predicate `validate --all`\n * grades with (`missingProjects`), so the grader can never name a gap this\n * writer would not fill.\n *\n * Nothing under `services/` is written, and no `exclude` is recomputed, unless\n * the ROOT `likec4.config.json` exists. Without it the tree is not a loadable\n * workspace at all — every model would merge into one project and report every\n * declaration as a duplicate — and a nested project beside a missing root is a\n * promise about a renderer that cannot be opened. `loam doctor` prints the root\n * file; sync says so and writes nothing for the services until it is there.\n *\n * Every write goes through the same lock + journaled transaction every docs\n * writer uses (`commitStaged`), and both kinds land in ONE commit: a\n * predecessor's interrupted commit is recovered first and a sync killed\n * mid-swap is rolled forward by the next writer. Idempotent by construction:\n * the expected views bytes are a pure function of the tree, and a project\n * file, once present, is never a gap again — so a second run reports\n * `current` and writes nothing.\n *\n * The expected views bytes come from `./txn/views.ts` — the same module every\n * writer verb renders from, so sync and the transactions cannot disagree\n * about what the file should say. The subsystem verbs' own commit window\n * (`./txn/txn.ts`) does NOT write project files, and records why. What this run\n * SAYS it did is `./txn/report.ts`: the third answer about the same three files,\n * and the phase that is not part of the commit.\n */\nimport { existsSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { readModelShapes, type ModelShape } from \"../../core/c4/service-model/shape.js\";\nimport type { DocsDir } from \"../../core/kernel/ids/dirs.js\";\nimport { fail, repoPath } from \"../../core/envelope/json.js\";\nimport { LIKEC4_ROOT_PROJECT, rootProjectPath, serviceRenderPaths } from \"../../core/repo/paths.js\";\nimport { listFleetTree } from \"../../core/repo/repo.js\";\nimport {\n type ProjectGap,\n renderServiceProject,\n surveyProjects,\n type SurveyedModel,\n} from \"../../core/repo/tree/render/projects.js\";\nimport type { WalkedService } from \"../../core/repo/tree/walk.js\";\nimport { stageWrites } from \"../../core/staging/commit.js\";\nimport { LOCK_WAIT_MS } from \"../../core/staging/lock.js\";\nimport { openCommitWindow } from \"../../core/staging/recovery/recover.js\";\nimport { commitStaged } from \"../../core/staging/txn/transaction.js\";\nimport { planWrite, type PlannedWrite } from \"../../core/staging/writes.js\";\nimport { readGeneratedFile } from \"../../core/repo/tree/render/service/header.js\";\nimport { NO_EXCLUDE, planExclude } from \"./txn/exclude.js\";\nimport { type ProjectsReport, reportSync, type SyncAction } from \"./txn/report.js\";\nimport { type ExpectedFile, expectedViews, planGenerated } from \"./txn/views.js\";\n\n/**\n * The per-service project half of one sync, before the write: what the\n * predicate found, and the two counts the report needs beside it.\n */\ninterface ProjectPlan {\n /** Whether the root project file exists — the gate on every service write. */\n root: boolean;\n /** The files this run will create. Empty whenever `root` is false. */\n gaps: ProjectGap<WalkedService>[];\n /** The files this run will DELETE — a project file beside an extending model. Empty whenever `root` is false. */\n strays: ProjectGap<WalkedService>[];\n /**\n * Services owed a project file that ALREADY had one — so STANDALONE models\n * only; 0 whenever `root` is false. An extending model is owed none, and\n * counting it here said a file was in place beside a model that must not have\n * one (`service.likec4-config-stray` grades exactly that state).\n */\n current: number;\n /** Model-bearing services, root or no root — what the root-missing note is owed to. */\n modelled: number;\n /** Every model this run considered, with its shape — the exclude list is derived from the same walk. */\n models: SurveyedModel<WalkedService>[];\n}\n\nexport async function runSync(docsDir: DocsDir, json: boolean): Promise<void> {\n // A predecessor's journal is recovered (or refused) before the tree is\n // read: the views file itself may be the half-written one.\n const opened = await openCommitWindow(docsDir, LOCK_WAIT_MS);\n if (!opened.ok) {\n fail(json, opened.code, opened.message);\n return;\n }\n const { recovered } = opened;\n try {\n const tree = await listFleetTree(docsDir);\n // BOTH generated files, from ONE read of the map — `./txn/views.ts` says why\n // the pair is one answer and why the parsed document, never a literal, is\n // what the per-service peer sets are computed from.\n const expected = await expectedViews(docsDir, tree);\n const views = await planFile(expected.subsystems, expected.known);\n const services = await planFile(expected.services, expected.known);\n // ONE read of every model's bytes for the whole run, and the same scan the\n // grader uses: it decides which directories are owed a project file AND\n // which the root project must exclude, and those are opposite answers for\n // the two shapes (`core/repo/tree/render/projects.ts`).\n const shapes = await readModelShapes(tree.services.map((svc) => serviceRenderPaths(svc.dir).model));\n const plan = planProjects(docsDir, tree.services, shapes);\n const exclude = plan.root ? await planExclude(docsDir, tree.services, plan.models) : NO_EXCLUDE;\n // The plan IS the report: every gap is created and every stray removed in\n // the one commit below, and the early return is the branch where both lists\n // are empty.\n const projects = (): ProjectsReport => ({\n root: plan.root,\n // SORTED BY PATH, which is what the contract says these keys hold and what\n // the survey's own order is not: `surveyProjects` sorts by service id, so\n // `services/svc-a/…` came out before `services/platform/svc-d/…` and a\n // consumer told the list was \"sorted\" got an order no path sort produces\n // (re-verification 2026-09-04, area C item 6). The text view prints the\n // same array, so the two orders cannot drift apart.\n created: plan.gaps.map((gap) => repoPath(docsDir, gap.path)).sort(),\n removed: plan.strays.map((stray) => repoPath(docsDir, stray.path)).sort(),\n current: plan.current,\n modelled: plan.modelled,\n exclude,\n });\n // `action` still describes `architecture/subsystems.likec4` ALONE — a run\n // that only created project files, or only rewrote the per-service\n // overviews, answers `current` for it, exactly as before either existed, so\n // nothing reading the key sees a new meaning. The second generated file\n // arrives as a key of its own (`serviceViews`), because a payload key's\n // meaning is frozen and folding two files into one answer would lose which\n // one moved — the only thing either sentence has to say.\n const say = (): void => {\n reportSync(json, {\n action: views.action,\n serviceViews: services.action,\n subsystems: tree.subsystems.length,\n recovered,\n projects: projects(),\n mapUnreadable: !expected.known,\n });\n // A REFUSAL MUST NOT READ AS A CLEAN RUN. The rest of the sync really did\n // happen — the other generated file, the project files, the root\n // `exclude` — so this is `loam doctor`'s and `loam validate`'s shape and\n // not `fail()`'s: the whole report is emitted, and the exit code says the\n // tree was not left in the state the command was asked to leave it in. A\n // caller that runs `loam subsystem sync` in a hook or a CI step would\n // otherwise be told nothing, forever, about a file it can never repair —\n // and `loam validate --all` would go on reporting `subsystem.views-stale`\n // for that path with this very command named as the fix.\n if (views.action === \"refused\" || services.action === \"refused\") process.exitCode = 1;\n };\n const generated = [views.write, services.write].filter((write) => write !== null);\n if (generated.length === 0 && plan.gaps.length === 0 && plan.strays.length === 0 && exclude.write === null) {\n say();\n return;\n }\n const writes: PlannedWrite[] = [...generated];\n // `planWrite` marks a non-existent target exclusive — a no-clobber create\n // that fails EEXIST rather than replacing a file another writer landed in\n // the same instant. That IS the create-only rule, enforced by the write\n // path rather than by the `existsSync` the predicate already ran: a file\n // that appears between the check and the swap is somebody's, and stays.\n for (const gap of plan.gaps) {\n writes.push(planWrite(gap.path, renderServiceProject(gap.service.id, LIKEC4_ROOT_PROJECT)));\n }\n // The one file this verb DELETES, and it rides the same journal as the rest,\n // so a run killed mid-swap is rolled forward rather than half-done.\n // `content: null` is the delete the views file already uses.\n for (const stray of plan.strays) writes.push({ path: stray.path, content: null });\n // The root project's `exclude`, in the SAME transaction as the files it\n // decides the fate of: a run that wrote the per-service projects and died\n // before the exclude would leave a tree where the renderer loads a\n // standalone model twice — once in the root project, where every kind it\n // declares is a duplicate — which is worse than either end state.\n if (exclude.write !== null) writes.push(exclude.write);\n // One lock, one journal, one commit for both kinds of file — a sync killed\n // between the views swap and the project creates would otherwise leave a\n // half-state no later run could tell from a team's deliberate deletion.\n const staged = await stageWrites(writes);\n const committed = await commitStaged(\n { root: docsDir, command: \"subsystem\", rerun: \"loam subsystem sync\", target: \"subsystems\" },\n staged,\n \"synced\",\n );\n if (!committed.ok) {\n fail(json, committed.code, committed.message);\n return;\n }\n say();\n } finally {\n await opened.release();\n }\n}\n\n/**\n * What this run will do to ONE generated file: the action to report, and the\n * write to stage (or null for \"leave it alone\").\n *\n * ONE function for both generated files, because the rule is one rule and a\n * second spelling of it would be a second chance for `subsystems.likec4` and\n * `services.likec4` to answer differently about the same map. Past the two\n * vetoes below, the compare is `planGenerated` (`./txn/views.ts`), the one the\n * tree-changing verbs make too, which says why it is over CONTENT, not bytes.\n *\n * `blocked` is the map's veto and it is the whole reason `known` is threaded\n * this far. The render cannot be trusted against a file that already exists when\n * `architecture/` does not parse as one project: without the element join and\n * the style census, `subsystems.likec4` is a title and a description — writing\n * it would take the `include` lines, the boundary comment and the palette\n * reference off a file whose only fault is a sibling document that does not\n * parse — and `services.likec4` is NOTHING AT ALL, because every one of its\n * views is gated on a service resolving to a map element, so the tolerant render\n * would delete the whole file. An absent file is not protected: there is nothing\n * to lose and a fleet being scaffolded must still get its first one.\n *\n * `refused` is the OTHER veto and it comes from the file rather than from the\n * map: a file at one of these reserved paths that does not open with loam's mark\n * was written by somebody, and this command writes both files whole. It is\n * checked first, applies to both files through one predicate, and is the one\n * answer here that makes the run exit non-zero — see `runSync`.\n */\nasync function planFile(file: ExpectedFile, known: boolean): Promise<{ action: SyncAction; write: PlannedWrite | null }> {\n // ONE read for both questions — what the file says, and whose it is. The\n // predicate and the reader live beside the mark itself\n // (`core/repo/tree/render/service/header.ts`), below every writer of these two\n // paths, because sync is one of FIVE and was for a while the only one holding\n // the line.\n const { text: actual, authored } = await readGeneratedFile(file.path);\n // OWNERSHIP FIRST, before the map's veto and before the compare, because it is\n // the one question whose wrong answer destroys work. Both of these are\n // filenames loam RESERVES inside a directory the team owns, and every arm\n // below writes the whole file or deletes it: a docs repo that already kept a\n // hand-authored diagram at one of them would have lost it on the first sync\n // after the upgrade that reserved the name, silently, breaking the promise the\n // rest of the tree keeps (archive's verbatim splice: authored bytes stay\n // authored). So the file is asked who wrote it. An EDIT of a generated file\n // still carries the mark and is still loam's to repair — that is the whole\n // point of `subsystem.views-stale` — and only a file that never carried it is\n // somebody else's. Absent is not refused: there is nothing to lose.\n if (authored) return { action: \"refused\", write: null };\n if (!known && actual !== null) return { action: \"blocked\", write: null };\n return planGenerated(file, actual);\n}\n\n/**\n * What the project half of this run owes, from ONE predicate. `surveyProjects`\n * is the shared spelling of \"has a model, a legal id, and no file\", and it\n * hands back the sizes of the two domains it counted against — every model it\n * walked, and the standalone models a file is owed for — so `current` is a\n * subtraction rather than a second reading of the same two paths. A loop here\n * re-spelling \"has a model\" was the drift the shared predicate exists to\n * prevent, and it would have kept counting a directory the survey had\n * skipped. Without the root file the gaps are real but stay unfilled —\n * writing them would promise a renderer nobody can open — and `current` is 0\n * because \"already had a file\" is only a fact about a workspace that exists.\n */\nfunction planProjects(\n docsDir: DocsDir,\n services: readonly WalkedService[],\n shapes: ReadonlyMap<string, ModelShape>,\n): ProjectPlan {\n const root = existsSync(rootProjectPath(docsDir));\n // A model that EXTENDS the map is owed no file, and the survey is where that\n // is decided — one predicate for the writer and the grader, so `validate --all`\n // can never name a gap this run would not fill. An unreadable model classifies\n // as standalone (`readModelShapes`), which is the conservative arm: it gets a\n // project file, which is what every model got before shapes existed.\n const survey = surveyProjects(services, serviceRenderPaths, (model) => shapes.get(resolve(model)) !== \"extending\");\n if (!root) return { root, gaps: [], strays: [], current: 0, modelled: survey.modelled, models: survey.models };\n return {\n root,\n gaps: survey.gaps,\n // The removal is gated on the root file for the same reason the create is:\n // without it the docs root is not a LikeC4 workspace, so nothing there is\n // claiming anything out of a root project that does not exist, and deleting\n // a team's file over a renderer nobody can open is a writer acting on a\n // hazard it cannot see.\n strays: survey.strays,\n // Over the STANDALONE domain, which is the one `gaps` was drawn from: a\n // model that extends the map is owed no file, so it can neither be a gap nor\n // \"already have one\", and subtracting from `modelled` counted every\n // extending model as the latter.\n current: survey.standalone - survey.gaps.length,\n modelled: survey.modelled,\n models: survey.models,\n };\n}\n"]}
@@ -0,0 +1,132 @@
1
+ /**
2
+ * The ROOT `likec4.config.json`'s `exclude` list, as `loam subsystem sync`
3
+ * derives it from the shapes on disk.
4
+ *
5
+ * It sits beside `./views.ts` for that module's reason and by the same seam:
6
+ * both answer "what should this renderer-only file say, given the tree?", both
7
+ * are pure derivations one command writes, and keeping them together is what
8
+ * stops the writer and the grader spelling one rule twice. The difference is
9
+ * ownership, and it is stated in `core/c4/service-model/renderer.ts`: every byte
10
+ * of the generated views file is loam's, while this file is the team's and loam
11
+ * maintains exactly the `services/` entries in it. What an entry COVERS is
12
+ * `core/c4/root-project/exclude.ts`'s question, asked of the directory the entry
13
+ * names rather than of its spelling.
14
+ *
15
+ * It is a module rather than three functions in `../sync.ts` because that file
16
+ * reached its line limit carrying them, and this is the phase boundary inside
17
+ * it: `sync.ts` is the lock, the transaction and the report; this is one of the
18
+ * three things it decides to write.
19
+ */
20
+ import { readFile } from "node:fs/promises";
21
+ import { excludingEntry, parseRootProject, readRootExclude } from "../../../core/c4/root-project/exclude.js";
22
+ import { standaloneExclude } from "../../../core/c4/service-model/renderer.js";
23
+ import { serviceTreePath } from "../../../core/kernel/ids/dirs.js";
24
+ import { rootProjectPath } from "../../../core/repo/paths.js";
25
+ import { planWrite } from "../../../core/staging/writes.js";
26
+ /** The answer for a run that has no root file to read, and the shape every other arm fills. */
27
+ export const NO_EXCLUDE = {
28
+ updated: false,
29
+ entries: [],
30
+ added: [],
31
+ removed: [],
32
+ write: null,
33
+ unreadable: false,
34
+ };
35
+ /**
36
+ * The root project's `exclude` list, recomputed from the shapes on disk.
37
+ *
38
+ * WHAT MAKES THIS SAFE TO RUN ON EVERY SYNC is the split `standaloneExclude`
39
+ * enforces: the `services/` half of the list is loam's and every other entry is
40
+ * the team's, kept in order. The scaffold's node_modules glob, `features/**`, a
41
+ * team's own `drafts/**` all survive; only the entries that decide whether a
42
+ * model is renderable are derived. A standalone model MUST be excluded (inside
43
+ * the root project every kind it declares is a duplicate blamed on the map as
44
+ * well) and an extending model must NOT be (the root project is the only place
45
+ * it parses), so a service that migrates from one shape to the other has its
46
+ * entry added or dropped on the next sync instead of quietly blanking a project.
47
+ *
48
+ * THE GATE keeps an old repository untouched. A fleet whose models all stand
49
+ * alone and whose root already says `services/**` is already correct, and
50
+ * rewriting it into one entry per service would be a diff with no fact behind
51
+ * it — so the rewrite happens only when at least one model extends the map (the
52
+ * blanket exclusion is then wrong) or some standalone model is not covered at
53
+ * all (the renderer is merging it into the map right now). Comparing the parsed
54
+ * ARRAYS rather than the bytes is the second half of the same rule: a file whose
55
+ * `exclude` already says what this run would write is left exactly as the team
56
+ * formatted it.
57
+ *
58
+ * A root config loam cannot read an `exclude` list out of is REPORTED and never
59
+ * rewritten. Guessing at the JSON a team hand-wrote is how a writer destroys a
60
+ * file it did not understand.
61
+ */
62
+ export async function planExclude(docsDir, services, models) {
63
+ const current = await readRootExclude(docsDir);
64
+ if (current === null)
65
+ return { ...NO_EXCLUDE, unreadable: true };
66
+ const standalone = models.filter((m) => m.standalone).map((m) => serviceTreePath(m.service));
67
+ // Both halves of the shape scan travel, not just the standalone one: an entry
68
+ // is loam's to take back either because loam wrote it (a tree the enumeration
69
+ // returns) or because it HIDES a model that only parses in the root project,
70
+ // and only the extending list can answer the second question. Without it a
71
+ // subsystem-wide `services/platform/**` survived every sync while
72
+ // `service.model-excluded` named that same sync as the repair.
73
+ const extending = models.filter((m) => !m.standalone).map((m) => serviceTreePath(m.service));
74
+ const wanted = standaloneExclude(current, {
75
+ standalone,
76
+ extending,
77
+ enumerated: services.map((svc) => serviceTreePath(svc)),
78
+ });
79
+ const uncovered = standalone.some((tree) => excludingEntry(current, tree) === null);
80
+ if (extending.length === 0 && !uncovered)
81
+ return { ...NO_EXCLUDE, entries: [...current] };
82
+ if (current.length === wanted.length && current.every((entry, i) => entry === wanted[i])) {
83
+ return { ...NO_EXCLUDE, entries: wanted };
84
+ }
85
+ const bytes = await rewrittenRootProject(docsDir, wanted);
86
+ if (bytes === null)
87
+ return { ...NO_EXCLUDE, entries: [...current], unreadable: true };
88
+ return {
89
+ updated: true,
90
+ entries: wanted,
91
+ added: wanted.filter((entry) => !current.includes(entry)),
92
+ removed: current.filter((entry) => !wanted.includes(entry)),
93
+ // `planWrite` decides create-vs-overwrite from the filesystem, so the root
94
+ // file — which by definition already exists here — is staged as an
95
+ // OVERWRITE, and `swapStaged` compares it against its pre-image immediately
96
+ // before the rename: a team member editing the same file during the sync
97
+ // stops the commit instead of having their bytes buried.
98
+ write: planWrite(rootProjectPath(docsDir), bytes),
99
+ unreadable: false,
100
+ };
101
+ }
102
+ /**
103
+ * The root project file with its `exclude` replaced and NOTHING else touched —
104
+ * every other key kept, in the order the team wrote them, re-serialised as
105
+ * 2-space JSON with a trailing newline (`core/docs.ts`'s own form, so a
106
+ * scaffolded file round-trips byte for byte).
107
+ *
108
+ * Null when the file stopped being a JSON object between `readRootExclude` and
109
+ * here, which is a concurrent edit rather than a state loam may write over.
110
+ */
111
+ async function rewrittenRootProject(docsDir, exclude) {
112
+ let text;
113
+ try {
114
+ text = await readFile(rootProjectPath(docsDir), "utf8");
115
+ }
116
+ catch {
117
+ // Unreadable is not "excludes nothing": the caller reports it and writes
118
+ // nothing at all.
119
+ return null;
120
+ }
121
+ // The SAME parse the grader read the list with — `parseRootProject`, which
122
+ // tolerates the byte-order mark PowerShell's `Out-File` writes. Two parses
123
+ // would mean a run that read an `exclude` here and then declared the file
124
+ // unreadable at the write, which is exactly what a BOM produced before
125
+ // (re-verification 2026-09-04, area C item 3). Re-read rather than carried:
126
+ // the point of this read is that it happens immediately before the swap.
127
+ const parsed = parseRootProject(text);
128
+ if (parsed === null)
129
+ return null;
130
+ return `${JSON.stringify({ ...parsed, exclude: [...exclude] }, null, 2)}\n`;
131
+ }
132
+ //# sourceMappingURL=exclude.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exclude.js","sourceRoot":"","sources":["../../../../src/commands/subsystem/txn/exclude.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The ROOT `likec4.config.json`'s `exclude` list, as `loam subsystem sync`\n * derives it from the shapes on disk.\n *\n * It sits beside `./views.ts` for that module's reason and by the same seam:\n * both answer \"what should this renderer-only file say, given the tree?\", both\n * are pure derivations one command writes, and keeping them together is what\n * stops the writer and the grader spelling one rule twice. The difference is\n * ownership, and it is stated in `core/c4/service-model/renderer.ts`: every byte\n * of the generated views file is loam's, while this file is the team's and loam\n * maintains exactly the `services/` entries in it. What an entry COVERS is\n * `core/c4/root-project/exclude.ts`'s question, asked of the directory the entry\n * names rather than of its spelling.\n *\n * It is a module rather than three functions in `../sync.ts` because that file\n * reached its line limit carrying them, and this is the phase boundary inside\n * it: `sync.ts` is the lock, the transaction and the report; this is one of the\n * three things it decides to write.\n */\nimport { readFile } from \"node:fs/promises\";\nimport { excludingEntry, parseRootProject, readRootExclude } from \"../../../core/c4/root-project/exclude.js\";\nimport { standaloneExclude } from \"../../../core/c4/service-model/renderer.js\";\nimport { serviceTreePath, type DocsDir } from \"../../../core/kernel/ids/dirs.js\";\nimport { rootProjectPath } from \"../../../core/repo/paths.js\";\nimport type { SurveyedModel } from \"../../../core/repo/tree/render/projects.js\";\nimport type { WalkedService } from \"../../../core/repo/tree/walk.js\";\nimport { planWrite, type PlannedWrite } from \"../../../core/staging/writes.js\";\n\n/** What one sync did to the ROOT project's `exclude` list. */\nexport interface ExcludePlan {\n /** Whether this run rewrites the list. */\n updated: boolean;\n /** The list as it stands after this run — the current one when nothing changed. */\n entries: string[];\n added: string[];\n removed: string[];\n /** The rewrite, staged with everything else. Null when nothing is owed. */\n write: PlannedWrite | null;\n /** The root file exists and loam could not read an `exclude` list out of it — reported, never rewritten. */\n unreadable: boolean;\n}\n\n/** The answer for a run that has no root file to read, and the shape every other arm fills. */\nexport const NO_EXCLUDE: ExcludePlan = {\n updated: false,\n entries: [],\n added: [],\n removed: [],\n write: null,\n unreadable: false,\n};\n\n/**\n * The root project's `exclude` list, recomputed from the shapes on disk.\n *\n * WHAT MAKES THIS SAFE TO RUN ON EVERY SYNC is the split `standaloneExclude`\n * enforces: the `services/` half of the list is loam's and every other entry is\n * the team's, kept in order. The scaffold's node_modules glob, `features/**`, a\n * team's own `drafts/**` all survive; only the entries that decide whether a\n * model is renderable are derived. A standalone model MUST be excluded (inside\n * the root project every kind it declares is a duplicate blamed on the map as\n * well) and an extending model must NOT be (the root project is the only place\n * it parses), so a service that migrates from one shape to the other has its\n * entry added or dropped on the next sync instead of quietly blanking a project.\n *\n * THE GATE keeps an old repository untouched. A fleet whose models all stand\n * alone and whose root already says `services/**` is already correct, and\n * rewriting it into one entry per service would be a diff with no fact behind\n * it — so the rewrite happens only when at least one model extends the map (the\n * blanket exclusion is then wrong) or some standalone model is not covered at\n * all (the renderer is merging it into the map right now). Comparing the parsed\n * ARRAYS rather than the bytes is the second half of the same rule: a file whose\n * `exclude` already says what this run would write is left exactly as the team\n * formatted it.\n *\n * A root config loam cannot read an `exclude` list out of is REPORTED and never\n * rewritten. Guessing at the JSON a team hand-wrote is how a writer destroys a\n * file it did not understand.\n */\nexport async function planExclude(\n docsDir: DocsDir,\n services: readonly WalkedService[],\n models: readonly SurveyedModel<WalkedService>[],\n): Promise<ExcludePlan> {\n const current = await readRootExclude(docsDir);\n if (current === null) return { ...NO_EXCLUDE, unreadable: true };\n const standalone = models.filter((m) => m.standalone).map((m) => serviceTreePath(m.service));\n // Both halves of the shape scan travel, not just the standalone one: an entry\n // is loam's to take back either because loam wrote it (a tree the enumeration\n // returns) or because it HIDES a model that only parses in the root project,\n // and only the extending list can answer the second question. Without it a\n // subsystem-wide `services/platform/**` survived every sync while\n // `service.model-excluded` named that same sync as the repair.\n const extending = models.filter((m) => !m.standalone).map((m) => serviceTreePath(m.service));\n const wanted = standaloneExclude(current, {\n standalone,\n extending,\n enumerated: services.map((svc) => serviceTreePath(svc)),\n });\n const uncovered = standalone.some((tree) => excludingEntry(current, tree) === null);\n if (extending.length === 0 && !uncovered) return { ...NO_EXCLUDE, entries: [...current] };\n if (current.length === wanted.length && current.every((entry, i) => entry === wanted[i])) {\n return { ...NO_EXCLUDE, entries: wanted };\n }\n const bytes = await rewrittenRootProject(docsDir, wanted);\n if (bytes === null) return { ...NO_EXCLUDE, entries: [...current], unreadable: true };\n return {\n updated: true,\n entries: wanted,\n added: wanted.filter((entry) => !current.includes(entry)),\n removed: current.filter((entry) => !wanted.includes(entry)),\n // `planWrite` decides create-vs-overwrite from the filesystem, so the root\n // file — which by definition already exists here — is staged as an\n // OVERWRITE, and `swapStaged` compares it against its pre-image immediately\n // before the rename: a team member editing the same file during the sync\n // stops the commit instead of having their bytes buried.\n write: planWrite(rootProjectPath(docsDir), bytes),\n unreadable: false,\n };\n}\n\n/**\n * The root project file with its `exclude` replaced and NOTHING else touched —\n * every other key kept, in the order the team wrote them, re-serialised as\n * 2-space JSON with a trailing newline (`core/docs.ts`'s own form, so a\n * scaffolded file round-trips byte for byte).\n *\n * Null when the file stopped being a JSON object between `readRootExclude` and\n * here, which is a concurrent edit rather than a state loam may write over.\n */\nasync function rewrittenRootProject(docsDir: DocsDir, exclude: readonly string[]): Promise<string | null> {\n let text: string;\n try {\n text = await readFile(rootProjectPath(docsDir), \"utf8\");\n } catch {\n // Unreadable is not \"excludes nothing\": the caller reports it and writes\n // nothing at all.\n return null;\n }\n // The SAME parse the grader read the list with — `parseRootProject`, which\n // tolerates the byte-order mark PowerShell's `Out-File` writes. Two parses\n // would mean a run that read an `exclude` here and then declared the file\n // unreadable at the write, which is exactly what a BOM produced before\n // (re-verification 2026-09-04, area C item 3). Re-read rather than carried:\n // the point of this read is that it happens immediately before the swap.\n const parsed = parseRootProject(text);\n if (parsed === null) return null;\n return `${JSON.stringify({ ...parsed, exclude: [...exclude] }, null, 2)}\\n`;\n}\n"]}