@ybotok/loam 0.2.0-alpha.1 → 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 (901) hide show
  1. package/CHANGELOG.md +3448 -0
  2. package/COMPARISON.md +91 -3
  3. package/CONTRIBUTING.md +37 -0
  4. package/MIGRATING-from-OpenSpec.md +47 -23
  5. package/QUICKSTART.md +189 -12
  6. package/README.md +274 -65
  7. package/ROADMAP.md +572 -31
  8. package/SCHEMA.md +1709 -155
  9. package/WORKFLOW.md +298 -72
  10. package/dist/cli.js +26 -8
  11. package/dist/cli.js.map +1 -1
  12. package/dist/commands/adopt/adopt.js +5 -10
  13. package/dist/commands/adopt/adopt.js.map +1 -1
  14. package/dist/commands/adopt/render.js +50 -9
  15. package/dist/commands/adopt/render.js.map +1 -1
  16. package/dist/commands/archive/archive.js +16 -19
  17. package/dist/commands/archive/archive.js.map +1 -1
  18. package/dist/commands/archive/closing.js +42 -0
  19. package/dist/commands/archive/closing.js.map +1 -0
  20. package/dist/commands/archive/plan/contracts/asyncapi.js +36 -42
  21. package/dist/commands/archive/plan/contracts/asyncapi.js.map +1 -1
  22. package/dist/commands/archive/plan/contracts/consumers.js +56 -0
  23. package/dist/commands/archive/plan/contracts/consumers.js.map +1 -0
  24. package/dist/commands/archive/plan/contracts/openapi.js +77 -43
  25. package/dist/commands/archive/plan/contracts/openapi.js.map +1 -1
  26. package/dist/commands/archive/plan/contracts/verdict-lines.js +103 -0
  27. package/dist/commands/archive/plan/contracts/verdict-lines.js.map +1 -0
  28. package/dist/commands/archive/plan/document/head.js +151 -0
  29. package/dist/commands/archive/plan/document/head.js.map +1 -0
  30. package/dist/commands/archive/plan/document/links.js +284 -0
  31. package/dist/commands/archive/plan/document/links.js.map +1 -0
  32. package/dist/commands/archive/plan/document/run.js +136 -0
  33. package/dist/commands/archive/plan/document/run.js.map +1 -0
  34. package/dist/commands/archive/plan/gate.js +21 -19
  35. package/dist/commands/archive/plan/gate.js.map +1 -1
  36. package/dist/commands/archive/plan/landscape.js +167 -30
  37. package/dist/commands/archive/plan/landscape.js.map +1 -1
  38. package/dist/commands/archive/plan/model/extending.js +85 -0
  39. package/dist/commands/archive/plan/model/extending.js.map +1 -0
  40. package/dist/commands/archive/plan/refusal.js +14 -19
  41. package/dist/commands/archive/plan/refusal.js.map +1 -1
  42. package/dist/commands/archive/plan/specs.js +137 -56
  43. package/dist/commands/archive/plan/specs.js.map +1 -1
  44. package/dist/commands/archive/plan/state.js +3 -0
  45. package/dist/commands/archive/plan/state.js.map +1 -1
  46. package/dist/commands/archive/run.js +134 -30
  47. package/dist/commands/archive/run.js.map +1 -1
  48. package/dist/commands/archive/shipped.js +49 -0
  49. package/dist/commands/archive/shipped.js.map +1 -0
  50. package/dist/commands/context/context.js +85 -18
  51. package/dist/commands/context/context.js.map +1 -1
  52. package/dist/commands/context/print.js +29 -7
  53. package/dist/commands/context/print.js.map +1 -1
  54. package/dist/commands/delta/delta.js +102 -14
  55. package/dist/commands/delta/delta.js.map +1 -1
  56. package/dist/commands/delta/print.js +17 -1
  57. package/dist/commands/delta/print.js.map +1 -1
  58. package/dist/commands/dependencies.js +3 -7
  59. package/dist/commands/dependencies.js.map +1 -1
  60. package/dist/commands/diff/diff.js +20 -27
  61. package/dist/commands/diff/diff.js.map +1 -1
  62. package/dist/commands/doctor.js +60 -1
  63. package/dist/commands/doctor.js.map +1 -1
  64. package/dist/commands/explain/explain.js +89 -13
  65. package/dist/commands/explain/explain.js.map +1 -1
  66. package/dist/commands/explore.js +16 -10
  67. package/dist/commands/explore.js.map +1 -1
  68. package/dist/commands/gate/gate.js +45 -8
  69. package/dist/commands/gate/gate.js.map +1 -1
  70. package/dist/commands/gate/print.js +15 -3
  71. package/dist/commands/gate/print.js.map +1 -1
  72. package/dist/commands/gherkin/commit.js +13 -54
  73. package/dist/commands/gherkin/commit.js.map +1 -1
  74. package/dist/commands/gherkin/gherkin.js +36 -20
  75. package/dist/commands/gherkin/gherkin.js.map +1 -1
  76. package/dist/commands/gherkin/reconcile.js +10 -13
  77. package/dist/commands/gherkin/reconcile.js.map +1 -1
  78. package/dist/commands/init/first-hour.js +44 -0
  79. package/dist/commands/init/first-hour.js.map +1 -1
  80. package/dist/commands/init/init.js +18 -22
  81. package/dist/commands/init/init.js.map +1 -1
  82. package/dist/commands/list/campaign/campaign.js +4 -6
  83. package/dist/commands/list/campaign/campaign.js.map +1 -1
  84. package/dist/commands/list/json.js +5 -7
  85. package/dist/commands/list/json.js.map +1 -1
  86. package/dist/commands/list/list.js +44 -29
  87. package/dist/commands/list/list.js.map +1 -1
  88. package/dist/commands/list/print.js +52 -9
  89. package/dist/commands/list/print.js.map +1 -1
  90. package/dist/commands/list/suites/suites.js +140 -0
  91. package/dist/commands/list/suites/suites.js.map +1 -0
  92. package/dist/commands/list/views.js +37 -34
  93. package/dist/commands/list/views.js.map +1 -1
  94. package/dist/commands/mcp/dispatch.js +91 -36
  95. package/dist/commands/mcp/dispatch.js.map +1 -1
  96. package/dist/commands/mcp/mcp.js +56 -15
  97. package/dist/commands/mcp/mcp.js.map +1 -1
  98. package/dist/commands/mcp/serve.js.map +1 -1
  99. package/dist/commands/migrate-openspec/materialize/active.js +27 -22
  100. package/dist/commands/migrate-openspec/materialize/active.js.map +1 -1
  101. package/dist/commands/migrate-openspec/materialize/stage.js +4 -3
  102. package/dist/commands/migrate-openspec/materialize/stage.js.map +1 -1
  103. package/dist/commands/migrate-openspec/materialize/target.js +2 -2
  104. package/dist/commands/migrate-openspec/materialize/target.js.map +1 -1
  105. package/dist/commands/migrate-openspec/openspec/decisions.js +9 -14
  106. package/dist/commands/migrate-openspec/openspec/decisions.js.map +1 -1
  107. package/dist/commands/migrate-openspec/openspec/error.js +7 -8
  108. package/dist/commands/migrate-openspec/openspec/error.js.map +1 -1
  109. package/dist/commands/migrate-openspec/openspec/mapping.js +1 -9
  110. package/dist/commands/migrate-openspec/openspec/mapping.js.map +1 -1
  111. package/dist/commands/migrate-openspec/openspec/paths.js +3 -6
  112. package/dist/commands/migrate-openspec/openspec/paths.js.map +1 -1
  113. package/dist/commands/new/capability-template.js +118 -0
  114. package/dist/commands/new/capability-template.js.map +1 -0
  115. package/dist/commands/new/commit.js +8 -22
  116. package/dist/commands/new/commit.js.map +1 -1
  117. package/dist/commands/new/modifies.js +206 -0
  118. package/dist/commands/new/modifies.js.map +1 -0
  119. package/dist/commands/new/new.js +59 -14
  120. package/dist/commands/new/new.js.map +1 -1
  121. package/dist/commands/new/templates.js +48 -124
  122. package/dist/commands/new/templates.js.map +1 -1
  123. package/dist/commands/open.js +3 -7
  124. package/dist/commands/open.js.map +1 -1
  125. package/dist/commands/policy/gate.js +27 -0
  126. package/dist/commands/policy/gate.js.map +1 -1
  127. package/dist/commands/rebase/plan.js +2 -2
  128. package/dist/commands/rebase/plan.js.map +1 -1
  129. package/dist/commands/rebase/rebase.js +60 -35
  130. package/dist/commands/rebase/rebase.js.map +1 -1
  131. package/dist/commands/seed/commit.js +55 -26
  132. package/dist/commands/seed/commit.js.map +1 -1
  133. package/dist/commands/seed/plan.js +158 -13
  134. package/dist/commands/seed/plan.js.map +1 -1
  135. package/dist/commands/seed/seed.js +13 -11
  136. package/dist/commands/seed/seed.js.map +1 -1
  137. package/dist/commands/show/feature.js +9 -5
  138. package/dist/commands/show/feature.js.map +1 -1
  139. package/dist/commands/show/introduced.js +157 -0
  140. package/dist/commands/show/introduced.js.map +1 -0
  141. package/dist/commands/show/marks.js +35 -6
  142. package/dist/commands/show/marks.js.map +1 -1
  143. package/dist/commands/show/service.js +41 -33
  144. package/dist/commands/show/service.js.map +1 -1
  145. package/dist/commands/show/show.js +17 -7
  146. package/dist/commands/show/show.js.map +1 -1
  147. package/dist/commands/status/fleet-next.js +90 -0
  148. package/dist/commands/status/fleet-next.js.map +1 -0
  149. package/dist/commands/status/json.js +2 -0
  150. package/dist/commands/status/json.js.map +1 -1
  151. package/dist/commands/status/print.js +89 -37
  152. package/dist/commands/status/print.js.map +1 -1
  153. package/dist/commands/status/status.js +3 -7
  154. package/dist/commands/status/status.js.map +1 -1
  155. package/dist/commands/steps/steps.js +103 -23
  156. package/dist/commands/steps/steps.js.map +1 -1
  157. package/dist/commands/subsystem/edit.js +7 -7
  158. package/dist/commands/subsystem/edit.js.map +1 -1
  159. package/dist/commands/subsystem/move.js +106 -46
  160. package/dist/commands/subsystem/move.js.map +1 -1
  161. package/dist/commands/subsystem/query.js +2 -4
  162. package/dist/commands/subsystem/query.js.map +1 -1
  163. package/dist/commands/subsystem/subsystem.js +4 -7
  164. package/dist/commands/subsystem/subsystem.js.map +1 -1
  165. package/dist/commands/subsystem/sync.js +289 -74
  166. package/dist/commands/subsystem/sync.js.map +1 -1
  167. package/dist/commands/subsystem/txn/exclude.js +132 -0
  168. package/dist/commands/subsystem/txn/exclude.js.map +1 -0
  169. package/dist/commands/subsystem/txn/links.js +128 -0
  170. package/dist/commands/subsystem/txn/links.js.map +1 -0
  171. package/dist/commands/subsystem/txn/report.js +174 -0
  172. package/dist/commands/subsystem/txn/report.js.map +1 -0
  173. package/dist/commands/subsystem/txn/txn.js +147 -45
  174. package/dist/commands/subsystem/txn/txn.js.map +1 -1
  175. package/dist/commands/subsystem/txn/views.js +200 -21
  176. package/dist/commands/subsystem/txn/views.js.map +1 -1
  177. package/dist/commands/tasks/actions.js +107 -0
  178. package/dist/commands/tasks/actions.js.map +1 -0
  179. package/dist/commands/tasks/render.js +253 -0
  180. package/dist/commands/tasks/render.js.map +1 -0
  181. package/dist/commands/tasks/tasks.js +119 -0
  182. package/dist/commands/tasks/tasks.js.map +1 -0
  183. package/dist/commands/unarchive/manifest.js +42 -26
  184. package/dist/commands/unarchive/manifest.js.map +1 -1
  185. package/dist/commands/unarchive/restore.js +83 -33
  186. package/dist/commands/unarchive/restore.js.map +1 -1
  187. package/dist/commands/unarchive/unarchive.js +22 -30
  188. package/dist/commands/unarchive/unarchive.js.map +1 -1
  189. package/dist/commands/validate/arch-coverage.js +78 -27
  190. package/dist/commands/validate/arch-coverage.js.map +1 -1
  191. package/dist/commands/validate/checks/fleet-shape.js +34 -126
  192. package/dist/commands/validate/checks/fleet-shape.js.map +1 -1
  193. package/dist/commands/validate/checks/health-deps.js +9 -6
  194. package/dist/commands/validate/checks/health-deps.js.map +1 -1
  195. package/dist/commands/validate/checks/introduced.js +102 -0
  196. package/dist/commands/validate/checks/introduced.js.map +1 -0
  197. package/dist/commands/validate/checks/requirements.js +18 -8
  198. package/dist/commands/validate/checks/requirements.js.map +1 -1
  199. package/dist/commands/validate/checks/sources.js +11 -2
  200. package/dist/commands/validate/checks/sources.js.map +1 -1
  201. package/dist/commands/validate/coverage/covers-after.js +105 -0
  202. package/dist/commands/validate/coverage/covers-after.js.map +1 -0
  203. package/dist/commands/validate/feature.js +26 -20
  204. package/dist/commands/validate/feature.js.map +1 -1
  205. package/dist/commands/validate/fleet/census.js +37 -13
  206. package/dist/commands/validate/fleet/census.js.map +1 -1
  207. package/dist/commands/validate/fleet/landscape.js +144 -126
  208. package/dist/commands/validate/fleet/landscape.js.map +1 -1
  209. package/dist/commands/validate/fleet/load.js +66 -0
  210. package/dist/commands/validate/fleet/load.js.map +1 -1
  211. package/dist/commands/validate/fleet/map/attest.js +98 -0
  212. package/dist/commands/validate/fleet/map/attest.js.map +1 -0
  213. package/dist/commands/validate/fleet/map/bindings.js +107 -0
  214. package/dist/commands/validate/fleet/map/bindings.js.map +1 -0
  215. package/dist/commands/validate/fleet/map/consumers.js +244 -0
  216. package/dist/commands/validate/fleet/map/consumers.js.map +1 -0
  217. package/dist/commands/validate/fleet/map/isolation.js +116 -0
  218. package/dist/commands/validate/fleet/map/isolation.js.map +1 -0
  219. package/dist/commands/validate/fleet/map/usecases.js +54 -0
  220. package/dist/commands/validate/fleet/map/usecases.js.map +1 -0
  221. package/dist/commands/validate/fleet/obligations.js +44 -14
  222. package/dist/commands/validate/fleet/obligations.js.map +1 -1
  223. package/dist/commands/validate/fleet/scorecard/print.js +10 -2
  224. package/dist/commands/validate/fleet/scorecard/print.js.map +1 -1
  225. package/dist/commands/validate/fleet/scorecard/scorecard.js +17 -11
  226. package/dist/commands/validate/fleet/scorecard/scorecard.js.map +1 -1
  227. package/dist/commands/validate/fleet/usecases/place.js.map +1 -1
  228. package/dist/commands/validate/fleet/views/fleet-project.js +217 -0
  229. package/dist/commands/validate/fleet/views/fleet-project.js.map +1 -0
  230. package/dist/commands/validate/fleet/views/ids.js +50 -15
  231. package/dist/commands/validate/fleet/views/ids.js.map +1 -1
  232. package/dist/commands/validate/fleet/views/projects.js +278 -0
  233. package/dist/commands/validate/fleet/views/projects.js.map +1 -0
  234. package/dist/commands/validate/fleet/views/root-documents.js +83 -0
  235. package/dist/commands/validate/fleet/views/root-documents.js.map +1 -0
  236. package/dist/commands/validate/fleet/views/stale.js +40 -47
  237. package/dist/commands/validate/fleet/views/stale.js.map +1 -1
  238. package/dist/commands/validate/links/corpus.js +1 -4
  239. package/dist/commands/validate/links/corpus.js.map +1 -1
  240. package/dist/commands/validate/links/glossary.js.map +1 -1
  241. package/dist/commands/validate/render/repeats.js +63 -0
  242. package/dist/commands/validate/render/repeats.js.map +1 -0
  243. package/dist/commands/validate/render/rollups.js +115 -0
  244. package/dist/commands/validate/render/rollups.js.map +1 -0
  245. package/dist/commands/validate/render/text.js +199 -0
  246. package/dist/commands/validate/render/text.js.map +1 -0
  247. package/dist/commands/validate/report.js +36 -160
  248. package/dist/commands/validate/report.js.map +1 -1
  249. package/dist/commands/validate/scope.js +113 -0
  250. package/dist/commands/validate/scope.js.map +1 -0
  251. package/dist/commands/validate/service/api.js +21 -107
  252. package/dist/commands/validate/service/api.js.map +1 -1
  253. package/dist/commands/validate/service/contracts/generated.js +134 -0
  254. package/dist/commands/validate/service/contracts/generated.js.map +1 -0
  255. package/dist/commands/validate/service/events/events.js +36 -14
  256. package/dist/commands/validate/service/events/events.js.map +1 -1
  257. package/dist/commands/validate/service/events/message-producers.js +1 -1
  258. package/dist/commands/validate/service/events/message-producers.js.map +1 -1
  259. package/dist/commands/validate/service/evidence-pins.js +56 -10
  260. package/dist/commands/validate/service/evidence-pins.js.map +1 -1
  261. package/dist/commands/validate/service/model/diverged.js +226 -0
  262. package/dist/commands/validate/service/model/diverged.js.map +1 -0
  263. package/dist/commands/validate/service/model/grade.js +163 -0
  264. package/dist/commands/validate/service/model/grade.js.map +1 -0
  265. package/dist/commands/validate/service/service.js +121 -61
  266. package/dist/commands/validate/service/service.js.map +1 -1
  267. package/dist/commands/validate/service/specs.js +88 -28
  268. package/dist/commands/validate/service/specs.js.map +1 -1
  269. package/dist/commands/validate/service/spine.js +38 -3
  270. package/dist/commands/validate/service/spine.js.map +1 -1
  271. package/dist/commands/validate/service/usecases/tags.js +113 -0
  272. package/dist/commands/validate/service/usecases/tags.js.map +1 -0
  273. package/dist/commands/validate/service/usecases/usecases.js +209 -0
  274. package/dist/commands/validate/service/usecases/usecases.js.map +1 -0
  275. package/dist/commands/validate/validate.js +85 -60
  276. package/dist/commands/validate/validate.js.map +1 -1
  277. package/dist/commands/verify/cross/diff.js +2 -6
  278. package/dist/commands/verify/cross/diff.js.map +1 -1
  279. package/dist/commands/verify/evidence/contract.js +1 -1
  280. package/dist/commands/verify/evidence/contract.js.map +1 -1
  281. package/dist/commands/verify/evidence/read.js +12 -3
  282. package/dist/commands/verify/evidence/read.js.map +1 -1
  283. package/dist/commands/verify/frozen.js +45 -23
  284. package/dist/commands/verify/frozen.js.map +1 -1
  285. package/dist/commands/verify/record.js +69 -17
  286. package/dist/commands/verify/record.js.map +1 -1
  287. package/dist/commands/verify/report.js +27 -44
  288. package/dist/commands/verify/report.js.map +1 -1
  289. package/dist/commands/verify/results.js +112 -30
  290. package/dist/commands/verify/results.js.map +1 -1
  291. package/dist/commands/verify/verify.js +55 -52
  292. package/dist/commands/verify/verify.js.map +1 -1
  293. package/dist/commands/vouch/pack/pack.js +2 -2
  294. package/dist/commands/vouch/pack/pack.js.map +1 -1
  295. package/dist/commands/vouch/pack/print.js +1 -6
  296. package/dist/commands/vouch/pack/print.js.map +1 -1
  297. package/dist/commands/vouch/pack/sections.js +1 -2
  298. package/dist/commands/vouch/pack/sections.js.map +1 -1
  299. package/dist/commands/vouch/run.js +26 -81
  300. package/dist/commands/vouch/run.js.map +1 -1
  301. package/dist/commands/vouch/sample/plan.js +20 -34
  302. package/dist/commands/vouch/sample/plan.js.map +1 -1
  303. package/dist/commands/vouch/vet/verify.js +39 -7
  304. package/dist/commands/vouch/vet/verify.js.map +1 -1
  305. package/dist/commands/vouch/vouch.js +10 -17
  306. package/dist/commands/vouch/vouch.js.map +1 -1
  307. package/dist/core/agent/agents-md/command-map.js +81 -106
  308. package/dist/core/agent/agents-md/command-map.js.map +1 -1
  309. package/dist/core/agent/agents-md/map/explain.js +21 -9
  310. package/dist/core/agent/agents-md/map/explain.js.map +1 -1
  311. package/dist/core/agent/agents-md/map/lenses/context.js +17 -8
  312. package/dist/core/agent/agents-md/map/lenses/context.js.map +1 -1
  313. package/dist/core/agent/agents-md/map/lenses/diff.js +33 -20
  314. package/dist/core/agent/agents-md/map/lenses/diff.js.map +1 -1
  315. package/dist/core/agent/agents-md/map/lenses/gate.js +13 -5
  316. package/dist/core/agent/agents-md/map/lenses/gate.js.map +1 -1
  317. package/dist/core/agent/agents-md/map/mcp.js +10 -7
  318. package/dist/core/agent/agents-md/map/mcp.js.map +1 -1
  319. package/dist/core/agent/agents-md/map/status.js +24 -8
  320. package/dist/core/agent/agents-md/map/status.js.map +1 -1
  321. package/dist/core/agent/agents-md/map/subsystem.js +80 -8
  322. package/dist/core/agent/agents-md/map/subsystem.js.map +1 -1
  323. package/dist/core/agent/agents-md/map/usecases.js +88 -10
  324. package/dist/core/agent/agents-md/map/usecases.js.map +1 -1
  325. package/dist/core/agent/agents-md/refusals.js +49 -22
  326. package/dist/core/agent/agents-md/refusals.js.map +1 -1
  327. package/dist/core/agent/agents-md.js +39 -6
  328. package/dist/core/agent/agents-md.js.map +1 -1
  329. package/dist/core/agent/agents-stamp.js +10 -0
  330. package/dist/core/agent/agents-stamp.js.map +1 -1
  331. package/dist/core/agent/protocol.js +1 -1
  332. package/dist/core/agent/protocol.js.map +1 -1
  333. package/dist/core/agent/scaffold.js +10 -15
  334. package/dist/core/agent/scaffold.js.map +1 -1
  335. package/dist/core/agent/support/report.js +46 -5
  336. package/dist/core/agent/support/report.js.map +1 -1
  337. package/dist/core/agent/tools/dialects.js +1 -0
  338. package/dist/core/agent/tools/dialects.js.map +1 -1
  339. package/dist/core/agent/tools/registry.js +41 -76
  340. package/dist/core/agent/tools/registry.js.map +1 -1
  341. package/dist/core/agent/workflows/adopt.js +158 -11
  342. package/dist/core/agent/workflows/adopt.js.map +1 -1
  343. package/dist/core/agent/workflows/check.js +78 -39
  344. package/dist/core/agent/workflows/check.js.map +1 -1
  345. package/dist/core/agent/workflows/closing.js +88 -27
  346. package/dist/core/agent/workflows/closing.js.map +1 -1
  347. package/dist/core/agent/workflows/feature.js +128 -13
  348. package/dist/core/agent/workflows/feature.js.map +1 -1
  349. package/dist/core/agent/workflows/implement.js +96 -13
  350. package/dist/core/agent/workflows/implement.js.map +1 -1
  351. package/dist/core/agent/workflows/reference/authoring.js +106 -4
  352. package/dist/core/agent/workflows/reference/authoring.js.map +1 -1
  353. package/dist/core/agent/workflows/reference/codes.js +8 -6
  354. package/dist/core/agent/workflows/reference/codes.js.map +1 -1
  355. package/dist/core/agent/workflows/reference/done-check.js +37 -15
  356. package/dist/core/agent/workflows/reference/done-check.js.map +1 -1
  357. package/dist/core/agent/workflows/reference/drawing/drawing.js +253 -0
  358. package/dist/core/agent/workflows/reference/drawing/drawing.js.map +1 -0
  359. package/dist/core/agent/workflows/reference/reference.js +6 -3
  360. package/dist/core/agent/workflows/reference/reference.js.map +1 -1
  361. package/dist/core/agent/workflows/reference/spine.js +68 -27
  362. package/dist/core/agent/workflows/reference/spine.js.map +1 -1
  363. package/dist/core/asyncapi/baseline/plan.js +14 -81
  364. package/dist/core/asyncapi/baseline/plan.js.map +1 -1
  365. package/dist/core/asyncapi/digest.js +30 -25
  366. package/dist/core/asyncapi/digest.js.map +1 -1
  367. package/dist/core/asyncapi/merge/components.js +5 -4
  368. package/dist/core/asyncapi/merge/components.js.map +1 -1
  369. package/dist/core/asyncapi/merge/error.js +7 -2
  370. package/dist/core/asyncapi/merge/error.js.map +1 -1
  371. package/dist/core/asyncapi/merge/markers.js +32 -50
  372. package/dist/core/asyncapi/merge/markers.js.map +1 -1
  373. package/dist/core/asyncapi/merge/merge.js +33 -53
  374. package/dist/core/asyncapi/merge/merge.js.map +1 -1
  375. package/dist/core/asyncapi/merge/pin.js +12 -36
  376. package/dist/core/asyncapi/merge/pin.js.map +1 -1
  377. package/dist/core/asyncapi/model.js.map +1 -1
  378. package/dist/core/asyncapi/read.js +36 -12
  379. package/dist/core/asyncapi/read.js.map +1 -1
  380. package/dist/core/brief/brief.js +96 -36
  381. package/dist/core/brief/brief.js.map +1 -1
  382. package/dist/core/brief/checks.js +138 -3
  383. package/dist/core/brief/checks.js.map +1 -1
  384. package/dist/core/brief/landscape.js +209 -130
  385. package/dist/core/brief/landscape.js.map +1 -1
  386. package/dist/core/brief/map/extend.js +84 -0
  387. package/dist/core/brief/map/extend.js.map +1 -0
  388. package/dist/core/brief/map/owed.js +266 -0
  389. package/dist/core/brief/map/owed.js.map +1 -0
  390. package/dist/core/brief/targets.js +109 -31
  391. package/dist/core/brief/targets.js.map +1 -1
  392. package/dist/core/brief/unchecked.js +14 -3
  393. package/dist/core/brief/unchecked.js.map +1 -1
  394. package/dist/core/c4/arch.js +90 -182
  395. package/dist/core/c4/arch.js.map +1 -1
  396. package/dist/core/c4/direction/direction.js +114 -0
  397. package/dist/core/c4/direction/direction.js.map +1 -0
  398. package/dist/core/c4/likec4.js +169 -14
  399. package/dist/core/c4/likec4.js.map +1 -1
  400. package/dist/core/c4/locate/unlocated.js +150 -0
  401. package/dist/core/c4/locate/unlocated.js.map +1 -0
  402. package/dist/core/c4/parsed/deployment.js +160 -0
  403. package/dist/core/c4/parsed/deployment.js.map +1 -0
  404. package/dist/core/c4/parsed/dynamic-views.js.map +1 -1
  405. package/dist/core/c4/parsed/values.js +54 -1
  406. package/dist/core/c4/parsed/values.js.map +1 -1
  407. package/dist/core/c4/parsed/view-ids.js +39 -1
  408. package/dist/core/c4/parsed/view-ids.js.map +1 -1
  409. package/dist/core/c4/prefetch/fleet.js +134 -0
  410. package/dist/core/c4/prefetch/fleet.js.map +1 -0
  411. package/dist/core/c4/project/architecture.js +123 -7
  412. package/dist/core/c4/project/architecture.js.map +1 -1
  413. package/dist/core/c4/project/batch.js +140 -0
  414. package/dist/core/c4/project/batch.js.map +1 -0
  415. package/dist/core/c4/project/documents.js +43 -12
  416. package/dist/core/c4/project/documents.js.map +1 -1
  417. package/dist/core/c4/project/load.js +79 -43
  418. package/dist/core/c4/project/load.js.map +1 -1
  419. package/dist/core/c4/project/staged.js +277 -0
  420. package/dist/core/c4/project/staged.js.map +1 -0
  421. package/dist/core/c4/resolve/attested.js +0 -0
  422. package/dist/core/c4/resolve/attested.js.map +1 -0
  423. package/dist/core/c4/resolve/external.js +51 -0
  424. package/dist/core/c4/resolve/external.js.map +1 -0
  425. package/dist/core/c4/resolve/service.js +78 -17
  426. package/dist/core/c4/resolve/service.js.map +1 -1
  427. package/dist/core/c4/resolve/steps.js +290 -0
  428. package/dist/core/c4/resolve/steps.js.map +1 -0
  429. package/dist/core/c4/resolve/systems.js +154 -0
  430. package/dist/core/c4/resolve/systems.js.map +1 -0
  431. package/dist/core/c4/root-project/exclude.js +352 -0
  432. package/dist/core/c4/root-project/exclude.js.map +1 -0
  433. package/dist/core/c4/seed/template.js +65 -1
  434. package/dist/core/c4/seed/template.js.map +1 -1
  435. package/dist/core/c4/service-model/created/models.js +96 -0
  436. package/dist/core/c4/service-model/created/models.js.map +1 -0
  437. package/dist/core/c4/service-model/documents.js +47 -0
  438. package/dist/core/c4/service-model/documents.js.map +1 -0
  439. package/dist/core/c4/service-model/fleet/extending.js +82 -0
  440. package/dist/core/c4/service-model/fleet/extending.js.map +1 -0
  441. package/dist/core/c4/service-model/load.js +165 -0
  442. package/dist/core/c4/service-model/load.js.map +1 -0
  443. package/dist/core/c4/service-model/renderer.js +128 -0
  444. package/dist/core/c4/service-model/renderer.js.map +1 -0
  445. package/dist/core/c4/service-model/shape.js +106 -0
  446. package/dist/core/c4/service-model/shape.js.map +1 -0
  447. package/dist/core/c4/service-model/slice.js +188 -0
  448. package/dist/core/c4/service-model/slice.js.map +1 -0
  449. package/dist/core/c4/source-mask.js +297 -10
  450. package/dist/core/c4/source-mask.js.map +1 -1
  451. package/dist/core/c4/source-scan.js +222 -141
  452. package/dist/core/c4/source-scan.js.map +1 -1
  453. package/dist/core/c4/splice/authored-source.js +79 -13
  454. package/dist/core/c4/splice/authored-source.js.map +1 -1
  455. package/dist/core/c4/splice/contract.js +20 -0
  456. package/dist/core/c4/splice/contract.js.map +1 -1
  457. package/dist/core/c4/splice/delta-blocks.js +20 -20
  458. package/dist/core/c4/splice/delta-blocks.js.map +1 -1
  459. package/dist/core/c4/splice/identity/declared.js +87 -0
  460. package/dist/core/c4/splice/identity/declared.js.map +1 -0
  461. package/dist/core/c4/splice/identity/edges.js +37 -0
  462. package/dist/core/c4/splice/identity/edges.js.map +1 -1
  463. package/dist/core/c4/splice/identity/existing.js +80 -0
  464. package/dist/core/c4/splice/identity/existing.js.map +1 -0
  465. package/dist/core/c4/splice/identity/interior.js +80 -0
  466. package/dist/core/c4/splice/identity/interior.js.map +1 -0
  467. package/dist/core/c4/splice/identity/owner.js +50 -0
  468. package/dist/core/c4/splice/identity/owner.js.map +1 -0
  469. package/dist/core/c4/splice/landscape-merge.js +182 -114
  470. package/dist/core/c4/splice/landscape-merge.js.map +1 -1
  471. package/dist/core/c4/splice/model/merge.js +151 -0
  472. package/dist/core/c4/splice/model/merge.js.map +1 -0
  473. package/dist/core/c4/splice/placement.js +160 -56
  474. package/dist/core/c4/splice/placement.js.map +1 -1
  475. package/dist/core/c4/splice/text/spot.js +131 -0
  476. package/dist/core/c4/splice/text/spot.js.map +1 -0
  477. package/dist/core/c4/workspace.js +13 -19
  478. package/dist/core/c4/workspace.js.map +1 -1
  479. package/dist/core/capabilities/capabilities.js +6 -6
  480. package/dist/core/capabilities/capabilities.js.map +1 -1
  481. package/dist/core/capabilities/delta/doc.js +7 -10
  482. package/dist/core/capabilities/delta/doc.js.map +1 -1
  483. package/dist/core/capabilities/delta/uncovered.js +2 -2
  484. package/dist/core/capabilities/delta/uncovered.js.map +1 -1
  485. package/dist/core/capabilities/findings.js +18 -22
  486. package/dist/core/capabilities/findings.js.map +1 -1
  487. package/dist/core/capabilities/realizes/findings.js +12 -19
  488. package/dist/core/capabilities/realizes/findings.js.map +1 -1
  489. package/dist/core/capabilities/realizes/join.js +0 -20
  490. package/dist/core/capabilities/realizes/join.js.map +1 -1
  491. package/dist/core/capabilities/rollup.js +6 -0
  492. package/dist/core/capabilities/rollup.js.map +1 -1
  493. package/dist/core/capabilities/tree.js +6 -28
  494. package/dist/core/capabilities/tree.js.map +1 -1
  495. package/dist/core/capabilities/usecase-join.js +3 -13
  496. package/dist/core/capabilities/usecase-join.js.map +1 -1
  497. package/dist/core/coherence/authoring/scaffold.js +11 -3
  498. package/dist/core/coherence/authoring/scaffold.js.map +1 -1
  499. package/dist/core/coherence/authoring/sentinels.js +2 -1
  500. package/dist/core/coherence/authoring/sentinels.js.map +1 -1
  501. package/dist/core/coherence/calls/called.js +52 -0
  502. package/dist/core/coherence/calls/called.js.map +1 -0
  503. package/dist/core/coherence/coherence.js +103 -22
  504. package/dist/core/coherence/coherence.js.map +1 -1
  505. package/dist/core/coherence/consumed/operations.js +70 -0
  506. package/dist/core/coherence/consumed/operations.js.map +1 -0
  507. package/dist/core/coherence/consumed/refusal.js +38 -0
  508. package/dist/core/coherence/consumed/refusal.js.map +1 -0
  509. package/dist/core/coherence/covers/health.js +85 -0
  510. package/dist/core/coherence/covers/health.js.map +1 -0
  511. package/dist/core/coherence/declared.js +60 -34
  512. package/dist/core/coherence/declared.js.map +1 -1
  513. package/dist/core/coherence/events/declared.js +44 -59
  514. package/dist/core/coherence/events/declared.js.map +1 -1
  515. package/dist/core/coherence/events/events.js +147 -16
  516. package/dist/core/coherence/events/events.js.map +1 -1
  517. package/dist/core/coherence/events/grades.js +31 -8
  518. package/dist/core/coherence/events/grades.js.map +1 -1
  519. package/dist/core/coherence/events/lookups.js +28 -87
  520. package/dist/core/coherence/events/lookups.js.map +1 -1
  521. package/dist/core/coherence/events/produced.js +100 -0
  522. package/dist/core/coherence/events/produced.js.map +1 -0
  523. package/dist/core/coherence/lookups.js +18 -78
  524. package/dist/core/coherence/lookups.js.map +1 -1
  525. package/dist/core/coherence/retired/archived.js +285 -0
  526. package/dist/core/coherence/retired/archived.js.map +1 -0
  527. package/dist/core/coherence/retired/event-pair.js +62 -0
  528. package/dist/core/coherence/retired/event-pair.js.map +1 -0
  529. package/dist/core/coherence/retired/merged.js +79 -0
  530. package/dist/core/coherence/retired/merged.js.map +1 -0
  531. package/dist/core/coherence/retired/retirement.js +49 -0
  532. package/dist/core/coherence/retired/retirement.js.map +1 -0
  533. package/dist/core/coherence/retired/revival/arrivals.js +131 -0
  534. package/dist/core/coherence/retired/revival/arrivals.js.map +1 -0
  535. package/dist/core/coherence/retired/revival/revived.js +297 -0
  536. package/dist/core/coherence/retired/revival/revived.js.map +1 -0
  537. package/dist/core/consumers/after.js +113 -0
  538. package/dist/core/consumers/after.js.map +1 -0
  539. package/dist/core/consumers/consumers.js +296 -0
  540. package/dist/core/consumers/consumers.js.map +1 -0
  541. package/dist/core/consumers/current.js +211 -0
  542. package/dist/core/consumers/current.js.map +1 -0
  543. package/dist/core/consumers/scan.js +46 -0
  544. package/dist/core/consumers/scan.js.map +1 -0
  545. package/dist/core/consumers/state.js +27 -0
  546. package/dist/core/consumers/state.js.map +1 -0
  547. package/dist/core/delta/delta.js +51 -6
  548. package/dist/core/delta/delta.js.map +1 -1
  549. package/dist/core/dependencies/fanin.js +2 -2
  550. package/dist/core/dependencies/fanin.js.map +1 -1
  551. package/dist/core/deployment/delta.js +191 -0
  552. package/dist/core/deployment/delta.js.map +1 -0
  553. package/dist/core/deployment/objects.js +145 -0
  554. package/dist/core/deployment/objects.js.map +1 -0
  555. package/dist/core/diff/base-git.js +94 -12
  556. package/dist/core/diff/base-git.js.map +1 -1
  557. package/dist/core/diff/base-state.js +49 -21
  558. package/dist/core/diff/base-state.js.map +1 -1
  559. package/dist/core/diff/joins.js +136 -0
  560. package/dist/core/diff/joins.js.map +1 -0
  561. package/dist/core/diff/scope/changed-paths.js +22 -6
  562. package/dist/core/diff/scope/changed-paths.js.map +1 -1
  563. package/dist/core/diff/scope/edges.js +82 -0
  564. package/dist/core/diff/scope/edges.js.map +1 -0
  565. package/dist/core/diff/semantic.js +100 -31
  566. package/dist/core/diff/semantic.js.map +1 -1
  567. package/dist/core/docs.js +31 -22
  568. package/dist/core/docs.js.map +1 -1
  569. package/dist/core/doctor/agents.js +34 -18
  570. package/dist/core/doctor/agents.js.map +1 -1
  571. package/dist/core/doctor/config.js +7 -3
  572. package/dist/core/doctor/config.js.map +1 -1
  573. package/dist/core/doctor/doctor.js +91 -11
  574. package/dist/core/doctor/doctor.js.map +1 -1
  575. package/dist/core/doctor/report.js.map +1 -1
  576. package/dist/core/doctor/reports/scan.js +242 -0
  577. package/dist/core/doctor/reports/scan.js.map +1 -0
  578. package/dist/core/document/apply.js +158 -11
  579. package/dist/core/document/apply.js.map +1 -1
  580. package/dist/core/document/frontmatter.js +55 -0
  581. package/dist/core/document/frontmatter.js.map +1 -1
  582. package/dist/core/document/parse.js +29 -6
  583. package/dist/core/document/parse.js.map +1 -1
  584. package/dist/core/document/scenarios.js +17 -0
  585. package/dist/core/document/scenarios.js.map +1 -1
  586. package/dist/core/document/spec.js +4 -11
  587. package/dist/core/document/spec.js.map +1 -1
  588. package/dist/core/envelope/config.js +10 -0
  589. package/dist/core/envelope/config.js.map +1 -1
  590. package/dist/core/envelope/json.js +34 -0
  591. package/dist/core/envelope/json.js.map +1 -1
  592. package/dist/core/explain/families.js +26 -21
  593. package/dist/core/explain/families.js.map +1 -1
  594. package/dist/core/explain/lookup.js +14 -1
  595. package/dist/core/explain/lookup.js.map +1 -1
  596. package/dist/core/explain/refusals.js +5 -5
  597. package/dist/core/explain/refusals.js.map +1 -1
  598. package/dist/core/explain/terms/documents.js +227 -0
  599. package/dist/core/explain/terms/documents.js.map +1 -0
  600. package/dist/core/explain/terms/done-check.js +144 -0
  601. package/dist/core/explain/terms/done-check.js.map +1 -0
  602. package/dist/core/explain/terms/entry.js +14 -0
  603. package/dist/core/explain/terms/entry.js.map +1 -0
  604. package/dist/core/explain/terms/stages.js +71 -0
  605. package/dist/core/explain/terms/stages.js.map +1 -0
  606. package/dist/core/explain/terms/tasks.js +97 -0
  607. package/dist/core/explain/terms/tasks.js.map +1 -0
  608. package/dist/core/explain/terms.js +68 -109
  609. package/dist/core/explain/terms.js.map +1 -1
  610. package/dist/core/explore/explore.js +40 -10
  611. package/dist/core/explore/explore.js.map +1 -1
  612. package/dist/core/fleet-context.js +81 -95
  613. package/dist/core/fleet-context.js.map +1 -1
  614. package/dist/core/gate/checks.js +11 -4
  615. package/dist/core/gate/checks.js.map +1 -1
  616. package/dist/core/gate/partners.js +69 -28
  617. package/dist/core/gate/partners.js.map +1 -1
  618. package/dist/core/gate/report.js.map +1 -1
  619. package/dist/core/gate/verification.js +75 -12
  620. package/dist/core/gate/verification.js.map +1 -1
  621. package/dist/core/gherkin/stale.js +13 -37
  622. package/dist/core/gherkin/stale.js.map +1 -1
  623. package/dist/core/glossary/delta.js +10 -7
  624. package/dist/core/glossary/delta.js.map +1 -1
  625. package/dist/core/glossary/tree.js +6 -19
  626. package/dist/core/glossary/tree.js.map +1 -1
  627. package/dist/core/kernel/concurrency.js +19 -0
  628. package/dist/core/kernel/concurrency.js.map +1 -1
  629. package/dist/core/kernel/ids/fqn/ancestors.js +65 -0
  630. package/dist/core/kernel/ids/fqn/ancestors.js.map +1 -0
  631. package/dist/core/kernel/path-safety.js +38 -0
  632. package/dist/core/kernel/path-safety.js.map +1 -1
  633. package/dist/core/kernel/records.js +11 -0
  634. package/dist/core/kernel/records.js.map +1 -1
  635. package/dist/core/links/backlinks.js +1 -3
  636. package/dist/core/links/backlinks.js.map +1 -1
  637. package/dist/core/links/corpus.js +51 -37
  638. package/dist/core/links/corpus.js.map +1 -1
  639. package/dist/core/links/findings.js.map +1 -1
  640. package/dist/core/links/parse.js +38 -9
  641. package/dist/core/links/parse.js.map +1 -1
  642. package/dist/core/mcp/argv.js +101 -0
  643. package/dist/core/mcp/argv.js.map +1 -1
  644. package/dist/core/mcp/author-tools.js +2 -1
  645. package/dist/core/mcp/author-tools.js.map +1 -1
  646. package/dist/core/mcp/protocol.js +2 -2
  647. package/dist/core/mcp/protocol.js.map +1 -1
  648. package/dist/core/mcp/tools.js +43 -33
  649. package/dist/core/mcp/tools.js.map +1 -1
  650. package/dist/core/openapi/baseline/gate.js +53 -12
  651. package/dist/core/openapi/baseline/gate.js.map +1 -1
  652. package/dist/core/openapi/baseline/plan.js +40 -10
  653. package/dist/core/openapi/baseline/plan.js.map +1 -1
  654. package/dist/core/openapi/baseline/record.js +0 -1
  655. package/dist/core/openapi/baseline/record.js.map +1 -1
  656. package/dist/core/openapi/contract-text.js +33 -0
  657. package/dist/core/openapi/contract-text.js.map +1 -0
  658. package/dist/core/openapi/contract-tree.js +301 -0
  659. package/dist/core/openapi/contract-tree.js.map +1 -0
  660. package/dist/core/openapi/depth.js +38 -24
  661. package/dist/core/openapi/depth.js.map +1 -1
  662. package/dist/core/openapi/digest.js +52 -2
  663. package/dist/core/openapi/digest.js.map +1 -1
  664. package/dist/core/openapi/doc.js +12 -4
  665. package/dist/core/openapi/doc.js.map +1 -1
  666. package/dist/core/openapi/merge/components.js +25 -60
  667. package/dist/core/openapi/merge/components.js.map +1 -1
  668. package/dist/core/openapi/merge/error.js +3 -13
  669. package/dist/core/openapi/merge/error.js.map +1 -1
  670. package/dist/core/openapi/merge/markers.js +26 -30
  671. package/dist/core/openapi/merge/markers.js.map +1 -1
  672. package/dist/core/openapi/merge/merge.js +28 -52
  673. package/dist/core/openapi/merge/merge.js.map +1 -1
  674. package/dist/core/openapi/merge/pin.js +17 -35
  675. package/dist/core/openapi/merge/pin.js.map +1 -1
  676. package/dist/core/openspec/decide/verdict.js.map +1 -1
  677. package/dist/core/openspec/inventory.js +4 -5
  678. package/dist/core/openspec/inventory.js.map +1 -1
  679. package/dist/core/openspec/model/mapping.js +30 -28
  680. package/dist/core/openspec/model/mapping.js.map +1 -1
  681. package/dist/core/openspec/model/model.js +12 -7
  682. package/dist/core/openspec/model/model.js.map +1 -1
  683. package/dist/core/openspec/scan/changes.js +10 -4
  684. package/dist/core/openspec/scan/changes.js.map +1 -1
  685. package/dist/core/openspec/scan/config.js +7 -16
  686. package/dist/core/openspec/scan/config.js.map +1 -1
  687. package/dist/core/openspec/scan/shape.js +63 -19
  688. package/dist/core/openspec/scan/shape.js.map +1 -1
  689. package/dist/core/openspec/scan/walk.js +21 -38
  690. package/dist/core/openspec/scan/walk.js.map +1 -1
  691. package/dist/core/pack/living.js +43 -4
  692. package/dist/core/pack/living.js.map +1 -1
  693. package/dist/core/pack/pack.js +50 -6
  694. package/dist/core/pack/pack.js.map +1 -1
  695. package/dist/core/projection/arch-slice.js +2 -2
  696. package/dist/core/projection/arch-slice.js.map +1 -1
  697. package/dist/core/projection/introduced.js +14 -0
  698. package/dist/core/projection/introduced.js.map +1 -0
  699. package/dist/core/provenance/findings.js +48 -12
  700. package/dist/core/provenance/findings.js.map +1 -1
  701. package/dist/core/provenance/git.js +33 -57
  702. package/dist/core/provenance/git.js.map +1 -1
  703. package/dist/core/provenance/gitq/moves.js +71 -114
  704. package/dist/core/provenance/gitq/moves.js.map +1 -1
  705. package/dist/core/provenance/gitq/vouched-ancestor.js +2 -2
  706. package/dist/core/provenance/gitq/vouched-ancestor.js.map +1 -1
  707. package/dist/core/provenance/sources.js +23 -6
  708. package/dist/core/provenance/sources.js.map +1 -1
  709. package/dist/core/provenance/stamp.js +5 -17
  710. package/dist/core/provenance/stamp.js.map +1 -1
  711. package/dist/core/repo/authored/paths.js +18 -0
  712. package/dist/core/repo/authored/paths.js.map +1 -1
  713. package/dist/core/repo/entries.js.map +1 -1
  714. package/dist/core/repo/paths.js +92 -6
  715. package/dist/core/repo/paths.js.map +1 -1
  716. package/dist/core/repo/repo.js +74 -14
  717. package/dist/core/repo/repo.js.map +1 -1
  718. package/dist/core/repo/tree/find.js +12 -3
  719. package/dist/core/repo/tree/find.js.map +1 -1
  720. package/dist/core/repo/tree/fs.js +27 -1
  721. package/dist/core/repo/tree/fs.js.map +1 -1
  722. package/dist/core/repo/tree/render/body.js +258 -0
  723. package/dist/core/repo/tree/render/body.js.map +1 -0
  724. package/dist/core/repo/tree/render/projects.js +182 -0
  725. package/dist/core/repo/tree/render/projects.js.map +1 -0
  726. package/dist/core/repo/tree/render/service/header.js +125 -0
  727. package/dist/core/repo/tree/render/service/header.js.map +1 -0
  728. package/dist/core/repo/tree/render/service/peers.js +28 -0
  729. package/dist/core/repo/tree/render/service/peers.js.map +1 -0
  730. package/dist/core/repo/tree/render/service/view-id.js +67 -0
  731. package/dist/core/repo/tree/render/service/view-id.js.map +1 -0
  732. package/dist/core/repo/tree/render/service/views.js +78 -0
  733. package/dist/core/repo/tree/render/service/views.js.map +1 -0
  734. package/dist/core/repo/tree/render/stale.js +42 -0
  735. package/dist/core/repo/tree/render/stale.js.map +1 -0
  736. package/dist/core/repo/tree/render/text.js +84 -0
  737. package/dist/core/repo/tree/render/text.js.map +1 -0
  738. package/dist/core/repo/tree/render/views.js +293 -0
  739. package/dist/core/repo/tree/render/views.js.map +1 -0
  740. package/dist/core/repo/tree/walk.js +53 -32
  741. package/dist/core/repo/tree/walk.js.map +1 -1
  742. package/dist/core/results.js +47 -12
  743. package/dist/core/results.js.map +1 -1
  744. package/dist/core/scaffold/landscape.js +121 -13
  745. package/dist/core/scaffold/landscape.js.map +1 -1
  746. package/dist/core/scaffold/legacy.js +271 -0
  747. package/dist/core/scaffold/legacy.js.map +1 -0
  748. package/dist/core/staging/commit.js +26 -15
  749. package/dist/core/staging/commit.js.map +1 -1
  750. package/dist/core/staging/lock.js +74 -12
  751. package/dist/core/staging/lock.js.map +1 -1
  752. package/dist/core/staging/recovery/intent.js +2 -5
  753. package/dist/core/staging/recovery/intent.js.map +1 -1
  754. package/dist/core/staging/recovery/recover.js +84 -6
  755. package/dist/core/staging/recovery/recover.js.map +1 -1
  756. package/dist/core/staging/snapshot/manifest.js +188 -0
  757. package/dist/core/staging/snapshot/manifest.js.map +1 -0
  758. package/dist/core/staging/{snapshot.js → snapshot/snapshot.js} +39 -45
  759. package/dist/core/staging/snapshot/snapshot.js.map +1 -0
  760. package/dist/core/staging/txn/forward.js +24 -14
  761. package/dist/core/staging/txn/forward.js.map +1 -1
  762. package/dist/core/staging/writes.js.map +1 -1
  763. package/dist/core/status/actions/execution.js +11 -0
  764. package/dist/core/status/actions/execution.js.map +1 -1
  765. package/dist/core/status/contracts.js +39 -15
  766. package/dist/core/status/contracts.js.map +1 -1
  767. package/dist/core/status/feature/artifacts.js +33 -8
  768. package/dist/core/status/feature/artifacts.js.map +1 -1
  769. package/dist/core/status/feature/feature.js +24 -17
  770. package/dist/core/status/feature/feature.js.map +1 -1
  771. package/dist/core/status/feature/next.js +20 -7
  772. package/dist/core/status/feature/next.js.map +1 -1
  773. package/dist/core/status/feature/words.js +96 -0
  774. package/dist/core/status/feature/words.js.map +1 -0
  775. package/dist/core/status/fleet/fleet.js +43 -14
  776. package/dist/core/status/fleet/fleet.js.map +1 -1
  777. package/dist/core/status/fleet/next.js +153 -58
  778. package/dist/core/status/fleet/next.js.map +1 -1
  779. package/dist/core/status/report.js.map +1 -1
  780. package/dist/core/status/scan.js.map +1 -1
  781. package/dist/core/status/verification.js +30 -15
  782. package/dist/core/status/verification.js.map +1 -1
  783. package/dist/core/tasks/packet.js +199 -0
  784. package/dist/core/tasks/packet.js.map +1 -0
  785. package/dist/core/tasks/record.js +43 -0
  786. package/dist/core/tasks/record.js.map +1 -0
  787. package/dist/core/tasks/sources.js +181 -0
  788. package/dist/core/tasks/sources.js.map +1 -0
  789. package/dist/core/tasks/stamps.js +76 -0
  790. package/dist/core/tasks/stamps.js.map +1 -0
  791. package/dist/core/tasks/unit.js +0 -0
  792. package/dist/core/tasks/unit.js.map +1 -0
  793. package/dist/core/usecases/capability.js +11 -14
  794. package/dist/core/usecases/capability.js.map +1 -1
  795. package/dist/core/usecases/delta/claims.js +31 -7
  796. package/dist/core/usecases/delta/claims.js.map +1 -1
  797. package/dist/core/usecases/delta/flows.js +5 -7
  798. package/dist/core/usecases/delta/flows.js.map +1 -1
  799. package/dist/core/usecases/delta/modified.js +315 -0
  800. package/dist/core/usecases/delta/modified.js.map +1 -0
  801. package/dist/core/usecases/delta/overlay.js +32 -191
  802. package/dist/core/usecases/delta/overlay.js.map +1 -1
  803. package/dist/core/usecases/fleet.js +195 -36
  804. package/dist/core/usecases/fleet.js.map +1 -1
  805. package/dist/{commands/validate/fleet/usecases → core/usecases/grade}/capability-tag.js +8 -9
  806. package/dist/core/usecases/grade/capability-tag.js.map +1 -0
  807. package/dist/core/usecases/grade/feature.js +88 -0
  808. package/dist/core/usecases/grade/feature.js.map +1 -0
  809. package/dist/{commands/validate/fleet/usecases → core/usecases/grade}/requirement-tag.js +3 -4
  810. package/dist/core/usecases/grade/requirement-tag.js.map +1 -0
  811. package/dist/{commands/validate/fleet/usecases → core/usecases/grade}/steps.js +102 -33
  812. package/dist/core/usecases/grade/steps.js.map +1 -0
  813. package/dist/{commands/validate/fleet/usecases → core/usecases/grade}/usecases.js +23 -10
  814. package/dist/core/usecases/grade/usecases.js.map +1 -0
  815. package/dist/core/usecases/operations.js +26 -14
  816. package/dist/core/usecases/operations.js.map +1 -1
  817. package/dist/core/usecases/place.js.map +1 -1
  818. package/dist/core/usecases/service/exclude.js +119 -0
  819. package/dist/core/usecases/service/exclude.js.map +1 -0
  820. package/dist/core/usecases/service/flows.js +164 -0
  821. package/dist/core/usecases/service/flows.js.map +1 -0
  822. package/dist/core/usecases/suites/participants.js +83 -0
  823. package/dist/core/usecases/suites/participants.js.map +1 -0
  824. package/dist/core/usecases/suites/suites.js +45 -0
  825. package/dist/core/usecases/suites/suites.js.map +1 -0
  826. package/dist/core/verify/answers.js +12 -5
  827. package/dist/core/verify/answers.js.map +1 -1
  828. package/dist/core/verify/build.js +102 -82
  829. package/dist/core/verify/build.js.map +1 -1
  830. package/dist/core/verify/checklist.js +70 -12
  831. package/dist/core/verify/checklist.js.map +1 -1
  832. package/dist/core/verify/location.js +67 -0
  833. package/dist/core/verify/location.js.map +1 -0
  834. package/dist/core/verify/pins/lint.js +3 -2
  835. package/dist/core/verify/pins/lint.js.map +1 -1
  836. package/dist/core/verify/pins/pin.js +1 -1
  837. package/dist/core/verify/pins/pin.js.map +1 -1
  838. package/dist/core/verify/read/file.js +224 -0
  839. package/dist/core/verify/read/file.js.map +1 -0
  840. package/dist/core/verify/{file.js → read/shape.js} +16 -104
  841. package/dist/core/verify/read/shape.js.map +1 -0
  842. package/dist/core/verify/read/union.js +105 -0
  843. package/dist/core/verify/read/union.js.map +1 -0
  844. package/dist/core/verify/record.js +35 -12
  845. package/dist/core/verify/record.js.map +1 -1
  846. package/dist/core/verify/store/commit.js +40 -30
  847. package/dist/core/verify/store/commit.js.map +1 -1
  848. package/dist/core/verify/store/render.js +8 -4
  849. package/dist/core/verify/store/render.js.map +1 -1
  850. package/dist/core/vocabulary/issue.js +4 -0
  851. package/dist/core/vocabulary/issue.js.map +1 -1
  852. package/dist/core/vocabulary/maturity.js +75 -4
  853. package/dist/core/vocabulary/maturity.js.map +1 -1
  854. package/dist/core/vocabulary/report.js +16 -1
  855. package/dist/core/vocabulary/report.js.map +1 -1
  856. package/examples/README.md +54 -11
  857. package/examples/docs/architecture/landscape.likec4 +62 -6
  858. package/examples/docs/architecture/services.likec4 +70 -0
  859. package/examples/docs/architecture/subsystems.likec4 +7 -0
  860. package/examples/docs/architecture/usecases/order-notification.likec4 +16 -7
  861. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-service/asyncapi.yaml +11 -8
  862. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/openapi.yaml +6 -6
  863. package/examples/docs/features/FEAT-112-retire-order-v1/specs/order-service/openapi.yaml +4 -1
  864. package/examples/docs/features/archive/FEAT-088-refunds/specs/payment-service/openapi.yaml +13 -10
  865. package/examples/docs/likec4.config.json +0 -1
  866. package/examples/docs/services/checkout-web/model.likec4 +39 -56
  867. package/examples/docs/services/order-service/arch.spec.md +13 -6
  868. package/examples/docs/services/order-service/asyncapi.yaml +3 -2
  869. package/examples/docs/services/order-service/model.likec4 +58 -70
  870. package/examples/docs/services/payment-service/arch.spec.md +7 -4
  871. package/examples/docs/services/payment-service/model.likec4 +38 -37
  872. package/examples/docs/services/platform/identity-service/arch.spec.md +7 -4
  873. package/examples/docs/services/platform/identity-service/model.likec4 +35 -37
  874. package/examples/docs/services/platform/notification-service/asyncapi.yaml +2 -1
  875. package/examples/docs/services/platform/notification-service/health.yaml +8 -3
  876. package/examples/docs/services/platform/notification-service/model.likec4 +43 -64
  877. package/package.json +1 -1
  878. package/dist/commands/validate/checks/vocabulary.js +0 -31
  879. package/dist/commands/validate/checks/vocabulary.js.map +0 -1
  880. package/dist/commands/validate/fleet/usecases/capability-tag.js.map +0 -1
  881. package/dist/commands/validate/fleet/usecases/requirement-tag.js.map +0 -1
  882. package/dist/commands/validate/fleet/usecases/steps.js.map +0 -1
  883. package/dist/commands/validate/fleet/usecases/usecases.js.map +0 -1
  884. package/dist/core/agent/agents-md/artifacts.js +0 -220
  885. package/dist/core/agent/agents-md/artifacts.js.map +0 -1
  886. package/dist/core/agent/agents-md/cycle.js +0 -165
  887. package/dist/core/agent/agents-md/cycle.js.map +0 -1
  888. package/dist/core/agent/agents-md/shipped/archive-gate.js +0 -98
  889. package/dist/core/agent/agents-md/shipped/archive-gate.js.map +0 -1
  890. package/dist/core/agent/agents-md/spine.js +0 -40
  891. package/dist/core/agent/agents-md/spine.js.map +0 -1
  892. package/dist/core/coherence/events/merged.js +0 -40
  893. package/dist/core/coherence/events/merged.js.map +0 -1
  894. package/dist/core/diff/current-state.js +0 -96
  895. package/dist/core/diff/current-state.js.map +0 -1
  896. package/dist/core/diff/victims.js +0 -247
  897. package/dist/core/diff/victims.js.map +0 -1
  898. package/dist/core/repo/tree/views.js +0 -172
  899. package/dist/core/repo/tree/views.js.map +0 -1
  900. package/dist/core/staging/snapshot.js.map +0 -1
  901. package/dist/core/verify/file.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"rebase.js","sourceRoot":"","sources":["../../../src/commands/rebase/rebase.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Command } from \"commander\";\nimport { existsSync } from \"node:fs\";\nimport { loadConfig } from \"../../core/envelope/config.js\";\nimport { NotUtf8DocumentError } from \"../../core/kernel/document-bytes.js\";\nimport { InvalidIdError, assertServiceId } from \"../../core/kernel/ids/service.js\";\nimport { emitJson, fail, repoPath, reportNoConfig } from \"../../core/envelope/json.js\";\nimport { compareIds } from \"../../core/repo/entries.js\";\nimport { featureSpecPaths, SPEC_AXES } from \"../../core/repo/paths.js\";\nimport { missingFeatureMessage, resolveFeature } from \"../../core/repo/repo.js\";\nimport { stageWrites } from \"../../core/staging/commit.js\";\nimport { type CommitRecovery, InterruptedCommitError } from \"../../core/staging/interrupted.js\";\nimport { acquireDocsLock, DocsBusyError } from \"../../core/staging/lock.js\";\nimport { recoverInterruptedCommit } from \"../../core/staging/recovery/recover.js\";\nimport { commitStaged } from \"../../core/staging/txn/transaction.js\";\nimport { type PlannedWrite } from \"../../core/staging/writes.js\";\nimport { plural, sayRecovered } from \"../policy/format.js\";\nimport { FleetContext } from \"../../core/fleet-context.js\";\nimport {\n planAsyncapi,\n planAxis,\n planCapabilityAxis,\n planOpenapi,\n type CapabilityPinOutcome,\n type PinOutcome,\n} from \"./plan.js\";\nimport type { DocsDir } from \"../../core/kernel/ids/dirs.js\";\nimport { rebaseLivingLocked } from \"./living.js\";\n\n/**\n * `loam rebase` — pin a feature's MODIFIED/REMOVED requirements to the living\n * text they are written against.\n *\n * The counterpart to `loam vouch`: vouch stamps a digest of the CODE a living\n * spec was written from, this stamps a digest of the LIVING REQUIREMENT a delta\n * was written from. Both exist so a later `loam validate` can tell \"still true\"\n * from \"something moved underneath\", and both are worth exactly what they claim\n * — so this command computes every pin from what is on disk right now and never\n * invents one for a requirement that addresses nothing living.\n *\n * It is the fix `delta.baseline-stale` sends people to, which is why the\n * rewrite is line SURGERY rather than a reserialize: a delta document is\n * authored prose — section headings, comments, the order the author chose — and\n * `serializeRequirements` would flatten all of it into a bare requirement run.\n * One line changes per requirement; every other byte is copied.\n *\n * Restamping is the LAST step of resolving a collision, never the resolution\n * itself: a pin says \"I read this version\", so running it without re-reading\n * makes it a lie with a digest on it. The output says so on the way out.\n */\n\ninterface RebaseOptions {\n service?: string;\n json?: boolean;\n dryRun?: boolean;\n living?: boolean;\n}\n\n/** What happened to one pin. */\n\nexport function registerRebase(program: Command): void {\n program\n .command(\"rebase\")\n // Optional ONLY because `--living` names no feature: that mode pins the\n // living corpus itself. Every existing invocation still parses, which is\n // what makes the relaxation additive rather than a contract change.\n .argument(\"[featureId]\", \"feature id, e.g. FEAT-101 — omitted with --living\")\n .description(\"Pin a feature's MODIFIED/REMOVED requirements to the living text they are written against\")\n .option(\"--service <id>\", \"restrict to one service (default: every service the feature touches)\")\n .option(\n \"--living\",\n \"pin the LIVING corpus's `Realizes:` entries to the capability requirements they name, instead of a feature's deltas\",\n )\n .option(\n \"--dry-run\",\n \"print what would be pinned and write nothing — beyond first finishing a predecessor's interrupted commit, exactly as a real run would\",\n )\n .option(\"--json\", \"emit the machine contract instead of the human view\")\n .action(async (featureId: string | undefined, opts: RebaseOptions) => {\n const json = opts.json === true;\n const loaded = await loadConfig();\n if (loaded.kind !== \"loaded\") {\n reportNoConfig(json, loaded);\n return;\n }\n const config = loaded.config;\n\n // The id grammar on the RAW argument, before it reaches a path join —\n // one grammar for the whole tool (core/kernel/ids/service.ts).\n if (opts.service !== undefined) {\n try {\n assertServiceId(opts.service, \"--service\");\n } catch (err) {\n if (!(err instanceof InvalidIdError)) throw err;\n return fail(json, \"invalid-option\", err.message);\n }\n }\n\n // The living specs must not move between the read that computes a pin and\n // the write that records it: a digest taken over a document an archive\n // replaced a millisecond later is precisely the false \"I read this\" the\n // pin exists to make impossible. One writer per docs repo, refusing\n // rather than queueing, exactly as archive takes it.\n let release: () => Promise<void>;\n try {\n release = await acquireDocsLock(config.docsDir);\n } catch (err) {\n if (!(err instanceof DocsBusyError)) throw err;\n return fail(json, \"docs-busy\", err.message);\n }\n try {\n // A journal in the repo means the LAST write never finished — reading\n // living documents to compute pins over a half-commit would digest\n // bytes no run ever produced. Recover (or refuse) first, under the\n // same lock the commit will hold.\n let recovered: CommitRecovery | null;\n try {\n recovered = await recoverInterruptedCommit(config.docsDir);\n } catch (err) {\n if (!(err instanceof InterruptedCommitError)) throw err;\n return fail(json, \"commit-interrupted\", err.message);\n }\n if (opts.living === true) {\n await rebaseLivingLocked(config.docsDir, opts);\n return;\n }\n if (featureId === undefined) {\n // The argument is optional only for the mode that names no feature.\n // Refusing here rather than making the whole command feature-less\n // keeps one rule: every pin says which documents it read.\n return fail(\n json,\n \"invalid-option\",\n \"loam rebase needs a feature id — e.g. `loam rebase FEAT-101`. To pin the living corpus's `Realizes:` entries instead, run `loam rebase --living`.\",\n );\n }\n await rebaseLocked(config.docsDir, featureId, { ...opts, recovered });\n } finally {\n await release();\n }\n });\n}\n\nasync function rebaseLocked(\n docsDir: DocsDir,\n featureId: string,\n opts: RebaseOptions & { recovered: CommitRecovery | null },\n): Promise<void> {\n const json = opts.json === true;\n const dryRun = opts.dryRun === true;\n\n const feature = await resolveFeature(docsDir, featureId, \"exclude\");\n if (!feature) {\n return fail(json, \"unknown-target\", await missingFeatureMessage(docsDir, featureId));\n }\n const { id } = feature;\n\n // The enumeration's own id is what travels on when --service names one\n // (`entry.id` rather than the argument — repo/service-target.ts's rule):\n // equal as strings, and only one of them was produced by a readdir.\n const chosen = opts.service === undefined ? undefined : feature.services.find((s) => s === opts.service);\n if (opts.service !== undefined && chosen === undefined) {\n // The refusal names the choices, the way `loam delta`'s does: a typo must\n // never be indistinguishable from a feature with nothing to pin.\n return fail(\n json,\n \"unknown-target\",\n `${id} carries no requirement delta for '${opts.service}'` +\n (feature.services.length === 0\n ? \" — it touches no service at all.\"\n : ` — it touches: ${[...feature.services].sort(compareIds).join(\", \")}.`),\n );\n }\n const services = (chosen === undefined ? [...feature.services] : [chosen]).sort(compareIds);\n\n // One read index for the whole loop below: every planner resolves its\n // living document through `locateServicePaths`, and without a shared\n // context each of those calls is a fresh fleet walk — services × axes of\n // them per run, on a tree that cannot change under the lock this holds.\n const repo = { docsDir, fleet: new FleetContext() };\n const outcomes: PinOutcome[] = [];\n const capabilityOutcomes: CapabilityPinOutcome[] = [];\n const writes: PlannedWrite[] = [];\n // The business corpus this feature changes. Skipped entirely under `--service`:\n // that flag means \"restrict to one service\", and a capability names none — so\n // pinning capability deltas under it would write files the caller narrowed the\n // command to exclude. One `existsSync` when the feature carries no capability\n // delta, which is every feature in a fleet that has not adopted the axis.\n const capabilities =\n chosen === undefined ? (await repo.fleet.featureCapabilityDeltas(feature.dir)).docs : [];\n try {\n for (const service of services) {\n for (const axis of SPEC_AXES) {\n const specPath = featureSpecPaths(feature.dir, service)[axis.key];\n if (!existsSync(specPath)) continue;\n const planned = await planAxis(repo, service, axis, specPath);\n outcomes.push(...planned.outcomes);\n if (planned.content !== null) writes.push({ path: specPath, content: planned.content });\n }\n // The contract axis. It needs the pin more than the requirement axes do:\n // a requirement delta spells only the requirements it changes, while an\n // openapi delta is a COMPLETE document and spells the whole contract.\n const openapiPath = featureSpecPaths(feature.dir, service).openapi;\n if (existsSync(openapiPath)) {\n const planned = await planOpenapi(repo, service, openapiPath);\n outcomes.push(...planned.outcomes);\n if (planned.content !== null) writes.push({ path: openapiPath, content: planned.content });\n }\n // The event axis, for the openapi reason: a feature's asyncapi.yaml is\n // a complete document too, so its quotes need pins or the merge cannot\n // tell them from edits.\n const asyncapiPath = featureSpecPaths(feature.dir, service).asyncapi;\n if (existsSync(asyncapiPath)) {\n const planned = await planAsyncapi(repo, service, asyncapiPath);\n outcomes.push(...planned.outcomes);\n if (planned.content !== null) writes.push({ path: asyncapiPath, content: planned.content });\n }\n }\n // The business axis, after the services and in the same transaction: a\n // feature that changes a promise and the services keeping it is ONE act,\n // and half of it pinned is the state the journal exists to prevent.\n for (const doc of capabilities) {\n const planned = await planCapabilityAxis(repo, doc.id, doc.spec);\n capabilityOutcomes.push(...planned.outcomes);\n if (planned.content !== null) writes.push({ path: doc.spec, content: planned.content });\n }\n } catch (err) {\n if (!(err instanceof NotUtf8DocumentError)) throw err;\n // A pin is a claim about text somebody read. Over a document loam could not\n // decode it would be a digest of mojibake with loam's name on it — the\n // precise false claim this command exists to prevent — and the next archive\n // would land a stale delta over living text on the strength of it. So it\n // refuses by name and writes nothing, exactly as `loam archive` refuses a\n // merge it could not read, under archive's code. The refusal is here, in\n // the PLAN, so it lands before stageWrites: no file is touched, and a\n // feature spanning four services does not get two of them pinned.\n return fail(json, \"merge-failed\", `rebase ${id} failed — nothing was pinned: ${err.message}`);\n }\n\n if (!dryRun && writes.length > 0) {\n // Staged and committed through the journaled transaction: a feature\n // spanning four services is one act, and neither a full disk between its\n // second and third file NOR a kill between two renames may leave two of\n // them pinned to a reading the other two never saw — the journal makes\n // the second case recoverable where rollback alone could not see it.\n const staged = await stageWrites(writes);\n const committed = await commitStaged(\n { root: docsDir, command: \"rebase\", rerun: `loam rebase ${id}`, target: id },\n staged,\n \"pinned\",\n );\n if (!committed.ok) {\n return fail(\n json,\n committed.code,\n committed.code === \"merge-failed\" ? `rebase ${id} failed — nothing was pinned: ${committed.message}` : committed.message,\n );\n }\n }\n\n // One line per pin, whichever corpus it came from: what to call the document,\n // and the record itself. The two lists are reported separately in `--json`\n // (the published `pins[]`/`services[]` keys keep meaning exactly what they\n // meant) and together here, because a human rebasing one feature wants one\n // list in one order.\n const lines = [\n ...outcomes.map((o) => ({ where: `${o.service}/${o.file}`, pin: o })),\n ...capabilityOutcomes.map((o) => ({ where: `capabilities/${o.capability}/${o.file}`, pin: o })),\n ];\n const changed = lines.filter((l) => l.pin.status === \"pinned\" || l.pin.status === \"repinned\");\n const unresolved = lines.filter((l) => l.pin.status === \"unresolved\");\n\n if (json) {\n emitJson({\n command: \"rebase\",\n feature: id,\n services,\n dryRun,\n pins: outcomes,\n // Additive, and separate from `pins[]` on purpose: `PinOutcome.service`\n // is a published field, and a capability id written into it would say\n // something false to every consumer that already reads it.\n capabilities: capabilities.map((c) => c.id),\n capabilityPins: capabilityOutcomes,\n written: dryRun ? [] : writes.map((w) => repoPath(docsDir, w.path)),\n ...(opts.recovered === null ? {} : { recovered: opts.recovered }),\n });\n return;\n }\n\n if (lines.length === 0) {\n console.log(\n `${id}: nothing to pin — a baseline only means something for a requirement, an operation, a path-level key, a component or an event slot that already exists in the living docs.`,\n );\n return;\n }\n\n if (opts.recovered !== null) console.log(`${sayRecovered(opts.recovered)}\\n`);\n console.log(`${id}${dryRun ? \" (dry run)\" : \"\"}\\n`);\n for (const { where, pin: o } of lines) {\n const what = `${where} ${o.kind} ${o.target}`;\n if (o.status === \"unresolved\") {\n console.log(` · ${what} — not in the living docs yet, nothing to pin`);\n } else if (o.status === \"unwritable\") {\n console.log(` ! ${what} — a YAML alias (or a key loam cannot address by name); loam will not stamp through it`);\n } else if (o.status === \"unchanged\") {\n console.log(` = ${what} — already ${o.to}`);\n } else if (o.status === \"pinned\") {\n console.log(` + ${what} — pinned ${o.to}`);\n } else {\n console.log(` ~ ${what} — ${o.from} → ${o.to}`);\n }\n }\n\n if (changed.length === 0) {\n console.log(`\\nNothing to write: every pin already names the living version.`);\n } else if (dryRun) {\n console.log(`\\n${plural(changed.length, \"pin\")} would be written. Nothing was written.`);\n } else {\n console.log(`\\n${plural(changed.length, \"pin\")} written across ${plural(writes.length, \"file\")}.`);\n // The one sentence that keeps this command honest. A pin is a claim about\n // what its author read, and a `repinned` line means the living text moved\n // under a delta that still says what it said before — restamping does not\n // fold in the change it just stopped reporting.\n const repinned = changed.filter((l) => l.pin.status === \"repinned\");\n if (repinned.length > 0) {\n console.log(\n `\\n⚠ ${plural(repinned.length, \"pin\")} moved since this delta was written. A pin records what you read — ` +\n `re-read those living requirements and operations and fold in what you still mean, or the next archive lands your version over theirs with loam's blessing.`,\n );\n }\n }\n if (unresolved.length > 0) {\n console.log(\n `\\n${plural(unresolved.length, \"item\")} could not be pinned because the living docs do not have them yet — ` +\n `for a requirement, \\`loam dependencies ${id}\\` says which feature introduces it first; for an operation, this feature is adding it.`,\n );\n }\n}\n"]}
