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

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 (1026) hide show
  1. package/CHANGELOG.md +2548 -86
  2. package/COMPARISON.md +80 -63
  3. package/CONTRIBUTING.md +84 -0
  4. package/MIGRATING-from-OpenSpec.md +213 -54
  5. package/QUICKSTART.md +125 -0
  6. package/README.md +450 -150
  7. package/ROADMAP.md +494 -0
  8. package/SCHEMA.md +2355 -256
  9. package/SECURITY.md +21 -3
  10. package/WORKFLOW.md +701 -0
  11. package/dist/cli.js +113 -19
  12. package/dist/cli.js.map +1 -1
  13. package/dist/commands/adopt/adopt.js +209 -0
  14. package/dist/commands/adopt/adopt.js.map +1 -0
  15. package/dist/commands/adopt/render.js +268 -0
  16. package/dist/commands/adopt/render.js.map +1 -0
  17. package/dist/commands/archive/archive.js +77 -0
  18. package/dist/commands/archive/archive.js.map +1 -0
  19. package/dist/commands/archive/plan/contracts/asyncapi.js +178 -0
  20. package/dist/commands/archive/plan/contracts/asyncapi.js.map +1 -0
  21. package/dist/commands/archive/plan/contracts/openapi.js +159 -0
  22. package/dist/commands/archive/plan/contracts/openapi.js.map +1 -0
  23. package/dist/commands/archive/plan/gate.js +317 -0
  24. package/dist/commands/archive/plan/gate.js.map +1 -0
  25. package/dist/commands/archive/plan/landscape.js +161 -0
  26. package/dist/commands/archive/plan/landscape.js.map +1 -0
  27. package/dist/commands/archive/plan/refusal.js +111 -0
  28. package/dist/commands/archive/plan/refusal.js.map +1 -0
  29. package/dist/commands/archive/plan/specs.js +237 -0
  30. package/dist/commands/archive/plan/specs.js.map +1 -0
  31. package/dist/commands/archive/plan/state.js +27 -0
  32. package/dist/commands/archive/plan/state.js.map +1 -0
  33. package/dist/commands/archive/run.js +251 -0
  34. package/dist/commands/archive/run.js.map +1 -0
  35. package/dist/commands/context/context.js +99 -0
  36. package/dist/commands/context/context.js.map +1 -0
  37. package/dist/commands/context/print.js +283 -0
  38. package/dist/commands/context/print.js.map +1 -0
  39. package/dist/commands/delta/delta.js +279 -0
  40. package/dist/commands/delta/delta.js.map +1 -0
  41. package/dist/commands/delta/print.js +205 -0
  42. package/dist/commands/delta/print.js.map +1 -0
  43. package/dist/commands/dependencies.js +9 -7
  44. package/dist/commands/dependencies.js.map +1 -1
  45. package/dist/commands/diff/diff.js +93 -0
  46. package/dist/commands/diff/diff.js.map +1 -0
  47. package/dist/commands/diff/print.js +38 -0
  48. package/dist/commands/diff/print.js.map +1 -0
  49. package/dist/commands/doctor.js +5 -4
  50. package/dist/commands/doctor.js.map +1 -1
  51. package/dist/commands/explain/explain.js +151 -0
  52. package/dist/commands/explain/explain.js.map +1 -0
  53. package/dist/commands/explore.js +29 -24
  54. package/dist/commands/explore.js.map +1 -1
  55. package/dist/commands/gate/gate.js +115 -0
  56. package/dist/commands/gate/gate.js.map +1 -0
  57. package/dist/commands/gate/print.js +54 -0
  58. package/dist/commands/gate/print.js.map +1 -0
  59. package/dist/commands/gherkin/commit.js +146 -0
  60. package/dist/commands/gherkin/commit.js.map +1 -0
  61. package/dist/commands/gherkin/gherkin.js +246 -0
  62. package/dist/commands/gherkin/gherkin.js.map +1 -0
  63. package/dist/commands/gherkin/reconcile.js +149 -0
  64. package/dist/commands/gherkin/reconcile.js.map +1 -0
  65. package/dist/commands/gherkin/render.js +77 -0
  66. package/dist/commands/gherkin/render.js.map +1 -0
  67. package/dist/commands/init/example.js +204 -0
  68. package/dist/commands/init/example.js.map +1 -0
  69. package/dist/commands/init/first-hour.js +28 -0
  70. package/dist/commands/init/first-hour.js.map +1 -0
  71. package/dist/commands/{init.js → init/init.js} +146 -71
  72. package/dist/commands/init/init.js.map +1 -0
  73. package/dist/commands/init/mcp.js +131 -0
  74. package/dist/commands/init/mcp.js.map +1 -0
  75. package/dist/commands/init/options.js +78 -0
  76. package/dist/commands/init/options.js.map +1 -0
  77. package/dist/commands/instructions.js +72 -14
  78. package/dist/commands/instructions.js.map +1 -1
  79. package/dist/commands/list/campaign/campaign.js +65 -0
  80. package/dist/commands/list/campaign/campaign.js.map +1 -0
  81. package/dist/commands/list/campaign/owners.js +65 -0
  82. package/dist/commands/list/campaign/owners.js.map +1 -0
  83. package/dist/commands/list/json.js +157 -0
  84. package/dist/commands/list/json.js.map +1 -0
  85. package/dist/commands/list/list.js +343 -0
  86. package/dist/commands/list/list.js.map +1 -0
  87. package/dist/commands/list/print.js +301 -0
  88. package/dist/commands/list/print.js.map +1 -0
  89. package/dist/commands/list/review.js +120 -0
  90. package/dist/commands/list/review.js.map +1 -0
  91. package/dist/commands/list/views.js +105 -0
  92. package/dist/commands/list/views.js.map +1 -0
  93. package/dist/commands/mcp/dispatch.js +183 -0
  94. package/dist/commands/mcp/dispatch.js.map +1 -0
  95. package/dist/commands/mcp/mcp.js +34 -0
  96. package/dist/commands/mcp/mcp.js.map +1 -0
  97. package/dist/commands/mcp/serve.js +55 -0
  98. package/dist/commands/mcp/serve.js.map +1 -0
  99. package/dist/commands/migrate-openspec/materialize/active.js +170 -0
  100. package/dist/commands/migrate-openspec/materialize/active.js.map +1 -0
  101. package/dist/commands/migrate-openspec/materialize/feature.js +41 -0
  102. package/dist/commands/migrate-openspec/materialize/feature.js.map +1 -0
  103. package/dist/commands/migrate-openspec/materialize/living.js +62 -0
  104. package/dist/commands/migrate-openspec/materialize/living.js.map +1 -0
  105. package/dist/commands/migrate-openspec/materialize/stage.js +142 -0
  106. package/dist/commands/migrate-openspec/materialize/stage.js.map +1 -0
  107. package/dist/commands/migrate-openspec/materialize/target.js +219 -0
  108. package/dist/commands/migrate-openspec/materialize/target.js.map +1 -0
  109. package/dist/commands/migrate-openspec/migrate-openspec.js +142 -0
  110. package/dist/commands/migrate-openspec/migrate-openspec.js.map +1 -0
  111. package/dist/commands/migrate-openspec/openspec/decisions.js +91 -0
  112. package/dist/commands/migrate-openspec/openspec/decisions.js.map +1 -0
  113. package/dist/commands/migrate-openspec/openspec/error.js +19 -0
  114. package/dist/commands/migrate-openspec/openspec/error.js.map +1 -0
  115. package/dist/commands/migrate-openspec/openspec/mapping.js +170 -0
  116. package/dist/commands/migrate-openspec/openspec/mapping.js.map +1 -0
  117. package/dist/commands/migrate-openspec/openspec/paths.js +43 -0
  118. package/dist/commands/migrate-openspec/openspec/paths.js.map +1 -0
  119. package/dist/commands/migrate-openspec/openspec/read.js +49 -0
  120. package/dist/commands/migrate-openspec/openspec/read.js.map +1 -0
  121. package/dist/commands/migrate-openspec/print.js +89 -0
  122. package/dist/commands/migrate-openspec/print.js.map +1 -0
  123. package/dist/commands/new/commit.js +76 -0
  124. package/dist/commands/new/commit.js.map +1 -0
  125. package/dist/commands/new/new.js +283 -0
  126. package/dist/commands/new/new.js.map +1 -0
  127. package/dist/commands/new/templates.js +355 -0
  128. package/dist/commands/new/templates.js.map +1 -0
  129. package/dist/commands/open.js +203 -0
  130. package/dist/commands/open.js.map +1 -0
  131. package/dist/commands/policy/format.js +152 -0
  132. package/dist/commands/policy/format.js.map +1 -0
  133. package/dist/commands/{docs-repo-gate.js → policy/gate.js} +11 -11
  134. package/dist/commands/policy/gate.js.map +1 -0
  135. package/dist/commands/rebase/edit.js +106 -0
  136. package/dist/commands/rebase/edit.js.map +1 -0
  137. package/dist/commands/rebase/living.js +185 -0
  138. package/dist/commands/rebase/living.js.map +1 -0
  139. package/dist/commands/rebase/plan.js +245 -0
  140. package/dist/commands/rebase/plan.js.map +1 -0
  141. package/dist/commands/rebase/rebase.js +275 -0
  142. package/dist/commands/rebase/rebase.js.map +1 -0
  143. package/dist/commands/seed/commit.js +192 -0
  144. package/dist/commands/seed/commit.js.map +1 -0
  145. package/dist/commands/seed/plan.js +133 -0
  146. package/dist/commands/seed/plan.js.map +1 -0
  147. package/dist/commands/seed/seed.js +172 -0
  148. package/dist/commands/seed/seed.js.map +1 -0
  149. package/dist/commands/show/feature.js +178 -0
  150. package/dist/commands/show/feature.js.map +1 -0
  151. package/dist/commands/show/marks.js +24 -0
  152. package/dist/commands/show/marks.js.map +1 -0
  153. package/dist/commands/{show.js → show/service.js} +63 -152
  154. package/dist/commands/show/service.js.map +1 -0
  155. package/dist/commands/show/show.js +77 -0
  156. package/dist/commands/show/show.js.map +1 -0
  157. package/dist/commands/status/json.js +45 -0
  158. package/dist/commands/status/json.js.map +1 -0
  159. package/dist/commands/status/print.js +157 -0
  160. package/dist/commands/status/print.js.map +1 -0
  161. package/dist/commands/status/status.js +119 -0
  162. package/dist/commands/status/status.js.map +1 -0
  163. package/dist/commands/steps/steps.js +189 -0
  164. package/dist/commands/steps/steps.js.map +1 -0
  165. package/dist/commands/subsystem/edit.js +192 -0
  166. package/dist/commands/subsystem/edit.js.map +1 -0
  167. package/dist/commands/subsystem/move.js +265 -0
  168. package/dist/commands/subsystem/move.js.map +1 -0
  169. package/dist/commands/subsystem/query.js +115 -0
  170. package/dist/commands/subsystem/query.js.map +1 -0
  171. package/dist/commands/subsystem/subsystem.js +101 -0
  172. package/dist/commands/subsystem/subsystem.js.map +1 -0
  173. package/dist/commands/subsystem/sync.js +103 -0
  174. package/dist/commands/subsystem/sync.js.map +1 -0
  175. package/dist/commands/subsystem/txn/txn.js +94 -0
  176. package/dist/commands/subsystem/txn/txn.js.map +1 -0
  177. package/dist/commands/subsystem/txn/views.js +70 -0
  178. package/dist/commands/subsystem/txn/views.js.map +1 -0
  179. package/dist/commands/unarchive/manifest.js +160 -0
  180. package/dist/commands/unarchive/manifest.js.map +1 -0
  181. package/dist/commands/{unarchive.js → unarchive/restore.js} +47 -160
  182. package/dist/commands/unarchive/restore.js.map +1 -0
  183. package/dist/commands/unarchive/unarchive.js +67 -0
  184. package/dist/commands/unarchive/unarchive.js.map +1 -0
  185. package/dist/commands/validate/arch-coverage.js +194 -0
  186. package/dist/commands/validate/arch-coverage.js.map +1 -0
  187. package/dist/commands/validate/checks/fleet-shape.js +296 -0
  188. package/dist/commands/validate/checks/fleet-shape.js.map +1 -0
  189. package/dist/commands/validate/checks/health-deps.js +55 -0
  190. package/dist/commands/validate/checks/health-deps.js.map +1 -0
  191. package/dist/commands/validate/checks/requirements.js +254 -0
  192. package/dist/commands/validate/checks/requirements.js.map +1 -0
  193. package/dist/commands/validate/checks/sources.js +76 -0
  194. package/dist/commands/validate/checks/sources.js.map +1 -0
  195. package/dist/commands/validate/checks/vocabulary.js +31 -0
  196. package/dist/commands/validate/checks/vocabulary.js.map +1 -0
  197. package/dist/commands/validate/feature.js +216 -0
  198. package/dist/commands/validate/feature.js.map +1 -0
  199. package/dist/commands/validate/fleet/census.js +69 -0
  200. package/dist/commands/validate/fleet/census.js.map +1 -0
  201. package/dist/commands/validate/fleet/kind-tags.js +39 -0
  202. package/dist/commands/validate/fleet/kind-tags.js.map +1 -0
  203. package/dist/commands/validate/fleet/landscape.js +353 -0
  204. package/dist/commands/validate/fleet/landscape.js.map +1 -0
  205. package/dist/commands/validate/fleet/load.js +52 -0
  206. package/dist/commands/validate/fleet/load.js.map +1 -0
  207. package/dist/commands/validate/fleet/obligations.js +236 -0
  208. package/dist/commands/validate/fleet/obligations.js.map +1 -0
  209. package/dist/commands/validate/fleet/scorecard/adoption.js +102 -0
  210. package/dist/commands/validate/fleet/scorecard/adoption.js.map +1 -0
  211. package/dist/commands/validate/fleet/scorecard/contracts.js +98 -0
  212. package/dist/commands/validate/fleet/scorecard/contracts.js.map +1 -0
  213. package/dist/commands/validate/fleet/scorecard/print.js +63 -0
  214. package/dist/commands/validate/fleet/scorecard/print.js.map +1 -0
  215. package/dist/commands/validate/fleet/scorecard/scorecard.js +156 -0
  216. package/dist/commands/validate/fleet/scorecard/scorecard.js.map +1 -0
  217. package/dist/commands/validate/fleet/usecases/capability-tag.js +94 -0
  218. package/dist/commands/validate/fleet/usecases/capability-tag.js.map +1 -0
  219. package/dist/commands/validate/fleet/usecases/place.js +13 -0
  220. package/dist/commands/validate/fleet/usecases/place.js.map +1 -0
  221. package/dist/commands/validate/fleet/usecases/requirement-tag.js +95 -0
  222. package/dist/commands/validate/fleet/usecases/requirement-tag.js.map +1 -0
  223. package/dist/commands/validate/fleet/usecases/steps.js +197 -0
  224. package/dist/commands/validate/fleet/usecases/steps.js.map +1 -0
  225. package/dist/commands/validate/fleet/usecases/usecases.js +99 -0
  226. package/dist/commands/validate/fleet/usecases/usecases.js.map +1 -0
  227. package/dist/commands/validate/fleet/views/ids.js +40 -0
  228. package/dist/commands/validate/fleet/views/ids.js.map +1 -0
  229. package/dist/commands/validate/fleet/views/stale.js +59 -0
  230. package/dist/commands/validate/fleet/views/stale.js.map +1 -0
  231. package/dist/commands/validate/links/corpus.js +92 -0
  232. package/dist/commands/validate/links/corpus.js.map +1 -0
  233. package/dist/commands/validate/links/glossary.js +75 -0
  234. package/dist/commands/validate/links/glossary.js.map +1 -0
  235. package/dist/commands/validate/report.js +269 -0
  236. package/dist/commands/validate/report.js.map +1 -0
  237. package/dist/commands/validate/service/api.js +338 -0
  238. package/dist/commands/validate/service/api.js.map +1 -0
  239. package/dist/commands/validate/service/events/events.js +219 -0
  240. package/dist/commands/validate/service/events/events.js.map +1 -0
  241. package/dist/commands/validate/service/events/message-producers.js +77 -0
  242. package/dist/commands/validate/service/events/message-producers.js.map +1 -0
  243. package/dist/commands/validate/service/evidence-pins.js +131 -0
  244. package/dist/commands/validate/service/evidence-pins.js.map +1 -0
  245. package/dist/commands/validate/service/service.js +250 -0
  246. package/dist/commands/validate/service/service.js.map +1 -0
  247. package/dist/commands/validate/service/specs.js +219 -0
  248. package/dist/commands/validate/service/specs.js.map +1 -0
  249. package/dist/commands/validate/service/spine.js +113 -0
  250. package/dist/commands/validate/service/spine.js.map +1 -0
  251. package/dist/commands/validate/validate.js +338 -0
  252. package/dist/commands/validate/validate.js.map +1 -0
  253. package/dist/commands/verify/cross/diff.js +182 -0
  254. package/dist/commands/verify/cross/diff.js.map +1 -0
  255. package/dist/commands/verify/evidence/contract.js +32 -0
  256. package/dist/commands/verify/evidence/contract.js.map +1 -0
  257. package/dist/commands/verify/evidence/pins.js +52 -0
  258. package/dist/commands/verify/evidence/pins.js.map +1 -0
  259. package/dist/commands/verify/evidence/read.js +72 -0
  260. package/dist/commands/verify/evidence/read.js.map +1 -0
  261. package/dist/commands/verify/frozen.js +241 -0
  262. package/dist/commands/verify/frozen.js.map +1 -0
  263. package/dist/commands/verify/record.js +226 -0
  264. package/dist/commands/verify/record.js.map +1 -0
  265. package/dist/commands/verify/report.js +223 -0
  266. package/dist/commands/verify/report.js.map +1 -0
  267. package/dist/commands/verify/results.js +246 -0
  268. package/dist/commands/verify/results.js.map +1 -0
  269. package/dist/commands/verify/verify.js +217 -0
  270. package/dist/commands/verify/verify.js.map +1 -0
  271. package/dist/commands/vouch/contract.js +11 -0
  272. package/dist/commands/vouch/contract.js.map +1 -0
  273. package/dist/commands/vouch/pack/contract.js +2 -0
  274. package/dist/commands/vouch/pack/contract.js.map +1 -0
  275. package/dist/commands/vouch/pack/pack.js +266 -0
  276. package/dist/commands/vouch/pack/pack.js.map +1 -0
  277. package/dist/commands/vouch/pack/print.js +271 -0
  278. package/dist/commands/vouch/pack/print.js.map +1 -0
  279. package/dist/commands/vouch/pack/sections.js +142 -0
  280. package/dist/commands/vouch/pack/sections.js.map +1 -0
  281. package/dist/commands/vouch/prompt/confirm.js +46 -0
  282. package/dist/commands/vouch/prompt/confirm.js.map +1 -0
  283. package/dist/commands/vouch/report.js +101 -0
  284. package/dist/commands/vouch/report.js.map +1 -0
  285. package/dist/commands/vouch/run.js +285 -0
  286. package/dist/commands/vouch/run.js.map +1 -0
  287. package/dist/commands/vouch/sample/plan.js +125 -0
  288. package/dist/commands/vouch/sample/plan.js.map +1 -0
  289. package/dist/commands/vouch/sample/print.js +109 -0
  290. package/dist/commands/vouch/sample/print.js.map +1 -0
  291. package/dist/commands/vouch/vet/verify.js +123 -0
  292. package/dist/commands/vouch/vet/verify.js.map +1 -0
  293. package/dist/commands/vouch/vouch.js +176 -0
  294. package/dist/commands/vouch/vouch.js.map +1 -0
  295. package/dist/core/agent/agents-md/artifacts.js +220 -0
  296. package/dist/core/agent/agents-md/artifacts.js.map +1 -0
  297. package/dist/core/agent/agents-md/command-map.js +324 -0
  298. package/dist/core/agent/agents-md/command-map.js.map +1 -0
  299. package/dist/core/agent/agents-md/cycle.js +165 -0
  300. package/dist/core/agent/agents-md/cycle.js.map +1 -0
  301. package/dist/core/agent/agents-md/map/explain.js +34 -0
  302. package/dist/core/agent/agents-md/map/explain.js.map +1 -0
  303. package/dist/core/agent/agents-md/map/lenses/context.js +41 -0
  304. package/dist/core/agent/agents-md/map/lenses/context.js.map +1 -0
  305. package/dist/core/agent/agents-md/map/lenses/diff.js +46 -0
  306. package/dist/core/agent/agents-md/map/lenses/diff.js.map +1 -0
  307. package/dist/core/agent/agents-md/map/lenses/gate.js +57 -0
  308. package/dist/core/agent/agents-md/map/lenses/gate.js.map +1 -0
  309. package/dist/core/agent/agents-md/map/mcp.js +41 -0
  310. package/dist/core/agent/agents-md/map/mcp.js.map +1 -0
  311. package/dist/core/agent/agents-md/map/status.js +62 -0
  312. package/dist/core/agent/agents-md/map/status.js.map +1 -0
  313. package/dist/core/agent/agents-md/map/subsystem.js +32 -0
  314. package/dist/core/agent/agents-md/map/subsystem.js.map +1 -0
  315. package/dist/core/agent/agents-md/map/usecases.js +60 -0
  316. package/dist/core/agent/agents-md/map/usecases.js.map +1 -0
  317. package/dist/core/agent/agents-md/refusals.js +246 -0
  318. package/dist/core/agent/agents-md/refusals.js.map +1 -0
  319. package/dist/core/agent/agents-md/shipped/archive-gate.js +98 -0
  320. package/dist/core/agent/agents-md/shipped/archive-gate.js.map +1 -0
  321. package/dist/core/agent/agents-md/spine.js +40 -0
  322. package/dist/core/agent/agents-md/spine.js.map +1 -0
  323. package/dist/core/agent/agents-md.js +170 -0
  324. package/dist/core/agent/agents-md.js.map +1 -0
  325. package/dist/core/{agents-stamp.js → agent/agents-stamp.js} +50 -0
  326. package/dist/core/agent/agents-stamp.js.map +1 -0
  327. package/dist/core/agent/contract.js +2 -0
  328. package/dist/core/agent/contract.js.map +1 -0
  329. package/dist/core/agent/protocol.js +193 -0
  330. package/dist/core/agent/protocol.js.map +1 -0
  331. package/dist/core/agent/scaffold.js +259 -0
  332. package/dist/core/agent/scaffold.js.map +1 -0
  333. package/dist/core/agent/support/report.js +103 -0
  334. package/dist/core/agent/support/report.js.map +1 -0
  335. package/dist/core/agent/tools/dialects.js +150 -0
  336. package/dist/core/agent/tools/dialects.js.map +1 -0
  337. package/dist/core/agent/tools/registry.js +228 -0
  338. package/dist/core/agent/tools/registry.js.map +1 -0
  339. package/dist/core/agent/workflows/adopt.js +133 -0
  340. package/dist/core/agent/workflows/adopt.js.map +1 -0
  341. package/dist/core/agent/workflows/check.js +334 -0
  342. package/dist/core/agent/workflows/check.js.map +1 -0
  343. package/dist/core/agent/workflows/closing.js +262 -0
  344. package/dist/core/agent/workflows/closing.js.map +1 -0
  345. package/dist/core/agent/workflows/feature.js +105 -0
  346. package/dist/core/agent/workflows/feature.js.map +1 -0
  347. package/dist/core/agent/workflows/implement.js +105 -0
  348. package/dist/core/agent/workflows/implement.js.map +1 -0
  349. package/dist/core/agent/workflows/reference/authoring.js +209 -0
  350. package/dist/core/agent/workflows/reference/authoring.js.map +1 -0
  351. package/dist/core/agent/workflows/reference/codes.js +65 -0
  352. package/dist/core/agent/workflows/reference/codes.js.map +1 -0
  353. package/dist/core/agent/workflows/reference/done-check.js +188 -0
  354. package/dist/core/agent/workflows/reference/done-check.js.map +1 -0
  355. package/dist/core/agent/workflows/reference/reference.js +16 -0
  356. package/dist/core/agent/workflows/reference/reference.js.map +1 -0
  357. package/dist/core/agent/workflows/reference/spine.js +297 -0
  358. package/dist/core/agent/workflows/reference/spine.js.map +1 -0
  359. package/dist/core/asyncapi/baseline/plan.js +110 -0
  360. package/dist/core/asyncapi/baseline/plan.js.map +1 -0
  361. package/dist/core/asyncapi/baseline/surfaces.js +54 -0
  362. package/dist/core/asyncapi/baseline/surfaces.js.map +1 -0
  363. package/dist/core/asyncapi/depth.js +164 -0
  364. package/dist/core/asyncapi/depth.js.map +1 -0
  365. package/dist/core/asyncapi/digest.js +141 -0
  366. package/dist/core/asyncapi/digest.js.map +1 -0
  367. package/dist/core/asyncapi/merge/components.js +91 -0
  368. package/dist/core/asyncapi/merge/components.js.map +1 -0
  369. package/dist/core/asyncapi/merge/error.js +33 -0
  370. package/dist/core/asyncapi/merge/error.js.map +1 -0
  371. package/dist/core/asyncapi/merge/markers.js +308 -0
  372. package/dist/core/asyncapi/merge/markers.js.map +1 -0
  373. package/dist/core/asyncapi/merge/merge.js +215 -0
  374. package/dist/core/asyncapi/merge/merge.js.map +1 -0
  375. package/dist/core/asyncapi/merge/pin.js +107 -0
  376. package/dist/core/asyncapi/merge/pin.js.map +1 -0
  377. package/dist/core/asyncapi/model.js +11 -0
  378. package/dist/core/asyncapi/model.js.map +1 -0
  379. package/dist/core/asyncapi/producers.js +50 -0
  380. package/dist/core/asyncapi/producers.js.map +1 -0
  381. package/dist/core/{asyncapi.js → asyncapi/read.js} +95 -109
  382. package/dist/core/asyncapi/read.js.map +1 -0
  383. package/dist/core/brief/brief.js +225 -0
  384. package/dist/core/brief/brief.js.map +1 -0
  385. package/dist/core/brief/checks.js +250 -0
  386. package/dist/core/brief/checks.js.map +1 -0
  387. package/dist/core/brief/landscape.js +194 -0
  388. package/dist/core/brief/landscape.js.map +1 -0
  389. package/dist/core/brief/targets.js +226 -0
  390. package/dist/core/brief/targets.js.map +1 -0
  391. package/dist/core/brief/unchecked.js +47 -0
  392. package/dist/core/brief/unchecked.js.map +1 -0
  393. package/dist/core/c4/arch.js +282 -0
  394. package/dist/core/c4/arch.js.map +1 -0
  395. package/dist/core/c4/likec4.js +88 -0
  396. package/dist/core/c4/likec4.js.map +1 -0
  397. package/dist/core/c4/parsed/dynamic-views.js +132 -0
  398. package/dist/core/c4/parsed/dynamic-views.js.map +1 -0
  399. package/dist/core/c4/parsed/specification.js +78 -0
  400. package/dist/core/c4/parsed/specification.js.map +1 -0
  401. package/dist/core/c4/parsed/values.js +57 -0
  402. package/dist/core/c4/parsed/values.js.map +1 -0
  403. package/dist/core/c4/parsed/view-ids.js +75 -0
  404. package/dist/core/c4/parsed/view-ids.js.map +1 -0
  405. package/dist/core/c4/project/architecture.js +45 -0
  406. package/dist/core/c4/project/architecture.js.map +1 -0
  407. package/dist/core/c4/project/documents.js +58 -0
  408. package/dist/core/c4/project/documents.js.map +1 -0
  409. package/dist/core/c4/project/load.js +183 -0
  410. package/dist/core/c4/project/load.js.map +1 -0
  411. package/dist/core/c4/resolve/service.js +113 -0
  412. package/dist/core/c4/resolve/service.js.map +1 -0
  413. package/dist/core/c4/seed/fleet-file.js +201 -0
  414. package/dist/core/c4/seed/fleet-file.js.map +1 -0
  415. package/dist/core/c4/seed/items.js +91 -0
  416. package/dist/core/c4/seed/items.js.map +1 -0
  417. package/dist/core/c4/seed/stamp.js +48 -0
  418. package/dist/core/c4/seed/stamp.js.map +1 -0
  419. package/dist/core/c4/seed/template.js +109 -0
  420. package/dist/core/c4/seed/template.js.map +1 -0
  421. package/dist/core/c4/source-mask.js +82 -0
  422. package/dist/core/c4/source-mask.js.map +1 -0
  423. package/dist/core/c4/source-scan.js +227 -0
  424. package/dist/core/c4/source-scan.js.map +1 -0
  425. package/dist/core/c4/splice/authored-source.js +101 -0
  426. package/dist/core/c4/splice/authored-source.js.map +1 -0
  427. package/dist/core/c4/splice/contract.js +10 -0
  428. package/dist/core/c4/splice/contract.js.map +1 -0
  429. package/dist/core/c4/splice/delta-blocks.js +126 -0
  430. package/dist/core/c4/splice/delta-blocks.js.map +1 -0
  431. package/dist/core/c4/splice/identity/edges.js +36 -0
  432. package/dist/core/c4/splice/identity/edges.js.map +1 -0
  433. package/dist/core/c4/splice/landscape-merge.js +269 -0
  434. package/dist/core/c4/splice/landscape-merge.js.map +1 -0
  435. package/dist/core/c4/splice/placement.js +194 -0
  436. package/dist/core/c4/splice/placement.js.map +1 -0
  437. package/dist/core/c4/workspace.js +172 -0
  438. package/dist/core/c4/workspace.js.map +1 -0
  439. package/dist/core/capabilities/authoring/notes.js +141 -0
  440. package/dist/core/capabilities/authoring/notes.js.map +1 -0
  441. package/dist/core/capabilities/capabilities.js +124 -0
  442. package/dist/core/capabilities/capabilities.js.map +1 -0
  443. package/dist/core/capabilities/delta/doc.js +50 -0
  444. package/dist/core/capabilities/delta/doc.js.map +1 -0
  445. package/dist/core/capabilities/delta/overlay.js +129 -0
  446. package/dist/core/capabilities/delta/overlay.js.map +1 -0
  447. package/dist/core/capabilities/delta/summary.js +57 -0
  448. package/dist/core/capabilities/delta/summary.js.map +1 -0
  449. package/dist/core/capabilities/delta/tree.js +43 -0
  450. package/dist/core/capabilities/delta/tree.js.map +1 -0
  451. package/dist/core/capabilities/delta/uncovered.js +222 -0
  452. package/dist/core/capabilities/delta/uncovered.js.map +1 -0
  453. package/dist/core/capabilities/findings.js +342 -0
  454. package/dist/core/capabilities/findings.js.map +1 -0
  455. package/dist/core/capabilities/realizes/findings.js +181 -0
  456. package/dist/core/capabilities/realizes/findings.js.map +1 -0
  457. package/dist/core/capabilities/realizes/join.js +143 -0
  458. package/dist/core/capabilities/realizes/join.js.map +1 -0
  459. package/dist/core/capabilities/rollup.js +199 -0
  460. package/dist/core/capabilities/rollup.js.map +1 -0
  461. package/dist/core/capabilities/tree.js +126 -0
  462. package/dist/core/capabilities/tree.js.map +1 -0
  463. package/dist/core/capabilities/usecase-join.js +277 -0
  464. package/dist/core/capabilities/usecase-join.js.map +1 -0
  465. package/dist/core/coherence/authoring/scaffold.js +177 -0
  466. package/dist/core/coherence/authoring/scaffold.js.map +1 -0
  467. package/dist/core/coherence/authoring/sentinels.js +74 -0
  468. package/dist/core/coherence/authoring/sentinels.js.map +1 -0
  469. package/dist/core/coherence/coherence.js +251 -0
  470. package/dist/core/coherence/coherence.js.map +1 -0
  471. package/dist/core/coherence/declared.js +269 -0
  472. package/dist/core/coherence/declared.js.map +1 -0
  473. package/dist/core/coherence/events/declared.js +206 -0
  474. package/dist/core/coherence/events/declared.js.map +1 -0
  475. package/dist/core/coherence/events/events.js +204 -0
  476. package/dist/core/coherence/events/events.js.map +1 -0
  477. package/dist/core/coherence/events/grades.js +166 -0
  478. package/dist/core/coherence/events/grades.js.map +1 -0
  479. package/dist/core/coherence/events/lookups.js +122 -0
  480. package/dist/core/coherence/events/lookups.js.map +1 -0
  481. package/dist/core/coherence/events/merged.js +40 -0
  482. package/dist/core/coherence/events/merged.js.map +1 -0
  483. package/dist/core/coherence/living.js +198 -0
  484. package/dist/core/coherence/living.js.map +1 -0
  485. package/dist/core/coherence/lookups.js +155 -0
  486. package/dist/core/coherence/lookups.js.map +1 -0
  487. package/dist/core/coherence/pending.js +39 -0
  488. package/dist/core/coherence/pending.js.map +1 -0
  489. package/dist/core/conflict-markers.js +60 -0
  490. package/dist/core/conflict-markers.js.map +1 -0
  491. package/dist/core/delta/claims.js +73 -0
  492. package/dist/core/delta/claims.js.map +1 -0
  493. package/dist/core/delta/delta.js +296 -0
  494. package/dist/core/delta/delta.js.map +1 -0
  495. package/dist/core/delta/document.js +177 -0
  496. package/dist/core/delta/document.js.map +1 -0
  497. package/dist/core/delta/scope.js +48 -0
  498. package/dist/core/delta/scope.js.map +1 -0
  499. package/dist/core/delta/select.js +237 -0
  500. package/dist/core/delta/select.js.map +1 -0
  501. package/dist/core/dependencies/dependencies.js +141 -0
  502. package/dist/core/dependencies/dependencies.js.map +1 -0
  503. package/dist/core/dependencies/facts.js +165 -0
  504. package/dist/core/dependencies/facts.js.map +1 -0
  505. package/dist/core/dependencies/fanin.js +88 -0
  506. package/dist/core/dependencies/fanin.js.map +1 -0
  507. package/dist/core/dependencies/graph.js +106 -0
  508. package/dist/core/dependencies/graph.js.map +1 -0
  509. package/dist/core/diff/base-git.js +148 -0
  510. package/dist/core/diff/base-git.js.map +1 -0
  511. package/dist/core/diff/base-state.js +209 -0
  512. package/dist/core/diff/base-state.js.map +1 -0
  513. package/dist/core/diff/current-state.js +96 -0
  514. package/dist/core/diff/current-state.js.map +1 -0
  515. package/dist/core/diff/scope/changed-paths.js +188 -0
  516. package/dist/core/diff/scope/changed-paths.js.map +1 -0
  517. package/dist/core/diff/semantic.js +243 -0
  518. package/dist/core/diff/semantic.js.map +1 -0
  519. package/dist/core/diff/victims.js +247 -0
  520. package/dist/core/diff/victims.js.map +1 -0
  521. package/dist/core/docs.js +7 -64
  522. package/dist/core/docs.js.map +1 -1
  523. package/dist/core/doctor/agents.js +222 -0
  524. package/dist/core/doctor/agents.js.map +1 -0
  525. package/dist/core/doctor/config.js +135 -0
  526. package/dist/core/doctor/config.js.map +1 -0
  527. package/dist/core/doctor/doctor.js +275 -0
  528. package/dist/core/doctor/doctor.js.map +1 -0
  529. package/dist/core/doctor/report.js +13 -0
  530. package/dist/core/doctor/report.js.map +1 -0
  531. package/dist/core/doctor/residue.js +110 -0
  532. package/dist/core/doctor/residue.js.map +1 -0
  533. package/dist/core/document/apply.js +77 -0
  534. package/dist/core/document/apply.js.map +1 -0
  535. package/dist/core/{frontmatter.js → document/frontmatter.js} +48 -2
  536. package/dist/core/document/frontmatter.js.map +1 -0
  537. package/dist/core/document/grammar/directives.js +143 -0
  538. package/dist/core/document/grammar/directives.js.map +1 -0
  539. package/dist/core/document/parse.js +263 -0
  540. package/dist/core/document/parse.js.map +1 -0
  541. package/dist/core/document/scenarios.js +221 -0
  542. package/dist/core/document/scenarios.js.map +1 -0
  543. package/dist/core/document/spec.js +241 -0
  544. package/dist/core/document/spec.js.map +1 -0
  545. package/dist/core/{config.js → envelope/config.js} +79 -18
  546. package/dist/core/envelope/config.js.map +1 -0
  547. package/dist/core/envelope/json.js +175 -0
  548. package/dist/core/envelope/json.js.map +1 -0
  549. package/dist/core/{version.js → envelope/version.js} +3 -3
  550. package/dist/core/envelope/version.js.map +1 -0
  551. package/dist/core/explain/families.js +175 -0
  552. package/dist/core/explain/families.js.map +1 -0
  553. package/dist/core/explain/fix-tables.js +178 -0
  554. package/dist/core/explain/fix-tables.js.map +1 -0
  555. package/dist/core/explain/lookup.js +181 -0
  556. package/dist/core/explain/lookup.js.map +1 -0
  557. package/dist/core/explain/refusals.js +49 -0
  558. package/dist/core/explain/refusals.js.map +1 -0
  559. package/dist/core/explain/terms.js +144 -0
  560. package/dist/core/explain/terms.js.map +1 -0
  561. package/dist/core/explore/describe.js +105 -0
  562. package/dist/core/explore/describe.js.map +1 -0
  563. package/dist/core/{explore.js → explore/explore.js} +50 -101
  564. package/dist/core/explore/explore.js.map +1 -0
  565. package/dist/core/fleet-context.js +120 -78
  566. package/dist/core/fleet-context.js.map +1 -1
  567. package/dist/core/gate/checks.js +201 -0
  568. package/dist/core/gate/checks.js.map +1 -0
  569. package/dist/core/gate/partners.js +205 -0
  570. package/dist/core/gate/partners.js.map +1 -0
  571. package/dist/core/gate/report.js +47 -0
  572. package/dist/core/gate/report.js.map +1 -0
  573. package/dist/core/gate/verification.js +113 -0
  574. package/dist/core/gate/verification.js.map +1 -0
  575. package/dist/core/gherkin/digest.js +60 -0
  576. package/dist/core/gherkin/digest.js.map +1 -0
  577. package/dist/core/gherkin/emit.js +177 -0
  578. package/dist/core/gherkin/emit.js.map +1 -0
  579. package/dist/core/gherkin/read.js +76 -0
  580. package/dist/core/gherkin/read.js.map +1 -0
  581. package/dist/core/gherkin/stale.js +234 -0
  582. package/dist/core/gherkin/stale.js.map +1 -0
  583. package/dist/core/gherkin/stamp.js +77 -0
  584. package/dist/core/gherkin/stamp.js.map +1 -0
  585. package/dist/core/gherkin/steps/catalogue.js +154 -0
  586. package/dist/core/gherkin/steps/catalogue.js.map +1 -0
  587. package/dist/core/gherkin/steps/inventory.js +98 -0
  588. package/dist/core/gherkin/steps/inventory.js.map +1 -0
  589. package/dist/core/gherkin/steps/phrase.js +72 -0
  590. package/dist/core/gherkin/steps/phrase.js.map +1 -0
  591. package/dist/core/glossary/delta.js +106 -0
  592. package/dist/core/glossary/delta.js.map +1 -0
  593. package/dist/core/glossary/tree.js +86 -0
  594. package/dist/core/glossary/tree.js.map +1 -0
  595. package/dist/core/kernel/concurrency.js.map +1 -0
  596. package/dist/core/{document-bytes.js → kernel/document-bytes.js} +1 -1
  597. package/dist/core/kernel/document-bytes.js.map +1 -0
  598. package/dist/core/kernel/fences.js +42 -0
  599. package/dist/core/kernel/fences.js.map +1 -0
  600. package/dist/core/kernel/ids/capability.js +72 -0
  601. package/dist/core/kernel/ids/capability.js.map +1 -0
  602. package/dist/core/kernel/ids/dirs.js +33 -0
  603. package/dist/core/kernel/ids/dirs.js.map +1 -0
  604. package/dist/core/kernel/ids/feature.js +75 -0
  605. package/dist/core/kernel/ids/feature.js.map +1 -0
  606. package/dist/core/kernel/ids/service.js +156 -0
  607. package/dist/core/kernel/ids/service.js.map +1 -0
  608. package/dist/core/kernel/ids/subsystem.js +63 -0
  609. package/dist/core/kernel/ids/subsystem.js.map +1 -0
  610. package/dist/core/{path-safety.js → kernel/path-safety.js} +18 -4
  611. package/dist/core/kernel/path-safety.js.map +1 -0
  612. package/dist/core/kernel/records.js.map +1 -0
  613. package/dist/core/links/backlinks.js +68 -0
  614. package/dist/core/links/backlinks.js.map +1 -0
  615. package/dist/core/links/case.js +74 -0
  616. package/dist/core/links/case.js.map +1 -0
  617. package/dist/core/links/corpus.js +104 -0
  618. package/dist/core/links/corpus.js.map +1 -0
  619. package/dist/core/links/findings.js +110 -0
  620. package/dist/core/links/findings.js.map +1 -0
  621. package/dist/core/links/parse.js +236 -0
  622. package/dist/core/links/parse.js.map +1 -0
  623. package/dist/core/mcp/argv.js +111 -0
  624. package/dist/core/mcp/argv.js.map +1 -0
  625. package/dist/core/mcp/author-tools.js +72 -0
  626. package/dist/core/mcp/author-tools.js.map +1 -0
  627. package/dist/core/mcp/framing.js +46 -0
  628. package/dist/core/mcp/framing.js.map +1 -0
  629. package/dist/core/mcp/protocol.js +280 -0
  630. package/dist/core/mcp/protocol.js.map +1 -0
  631. package/dist/core/mcp/tools.js +314 -0
  632. package/dist/core/mcp/tools.js.map +1 -0
  633. package/dist/core/obligations/obligations.js +106 -0
  634. package/dist/core/obligations/obligations.js.map +1 -0
  635. package/dist/core/openapi/baseline/gate.js +166 -0
  636. package/dist/core/openapi/baseline/gate.js.map +1 -0
  637. package/dist/core/openapi/baseline/plan.js +112 -0
  638. package/dist/core/openapi/baseline/plan.js.map +1 -0
  639. package/dist/core/openapi/baseline/record.js +175 -0
  640. package/dist/core/openapi/baseline/record.js.map +1 -0
  641. package/dist/core/openapi/depth.js +122 -0
  642. package/dist/core/openapi/depth.js.map +1 -0
  643. package/dist/core/openapi/digest.js +189 -0
  644. package/dist/core/openapi/digest.js.map +1 -0
  645. package/dist/core/{openapi.js → openapi/doc.js} +44 -106
  646. package/dist/core/openapi/doc.js.map +1 -0
  647. package/dist/core/openapi/merge/components.js +234 -0
  648. package/dist/core/openapi/merge/components.js.map +1 -0
  649. package/dist/core/openapi/merge/error.js +26 -0
  650. package/dist/core/openapi/merge/error.js.map +1 -0
  651. package/dist/core/openapi/merge/markers.js +208 -0
  652. package/dist/core/openapi/merge/markers.js.map +1 -0
  653. package/dist/core/openapi/merge/merge.js +256 -0
  654. package/dist/core/openapi/merge/merge.js.map +1 -0
  655. package/dist/core/openapi/merge/pin.js +128 -0
  656. package/dist/core/openapi/merge/pin.js.map +1 -0
  657. package/dist/core/openspec/decide/capabilities.js +244 -0
  658. package/dist/core/openspec/decide/capabilities.js.map +1 -0
  659. package/dist/core/openspec/decide/dispositions.js +63 -0
  660. package/dist/core/openspec/decide/dispositions.js.map +1 -0
  661. package/dist/core/openspec/decide/renames.js +179 -0
  662. package/dist/core/openspec/decide/renames.js.map +1 -0
  663. package/dist/core/openspec/decide/verdict.js +84 -0
  664. package/dist/core/openspec/decide/verdict.js.map +1 -0
  665. package/dist/core/openspec/inventory.js +221 -0
  666. package/dist/core/openspec/inventory.js.map +1 -0
  667. package/dist/core/openspec/model/mapping.js +76 -0
  668. package/dist/core/openspec/model/mapping.js.map +1 -0
  669. package/dist/core/openspec/model/model.js +65 -0
  670. package/dist/core/openspec/model/model.js.map +1 -0
  671. package/dist/core/openspec/scan/changes.js +235 -0
  672. package/dist/core/openspec/scan/changes.js.map +1 -0
  673. package/dist/core/openspec/scan/config.js +200 -0
  674. package/dist/core/openspec/scan/config.js.map +1 -0
  675. package/dist/core/openspec/scan/shape.js +260 -0
  676. package/dist/core/openspec/scan/shape.js.map +1 -0
  677. package/dist/core/openspec/scan/walk.js +133 -0
  678. package/dist/core/openspec/scan/walk.js.map +1 -0
  679. package/dist/core/openspec/scan/workspace.js +71 -0
  680. package/dist/core/openspec/scan/workspace.js.map +1 -0
  681. package/dist/core/owners/codeowners.js +141 -0
  682. package/dist/core/owners/codeowners.js.map +1 -0
  683. package/dist/core/pack/features.js +120 -0
  684. package/dist/core/pack/features.js.map +1 -0
  685. package/dist/core/pack/joins.js +112 -0
  686. package/dist/core/pack/joins.js.map +1 -0
  687. package/dist/core/pack/living.js +118 -0
  688. package/dist/core/pack/living.js.map +1 -0
  689. package/dist/core/pack/pack.js +76 -0
  690. package/dist/core/pack/pack.js.map +1 -0
  691. package/dist/core/permissions/permissions.js +87 -0
  692. package/dist/core/permissions/permissions.js.map +1 -0
  693. package/dist/core/projection/api.js +84 -0
  694. package/dist/core/projection/api.js.map +1 -0
  695. package/dist/core/projection/arch-slice.js +63 -0
  696. package/dist/core/projection/arch-slice.js.map +1 -0
  697. package/dist/core/projection/events.js +34 -0
  698. package/dist/core/projection/events.js.map +1 -0
  699. package/dist/core/provenance/findings.js +208 -0
  700. package/dist/core/provenance/findings.js.map +1 -0
  701. package/dist/core/provenance/git.js +225 -0
  702. package/dist/core/provenance/git.js.map +1 -0
  703. package/dist/core/provenance/gitq/moves.js +182 -0
  704. package/dist/core/provenance/gitq/moves.js.map +1 -0
  705. package/dist/core/provenance/gitq/vouched-ancestor.js +179 -0
  706. package/dist/core/provenance/gitq/vouched-ancestor.js.map +1 -0
  707. package/dist/core/provenance/sample/scope.js +238 -0
  708. package/dist/core/provenance/sample/scope.js.map +1 -0
  709. package/dist/core/provenance/sample/sections.js +61 -0
  710. package/dist/core/provenance/sample/sections.js.map +1 -0
  711. package/dist/core/provenance/sources.js +263 -0
  712. package/dist/core/provenance/sources.js.map +1 -0
  713. package/dist/core/provenance/stamp.js +232 -0
  714. package/dist/core/provenance/stamp.js.map +1 -0
  715. package/dist/core/provenance/walk.js +157 -0
  716. package/dist/core/provenance/walk.js.map +1 -0
  717. package/dist/core/repo/authored/paths.js +192 -0
  718. package/dist/core/repo/authored/paths.js.map +1 -0
  719. package/dist/core/repo/entries.js +126 -0
  720. package/dist/core/repo/entries.js.map +1 -0
  721. package/dist/core/repo/paths.js +236 -0
  722. package/dist/core/repo/paths.js.map +1 -0
  723. package/dist/core/repo/repo.js +248 -0
  724. package/dist/core/repo/repo.js.map +1 -0
  725. package/dist/core/repo/service-target.js +153 -0
  726. package/dist/core/repo/service-target.js.map +1 -0
  727. package/dist/core/repo/state.js +58 -0
  728. package/dist/core/repo/state.js.map +1 -0
  729. package/dist/core/repo/tree/find.js +52 -0
  730. package/dist/core/repo/tree/find.js.map +1 -0
  731. package/dist/core/repo/tree/fs.js +64 -0
  732. package/dist/core/repo/tree/fs.js.map +1 -0
  733. package/dist/core/repo/tree/marker.js +61 -0
  734. package/dist/core/repo/tree/marker.js.map +1 -0
  735. package/dist/core/repo/tree/views.js +172 -0
  736. package/dist/core/repo/tree/views.js.map +1 -0
  737. package/dist/core/repo/tree/walk.js +234 -0
  738. package/dist/core/repo/tree/walk.js.map +1 -0
  739. package/dist/core/results.js +99 -2
  740. package/dist/core/results.js.map +1 -1
  741. package/dist/core/scaffold/landscape.js +131 -0
  742. package/dist/core/scaffold/landscape.js.map +1 -0
  743. package/dist/core/scaffold/readme.js +84 -0
  744. package/dist/core/scaffold/readme.js.map +1 -0
  745. package/dist/core/staging/commit.js +241 -0
  746. package/dist/core/staging/commit.js.map +1 -0
  747. package/dist/core/staging/interrupted.js +96 -0
  748. package/dist/core/staging/interrupted.js.map +1 -0
  749. package/dist/core/staging/lock.js +206 -0
  750. package/dist/core/staging/lock.js.map +1 -0
  751. package/dist/core/staging/recovery/finding.js +35 -0
  752. package/dist/core/staging/recovery/finding.js.map +1 -0
  753. package/dist/core/staging/recovery/intent.js +98 -0
  754. package/dist/core/staging/recovery/intent.js.map +1 -0
  755. package/dist/core/staging/recovery/recover.js +126 -0
  756. package/dist/core/staging/recovery/recover.js.map +1 -0
  757. package/dist/core/staging/recovery/residue.js +62 -0
  758. package/dist/core/staging/recovery/residue.js.map +1 -0
  759. package/dist/core/staging/snapshot.js +202 -0
  760. package/dist/core/staging/snapshot.js.map +1 -0
  761. package/dist/core/staging/txn/forward.js +171 -0
  762. package/dist/core/staging/txn/forward.js.map +1 -0
  763. package/dist/core/staging/txn/journal.js +139 -0
  764. package/dist/core/staging/txn/journal.js.map +1 -0
  765. package/dist/core/staging/txn/transaction.js +75 -0
  766. package/dist/core/staging/txn/transaction.js.map +1 -0
  767. package/dist/core/staging/writes.js +113 -0
  768. package/dist/core/staging/writes.js.map +1 -0
  769. package/dist/core/status/actions/execution.js +49 -0
  770. package/dist/core/status/actions/execution.js.map +1 -0
  771. package/dist/core/status/contracts.js +102 -0
  772. package/dist/core/status/contracts.js.map +1 -0
  773. package/dist/core/status/feature/artifacts.js +171 -0
  774. package/dist/core/status/feature/artifacts.js.map +1 -0
  775. package/dist/core/status/feature/feature.js +207 -0
  776. package/dist/core/status/feature/feature.js.map +1 -0
  777. package/dist/core/status/feature/next.js +150 -0
  778. package/dist/core/status/feature/next.js.map +1 -0
  779. package/dist/core/status/feature/state.js +21 -0
  780. package/dist/core/status/feature/state.js.map +1 -0
  781. package/dist/core/status/fleet/fleet.js +187 -0
  782. package/dist/core/status/fleet/fleet.js.map +1 -0
  783. package/dist/core/status/fleet/next.js +207 -0
  784. package/dist/core/status/fleet/next.js.map +1 -0
  785. package/dist/core/status/interrupted.js +97 -0
  786. package/dist/core/status/interrupted.js.map +1 -0
  787. package/dist/core/status/report.js +31 -0
  788. package/dist/core/status/report.js.map +1 -0
  789. package/dist/core/status/scan.js +41 -0
  790. package/dist/core/status/scan.js.map +1 -0
  791. package/dist/core/status/verification.js +201 -0
  792. package/dist/core/status/verification.js.map +1 -0
  793. package/dist/core/usecases/capability.js +169 -0
  794. package/dist/core/usecases/capability.js.map +1 -0
  795. package/dist/core/usecases/delta/claims.js +116 -0
  796. package/dist/core/usecases/delta/claims.js.map +1 -0
  797. package/dist/core/usecases/delta/flows.js +103 -0
  798. package/dist/core/usecases/delta/flows.js.map +1 -0
  799. package/dist/core/usecases/delta/overlay.js +235 -0
  800. package/dist/core/usecases/delta/overlay.js.map +1 -0
  801. package/dist/core/usecases/fleet.js +137 -0
  802. package/dist/core/usecases/fleet.js.map +1 -0
  803. package/dist/core/usecases/operations.js +111 -0
  804. package/dist/core/usecases/operations.js.map +1 -0
  805. package/dist/core/usecases/place.js +44 -0
  806. package/dist/core/usecases/place.js.map +1 -0
  807. package/dist/core/usecases/touch.js +101 -0
  808. package/dist/core/usecases/touch.js.map +1 -0
  809. package/dist/core/verify/answers.js +173 -0
  810. package/dist/core/verify/answers.js.map +1 -0
  811. package/dist/core/verify/build.js +150 -0
  812. package/dist/core/verify/build.js.map +1 -0
  813. package/dist/core/verify/checklist.js +201 -0
  814. package/dist/core/verify/checklist.js.map +1 -0
  815. package/dist/core/verify/claims/identity.js +61 -0
  816. package/dist/core/verify/claims/identity.js.map +1 -0
  817. package/dist/core/verify/cross/diff.js +97 -0
  818. package/dist/core/verify/cross/diff.js.map +1 -0
  819. package/dist/core/verify/evidence/contract.js +169 -0
  820. package/dist/core/verify/evidence/contract.js.map +1 -0
  821. package/dist/core/verify/file.js +257 -0
  822. package/dist/core/verify/file.js.map +1 -0
  823. package/dist/core/verify/pins/lint.js +157 -0
  824. package/dist/core/verify/pins/lint.js.map +1 -0
  825. package/dist/core/verify/pins/pin.js +95 -0
  826. package/dist/core/verify/pins/pin.js.map +1 -0
  827. package/dist/core/verify/record.js +142 -0
  828. package/dist/core/verify/record.js.map +1 -0
  829. package/dist/core/verify/store/commit.js +89 -0
  830. package/dist/core/verify/store/commit.js.map +1 -0
  831. package/dist/core/verify/store/render.js +57 -0
  832. package/dist/core/verify/store/render.js.map +1 -0
  833. package/dist/core/vocabulary/health.js +91 -0
  834. package/dist/core/vocabulary/health.js.map +1 -0
  835. package/dist/core/vocabulary/issue.js +55 -0
  836. package/dist/core/vocabulary/issue.js.map +1 -0
  837. package/dist/core/vocabulary/maturity.js +145 -0
  838. package/dist/core/vocabulary/maturity.js.map +1 -0
  839. package/dist/core/{report.js → vocabulary/report.js} +30 -2
  840. package/dist/core/vocabulary/report.js.map +1 -0
  841. package/dist/core/vocabulary/steps.js +266 -0
  842. package/dist/core/vocabulary/steps.js.map +1 -0
  843. package/dist/core/workspace/discover.js +239 -0
  844. package/dist/core/workspace/discover.js.map +1 -0
  845. package/dist/core/workspace/render.js +52 -0
  846. package/dist/core/workspace/render.js.map +1 -0
  847. package/examples/README.md +189 -0
  848. package/examples/docs/architecture/adrs/0001-transactional-outbox.md +33 -0
  849. package/examples/docs/architecture/capabilities.yaml +31 -0
  850. package/examples/docs/architecture/landscape.likec4 +280 -0
  851. package/examples/docs/architecture/obligations.yaml +23 -0
  852. package/examples/docs/architecture/permissions.yaml +50 -0
  853. package/examples/docs/architecture/subsystems.likec4 +11 -0
  854. package/examples/docs/architecture/usecases/order-notification.likec4 +65 -0
  855. package/examples/docs/capabilities/checkout/spec.md +55 -0
  856. package/examples/docs/capabilities/identity/tokens/spec.md +42 -0
  857. package/examples/docs/capabilities/order-notifications/spec.md +43 -0
  858. package/examples/docs/features/FEAT-101-payment-splitting/adrs/0001-dedicated-split-service.md +18 -0
  859. package/examples/docs/features/FEAT-101-payment-splitting/delta.likec4 +94 -0
  860. package/examples/docs/features/FEAT-101-payment-splitting/intent.md +44 -0
  861. package/examples/docs/features/FEAT-101-payment-splitting/specs/checkout-web/spec.md +21 -0
  862. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-service/asyncapi.yaml +129 -0
  863. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-service/spec.md +36 -0
  864. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/arch.spec.md +40 -0
  865. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/openapi.yaml +116 -0
  866. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/spec.md +55 -0
  867. package/examples/docs/features/FEAT-112-retire-order-v1/intent.md +35 -0
  868. package/examples/docs/features/FEAT-112-retire-order-v1/specs/order-service/openapi.yaml +28 -0
  869. package/examples/docs/features/FEAT-112-retire-order-v1/specs/order-service/spec.md +17 -0
  870. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/architecture/landscape.likec4 +253 -0
  871. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/services/order-service/spec.md +121 -0
  872. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/services/payment-service/openapi.yaml +111 -0
  873. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/services/payment-service/spec.md +58 -0
  874. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/manifest.json +32 -0
  875. package/examples/docs/features/archive/FEAT-088-refunds/adrs/0001-refunds-stay-in-payment-service.md +26 -0
  876. package/examples/docs/features/archive/FEAT-088-refunds/delta.likec4 +28 -0
  877. package/examples/docs/features/archive/FEAT-088-refunds/intent.md +26 -0
  878. package/examples/docs/features/archive/FEAT-088-refunds/specs/order-service/spec.md +37 -0
  879. package/examples/docs/features/archive/FEAT-088-refunds/specs/payment-service/openapi.yaml +70 -0
  880. package/examples/docs/features/archive/FEAT-088-refunds/specs/payment-service/spec.md +23 -0
  881. package/examples/docs/features/archive/FEAT-088-refunds/verification.yaml +76 -0
  882. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/architecture/landscape.likec4 +275 -0
  883. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/payment-service/asyncapi.yaml +96 -0
  884. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/payment-service/spec.md +82 -0
  885. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/platform/notification-service/asyncapi.yaml +164 -0
  886. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/platform/notification-service/spec.md +91 -0
  887. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/manifest.json +46 -0
  888. package/examples/docs/features/archive/FEAT-120-refund-notification/delta.likec4 +36 -0
  889. package/examples/docs/features/archive/FEAT-120-refund-notification/intent.md +22 -0
  890. package/examples/docs/features/archive/FEAT-120-refund-notification/scenario-report.json +10 -0
  891. package/examples/docs/features/archive/FEAT-120-refund-notification/specs/notification-service/asyncapi.yaml +208 -0
  892. package/examples/docs/features/archive/FEAT-120-refund-notification/specs/notification-service/spec.md +24 -0
  893. package/examples/docs/features/archive/FEAT-120-refund-notification/specs/payment-service/asyncapi.yaml +137 -0
  894. package/examples/docs/features/archive/FEAT-120-refund-notification/specs/payment-service/spec.md +31 -0
  895. package/examples/docs/features/archive/FEAT-120-refund-notification/verification.yaml +84 -0
  896. package/examples/docs/glossary/order.md +15 -0
  897. package/examples/docs/glossary/payments/authorization.md +14 -0
  898. package/examples/docs/likec4.config.json +9 -0
  899. package/examples/docs/loam.json +3 -0
  900. package/examples/docs/services/checkout-web/model.likec4 +109 -0
  901. package/examples/docs/services/checkout-web/spec.md +91 -0
  902. package/examples/docs/services/checkout-web/ui/pages/checkout.page.yaml +40 -0
  903. package/examples/docs/services/checkout-web/ui/pages/order-status.page.yaml +24 -0
  904. package/examples/docs/services/checkout-web/ui/pages/split-payment.page.yaml +26 -0
  905. package/examples/docs/services/order-service/adrs/0001-orchestrated-order-lifecycle.md +52 -0
  906. package/examples/docs/services/order-service/arch.spec.md +127 -0
  907. package/examples/docs/services/order-service/asyncapi.yaml +108 -0
  908. package/examples/docs/services/order-service/health.yaml +57 -0
  909. package/examples/docs/services/order-service/model.likec4 +138 -0
  910. package/examples/docs/services/order-service/openapi.yaml +257 -0
  911. package/examples/docs/services/order-service/runbook.md +62 -0
  912. package/examples/docs/services/order-service/spec.md +134 -0
  913. package/examples/docs/services/payment-service/adrs/0001-payments-outbox.md +18 -0
  914. package/examples/docs/services/payment-service/adrs/0002-idempotency-keys-on-authorization.md +27 -0
  915. package/examples/docs/services/payment-service/arch.spec.md +73 -0
  916. package/examples/docs/services/payment-service/asyncapi.yaml +130 -0
  917. package/examples/docs/services/payment-service/health.yaml +39 -0
  918. package/examples/docs/services/payment-service/model.likec4 +67 -0
  919. package/examples/docs/services/payment-service/openapi.yaml +151 -0
  920. package/examples/docs/services/payment-service/runbook.md +37 -0
  921. package/examples/docs/services/payment-service/spec.md +88 -0
  922. package/examples/docs/services/platform/identity-service/adrs/0001-token-introspection-over-local-validation.md +60 -0
  923. package/examples/docs/services/platform/identity-service/arch.spec.md +117 -0
  924. package/examples/docs/services/platform/identity-service/health.yaml +70 -0
  925. package/examples/docs/services/platform/identity-service/model.likec4 +83 -0
  926. package/examples/docs/services/platform/identity-service/openapi.yaml +197 -0
  927. package/examples/docs/services/platform/identity-service/runbook.md +95 -0
  928. package/examples/docs/services/platform/identity-service/spec.md +119 -0
  929. package/examples/docs/services/platform/notification-service/asyncapi.yaml +199 -0
  930. package/examples/docs/services/platform/notification-service/health.yaml +35 -0
  931. package/examples/docs/services/platform/notification-service/model.likec4 +118 -0
  932. package/examples/docs/services/platform/notification-service/runbook.md +48 -0
  933. package/examples/docs/services/platform/notification-service/spec.md +112 -0
  934. package/examples/docs/services/platform/subsystem.yaml +2 -0
  935. package/examples/fleet.yaml +57 -0
  936. package/package.json +19 -6
  937. package/dist/commands/adopt.js +0 -240
  938. package/dist/commands/adopt.js.map +0 -1
  939. package/dist/commands/archive.js +0 -1313
  940. package/dist/commands/archive.js.map +0 -1
  941. package/dist/commands/delta.js +0 -388
  942. package/dist/commands/delta.js.map +0 -1
  943. package/dist/commands/docs-repo-gate.js.map +0 -1
  944. package/dist/commands/format.js +0 -17
  945. package/dist/commands/format.js.map +0 -1
  946. package/dist/commands/gherkin.js +0 -309
  947. package/dist/commands/gherkin.js.map +0 -1
  948. package/dist/commands/init.js.map +0 -1
  949. package/dist/commands/list.js +0 -295
  950. package/dist/commands/list.js.map +0 -1
  951. package/dist/commands/migrate-openspec.js +0 -950
  952. package/dist/commands/migrate-openspec.js.map +0 -1
  953. package/dist/commands/new.js +0 -413
  954. package/dist/commands/new.js.map +0 -1
  955. package/dist/commands/rebase.js +0 -356
  956. package/dist/commands/rebase.js.map +0 -1
  957. package/dist/commands/show.js.map +0 -1
  958. package/dist/commands/status.js +0 -262
  959. package/dist/commands/status.js.map +0 -1
  960. package/dist/commands/unarchive.js.map +0 -1
  961. package/dist/commands/validate.js +0 -1773
  962. package/dist/commands/validate.js.map +0 -1
  963. package/dist/commands/verify.js +0 -775
  964. package/dist/commands/verify.js.map +0 -1
  965. package/dist/commands/vouch.js +0 -421
  966. package/dist/commands/vouch.js.map +0 -1
  967. package/dist/core/agent.js +0 -2173
  968. package/dist/core/agent.js.map +0 -1
  969. package/dist/core/agents-stamp.js.map +0 -1
  970. package/dist/core/arch.js +0 -130
  971. package/dist/core/arch.js.map +0 -1
  972. package/dist/core/asyncapi.js.map +0 -1
  973. package/dist/core/brief.js +0 -755
  974. package/dist/core/brief.js.map +0 -1
  975. package/dist/core/coherence.js +0 -577
  976. package/dist/core/coherence.js.map +0 -1
  977. package/dist/core/concurrency.js.map +0 -1
  978. package/dist/core/config.js.map +0 -1
  979. package/dist/core/delta.js +0 -476
  980. package/dist/core/delta.js.map +0 -1
  981. package/dist/core/dependencies.js +0 -356
  982. package/dist/core/dependencies.js.map +0 -1
  983. package/dist/core/doctor.js +0 -596
  984. package/dist/core/doctor.js.map +0 -1
  985. package/dist/core/document-bytes.js.map +0 -1
  986. package/dist/core/explore.js.map +0 -1
  987. package/dist/core/frontmatter.js.map +0 -1
  988. package/dist/core/gherkin.js +0 -463
  989. package/dist/core/gherkin.js.map +0 -1
  990. package/dist/core/health.js +0 -67
  991. package/dist/core/health.js.map +0 -1
  992. package/dist/core/ids.js +0 -122
  993. package/dist/core/ids.js.map +0 -1
  994. package/dist/core/issue.js +0 -9
  995. package/dist/core/issue.js.map +0 -1
  996. package/dist/core/json.js +0 -74
  997. package/dist/core/json.js.map +0 -1
  998. package/dist/core/likec4.js +0 -489
  999. package/dist/core/likec4.js.map +0 -1
  1000. package/dist/core/maturity.js +0 -66
  1001. package/dist/core/maturity.js.map +0 -1
  1002. package/dist/core/openapi-merge.js +0 -552
  1003. package/dist/core/openapi-merge.js.map +0 -1
  1004. package/dist/core/openapi.js.map +0 -1
  1005. package/dist/core/openspec-inventory.js +0 -1440
  1006. package/dist/core/openspec-inventory.js.map +0 -1
  1007. package/dist/core/path-safety.js.map +0 -1
  1008. package/dist/core/provenance.js +0 -787
  1009. package/dist/core/provenance.js.map +0 -1
  1010. package/dist/core/records.js.map +0 -1
  1011. package/dist/core/repo.js +0 -438
  1012. package/dist/core/repo.js.map +0 -1
  1013. package/dist/core/report.js.map +0 -1
  1014. package/dist/core/spec.js +0 -505
  1015. package/dist/core/spec.js.map +0 -1
  1016. package/dist/core/staging.js +0 -890
  1017. package/dist/core/staging.js.map +0 -1
  1018. package/dist/core/status.js +0 -1132
  1019. package/dist/core/status.js.map +0 -1
  1020. package/dist/core/steps.js +0 -72
  1021. package/dist/core/steps.js.map +0 -1
  1022. package/dist/core/verify.js +0 -807
  1023. package/dist/core/verify.js.map +0 -1
  1024. package/dist/core/version.js.map +0 -1
  1025. /package/dist/core/{concurrency.js → kernel/concurrency.js} +0 -0
  1026. /package/dist/core/{records.js → kernel/records.js} +0 -0
