@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
package/dist/cli.js CHANGED
@@ -11,6 +11,7 @@ import { registerShow } from "./commands/show/show.js";
11
11
  import { registerStatus } from "./commands/status/status.js";
12
12
  import { registerSubsystem } from "./commands/subsystem/subsystem.js";
13
13
  import { registerDelta } from "./commands/delta/delta.js";
14
+ import { registerTasks } from "./commands/tasks/tasks.js";
14
15
  import { registerDiff } from "./commands/diff/diff.js";
15
16
  import { registerGherkin } from "./commands/gherkin/gherkin.js";
16
17
  import { registerRebase } from "./commands/rebase/rebase.js";
@@ -30,7 +31,7 @@ import { registerOpen } from "./commands/open.js";
30
31
  import { registerInstructions } from "./commands/instructions.js";
31
32
  import { registerExplain } from "./commands/explain/explain.js";
32
33
  import { registerMigrateOpenSpec } from "./commands/migrate-openspec/migrate-openspec.js";
33
- import { emitJsonError } from "./core/envelope/json.js";
34
+ import { emitJsonError, sayExplain } from "./core/envelope/json.js";
34
35
  import { LOAM_VERSION } from "./core/envelope/version.js";
35
36
  /**
36
37
  * The whole CLI surface, as a program nobody has parsed yet.
@@ -69,6 +70,7 @@ export function buildProgram() {
69
70
  registerStatus(program);
70
71
  registerSubsystem(program);
71
72
  registerDelta(program);
73
+ registerTasks(program);
72
74
  registerDiff(program);
73
75
  registerGherkin(program);
74
76
  registerRebase(program);
@@ -93,10 +95,10 @@ export function buildProgram() {
93
95
  * The two lines under the command list: where to start, and what to run when
94
96
  * lost.
95
97
  *
96
- * {@link HELP_GROUPS} does nearly all of the orienting work — twenty-nine
98
+ * {@link HELP_GROUPS} does nearly all of the orienting work — thirty
97
99
  * commands under seven headings, in the order of the work — but it stops one
98
100
  * step short of the two facts a newcomer does not have. Nothing on the page
99
- * said that `init` must run before any of the other twenty-eight, and nothing
101
+ * said that `init` must run before any of the others, and nothing
100
102
  * named the command that answers "what now"; the last thing a first
101
103
  * `loam --help` printed was `help [command]`.
102
104
  *
@@ -123,7 +125,7 @@ export const HELP_EPILOG = [
123
125
  * protocols (`loam instructions`) rather than inventing a second taxonomy, so a
124
126
  * reader who has met one has met the other.
125
127
  *
126
- * Twenty-nine commands printed as one flat registration-ordered list tells a
128
+ * Thirty commands printed as one flat registration-ordered list tells a
127
129
  * new reader nothing about which four to run first. NOTHING IS HIDDEN — a
128
130
  * hidden command is a command an agent cannot discover, and every one of these
129
131
  * still parses, still appears, and still carries the same flags. This is
@@ -135,7 +137,7 @@ const HELP_GROUPS = {
135
137
  explore: "Read the fleet", context: "Read the fleet", dependencies: "Read the fleet",
136
138
  explain: "Read the fleet", instructions: "Read the fleet", steps: "Read the fleet",
137
139
  adopt: "Adopt what exists", vouch: "Adopt what exists",
138
- new: "Change it", delta: "Change it", gherkin: "Change it", rebase: "Change it",
140
+ new: "Change it", delta: "Change it", tasks: "Change it", gherkin: "Change it", rebase: "Change it",
139
141
  subsystem: "Change it",
140
142
  validate: "Check it", diff: "Check it", verify: "Check it", gate: "Check it",
141
143
  archive: "Ship it", unarchive: "Ship it",
@@ -144,7 +146,7 @@ const HELP_GROUPS = {
144
146
  /**
145
147
  * Apply {@link HELP_GROUPS}, and FAIL CLOSED on a command it does not name.
146
148
  *
147
- * The throw is the point. A thirtieth command added without a heading would
149
+ * The throw is the point. A thirty-first command added without a heading would
148
150
  * otherwise land silently in an "unclassified" bucket at the bottom of the
149
151
  * page, which is the drift this whole file's neighbours are written to prevent;
150
152
  * `test/help-groups.test.ts` catches it at gate time, and this catches it the
@@ -162,6 +164,19 @@ function groupCommands(program) {
162
164
  }
163
165
  /** CommanderError codes whose output (already printed) is the point, not a failure to wrap. */
164
166
  const PASS_THROUGH = new Set(["commander.help", "commander.helpDisplayed", "commander.version"]);