1
+ {"version":3,"file":"rebase.js","sourceRoot":"","sources":["../../../src/commands/rebase/rebase.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Command } from \"commander\";\nimport { existsSync } from \"node:fs\";\nimport { NotUtf8DocumentError } from \"../../core/kernel/document-bytes.js\";\nimport { InvalidIdError, assertServiceId } from \"../../core/kernel/ids/service.js\";\nimport { configOrRefuse, emitJson, fail, repoPath } from \"../../core/envelope/json.js\";\nimport { compareIds } from \"../../core/repo/entries.js\";\nimport { featureSpecPaths, SPEC_AXES } from \"../../core/repo/paths.js\";\nimport { missingFeatureMessage, resolveFeature } from \"../../core/repo/repo.js\";\nimport { stageWrites } from \"../../core/staging/commit.js\";\nimport { type CommitRecovery } from \"../../core/staging/interrupted.js\";\nimport { openCommitWindow } from \"../../core/staging/recovery/recover.js\";\nimport { commitStaged } from \"../../core/staging/txn/transaction.js\";\nimport { type PlannedWrite } from \"../../core/staging/writes.js\";\nimport { plural, sayRecovered } from \"../policy/format.js\";\nimport { FleetContext } from \"../../core/fleet-context.js\";\nimport {\n planAsyncapi,\n planAxis,\n planCapabilityAxis,\n planOpenapi,\n type CapabilityPinOutcome,\n type PinOutcome,\n} from \"./plan.js\";\nimport type { DocsDir } from \"../../core/kernel/ids/dirs.js\";\nimport { issueFinding, type Issue } from \"../../core/vocabulary/issue.js\";\nimport { retiredLookup } from \"../../core/coherence/retired/archived.js\";\nimport { serviceRevivals } from \"../../core/coherence/retired/revival/revived.js\";\nimport { rebaseLivingLocked } from \"./living.js\";\n\n/**\n * `loam rebase` — pin a feature's MODIFIED/REMOVED requirements to the living\n * text they are written against.\n *\n * The counterpart to `loam vouch`: vouch stamps a digest of the CODE a living\n * spec was written from, this stamps a digest of the LIVING REQUIREMENT a delta\n * was written from. Both exist so a later `loam validate` can tell \"still true\"\n * from \"something moved underneath\", and both are worth exactly what they claim\n * — so this command computes every pin from what is on disk right now and never\n * invents one for a requirement that addresses nothing living.\n *\n * It is the fix `delta.baseline-stale` sends people to, which is why the\n * rewrite is line SURGERY rather than a reserialize: a delta document is\n * authored prose — section headings, comments, the order the author chose — and\n * `serializeRequirements` would flatten all of it into a bare requirement run.\n * One line changes per requirement; every other byte is copied.\n *\n * Restamping is the LAST step of resolving a collision, never the resolution\n * itself: a pin says \"I read this version\", so running it without re-reading\n * makes it a lie with a digest on it. The output says so on the way out.\n */\n\ninterface RebaseOptions {\n service?: string;\n json?: boolean;\n dryRun?: boolean;\n living?: boolean;\n}\n\n/** What happened to one pin. */\n\nexport function registerRebase(program: Command): void {\n program\n .command(\"rebase\")\n // Optional ONLY because `--living` names no feature: that mode pins the\n // living corpus itself. Every existing invocation still parses, which is\n // what makes the relaxation additive rather than a contract change.\n .argument(\"[featureId]\", \"feature id, e.g. FEAT-101 — omitted with --living\")\n .description(\"Pin a feature's MODIFIED/REMOVED requirements to the living text they are written against\")\n .option(\"--service <id>\", \"restrict to one service (default: every service the feature touches)\")\n .option(\n \"--living\",\n \"pin the LIVING corpus's `Realizes:` entries to the capability requirements they name, instead of a feature's deltas\",\n )\n .option(\n \"--dry-run\",\n \"print what would be pinned and write nothing — beyond first finishing a predecessor's interrupted commit, exactly as a real run would\",\n )\n .option(\"--json\", \"emit the machine contract instead of the human view\")\n .action(async (featureId: string | undefined, opts: RebaseOptions) => {\n const json = opts.json === true;\n const config = await configOrRefuse(json);\n if (config === null) return;\n\n // The id grammar on the RAW argument, before it reaches a path join —\n // one grammar for the whole tool (core/kernel/ids/service.ts).\n if (opts.service !== undefined) {\n try {\n assertServiceId(opts.service, \"--service\");\n } catch (err) {\n if (!(err instanceof InvalidIdError)) throw err;\n return fail(json, \"invalid-option\", err.message);\n }\n }\n\n // The living specs must not move between the read that computes a pin and\n // the write that records it: a digest taken over a document an archive\n // replaced a millisecond later is precisely the false \"I read this\" the\n // pin exists to make impossible. One writer per docs repo, refusing\n // rather than queueing, exactly as archive takes it.\n //\n // A journal in the repo means the LAST write never finished — reading\n // living documents to compute pins over a half-commit would digest\n // bytes no run ever produced. Recover (or refuse) first, under the\n // same lock the commit will hold.\n const opened = await openCommitWindow(config.docsDir, 0);\n if (!opened.ok) return fail(json, opened.code, opened.message);\n try {\n if (opts.living === true) {\n await rebaseLivingLocked(config.docsDir, opts);\n return;\n }\n if (featureId === undefined) {\n // The argument is optional only for the mode that names no feature.\n // Refusing here rather than making the whole command feature-less\n // keeps one rule: every pin says which documents it read.\n return fail(\n json,\n \"invalid-option\",\n \"loam rebase needs a feature id — e.g. `loam rebase FEAT-101`. To pin the living corpus's `Realizes:` entries instead, run `loam rebase --living`.\",\n );\n }\n await rebaseLocked(config.docsDir, featureId, { ...opts, recovered: opened.recovered });\n } finally {\n await opened.release();\n }\n });\n}\n\nasync function rebaseLocked(\n docsDir: DocsDir,\n featureId: string,\n opts: RebaseOptions & { recovered: CommitRecovery | null },\n): Promise<void> {\n const json = opts.json === true;\n const dryRun = opts.dryRun === true;\n\n const feature = await resolveFeature(docsDir, featureId, \"exclude\");\n if (!feature) {\n return fail(json, \"unknown-target\", await missingFeatureMessage(docsDir, featureId));\n }\n const { id } = feature;\n\n // The enumeration's own id is what travels on when --service names one\n // (`entry.id` rather than the argument — repo/service-target.ts's rule):\n // equal as strings, and only one of them was produced by a readdir.\n const chosen = opts.service === undefined ? undefined : feature.services.find((s) => s === opts.service);\n if (opts.service !== undefined && chosen === undefined) {\n // The refusal names the choices, the way `loam delta`'s does: a typo must\n // never be indistinguishable from a feature with nothing to pin.\n return fail(\n json,\n \"unknown-target\",\n `${id} carries no requirement delta for '${opts.service}'` +\n (feature.services.length === 0\n ? \" — it touches no service at all.\"\n : ` — it touches: ${[...feature.services].sort(compareIds).join(\", \")}.`),\n );\n }\n const services = (chosen === undefined ? [...feature.services] : [chosen]).sort(compareIds);\n\n // One read index for the whole loop below: every planner resolves its\n // living document through `locateServicePaths`, and without a shared\n // context each of those calls is a fresh fleet walk — services × axes of\n // them per run, on a tree that cannot change under the lock this holds.\n const repo = { docsDir, fleet: new FleetContext() };\n const outcomes: PinOutcome[] = [];\n const capabilityOutcomes: CapabilityPinOutcome[] = [];\n const writes: PlannedWrite[] = [];\n const revived: Issue[] = [];\n // The business corpus this feature changes. Skipped entirely under `--service`:\n // that flag means \"restrict to one service\", and a capability names none — so\n // pinning capability deltas under it would write files the caller narrowed the\n // command to exclude. One `existsSync` when the feature carries no capability\n // delta, which is every feature in a fleet that has not adopted the axis.\n const capabilities =\n chosen === undefined ? (await repo.fleet.featureCapabilityDeltas(feature.dir)).docs : [];\n try {\n for (const service of services) {\n for (const axis of SPEC_AXES) {\n const specPath = featureSpecPaths(feature.dir, service)[axis.key];\n if (!existsSync(specPath)) continue;\n const planned = await planAxis(repo, service, axis, specPath);\n outcomes.push(...planned.outcomes);\n if (planned.content !== null) writes.push({ path: specPath, content: planned.content });\n }\n // The contract axis. It needs the pin more than the requirement axes do:\n // a requirement delta spells only the requirements it changes, while an\n // openapi delta is a COMPLETE document and spells the whole contract.\n const openapiPath = featureSpecPaths(feature.dir, service).openapi;\n if (existsSync(openapiPath)) {\n const planned = await planOpenapi(repo, service, openapiPath);\n outcomes.push(...planned.outcomes);\n if (planned.content !== null) writes.push({ path: openapiPath, content: planned.content });\n }\n // The event axis, for the openapi reason: a feature's asyncapi.yaml is\n // a complete document too, so its quotes need pins or the merge cannot\n // tell them from edits.\n const asyncapiPath = featureSpecPaths(feature.dir, service).asyncapi;\n if (existsSync(asyncapiPath)) {\n const planned = await planAsyncapi(repo, service, asyncapiPath);\n outcomes.push(...planned.outcomes);\n if (planned.content !== null) writes.push({ path: asyncapiPath, content: planned.content });\n }\n }\n // The business axis, after the services and in the same transaction: a\n // feature that changes a promise and the services keeping it is ONE act,\n // and half of it pinned is the state the journal exists to prevent.\n for (const doc of capabilities) {\n const planned = await planCapabilityAxis(repo, doc.id, doc.spec);\n capabilityOutcomes.push(...planned.outcomes);\n if (planned.content !== null) writes.push({ path: doc.spec, content: planned.content });\n }\n // An operation or event slot the living docs do not hold reads `unresolved`\n // above — \"this feature is adding it\". For one an ARCHIVED feature retired,\n // that is the false sentence that put retired operations back: unpinned, the\n // merge upserts it as an addition. Rebase pins nothing for it, so what it\n // owes is the same finding the gate raises, said here before the archive\n // refuses it, and the decision left to the human. Asked of the documents\n // as this run leaves them (`planned`): a repin over whatever lives at an\n // address now turns a quote the merge skipped into an edit it writes, and\n // a revival that edit makes is this run's to report — the next validate\n // reports it, and a dry run must say what the real one would leave.\n const retired = retiredLookup(docsDir, repo.fleet);\n const planned = new Map(writes.flatMap((w) => (typeof w.content === \"string\" ? [[w.path, w.content] as const] : [])));\n for (const service of services) {\n revived.push(...(await serviceRevivals({ docsDir, featureDir: feature.dir, service, retired, context: repo.fleet, planned })));\n }\n } catch (err) {\n if (!(err instanceof NotUtf8DocumentError)) throw err;\n // A pin is a claim about text somebody read. Over a document loam could not\n // decode it would be a digest of mojibake with loam's name on it — the\n // precise false claim this command exists to prevent — and the next archive\n // would land a stale delta over living text on the strength of it. So it\n // refuses by name and writes nothing, exactly as `loam archive` refuses a\n // merge it could not read, under archive's code. The refusal is here, in\n // the PLAN, so it lands before stageWrites: no file is touched, and a\n // feature spanning four services does not get two of them pinned.\n return fail(json, \"merge-failed\", `rebase ${id} failed — nothing was pinned: ${err.message}`);\n }\n\n if (!dryRun && writes.length > 0) {\n // Staged and committed through the journaled transaction: a feature\n // spanning four services is one act, and neither a full disk between its\n // second and third file NOR a kill between two renames may leave two of\n // them pinned to a reading the other two never saw — the journal makes\n // the second case recoverable where rollback alone could not see it.\n const staged = await stageWrites(writes);\n const committed = await commitStaged(\n { root: docsDir, command: \"rebase\", rerun: `loam rebase ${id}`, target: id },\n staged,\n \"pinned\",\n );\n if (!committed.ok) {\n return fail(\n json,\n committed.code,\n committed.code === \"merge-failed\" ? `rebase ${id} failed — nothing was pinned: ${committed.message}` : committed.message,\n );\n }\n }\n\n // One line per pin, whichever corpus it came from: what to call the document,\n // and the record itself. The two lists are reported separately in `--json`\n // (the published `pins[]`/`services[]` keys keep meaning exactly what they\n // meant) and together here, because a human rebasing one feature wants one\n // list in one order.\n const lines = [\n ...outcomes.map((o) => ({ where: `${o.service}/${o.file}`, pin: o })),\n ...capabilityOutcomes.map((o) => ({ where: `capabilities/${o.capability}/${o.file}`, pin: o })),\n ];\n const changed = lines.filter((l) => l.pin.status === \"pinned\" || l.pin.status === \"repinned\");\n const unresolved = lines.filter((l) => l.pin.status === \"unresolved\");\n\n if (json) {\n emitJson({\n command: \"rebase\",\n feature: id,\n services,\n dryRun,\n pins: outcomes,\n // Additive, and separate from `pins[]` on purpose: `PinOutcome.service`\n // is a published field, and a capability id written into it would say\n // something false to every consumer that already reads it.\n capabilities: capabilities.map((c) => c.id),\n capabilityPins: capabilityOutcomes,\n // Additive: the `openapi.op-revived` / `asyncapi.slot-revived` findings\n // for what this feature spells that an archived feature retired. Their\n // `pins[]` rows still say `unresolved` — true, and published — and this\n // key is what says those rows are not additions.\n revived: revived.map(issueFinding),\n written: dryRun ? [] : writes.map((w) => repoPath(docsDir, w.path)),\n ...(opts.recovered === null ? {} : { recovered: opts.recovered }),\n });\n return;\n }\n\n if (lines.length === 0) {\n console.log(\n `${id}: nothing to pin — a baseline only means something for a requirement, an operation, a path-level key, a component or an event slot that already exists in the living docs.`,\n );\n sayRevived(revived);\n return;\n }\n\n if (opts.recovered !== null) console.log(`${sayRecovered(opts.recovered)}\\n`);\n console.log(`${id}${dryRun ? \" (dry run)\" : \"\"}\\n`);\n for (const { where, pin: o } of lines) {\n const what = `${where} ${o.kind} ${o.target}`;\n if (o.status === \"unresolved\") {\n console.log(` · ${what} — not in the living docs yet, nothing to pin`);\n } else if (o.status === \"unwritable\") {\n console.log(` ! ${what} — a YAML alias (or a key loam cannot address by name); loam will not stamp through it`);\n } else if (o.status === \"unchanged\") {\n console.log(` = ${what} — already ${o.to}`);\n } else if (o.status === \"pinned\") {\n console.log(` + ${what} — pinned ${o.to}`);\n } else {\n console.log(` ~ ${what} — ${o.from} → ${o.to}`);\n }\n }\n\n if (changed.length === 0) {\n console.log(`\\nNothing to write: every pin already names the living version.`);\n } else if (dryRun) {\n console.log(`\\n${plural(changed.length, \"pin\")} would be written. Nothing was written.`);\n } else {\n console.log(`\\n${plural(changed.length, \"pin\")} written across ${plural(writes.length, \"file\")}.`);\n // The one sentence that keeps this command honest. A pin is a claim about\n // what its author read, and a `repinned` line means the living text moved\n // under a delta that still says what it said before — restamping does not\n // fold in the change it just stopped reporting.\n const repinned = changed.filter((l) => l.pin.status === \"repinned\");\n if (repinned.length > 0) {\n console.log(\n `\\n⚠ ${plural(repinned.length, \"pin\")} moved since this delta was written. A pin records what you read — ` +\n `re-read those living requirements and operations and fold in what you still mean, or the next archive lands your version over theirs with loam's blessing.`,\n );\n }\n }\n if (unresolved.length > 0) {\n console.log(\n `\\n${plural(unresolved.length, \"item\")} could not be pinned because the living docs do not have them yet — ` +\n `for a requirement, \\`loam dependencies ${id}\\` says which feature introduces it first; for an operation, this feature is adding it` +\n (revived.length === 0 ? \".\" : \", unless an archived feature retired it or moved it away — those are listed below, and they are not new.\"),\n );\n }\n sayRevived(revived);\n}\n\n/**\n * The revival findings, in the gate's own words. Printed rather than acted on:\n * deleting a quote and re-adding a retired operation on purpose are both\n * legitimate, and which one this is is the author's call. The sentence once\n * said \"nothing was pinned\" for them — true of a retired entry, which has no\n * living version, and false of a quote this run repinned over whatever lives\n * at its address now, the very pin that made it a revival.\n */\nfunction sayRevived(revived: readonly Issue[]): void {\n if (revived.length === 0) return;\n const one = revived.length === 1;\n console.log(\n `\\n⚠ ${plural(revived.length, \"item\")} this feature spells ${one ? \"was\" : \"were\"} RETIRED by an archived feature, or moved to another address by one — ` +\n `${one ? \"it is\" : \"they are\"} not new, pinned or not, and \\`loam archive\\` refuses ${one ? \"it\" : \"them\"} until you decide:`,\n );\n for (const issue of revived) console.log(` ⚠ ${issue.message}`);\n}\n"]}
@@ -5,7 +5,7 @@
5
5
  * the docs lock, nothing outside it does, and the module prints nothing —