@@ -1,64 +1,18 @@
1
1
  import { existsSync, statSync } from "node:fs";
2
2
  import { resolve } from "node:path";
3
- import { CONFIG_FILENAME, findConfigPath, loadConfig, localConfigPath, saveConfig, } from "../core/config.js";
4
- import { emitJson, fail } from "../core/json.js";
5
- import { plannedDocsFiles, scaffoldDocs } from "../core/docs.js";
6
- import { agentsPath, docsRepoState, listServices } from "../core/repo.js";
7
- import { InvalidIdError, assertServiceId } from "../core/ids.js";
8
- import { AGENT_TOOLS, detectAgentTools, plannedCommandFiles, scaffoldAgentCommands, } from "../core/agent.js";
9
- /**
10
- * Resolve --tools to registry ids, or null after reporting the refusal. The
11
- * default (the cwd scan) lives at the call site, not in commander, so an
12
- * explicit `--tools` is distinguishable from none — which is what lets both the
13
- * autodetection fallback and the `--no-*` contradiction be decided instead of
14
- * silently arbitrated.
15
- */
16
- function resolveTools(raw, json) {
17
- const supported = Object.keys(AGENT_TOOLS);
18
- if (raw === "all")
19
- return supported;
20
- const ids = [...new Set(raw.split(",").map((t) => t.trim()).filter((t) => t !== ""))];
21
- const unknown = ids.filter((t) => !(t in AGENT_TOOLS));
22
- if (ids.length === 0 || unknown.length > 0) {
23
- fail(json, "invalid-option", (ids.length === 0
24
- ? "--tools names no tool."
25
- : `--tools does not recognize: ${unknown.join(", ")}.`) +
26
- ` Supported: ${supported.join(", ")} — or "all".`);
27
- return null;
28
- }
29
- return ids;
30
- }
31
- /**
32
- * `--docs` exactly as the caller wrote it, with separators normalised.
33
- *
34
- * Stored verbatim on purpose. `init` used to resolve it and write the absolute
35
- * result, which meant a committed loam.json named a directory that existed on
36
- * one laptop: every teammate who cloned the service repo got a docsDir under
37
- * someone else's home directory, and `loam list` reported an empty fleet
38
- * instead of saying so. `loadConfig` resolves relative paths against the config
39
- * file's own directory, so `../docs` keeps meaning "next to this repo" wherever
40
- * the pair is checked out. An absolute `--docs` is still stored absolute — that
41
- * is the caller's explicit choice, and `loam doctor` warns about it.
42
- *
43
- * Backslashes become forward slashes so a config written on Windows resolves on
44
- * POSIX; a trailing separator is dropped so the stored spelling is stable.
45
- */
46
- function storedDocsDir(raw) {
47
- const slashed = raw.split("\\").join("/");
48
- if (slashed.length <= 1)
49
- return slashed;
50
- const trimmed = slashed.replace(/\/+$/, "");
51
- return trimmed === "" ? "/" : trimmed;
52
- }
53
- /**
54
- * Does this directory already hold a docs repo? `services/` plus `AGENTS.md` —
55
- * the two things every docs repo has and no service repo does. The pair is the
56
- * whole point: a single marker would make `init --docs ../srv` (a typo for
57
- * `../docs`) look like a join and adopt the service repo as the fleet.
58
- */
59
- function isDocsRepo(dir) {
60
- return docsRepoState(dir).kind === "ok" && existsSync(agentsPath(dir));
61
- }
3
+ import { CONFIG_FILENAME, findConfigPath, loadConfig, localConfigPath, saveConfig, } from "../../core/envelope/config.js";
4
+ import { docsDirOf } from "../../core/kernel/ids/dirs.js";
5
+ import { emitJson, fail } from "../../core/envelope/json.js";
6
+ import { plannedDocsFiles, scaffoldDocs } from "../../core/docs.js";
7
+ import { docsRepoState } from "../../core/repo/state.js";
8
+ import { listServices } from "../../core/repo/repo.js";
9
+ import { InvalidIdError, assertServiceId } from "../../core/kernel/ids/service.js";
10
+ import { detectAgentTools, plannedCommandFiles, syncAgentCommands, updatedAgentFileManifest, } from "../../core/agent/scaffold.js";
11
+ import { AGENT_TOOLS } from "../../core/agent/tools/registry.js";
12
+ import { initExample } from "./example.js";
13
+ import { firstHour } from "./first-hour.js";
14
+ import { MCP_CONFIG_FILENAME, mcpConfigPath, mcpServerSnippet, writeMcpConfig } from "./mcp.js";
15
+ import { isDocsRepo, resolveAgentProfile, resolveTools, storedDocsDir } from "./options.js";
62
16
  export function registerInit(program) {
63
17
  program
64
18
  .command("init")
@@ -69,12 +23,42 @@ export function registerInit(program) {
69
23
  .option("--force", `write ${CONFIG_FILENAME} here even though one governs a parent directory`)
70
24
  .option("--tools <ids>", "agent tools to generate for, overriding the scan of this directory: " +
71
25
  `comma-separated (${Object.keys(AGENT_TOOLS).join(", ")}) or "all"`)
26
+ .option("--agent-profile <profile>", "workflow set: full | service | docs")
27
+ .option("--example <dir>", "copy the packaged example fleet to <dir> and stop: no repository is bound, nothing is scaffolded")
72
28
  .option("--no-commands", "skip the slash commands for this repo entirely")
73
29
  .option("--no-skills", "skip the agent skills for this repo entirely")
30
+ .option("--mcp", `also write ${MCP_CONFIG_FILENAME} here, so an MCP host launches \`loam mcp\` for this repo`)
31
+ .option("--mcp-author", `write ${MCP_CONFIG_FILENAME} with the opt-in authoring profile`)
74
32
  .option("--json", "emit the machine contract instead of the human view")
75
33
  .action(async (opts, command) => {
76
34
  const json = opts.json === true;
77
35
  const cwd = process.cwd();
36
+ // FIRST, before every guard below including the governing-config one:
37
+ // `--example` writes a fresh tree, it does not join a system. A
38
+ // loam.json in an ancestor governs the directories a repository is bound
39
+ // INTO, and this flag binds nothing — refusing here would be the tool
40
+ // declining to show itself working because of a config that has no
41
+ // bearing on the copy. Before the --service id check too, so a run
42
+ // combining the two answers the contradiction rather than grading an id
43
+ // it is about to refuse to use.
44
+ if (opts.example !== undefined) {
45
+ await initExample({
46
+ dir: opts.example,
47
+ conflicts: [
48
+ // `--docs` carries a default, so only its SOURCE can say whether
49
+ // anybody typed it — the same question the docsDir precedence
50
+ // below asks, for the same reason.
51
+ ...(command.getOptionValueSource("docs") !== "default" ? ["--docs"] : []),
52
+ ...(opts.service !== undefined ? ["--service"] : []),
53
+ ...(opts.create === true ? ["--create"] : []),
54
+ ...(opts.tools !== undefined ? ["--tools"] : []),
55
+ ...(opts.agentProfile !== undefined ? ["--agent-profile"] : []),
56
+ ...(opts.mcpAuthor === true ? ["--mcp-author"] : []),
57
+ ],
58
+ json,
59
+ });
60
+ return;
61
+ }
78
62
  // The id becomes services/<id>/ in the shared repo, so it is validated
79
63
  // before anything is written — by the same rule adopt, vouch and gherkin
80
64
  // use, never by a guard invented here.
@@ -103,7 +87,12 @@ export function registerInit(program) {
103
87
  // Only THIS directory's config is spread forward. Under --force there is
104
88
  // a config in an ancestor too, and inheriting its `service` would bind
105
89
  // this repo to a service somebody else's repo declared.
106
- const existing = existsSync(localConfigPath(cwd)) ? await loadConfig(cwd) : null;
90
+ // `kind: "invalid"` reads as null on purpose: init REPAIRS a corrupt
91
+ // loam.json by rewriting it, so a config nobody can read is treated
92
+ // exactly like no config at all. The old stderr line about it was
93
+ // core's side effect, promised nowhere.
94
+ const load = existsSync(localConfigPath(cwd)) ? await loadConfig(cwd) : null;
95
+ const existing = load?.kind === "loaded" ? load.config : null;
107
96
  // A re-run must not move a committed pointer. `--docs` has a default
108
97
  // (`.loam-docs`), so an init invoked for any OTHER reason — `--service`,
109
98
  // a new `--tools`, the fix `doctor.agent-files-missing` prints — used to
@@ -118,7 +107,11 @@ export function registerInit(program) {
118
107
  const docsTyped = command.getOptionValueSource("docs") !== "default";
119
108
  const docsSource = docsTyped ? "flag" : committedDocs === undefined ? "default" : "config";
120
109
  const docsOption = !docsTyped && committedDocs !== undefined ? committedDocs : opts.docs;
121
- const docsDir = resolve(cwd, docsOption);
110
+ // Branded at the resolution, because the guards below are what validate
111
+ // it — the brand's provenance is "an explicit --docs a command
112
+ // validated", and this command is the one that does. The STORED spelling
113
+ // (`storedDocsDir` below) deliberately stays a plain string.
114
+ const docsDir = docsDirOf(resolve(cwd, docsOption));
122
115
  // The one predictable failure: --docs naming a file. Refused here so the
123
116
  // caller gets a clean envelope/message instead of mkdir's ENOTDIR throw.
124
117
  if (existsSync(docsDir) && !statSync(docsDir).isDirectory()) {
@@ -165,33 +158,72 @@ export function registerInit(program) {
165
158
  const tools = opts.tools === undefined ? scanned : resolveTools(opts.tools, json);
166
159
  if (tools === null)
167
160
  return;
168
- // `skipped` is the other half of the never-overwrite contract: the
169
- // scaffolds return only what they created, so what they left alone is
170
- // probed here, before they run — in the order they would create it, so
171
- // created + skipped is the same list on every repo. Both halves come from
172
- // the scaffolds' own planned-file lists, so the probe cannot drift from
173
- // what is actually written.
174
- const agentFiles = delivery.length > 0 ? plannedCommandFiles(cwd, tools, delivery) : [];
175
- const candidates = [...plannedDocsFiles(docsDir), ...agentFiles.map((f) => f.path)];
176
- const skipped = candidates.filter((p) => existsSync(p));
161
+ const profile = resolveAgentProfile(opts.agentProfile, existing?.agentProfile, json);
162
+ if (profile === null)
163
+ return;
164
+ // Probe the pre-existing paths in planned order. Managed files refreshed
165
+ // below are removed from `skipped`; custom and already-current files stay.
166
+ const plannedAgentFiles = delivery.length > 0 ? plannedCommandFiles(cwd, tools, delivery, profile) : [];
167
+ // `.mcp.json` joins the same list rather than being reported on the side:
168
+ // it is a scaffolded path like any other, so it must appear in `created`
169
+ // or in `skipped` by the one rule that governs both. Last, because it is
170
+ // written last.
171
+ const candidates = [
172
+ ...plannedDocsFiles(docsDir),
173
+ ...plannedAgentFiles.map((f) => f.path),
174
+ ...(opts.mcp === true || opts.mcpAuthor === true ? [mcpConfigPath(cwd)] : []),
175
+ ];
176
+ let skipped = candidates.filter((p) => existsSync(p));
177
177
  // Joining touches the docs repo not at all: it is somebody's committed
178
178
  // repository, and "point at it" must never mean "write to it".
179
179
  const created = joining && opts.create !== true ? [] : (await scaffoldDocs(docsDir)).created;
180
180
  const generatedFor = delivery.length > 0 ? tools : [];
181
+ let refreshed = [];
182
+ let managedFiles = {};
181
183
  if (delivery.length > 0) {
182
- created.push(...(await scaffoldAgentCommands(cwd, tools, delivery)));
184
+ const synced = await syncAgentCommands({
185
+ cwd,
186
+ toolIds: tools,
187
+ delivery,
188
+ profile,
189
+ known: existing?.agentFiles,
190
+ });
191
+ created.push(...synced.created);
192
+ refreshed = synced.refreshed;
193
+ managedFiles = synced.managed;
194
+ skipped = skipped.filter((path) => !refreshed.includes(path));
195
+ }
196
+ // The third delivery, and the only machine-readable one. It refuses out
197
+ // loud rather than being written best-effort: a `.mcp.json` half-landed
198
+ // is a host that starts a broken server, and the caller asked for it by
199
+ // name. Before saveConfig, so a run that cannot write this file has not
200
+ // yet moved the committed pointer either.
201
+ let mcpWritten = false;
202
+ if (opts.mcp === true || opts.mcpAuthor === true) {
203
+ const write = await writeMcpConfig(cwd, opts.mcpAuthor === true);
204
+ if (write.kind === "failed") {
205
+ fail(json, write.code, write.message);
206
+ return;
207
+ }
208
+ mcpWritten = write.kind === "created";
209
+ if (mcpWritten)
210
+ created.push(mcpConfigPath(cwd));
183
211
  }
184
212
  const stored = storedDocsDir(docsOption);
185
213
  // Union, not replacement: this run's files join the ones earlier runs left
186
214
  // on disk, and `agentTools` is a record of what the repo HOLDS. A run that
187
215
  // generated nothing adds nothing and erases nothing.
188
216
  const recordedTools = [...new Set([...(existing?.agentTools ?? []), ...generatedFor])];
217
+ const agentFileManifest = updatedAgentFileManifest(cwd, plannedAgentFiles, existing?.agentFiles, managedFiles);
189
218
  const config = {
190
219
  ...existing,
191
220
  docsDir: stored,
192
221
  ...(opts.service ? { service: opts.service } : {}),
193
222
  ...(recordedTools.length > 0 ? { agentTools: recordedTools } : {}),
223
+ agentProfile: profile,
194
224
  };
225
+ if (Object.keys(agentFileManifest).length > 0)
226
+ config.agentFiles = agentFileManifest;
195
227
  const configFile = await saveConfig(config, cwd);
196
228
  const serviceCount = (await listServices(docsDir)).length;
197
229
  if (json) {
@@ -204,6 +236,7 @@ export function registerInit(program) {
204
236
  // changing: an agent comparing the two learns whether its selection
205
237
  // matches the repo.
206
238
  emitJson({
239
+ command: "init",
207
240
  docsDir,
208
241
  docsDirStored: stored,
209
242
  // Where the pointer came from: `flag` (a --docs somebody typed),
@@ -213,8 +246,10 @@ export function registerInit(program) {
213
246
  docsRepo: joining ? "existing" : "created",
214
247
  services: serviceCount,
215
248
  created,
249
+ refreshed,
216
250
  skipped,
217
251
  tools: generatedFor,
252
+ agentProfile: profile,
218
253
  detected,
219
254
  });
220
255
  return;
@@ -240,11 +275,51 @@ export function registerInit(program) {
240
275
  console.log(` commands: ${tools.join(", ")}`);
241
276
  if (opts.skills)
242
277
  console.log(` skills: ${tools.join(", ")}`);
278
+ console.log(` profile: ${profile}`);
243
279
  if (created.length > 0) {
244
280
  console.log(" scaffolded:");
245
281
  for (const c of created)
246
282
  console.log(` + ${c}`);
247
283
  }
284
+ if (refreshed.length > 0) {
285
+ console.log(" refreshed (unchanged since loam last wrote them):");
286
+ for (const path of refreshed)
287
+ console.log(` ↻ ${path}`);
288
+ }
289
+ // The one skipped path that earns more than its line in `skipped`: loam
290
+ // will not merge into a `.mcp.json` a human owns, and the caller asked
291
+ // for this delivery by name — so they are handed the exact key to paste
292
+ // into their own `mcpServers` object. Nothing was read out of their file
293
+ // to produce it; the snippet is the same bytes a fresh write would have
294
+ // used, which is also why it names the launch form this install shape
295
+ // actually needs.
296
+ if ((opts.mcp === true || opts.mcpAuthor === true) && !mcpWritten) {
297
+ console.log(` mcp: ${MCP_CONFIG_FILENAME} is already here — left exactly as it is.`);
298
+ console.log(` paste this into its "mcpServers" object:`);
299
+ for (const line of mcpServerSnippet(cwd, opts.mcpAuthor === true))
300
+ console.log(` ${line}`);
301
+ }
302
+ // Printed ONLY for the single-repo trial composition: one run that both
303
+ // created the docs repo and left a service bound (the binding may
304
+ // predate the run — the config spread above carries an existing
305
+ // loam.json's `service` forward). `loam status` is NOT mute here — its
306
+ // first-hour ladder (core/status/fleet/next.ts) already answers
307
+ // `next.adopt-bound` in exactly this state — but status has to be run
308
+ // to say so, and no status rung ever names `loam vouch`, the one step
309
+ // of this loop that is a person's; init's output is already on screen,
310
+ // so it prints the whole hour once. A join stays silent on purpose: a
311
+ // joined fleet has other repositories already through this loop, and
312
+ // `loam status` in its docs repo is the working guide there. The --json
313
+ // path returned above, so the envelope is byte-identical to before
314
+ // this block existed.
315
+ if (!joining && config.service !== undefined) {
316
+ const steps = firstHour(config.service);
317
+ const width = Math.max(...steps.map(([command]) => command.length));
318
+ console.log(" next — the first hour:");
319
+ for (const [command, why] of steps) {
320
+ console.log(` ${command.padEnd(width)} # ${why}`);
321
+ }
322
+ }
248
323
  });
249
324
  }
250
325
  //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/commands/init/init.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Command } from \"commander\";\nimport { existsSync, statSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport {\n CONFIG_FILENAME,\n findConfigPath,\n loadConfig,\n localConfigPath,\n saveConfig,\n type StoredConfig,\n} from \"../../core/envelope/config.js\";\nimport { docsDirOf } from \"../../core/kernel/ids/dirs.js\";\nimport { emitJson, fail } from \"../../core/envelope/json.js\";\nimport { plannedDocsFiles, scaffoldDocs } from \"../../core/docs.js\";\nimport { docsRepoState } from \"../../core/repo/state.js\";\nimport { listServices } from \"../../core/repo/repo.js\";\nimport { InvalidIdError, assertServiceId } from \"../../core/kernel/ids/service.js\";\nimport {\n detectAgentTools,\n plannedCommandFiles,\n syncAgentCommands,\n updatedAgentFileManifest,\n type Delivery,\n} from \"../../core/agent/scaffold.js\";\nimport { AGENT_TOOLS } from \"../../core/agent/tools/registry.js\";\nimport { initExample } from \"./example.js\";\nimport { firstHour } from \"./first-hour.js\";\nimport { MCP_CONFIG_FILENAME, mcpConfigPath, mcpServerSnippet, writeMcpConfig } from \"./mcp.js\";\nimport { isDocsRepo, resolveAgentProfile, resolveTools, storedDocsDir } from \"./options.js\";\n\ninterface InitOptions {\n docs: string;\n service?: string;\n /** --create: make a new docs repo at --docs instead of joining an existing one. */\n create?: boolean;\n /** --force: write loam.json here even though one already governs a parent directory. */\n force?: boolean;\n /** commander's --no-commands: true unless the flag is passed. */\n commands: boolean;\n /** commander's --no-skills: true unless the flag is passed. */\n skills: boolean;\n /**\n * --mcp: also write the repo-root `.mcp.json`. Opt-in and default off — a\n * third delivery, independent of the two `--no-*` flags rather than a\n * variation on them, so it neither contradicts them nor is suppressed by\n * either. See ./mcp.ts for why the file is opt-in at all.\n */\n mcp?: boolean;\n mcpAuthor?: boolean;\n /** --tools: comma-separated AGENT_TOOLS ids, or \"all\". Absent = autodetect. */\n tools?: string;\n /** Workflow subset to scaffold. */\n agentProfile?: string;\n /** --example: copy the packaged example fleet to this directory and do nothing else. */\n example?: string;\n json?: boolean;\n}\n\nexport function registerInit(program: Command): void {\n program\n .command(\"init\")\n .description(\"Initialize loam: create/point at the shared docs repo and write local config\")\n .option(\"--docs <dir>\", \"path to the shared docs repo (the source of truth)\", \".loam-docs\")\n .option(\"--service <id>\", \"canonical id of the service in this repo\")\n .option(\"--create\", \"create a new docs repo at --docs instead of joining an existing one\")\n .option(\"--force\", `write ${CONFIG_FILENAME} here even though one governs a parent directory`)\n .option(\n \"--tools <ids>\",\n \"agent tools to generate for, overriding the scan of this directory: \" +\n `comma-separated (${Object.keys(AGENT_TOOLS).join(\", \")}) or \"all\"`,\n )\n .option(\"--agent-profile <profile>\", \"workflow set: full | service | docs\")\n .option(\n \"--example <dir>\",\n \"copy the packaged example fleet to <dir> and stop: no repository is bound, nothing is scaffolded\",\n )\n .option(\"--no-commands\", \"skip the slash commands for this repo entirely\")\n .option(\"--no-skills\", \"skip the agent skills for this repo entirely\")\n .option(\n \"--mcp\",\n `also write ${MCP_CONFIG_FILENAME} here, so an MCP host launches \\`loam mcp\\` for this repo`,\n )\n .option(\"--mcp-author\", `write ${MCP_CONFIG_FILENAME} with the opt-in authoring profile`)\n .option(\"--json\", \"emit the machine contract instead of the human view\")\n .action(async (opts: InitOptions, command: Command) => {\n const json = opts.json === true;\n const cwd = process.cwd();\n\n // FIRST, before every guard below including the governing-config one:\n // `--example` writes a fresh tree, it does not join a system. A\n // loam.json in an ancestor governs the directories a repository is bound\n // INTO, and this flag binds nothing — refusing here would be the tool\n // declining to show itself working because of a config that has no\n // bearing on the copy. Before the --service id check too, so a run\n // combining the two answers the contradiction rather than grading an id\n // it is about to refuse to use.\n if (opts.example !== undefined) {\n await initExample({\n dir: opts.example,\n conflicts: [\n // `--docs` carries a default, so only its SOURCE can say whether\n // anybody typed it — the same question the docsDir precedence\n // below asks, for the same reason.\n ...(command.getOptionValueSource(\"docs\") !== \"default\" ? [\"--docs\"] : []),\n ...(opts.service !== undefined ? [\"--service\"] : []),\n ...(opts.create === true ? [\"--create\"] : []),\n ...(opts.tools !== undefined ? [\"--tools\"] : []),\n ...(opts.agentProfile !== undefined ? [\"--agent-profile\"] : []),\n ...(opts.mcpAuthor === true ? [\"--mcp-author\"] : []),\n ],\n json,\n });\n return;\n }\n\n // The id becomes services/<id>/ in the shared repo, so it is validated\n // before anything is written — by the same rule adopt, vouch and gherkin\n // use, never by a guard invented here.\n if (opts.service !== undefined) {\n try {\n assertServiceId(opts.service);\n } catch (err) {\n if (!(err instanceof InvalidIdError)) throw err;\n fail(json, \"invalid-option\", err.message);\n return;\n }\n }\n\n // A loam.json in an ancestor already governs this directory: every command\n // run from here resolves to it. Writing a second one below it would shadow\n // the first for this subtree only — the kind of split-brain nobody\n // discovers until two commands disagree about which docs repo is the fleet.\n const governing = findConfigPath(cwd);\n if (governing !== null && governing !== localConfigPath(cwd) && opts.force !== true) {\n fail(\n json,\n \"already-exists\",\n `${governing} already governs this directory. ` +\n `Run loam from ${resolve(governing, \"..\")}, or pass --force to give this ` +\n `subdirectory its own ${CONFIG_FILENAME}.`,\n );\n return;\n }\n\n // Only THIS directory's config is spread forward. Under --force there is\n // a config in an ancestor too, and inheriting its `service` would bind\n // this repo to a service somebody else's repo declared.\n // `kind: \"invalid\"` reads as null on purpose: init REPAIRS a corrupt\n // loam.json by rewriting it, so a config nobody can read is treated\n // exactly like no config at all. The old stderr line about it was\n // core's side effect, promised nowhere.\n const load = existsSync(localConfigPath(cwd)) ? await loadConfig(cwd) : null;\n const existing = load?.kind === \"loaded\" ? load.config : null;\n\n // A re-run must not move a committed pointer. `--docs` has a default\n // (`.loam-docs`), so an init invoked for any OTHER reason — `--service`,\n // a new `--tools`, the fix `doctor.agent-files-missing` prints — used to\n // arrive here carrying a docsDir nobody typed: the default then named no\n // docs repo, the refusal steered the caller to `--create`, and `--create`\n // rewrote `docsDir` in the committed loam.json to a freshly scaffolded\n // empty one. `validate --all` went green over an empty fleet, which is\n // the exact outcome `--create` exists to prevent. So the flag wins only\n // when it was actually passed; otherwise the file this repo already\n // committed does.\n const committedDocs = existing?.docsDirAsWritten;\n const docsTyped = command.getOptionValueSource(\"docs\") !== \"default\";\n const docsSource: \"flag\" | \"config\" | \"default\" =\n docsTyped ? \"flag\" : committedDocs === undefined ? \"default\" : \"config\";\n const docsOption = !docsTyped && committedDocs !== undefined ? committedDocs : opts.docs;\n // Branded at the resolution, because the guards below are what validate\n // it — the brand's provenance is \"an explicit --docs a command\n // validated\", and this command is the one that does. The STORED spelling\n // (`storedDocsDir` below) deliberately stays a plain string.\n const docsDir = docsDirOf(resolve(cwd, docsOption));\n\n // The one predictable failure: --docs naming a file. Refused here so the\n // caller gets a clean envelope/message instead of mkdir's ENOTDIR throw.\n if (existsSync(docsDir) && !statSync(docsDir).isDirectory()) {\n fail(json, \"invalid-option\", `--docs points at a file, not a directory: ${docsDir}`);\n return;\n }\n\n // Joining an existing docs repo and creating a new one are different\n // intentions, and `init` used to perform the second one whenever the first\n // was misspelled: `--docs ../dcos` scaffolded a second, empty docs repo\n // beside the real one, and the fleet quietly split in two. Creation is now\n // something the caller asks for.\n const joining = isDocsRepo(docsDir);\n if (!joining && opts.create !== true) {\n fail(\n json,\n \"invalid-option\",\n docsRepoState(docsDir).kind === \"missing\"\n ? `--docs points at a directory that does not exist: ${docsDir}. ` +\n \"If that is a typo, fix it; to create a new docs repo there, pass --create.\"\n : `--docs points at ${docsDir}, which is not a docs repo ` +\n \"(a docs repo has services/ and AGENTS.md). \" +\n \"Point --docs at the shared docs repo, or pass --create to make a new one here.\",\n );\n return;\n }\n\n // --tools selects the files to write; --no-commands and --no-skills each\n // say write none of that kind. Together they contradict — refused, not\n // arbitrated, in either combination.\n const suppressed = [\n ...(opts.commands ? [] : [\"--no-commands\"]),\n ...(opts.skills ? [] : [\"--no-skills\"]),\n ];\n if (opts.tools !== undefined && suppressed.length > 0) {\n fail(\n json,\n \"invalid-option\",\n `--tools contradicts ${suppressed.join(\" and \")}: ` +\n \"one selects the files to generate, the other suppresses them.\",\n );\n return;\n }\n const delivery: Delivery[] = [\n ...(opts.commands ? ([\"commands\"] as const) : []),\n ...(opts.skills ? ([\"skills\"] as const) : []),\n ];\n\n // Without --tools the repo decides: whichever tools have left their own\n // dot-directories here. Falling back to claude keeps a bare repo behaving\n // exactly as it did before the scan existed. `detected` is reported either\n // way — what the scan saw is a fact about the repo, not about the flags.\n const detected = detectAgentTools(cwd);\n const scanned = detected.length > 0 ? detected : [\"claude\"];\n const tools = opts.tools === undefined ? scanned : resolveTools(opts.tools, json);\n if (tools === null) return;\n const profile = resolveAgentProfile(opts.agentProfile, existing?.agentProfile, json);\n if (profile === null) return;\n\n // Probe the pre-existing paths in planned order. Managed files refreshed\n // below are removed from `skipped`; custom and already-current files stay.\n const plannedAgentFiles = delivery.length > 0 ? plannedCommandFiles(cwd, tools, delivery, profile) : [];\n // `.mcp.json` joins the same list rather than being reported on the side:\n // it is a scaffolded path like any other, so it must appear in `created`\n // or in `skipped` by the one rule that governs both. Last, because it is\n // written last.\n const candidates = [\n ...plannedDocsFiles(docsDir),\n ...plannedAgentFiles.map((f) => f.path),\n ...(opts.mcp === true || opts.mcpAuthor === true ? [mcpConfigPath(cwd)] : []),\n ];\n let skipped = candidates.filter((p) => existsSync(p));\n\n // Joining touches the docs repo not at all: it is somebody's committed\n // repository, and \"point at it\" must never mean \"write to it\".\n const created = joining && opts.create !== true ? [] : (await scaffoldDocs(docsDir)).created;\n const generatedFor = delivery.length > 0 ? tools : [];\n let refreshed: string[] = [];\n let managedFiles: Record<string, string> = {};\n if (delivery.length > 0) {\n const synced = await syncAgentCommands({\n cwd,\n toolIds: tools,\n delivery,\n profile,\n known: existing?.agentFiles,\n });\n created.push(...synced.created);\n refreshed = synced.refreshed;\n managedFiles = synced.managed;\n skipped = skipped.filter((path) => !refreshed.includes(path));\n }\n\n // The third delivery, and the only machine-readable one. It refuses out\n // loud rather than being written best-effort: a `.mcp.json` half-landed\n // is a host that starts a broken server, and the caller asked for it by\n // name. Before saveConfig, so a run that cannot write this file has not\n // yet moved the committed pointer either.\n let mcpWritten = false;\n if (opts.mcp === true || opts.mcpAuthor === true) {\n const write = await writeMcpConfig(cwd, opts.mcpAuthor === true);\n if (write.kind === \"failed\") {\n fail(json, write.code, write.message);\n return;\n }\n mcpWritten = write.kind === \"created\";\n if (mcpWritten) created.push(mcpConfigPath(cwd));\n }\n\n const stored = storedDocsDir(docsOption);\n // Union, not replacement: this run's files join the ones earlier runs left\n // on disk, and `agentTools` is a record of what the repo HOLDS. A run that\n // generated nothing adds nothing and erases nothing.\n const recordedTools = [...new Set([...(existing?.agentTools ?? []), ...generatedFor])];\n const agentFileManifest = updatedAgentFileManifest(cwd, plannedAgentFiles, existing?.agentFiles, managedFiles);\n const config: StoredConfig = {\n ...existing,\n docsDir: stored,\n ...(opts.service ? { service: opts.service } : {}),\n ...(recordedTools.length > 0 ? { agentTools: recordedTools } : {}),\n agentProfile: profile,\n };\n if (Object.keys(agentFileManifest).length > 0) config.agentFiles = agentFileManifest;\n const configFile = await saveConfig(config, cwd);\n\n const serviceCount = (await listServices(docsDir)).length;\n\n if (json) {\n // `docsDir` stays the resolved absolute path — it is what a consumer\n // needs to find the repo. `docsDirStored` is what was written to\n // loam.json, which is the fact this command is now careful about.\n // `tools` names what files were generated FOR — empty when every\n // delivery was suppressed and none were. `detected` is the separate\n // question of what the scan SAW, which `--tools` overrides without\n // changing: an agent comparing the two learns whether its selection\n // matches the repo.\n emitJson({\n command: \"init\",\n docsDir,\n docsDirStored: stored,\n // Where the pointer came from: `flag` (a --docs somebody typed),\n // `config` (the one this repo already committed — a re-run cannot\n // move it), or `default` (nothing said, nothing committed).\n docsDirSource: docsSource,\n docsRepo: joining ? \"existing\" : \"created\",\n services: serviceCount,\n created,\n refreshed,\n skipped,\n tools: generatedFor,\n agentProfile: profile,\n detected,\n });\n return;\n }\n\n console.log(\"loam initialized.\");\n if (joining) {\n console.log(` docs repo: ${docsDir}`);\n console.log(` pointing at existing docs repo (${serviceCount} services)`);\n } else {\n console.log(` docs repo: ${docsDir} (created)`);\n }\n console.log(\n ` docsDir: ${stored} (as stored in ${CONFIG_FILENAME}`\n + (docsSource === \"config\" ? \" — kept; no --docs was passed\" : \"\") + \")\",\n );\n if (config.service) console.log(` service: ${config.service}`);\n console.log(` config: ${configFile}`);\n console.log(` commit ${CONFIG_FILENAME} — docsDir is resolved relative to it`);\n if (opts.tools === undefined && detected.length > 0) {\n console.log(` detected: ${detected.join(\", \")}`);\n }\n if (opts.commands) console.log(` commands: ${tools.join(\", \")}`);\n if (opts.skills) console.log(` skills: ${tools.join(\", \")}`);\n console.log(` profile: ${profile}`);\n if (created.length > 0) {\n console.log(\" scaffolded:\");\n for (const c of created) console.log(` + ${c}`);\n }\n if (refreshed.length > 0) {\n console.log(\" refreshed (unchanged since loam last wrote them):\");\n for (const path of refreshed) console.log(` ↻ ${path}`);\n }\n\n // The one skipped path that earns more than its line in `skipped`: loam\n // will not merge into a `.mcp.json` a human owns, and the caller asked\n // for this delivery by name — so they are handed the exact key to paste\n // into their own `mcpServers` object. Nothing was read out of their file\n // to produce it; the snippet is the same bytes a fresh write would have\n // used, which is also why it names the launch form this install shape\n // actually needs.\n if ((opts.mcp === true || opts.mcpAuthor === true) && !mcpWritten) {\n console.log(` mcp: ${MCP_CONFIG_FILENAME} is already here — left exactly as it is.`);\n console.log(` paste this into its \"mcpServers\" object:`);\n for (const line of mcpServerSnippet(cwd, opts.mcpAuthor === true)) console.log(` ${line}`);\n }\n\n // Printed ONLY for the single-repo trial composition: one run that both\n // created the docs repo and left a service bound (the binding may\n // predate the run — the config spread above carries an existing\n // loam.json's `service` forward). `loam status` is NOT mute here — its\n // first-hour ladder (core/status/fleet/next.ts) already answers\n // `next.adopt-bound` in exactly this state — but status has to be run\n // to say so, and no status rung ever names `loam vouch`, the one step\n // of this loop that is a person's; init's output is already on screen,\n // so it prints the whole hour once. A join stays silent on purpose: a\n // joined fleet has other repositories already through this loop, and\n // `loam status` in its docs repo is the working guide there. The --json\n // path returned above, so the envelope is byte-identical to before\n // this block existed.\n if (!joining && config.service !== undefined) {\n const steps = firstHour(config.service);\n const width = Math.max(...steps.map(([command]) => command.length));\n console.log(\" next — the first hour:\");\n for (const [command, why] of steps) {\n console.log(` ${command.padEnd(width)} # ${why}`);\n }\n }\n });\n}\n"]}
@@ -0,0 +1,131 @@
1
+ /**
2
+ * `loam init --mcp`: the one MACHINE delivery `init` makes.
3
+ *
4
+ * Every other thing init writes is prose an agent reads — command files and
5
+ * Agent Skills, twenty tools' worth of dialects, all of them pointers at
6
+ * `loam instructions`. The MCP facade is the opposite: a typed read surface,
7
+ * four bounded authoring entries under `--author`, version-matched resources,
8
+ * and every result carrying the `--json` envelope as `structuredContent`. It
9
+ * was also the only delivery that required a human to hand-edit a JSON file
10
+ * before anything could reach it — the generated
11
+ * AGENTS.md said no more than "configure the host to launch `loam mcp` in the
12
+ * repository the tools should answer for", so a scaffolded repository reliably
13
+ * got the prose deliveries and never the typed one.
14
+ *
15
+ * OPT-IN, and that is not timidity. `.mcp.json` at the repo root is a file a
16
+ * host reads and then STARTS A PROCESS from, for everyone who checks the
17
+ * repository out. Writing one by default would mean `loam init` silently
18
+ * arranging for a binary to be launched on a teammate's machine, which is a
19
+ * decision that belongs to whoever runs the command, not to us.
20
+ *
21
+ * ## Why only the repo-root `.mcp.json`
22
+ *
23
+ * loam knows twenty agent tools and several of them read MCP configuration
24
+ * from a file of their own. None of the others is written here, and a future
25
+ * reader who wants to add them should meet the argument first:
26
+ *
27
+ * - `.github/.mcp.json` is already in the registry as a Copilot DETECTION
28
+ * marker (tools/registry.ts). Writing it would make the next `init` detect
29
+ * Copilot in a repository that has none, because we put the marker there —
30
+ * a scan reporting its own output back to itself.
31
+ * - `.cursor/mcp.json` and `.vscode/mcp.json` carry different schemas
32
+ * (`servers` rather than `mcpServers`, plus per-host keys), so a single set
33
+ * of bytes cannot serve all three, and one template per host is one more
34
+ * thing to keep true across releases of somebody else's product.
35
+ * - `.gemini/settings.json` is a GENERAL settings file. Its MCP block is one
36
+ * key among many, so loam could only land it by merging into a file the
37
+ * user owns — and merging into a file a human owns is the one thing every
38
+ * init delivery is built not to do.
39
+ *
40
+ * The repo-root `.mcp.json` is the form with none of those problems: it is a
41
+ * dedicated file, it is nobody's detection marker, and it is read by the hosts
42
+ * that matter without being owned by any of them.
43
+ */
44
+ import { existsSync } from "node:fs";
45
+ import { join } from "node:path";
46
+ import { stageWrites } from "../../core/staging/commit.js";
47
+ import { commitStaged } from "../../core/staging/txn/transaction.js";
48
+ import { planWrite } from "../../core/staging/writes.js";
49
+ export const MCP_CONFIG_FILENAME = ".mcp.json";
50
+ /** The one file this delivery writes, so init's `skipped` probe and the writer cannot disagree. */
51
+ export function mcpConfigPath(cwd) {
52
+ return join(cwd, MCP_CONFIG_FILENAME);
53
+ }
54
+ /**
55
+ * How `loam` is launched HERE, decided from how it is installed here.
56
+ *
57
+ * A fixed `"command": "loam"` would be an unlaunchable entry in exactly the
58
+ * repositories README tells people to make: the documented install is a
59
+ * per-repo devDependency, which puts the binary in `node_modules/.bin/` and on
60
+ * no PATH an MCP host inherits. So the local bin decides — `npx --no` when it
61
+ * is there, the bare name when it is not.
62
+ *
63
+ * `--no` and not a bare `npx loam mcp`: without it npx will FETCH `loam` from
64
+ * the registry when the local resolution misses, which turns a stale checkout
65
+ * into a silent download of a package with a name loam does not own. With it,
66
+ * a missing local binary is an error the host reports.
67
+ *
68
+ * The probe is the extensionless name on both platforms deliberately: npm's
69
+ * shim writer lays down `loam`, `loam.cmd` and `loam.ps1` together on Windows,
70
+ * the first of them for the POSIX shells that run there, so its presence is the
71
+ * portable question "is loam installed into this project".
72
+ */
73
+ export function mcpLaunch(cwd, author = false) {
74
+ const localBin = join(cwd, "node_modules", ".bin", "loam");
75
+ const args = ["mcp", ...(author ? ["--author"] : [])];
76
+ return existsSync(localBin)
77
+ ? { command: "npx", args: ["--no", "loam", ...args] }
78
+ : { command: "loam", args };
79
+ }
80
+ /** The whole file, exactly as it lands. */
81
+ export function mcpConfigContent(cwd, author = false) {
82
+ return `${JSON.stringify({ mcpServers: { loam: mcpLaunch(cwd, author) } }, null, 2)}\n`;
83
+ }
84
+ /**
85
+ * The `"loam": { … }` entry alone, as lines — what init prints when the file
86
+ * is already there so a person can paste the one key into their own
87
+ * `mcpServers` object.
88
+ *
89
+ * Sliced out of the same object the file is made of rather than spelled a
90
+ * second time: a snippet that drifts from the bytes is worse than no snippet,
91
+ * because the reader has no way to tell which of the two is current.
92
+ */
93
+ export function mcpServerSnippet(cwd, author = false) {
94
+ return JSON.stringify({ loam: mcpLaunch(cwd, author) }, null, 2)
95
+ .split("\n")
96
+ .slice(1, -1)
97
+ .map((line) => line.slice(2));
98
+ }
99
+ /**
100
+ * Write `.mcp.json`, or report why not.
101
+ *
102
+ * Through the journaled transaction every other loam writer uses, not a bare
103
+ * `writeFile`: the write is an exclusive create (the existsSync above proves
104
+ * the path is free), so two inits racing for the same repository serialise
105
+ * into the same "already there, left alone" answer instead of one of them
106
+ * silently burying the other's bytes. `root` is the repository being
107
+ * scaffolded, which is where a killed run's `.loam-commit` belongs — the same
108
+ * place `gherkin` journals its own writes into a service repo.
109
+ */
110
+ export async function writeMcpConfig(cwd, author = false) {
111
+ const path = mcpConfigPath(cwd);
112
+ if (existsSync(path))
113
+ return { kind: "skipped" };
114
+ const staged = await stageWrites([planWrite(path, mcpConfigContent(cwd, author))]);
115
+ const committed = await commitStaged({
116
+ root: cwd,
117
+ command: "init",
118
+ rerun: author ? "loam init --mcp-author" : "loam init --mcp",
119
+ target: MCP_CONFIG_FILENAME,
120
+ }, staged, "written");
121
+ if (committed.ok)
122
+ return { kind: "created" };
123
+ // A lost exclusive create is the never-overwrite contract firing one layer
124
+ // down — somebody else's `.mcp.json` is there now, and "present, so skipped"
125
+ // is the answer the probe above would have given a moment later. Nothing of
126
+ // ours went in; there is no half-state to report.
127
+ if (committed.raced)
128
+ return { kind: "skipped" };
129
+ return { kind: "failed", code: committed.code, message: committed.message };
130
+ }
131
+ //# sourceMappingURL=mcp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp.js","sourceRoot":"","sources":["../../../src/commands/init/mcp.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `loam init --mcp`: the one MACHINE delivery `init` makes.\n *\n * Every other thing init writes is prose an agent reads — command files and\n * Agent Skills, twenty tools' worth of dialects, all of them pointers at\n * `loam instructions`. The MCP facade is the opposite: a typed read surface,\n * four bounded authoring entries under `--author`, version-matched resources,\n * and every result carrying the `--json` envelope as `structuredContent`. It\n * was also the only delivery that required a human to hand-edit a JSON file\n * before anything could reach it — the generated\n * AGENTS.md said no more than \"configure the host to launch `loam mcp` in the\n * repository the tools should answer for\", so a scaffolded repository reliably\n * got the prose deliveries and never the typed one.\n *\n * OPT-IN, and that is not timidity. `.mcp.json` at the repo root is a file a\n * host reads and then STARTS A PROCESS from, for everyone who checks the\n * repository out. Writing one by default would mean `loam init` silently\n * arranging for a binary to be launched on a teammate's machine, which is a\n * decision that belongs to whoever runs the command, not to us.\n *\n * ## Why only the repo-root `.mcp.json`\n *\n * loam knows twenty agent tools and several of them read MCP configuration\n * from a file of their own. None of the others is written here, and a future\n * reader who wants to add them should meet the argument first:\n *\n * - `.github/.mcp.json` is already in the registry as a Copilot DETECTION\n * marker (tools/registry.ts). Writing it would make the next `init` detect\n * Copilot in a repository that has none, because we put the marker there —\n * a scan reporting its own output back to itself.\n * - `.cursor/mcp.json` and `.vscode/mcp.json` carry different schemas\n * (`servers` rather than `mcpServers`, plus per-host keys), so a single set\n * of bytes cannot serve all three, and one template per host is one more\n * thing to keep true across releases of somebody else's product.\n * - `.gemini/settings.json` is a GENERAL settings file. Its MCP block is one\n * key among many, so loam could only land it by merging into a file the\n * user owns — and merging into a file a human owns is the one thing every\n * init delivery is built not to do.\n *\n * The repo-root `.mcp.json` is the form with none of those problems: it is a\n * dedicated file, it is nobody's detection marker, and it is read by the hosts\n * that matter without being owned by any of them.\n */\nimport { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { stageWrites } from \"../../core/staging/commit.js\";\nimport { commitStaged } from \"../../core/staging/txn/transaction.js\";\nimport { planWrite } from \"../../core/staging/writes.js\";\n\nexport const MCP_CONFIG_FILENAME = \".mcp.json\";\n\n/** The one file this delivery writes, so init's `skipped` probe and the writer cannot disagree. */\nexport function mcpConfigPath(cwd: string): string {\n return join(cwd, MCP_CONFIG_FILENAME);\n}\n\n/** What a host is told to run: the `command`/`args` pair of the `loam` server entry. */\nexport interface McpLaunch {\n command: string;\n args: string[];\n}\n\n/**\n * How `loam` is launched HERE, decided from how it is installed here.\n *\n * A fixed `\"command\": \"loam\"` would be an unlaunchable entry in exactly the\n * repositories README tells people to make: the documented install is a\n * per-repo devDependency, which puts the binary in `node_modules/.bin/` and on\n * no PATH an MCP host inherits. So the local bin decides — `npx --no` when it\n * is there, the bare name when it is not.\n *\n * `--no` and not a bare `npx loam mcp`: without it npx will FETCH `loam` from\n * the registry when the local resolution misses, which turns a stale checkout\n * into a silent download of a package with a name loam does not own. With it,\n * a missing local binary is an error the host reports.\n *\n * The probe is the extensionless name on both platforms deliberately: npm's\n * shim writer lays down `loam`, `loam.cmd` and `loam.ps1` together on Windows,\n * the first of them for the POSIX shells that run there, so its presence is the\n * portable question \"is loam installed into this project\".\n */\nexport function mcpLaunch(cwd: string, author = false): McpLaunch {\n const localBin = join(cwd, \"node_modules\", \".bin\", \"loam\");\n const args = [\"mcp\", ...(author ? [\"--author\"] : [])];\n return existsSync(localBin)\n ? { command: \"npx\", args: [\"--no\", \"loam\", ...args] }\n : { command: \"loam\", args };\n}\n\n/** The whole file, exactly as it lands. */\nexport function mcpConfigContent(cwd: string, author = false): string {\n return `${JSON.stringify({ mcpServers: { loam: mcpLaunch(cwd, author) } }, null, 2)}\\n`;\n}\n\n/**\n * The `\"loam\": { … }` entry alone, as lines — what init prints when the file\n * is already there so a person can paste the one key into their own\n * `mcpServers` object.\n *\n * Sliced out of the same object the file is made of rather than spelled a\n * second time: a snippet that drifts from the bytes is worse than no snippet,\n * because the reader has no way to tell which of the two is current.\n */\nexport function mcpServerSnippet(cwd: string, author = false): string[] {\n return JSON.stringify({ loam: mcpLaunch(cwd, author) }, null, 2)\n .split(\"\\n\")\n .slice(1, -1)\n .map((line) => line.slice(2));\n}\n\n/**\n * What happened to `.mcp.json` on this run. `skipped` is the never-overwrite\n * contract every other init delivery follows, and for the same reason: loam\n * does not merge into a file a human owns, so an existing `.mcp.json` is\n * reported and left byte-for-byte alone — no parse, no key merge, no rewrite.\n */\nexport type McpWrite =\n | { kind: \"created\" }\n | { kind: \"skipped\" }\n | { kind: \"failed\"; code: \"merge-failed\" | \"rollback-incomplete\"; message: string };\n\n/**\n * Write `.mcp.json`, or report why not.\n *\n * Through the journaled transaction every other loam writer uses, not a bare\n * `writeFile`: the write is an exclusive create (the existsSync above proves\n * the path is free), so two inits racing for the same repository serialise\n * into the same \"already there, left alone\" answer instead of one of them\n * silently burying the other's bytes. `root` is the repository being\n * scaffolded, which is where a killed run's `.loam-commit` belongs — the same\n * place `gherkin` journals its own writes into a service repo.\n */\nexport async function writeMcpConfig(cwd: string, author = false): Promise<McpWrite> {\n const path = mcpConfigPath(cwd);\n if (existsSync(path)) return { kind: \"skipped\" };\n\n const staged = await stageWrites([planWrite(path, mcpConfigContent(cwd, author))]);\n const committed = await commitStaged(\n {\n root: cwd,\n command: \"init\",\n rerun: author ? \"loam init --mcp-author\" : \"loam init --mcp\",\n target: MCP_CONFIG_FILENAME,\n },\n staged,\n \"written\",\n );\n if (committed.ok) return { kind: \"created\" };\n // A lost exclusive create is the never-overwrite contract firing one layer\n // down — somebody else's `.mcp.json` is there now, and \"present, so skipped\"\n // is the answer the probe above would have given a moment later. Nothing of\n // ours went in; there is no half-state to report.\n if (committed.raced) return { kind: \"skipped\" };\n return { kind: \"failed\", code: committed.code, message: committed.message };\n}\n"]}
@@ -0,0 +1,78 @@
1
+ /**
2
+ * The three questions `loam init` answers before it writes anything: which
3
+ * agent tools were asked for, where the docs are being recorded, and whether a
4
+ * directory already IS a docs repo.
5
+ *
6
+ * They are here rather than inline because each one has a default that is a
7
+ * decision. `--tools` has no commander default on purpose, so an explicit flag
8
+ * stays distinguishable from none — which is what lets the autodetection
9
+ * fallback and the `--no-*` contradiction be decided rather than silently
10
+ * arbitrated.
11
+ */
12
+ import { existsSync } from "node:fs";
13
+ import { fail } from "../../core/envelope/json.js";
14
+ import { agentsPath } from "../../core/repo/paths.js";
15
+ import { docsRepoState } from "../../core/repo/state.js";
16
+ import { AGENT_TOOLS } from "../../core/agent/tools/registry.js";
17
+ import { AGENT_PROFILES, } from "../../core/agent/scaffold.js";
18
+ export function resolveAgentProfile(raw, current, json) {
19
+ const value = raw ?? current ?? "full";
20
+ if (AGENT_PROFILES.includes(value))
21
+ return value;
22
+ fail(json, "invalid-option", `Unknown --agent-profile '${value}'. Expected: ${AGENT_PROFILES.join(" | ")}.`);
23
+ return null;
24
+ }
25
+ /**
26
+ * Resolve --tools to registry ids, or null after reporting the refusal. The
27
+ * default (the cwd scan) lives at the call site, not in commander, so an
28
+ * explicit `--tools` is distinguishable from none — which is what lets both the
29
+ * autodetection fallback and the `--no-*` contradiction be decided instead of
30
+ * silently arbitrated.
31
+ */
32
+ export function resolveTools(raw, json) {
33
+ const supported = Object.keys(AGENT_TOOLS);
34
+ if (raw === "all")
35
+ return supported;
36
+ const ids = [...new Set(raw.split(",").map((t) => t.trim()).filter((t) => t !== ""))];
37
+ const unknown = ids.filter((t) => !(t in AGENT_TOOLS));
38
+ if (ids.length === 0 || unknown.length > 0) {
39
+ fail(json, "invalid-option", (ids.length === 0
40
+ ? "--tools names no tool."
41
+ : `--tools does not recognize: ${unknown.join(", ")}.`) +
42
+ ` Supported: ${supported.join(", ")} — or "all".`);
43
+ return null;
44
+ }
45
+ return ids;
46
+ }
47
+ /**
48
+ * `--docs` exactly as the caller wrote it, with separators normalised.
49
+ *
50
+ * Stored verbatim on purpose. `init` used to resolve it and write the absolute
51
+ * result, which meant a committed loam.json named a directory that existed on
52
+ * one laptop: every teammate who cloned the service repo got a docsDir under
53
+ * someone else's home directory, and `loam list` reported an empty fleet
54
+ * instead of saying so. `loadConfig` resolves relative paths against the config
55
+ * file's own directory, so `../docs` keeps meaning "next to this repo" wherever
56
+ * the pair is checked out. An absolute `--docs` is still stored absolute — that
57
+ * is the caller's explicit choice, and `loam doctor` warns about it.
58
+ *
59
+ * Backslashes become forward slashes so a config written on Windows resolves on
60
+ * POSIX; a trailing separator is dropped so the stored spelling is stable.
61
+ */
62
+ export function storedDocsDir(raw) {
63
+ const slashed = raw.split("\\").join("/");
64
+ if (slashed.length <= 1)
65
+ return slashed;
66
+ const trimmed = slashed.replace(/\/+$/, "");
67
+ return trimmed === "" ? "/" : trimmed;
68
+ }
69
+ /**
70
+ * Does this directory already hold a docs repo? `services/` plus `AGENTS.md` —
71
+ * the two things every docs repo has and no service repo does. The pair is the
72
+ * whole point: a single marker would make `init --docs ../srv` (a typo for
73
+ * `../docs`) look like a join and adopt the service repo as the fleet.
74
+ */
75
+ export function isDocsRepo(dir) {
76
+ return docsRepoState(dir).kind === "ok" && existsSync(agentsPath(dir));
77
+ }
78
+ //# sourceMappingURL=options.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"options.js","sourceRoot":"","sources":["../../../src/commands/init/options.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAErC,OAAO,EAAE,IAAI,EAAE,MAAM,6BAA6B,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,oCAAoC,CAAC;AACjE,OAAO,EACL,cAAc,GAEf,MAAM,8BAA8B,CAAC;AAEtC,MAAM,UAAU,mBAAmB,CACjC,GAAuB,EACvB,OAAiC,EACjC,IAAa;IAEb,MAAM,KAAK,GAAG,GAAG,IAAI,OAAO,IAAI,MAAM,CAAC;IACvC,IAAI,cAAc,CAAC,QAAQ,CAAC,KAAqB,CAAC;QAAE,OAAO,KAAqB,CAAC;IACjF,IAAI,CAAC,IAAI,EAAE,gBAAgB,EAAE,4BAA4B,KAAK,gBAAgB,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC7G,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,YAAY,CAAC,GAAW,EAAE,IAAa;IACrD,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC3C,IAAI,GAAG,KAAK,KAAK;QAAE,OAAO,SAAS,CAAC;IACpC,MAAM,GAAG,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;IACtF,MAAM,OAAO,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,WAAW,CAAC,CAAC,CAAC;IACvD,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC3C,IAAI,CACF,IAAI,EACJ,gBAAgB,EAChB,CAAC,GAAG,CAAC,MAAM,KAAK,CAAC;YACf,CAAC,CAAC,wBAAwB;YAC1B,CAAC,CAAC,+BAA+B,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;YACvD,eAAe,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,CACpD,CAAC;QACF,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,aAAa,CAAC,GAAW;IACvC,MAAM,OAAO,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC1C,IAAI,OAAO,CAAC,MAAM,IAAI,CAAC;QAAE,OAAO,OAAO,CAAC;IACxC,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAC5C,OAAO,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC;AACxC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,UAAU,CAAC,GAAY;IACrC,OAAO,aAAa,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,IAAI,IAAI,UAAU,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;AACzE,CAAC","sourcesContent":["/**\n * The three questions `loam init` answers before it writes anything: which\n * agent tools were asked for, where the docs are being recorded, and whether a\n * directory already IS a docs repo.\n *\n * They are here rather than inline because each one has a default that is a\n * decision. `--tools` has no commander default on purpose, so an explicit flag\n * stays distinguishable from none — which is what lets the autodetection\n * fallback and the `--no-*` contradiction be decided rather than silently\n * arbitrated.\n */\nimport { existsSync } from \"node:fs\";\nimport type { DocsDir } from \"../../core/kernel/ids/dirs.js\";\nimport { fail } from \"../../core/envelope/json.js\";\nimport { agentsPath } from \"../../core/repo/paths.js\";\nimport { docsRepoState } from \"../../core/repo/state.js\";\nimport { AGENT_TOOLS } from \"../../core/agent/tools/registry.js\";\nimport {\n AGENT_PROFILES,\n type AgentProfile,\n} from \"../../core/agent/scaffold.js\";\n\nexport function resolveAgentProfile(\n raw: string | undefined,\n current: AgentProfile | undefined,\n json: boolean,\n): AgentProfile | null {\n const value = raw ?? current ?? \"full\";\n if (AGENT_PROFILES.includes(value as AgentProfile)) return value as AgentProfile;\n fail(json, \"invalid-option\", `Unknown --agent-profile '${value}'. Expected: ${AGENT_PROFILES.join(\" | \")}.`);\n return null;\n}\n\n/**\n * Resolve --tools to registry ids, or null after reporting the refusal. The\n * default (the cwd scan) lives at the call site, not in commander, so an\n * explicit `--tools` is distinguishable from none — which is what lets both the\n * autodetection fallback and the `--no-*` contradiction be decided instead of\n * silently arbitrated.\n */\nexport function resolveTools(raw: string, json: boolean): string[] | null {\n const supported = Object.keys(AGENT_TOOLS);\n if (raw === \"all\") return supported;\n const ids = [...new Set(raw.split(\",\").map((t) => t.trim()).filter((t) => t !== \"\"))];\n const unknown = ids.filter((t) => !(t in AGENT_TOOLS));\n if (ids.length === 0 || unknown.length > 0) {\n fail(\n json,\n \"invalid-option\",\n (ids.length === 0\n ? \"--tools names no tool.\"\n : `--tools does not recognize: ${unknown.join(\", \")}.`) +\n ` Supported: ${supported.join(\", \")} — or \"all\".`,\n );\n return null;\n }\n return ids;\n}\n\n/**\n * `--docs` exactly as the caller wrote it, with separators normalised.\n *\n * Stored verbatim on purpose. `init` used to resolve it and write the absolute\n * result, which meant a committed loam.json named a directory that existed on\n * one laptop: every teammate who cloned the service repo got a docsDir under\n * someone else's home directory, and `loam list` reported an empty fleet\n * instead of saying so. `loadConfig` resolves relative paths against the config\n * file's own directory, so `../docs` keeps meaning \"next to this repo\" wherever\n * the pair is checked out. An absolute `--docs` is still stored absolute — that\n * is the caller's explicit choice, and `loam doctor` warns about it.\n *\n * Backslashes become forward slashes so a config written on Windows resolves on\n * POSIX; a trailing separator is dropped so the stored spelling is stable.\n */\nexport function storedDocsDir(raw: string): string {\n const slashed = raw.split(\"\\\\\").join(\"/\");\n if (slashed.length <= 1) return slashed;\n const trimmed = slashed.replace(/\\/+$/, \"\");\n return trimmed === \"\" ? \"/\" : trimmed;\n}\n\n/**\n * Does this directory already hold a docs repo? `services/` plus `AGENTS.md` —\n * the two things every docs repo has and no service repo does. The pair is the\n * whole point: a single marker would make `init --docs ../srv` (a typo for\n * `../docs`) look like a join and adopt the service repo as the fleet.\n */\nexport function isDocsRepo(dir: DocsDir): boolean {\n return docsRepoState(dir).kind === \"ok\" && existsSync(agentsPath(dir));\n}\n"]}