167
+ /**
168
+ * What a text-mode usage error prints under commander's own diagnostic: the
169
+ * fix and the stable code, the two lines every other refusal carries through
170
+ * `fail`. Without them `loam diff` with no `--base` printed commander's one
171
+ * sentence and nothing else — the only refusals in the CLI a person could not
172
+ * look up, while `--json` already reported them as `invalid-option`.
173
+ */
174
+ function sayUsageFix(program) {
175
+ const name = process.argv.slice(2).find((token) => program.commands.some((c) => c.name() === token));
176
+ const help = name === undefined ? "`loam --help` lists the commands" : `\`loam ${name} --help\` lists the arguments and options it takes`;
177
+ console.error(`Fix the invocation: ${help}.`);
178
+ sayExplain("invalid-option");
179
+ }
165
180
  function main() {
166
181
  const program = buildProgram();
167
182
  // Set once a command's action actually runs: every subcommand declares its own
@@ -194,8 +209,11 @@ function main() {
194
209
  // Anything else is a usage error (unknown option/command, missing or
195
210
  // invalid argument). Commander has already printed its diagnostic to
196
211
  // stderr, and that line stays: the invariant below is about stdout only.
197
- if (!PASS_THROUGH.has(err.code) && jsonRequested()) {
198
- emitJsonError("invalid-option", err.message.replace(/^error: /, ""));
212
+ if (!PASS_THROUGH.has(err.code)) {
213
+ if (jsonRequested())
214
+ emitJsonError("invalid-option", err.message.replace(/^error: /, ""));
215
+ else
216
+ sayUsageFix(program);
199
217
  }
200
218
  process.exitCode = err.exitCode;
201
219
  return;
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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","sourcesContent":["#!/usr/bin/env node\nimport { Command, CommanderError } from \"commander\";\nimport { realpathSync } from \"node:fs\";\nimport { fileURLToPath } from \"node:url\";\nimport { registerInit } from \"./commands/init/init.js\";\nimport { registerAdopt } from \"./commands/adopt/adopt.js\";\nimport { registerList } from \"./commands/list/list.js\";\nimport { registerNew } from \"./commands/new/new.js\";\nimport { registerSeed } from \"./commands/seed/seed.js\";\nimport { registerShow } from \"./commands/show/show.js\";\nimport { registerStatus } from \"./commands/status/status.js\";\nimport { registerSubsystem } from \"./commands/subsystem/subsystem.js\";\nimport { registerDelta } from \"./commands/delta/delta.js\";\nimport { registerDiff } from \"./commands/diff/diff.js\";\nimport { registerGherkin } from \"./commands/gherkin/gherkin.js\";\nimport { registerRebase } from \"./commands/rebase/rebase.js\";\nimport { registerArchive } from \"./commands/archive/archive.js\";\nimport { registerUnarchive } from \"./commands/unarchive/unarchive.js\";\nimport { registerValidate } from \"./commands/validate/validate.js\";\nimport { registerVerify } from \"./commands/verify/verify.js\";\nimport { registerVouch } from \"./commands/vouch/vouch.js\";\nimport { registerGate } from \"./commands/gate/gate.js\";\nimport { registerDoctor } from \"./commands/doctor.js\";\nimport { registerDependencies } from \"./commands/dependencies.js\";\nimport { registerSteps } from \"./commands/steps/steps.js\";\nimport { registerExplore } from \"./commands/explore.js\";\nimport { registerContext } from \"./commands/context/context.js\";\nimport { registerMcp } from \"./commands/mcp/mcp.js\";\nimport { registerOpen } from \"./commands/open.js\";\nimport { registerInstructions } from \"./commands/instructions.js\";\nimport { registerExplain } from \"./commands/explain/explain.js\";\nimport { registerMigrateOpenSpec } from \"./commands/migrate-openspec/migrate-openspec.js\";\nimport { emitJsonError } from \"./core/envelope/json.js\";\nimport { LOAM_VERSION } from \"./core/envelope/version.js\";\n\n/**\n * The whole CLI surface, as a program nobody has parsed yet.\n *\n * Exported because loam PRINTS commands — every `loam …` in AGENTS.md, in the\n * generated command and skill bodies, in a `doctor` finding's `fix` and in a\n * `status` next[] step is an instruction somebody (usually an agent) will type\n * back. The only way to prove one of those parses is to hand it to the program\n * that would receive it; a second copy of the registrations in a test agrees\n * with itself and with nothing else, which is exactly how\n * `Run \\`loam adopt <id>\\`` shipped as the first instruction a bound service\n * repo received. `test/agent-commands-runnable.test.ts` is the consumer.\n */\nexport function buildProgram(): Command {\n const program = new Command();\n\n program\n .name(\"loam\")\n .description(\"Architecture-first semantic integrity and change governance for evolving software systems\")\n .version(LOAM_VERSION)\n // The blank line is part of the attachment, not part of the text: commander\n // writes this straight under the `Commands:` block, and two sentences flush\n // against `help [command]` read as two more commands.\n .addHelpText(\"after\", `\\n${HELP_EPILOG}`);\n\n // Make commander throw a CommanderError instead of process.exit()ing, so a\n // usage error (mistyped flag, unknown command) can still honour the envelope\n // invariant in the catch below instead of dying with an empty stdout.\n program.exitOverride();\n\n registerInit(program);\n registerAdopt(program);\n registerList(program);\n registerExplore(program);\n registerContext(program);\n registerNew(program);\n registerSeed(program);\n registerShow(program);\n registerStatus(program);\n registerSubsystem(program);\n registerDelta(program);\n registerDiff(program);\n registerGherkin(program);\n registerRebase(program);\n registerArchive(program);\n registerUnarchive(program);\n registerValidate(program);\n registerVerify(program);\n registerVouch(program);\n registerGate(program);\n registerDoctor(program);\n registerDependencies(program);\n registerSteps(program);\n registerMcp(program);\n registerInstructions(program);\n registerExplain(program);\n registerOpen(program);\n registerMigrateOpenSpec(program);\n\n groupCommands(program);\n\n return program;\n}\n\n/**\n * The two lines under the command list: where to start, and what to run when\n * lost.\n *\n * {@link HELP_GROUPS} does nearly all of the orienting work — twenty-nine\n * commands under seven headings, in the order of the work — but it stops one\n * step short of the two facts a newcomer does not have. Nothing on the page\n * said that `init` must run before any of the other twenty-eight, and nothing\n * named the command that answers \"what now\"; the last thing a first\n * `loam --help` printed was `help [command]`.\n *\n * Two lines, and no more, because the grouping is what does the work and a\n * paragraph here would compete with it.\n *\n * Both lines name a command that PARSES, and that is not a style rule:\n * `test/agent-commands-runnable.test.ts` takes this constant BY IMPORT and\n * hands both invocations to the real program, exactly as it does the `init`\n * first-hour lines. `loam init --create` is the form that works with no prior\n * knowledge — bare `loam init` defaults `--docs` to a `.loam-docs` that does\n * not exist yet and refuses, which is correct for a repo joining an existing\n * docs repo and wrong as the first thing a newcomer is told to type.\n */\nexport const HELP_EPILOG = [\n \"New here? Run `loam init --create` first — every other command needs the docs repo it writes.\",\n \"Lost? Run `loam doctor` — it prints the state, the resolved path, the finding code and a `fix:` line.\",\n].join(\"\\n\");\n\n/**\n * Which heading each command sits under in `loam --help`.\n *\n * The order is the order of the work: wire the repo, read the fleet, adopt what\n * exists, change it, check it, ship it. It mirrors the six shipped workflow\n * protocols (`loam instructions`) rather than inventing a second taxonomy, so a\n * reader who has met one has met the other.\n *\n * Twenty-nine commands printed as one flat registration-ordered list tells a\n * new reader nothing about which four to run first. NOTHING IS HIDDEN — a\n * hidden command is a command an agent cannot discover, and every one of these\n * still parses, still appears, and still carries the same flags. This is\n * typography, not surface.\n */\nconst HELP_GROUPS: Record<string, string> = {\n init: \"Set up\", seed: \"Set up\", doctor: \"Set up\", open: \"Set up\", mcp: \"Set up\",\n list: \"Read the fleet\", status: \"Read the fleet\", show: \"Read the fleet\",\n explore: \"Read the fleet\", context: \"Read the fleet\", dependencies: \"Read the fleet\",\n explain: \"Read the fleet\", instructions: \"Read the fleet\", steps: \"Read the fleet\",\n adopt: \"Adopt what exists\", vouch: \"Adopt what exists\",\n new: \"Change it\", delta: \"Change it\", gherkin: \"Change it\", rebase: \"Change it\",\n subsystem: \"Change it\",\n validate: \"Check it\", diff: \"Check it\", verify: \"Check it\", gate: \"Check it\",\n archive: \"Ship it\", unarchive: \"Ship it\",\n \"audit-openspec\": \"Migrate\", \"migrate-openspec\": \"Migrate\",\n};\n\n/**\n * Apply {@link HELP_GROUPS}, and FAIL CLOSED on a command it does not name.\n *\n * The throw is the point. A thirtieth command added without a heading would\n * otherwise land silently in an \"unclassified\" bucket at the bottom of the\n * page, which is the drift this whole file's neighbours are written to prevent;\n * `test/help-groups.test.ts` catches it at gate time, and this catches it the\n * first time anybody runs the binary. Same discipline as\n * `test/codes-drift.test.ts` applies to codes.\n */\nfunction groupCommands(program: Command): void {\n for (const command of program.commands) {\n const group = HELP_GROUPS[command.name()];\n if (group === undefined) {\n throw new Error(`cli: command '${command.name()}' has no HELP_GROUPS heading — add one in src/cli.ts`);\n }\n command.helpGroup(group);\n }\n}\n\n/** CommanderError codes whose output (already printed) is the point, not a failure to wrap. */\nconst PASS_THROUGH = new Set([\"commander.help\", \"commander.helpDisplayed\", \"commander.version\"]);\n\nfunction main(): void {\n const program = buildProgram();\n\n // Set once a command's action actually runs: every subcommand declares its own\n // `--json`, so past that point the parsed option is the authoritative answer.\n let parsedJson: boolean | undefined;\n program.hook(\"preAction\", (_thisCommand, actionCommand) => {\n parsedJson = Boolean((actionCommand.optsWithGlobals() as { json?: boolean }).json);\n });\n\n /**\n * Did this invocation ask for --json? Prefers the parsed option once an action\n * has run; before that (commander usage errors abort mid-parse) falls back to\n * scanning raw argv. The scan is a heuristic and cannot be made exact: a token\n * spelled `--json` that was meant as an option VALUE (e.g. --title \"--json\")\n * is indistinguishable from the flag in raw argv. It gets the common cases\n * right: a `--json` token anywhere before a `--` terminator counts, and tokens\n * after `--` never do.\n */\n const jsonRequested = (): boolean => {\n if (parsedJson !== undefined) return parsedJson;\n const argv = process.argv.slice(2);\n const terminator = argv.indexOf(\"--\");\n return (terminator === -1 ? argv : argv.slice(0, terminator)).includes(\"--json\");\n };\n\n program.parseAsync(process.argv).catch((err: unknown) => {\n if (err instanceof CommanderError) {\n // Help/version output was already written by commander — pass it through\n // untouched with the exit code it always had.\n //\n // Anything else is a usage error (unknown option/command, missing or\n // invalid argument). Commander has already printed its diagnostic to\n // stderr, and that line stays: the invariant below is about stdout only.\n if (!PASS_THROUGH.has(err.code) && jsonRequested()) {\n emitJsonError(\"invalid-option\", err.message.replace(/^error: /, \"\"));\n }\n process.exitCode = err.exitCode;\n return;\n }\n const message = err instanceof Error ? err.message : String(err);\n // The envelope's one hard invariant is that stdout is JSON whenever --json\n // was asked for — an unexpected throw must not be the exception to it.\n if (jsonRequested()) {\n emitJsonError(\"internal\", message);\n } else {\n console.error(message);\n process.exitCode = 1;\n }\n });\n}\n\n/**\n * Was this file run, or merely imported? Realpath on both sides because the\n * installed entry point is reached through a symlink (`node_modules/.bin/loam`)\n * on every platform that has them, and a string compare against the link would\n * make the binary a no-op. A failure to resolve reads as \"not the entry\" only\n * for the import side; `process.argv[1]` that cannot be realpath'd is not a\n * loam invocation either.\n */\nfunction invokedDirectly(): boolean {\n const entry = process.argv[1];\n if (entry === undefined) return false;\n try {\n return realpathSync(entry) === realpathSync(fileURLToPath(import.meta.url));\n } catch {\n return false;\n }\n}\n\nif (invokedDirectly()) main();\n"]}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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","sourcesContent":["#!/usr/bin/env node\nimport { Command, CommanderError } from \"commander\";\nimport { realpathSync } from \"node:fs\";\nimport { fileURLToPath } from \"node:url\";\nimport { registerInit } from \"./commands/init/init.js\";\nimport { registerAdopt } from \"./commands/adopt/adopt.js\";\nimport { registerList } from \"./commands/list/list.js\";\nimport { registerNew } from \"./commands/new/new.js\";\nimport { registerSeed } from \"./commands/seed/seed.js\";\nimport { registerShow } from \"./commands/show/show.js\";\nimport { registerStatus } from \"./commands/status/status.js\";\nimport { registerSubsystem } from \"./commands/subsystem/subsystem.js\";\nimport { registerDelta } from \"./commands/delta/delta.js\";\nimport { registerTasks } from \"./commands/tasks/tasks.js\";\nimport { registerDiff } from \"./commands/diff/diff.js\";\nimport { registerGherkin } from \"./commands/gherkin/gherkin.js\";\nimport { registerRebase } from \"./commands/rebase/rebase.js\";\nimport { registerArchive } from \"./commands/archive/archive.js\";\nimport { registerUnarchive } from \"./commands/unarchive/unarchive.js\";\nimport { registerValidate } from \"./commands/validate/validate.js\";\nimport { registerVerify } from \"./commands/verify/verify.js\";\nimport { registerVouch } from \"./commands/vouch/vouch.js\";\nimport { registerGate } from \"./commands/gate/gate.js\";\nimport { registerDoctor } from \"./commands/doctor.js\";\nimport { registerDependencies } from \"./commands/dependencies.js\";\nimport { registerSteps } from \"./commands/steps/steps.js\";\nimport { registerExplore } from \"./commands/explore.js\";\nimport { registerContext } from \"./commands/context/context.js\";\nimport { registerMcp } from \"./commands/mcp/mcp.js\";\nimport { registerOpen } from \"./commands/open.js\";\nimport { registerInstructions } from \"./commands/instructions.js\";\nimport { registerExplain } from \"./commands/explain/explain.js\";\nimport { registerMigrateOpenSpec } from \"./commands/migrate-openspec/migrate-openspec.js\";\nimport { emitJsonError, sayExplain } from \"./core/envelope/json.js\";\nimport { LOAM_VERSION } from \"./core/envelope/version.js\";\n\n/**\n * The whole CLI surface, as a program nobody has parsed yet.\n *\n * Exported because loam PRINTS commands — every `loam …` in AGENTS.md, in the\n * generated command and skill bodies, in a `doctor` finding's `fix` and in a\n * `status` next[] step is an instruction somebody (usually an agent) will type\n * back. The only way to prove one of those parses is to hand it to the program\n * that would receive it; a second copy of the registrations in a test agrees\n * with itself and with nothing else, which is exactly how\n * `Run \\`loam adopt <id>\\`` shipped as the first instruction a bound service\n * repo received. `test/agent-commands-runnable.test.ts` is the consumer.\n */\nexport function buildProgram(): Command {\n const program = new Command();\n\n program\n .name(\"loam\")\n .description(\"Architecture-first semantic integrity and change governance for evolving software systems\")\n .version(LOAM_VERSION)\n // The blank line is part of the attachment, not part of the text: commander\n // writes this straight under the `Commands:` block, and two sentences flush\n // against `help [command]` read as two more commands.\n .addHelpText(\"after\", `\\n${HELP_EPILOG}`);\n\n // Make commander throw a CommanderError instead of process.exit()ing, so a\n // usage error (mistyped flag, unknown command) can still honour the envelope\n // invariant in the catch below instead of dying with an empty stdout.\n program.exitOverride();\n\n registerInit(program);\n registerAdopt(program);\n registerList(program);\n registerExplore(program);\n registerContext(program);\n registerNew(program);\n registerSeed(program);\n registerShow(program);\n registerStatus(program);\n registerSubsystem(program);\n registerDelta(program);\n registerTasks(program);\n registerDiff(program);\n registerGherkin(program);\n registerRebase(program);\n registerArchive(program);\n registerUnarchive(program);\n registerValidate(program);\n registerVerify(program);\n registerVouch(program);\n registerGate(program);\n registerDoctor(program);\n registerDependencies(program);\n registerSteps(program);\n registerMcp(program);\n registerInstructions(program);\n registerExplain(program);\n registerOpen(program);\n registerMigrateOpenSpec(program);\n\n groupCommands(program);\n\n return program;\n}\n\n/**\n * The two lines under the command list: where to start, and what to run when\n * lost.\n *\n * {@link HELP_GROUPS} does nearly all of the orienting work — thirty\n * commands under seven headings, in the order of the work — but it stops one\n * step short of the two facts a newcomer does not have. Nothing on the page\n * said that `init` must run before any of the others, and nothing\n * named the command that answers \"what now\"; the last thing a first\n * `loam --help` printed was `help [command]`.\n *\n * Two lines, and no more, because the grouping is what does the work and a\n * paragraph here would compete with it.\n *\n * Both lines name a command that PARSES, and that is not a style rule:\n * `test/agent-commands-runnable.test.ts` takes this constant BY IMPORT and\n * hands both invocations to the real program, exactly as it does the `init`\n * first-hour lines. `loam init --create` is the form that works with no prior\n * knowledge — bare `loam init` defaults `--docs` to a `.loam-docs` that does\n * not exist yet and refuses, which is correct for a repo joining an existing\n * docs repo and wrong as the first thing a newcomer is told to type.\n */\nexport const HELP_EPILOG = [\n \"New here? Run `loam init --create` first — every other command needs the docs repo it writes.\",\n \"Lost? Run `loam doctor` — it prints the state, the resolved path, the finding code and a `fix:` line.\",\n].join(\"\\n\");\n\n/**\n * Which heading each command sits under in `loam --help`.\n *\n * The order is the order of the work: wire the repo, read the fleet, adopt what\n * exists, change it, check it, ship it. It mirrors the six shipped workflow\n * protocols (`loam instructions`) rather than inventing a second taxonomy, so a\n * reader who has met one has met the other.\n *\n * Thirty commands printed as one flat registration-ordered list tells a\n * new reader nothing about which four to run first. NOTHING IS HIDDEN — a\n * hidden command is a command an agent cannot discover, and every one of these\n * still parses, still appears, and still carries the same flags. This is\n * typography, not surface.\n */\nconst HELP_GROUPS: Record<string, string> = {\n init: \"Set up\", seed: \"Set up\", doctor: \"Set up\", open: \"Set up\", mcp: \"Set up\",\n list: \"Read the fleet\", status: \"Read the fleet\", show: \"Read the fleet\",\n explore: \"Read the fleet\", context: \"Read the fleet\", dependencies: \"Read the fleet\",\n explain: \"Read the fleet\", instructions: \"Read the fleet\", steps: \"Read the fleet\",\n adopt: \"Adopt what exists\", vouch: \"Adopt what exists\",\n new: \"Change it\", delta: \"Change it\", tasks: \"Change it\", gherkin: \"Change it\", rebase: \"Change it\",\n subsystem: \"Change it\",\n validate: \"Check it\", diff: \"Check it\", verify: \"Check it\", gate: \"Check it\",\n archive: \"Ship it\", unarchive: \"Ship it\",\n \"audit-openspec\": \"Migrate\", \"migrate-openspec\": \"Migrate\",\n};\n\n/**\n * Apply {@link HELP_GROUPS}, and FAIL CLOSED on a command it does not name.\n *\n * The throw is the point. A thirty-first command added without a heading would\n * otherwise land silently in an \"unclassified\" bucket at the bottom of the\n * page, which is the drift this whole file's neighbours are written to prevent;\n * `test/help-groups.test.ts` catches it at gate time, and this catches it the\n * first time anybody runs the binary. Same discipline as\n * `test/codes-drift.test.ts` applies to codes.\n */\nfunction groupCommands(program: Command): void {\n for (const command of program.commands) {\n const group = HELP_GROUPS[command.name()];\n if (group === undefined) {\n throw new Error(`cli: command '${command.name()}' has no HELP_GROUPS heading — add one in src/cli.ts`);\n }\n command.helpGroup(group);\n }\n}\n\n/** CommanderError codes whose output (already printed) is the point, not a failure to wrap. */\nconst PASS_THROUGH = new Set([\"commander.help\", \"commander.helpDisplayed\", \"commander.version\"]);\n\n/**\n * What a text-mode usage error prints under commander's own diagnostic: the\n * fix and the stable code, the two lines every other refusal carries through\n * `fail`. Without them `loam diff` with no `--base` printed commander's one\n * sentence and nothing else — the only refusals in the CLI a person could not\n * look up, while `--json` already reported them as `invalid-option`.\n */\nfunction sayUsageFix(program: Command): void {\n const name = process.argv.slice(2).find((token) => program.commands.some((c) => c.name() === token));\n const help = name === undefined ? \"`loam --help` lists the commands\" : `\\`loam ${name} --help\\` lists the arguments and options it takes`;\n console.error(`Fix the invocation: ${help}.`);\n sayExplain(\"invalid-option\");\n}\n\nfunction main(): void {\n const program = buildProgram();\n\n // Set once a command's action actually runs: every subcommand declares its own\n // `--json`, so past that point the parsed option is the authoritative answer.\n let parsedJson: boolean | undefined;\n program.hook(\"preAction\", (_thisCommand, actionCommand) => {\n parsedJson = Boolean((actionCommand.optsWithGlobals() as { json?: boolean }).json);\n });\n\n /**\n * Did this invocation ask for --json? Prefers the parsed option once an action\n * has run; before that (commander usage errors abort mid-parse) falls back to\n * scanning raw argv. The scan is a heuristic and cannot be made exact: a token\n * spelled `--json` that was meant as an option VALUE (e.g. --title \"--json\")\n * is indistinguishable from the flag in raw argv. It gets the common cases\n * right: a `--json` token anywhere before a `--` terminator counts, and tokens\n * after `--` never do.\n */\n const jsonRequested = (): boolean => {\n if (parsedJson !== undefined) return parsedJson;\n const argv = process.argv.slice(2);\n const terminator = argv.indexOf(\"--\");\n return (terminator === -1 ? argv : argv.slice(0, terminator)).includes(\"--json\");\n };\n\n program.parseAsync(process.argv).catch((err: unknown) => {\n if (err instanceof CommanderError) {\n // Help/version output was already written by commander — pass it through\n // untouched with the exit code it always had.\n //\n // Anything else is a usage error (unknown option/command, missing or\n // invalid argument). Commander has already printed its diagnostic to\n // stderr, and that line stays: the invariant below is about stdout only.\n if (!PASS_THROUGH.has(err.code)) {\n if (jsonRequested()) emitJsonError(\"invalid-option\", err.message.replace(/^error: /, \"\"));\n else sayUsageFix(program);\n }\n process.exitCode = err.exitCode;\n return;\n }\n const message = err instanceof Error ? err.message : String(err);\n // The envelope's one hard invariant is that stdout is JSON whenever --json\n // was asked for — an unexpected throw must not be the exception to it.\n if (jsonRequested()) {\n emitJsonError(\"internal\", message);\n } else {\n console.error(message);\n process.exitCode = 1;\n }\n });\n}\n\n/**\n * Was this file run, or merely imported? Realpath on both sides because the\n * installed entry point is reached through a symlink (`node_modules/.bin/loam`)\n * on every platform that has them, and a string compare against the link would\n * make the binary a no-op. A failure to resolve reads as \"not the entry\" only\n * for the import side; `process.argv[1]` that cannot be realpath'd is not a\n * loam invocation either.\n */\nfunction invokedDirectly(): boolean {\n const entry = process.argv[1];\n if (entry === undefined) return false;\n try {\n return realpathSync(entry) === realpathSync(fileURLToPath(import.meta.url));\n } catch {\n return false;\n }\n}\n\nif (invokedDirectly()) main();\n"]}
@@ -1,10 +1,9 @@
1
1
  import { closeIds } from "../../core/c4/arch.js";
2
- import { loadConfig } from "../../core/envelope/config.js";
3
2
  import { InvalidIdError, assertServiceId } from "../../core/kernel/ids/service.js";
4
- import { emitJson, fail, NO_SERVICE_MESSAGE, repoPath, reportNoConfig } from "../../core/envelope/json.js";
3
+ import { configOrRefuse, emitJson, fail, NO_SERVICE_MESSAGE, repoPath } from "../../core/envelope/json.js";
5
4
  import { DocsRepoUnavailableError } from "../../core/repo/state.js";
6
5
  import { listFleetTree, listServices } from "../../core/repo/repo.js";
7
- import { findInTree, nearestTreeNames } from "../../core/repo/tree/find.js";
6
+ import { closeNamesHint, findInTree } from "../../core/repo/tree/find.js";
8
7
  import { servicePathsUnder } from "../../core/repo/paths.js";
9
8
  import { serviceBrief } from "../../core/brief/brief.js";
10
9
  import { docsRepoReady } from "../policy/gate.js";
@@ -21,9 +20,8 @@ async function subsystemTarget(docsDir, name, service, json) {
21
20
  const tree = await listFleetTree(docsDir);
22
21
  const hit = findInTree(tree, name);
23
22
  if (hit === null) {
24
- const close = nearestTreeNames(name, tree.subsystems.map((s) => s.name));
25
23
  fail(json, "unknown-target", `No subsystem '${name}' in the tree.` +
26
- (close.length > 0 ? ` Close names: ${close.join(", ")}.` : " `loam subsystem new` creates one; `loam subsystem list` shows what exists."));
24
+ closeNamesHint(name, tree.subsystems.map((s) => s.name), " `loam subsystem new` creates one; `loam subsystem list` shows what exists."));
27
25
  return null;
28
26
  }
29
27
  if (hit.kind === "service") {
@@ -141,12 +139,9 @@ export function registerAdopt(program) {
141
139
  .option("--json", "emit the machine contract instead of the human view")
142
140
  .action(async (opts) => {
143
141
  const json = opts.json === true;
144
- const loaded = await loadConfig();
145
- if (loaded.kind !== "loaded") {
146
- reportNoConfig(json, loaded);
142
+ const config = await configOrRefuse(json);
143
+ if (config === null)
147
144
  return;
148
- }
149
- const config = loaded.config;
150
145
  // This command writes nothing, but it briefs an agent to write a whole
151
146
  // baseline — so a docsDir that does not exist is not a harmless read: it
152
147
  // hands over eight target paths under a directory nobody has, at exit 0,
@@ -1 +1 @@
1
- {"version":3,"file":"adopt.js","sourceRoot":"","sources":["../../../src/commands/adopt/adopt.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Command } from \"commander\";\nimport { closeIds } from \"../../core/c4/arch.js\";\nimport { loadConfig } from \"../../core/envelope/config.js\";\nimport { InvalidIdError, assertServiceId, type PathableService } from \"../../core/kernel/ids/service.js\";\nimport { emitJson, fail, NO_SERVICE_MESSAGE, repoPath, reportNoConfig } from \"../../core/envelope/json.js\";\nimport { DocsRepoUnavailableError } from \"../../core/repo/state.js\";\nimport { listFleetTree, listServices } from \"../../core/repo/repo.js\";\nimport { findInTree, nearestTreeNames } from \"../../core/repo/tree/find.js\";\nimport { servicePathsUnder, type ServicePaths } from \"../../core/repo/paths.js\";\nimport { serviceBrief, type Brief } from \"../../core/brief/brief.js\";\nimport { docsRepoReady } from \"../policy/gate.js\";\nimport { render } from \"./render.js\";\nimport type { DocsDir } from \"../../core/kernel/ids/dirs.js\";\n\n/**\n * `loam adopt` — the bootstrap flow, as a contract with an agent.\n *\n * It emits a BRIEF, not an extraction: the artifacts one service's baseline is\n * made of, the grammar each has to be written in, what the fleet already says\n * about the service, the checks that follow, and the checks that do not exist.\n * The agent reads the code; loam states the work and then judges the result.\n *\n * It writes nothing. A command that produced the documents it is asking for\n * would be doing the half of the job it exists to hand over.\n */\n\ninterface AdoptOptions {\n service?: string;\n subsystem?: string;\n targets?: boolean;\n json?: boolean;\n}\n\n/**\n * Where `--subsystem` points the brief: the target directory inside the\n * group for a service that does not exist yet, or nothing — with a warning —\n * for one that already does, because adopt writes nothing and MOVES nothing\n * (`loam subsystem move` is the verb that relocates). An unknown subsystem\n * refuses with close-name hints, exactly as a mistyped service id warns: a\n * typo here would brief a whole baseline into a group nobody has.\n */\nasync function subsystemTarget(\n docsDir: DocsDir,\n name: string,\n service: PathableService,\n json: boolean,\n): Promise<{ at?: ServicePaths; warning?: string } | null> {\n const tree = await listFleetTree(docsDir);\n const hit = findInTree(tree, name);\n if (hit === null) {\n const close = nearestTreeNames(name, tree.subsystems.map((s) => s.name));\n fail(\n json,\n \"unknown-target\",\n `No subsystem '${name}' in the tree.` +\n (close.length > 0 ? ` Close names: ${close.join(\", \")}.` : \" `loam subsystem new` creates one; `loam subsystem list` shows what exists.\"),\n );\n return null;\n }\n if (hit.kind === \"service\") {\n fail(json, \"invalid-option\", `--subsystem names the service '${name}' — a service never contains other services.`);\n return null;\n }\n const filed = tree.services.find((s) => s.id === service);\n if (filed !== undefined) {\n return {\n warning:\n `'${service}' already exists at ${repoPath(docsDir, filed.dir)}/ — --subsystem does not move a service ` +\n `(\\`loam subsystem move ${service} --into ${name}\\` does), so the brief targets its existing directory.`,\n };\n }\n return { at: servicePathsUnder(hit.subsystem.dir, service) };\n}\n\n/**\n * What is suspicious about this invocation without being wrong.\n *\n * Adopting a service that has no `services/<id>/` yet is the NORMAL case — it\n * is the whole point of the command — so neither of these can be a refusal.\n * But both used to be silent, and both produce the same outcome: a complete,\n * validating baseline written under a directory name nobody meant. `adopt\n * --service biling-service` briefed a phantom service beside the real\n * `billing-service`, and an agent following the brief created it.\n */\nasync function invocationWarnings(\n docsDir: DocsDir,\n service: PathableService,\n bound: string | undefined,\n): Promise<string[]> {\n const warnings: string[] = [];\n\n if (bound !== undefined && bound !== service) {\n warnings.push(\n `This repository's loam.json declares service '${bound}', but you asked to adopt '${service}'. ` +\n `That is legal — one repo can author another service's baseline — but \\`loam vouch\\`, ` +\n `\\`loam gherkin\\` and \\`loam verify --service\\` all bind to '${bound}' here, so the baseline ` +\n `you write cannot be vouched from this repo. If '${service}' is a typo, fix it; otherwise run ` +\n `adopt from '${service}''s own repository.`,\n );\n }\n\n // \"Does the service already exist\" is enumeration MEMBERSHIP, not an\n // existsSync of services/<id>/ at the root: a service filed into a subsystem\n // exists wherever the tree walk found it, and the root probe read every\n // filed service as new — the near-miss warning then accused its own name of\n // being a typo. One enumeration answers both this and the near-miss list;\n // a repo that refuses enumeration is a different problem, reported by every\n // other command, and adopt has nothing useful to add to it.\n let known: string[] = [];\n try {\n known = (await listServices(docsDir)).map((s) => s.id);\n } catch (err) {\n if (!(err instanceof DocsRepoUnavailableError)) throw err;\n return warnings;\n }\n if (known.includes(service)) return warnings;\n const close = closeIds(service, known);\n if (close.length > 0) {\n warnings.push(\n `There is no services/${service}/ yet, but the docs repo already has ${close.join(\", \")}. ` +\n `If '${service}' is a misspelling of one of those, stop now: an agent following this brief ` +\n `writes a complete, validating baseline for a service that does not exist, and nothing ` +\n `downstream can tell it from a real one. If it really is a new service, this is expected.`,\n );\n }\n return warnings;\n}\n\n/**\n * The half of the brief that is computed from THIS repository, for THIS\n * service — what `--targets` keeps.\n *\n * Everything omitted is a module-level constant: `walk` and `walkClose` are the\n * code-reading order, `frontmatter` the field rules, `checks` the named checks,\n * `unchecked` the statements of what nothing checks, `rule` the never-overwrite\n * instruction. None of them is a function of the service, so a fleet-wide\n * adoption pays for the same bytes once per service — measured on the shipped\n * example fleet, about 23 KB of the 42 KB brief, which is four fifths of what\n * an agent reads and none of what it could not have read once.\n *\n * The keys are picked one by one rather than deleted from a rest — a field\n * added to `Brief` later must land in the DEFAULT payload and stay out of this\n * one until somebody decides it varies by service. Getting that wrong the\n * other way round is how a narrowing flag silently becomes the full brief\n * again.\n */\nfunction narrowed(b: Brief): Pick<Brief, \"service\" | \"docsDir\" | \"path\" | \"targets\" | \"landscape\"> {\n return { service: b.service, docsDir: b.docsDir, path: b.path, targets: b.targets, landscape: b.landscape };\n}\n\n/**\n * The `full` pointer: the run that carries what `--targets` dropped, and the\n * reason it is worth making.\n *\n * It is REQUIRED in the narrowed envelope, and the second sentence is why. The\n * unchecked list is loam shipping, in the binary, the statements of what no\n * check will ever tell you — the one thing standing between a green\n * `loam validate` and being read as more than it means. Merely leaving it out\n * would not read as \"omitted for brevity\"; it would read as \"there is no such\n * list\", which is the failure `src/core/brief/unchecked.ts` exists to prevent\n * and the one promise the brief keeps that no validator supplies. So the\n * narrowed view never hides it — it says how many there are and where to read\n * them.\n *\n * Every count comes off the brief that was just assembled, never off a number\n * typed here: a literal would be correct until the next check is added and\n * wrong silently forever after.\n */\nfunction fullBrief(b: Brief): string {\n return (\n `loam adopt --service ${b.service} --json — everything this view leaves out: the ` +\n `${b.walk.length}-stop code walk, the frontmatter rules, the ${b.checks.length} named checks, ` +\n `and the ${b.unchecked.length} statements of what nothing checks. None of it varies by service, ` +\n `so run it once for the system rather than once per service — but do run it: those ` +\n `${b.unchecked.length} statements are the only place loam says where its checking stops.`\n );\n}\n\nexport function registerAdopt(program: Command): void {\n program\n .command(\"adopt\")\n .description(\"Brief an agent to write one service's baseline docs from its code, and say what will be checked\")\n .option(\"--service <id>\", \"service to adopt (defaults to the configured service)\")\n .option(\"--subsystem <name>\", \"file the new service's baseline into this subsystem instead of the services/ root\")\n .option(\"--targets\", \"narrow the brief to what varies by service; the walk, the checks and the unchecked list are omitted, and a `full` field names the run that carries them\")\n .option(\"--json\", \"emit the machine contract instead of the human view\")\n .action(async (opts: AdoptOptions) => {\n const json = opts.json === true;\n\n const loaded = await loadConfig();\n if (loaded.kind !== \"loaded\") {\n reportNoConfig(json, loaded);\n return;\n }\n const config = loaded.config;\n // This command writes nothing, but it briefs an agent to write a whole\n // baseline — so a docsDir that does not exist is not a harmless read: it\n // hands over eight target paths under a directory nobody has, at exit 0,\n // with the near-miss warning below silently switched off (listServices\n // throws, `invocationWarnings` swallows it and returns nothing). The same\n // refusal every enumerating command owes; see docs-repo-gate.ts.\n //\n // `docs`, not `services`: a docs repo that has no services/ yet is exactly\n // the repo adopt exists to fill, and refusing there would refuse the\n // command's own first use.\n if (!docsRepoReady(json, config.docsDir, \"docs\")) return;\n\n const service = opts.service ?? config.service;\n if (service === undefined) {\n fail(json, \"invalid-option\", NO_SERVICE_MESSAGE);\n return;\n }\n // The id becomes `services/<id>/` in a shared repo, so it goes through the\n // one grammar before anything interpolates it into a path.\n try {\n assertServiceId(service, opts.service === undefined ? \"service (loam.json)\" : \"--service\");\n } catch (err) {\n if (!(err instanceof InvalidIdError)) throw err;\n fail(json, \"invalid-option\", err.message);\n return;\n }\n\n const warnings = await invocationWarnings(config.docsDir, service, config.service);\n let at: ServicePaths | undefined;\n if (opts.subsystem !== undefined) {\n const target = await subsystemTarget(config.docsDir, opts.subsystem, service, json);\n if (target === null) return;\n at = target.at;\n if (target.warning !== undefined) warnings.push(target.warning);\n }\n const brief = await serviceBrief(config.docsDir, service, at);\n // Computed only under `--targets`, and it is what makes the narrowing\n // legible from inside the payload: a consumer holding `full` knows there\n // is more and what it is, and a consumer without it is holding all of it.\n // The narrowing happens HERE, by omission, so the brief itself is\n // unchanged and every field it can produce still exists.\n const full = opts.targets === true ? fullBrief(brief) : undefined;\n if (json) {\n // Two separate emits rather than one conditional spread: the default\n // payload is a frozen contract, and it must stay the same bytes in the\n // same order whatever this flag grows into.\n if (full !== undefined) {\n emitJson({ command: \"adopt\", ...narrowed(brief), warnings, full });\n return;\n }\n emitJson({ command: \"adopt\", ...brief, warnings });\n return;\n }\n render(brief, warnings, full);\n });\n}\n"]}
1
+ {"version":3,"file":"adopt.js","sourceRoot":"","sources":["../../../src/commands/adopt/adopt.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Command } from \"commander\";\nimport { closeIds } from \"../../core/c4/arch.js\";\nimport { InvalidIdError, assertServiceId, type PathableService } from \"../../core/kernel/ids/service.js\";\nimport { configOrRefuse, emitJson, fail, NO_SERVICE_MESSAGE, repoPath } from \"../../core/envelope/json.js\";\nimport { DocsRepoUnavailableError } from \"../../core/repo/state.js\";\nimport { listFleetTree, listServices } from \"../../core/repo/repo.js\";\nimport { closeNamesHint, findInTree } from \"../../core/repo/tree/find.js\";\nimport { servicePathsUnder, type ServicePaths } from \"../../core/repo/paths.js\";\nimport { serviceBrief, type Brief } from \"../../core/brief/brief.js\";\nimport { docsRepoReady } from \"../policy/gate.js\";\nimport { render } from \"./render.js\";\nimport type { DocsDir } from \"../../core/kernel/ids/dirs.js\";\n\n/**\n * `loam adopt` — the bootstrap flow, as a contract with an agent.\n *\n * It emits a BRIEF, not an extraction: the artifacts one service's baseline is\n * made of, the grammar each has to be written in, what the fleet already says\n * about the service, the checks that follow, and the checks that do not exist.\n * The agent reads the code; loam states the work and then judges the result.\n *\n * It writes nothing. A command that produced the documents it is asking for\n * would be doing the half of the job it exists to hand over.\n */\n\ninterface AdoptOptions {\n service?: string;\n subsystem?: string;\n targets?: boolean;\n json?: boolean;\n}\n\n/**\n * Where `--subsystem` points the brief: the target directory inside the\n * group for a service that does not exist yet, or nothing — with a warning —\n * for one that already does, because adopt writes nothing and MOVES nothing\n * (`loam subsystem move` is the verb that relocates). An unknown subsystem\n * refuses with close-name hints, exactly as a mistyped service id warns: a\n * typo here would brief a whole baseline into a group nobody has.\n */\nasync function subsystemTarget(\n docsDir: DocsDir,\n name: string,\n service: PathableService,\n json: boolean,\n): Promise<{ at?: ServicePaths; warning?: string } | null> {\n const tree = await listFleetTree(docsDir);\n const hit = findInTree(tree, name);\n if (hit === null) {\n fail(\n json,\n \"unknown-target\",\n `No subsystem '${name}' in the tree.` +\n closeNamesHint(name, tree.subsystems.map((s) => s.name), \" `loam subsystem new` creates one; `loam subsystem list` shows what exists.\"),\n );\n return null;\n }\n if (hit.kind === \"service\") {\n fail(json, \"invalid-option\", `--subsystem names the service '${name}' — a service never contains other services.`);\n return null;\n }\n const filed = tree.services.find((s) => s.id === service);\n if (filed !== undefined) {\n return {\n warning:\n `'${service}' already exists at ${repoPath(docsDir, filed.dir)}/ — --subsystem does not move a service ` +\n `(\\`loam subsystem move ${service} --into ${name}\\` does), so the brief targets its existing directory.`,\n };\n }\n return { at: servicePathsUnder(hit.subsystem.dir, service) };\n}\n\n/**\n * What is suspicious about this invocation without being wrong.\n *\n * Adopting a service that has no `services/<id>/` yet is the NORMAL case — it\n * is the whole point of the command — so neither of these can be a refusal.\n * But both used to be silent, and both produce the same outcome: a complete,\n * validating baseline written under a directory name nobody meant. `adopt\n * --service biling-service` briefed a phantom service beside the real\n * `billing-service`, and an agent following the brief created it.\n */\nasync function invocationWarnings(\n docsDir: DocsDir,\n service: PathableService,\n bound: string | undefined,\n): Promise<string[]> {\n const warnings: string[] = [];\n\n if (bound !== undefined && bound !== service) {\n warnings.push(\n `This repository's loam.json declares service '${bound}', but you asked to adopt '${service}'. ` +\n `That is legal — one repo can author another service's baseline — but \\`loam vouch\\`, ` +\n `\\`loam gherkin\\` and \\`loam verify --service\\` all bind to '${bound}' here, so the baseline ` +\n `you write cannot be vouched from this repo. If '${service}' is a typo, fix it; otherwise run ` +\n `adopt from '${service}''s own repository.`,\n );\n }\n\n // \"Does the service already exist\" is enumeration MEMBERSHIP, not an\n // existsSync of services/<id>/ at the root: a service filed into a subsystem\n // exists wherever the tree walk found it, and the root probe read every\n // filed service as new — the near-miss warning then accused its own name of\n // being a typo. One enumeration answers both this and the near-miss list;\n // a repo that refuses enumeration is a different problem, reported by every\n // other command, and adopt has nothing useful to add to it.\n let known: string[] = [];\n try {\n known = (await listServices(docsDir)).map((s) => s.id);\n } catch (err) {\n if (!(err instanceof DocsRepoUnavailableError)) throw err;\n return warnings;\n }\n if (known.includes(service)) return warnings;\n const close = closeIds(service, known);\n if (close.length > 0) {\n warnings.push(\n `There is no services/${service}/ yet, but the docs repo already has ${close.join(\", \")}. ` +\n `If '${service}' is a misspelling of one of those, stop now: an agent following this brief ` +\n `writes a complete, validating baseline for a service that does not exist, and nothing ` +\n `downstream can tell it from a real one. If it really is a new service, this is expected.`,\n );\n }\n return warnings;\n}\n\n/**\n * The half of the brief that is computed from THIS repository, for THIS\n * service — what `--targets` keeps.\n *\n * Everything omitted is a module-level constant: `walk` and `walkClose` are the\n * code-reading order, `frontmatter` the field rules, `checks` the named checks,\n * `unchecked` the statements of what nothing checks, `rule` the never-overwrite\n * instruction. None of them is a function of the service, so a fleet-wide\n * adoption pays for the same bytes once per service — measured on the shipped\n * example fleet, about 23 KB of the 42 KB brief, which is four fifths of what\n * an agent reads and none of what it could not have read once.\n *\n * The keys are picked one by one rather than deleted from a rest — a field\n * added to `Brief` later must land in the DEFAULT payload and stay out of this\n * one until somebody decides it varies by service. Getting that wrong the\n * other way round is how a narrowing flag silently becomes the full brief\n * again.\n */\nfunction narrowed(b: Brief): Pick<Brief, \"service\" | \"docsDir\" | \"path\" | \"targets\" | \"landscape\"> {\n return { service: b.service, docsDir: b.docsDir, path: b.path, targets: b.targets, landscape: b.landscape };\n}\n\n/**\n * The `full` pointer: the run that carries what `--targets` dropped, and the\n * reason it is worth making.\n *\n * It is REQUIRED in the narrowed envelope, and the second sentence is why. The\n * unchecked list is loam shipping, in the binary, the statements of what no\n * check will ever tell you — the one thing standing between a green\n * `loam validate` and being read as more than it means. Merely leaving it out\n * would not read as \"omitted for brevity\"; it would read as \"there is no such\n * list\", which is the failure `src/core/brief/unchecked.ts` exists to prevent\n * and the one promise the brief keeps that no validator supplies. So the\n * narrowed view never hides it — it says how many there are and where to read\n * them.\n *\n * Every count comes off the brief that was just assembled, never off a number\n * typed here: a literal would be correct until the next check is added and\n * wrong silently forever after.\n */\nfunction fullBrief(b: Brief): string {\n return (\n `loam adopt --service ${b.service} --json — everything this view leaves out: the ` +\n `${b.walk.length}-stop code walk, the frontmatter rules, the ${b.checks.length} named checks, ` +\n `and the ${b.unchecked.length} statements of what nothing checks. None of it varies by service, ` +\n `so run it once for the system rather than once per service — but do run it: those ` +\n `${b.unchecked.length} statements are the only place loam says where its checking stops.`\n );\n}\n\nexport function registerAdopt(program: Command): void {\n program\n .command(\"adopt\")\n .description(\"Brief an agent to write one service's baseline docs from its code, and say what will be checked\")\n .option(\"--service <id>\", \"service to adopt (defaults to the configured service)\")\n .option(\"--subsystem <name>\", \"file the new service's baseline into this subsystem instead of the services/ root\")\n .option(\"--targets\", \"narrow the brief to what varies by service; the walk, the checks and the unchecked list are omitted, and a `full` field names the run that carries them\")\n .option(\"--json\", \"emit the machine contract instead of the human view\")\n .action(async (opts: AdoptOptions) => {\n const json = opts.json === true;\n\n const config = await configOrRefuse(json);\n if (config === null) return;\n // This command writes nothing, but it briefs an agent to write a whole\n // baseline — so a docsDir that does not exist is not a harmless read: it\n // hands over eight target paths under a directory nobody has, at exit 0,\n // with the near-miss warning below silently switched off (listServices\n // throws, `invocationWarnings` swallows it and returns nothing). The same\n // refusal every enumerating command owes; see docs-repo-gate.ts.\n //\n // `docs`, not `services`: a docs repo that has no services/ yet is exactly\n // the repo adopt exists to fill, and refusing there would refuse the\n // command's own first use.\n if (!docsRepoReady(json, config.docsDir, \"docs\")) return;\n\n const service = opts.service ?? config.service;\n if (service === undefined) {\n fail(json, \"invalid-option\", NO_SERVICE_MESSAGE);\n return;\n }\n // The id becomes `services/<id>/` in a shared repo, so it goes through the\n // one grammar before anything interpolates it into a path.\n try {\n assertServiceId(service, opts.service === undefined ? \"service (loam.json)\" : \"--service\");\n } catch (err) {\n if (!(err instanceof InvalidIdError)) throw err;\n fail(json, \"invalid-option\", err.message);\n return;\n }\n\n const warnings = await invocationWarnings(config.docsDir, service, config.service);\n let at: ServicePaths | undefined;\n if (opts.subsystem !== undefined) {\n const target = await subsystemTarget(config.docsDir, opts.subsystem, service, json);\n if (target === null) return;\n at = target.at;\n if (target.warning !== undefined) warnings.push(target.warning);\n }\n const brief = await serviceBrief(config.docsDir, service, at);\n // Computed only under `--targets`, and it is what makes the narrowing\n // legible from inside the payload: a consumer holding `full` knows there\n // is more and what it is, and a consumer without it is holding all of it.\n // The narrowing happens HERE, by omission, so the brief itself is\n // unchanged and every field it can produce still exists.\n const full = opts.targets === true ? fullBrief(brief) : undefined;\n if (json) {\n // Two separate emits rather than one conditional spread: the default\n // payload is a frozen contract, and it must stay the same bytes in the\n // same order whatever this flag grows into.\n if (full !== undefined) {\n emitJson({ command: \"adopt\", ...narrowed(brief), warnings, full });\n return;\n }\n emitJson({ command: \"adopt\", ...brief, warnings });\n return;\n }\n render(brief, warnings, full);\n });\n}\n"]}
@@ -55,7 +55,21 @@ export function render(b, warnings, full) {
55
55
  for (const t of b.targets) {
56
56
  // `edit` is the shared fleet map: the file exists, but "present" would read
57
57
  // as "nothing to do here", which is the opposite of why it is on the list.
58
- const flag = t.action === "edit" ? "UNDRAWN" : t.exists ? "present" : t.required ? "MISSING" : "missing";
58
+ // Two words for it, because the two states want different work: `UNDRAWN`
59
+ // when nothing resolves to the service, `EDGELESS` when an element does
60
+ // and no edge touches it — a reader acting on `UNDRAWN` there would look
61
+ // for a box that is already on the map.
62
+ const flag = t.action === "edit"
63
+ ? b.landscape.modelled === true
64
+ ? "EDGELESS"
65
+ : "UNDRAWN"
66
+ : t.partial === true
67
+ ? "PARTIAL"
68
+ : t.exists
69
+ ? "present"
70
+ : t.required
71
+ ? "MISSING"
72
+ : "missing";
59
73
  console.log(` ${t.artifact.padEnd(width)} ${t.action.padEnd(6)} ${flag.padEnd(7)} ${t.purpose}`);
60
74
  }
61
75
  for (const t of b.targets)
@@ -81,8 +95,8 @@ export function render(b, warnings, full) {
81
95
  console.log("");
82
96
  console.log(wrap("Leave everything `status: draft`. Vouching is somebody reading the code and saying the document matches it — it is not yours to do, and a status with no digest behind it is a claim with nothing behind it.", " "));
83
97
  }
84
- /** The table's four flags, compressed to one terminal line for the scroll-back reader. */
85
- const LEGEND_LINE = "MISSING required · missing optional · present diff it · UNDRAWN add to the map";
98
+ /** The table's five flags, compressed to one terminal line for the scroll-back reader. */
99
+ const LEGEND_LINE = "MISSING required · missing optional · present diff it · PARTIAL one feature's slice, adopt around it · UNDRAWN add to the map · EDGELESS an element exists, no edge does";
86
100
  /**
87
101
  * A required target whose work is still outstanding.
88
102
  *
@@ -91,10 +105,11 @@ const LEGEND_LINE = "MISSING required · missing optional · present diff it ·
91
105
  * exists, so `exists` is true while nothing in it resolves to this boundary —
92
106
  * which `loam validate --all` grades `landscape.service-unmodelled`, an ERROR.
93
107
  * `action` carries that distinction and nothing else does: `edit` is only ever
94
- * the undrawn fleet map (see `BriefTarget.action`, core/brief/targets.ts).
108
+ * the fleet map still owed — undrawn, or drawn with no edge touching it (see
109
+ * `BriefTarget.action`, core/brief/targets.ts).
95
110
  */
96
111
  function outstanding(t) {
97
- return t.required && (!t.exists || t.action === "edit");
112
+ return t.required && (!t.exists || t.action === "edit" || t.partial === true);
98
113
  }
99
114
  /**
100
115
  * The three sentences that make the rest of the page readable: how much of it
@@ -121,7 +136,7 @@ function printOrientation(b) {
121
136
  // capitals were emphasis; they are the required/optional distinction, and
122
137
  // nothing on the page said so. `UNDRAWN` needs more than a gloss — it is the
123
138
  // one row that is not this boundary's file at all.
124
- console.log(bullet("The flags in that table: `MISSING` in capitals is required and not there, lowercase `missing` is optional and not there, `present` means the file exists — diff it, never replace it. `UNDRAWN` marks the one row that is not this boundary's own file: `architecture/landscape.likec4` is the whole system's map and already holds every other boundary, so ADD to it rather than rewriting it. Until an element in it resolves to this directory, `loam validate --all` reports `landscape.service-unmodelled` (error).", " "));
139
+ console.log(bullet("The flags in that table: `MISSING` in capitals is required and not there, lowercase `missing` is optional and not there, `present` means the file exists — diff it, never replace it. `PARTIAL` is a spec.md marked `adoption: partial`: one archived feature's slice, so keep every requirement in it, write the rest of the service around them, and then delete the `adoption: partial` line. `UNDRAWN` and `EDGELESS` mark the one row that is not this boundary's own file: `architecture/landscape.likec4` is the whole system's map and already holds every other boundary, so ADD to it rather than rewriting it. Until an element in it resolves to this directory, `loam validate --all` reports `landscape.service-unmodelled` (error); `EDGELESS` means an element already does and no edge touches it, so what the map lacks is the calls in and out of it, never a second element.", " "));
125
140
  console.log("");
126
141
  // What the rest of the page is, so a reader who stops here still knows what
127
142
  // they scrolled past — and where the same content lives for an agent, which
@@ -215,9 +230,15 @@ function printLandscape(b) {
215
230
  return;
216
231
  }
217
232
  if (!l.parses) {
218
- console.log(" architecture/landscape.likec4 does not parse — bind by hand, and fix it first.");
233
+ // Not "architecture/landscape.likec4 does not parse": the map is the whole
234
+ // `architecture/` project, so the file that broke is usually a sibling —
235
+ // and this line accused the landscape of errors `validate --all` blamed on
236
+ // a palette. The instruction printed directly below names the documents
237
+ // that actually failed, so the headline says the project and nothing more.
238
+ console.log(" The fleet map (architecture/) does not parse — fix that first; the files are named below.");
219
239
  console.log("");
220
240
  console.log(wrap(l.instruction ?? "", " "));
241
+ printExpects(l);
221
242
  return;
222
243
  }
223
244
  if (l.elements.length === 0) {
@@ -234,10 +255,30 @@ function printLandscape(b) {
234
255
  console.log(` ← ${e.from} ${e.op ?? `"${e.title ?? ""}"`}`);
235
256
  for (const e of l.outbound)
236
257
  console.log(` → ${e.to} ${e.op ?? `"${e.title ?? ""}"`}`);
237
- if (l.expects.length > 0) {
258
+ // The edgeless state: an element and no edge lines above it. The modelled
259
+ // branch used to return here without ever printing an instruction, which
260
+ // is how the text view briefed "the map owes nothing" over two empty lists.
261
+ if (l.instruction !== null) {
238
262
  console.log("");
239
- console.log(wrap(`openapi.yaml must define ${l.expects.map((o) => `'${o}'`).join(", ")} — the fleet already calls ${l.expects.length === 1 ? "it" : "them"}, and a contract that omits ${l.expects.length === 1 ? "it" : "them"} fails spine.op-undefined the moment it lands.`, " "));
263
+ console.log(wrap(l.instruction, " "));
240
264
  }
265
+ printExpects(l);
266
+ }
267
+ /**
268
+ * What the fleet already calls on this service, and why the contract owes it.
269
+ *
270
+ * Printed in the unparseable branch as well as the healthy one: the landscape
271
+ * FILE still answers who calls this service when a sibling under `architecture/`
272
+ * breaks the project, and it is what decides whether `openapi.yaml` is flagged
273
+ * required — so a reader who is told the map is unreadable still gets the
274
+ * evidence behind that row.
275
+ */
276
+ function printExpects(l) {
277
+ if (l.expects.length === 0)
278
+ return;
279
+ const it = l.expects.length === 1 ? "it" : "them";
280
+ console.log("");
281
+ console.log(wrap(`openapi.yaml must define ${l.expects.map((o) => `'${o}'`).join(", ")} — the fleet already calls ${it}, and a contract that omits ${it} fails spine.op-undefined the moment it lands.`, " "));
241
282
  }
242
283
  /**
243
284
  * Wrap prose so the brief is readable in a terminal. Continuation lines are
@@ -1 +1 @@
1
- {"version":3,"file":"render.js","sourceRoot":"","sources":["../../../src/commands/adopt/render.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The brief as a person reads it.\n *\n * A module of its own because the brief is the one loam output an agent is\n * expected to FOLLOW rather than parse: `--json` carries the same eight targets,\n * and this decides only how they read. The wrapping matters for that reason —\n * a continuation line indented past its marker cannot be misread as a second\n * bullet, which is what a hand-followed checklist gets wrong first.\n */\nimport { SEVERITY_MARK } from \"../../core/vocabulary/report.js\";\nimport { type Brief } from \"../../core/brief/brief.js\";\nimport { VIA_ALL, type BriefCheck } from \"../../core/brief/checks.js\";\nimport type { BriefTarget } from \"../../core/brief/targets.js\";\n\n/* ------------------------------------------------------------------ */\n/* Text */\n/* ------------------------------------------------------------------ */\n\n/**\n * `full` is the `--targets` pointer — the sentence naming the run that carries\n * the invariant half of the brief. Its PRESENCE is what narrows this view, so\n * the two views cannot disagree about what `--targets` means: exactly the\n * sections `--targets` omits from `--json` are the sections skipped here.\n * `undefined` is the default brief, unchanged byte for byte.\n */\nexport function render(b: Brief, warnings: string[], full?: string): void {\n console.log(`adopt ${b.service} — write the baseline into ${b.path}/\\n`);\n // In the header, before the work: a warning printed after eight artifact\n // shapes is a warning read after the agent has started writing.\n for (const w of warnings) {\n console.log(wrap(`! ${w}`, \" \"));\n console.log(\"\");\n }\n if (full === undefined) {\n // First, above even the never-overwrite rule, because the rule is an\n // instruction and this is the answer to \"what am I looking at\": measured on\n // the example fleet, this view is over 650 lines and 5,600 words to an\n // unpaged terminal, and the two rows that actually orient a person —\n // `model.likec4 create MISSING`, `spec.md create MISSING` — land past line\n // 450, behind four hundred lines of prose. `--json` is explicitly the agent\n // contract, so nothing was served by leaving the human view unintroduced.\n // `--targets` skips it — bullet three describes sections that view omits,\n // and that view has its own pointer for the same job.\n printOrientation(b);\n console.log(wrap(b.rule, \" \"));\n\n // Before the artifact table, because the table is the output and this is the\n // input: an agent that meets the file list first starts writing files.\n printWalk(b);\n }\n\n console.log(\"\\n artifacts\\n\");\n // The legend again, next to the thing it decodes. A reader who scrolls back\n // to the table two hundred lines later arrives at four flags and no key, and\n // the capital/lowercase distinction is invisible to anyone who has to\n // remember it rather than read it.\n console.log(wrap(LEGEND_LINE, \" \"));\n console.log(\"\");\n const width = Math.max(...b.targets.map((t) => t.artifact.length));\n for (const t of b.targets) {\n // `edit` is the shared fleet map: the file exists, but \"present\" would read\n // as \"nothing to do here\", which is the opposite of why it is on the list.\n const flag = t.action === \"edit\" ? \"UNDRAWN\" : t.exists ? \"present\" : t.required ? \"MISSING\" : \"missing\";\n console.log(` ${t.artifact.padEnd(width)} ${t.action.padEnd(6)} ${flag.padEnd(7)} ${t.purpose}`);\n }\n\n for (const t of b.targets) printShape(t);\n\n printLandscape(b);\n\n if (full === undefined) printChecking(b);\n else {\n // The pointer takes the place of the sections it stands for, in the same\n // position they would have occupied. Anywhere else — a footnote under the\n // closing instructions, say — and it reads as a cross-reference rather\n // than as the notice that this brief is not all of the brief.\n console.log(\"\\n the rest of the brief\\n\");\n console.log(wrap(full, \" \"));\n }\n\n console.log(\"\\n when you are done\\n\");\n console.log(` loam validate --service ${b.service} --json # fix every error`);\n // The fleet run is not a nicety: --service never reports the landscape\n // cross-check, so a baseline can pass the line above with the fleet map\n // never edited at all.\n console.log(` loam validate --all --json # in the docs repo: the fleet map`);\n console.log(` loam vouch --service ${b.service} # a HUMAN, in the service's own repo`);\n console.log(\"\");\n console.log(\n wrap(\n \"Leave everything `status: draft`. Vouching is somebody reading the code and saying the document matches it — it is not yours to do, and a status with no digest behind it is a claim with nothing behind it.\",\n \" \",\n ),\n );\n}\n\n/** The table's four flags, compressed to one terminal line for the scroll-back reader. */\nconst LEGEND_LINE = \"MISSING required · missing optional · present diff it · UNDRAWN add to the map\";\n\n/**\n * A required target whose work is still outstanding.\n *\n * `!t.exists` alone is the wrong test, and the fleet map is the reason: for\n * every repo after its first service `architecture/landscape.likec4` already\n * exists, so `exists` is true while nothing in it resolves to this boundary —\n * which `loam validate --all` grades `landscape.service-unmodelled`, an ERROR.\n * `action` carries that distinction and nothing else does: `edit` is only ever\n * the undrawn fleet map (see `BriefTarget.action`, core/brief/targets.ts).\n */\nfunction outstanding(t: BriefTarget): boolean {\n return t.required && (!t.exists || t.action === \"edit\");\n}\n\n/**\n * The three sentences that make the rest of the page readable: how much of it\n * is owed, what the table's own convention means, and what the four hundred\n * lines below it are.\n *\n * Every number here is computed from the brief that was just assembled — the\n * outstanding count off `targets`, the section sizes off `walk`, `checks` and\n * `unchecked`. A literal would be right until the next check is added and\n * silently wrong forever after, and this block's whole value is that a reader\n * can trust it instead of scrolling to verify it.\n */\nfunction printOrientation(b: Brief): void {\n const owed = b.targets.filter(outstanding);\n console.log(\" read this first\\n\");\n\n // What is actually owed, named. The count is the load-bearing half: \"some of\n // these are required\" is a sentence a reader skips, \"three of the nine, and\n // here they are\" is one they act on.\n console.log(\n bullet(\n owed.length === 0\n ? `None of the ${String(b.targets.length)} artifacts below is both required and outstanding — every required one is already there. What is left is optional, or an existing document to diff your findings against.`\n : `${String(owed.length)} of the ${String(b.targets.length)} artifacts below ${owed.length === 1 ? \"is\" : \"are\"} required and not yet done: ${owed.map((t) => t.artifact).join(\", \")}. Everything else in the table is optional, or already written and wants diffing rather than replacing.`,\n \" \",\n ),\n );\n console.log(\"\");\n\n // The legend, in full. The table prints `MISSING` and `missing` as if the\n // capitals were emphasis; they are the required/optional distinction, and\n // nothing on the page said so. `UNDRAWN` needs more than a gloss — it is the\n // one row that is not this boundary's file at all.\n console.log(\n bullet(\n \"The flags in that table: `MISSING` in capitals is required and not there, lowercase `missing` is optional and not there, `present` means the file exists — diff it, never replace it. `UNDRAWN` marks the one row that is not this boundary's own file: `architecture/landscape.likec4` is the whole system's map and already holds every other boundary, so ADD to it rather than rewriting it. Until an element in it resolves to this directory, `loam validate --all` reports `landscape.service-unmodelled` (error).\",\n \" \",\n ),\n );\n console.log(\"\");\n\n // What the rest of the page is, so a reader who stops here still knows what\n // they scrolled past — and where the same content lives for an agent, which\n // is the reader this long body was written for.\n console.log(\n bullet(\n `The rest of this page, in order: the ${String(b.walk.length)}-stop order to read the code in, then the grammar of each artifact — every rule there is one a later check depends on — then the ${String(b.checks.length)} named checks the result will face and the ${String(b.unchecked.length)} statements of what nothing checks. \\`loam adopt --service ${b.service} --json\\` carries the same targets for an agent, and \\`--targets\\` narrows that to only the part that varies by boundary.`,\n \" \",\n ),\n );\n console.log(\"\");\n}\n\n/**\n * The invariant half: the frontmatter rules, the checks that run, and the\n * checks that do not exist. A function of its own only so `--targets` can skip\n * all three in one place — the three sections are the exact set `--targets`\n * omits from `--json`, and splitting them here is what keeps that a single\n * decision instead of three that can drift apart.\n */\nfunction printChecking(b: Brief): void {\n console.log(\"\\n frontmatter — on every markdown artifact\\n\");\n for (const [field, what] of Object.entries(b.frontmatter.fields)) {\n console.log(` ${field}`);\n console.log(wrap(what, \" \"));\n }\n console.log(`\\n never write by hand: ${b.frontmatter.never.join(\", \")}`);\n console.log(`\\n${wrap(b.frontmatter.why, \" \")}`);\n\n // Attribution matters here: the fleet cross-check runs under `--all`, and a\n // header promising it to `--service` sent agents chasing a finding that\n // invocation never reports.\n console.log(`\\n what \\`loam validate --service ${b.service}\\` then checks\\n`);\n for (const c of b.checks) {\n if (c.via !== VIA_ALL) printCheck(c);\n }\n console.log(`\\n and what only \\`loam validate --all\\` surfaces\\n`);\n for (const c of b.checks) {\n if (c.via === VIA_ALL) printCheck(c);\n }\n\n console.log(\"\\n what nothing checks\\n\");\n for (const u of b.unchecked) console.log(bullet(u, \" \"));\n}\n\n/**\n * The walk, numbered. The numbers are the point: an unordered list of nine\n * places to look reads as nine optional suggestions, and the two stops that fix\n * what the service IS have to happen before the surfaces are enumerated.\n */\nfunction printWalk(b: Brief): void {\n console.log(\"\\n read the code in this order — nothing below is written from anything else\\n\");\n for (const [i, stop] of b.walk.entries()) {\n // The hang is explicit rather than derived: `wrap` infers one from a leading\n // `- `, and a numbered stop whose second line starts at the number's own\n // column reads as the next stop — which for a list whose ORDER is the point\n // is the one misreading that costs something.\n console.log(wrap(`${String(i + 1)}. ${stop.where}`, \" \", 88, \" \"));\n // Two more columns than the stop it belongs to: where-to-look and\n // what-to-take are different sentences, and at one indent the second reads\n // as a continuation of the first.\n console.log(wrap(stop.find, \" \"));\n console.log(` → ${stop.lands.join(\", \")}`);\n console.log(\"\");\n }\n console.log(wrap(b.walkClose, \" \"));\n}\n\nfunction printCheck(c: BriefCheck): void {\n console.log(` ${SEVERITY_MARK[c.severity]} ${c.code}`);\n console.log(wrap(c.what, \" \"));\n}\n\nconst ACTION_NOTE: Record<BriefTarget[\"action\"], string> = {\n create: \"\",\n diff: \" (exists — diff, do not replace)\",\n edit: \" (the whole fleet's file — ADD to it, never rewrite it)\",\n};\n\nfunction printShape(t: BriefTarget): void {\n console.log(`\\n ${t.path}${ACTION_NOTE[t.action]}\\n`);\n for (const rule of t.shape) console.log(bullet(rule, \" \"));\n if (t.example === undefined) return;\n console.log(\"\");\n for (const line of t.example.trimEnd().split(\"\\n\")) console.log(` ${line}`.trimEnd());\n}\n\nfunction printLandscape(b: Brief): void {\n const l = b.landscape;\n console.log(\"\\n what the fleet already says about this service\\n\");\n // The instruction is the same sentence the JSON carries, printed from the\n // same field — the text view and `--json` cannot drift into briefing two\n // different writes.\n if (!l.present) {\n console.log(\" architecture/landscape.likec4 does not exist yet — nothing to bind to.\");\n console.log(\"\");\n console.log(wrap(l.instruction ?? \"\", \" \"));\n return;\n }\n if (!l.parses) {\n console.log(\" architecture/landscape.likec4 does not parse — bind by hand, and fix it first.\");\n console.log(\"\");\n console.log(wrap(l.instruction ?? \"\", \" \"));\n return;\n }\n if (l.elements.length === 0) {\n console.log(` Nothing in the landscape models '${b.service}'.`);\n console.log(\"\");\n console.log(wrap(l.instruction ?? \"\", \" \"));\n return;\n }\n for (const e of l.elements) {\n const bound = e.bound ? \"bound\" : \"matched by title — bind it\";\n console.log(` ${e.id} = ${e.kind} '${e.title}' (${bound})`);\n }\n for (const e of l.inbound) console.log(` ← ${e.from} ${e.op ?? `\"${e.title ?? \"\"}\"`}`);\n for (const e of l.outbound) console.log(` → ${e.to} ${e.op ?? `\"${e.title ?? \"\"}\"`}`);\n if (l.expects.length > 0) {\n console.log(\"\");\n console.log(\n wrap(\n `openapi.yaml must define ${l.expects.map((o) => `'${o}'`).join(\", \")} — the fleet already calls ${l.expects.length === 1 ? \"it\" : \"them\"}, and a contract that omits ${l.expects.length === 1 ? \"it\" : \"them\"} fails spine.op-undefined the moment it lands.`,\n \" \",\n ),\n );\n }\n}\n\n/**\n * Wrap prose so the brief is readable in a terminal. Continuation lines are\n * indented past the marker, so a wrapped bullet cannot be misread as two.\n */\nfunction wrap(text: string, indent: string, width = 88, hangIndent?: string): string {\n const hang = hangIndent ?? (/^\\s*-\\s/.test(text) ? `${indent} ` : indent);\n const out: string[] = [];\n let line = indent;\n let pad = indent;\n for (const word of text.trim().split(/\\s+/)) {\n if (line.length > pad.length && line.length + 1 + word.length > width) {\n out.push(line);\n pad = hang;\n line = hang + word;\n } else {\n line = line.length > pad.length ? `${line} ${word}` : line + word;\n }\n }\n out.push(line);\n return out.join(\"\\n\");\n}\n\n/** A bullet, wrapped with its continuation lines hanging under the text. */\nfunction bullet(text: string, indent: string): string {\n return wrap(`- ${text}`, indent);\n}\n"]}
1
+ {"version":3,"file":"render.js","sourceRoot":"","sources":["../../../src/commands/adopt/render.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The brief as a person reads it.\n *\n * A module of its own because the brief is the one loam output an agent is\n * expected to FOLLOW rather than parse: `--json` carries the same eight targets,\n * and this decides only how they read. The wrapping matters for that reason —\n * a continuation line indented past its marker cannot be misread as a second\n * bullet, which is what a hand-followed checklist gets wrong first.\n */\nimport { SEVERITY_MARK } from \"../../core/vocabulary/report.js\";\nimport { type Brief } from \"../../core/brief/brief.js\";\nimport { VIA_ALL, type BriefCheck } from \"../../core/brief/checks.js\";\nimport type { BriefTarget } from \"../../core/brief/targets.js\";\n\n/* ------------------------------------------------------------------ */\n/* Text */\n/* ------------------------------------------------------------------ */\n\n/**\n * `full` is the `--targets` pointer — the sentence naming the run that carries\n * the invariant half of the brief. Its PRESENCE is what narrows this view, so\n * the two views cannot disagree about what `--targets` means: exactly the\n * sections `--targets` omits from `--json` are the sections skipped here.\n * `undefined` is the default brief, unchanged byte for byte.\n */\nexport function render(b: Brief, warnings: string[], full?: string): void {\n console.log(`adopt ${b.service} — write the baseline into ${b.path}/\\n`);\n // In the header, before the work: a warning printed after eight artifact\n // shapes is a warning read after the agent has started writing.\n for (const w of warnings) {\n console.log(wrap(`! ${w}`, \" \"));\n console.log(\"\");\n }\n if (full === undefined) {\n // First, above even the never-overwrite rule, because the rule is an\n // instruction and this is the answer to \"what am I looking at\": measured on\n // the example fleet, this view is over 650 lines and 5,600 words to an\n // unpaged terminal, and the two rows that actually orient a person —\n // `model.likec4 create MISSING`, `spec.md create MISSING` — land past line\n // 450, behind four hundred lines of prose. `--json` is explicitly the agent\n // contract, so nothing was served by leaving the human view unintroduced.\n // `--targets` skips it — bullet three describes sections that view omits,\n // and that view has its own pointer for the same job.\n printOrientation(b);\n console.log(wrap(b.rule, \" \"));\n\n // Before the artifact table, because the table is the output and this is the\n // input: an agent that meets the file list first starts writing files.\n printWalk(b);\n }\n\n console.log(\"\\n artifacts\\n\");\n // The legend again, next to the thing it decodes. A reader who scrolls back\n // to the table two hundred lines later arrives at four flags and no key, and\n // the capital/lowercase distinction is invisible to anyone who has to\n // remember it rather than read it.\n console.log(wrap(LEGEND_LINE, \" \"));\n console.log(\"\");\n const width = Math.max(...b.targets.map((t) => t.artifact.length));\n for (const t of b.targets) {\n // `edit` is the shared fleet map: the file exists, but \"present\" would read\n // as \"nothing to do here\", which is the opposite of why it is on the list.\n // Two words for it, because the two states want different work: `UNDRAWN`\n // when nothing resolves to the service, `EDGELESS` when an element does\n // and no edge touches it — a reader acting on `UNDRAWN` there would look\n // for a box that is already on the map.\n const flag =\n t.action === \"edit\"\n ? b.landscape.modelled === true\n ? \"EDGELESS\"\n : \"UNDRAWN\"\n : t.partial === true\n ? \"PARTIAL\"\n : t.exists\n ? \"present\"\n : t.required\n ? \"MISSING\"\n : \"missing\";\n console.log(` ${t.artifact.padEnd(width)} ${t.action.padEnd(6)} ${flag.padEnd(7)} ${t.purpose}`);\n }\n\n for (const t of b.targets) printShape(t);\n\n printLandscape(b);\n\n if (full === undefined) printChecking(b);\n else {\n // The pointer takes the place of the sections it stands for, in the same\n // position they would have occupied. Anywhere else — a footnote under the\n // closing instructions, say — and it reads as a cross-reference rather\n // than as the notice that this brief is not all of the brief.\n console.log(\"\\n the rest of the brief\\n\");\n console.log(wrap(full, \" \"));\n }\n\n console.log(\"\\n when you are done\\n\");\n console.log(` loam validate --service ${b.service} --json # fix every error`);\n // The fleet run is not a nicety: --service never reports the landscape\n // cross-check, so a baseline can pass the line above with the fleet map\n // never edited at all.\n console.log(` loam validate --all --json # in the docs repo: the fleet map`);\n console.log(` loam vouch --service ${b.service} # a HUMAN, in the service's own repo`);\n console.log(\"\");\n console.log(\n wrap(\n \"Leave everything `status: draft`. Vouching is somebody reading the code and saying the document matches it — it is not yours to do, and a status with no digest behind it is a claim with nothing behind it.\",\n \" \",\n ),\n );\n}\n\n/** The table's five flags, compressed to one terminal line for the scroll-back reader. */\nconst LEGEND_LINE =\n \"MISSING required · missing optional · present diff it · PARTIAL one feature's slice, adopt around it · UNDRAWN add to the map · EDGELESS an element exists, no edge does\";\n\n/**\n * A required target whose work is still outstanding.\n *\n * `!t.exists` alone is the wrong test, and the fleet map is the reason: for\n * every repo after its first service `architecture/landscape.likec4` already\n * exists, so `exists` is true while nothing in it resolves to this boundary —\n * which `loam validate --all` grades `landscape.service-unmodelled`, an ERROR.\n * `action` carries that distinction and nothing else does: `edit` is only ever\n * the fleet map still owed — undrawn, or drawn with no edge touching it (see\n * `BriefTarget.action`, core/brief/targets.ts).\n */\nfunction outstanding(t: BriefTarget): boolean {\n return t.required && (!t.exists || t.action === \"edit\" || t.partial === true);\n}\n\n/**\n * The three sentences that make the rest of the page readable: how much of it\n * is owed, what the table's own convention means, and what the four hundred\n * lines below it are.\n *\n * Every number here is computed from the brief that was just assembled — the\n * outstanding count off `targets`, the section sizes off `walk`, `checks` and\n * `unchecked`. A literal would be right until the next check is added and\n * silently wrong forever after, and this block's whole value is that a reader\n * can trust it instead of scrolling to verify it.\n */\nfunction printOrientation(b: Brief): void {\n const owed = b.targets.filter(outstanding);\n console.log(\" read this first\\n\");\n\n // What is actually owed, named. The count is the load-bearing half: \"some of\n // these are required\" is a sentence a reader skips, \"three of the nine, and\n // here they are\" is one they act on.\n console.log(\n bullet(\n owed.length === 0\n ? `None of the ${String(b.targets.length)} artifacts below is both required and outstanding — every required one is already there. What is left is optional, or an existing document to diff your findings against.`\n : `${String(owed.length)} of the ${String(b.targets.length)} artifacts below ${owed.length === 1 ? \"is\" : \"are\"} required and not yet done: ${owed.map((t) => t.artifact).join(\", \")}. Everything else in the table is optional, or already written and wants diffing rather than replacing.`,\n \" \",\n ),\n );\n console.log(\"\");\n\n // The legend, in full. The table prints `MISSING` and `missing` as if the\n // capitals were emphasis; they are the required/optional distinction, and\n // nothing on the page said so. `UNDRAWN` needs more than a gloss — it is the\n // one row that is not this boundary's file at all.\n console.log(\n bullet(\n \"The flags in that table: `MISSING` in capitals is required and not there, lowercase `missing` is optional and not there, `present` means the file exists — diff it, never replace it. `PARTIAL` is a spec.md marked `adoption: partial`: one archived feature's slice, so keep every requirement in it, write the rest of the service around them, and then delete the `adoption: partial` line. `UNDRAWN` and `EDGELESS` mark the one row that is not this boundary's own file: `architecture/landscape.likec4` is the whole system's map and already holds every other boundary, so ADD to it rather than rewriting it. Until an element in it resolves to this directory, `loam validate --all` reports `landscape.service-unmodelled` (error); `EDGELESS` means an element already does and no edge touches it, so what the map lacks is the calls in and out of it, never a second element.\",\n \" \",\n ),\n );\n console.log(\"\");\n\n // What the rest of the page is, so a reader who stops here still knows what\n // they scrolled past — and where the same content lives for an agent, which\n // is the reader this long body was written for.\n console.log(\n bullet(\n `The rest of this page, in order: the ${String(b.walk.length)}-stop order to read the code in, then the grammar of each artifact — every rule there is one a later check depends on — then the ${String(b.checks.length)} named checks the result will face and the ${String(b.unchecked.length)} statements of what nothing checks. \\`loam adopt --service ${b.service} --json\\` carries the same targets for an agent, and \\`--targets\\` narrows that to only the part that varies by boundary.`,\n \" \",\n ),\n );\n console.log(\"\");\n}\n\n/**\n * The invariant half: the frontmatter rules, the checks that run, and the\n * checks that do not exist. A function of its own only so `--targets` can skip\n * all three in one place — the three sections are the exact set `--targets`\n * omits from `--json`, and splitting them here is what keeps that a single\n * decision instead of three that can drift apart.\n */\nfunction printChecking(b: Brief): void {\n console.log(\"\\n frontmatter — on every markdown artifact\\n\");\n for (const [field, what] of Object.entries(b.frontmatter.fields)) {\n console.log(` ${field}`);\n console.log(wrap(what, \" \"));\n }\n console.log(`\\n never write by hand: ${b.frontmatter.never.join(\", \")}`);\n console.log(`\\n${wrap(b.frontmatter.why, \" \")}`);\n\n // Attribution matters here: the fleet cross-check runs under `--all`, and a\n // header promising it to `--service` sent agents chasing a finding that\n // invocation never reports.\n console.log(`\\n what \\`loam validate --service ${b.service}\\` then checks\\n`);\n for (const c of b.checks) {\n if (c.via !== VIA_ALL) printCheck(c);\n }\n console.log(`\\n and what only \\`loam validate --all\\` surfaces\\n`);\n for (const c of b.checks) {\n if (c.via === VIA_ALL) printCheck(c);\n }\n\n console.log(\"\\n what nothing checks\\n\");\n for (const u of b.unchecked) console.log(bullet(u, \" \"));\n}\n\n/**\n * The walk, numbered. The numbers are the point: an unordered list of nine\n * places to look reads as nine optional suggestions, and the two stops that fix\n * what the service IS have to happen before the surfaces are enumerated.\n */\nfunction printWalk(b: Brief): void {\n console.log(\"\\n read the code in this order — nothing below is written from anything else\\n\");\n for (const [i, stop] of b.walk.entries()) {\n // The hang is explicit rather than derived: `wrap` infers one from a leading\n // `- `, and a numbered stop whose second line starts at the number's own\n // column reads as the next stop — which for a list whose ORDER is the point\n // is the one misreading that costs something.\n console.log(wrap(`${String(i + 1)}. ${stop.where}`, \" \", 88, \" \"));\n // Two more columns than the stop it belongs to: where-to-look and\n // what-to-take are different sentences, and at one indent the second reads\n // as a continuation of the first.\n console.log(wrap(stop.find, \" \"));\n console.log(` → ${stop.lands.join(\", \")}`);\n console.log(\"\");\n }\n console.log(wrap(b.walkClose, \" \"));\n}\n\nfunction printCheck(c: BriefCheck): void {\n console.log(` ${SEVERITY_MARK[c.severity]} ${c.code}`);\n console.log(wrap(c.what, \" \"));\n}\n\nconst ACTION_NOTE: Record<BriefTarget[\"action\"], string> = {\n create: \"\",\n diff: \" (exists — diff, do not replace)\",\n edit: \" (the whole fleet's file — ADD to it, never rewrite it)\",\n};\n\nfunction printShape(t: BriefTarget): void {\n console.log(`\\n ${t.path}${ACTION_NOTE[t.action]}\\n`);\n for (const rule of t.shape) console.log(bullet(rule, \" \"));\n if (t.example === undefined) return;\n console.log(\"\");\n for (const line of t.example.trimEnd().split(\"\\n\")) console.log(` ${line}`.trimEnd());\n}\n\nfunction printLandscape(b: Brief): void {\n const l = b.landscape;\n console.log(\"\\n what the fleet already says about this service\\n\");\n // The instruction is the same sentence the JSON carries, printed from the\n // same field — the text view and `--json` cannot drift into briefing two\n // different writes.\n if (!l.present) {\n console.log(\" architecture/landscape.likec4 does not exist yet — nothing to bind to.\");\n console.log(\"\");\n console.log(wrap(l.instruction ?? \"\", \" \"));\n return;\n }\n if (!l.parses) {\n // Not \"architecture/landscape.likec4 does not parse\": the map is the whole\n // `architecture/` project, so the file that broke is usually a sibling —\n // and this line accused the landscape of errors `validate --all` blamed on\n // a palette. The instruction printed directly below names the documents\n // that actually failed, so the headline says the project and nothing more.\n console.log(\" The fleet map (architecture/) does not parse — fix that first; the files are named below.\");\n console.log(\"\");\n console.log(wrap(l.instruction ?? \"\", \" \"));\n printExpects(l);\n return;\n }\n if (l.elements.length === 0) {\n console.log(` Nothing in the landscape models '${b.service}'.`);\n console.log(\"\");\n console.log(wrap(l.instruction ?? \"\", \" \"));\n return;\n }\n for (const e of l.elements) {\n const bound = e.bound ? \"bound\" : \"matched by title — bind it\";\n console.log(` ${e.id} = ${e.kind} '${e.title}' (${bound})`);\n }\n for (const e of l.inbound) console.log(` ← ${e.from} ${e.op ?? `\"${e.title ?? \"\"}\"`}`);\n for (const e of l.outbound) console.log(` → ${e.to} ${e.op ?? `\"${e.title ?? \"\"}\"`}`);\n // The edgeless state: an element and no edge lines above it. The modelled\n // branch used to return here without ever printing an instruction, which\n // is how the text view briefed \"the map owes nothing\" over two empty lists.\n if (l.instruction !== null) {\n console.log(\"\");\n console.log(wrap(l.instruction, \" \"));\n }\n printExpects(l);\n}\n\n/**\n * What the fleet already calls on this service, and why the contract owes it.\n *\n * Printed in the unparseable branch as well as the healthy one: the landscape\n * FILE still answers who calls this service when a sibling under `architecture/`\n * breaks the project, and it is what decides whether `openapi.yaml` is flagged\n * required — so a reader who is told the map is unreadable still gets the\n * evidence behind that row.\n */\nfunction printExpects(l: Brief[\"landscape\"]): void {\n if (l.expects.length === 0) return;\n const it = l.expects.length === 1 ? \"it\" : \"them\";\n console.log(\"\");\n console.log(\n wrap(\n `openapi.yaml must define ${l.expects.map((o) => `'${o}'`).join(\", \")} — the fleet already calls ${it}, and a contract that omits ${it} fails spine.op-undefined the moment it lands.`,\n \" \",\n ),\n );\n}\n\n/**\n * Wrap prose so the brief is readable in a terminal. Continuation lines are\n * indented past the marker, so a wrapped bullet cannot be misread as two.\n */\nfunction wrap(text: string, indent: string, width = 88, hangIndent?: string): string {\n const hang = hangIndent ?? (/^\\s*-\\s/.test(text) ? `${indent} ` : indent);\n const out: string[] = [];\n let line = indent;\n let pad = indent;\n for (const word of text.trim().split(/\\s+/)) {\n if (line.length > pad.length && line.length + 1 + word.length > width) {\n out.push(line);\n pad = hang;\n line = hang + word;\n } else {\n line = line.length > pad.length ? `${line} ${word}` : line + word;\n }\n }\n out.push(line);\n return out.join(\"\\n\");\n}\n\n/** A bullet, wrapped with its continuation lines hanging under the text. */\nfunction bullet(text: string, indent: string): string {\n return wrap(`- ${text}`, indent);\n}\n"]}