6
6
  * the caller renders every arm.
7
7
  *
8
- * The checks live UNDER the lock on purpose: the never-overwrite promise is a
8
+ * The three refusals live UNDER the lock on purpose: the never-overwrite promise is a
9
9
  * statement about the landscape as it is at the moment of the write, and an
10
10
  * unlocked classification would be a TOCTOU against every other docs writer.
11
11
  */
@@ -16,34 +16,21 @@ import { isLandscapeStub } from "../../core/scaffold/landscape.js";
16
16
  import { parseServiceId } from "../../core/kernel/ids/service.js";
17
17
  import { landscapePath } from "../../core/repo/paths.js";
18
18
  import { listFleetTree } from "../../core/repo/repo.js";
19
+ import { authoredRefusal } from "../../core/repo/tree/render/service/header.js";
19
20
  import { DocsRepoUnavailableError } from "../../core/repo/state.js";
20
21
  import { stageWrites } from "../../core/staging/commit.js";
21
- import { InterruptedCommitError } from "../../core/staging/interrupted.js";
22
- import { acquireDocsLockWaiting, DocsBusyError, LOCK_WAIT_MS } from "../../core/staging/lock.js";
23
- import { recoverInterruptedCommit } from "../../core/staging/recovery/recover.js";
22
+ import {} from "../../core/staging/interrupted.js";
23
+ import { LOCK_WAIT_MS } from "../../core/staging/lock.js";
24
+ import { openCommitWindow } from "../../core/staging/recovery/recover.js";
24
25
  import { commitStaged } from "../../core/staging/txn/transaction.js";
25
26
  import { planSeedWrites } from "./plan.js";
26
27
  export async function commitSeed(req) {
27
28
  const { docsDir } = req;
28
- let releaseLock;
29
+ const opened = await openCommitWindow(docsDir, LOCK_WAIT_MS);
30
+ if (!opened.ok)
31
+ return opened;
32
+ const { recovered } = opened;
29
33
  try {
30
- releaseLock = await acquireDocsLockWaiting(docsDir, LOCK_WAIT_MS);
31
- }
32
- catch (err) {
33
- if (err instanceof DocsBusyError)
34
- return { ok: false, code: "docs-busy", message: err.message };
35
- throw err;
36
- }
37
- try {
38
- let recovered;
39
- try {
40
- recovered = await recoverInterruptedCommit(docsDir);
41
- }
42
- catch (err) {
43
- if (!(err instanceof InterruptedCommitError))
44
- throw err;
45
- return { ok: false, code: "commit-interrupted", message: err.message };
46
- }
47
34
  // Provenance first, then the tree: both read the repo as this run will
48
35
  // leave it, and both refusals must prove nothing was written.
49
36
  const landscape = await classifyLandscape(docsDir);
@@ -63,6 +50,38 @@ export async function commitSeed(req) {
63
50
  if (inconsistency !== null)
64
51
  return inconsistency;
65
52
  const plan = await planSeedWrites(req, tree);
53
+ // THE OTHER never-overwrite promise, and the third refusal this window owns.
54
+ //
55
+ // `classifyLandscape` above keeps it for `architecture/landscape.likec4`;
56
+ // this keeps it for the two files seed does not share with the team at all —
57
+ // `architecture/subsystems.likec4` and `architecture/services.likec4` are
58
+ // filenames loam RESERVES inside a directory the team owns, and seed writes
59
+ // them whole. Until this line existed a `loam seed` into a repository that
60
+ // kept a hand-authored diagram at one of those paths destroyed it in
61
+ // silence: the same clobber reproduced through `loam subsystem new`, and the
62
+ // guard that caught it lived in `subsystem sync` alone.
63
+ //
64
+ // THE WHOLE SEED IS REFUSED, exactly as an edited landscape refuses it, and
65
+ // for the same reason: seed regenerates every file it owns wholesale from
66
+ // fleet.yaml, so landing the landscape and the markers while declining a
67
+ // views file would leave a tree whose very next `validate --all` — seed's
68
+ // own `next` command — reports `subsystem.views-stale` over a file no
69
+ // command could ever repair. `planSeedWrites` has staged nothing; the
70
+ // transaction below is the first byte, and it does not run.
71
+ if (plan.authored.length > 0) {
72
+ return {
73
+ ok: false,
74
+ // `already-exists` for the reason commands/subsystem/txn/txn.ts gives at
75
+ // its own copy of this refusal: it is what that code has always meant —
76
+ // refusing to create over something that already exists, because
77
+ // overwriting would destroy work nobody asked to lose.
78
+ code: "already-exists",
79
+ message: plan.authored.map((file) => authoredRefusal(file)).join(" ") +
80
+ " NOTHING was written: not the landscape, not a subsystem marker, not a `.gitkeep`. Seed regenerates " +
81
+ "every file it owns wholesale, so it never proceeds past human work standing at one of its paths — the " +
82
+ "same promise `seed-landscape-edited` makes one file over.",
83
+ };
84
+ }
66
85
  const staged = await stageWrites(plan.writes);
67
86
  const committed = await commitStaged({ root: docsDir, command: "seed", rerun: req.rerun, target: "landscape" }, staged, "seeded");
68
87
  if (!committed.ok) {
@@ -83,7 +102,7 @@ export async function commitSeed(req) {
83
102
  };
84
103
  }
85
104
  finally {
86
- await releaseLock();
105
+ await opened.release();
87
106
  }
88
107
  }
89
108
  /**
@@ -109,12 +128,22 @@ async function classifyLandscape(docsDir) {
109
128
  const provenance = landscapeProvenance(text);
110
129
  if (provenance === "seed-stamped")
111
130
  return { disposition: "regenerated" };
131
+ // The advice used to be "fold the edits into fleet.yaml and delete the
132
+ // file", which is impossible for the edit every documented next step makes:
133
+ // the first `metadata { op }` an author or an adopt brief writes onto an edge
134
+ // has no spelling in fleet.yaml (services, subsystems, plain `a -> b` calls),
135
+ // so a reader following it would delete the operation links the spine is
136
+ // graded on. Seed is a day-zero tool; the honest answer names what grows the
137
+ // map after day zero.
112
138
  return {
113
139
  refusal: `architecture/landscape.likec4 ${provenance === "seed-edited"
114
140
  ? "was seeded but has been hand-edited since — the line-1 stamp's digest no longer matches the content"
115
- : "was not written by `loam seed`: it carries no line-1 stamp and is not the scaffold's untouched stub"}. Seed never overwrites human work; nothing was written. Either fold the edits into ` +
116
- `fleet.yaml and delete the file, then re-run — or keep the hand-authored map and stop ` +
117
- `using seed here.`,
141
+ : "was not written by `loam seed`: it carries no line-1 stamp and is not the scaffold's untouched stub"}. Seed never overwrites human work; nothing was written. Seed runs once, before anyone ` +
142
+ `draws an operation: fleet.yaml cannot carry \`metadata { op }\`, publishes or consumes, so a map ` +
143
+ `holding them is past seeding. Grow it from here without seed — \`loam adopt --service <id>\` ` +
144
+ `briefs the element and edges a new service adds, and a feature's C4 delta carries every other ` +
145
+ `change. Only if the edits are things fleet.yaml can say (a service, a subsystem, a plain call) ` +
146
+ `is folding them into fleet.yaml and deleting the file still an option.`,
118
147
  };
119
148
  }
120
149
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"commit.js","sourceRoot":"","sources":["../../../src/commands/seed/commit.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Seed's commit window: lock, recover, the under-lock provenance and\n * fleet-consistency checks, one journaled transaction. Modeled line for line\n * on commands/new/commit.ts and on the same seam: everything in here holds\n * the docs lock, nothing outside it does, and the module prints nothing —\n * the caller renders every arm.\n *\n * The checks live UNDER the lock on purpose: the never-overwrite promise is a\n * statement about the landscape as it is at the moment of the write, and an\n * unlocked classification would be a TOCTOU against every other docs writer.\n */\nimport { existsSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport type { FleetSeed } from \"../../core/c4/seed/fleet-file.js\";\nimport { landscapeProvenance } from \"../../core/c4/seed/stamp.js\";\nimport { isLandscapeStub } from \"../../core/scaffold/landscape.js\";\nimport type { DocsDir } from \"../../core/kernel/ids/dirs.js\";\nimport { parseServiceId } from \"../../core/kernel/ids/service.js\";\nimport { landscapePath } from \"../../core/repo/paths.js\";\nimport { listFleetTree } from \"../../core/repo/repo.js\";\nimport { DocsRepoUnavailableError } from \"../../core/repo/state.js\";\nimport type { FleetTree } from \"../../core/repo/tree/walk.js\";\nimport { stageWrites } from \"../../core/staging/commit.js\";\nimport { type CommitRecovery, InterruptedCommitError } from \"../../core/staging/interrupted.js\";\nimport { acquireDocsLockWaiting, DocsBusyError, LOCK_WAIT_MS } from \"../../core/staging/lock.js\";\nimport { recoverInterruptedCommit } from \"../../core/staging/recovery/recover.js\";\nimport { commitStaged } from \"../../core/staging/txn/transaction.js\";\nimport { planSeedWrites, type SeedPlanInput } from \"./plan.js\";\n\n/** The plan's input, plus the one fact only the transaction needs. */\nexport interface SeedCommitRequest extends SeedPlanInput {\n /** How a human re-runs this command — the transaction journal's `rerun`. */\n rerun: string;\n}\n\n/** What happened to architecture/landscape.likec4 — the three writes seed may prove safe. */\nexport type LandscapeDisposition = \"created\" | \"replaced-stub\" | \"regenerated\";\n\nexport type SeedCommit =\n | {\n ok: true;\n landscape: LandscapeDisposition;\n /** Absolute path of every file the transaction wrote, in write order. */\n written: string[];\n /**\n * Absolute path of every file the transaction REMOVED — only ever the\n * generated views file, when the resulting tree has no subsystems left\n * to view. Separate from `written` because \"+ path\" is a lie about a\n * delete.\n */\n removed: string[];\n /** Service ids split by whether this run created the directory. */\n services: { created: string[]; existing: string[] };\n recovered: CommitRecovery | null;\n }\n | {\n ok: false;\n code:\n | \"docs-busy\"\n | \"commit-interrupted\"\n | \"merge-failed\"\n | \"rollback-incomplete\"\n | \"seed-landscape-edited\";\n message: string;\n }\n /** The under-lock fleet-consistency preflight refusing; see `missingServices`. */\n | { ok: false; code: \"seed-file-invalid\"; message: string; missingServices: string[] }\n /** The docs repo went away between the command's gate and the locked read — new/commit.ts says why this is not a `code:` arm. */\n | { ok: false; repoGone: DocsRepoUnavailableError };\n\nexport async function commitSeed(req: SeedCommitRequest): Promise<SeedCommit> {\n const { docsDir } = req;\n let releaseLock: () => Promise<void>;\n try {\n releaseLock = await acquireDocsLockWaiting(docsDir, LOCK_WAIT_MS);\n } catch (err) {\n if (err instanceof DocsBusyError) return { ok: false, code: \"docs-busy\", message: err.message };\n throw err;\n }\n try {\n let recovered: CommitRecovery | null;\n try {\n recovered = await recoverInterruptedCommit(docsDir);\n } catch (err) {\n if (!(err instanceof InterruptedCommitError)) throw err;\n return { ok: false, code: \"commit-interrupted\", message: err.message };\n }\n\n // Provenance first, then the tree: both read the repo as this run will\n // leave it, and both refusals must prove nothing was written.\n const landscape = await classifyLandscape(docsDir);\n if (\"refusal\" in landscape) {\n return { ok: false, code: \"seed-landscape-edited\", message: landscape.refusal };\n }\n\n let tree: FleetTree;\n try {\n tree = await listFleetTree(docsDir);\n } catch (err) {\n if (!(err instanceof DocsRepoUnavailableError)) throw err;\n return { ok: false, repoGone: err };\n }\n const inconsistency = preflight(tree, req.seed);\n if (inconsistency !== null) return inconsistency;\n\n const plan = await planSeedWrites(req, tree);\n const staged = await stageWrites(plan.writes);\n const committed = await commitStaged(\n { root: docsDir, command: \"seed\", rerun: req.rerun, target: \"landscape\" },\n staged,\n \"seeded\",\n );\n if (!committed.ok) {\n // `committed.raced` is deliberately NOT remapped: the lock serialises\n // loam writers, so a fired CAS or a lost exclusive create here means an\n // out-of-band editor, and seed has no softer race answer the way `new`\n // has already-exists — merge-failed's \"nothing was written, re-run\" is\n // the honest sentence either way.\n return { ok: false, code: committed.code, message: committed.message };\n }\n return {\n ok: true,\n landscape: landscape.disposition,\n written: plan.writes.filter((w) => w.content !== null).map((w) => w.path),\n removed: plan.writes.filter((w) => w.content === null).map((w) => w.path),\n services: plan.services,\n recovered,\n };\n } finally {\n await releaseLock();\n }\n}\n\n/**\n * May seed write the landscape? Absent and untouched-scaffold-stub are the\n * two states with provably no human work in them; a matching stamp digest is\n * the third (`core/c4/seed/stamp.ts`). Everything else refuses.\n */\nasync function classifyLandscape(\n docsDir: DocsDir,\n): Promise<{ disposition: LandscapeDisposition } | { refusal: string }> {\n const path = landscapePath(docsDir);\n if (!existsSync(path)) return { disposition: \"created\" };\n const text = (await readFile(path)).toString(\"utf8\");\n // `isLandscapeStub`, never a byte-compare of our own: that function IS the\n // repo's answer to \"is this still the scaffold's untouched map\", it is what\n // `loam status` reads before telling the reader to run seed, and it is\n // suffix-matched and CRLF-normalised for two reasons seed shares —\n // `migrate-openspec` prepends a preamble to the identical stub, and a\n // checkout under `core.autocrlf` (Git for Windows' installer default)\n // rewrites every line without touching a fact. A stricter compare here made\n // status and seed contradict each other about the same file.\n if (isLandscapeStub(text)) return { disposition: \"replaced-stub\" };\n const provenance = landscapeProvenance(text);\n if (provenance === \"seed-stamped\") return { disposition: \"regenerated\" };\n return {\n refusal:\n `architecture/landscape.likec4 ${\n provenance === \"seed-edited\"\n ? \"was seeded but has been hand-edited since — the line-1 stamp's digest no longer matches the content\"\n : \"was not written by `loam seed`: it carries no line-1 stamp and is not the scaffold's untouched stub\"\n }. Seed never overwrites human work; nothing was written. Either fold the edits into ` +\n `fleet.yaml and delete the file, then re-run — or keep the hand-authored map and stop ` +\n `using seed here.`,\n };\n}\n\n/**\n * The fleet-consistency preflight. Seed regenerates the landscape WHOLESALE —\n * that is the only posture the stamp can prove safe — so every existing\n * services/<id>/ must be named in fleet.yaml, or the regenerate would orphan\n * it into `landscape.service-unmodelled`. And the file's names must not\n * collide with what the tree already holds under a different kind: one flat\n * namespace, the same rule the walk enforces.\n */\nfunction preflight(tree: FleetTree, seed: FleetSeed): SeedCommit | null {\n const treeSubs = new Set(tree.subsystems.map((s) => s.name));\n const treeIds = new Set(tree.services.map((s) => s.id as string));\n\n // The collision scan runs BEFORE the missing-service scan, and the order is\n // load-bearing. A name the file declares as a subsystem or an external while\n // the tree holds it as a service DIRECTORY is both facts at once: it is a\n // namespace collision, and it is also an existing service the file does not\n // name. With the missing scan first, the caller was told to paste that name\n // into `services:` — advice that walks straight into `seed-duplicate-service`\n // on the next run, because the file already declares it as something else.\n const collisions: string[] = [];\n for (const sub of seed.subsystems) {\n if (treeIds.has(sub as string)) collisions.push(`subsystem '${sub}' is an existing service directory`);\n }\n for (const s of seed.services) {\n if (treeSubs.has(s.id as string)) collisions.push(`service '${s.id}' is an existing subsystem directory`);\n }\n for (const x of seed.externals) {\n if (treeIds.has(x)) collisions.push(`external '${x}' is an existing service directory`);\n if (treeSubs.has(x)) collisions.push(`external '${x}' is an existing subsystem directory`);\n }\n if (collisions.length > 0) {\n return {\n ok: false,\n code: \"seed-file-invalid\",\n message:\n `fleet.yaml collides with the services/ tree — service ids, subsystem names and externals ` +\n `share one flat namespace: ${collisions.join(\"; \")}. Rename the fleet.yaml side (or the ` +\n `directory, with \\`loam subsystem rename <from> <to>\\`), then re-run. Nothing was written.`,\n missingServices: [],\n };\n }\n\n const ids = new Set(seed.services.map((s) => s.id as string));\n const missing = tree.services.map((s) => s.id as string).filter((id) => !ids.has(id)).sort();\n if (missing.length === 0) return null;\n // The ids are partitioned because one half cannot take the other's advice.\n // `tree.services` carries RAW ids — a directory whose name fails the service\n // grammar is still a service to the walk, by design — and \"add it to\n // services: exactly as spelled\" is impossible for one of those: the fleet\n // file would refuse the entry. Without this split, seed was simply unusable\n // on such a repo and never said so.\n const legal = missing.filter((id) => parseServiceId(id, \"services entry\").ok);\n const illegal = missing.filter((id) => !parseServiceId(id, \"services entry\").ok);\n const fixes: string[] = [];\n if (legal.length > 0) fixes.push(`add ${legal.join(\", \")} to services:, exactly as spelled`);\n if (illegal.length > 0) {\n fixes.push(\n `rename the ${illegal.length === 1 ? \"directory\" : \"directories\"} ${illegal.join(\", \")} ` +\n `first — ${illegal.length === 1 ? \"that name is not a legal service id\" : \"those names are not legal service ids\"}, ` +\n `so no services: entry can name ${illegal.length === 1 ? \"it\" : \"them\"}`,\n );\n }\n return {\n ok: false,\n code: \"seed-file-invalid\",\n message:\n `fleet.yaml must name every existing service — seed regenerates the landscape wholesale, ` +\n `and these services/ directories are not in it: ${missing.join(\", \")}. ` +\n `To fix: ${fixes.join(\"; and \")}. Then re-run. Nothing was written.`,\n missingServices: missing,\n };\n}\n"]}
1
+ {"version":3,"file":"commit.js","sourceRoot":"","sources":["../../../src/commands/seed/commit.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Seed's commit window: lock, recover, the under-lock provenance and\n * fleet-consistency checks, one journaled transaction. Modeled line for line\n * on commands/new/commit.ts and on the same seam: everything in here holds\n * the docs lock, nothing outside it does, and the module prints nothing —\n * the caller renders every arm.\n *\n * The three refusals live UNDER the lock on purpose: the never-overwrite promise is a\n * statement about the landscape as it is at the moment of the write, and an\n * unlocked classification would be a TOCTOU against every other docs writer.\n */\nimport { existsSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport type { FleetSeed } from \"../../core/c4/seed/fleet-file.js\";\nimport { landscapeProvenance } from \"../../core/c4/seed/stamp.js\";\nimport { isLandscapeStub } from \"../../core/scaffold/landscape.js\";\nimport type { DocsDir } from \"../../core/kernel/ids/dirs.js\";\nimport { parseServiceId } from \"../../core/kernel/ids/service.js\";\nimport { landscapePath } from \"../../core/repo/paths.js\";\nimport { listFleetTree } from \"../../core/repo/repo.js\";\nimport { authoredRefusal } from \"../../core/repo/tree/render/service/header.js\";\nimport { DocsRepoUnavailableError } from \"../../core/repo/state.js\";\nimport type { FleetTree } from \"../../core/repo/tree/walk.js\";\nimport { stageWrites } from \"../../core/staging/commit.js\";\nimport { type CommitRecovery } from \"../../core/staging/interrupted.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 { planSeedWrites, type SeedPlanInput } from \"./plan.js\";\n\n/** The plan's input, plus the one fact only the transaction needs. */\nexport interface SeedCommitRequest extends SeedPlanInput {\n /** How a human re-runs this command — the transaction journal's `rerun`. */\n rerun: string;\n}\n\n/** What happened to architecture/landscape.likec4 — the three writes seed may prove safe. */\nexport type LandscapeDisposition = \"created\" | \"replaced-stub\" | \"regenerated\";\n\nexport type SeedCommit =\n | {\n ok: true;\n landscape: LandscapeDisposition;\n /** Absolute path of every file the transaction wrote, in write order. */\n written: string[];\n /**\n * Absolute path of every file the transaction REMOVED — only ever the\n * generated views file, when the resulting tree has no subsystems left\n * to view. Separate from `written` because \"+ path\" is a lie about a\n * delete.\n */\n removed: string[];\n /** Service ids split by whether this run created the directory. */\n services: { created: string[]; existing: string[] };\n recovered: CommitRecovery | null;\n }\n | {\n ok: false;\n code:\n | \"docs-busy\"\n | \"commit-interrupted\"\n | \"merge-failed\"\n | \"rollback-incomplete\"\n | \"seed-landscape-edited\"\n /** A hand-authored document standing at one of the two generated views paths — see the refusal in `commitSeed`. */\n | \"already-exists\";\n message: string;\n }\n /** The under-lock fleet-consistency preflight refusing; see `missingServices`. */\n | { ok: false; code: \"seed-file-invalid\"; message: string; missingServices: string[] }\n /** The docs repo went away between the command's gate and the locked read — new/commit.ts says why this is not a `code:` arm. */\n | { ok: false; repoGone: DocsRepoUnavailableError };\n\nexport async function commitSeed(req: SeedCommitRequest): Promise<SeedCommit> {\n const { docsDir } = req;\n const opened = await openCommitWindow(docsDir, LOCK_WAIT_MS);\n if (!opened.ok) return opened;\n const { recovered } = opened;\n try {\n // Provenance first, then the tree: both read the repo as this run will\n // leave it, and both refusals must prove nothing was written.\n const landscape = await classifyLandscape(docsDir);\n if (\"refusal\" in landscape) {\n return { ok: false, code: \"seed-landscape-edited\", message: landscape.refusal };\n }\n\n let tree: FleetTree;\n try {\n tree = await listFleetTree(docsDir);\n } catch (err) {\n if (!(err instanceof DocsRepoUnavailableError)) throw err;\n return { ok: false, repoGone: err };\n }\n const inconsistency = preflight(tree, req.seed);\n if (inconsistency !== null) return inconsistency;\n\n const plan = await planSeedWrites(req, tree);\n // THE OTHER never-overwrite promise, and the third refusal this window owns.\n //\n // `classifyLandscape` above keeps it for `architecture/landscape.likec4`;\n // this keeps it for the two files seed does not share with the team at all —\n // `architecture/subsystems.likec4` and `architecture/services.likec4` are\n // filenames loam RESERVES inside a directory the team owns, and seed writes\n // them whole. Until this line existed a `loam seed` into a repository that\n // kept a hand-authored diagram at one of those paths destroyed it in\n // silence: the same clobber reproduced through `loam subsystem new`, and the\n // guard that caught it lived in `subsystem sync` alone.\n //\n // THE WHOLE SEED IS REFUSED, exactly as an edited landscape refuses it, and\n // for the same reason: seed regenerates every file it owns wholesale from\n // fleet.yaml, so landing the landscape and the markers while declining a\n // views file would leave a tree whose very next `validate --all` — seed's\n // own `next` command — reports `subsystem.views-stale` over a file no\n // command could ever repair. `planSeedWrites` has staged nothing; the\n // transaction below is the first byte, and it does not run.\n if (plan.authored.length > 0) {\n return {\n ok: false,\n // `already-exists` for the reason commands/subsystem/txn/txn.ts gives at\n // its own copy of this refusal: it is what that code has always meant —\n // refusing to create over something that already exists, because\n // overwriting would destroy work nobody asked to lose.\n code: \"already-exists\",\n message:\n plan.authored.map((file) => authoredRefusal(file)).join(\" \") +\n \" NOTHING was written: not the landscape, not a subsystem marker, not a `.gitkeep`. Seed regenerates \" +\n \"every file it owns wholesale, so it never proceeds past human work standing at one of its paths — the \" +\n \"same promise `seed-landscape-edited` makes one file over.\",\n };\n }\n const staged = await stageWrites(plan.writes);\n const committed = await commitStaged(\n { root: docsDir, command: \"seed\", rerun: req.rerun, target: \"landscape\" },\n staged,\n \"seeded\",\n );\n if (!committed.ok) {\n // `committed.raced` is deliberately NOT remapped: the lock serialises\n // loam writers, so a fired CAS or a lost exclusive create here means an\n // out-of-band editor, and seed has no softer race answer the way `new`\n // has already-exists — merge-failed's \"nothing was written, re-run\" is\n // the honest sentence either way.\n return { ok: false, code: committed.code, message: committed.message };\n }\n return {\n ok: true,\n landscape: landscape.disposition,\n written: plan.writes.filter((w) => w.content !== null).map((w) => w.path),\n removed: plan.writes.filter((w) => w.content === null).map((w) => w.path),\n services: plan.services,\n recovered,\n };\n } finally {\n await opened.release();\n }\n}\n\n/**\n * May seed write the landscape? Absent and untouched-scaffold-stub are the\n * two states with provably no human work in them; a matching stamp digest is\n * the third (`core/c4/seed/stamp.ts`). Everything else refuses.\n */\nasync function classifyLandscape(\n docsDir: DocsDir,\n): Promise<{ disposition: LandscapeDisposition } | { refusal: string }> {\n const path = landscapePath(docsDir);\n if (!existsSync(path)) return { disposition: \"created\" };\n const text = (await readFile(path)).toString(\"utf8\");\n // `isLandscapeStub`, never a byte-compare of our own: that function IS the\n // repo's answer to \"is this still the scaffold's untouched map\", it is what\n // `loam status` reads before telling the reader to run seed, and it is\n // suffix-matched and CRLF-normalised for two reasons seed shares —\n // `migrate-openspec` prepends a preamble to the identical stub, and a\n // checkout under `core.autocrlf` (Git for Windows' installer default)\n // rewrites every line without touching a fact. A stricter compare here made\n // status and seed contradict each other about the same file.\n if (isLandscapeStub(text)) return { disposition: \"replaced-stub\" };\n const provenance = landscapeProvenance(text);\n if (provenance === \"seed-stamped\") return { disposition: \"regenerated\" };\n // The advice used to be \"fold the edits into fleet.yaml and delete the\n // file\", which is impossible for the edit every documented next step makes:\n // the first `metadata { op }` an author or an adopt brief writes onto an edge\n // has no spelling in fleet.yaml (services, subsystems, plain `a -> b` calls),\n // so a reader following it would delete the operation links the spine is\n // graded on. Seed is a day-zero tool; the honest answer names what grows the\n // map after day zero.\n return {\n refusal:\n `architecture/landscape.likec4 ${\n provenance === \"seed-edited\"\n ? \"was seeded but has been hand-edited since — the line-1 stamp's digest no longer matches the content\"\n : \"was not written by `loam seed`: it carries no line-1 stamp and is not the scaffold's untouched stub\"\n }. Seed never overwrites human work; nothing was written. Seed runs once, before anyone ` +\n `draws an operation: fleet.yaml cannot carry \\`metadata { op }\\`, publishes or consumes, so a map ` +\n `holding them is past seeding. Grow it from here without seed — \\`loam adopt --service <id>\\` ` +\n `briefs the element and edges a new service adds, and a feature's C4 delta carries every other ` +\n `change. Only if the edits are things fleet.yaml can say (a service, a subsystem, a plain call) ` +\n `is folding them into fleet.yaml and deleting the file still an option.`,\n };\n}\n\n/**\n * The fleet-consistency preflight. Seed regenerates the landscape WHOLESALE —\n * that is the only posture the stamp can prove safe — so every existing\n * services/<id>/ must be named in fleet.yaml, or the regenerate would orphan\n * it into `landscape.service-unmodelled`. And the file's names must not\n * collide with what the tree already holds under a different kind: one flat\n * namespace, the same rule the walk enforces.\n */\nfunction preflight(tree: FleetTree, seed: FleetSeed): SeedCommit | null {\n const treeSubs = new Set(tree.subsystems.map((s) => s.name));\n const treeIds = new Set(tree.services.map((s) => s.id as string));\n\n // The collision scan runs BEFORE the missing-service scan, and the order is\n // load-bearing. A name the file declares as a subsystem or an external while\n // the tree holds it as a service DIRECTORY is both facts at once: it is a\n // namespace collision, and it is also an existing service the file does not\n // name. With the missing scan first, the caller was told to paste that name\n // into `services:` — advice that walks straight into `seed-duplicate-service`\n // on the next run, because the file already declares it as something else.\n const collisions: string[] = [];\n for (const sub of seed.subsystems) {\n if (treeIds.has(sub as string)) collisions.push(`subsystem '${sub}' is an existing service directory`);\n }\n for (const s of seed.services) {\n if (treeSubs.has(s.id as string)) collisions.push(`service '${s.id}' is an existing subsystem directory`);\n }\n for (const x of seed.externals) {\n if (treeIds.has(x)) collisions.push(`external '${x}' is an existing service directory`);\n if (treeSubs.has(x)) collisions.push(`external '${x}' is an existing subsystem directory`);\n }\n if (collisions.length > 0) {\n return {\n ok: false,\n code: \"seed-file-invalid\",\n message:\n `fleet.yaml collides with the services/ tree — service ids, subsystem names and externals ` +\n `share one flat namespace: ${collisions.join(\"; \")}. Rename the fleet.yaml side (or the ` +\n `directory, with \\`loam subsystem rename <from> <to>\\`), then re-run. Nothing was written.`,\n missingServices: [],\n };\n }\n\n const ids = new Set(seed.services.map((s) => s.id as string));\n const missing = tree.services.map((s) => s.id as string).filter((id) => !ids.has(id)).sort();\n if (missing.length === 0) return null;\n // The ids are partitioned because one half cannot take the other's advice.\n // `tree.services` carries RAW ids — a directory whose name fails the service\n // grammar is still a service to the walk, by design — and \"add it to\n // services: exactly as spelled\" is impossible for one of those: the fleet\n // file would refuse the entry. Without this split, seed was simply unusable\n // on such a repo and never said so.\n const legal = missing.filter((id) => parseServiceId(id, \"services entry\").ok);\n const illegal = missing.filter((id) => !parseServiceId(id, \"services entry\").ok);\n const fixes: string[] = [];\n if (legal.length > 0) fixes.push(`add ${legal.join(\", \")} to services:, exactly as spelled`);\n if (illegal.length > 0) {\n fixes.push(\n `rename the ${illegal.length === 1 ? \"directory\" : \"directories\"} ${illegal.join(\", \")} ` +\n `first — ${illegal.length === 1 ? \"that name is not a legal service id\" : \"those names are not legal service ids\"}, ` +\n `so no services: entry can name ${illegal.length === 1 ? \"it\" : \"them\"}`,\n );\n }\n return {\n ok: false,\n code: \"seed-file-invalid\",\n message:\n `fleet.yaml must name every existing service — seed regenerates the landscape wholesale, ` +\n `and these services/ directories are not in it: ${missing.join(\", \")}. ` +\n `To fix: ${fixes.join(\"; and \")}. Then re-run. Nothing was written.`,\n missingServices: missing,\n };\n}\n"]}
@@ -1,21 +1,125 @@
1
1
  /**
2
2
  * What a seed run will write, decided in full before a byte lands. Split from
3
3
  * `./commit.ts` on the phase seam: that module owns the WINDOW — the lock, the
4
- * interrupted-commit recovery, the two refusals and the transaction — while
4
+ * interrupted-commit recovery, the refusals and the transaction — while
5
5
  * this one answers the single question "given the tree as it is and the fleet
6
6
  * file as it reads, which files change and how". Nothing here acquires
7
7
  * anything, and nothing here writes: it is called under the lock and hands
8
8
  * back a plan the transaction executes or rolls back whole.
9
9
  */
10
- import { existsSync } from "node:fs";
11
- import { readdir, readFile } from "node:fs/promises";
12
- import { join } from "node:path";
10
+ import { copyFile, mkdir, mkdtemp, readdir, rm, writeFile } from "node:fs/promises";
11
+ import { tmpdir } from "node:os";
12
+ import { dirname, join, relative, resolve } from "node:path";
13
+ import { architectureDir, architectureProjectDocuments } from "../../core/c4/project/architecture.js";
14
+ import { loadProject } from "../../core/c4/project/load.js";
15
+ import { repoPath } from "../../core/envelope/json.js";
13
16
  import { serviceDirOf } from "../../core/kernel/ids/dirs.js";
14
- import { landscapePath, servicePathsUnder, servicesDir, subsystemPathUnder, subsystemViewsPath, unfiledServicePaths, } from "../../core/repo/paths.js";
17
+ import { landscapePath, servicePathsUnder, servicesDir, serviceViewsPath, subsystemPathUnder, subsystemViewsPath, unfiledServicePaths, } from "../../core/repo/paths.js";
15
18
  import { SUBSYSTEM_MARKER } from "../../core/repo/tree/marker.js";
16
- import { renderSubsystemViews, viewsAgree } from "../../core/repo/tree/views.js";
19
+ import { readGeneratedFile } from "../../core/repo/tree/render/service/header.js";
20
+ import { renderServiceOverviews, renderSubsystemViews, viewsAgree, } from "../../core/repo/tree/render/views.js";
17
21
  import { TEMP_FILE_RE } from "../../core/staging/commit.js";
18
22
  import { planWrite } from "../../core/staging/writes.js";
23
+ /**
24
+ * The facts the generated views are rendered from: the `architecture/` PROJECT
25
+ * as this commit leaves it — the sealed landscape standing in for the file it is
26
+ * about to become, beside every other `.likec4` the directory already holds —
27
+ * and never the sealed landscape alone.
28
+ *
29
+ * WHY THE PROJECT. `subsystem.views-stale` (`validate --all`) and `loam
30
+ * subsystem sync` both recompute the expected bytes from `loadArchitecture` —
31
+ * the landscape merged with every other `architecture/**` document, the
32
+ * generated file excluded — and the render asks that document set which global
33
+ * style ids it declares. A repository's `global { styleGroup subsystems { … } }`
34
+ * naturally lives in a sibling such as `architecture/usecases/palette.likec4`,
35
+ * since seed regenerates the landscape wholesale, so it was in the grader's
36
+ * census and not in seed's: a seed into such a repo wrote a views file the very
37
+ * next `validate --all` — seed's own first `next` command — graded stale, and
38
+ * re-seeding wrote the same bytes again, the one loop no `next` could leave.
39
+ * Reading the same documents the grader reads is what makes the shared render
40
+ * shared in fact rather than in name (commands/subsystem/txn/views.ts's banner).
41
+ *
42
+ * NO SIBLING, NO WORKSPACE: the landscape's own facts, already in hand from the
43
+ * self-check, ARE the project's, and the common case pays one readdir.
44
+ *
45
+ * STAGED, for `core/c4/project/staged.ts`'s reason: `loadProject` copies
46
+ * documents from disk keyed on their path relative to a base, and the landscape
47
+ * here exists only in memory. That module's staging is bound to a feature's
48
+ * merge preview, so the same handful of copies is made here once more — the
49
+ * temp tree is gone before this returns, and nothing under the docs repo is
50
+ * touched.
51
+ *
52
+ * FAIL CLOSED to the landscape's own facts. A project that does not parse (a
53
+ * sibling carrying an error of its own, or a copy the temp directory refused)
54
+ * declares nothing loam can rely on, so the render carries exactly what it
55
+ * carried before the project was asked, and the seed still lands: that sibling
56
+ * is `landscape.invalid`'s to name on the next `validate --all`, and a seed
57
+ * refusing over it would make seed the first command to grade a file it does
58
+ * not own. Nothing is hidden by the fallback: the grader compares the views
59
+ * file only once the project has parsed (`validate/fleet/landscape.ts`), so
60
+ * the repo sees the one finding that names the sibling, never a stale-views
61
+ * finding over a file no command could have rendered differently.
62
+ */
63
+ async function projectFacts(req) {
64
+ const arch = architectureDir(req.docsDir);
65
+ const landscape = resolve(landscapePath(req.docsDir));
66
+ // The PROJECT's documents, root `exclude` applied — `loadArchitecture`'s own
67
+ // list minus the landscape, which is staged from memory just below. Walking
68
+ // `architecture/` directly skipped that filter, and here that is a WRONG
69
+ // answer rather than an over-scan: a `palette.likec4` under an excluded path
70
+ // is a document the renderer never loads, so its `global styleGroup` id put
71
+ // `global style subsystems` into the generated views file — a name the fleet
72
+ // project cannot resolve — and the very next `validate --all` (seed's own
73
+ // `next` command) graded that file against the same set THIS one now reads.
74
+ // The W5b defect, one command over.
75
+ const siblings = (await architectureProjectDocuments(req.docsDir)).filter((p) => resolve(p) !== landscape);
76
+ if (siblings.length === 0)
77
+ return req.map;
78
+ // The temp directory is made INSIDE the try, not one line above it: a full
79
+ // disk, a read-only temp root, or a TMPDIR naming a directory that no longer
80
+ // exists rejects `mkdtemp`, and outside the try that rejection left `seed` as
81
+ // the generic `internal` refusal on a repository where nothing is wrong — the
82
+ // defect docs/CODE-STYLE.md's "read inside the try that handles the read" rule
83
+ // was written from.
84
+ let root = null;
85
+ try {
86
+ root = await mkdtemp(join(tmpdir(), "loam-seed-"));
87
+ const staged = [];
88
+ for (const path of [landscape, ...siblings]) {
89
+ const dest = join(root, relative(arch, path));
90
+ await mkdir(dirname(dest), { recursive: true });
91
+ // The landscape is staged from the bytes this commit writes, never from
92
+ // the file on disk — which may be the scaffold's stub, a stamped
93
+ // predecessor, or absent — so the project parsed is the one the grader
94
+ // will read after the commit.
95
+ if (path === landscape)
96
+ await writeFile(dest, req.landscape, "utf8");
97
+ else
98
+ await copyFile(path, dest);
99
+ staged.push(dest);
100
+ }
101
+ const project = await loadProject(root, staged);
102
+ // RELATIONSHIPS travel with the elements, and dropping them is silent: they
103
+ // are what each per-service overview computes its peer set from, so a facts
104
+ // record without them renders every service view peerless — the service and
105
+ // its own interior, and nothing it touches — with no error anywhere
106
+ // (`core/repo/tree/render/views.ts` states the consequence beside the
107
+ // optional field). The fallback `req.map` is the whole self-check document
108
+ // and already carries them.
109
+ return project.clean
110
+ ? { elements: project.elements, globalStyles: project.globalStyles, relationships: project.relationships }
111
+ : req.map;
112
+ }
113
+ catch {
114
+ // `loadProject` throws on an error it cannot attribute to a document, and
115
+ // a full disk fails the staging above; both are the fail-closed arm.
116
+ return req.map;
117
+ }
118
+ finally {
119
+ if (root !== null)
120
+ await rm(root, { recursive: true, force: true });
121
+ }
122
+ }
19
123
  /**
20
124
  * Does this existing service directory hold nothing git would keep? An empty
21
125
  * directory is a service to the walk but nothing at all to git, so a landscape
@@ -122,12 +226,53 @@ export async function planSeedWrites(req, tree) {
122
226
  // to disk that writes.ts forbids; a views file whose bytes are not UTF-8
123
227
  // therefore fails the compare and is regenerated, which is the right answer
124
228
  // for it anyway.
125
- const viewsPath = subsystemViewsPath(docsDir);
126
- const views = renderSubsystemViews(plannedTree, req.elements);
127
- const wanted = views === null ? null : Buffer.from(views, "utf8");
128
- const onDisk = existsSync(viewsPath) ? await readFile(viewsPath, "utf8") : null;
129
- if (!viewsAgree(onDisk, views))
130
- writes.push({ path: viewsPath, content: wanted });
131
- return { writes, services: { created: created.sort(), existing: existing.sort() } };
229
+ //
230
+ // BOTH generated files, from ONE read of the project: `architecture/services.likec4`
231
+ // is the same contract one file over — one overview view per service the map
232
+ // draws, absent when it draws none — and a seed that landed only the subsystem
233
+ // views would send its caller, through its own `next` list, into a
234
+ // `subsystem.views-stale` no `seed` could clear. This is where the seeded
235
+ // services first exist AND the sealed landscape first says what they are, so
236
+ // it is the only moment the pair can be rendered together.
237
+ const facts = await projectFacts(req);
238
+ const authored = [
239
+ await stageGenerated(writes, subsystemViewsPath(docsDir), renderSubsystemViews(plannedTree, facts)),
240
+ await stageGenerated(writes, serviceViewsPath(docsDir), renderServiceOverviews(plannedTree, facts)),
241
+ ].filter((path) => path !== null);
242
+ return {
243
+ writes,
244
+ services: { created: created.sort(), existing: existing.sort() },
245
+ authored: authored.map((path) => repoPath(docsDir, path)),
246
+ };
247
+ }
248
+ /**
249
+ * Append the write for ONE generated file, or nothing when the file already
250
+ * says it — the comparison the block above argues for, spelled once so the two
251
+ * generated files cannot drift into two rules. Answers the path when the file
252
+ * standing there is SOMEBODY ELSE'S, and stages nothing for it.
253
+ *
254
+ * OWNERSHIP FIRST, before the compare, exactly as `commands/subsystem/sync.ts`
255
+ * asks it — through the same reader, from beneath every writer
256
+ * (`core/repo/tree/render/service/header.ts`). Both of these are filenames loam
257
+ * RESERVES inside `architecture/`, a directory the team owns, and seed rewrites
258
+ * them whole; until this line existed a `loam seed` into a repository that kept
259
+ * a hand-authored diagram at one of those paths destroyed it without a word.
260
+ * That is the same promise `seed-landscape-edited` makes one file over — seed
261
+ * never overwrites human work — and it was missing for the two files seed
262
+ * reserves rather than shares.
263
+ *
264
+ * It is checked before the compare and not after, so that "the file already says
265
+ * this" can never vouch for a file loam did not write. An authored file cannot
266
+ * in fact agree with a render that opens with loam's mark, but a reader must not
267
+ * have to prove that to know the guard holds.
268
+ */
269
+ async function stageGenerated(writes, path, content) {
270
+ const { text: onDisk, authored } = await readGeneratedFile(path);
271
+ if (authored)
272
+ return path;
273
+ if (viewsAgree(onDisk, content))
274
+ return null;
275
+ writes.push({ path, content: content === null ? null : Buffer.from(content, "utf8") });
276
+ return null;
132
277
  }
133
278
  //# sourceMappingURL=plan.js.map