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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1036) hide show
  1. package/CHANGELOG.md +2635 -86
  2. package/COMPARISON.md +80 -63
  3. package/CONTRIBUTING.md +84 -0
  4. package/MIGRATING-from-OpenSpec.md +213 -54
  5. package/QUICKSTART.md +125 -0
  6. package/README.md +450 -150
  7. package/ROADMAP.md +599 -0
  8. package/SCHEMA.md +2355 -256
  9. package/SECURITY.md +21 -3
  10. package/WORKFLOW.md +701 -0
  11. package/dist/cli.js +113 -19
  12. package/dist/cli.js.map +1 -1
  13. package/dist/commands/adopt/adopt.js +209 -0
  14. package/dist/commands/adopt/adopt.js.map +1 -0
  15. package/dist/commands/adopt/render.js +268 -0
  16. package/dist/commands/adopt/render.js.map +1 -0
  17. package/dist/commands/archive/archive.js +77 -0
  18. package/dist/commands/archive/archive.js.map +1 -0
  19. package/dist/commands/archive/plan/contracts/asyncapi.js +178 -0
  20. package/dist/commands/archive/plan/contracts/asyncapi.js.map +1 -0
  21. package/dist/commands/archive/plan/contracts/openapi.js +159 -0
  22. package/dist/commands/archive/plan/contracts/openapi.js.map +1 -0
  23. package/dist/commands/archive/plan/gate.js +323 -0
  24. package/dist/commands/archive/plan/gate.js.map +1 -0
  25. package/dist/commands/archive/plan/landscape.js +180 -0
  26. package/dist/commands/archive/plan/landscape.js.map +1 -0
  27. package/dist/commands/archive/plan/refusal.js +111 -0
  28. package/dist/commands/archive/plan/refusal.js.map +1 -0
  29. package/dist/commands/archive/plan/specs.js +237 -0
  30. package/dist/commands/archive/plan/specs.js.map +1 -0
  31. package/dist/commands/archive/plan/state.js +27 -0
  32. package/dist/commands/archive/plan/state.js.map +1 -0
  33. package/dist/commands/archive/run.js +252 -0
  34. package/dist/commands/archive/run.js.map +1 -0
  35. package/dist/commands/context/context.js +99 -0
  36. package/dist/commands/context/context.js.map +1 -0
  37. package/dist/commands/context/print.js +283 -0
  38. package/dist/commands/context/print.js.map +1 -0
  39. package/dist/commands/delta/delta.js +279 -0
  40. package/dist/commands/delta/delta.js.map +1 -0
  41. package/dist/commands/delta/print.js +205 -0
  42. package/dist/commands/delta/print.js.map +1 -0
  43. package/dist/commands/dependencies.js +9 -7
  44. package/dist/commands/dependencies.js.map +1 -1
  45. package/dist/commands/diff/diff.js +93 -0
  46. package/dist/commands/diff/diff.js.map +1 -0
  47. package/dist/commands/diff/print.js +38 -0
  48. package/dist/commands/diff/print.js.map +1 -0
  49. package/dist/commands/doctor.js +5 -4
  50. package/dist/commands/doctor.js.map +1 -1
  51. package/dist/commands/explain/explain.js +151 -0
  52. package/dist/commands/explain/explain.js.map +1 -0
  53. package/dist/commands/explore.js +29 -24
  54. package/dist/commands/explore.js.map +1 -1
  55. package/dist/commands/gate/gate.js +115 -0
  56. package/dist/commands/gate/gate.js.map +1 -0
  57. package/dist/commands/gate/print.js +54 -0
  58. package/dist/commands/gate/print.js.map +1 -0
  59. package/dist/commands/gherkin/commit.js +146 -0
  60. package/dist/commands/gherkin/commit.js.map +1 -0
  61. package/dist/commands/gherkin/gherkin.js +246 -0
  62. package/dist/commands/gherkin/gherkin.js.map +1 -0
  63. package/dist/commands/gherkin/reconcile.js +149 -0
  64. package/dist/commands/gherkin/reconcile.js.map +1 -0
  65. package/dist/commands/gherkin/render.js +77 -0
  66. package/dist/commands/gherkin/render.js.map +1 -0
  67. package/dist/commands/init/example.js +204 -0
  68. package/dist/commands/init/example.js.map +1 -0
  69. package/dist/commands/init/first-hour.js +28 -0
  70. package/dist/commands/init/first-hour.js.map +1 -0
  71. package/dist/commands/{init.js → init/init.js} +146 -71
  72. package/dist/commands/init/init.js.map +1 -0
  73. package/dist/commands/init/mcp.js +131 -0
  74. package/dist/commands/init/mcp.js.map +1 -0
  75. package/dist/commands/init/options.js +78 -0
  76. package/dist/commands/init/options.js.map +1 -0
  77. package/dist/commands/instructions.js +72 -14
  78. package/dist/commands/instructions.js.map +1 -1
  79. package/dist/commands/list/campaign/campaign.js +65 -0
  80. package/dist/commands/list/campaign/campaign.js.map +1 -0
  81. package/dist/commands/list/campaign/owners.js +65 -0
  82. package/dist/commands/list/campaign/owners.js.map +1 -0
  83. package/dist/commands/list/json.js +157 -0
  84. package/dist/commands/list/json.js.map +1 -0
  85. package/dist/commands/list/list.js +343 -0
  86. package/dist/commands/list/list.js.map +1 -0
  87. package/dist/commands/list/print.js +301 -0
  88. package/dist/commands/list/print.js.map +1 -0
  89. package/dist/commands/list/review.js +120 -0
  90. package/dist/commands/list/review.js.map +1 -0
  91. package/dist/commands/list/views.js +105 -0
  92. package/dist/commands/list/views.js.map +1 -0
  93. package/dist/commands/mcp/dispatch.js +183 -0
  94. package/dist/commands/mcp/dispatch.js.map +1 -0
  95. package/dist/commands/mcp/mcp.js +34 -0
  96. package/dist/commands/mcp/mcp.js.map +1 -0
  97. package/dist/commands/mcp/serve.js +55 -0
  98. package/dist/commands/mcp/serve.js.map +1 -0
  99. package/dist/commands/migrate-openspec/materialize/active.js +170 -0
  100. package/dist/commands/migrate-openspec/materialize/active.js.map +1 -0
  101. package/dist/commands/migrate-openspec/materialize/feature.js +41 -0
  102. package/dist/commands/migrate-openspec/materialize/feature.js.map +1 -0
  103. package/dist/commands/migrate-openspec/materialize/living.js +62 -0
  104. package/dist/commands/migrate-openspec/materialize/living.js.map +1 -0
  105. package/dist/commands/migrate-openspec/materialize/stage.js +142 -0
  106. package/dist/commands/migrate-openspec/materialize/stage.js.map +1 -0
  107. package/dist/commands/migrate-openspec/materialize/target.js +219 -0
  108. package/dist/commands/migrate-openspec/materialize/target.js.map +1 -0
  109. package/dist/commands/migrate-openspec/migrate-openspec.js +142 -0
  110. package/dist/commands/migrate-openspec/migrate-openspec.js.map +1 -0
  111. package/dist/commands/migrate-openspec/openspec/decisions.js +91 -0
  112. package/dist/commands/migrate-openspec/openspec/decisions.js.map +1 -0
  113. package/dist/commands/migrate-openspec/openspec/error.js +19 -0
  114. package/dist/commands/migrate-openspec/openspec/error.js.map +1 -0
  115. package/dist/commands/migrate-openspec/openspec/mapping.js +170 -0
  116. package/dist/commands/migrate-openspec/openspec/mapping.js.map +1 -0
  117. package/dist/commands/migrate-openspec/openspec/paths.js +43 -0
  118. package/dist/commands/migrate-openspec/openspec/paths.js.map +1 -0
  119. package/dist/commands/migrate-openspec/openspec/read.js +49 -0
  120. package/dist/commands/migrate-openspec/openspec/read.js.map +1 -0
  121. package/dist/commands/migrate-openspec/print.js +89 -0
  122. package/dist/commands/migrate-openspec/print.js.map +1 -0
  123. package/dist/commands/new/commit.js +76 -0
  124. package/dist/commands/new/commit.js.map +1 -0
  125. package/dist/commands/new/new.js +283 -0
  126. package/dist/commands/new/new.js.map +1 -0
  127. package/dist/commands/new/templates.js +355 -0
  128. package/dist/commands/new/templates.js.map +1 -0
  129. package/dist/commands/open.js +203 -0
  130. package/dist/commands/open.js.map +1 -0
  131. package/dist/commands/policy/format.js +152 -0
  132. package/dist/commands/policy/format.js.map +1 -0
  133. package/dist/commands/{docs-repo-gate.js → policy/gate.js} +11 -11
  134. package/dist/commands/policy/gate.js.map +1 -0
  135. package/dist/commands/rebase/edit.js +106 -0
  136. package/dist/commands/rebase/edit.js.map +1 -0
  137. package/dist/commands/rebase/living.js +185 -0
  138. package/dist/commands/rebase/living.js.map +1 -0
  139. package/dist/commands/rebase/plan.js +245 -0
  140. package/dist/commands/rebase/plan.js.map +1 -0
  141. package/dist/commands/rebase/rebase.js +275 -0
  142. package/dist/commands/rebase/rebase.js.map +1 -0
  143. package/dist/commands/seed/commit.js +192 -0
  144. package/dist/commands/seed/commit.js.map +1 -0
  145. package/dist/commands/seed/plan.js +133 -0
  146. package/dist/commands/seed/plan.js.map +1 -0
  147. package/dist/commands/seed/seed.js +172 -0
  148. package/dist/commands/seed/seed.js.map +1 -0
  149. package/dist/commands/show/feature.js +178 -0
  150. package/dist/commands/show/feature.js.map +1 -0
  151. package/dist/commands/show/marks.js +24 -0
  152. package/dist/commands/show/marks.js.map +1 -0
  153. package/dist/commands/{show.js → show/service.js} +63 -152
  154. package/dist/commands/show/service.js.map +1 -0
  155. package/dist/commands/show/show.js +77 -0
  156. package/dist/commands/show/show.js.map +1 -0
  157. package/dist/commands/status/json.js +45 -0
  158. package/dist/commands/status/json.js.map +1 -0
  159. package/dist/commands/status/print.js +157 -0
  160. package/dist/commands/status/print.js.map +1 -0
  161. package/dist/commands/status/status.js +119 -0
  162. package/dist/commands/status/status.js.map +1 -0
  163. package/dist/commands/steps/steps.js +189 -0
  164. package/dist/commands/steps/steps.js.map +1 -0
  165. package/dist/commands/subsystem/edit.js +192 -0
  166. package/dist/commands/subsystem/edit.js.map +1 -0
  167. package/dist/commands/subsystem/move.js +265 -0
  168. package/dist/commands/subsystem/move.js.map +1 -0
  169. package/dist/commands/subsystem/query.js +115 -0
  170. package/dist/commands/subsystem/query.js.map +1 -0
  171. package/dist/commands/subsystem/subsystem.js +101 -0
  172. package/dist/commands/subsystem/subsystem.js.map +1 -0
  173. package/dist/commands/subsystem/sync.js +103 -0
  174. package/dist/commands/subsystem/sync.js.map +1 -0
  175. package/dist/commands/subsystem/txn/txn.js +94 -0
  176. package/dist/commands/subsystem/txn/txn.js.map +1 -0
  177. package/dist/commands/subsystem/txn/views.js +70 -0
  178. package/dist/commands/subsystem/txn/views.js.map +1 -0
  179. package/dist/commands/unarchive/manifest.js +160 -0
  180. package/dist/commands/unarchive/manifest.js.map +1 -0
  181. package/dist/commands/{unarchive.js → unarchive/restore.js} +47 -160
  182. package/dist/commands/unarchive/restore.js.map +1 -0
  183. package/dist/commands/unarchive/unarchive.js +67 -0
  184. package/dist/commands/unarchive/unarchive.js.map +1 -0
  185. package/dist/commands/validate/arch-coverage.js +204 -0
  186. package/dist/commands/validate/arch-coverage.js.map +1 -0
  187. package/dist/commands/validate/checks/fleet-shape.js +296 -0
  188. package/dist/commands/validate/checks/fleet-shape.js.map +1 -0
  189. package/dist/commands/validate/checks/health-deps.js +55 -0
  190. package/dist/commands/validate/checks/health-deps.js.map +1 -0
  191. package/dist/commands/validate/checks/requirements.js +254 -0
  192. package/dist/commands/validate/checks/requirements.js.map +1 -0
  193. package/dist/commands/validate/checks/sources.js +76 -0
  194. package/dist/commands/validate/checks/sources.js.map +1 -0
  195. package/dist/commands/validate/checks/vocabulary.js +31 -0
  196. package/dist/commands/validate/checks/vocabulary.js.map +1 -0
  197. package/dist/commands/validate/feature.js +216 -0
  198. package/dist/commands/validate/feature.js.map +1 -0
  199. package/dist/commands/validate/fleet/census.js +69 -0
  200. package/dist/commands/validate/fleet/census.js.map +1 -0
  201. package/dist/commands/validate/fleet/kind-tags.js +39 -0
  202. package/dist/commands/validate/fleet/kind-tags.js.map +1 -0
  203. package/dist/commands/validate/fleet/landscape.js +353 -0
  204. package/dist/commands/validate/fleet/landscape.js.map +1 -0
  205. package/dist/commands/validate/fleet/load.js +52 -0
  206. package/dist/commands/validate/fleet/load.js.map +1 -0
  207. package/dist/commands/validate/fleet/obligations.js +270 -0
  208. package/dist/commands/validate/fleet/obligations.js.map +1 -0
  209. package/dist/commands/validate/fleet/scorecard/adoption.js +102 -0
  210. package/dist/commands/validate/fleet/scorecard/adoption.js.map +1 -0
  211. package/dist/commands/validate/fleet/scorecard/contracts.js +98 -0
  212. package/dist/commands/validate/fleet/scorecard/contracts.js.map +1 -0
  213. package/dist/commands/validate/fleet/scorecard/print.js +63 -0
  214. package/dist/commands/validate/fleet/scorecard/print.js.map +1 -0
  215. package/dist/commands/validate/fleet/scorecard/scorecard.js +156 -0
  216. package/dist/commands/validate/fleet/scorecard/scorecard.js.map +1 -0
  217. package/dist/commands/validate/fleet/usecases/capability-tag.js +94 -0
  218. package/dist/commands/validate/fleet/usecases/capability-tag.js.map +1 -0
  219. package/dist/commands/validate/fleet/usecases/place.js +13 -0
  220. package/dist/commands/validate/fleet/usecases/place.js.map +1 -0
  221. package/dist/commands/validate/fleet/usecases/requirement-tag.js +95 -0
  222. package/dist/commands/validate/fleet/usecases/requirement-tag.js.map +1 -0
  223. package/dist/commands/validate/fleet/usecases/steps.js +197 -0
  224. package/dist/commands/validate/fleet/usecases/steps.js.map +1 -0
  225. package/dist/commands/validate/fleet/usecases/usecases.js +99 -0
  226. package/dist/commands/validate/fleet/usecases/usecases.js.map +1 -0
  227. package/dist/commands/validate/fleet/views/ids.js +40 -0
  228. package/dist/commands/validate/fleet/views/ids.js.map +1 -0
  229. package/dist/commands/validate/fleet/views/stale.js +59 -0
  230. package/dist/commands/validate/fleet/views/stale.js.map +1 -0
  231. package/dist/commands/validate/links/corpus.js +92 -0
  232. package/dist/commands/validate/links/corpus.js.map +1 -0
  233. package/dist/commands/validate/links/glossary.js +75 -0
  234. package/dist/commands/validate/links/glossary.js.map +1 -0
  235. package/dist/commands/validate/report.js +269 -0
  236. package/dist/commands/validate/report.js.map +1 -0
  237. package/dist/commands/validate/service/api.js +338 -0
  238. package/dist/commands/validate/service/api.js.map +1 -0
  239. package/dist/commands/validate/service/events/events.js +219 -0
  240. package/dist/commands/validate/service/events/events.js.map +1 -0
  241. package/dist/commands/validate/service/events/message-producers.js +77 -0
  242. package/dist/commands/validate/service/events/message-producers.js.map +1 -0
  243. package/dist/commands/validate/service/evidence-pins.js +131 -0
  244. package/dist/commands/validate/service/evidence-pins.js.map +1 -0
  245. package/dist/commands/validate/service/service.js +251 -0
  246. package/dist/commands/validate/service/service.js.map +1 -0
  247. package/dist/commands/validate/service/specs.js +251 -0
  248. package/dist/commands/validate/service/specs.js.map +1 -0
  249. package/dist/commands/validate/service/spine.js +113 -0
  250. package/dist/commands/validate/service/spine.js.map +1 -0
  251. package/dist/commands/validate/validate.js +338 -0
  252. package/dist/commands/validate/validate.js.map +1 -0
  253. package/dist/commands/verify/cross/diff.js +182 -0
  254. package/dist/commands/verify/cross/diff.js.map +1 -0
  255. package/dist/commands/verify/evidence/contract.js +32 -0
  256. package/dist/commands/verify/evidence/contract.js.map +1 -0
  257. package/dist/commands/verify/evidence/pins.js +52 -0
  258. package/dist/commands/verify/evidence/pins.js.map +1 -0
  259. package/dist/commands/verify/evidence/read.js +72 -0
  260. package/dist/commands/verify/evidence/read.js.map +1 -0
  261. package/dist/commands/verify/frozen.js +241 -0
  262. package/dist/commands/verify/frozen.js.map +1 -0
  263. package/dist/commands/verify/record.js +226 -0
  264. package/dist/commands/verify/record.js.map +1 -0
  265. package/dist/commands/verify/report.js +223 -0
  266. package/dist/commands/verify/report.js.map +1 -0
  267. package/dist/commands/verify/results.js +246 -0
  268. package/dist/commands/verify/results.js.map +1 -0
  269. package/dist/commands/verify/verify.js +217 -0
  270. package/dist/commands/verify/verify.js.map +1 -0
  271. package/dist/commands/vouch/contract.js +11 -0
  272. package/dist/commands/vouch/contract.js.map +1 -0
  273. package/dist/commands/vouch/pack/contract.js +2 -0
  274. package/dist/commands/vouch/pack/contract.js.map +1 -0
  275. package/dist/commands/vouch/pack/pack.js +266 -0
  276. package/dist/commands/vouch/pack/pack.js.map +1 -0
  277. package/dist/commands/vouch/pack/print.js +271 -0
  278. package/dist/commands/vouch/pack/print.js.map +1 -0
  279. package/dist/commands/vouch/pack/sections.js +142 -0
  280. package/dist/commands/vouch/pack/sections.js.map +1 -0
  281. package/dist/commands/vouch/prompt/confirm.js +46 -0
  282. package/dist/commands/vouch/prompt/confirm.js.map +1 -0
  283. package/dist/commands/vouch/report.js +101 -0
  284. package/dist/commands/vouch/report.js.map +1 -0
  285. package/dist/commands/vouch/run.js +285 -0
  286. package/dist/commands/vouch/run.js.map +1 -0
  287. package/dist/commands/vouch/sample/plan.js +125 -0
  288. package/dist/commands/vouch/sample/plan.js.map +1 -0
  289. package/dist/commands/vouch/sample/print.js +109 -0
  290. package/dist/commands/vouch/sample/print.js.map +1 -0
  291. package/dist/commands/vouch/vet/verify.js +123 -0
  292. package/dist/commands/vouch/vet/verify.js.map +1 -0
  293. package/dist/commands/vouch/vouch.js +176 -0
  294. package/dist/commands/vouch/vouch.js.map +1 -0
  295. package/dist/core/agent/agents-md/artifacts.js +220 -0
  296. package/dist/core/agent/agents-md/artifacts.js.map +1 -0
  297. package/dist/core/agent/agents-md/command-map.js +324 -0
  298. package/dist/core/agent/agents-md/command-map.js.map +1 -0
  299. package/dist/core/agent/agents-md/cycle.js +165 -0
  300. package/dist/core/agent/agents-md/cycle.js.map +1 -0
  301. package/dist/core/agent/agents-md/map/explain.js +34 -0
  302. package/dist/core/agent/agents-md/map/explain.js.map +1 -0
  303. package/dist/core/agent/agents-md/map/lenses/context.js +41 -0
  304. package/dist/core/agent/agents-md/map/lenses/context.js.map +1 -0
  305. package/dist/core/agent/agents-md/map/lenses/diff.js +46 -0
  306. package/dist/core/agent/agents-md/map/lenses/diff.js.map +1 -0
  307. package/dist/core/agent/agents-md/map/lenses/gate.js +57 -0
  308. package/dist/core/agent/agents-md/map/lenses/gate.js.map +1 -0
  309. package/dist/core/agent/agents-md/map/mcp.js +41 -0
  310. package/dist/core/agent/agents-md/map/mcp.js.map +1 -0
  311. package/dist/core/agent/agents-md/map/status.js +62 -0
  312. package/dist/core/agent/agents-md/map/status.js.map +1 -0
  313. package/dist/core/agent/agents-md/map/subsystem.js +32 -0
  314. package/dist/core/agent/agents-md/map/subsystem.js.map +1 -0
  315. package/dist/core/agent/agents-md/map/usecases.js +60 -0
  316. package/dist/core/agent/agents-md/map/usecases.js.map +1 -0
  317. package/dist/core/agent/agents-md/refusals.js +246 -0
  318. package/dist/core/agent/agents-md/refusals.js.map +1 -0
  319. package/dist/core/agent/agents-md/shipped/archive-gate.js +98 -0
  320. package/dist/core/agent/agents-md/shipped/archive-gate.js.map +1 -0
  321. package/dist/core/agent/agents-md/spine.js +40 -0
  322. package/dist/core/agent/agents-md/spine.js.map +1 -0
  323. package/dist/core/agent/agents-md.js +170 -0
  324. package/dist/core/agent/agents-md.js.map +1 -0
  325. package/dist/core/{agents-stamp.js → agent/agents-stamp.js} +50 -0
  326. package/dist/core/agent/agents-stamp.js.map +1 -0
  327. package/dist/core/agent/contract.js +2 -0
  328. package/dist/core/agent/contract.js.map +1 -0
  329. package/dist/core/agent/protocol.js +193 -0
  330. package/dist/core/agent/protocol.js.map +1 -0
  331. package/dist/core/agent/scaffold.js +259 -0
  332. package/dist/core/agent/scaffold.js.map +1 -0
  333. package/dist/core/agent/support/report.js +103 -0
  334. package/dist/core/agent/support/report.js.map +1 -0
  335. package/dist/core/agent/tools/dialects.js +150 -0
  336. package/dist/core/agent/tools/dialects.js.map +1 -0
  337. package/dist/core/agent/tools/registry.js +228 -0
  338. package/dist/core/agent/tools/registry.js.map +1 -0
  339. package/dist/core/agent/workflows/adopt.js +133 -0
  340. package/dist/core/agent/workflows/adopt.js.map +1 -0
  341. package/dist/core/agent/workflows/check.js +337 -0
  342. package/dist/core/agent/workflows/check.js.map +1 -0
  343. package/dist/core/agent/workflows/closing.js +262 -0
  344. package/dist/core/agent/workflows/closing.js.map +1 -0
  345. package/dist/core/agent/workflows/feature.js +105 -0
  346. package/dist/core/agent/workflows/feature.js.map +1 -0
  347. package/dist/core/agent/workflows/implement.js +105 -0
  348. package/dist/core/agent/workflows/implement.js.map +1 -0
  349. package/dist/core/agent/workflows/reference/authoring.js +209 -0
  350. package/dist/core/agent/workflows/reference/authoring.js.map +1 -0
  351. package/dist/core/agent/workflows/reference/codes.js +65 -0
  352. package/dist/core/agent/workflows/reference/codes.js.map +1 -0
  353. package/dist/core/agent/workflows/reference/done-check.js +188 -0
  354. package/dist/core/agent/workflows/reference/done-check.js.map +1 -0
  355. package/dist/core/agent/workflows/reference/reference.js +16 -0
  356. package/dist/core/agent/workflows/reference/reference.js.map +1 -0
  357. package/dist/core/agent/workflows/reference/spine.js +297 -0
  358. package/dist/core/agent/workflows/reference/spine.js.map +1 -0
  359. package/dist/core/asyncapi/baseline/plan.js +110 -0
  360. package/dist/core/asyncapi/baseline/plan.js.map +1 -0
  361. package/dist/core/asyncapi/baseline/surfaces.js +54 -0
  362. package/dist/core/asyncapi/baseline/surfaces.js.map +1 -0
  363. package/dist/core/asyncapi/depth.js +164 -0
  364. package/dist/core/asyncapi/depth.js.map +1 -0
  365. package/dist/core/asyncapi/digest.js +141 -0
  366. package/dist/core/asyncapi/digest.js.map +1 -0
  367. package/dist/core/asyncapi/merge/components.js +91 -0
  368. package/dist/core/asyncapi/merge/components.js.map +1 -0
  369. package/dist/core/asyncapi/merge/error.js +33 -0
  370. package/dist/core/asyncapi/merge/error.js.map +1 -0
  371. package/dist/core/asyncapi/merge/markers.js +308 -0
  372. package/dist/core/asyncapi/merge/markers.js.map +1 -0
  373. package/dist/core/asyncapi/merge/merge.js +215 -0
  374. package/dist/core/asyncapi/merge/merge.js.map +1 -0
  375. package/dist/core/asyncapi/merge/pin.js +107 -0
  376. package/dist/core/asyncapi/merge/pin.js.map +1 -0
  377. package/dist/core/asyncapi/model.js +11 -0
  378. package/dist/core/asyncapi/model.js.map +1 -0
  379. package/dist/core/asyncapi/producers.js +50 -0
  380. package/dist/core/asyncapi/producers.js.map +1 -0
  381. package/dist/core/{asyncapi.js → asyncapi/read.js} +95 -109
  382. package/dist/core/asyncapi/read.js.map +1 -0
  383. package/dist/core/brief/brief.js +225 -0
  384. package/dist/core/brief/brief.js.map +1 -0
  385. package/dist/core/brief/checks.js +250 -0
  386. package/dist/core/brief/checks.js.map +1 -0
  387. package/dist/core/brief/landscape.js +194 -0
  388. package/dist/core/brief/landscape.js.map +1 -0
  389. package/dist/core/brief/targets.js +226 -0
  390. package/dist/core/brief/targets.js.map +1 -0
  391. package/dist/core/brief/unchecked.js +48 -0
  392. package/dist/core/brief/unchecked.js.map +1 -0
  393. package/dist/core/c4/arch.js +174 -0
  394. package/dist/core/c4/arch.js.map +1 -0
  395. package/dist/core/c4/likec4.js +90 -0
  396. package/dist/core/c4/likec4.js.map +1 -0
  397. package/dist/core/c4/parsed/deployment.js +158 -0
  398. package/dist/core/c4/parsed/deployment.js.map +1 -0
  399. package/dist/core/c4/parsed/dynamic-views.js +132 -0
  400. package/dist/core/c4/parsed/dynamic-views.js.map +1 -0
  401. package/dist/core/c4/parsed/specification.js +78 -0
  402. package/dist/core/c4/parsed/specification.js.map +1 -0
  403. package/dist/core/c4/parsed/values.js +57 -0
  404. package/dist/core/c4/parsed/values.js.map +1 -0
  405. package/dist/core/c4/parsed/view-ids.js +75 -0
  406. package/dist/core/c4/parsed/view-ids.js.map +1 -0
  407. package/dist/core/c4/project/architecture.js +45 -0
  408. package/dist/core/c4/project/architecture.js.map +1 -0
  409. package/dist/core/c4/project/documents.js +58 -0
  410. package/dist/core/c4/project/documents.js.map +1 -0
  411. package/dist/core/c4/project/load.js +187 -0
  412. package/dist/core/c4/project/load.js.map +1 -0
  413. package/dist/core/c4/project/staged.js +220 -0
  414. package/dist/core/c4/project/staged.js.map +1 -0
  415. package/dist/core/c4/resolve/service.js +159 -0
  416. package/dist/core/c4/resolve/service.js.map +1 -0
  417. package/dist/core/c4/resolve/steps.js +144 -0
  418. package/dist/core/c4/resolve/steps.js.map +1 -0
  419. package/dist/core/c4/seed/fleet-file.js +201 -0
  420. package/dist/core/c4/seed/fleet-file.js.map +1 -0
  421. package/dist/core/c4/seed/items.js +91 -0
  422. package/dist/core/c4/seed/items.js.map +1 -0
  423. package/dist/core/c4/seed/stamp.js +48 -0
  424. package/dist/core/c4/seed/stamp.js.map +1 -0
  425. package/dist/core/c4/seed/template.js +109 -0
  426. package/dist/core/c4/seed/template.js.map +1 -0
  427. package/dist/core/c4/source-mask.js +82 -0
  428. package/dist/core/c4/source-mask.js.map +1 -0
  429. package/dist/core/c4/source-scan.js +227 -0
  430. package/dist/core/c4/source-scan.js.map +1 -0
  431. package/dist/core/c4/splice/authored-source.js +101 -0
  432. package/dist/core/c4/splice/authored-source.js.map +1 -0
  433. package/dist/core/c4/splice/contract.js +10 -0
  434. package/dist/core/c4/splice/contract.js.map +1 -0
  435. package/dist/core/c4/splice/delta-blocks.js +139 -0
  436. package/dist/core/c4/splice/delta-blocks.js.map +1 -0
  437. package/dist/core/c4/splice/identity/edges.js +36 -0
  438. package/dist/core/c4/splice/identity/edges.js.map +1 -0
  439. package/dist/core/c4/splice/landscape-merge.js +269 -0
  440. package/dist/core/c4/splice/landscape-merge.js.map +1 -0
  441. package/dist/core/c4/splice/placement.js +194 -0
  442. package/dist/core/c4/splice/placement.js.map +1 -0
  443. package/dist/core/c4/workspace.js +174 -0
  444. package/dist/core/c4/workspace.js.map +1 -0
  445. package/dist/core/capabilities/authoring/notes.js +141 -0
  446. package/dist/core/capabilities/authoring/notes.js.map +1 -0
  447. package/dist/core/capabilities/capabilities.js +124 -0
  448. package/dist/core/capabilities/capabilities.js.map +1 -0
  449. package/dist/core/capabilities/delta/doc.js +50 -0
  450. package/dist/core/capabilities/delta/doc.js.map +1 -0
  451. package/dist/core/capabilities/delta/overlay.js +129 -0
  452. package/dist/core/capabilities/delta/overlay.js.map +1 -0
  453. package/dist/core/capabilities/delta/summary.js +57 -0
  454. package/dist/core/capabilities/delta/summary.js.map +1 -0
  455. package/dist/core/capabilities/delta/tree.js +43 -0
  456. package/dist/core/capabilities/delta/tree.js.map +1 -0
  457. package/dist/core/capabilities/delta/uncovered.js +222 -0
  458. package/dist/core/capabilities/delta/uncovered.js.map +1 -0
  459. package/dist/core/capabilities/findings.js +342 -0
  460. package/dist/core/capabilities/findings.js.map +1 -0
  461. package/dist/core/capabilities/realizes/findings.js +181 -0
  462. package/dist/core/capabilities/realizes/findings.js.map +1 -0
  463. package/dist/core/capabilities/realizes/join.js +143 -0
  464. package/dist/core/capabilities/realizes/join.js.map +1 -0
  465. package/dist/core/capabilities/rollup.js +199 -0
  466. package/dist/core/capabilities/rollup.js.map +1 -0
  467. package/dist/core/capabilities/tree.js +126 -0
  468. package/dist/core/capabilities/tree.js.map +1 -0
  469. package/dist/core/capabilities/usecase-join.js +277 -0
  470. package/dist/core/capabilities/usecase-join.js.map +1 -0
  471. package/dist/core/coherence/authoring/scaffold.js +177 -0
  472. package/dist/core/coherence/authoring/scaffold.js.map +1 -0
  473. package/dist/core/coherence/authoring/sentinels.js +74 -0
  474. package/dist/core/coherence/authoring/sentinels.js.map +1 -0
  475. package/dist/core/coherence/coherence.js +287 -0
  476. package/dist/core/coherence/coherence.js.map +1 -0
  477. package/dist/core/coherence/declared.js +269 -0
  478. package/dist/core/coherence/declared.js.map +1 -0
  479. package/dist/core/coherence/events/declared.js +206 -0
  480. package/dist/core/coherence/events/declared.js.map +1 -0
  481. package/dist/core/coherence/events/events.js +204 -0
  482. package/dist/core/coherence/events/events.js.map +1 -0
  483. package/dist/core/coherence/events/grades.js +166 -0
  484. package/dist/core/coherence/events/grades.js.map +1 -0
  485. package/dist/core/coherence/events/lookups.js +122 -0
  486. package/dist/core/coherence/events/lookups.js.map +1 -0
  487. package/dist/core/coherence/events/merged.js +40 -0
  488. package/dist/core/coherence/events/merged.js.map +1 -0
  489. package/dist/core/coherence/living.js +198 -0
  490. package/dist/core/coherence/living.js.map +1 -0
  491. package/dist/core/coherence/lookups.js +155 -0
  492. package/dist/core/coherence/lookups.js.map +1 -0
  493. package/dist/core/coherence/pending.js +39 -0
  494. package/dist/core/coherence/pending.js.map +1 -0
  495. package/dist/core/conflict-markers.js +60 -0
  496. package/dist/core/conflict-markers.js.map +1 -0
  497. package/dist/core/delta/claims.js +73 -0
  498. package/dist/core/delta/claims.js.map +1 -0
  499. package/dist/core/delta/delta.js +296 -0
  500. package/dist/core/delta/delta.js.map +1 -0
  501. package/dist/core/delta/document.js +177 -0
  502. package/dist/core/delta/document.js.map +1 -0
  503. package/dist/core/delta/scope.js +48 -0
  504. package/dist/core/delta/scope.js.map +1 -0
  505. package/dist/core/delta/select.js +237 -0
  506. package/dist/core/delta/select.js.map +1 -0
  507. package/dist/core/dependencies/dependencies.js +141 -0
  508. package/dist/core/dependencies/dependencies.js.map +1 -0
  509. package/dist/core/dependencies/facts.js +165 -0
  510. package/dist/core/dependencies/facts.js.map +1 -0
  511. package/dist/core/dependencies/fanin.js +88 -0
  512. package/dist/core/dependencies/fanin.js.map +1 -0
  513. package/dist/core/dependencies/graph.js +106 -0
  514. package/dist/core/dependencies/graph.js.map +1 -0
  515. package/dist/core/deployment/delta.js +188 -0
  516. package/dist/core/deployment/delta.js.map +1 -0
  517. package/dist/core/deployment/objects.js +145 -0
  518. package/dist/core/deployment/objects.js.map +1 -0
  519. package/dist/core/diff/base-git.js +148 -0
  520. package/dist/core/diff/base-git.js.map +1 -0
  521. package/dist/core/diff/base-state.js +209 -0
  522. package/dist/core/diff/base-state.js.map +1 -0
  523. package/dist/core/diff/current-state.js +96 -0
  524. package/dist/core/diff/current-state.js.map +1 -0
  525. package/dist/core/diff/scope/changed-paths.js +188 -0
  526. package/dist/core/diff/scope/changed-paths.js.map +1 -0
  527. package/dist/core/diff/semantic.js +243 -0
  528. package/dist/core/diff/semantic.js.map +1 -0
  529. package/dist/core/diff/victims.js +247 -0
  530. package/dist/core/diff/victims.js.map +1 -0
  531. package/dist/core/docs.js +7 -64
  532. package/dist/core/docs.js.map +1 -1
  533. package/dist/core/doctor/agents.js +222 -0
  534. package/dist/core/doctor/agents.js.map +1 -0
  535. package/dist/core/doctor/config.js +135 -0
  536. package/dist/core/doctor/config.js.map +1 -0
  537. package/dist/core/doctor/doctor.js +275 -0
  538. package/dist/core/doctor/doctor.js.map +1 -0
  539. package/dist/core/doctor/report.js +13 -0
  540. package/dist/core/doctor/report.js.map +1 -0
  541. package/dist/core/doctor/residue.js +110 -0
  542. package/dist/core/doctor/residue.js.map +1 -0
  543. package/dist/core/document/apply.js +77 -0
  544. package/dist/core/document/apply.js.map +1 -0
  545. package/dist/core/{frontmatter.js → document/frontmatter.js} +48 -2
  546. package/dist/core/document/frontmatter.js.map +1 -0
  547. package/dist/core/document/grammar/directives.js +143 -0
  548. package/dist/core/document/grammar/directives.js.map +1 -0
  549. package/dist/core/document/parse.js +263 -0
  550. package/dist/core/document/parse.js.map +1 -0
  551. package/dist/core/document/scenarios.js +221 -0
  552. package/dist/core/document/scenarios.js.map +1 -0
  553. package/dist/core/document/spec.js +241 -0
  554. package/dist/core/document/spec.js.map +1 -0
  555. package/dist/core/{config.js → envelope/config.js} +79 -18
  556. package/dist/core/envelope/config.js.map +1 -0
  557. package/dist/core/envelope/json.js +175 -0
  558. package/dist/core/envelope/json.js.map +1 -0
  559. package/dist/core/{version.js → envelope/version.js} +3 -3
  560. package/dist/core/envelope/version.js.map +1 -0
  561. package/dist/core/explain/families.js +175 -0
  562. package/dist/core/explain/families.js.map +1 -0
  563. package/dist/core/explain/fix-tables.js +178 -0
  564. package/dist/core/explain/fix-tables.js.map +1 -0
  565. package/dist/core/explain/lookup.js +181 -0
  566. package/dist/core/explain/lookup.js.map +1 -0
  567. package/dist/core/explain/refusals.js +49 -0
  568. package/dist/core/explain/refusals.js.map +1 -0
  569. package/dist/core/explain/terms.js +144 -0
  570. package/dist/core/explain/terms.js.map +1 -0
  571. package/dist/core/explore/describe.js +105 -0
  572. package/dist/core/explore/describe.js.map +1 -0
  573. package/dist/core/{explore.js → explore/explore.js} +50 -101
  574. package/dist/core/explore/explore.js.map +1 -0
  575. package/dist/core/fleet-context.js +120 -78
  576. package/dist/core/fleet-context.js.map +1 -1
  577. package/dist/core/gate/checks.js +201 -0
  578. package/dist/core/gate/checks.js.map +1 -0
  579. package/dist/core/gate/partners.js +205 -0
  580. package/dist/core/gate/partners.js.map +1 -0
  581. package/dist/core/gate/report.js +47 -0
  582. package/dist/core/gate/report.js.map +1 -0
  583. package/dist/core/gate/verification.js +113 -0
  584. package/dist/core/gate/verification.js.map +1 -0
  585. package/dist/core/gherkin/digest.js +60 -0
  586. package/dist/core/gherkin/digest.js.map +1 -0
  587. package/dist/core/gherkin/emit.js +177 -0
  588. package/dist/core/gherkin/emit.js.map +1 -0
  589. package/dist/core/gherkin/read.js +76 -0
  590. package/dist/core/gherkin/read.js.map +1 -0
  591. package/dist/core/gherkin/stale.js +234 -0
  592. package/dist/core/gherkin/stale.js.map +1 -0
  593. package/dist/core/gherkin/stamp.js +77 -0
  594. package/dist/core/gherkin/stamp.js.map +1 -0
  595. package/dist/core/gherkin/steps/catalogue.js +154 -0
  596. package/dist/core/gherkin/steps/catalogue.js.map +1 -0
  597. package/dist/core/gherkin/steps/inventory.js +98 -0
  598. package/dist/core/gherkin/steps/inventory.js.map +1 -0
  599. package/dist/core/gherkin/steps/phrase.js +72 -0
  600. package/dist/core/gherkin/steps/phrase.js.map +1 -0
  601. package/dist/core/glossary/delta.js +106 -0
  602. package/dist/core/glossary/delta.js.map +1 -0
  603. package/dist/core/glossary/tree.js +86 -0
  604. package/dist/core/glossary/tree.js.map +1 -0
  605. package/dist/core/kernel/concurrency.js.map +1 -0
  606. package/dist/core/{document-bytes.js → kernel/document-bytes.js} +1 -1
  607. package/dist/core/kernel/document-bytes.js.map +1 -0
  608. package/dist/core/kernel/fences.js +42 -0
  609. package/dist/core/kernel/fences.js.map +1 -0
  610. package/dist/core/kernel/ids/capability.js +72 -0
  611. package/dist/core/kernel/ids/capability.js.map +1 -0
  612. package/dist/core/kernel/ids/dirs.js +33 -0
  613. package/dist/core/kernel/ids/dirs.js.map +1 -0
  614. package/dist/core/kernel/ids/feature.js +75 -0
  615. package/dist/core/kernel/ids/feature.js.map +1 -0
  616. package/dist/core/kernel/ids/service.js +156 -0
  617. package/dist/core/kernel/ids/service.js.map +1 -0
  618. package/dist/core/kernel/ids/subsystem.js +63 -0
  619. package/dist/core/kernel/ids/subsystem.js.map +1 -0
  620. package/dist/core/{path-safety.js → kernel/path-safety.js} +18 -4
  621. package/dist/core/kernel/path-safety.js.map +1 -0
  622. package/dist/core/kernel/records.js.map +1 -0
  623. package/dist/core/links/backlinks.js +68 -0
  624. package/dist/core/links/backlinks.js.map +1 -0
  625. package/dist/core/links/case.js +74 -0
  626. package/dist/core/links/case.js.map +1 -0
  627. package/dist/core/links/corpus.js +104 -0
  628. package/dist/core/links/corpus.js.map +1 -0
  629. package/dist/core/links/findings.js +110 -0
  630. package/dist/core/links/findings.js.map +1 -0
  631. package/dist/core/links/parse.js +236 -0
  632. package/dist/core/links/parse.js.map +1 -0
  633. package/dist/core/mcp/argv.js +111 -0
  634. package/dist/core/mcp/argv.js.map +1 -0
  635. package/dist/core/mcp/author-tools.js +72 -0
  636. package/dist/core/mcp/author-tools.js.map +1 -0
  637. package/dist/core/mcp/framing.js +46 -0
  638. package/dist/core/mcp/framing.js.map +1 -0
  639. package/dist/core/mcp/protocol.js +280 -0
  640. package/dist/core/mcp/protocol.js.map +1 -0
  641. package/dist/core/mcp/tools.js +314 -0
  642. package/dist/core/mcp/tools.js.map +1 -0
  643. package/dist/core/obligations/obligations.js +106 -0
  644. package/dist/core/obligations/obligations.js.map +1 -0
  645. package/dist/core/openapi/baseline/gate.js +166 -0
  646. package/dist/core/openapi/baseline/gate.js.map +1 -0
  647. package/dist/core/openapi/baseline/plan.js +112 -0
  648. package/dist/core/openapi/baseline/plan.js.map +1 -0
  649. package/dist/core/openapi/baseline/record.js +175 -0
  650. package/dist/core/openapi/baseline/record.js.map +1 -0
  651. package/dist/core/openapi/depth.js +122 -0
  652. package/dist/core/openapi/depth.js.map +1 -0
  653. package/dist/core/openapi/digest.js +189 -0
  654. package/dist/core/openapi/digest.js.map +1 -0
  655. package/dist/core/{openapi.js → openapi/doc.js} +44 -106
  656. package/dist/core/openapi/doc.js.map +1 -0
  657. package/dist/core/openapi/merge/components.js +234 -0
  658. package/dist/core/openapi/merge/components.js.map +1 -0
  659. package/dist/core/openapi/merge/error.js +26 -0
  660. package/dist/core/openapi/merge/error.js.map +1 -0
  661. package/dist/core/openapi/merge/markers.js +208 -0
  662. package/dist/core/openapi/merge/markers.js.map +1 -0
  663. package/dist/core/openapi/merge/merge.js +256 -0
  664. package/dist/core/openapi/merge/merge.js.map +1 -0
  665. package/dist/core/openapi/merge/pin.js +128 -0
  666. package/dist/core/openapi/merge/pin.js.map +1 -0
  667. package/dist/core/openspec/decide/capabilities.js +244 -0
  668. package/dist/core/openspec/decide/capabilities.js.map +1 -0
  669. package/dist/core/openspec/decide/dispositions.js +63 -0
  670. package/dist/core/openspec/decide/dispositions.js.map +1 -0
  671. package/dist/core/openspec/decide/renames.js +179 -0
  672. package/dist/core/openspec/decide/renames.js.map +1 -0
  673. package/dist/core/openspec/decide/verdict.js +84 -0
  674. package/dist/core/openspec/decide/verdict.js.map +1 -0
  675. package/dist/core/openspec/inventory.js +221 -0
  676. package/dist/core/openspec/inventory.js.map +1 -0
  677. package/dist/core/openspec/model/mapping.js +76 -0
  678. package/dist/core/openspec/model/mapping.js.map +1 -0
  679. package/dist/core/openspec/model/model.js +65 -0
  680. package/dist/core/openspec/model/model.js.map +1 -0
  681. package/dist/core/openspec/scan/changes.js +235 -0
  682. package/dist/core/openspec/scan/changes.js.map +1 -0
  683. package/dist/core/openspec/scan/config.js +200 -0
  684. package/dist/core/openspec/scan/config.js.map +1 -0
  685. package/dist/core/openspec/scan/shape.js +260 -0
  686. package/dist/core/openspec/scan/shape.js.map +1 -0
  687. package/dist/core/openspec/scan/walk.js +133 -0
  688. package/dist/core/openspec/scan/walk.js.map +1 -0
  689. package/dist/core/openspec/scan/workspace.js +71 -0
  690. package/dist/core/openspec/scan/workspace.js.map +1 -0
  691. package/dist/core/owners/codeowners.js +141 -0
  692. package/dist/core/owners/codeowners.js.map +1 -0
  693. package/dist/core/pack/features.js +120 -0
  694. package/dist/core/pack/features.js.map +1 -0
  695. package/dist/core/pack/joins.js +112 -0
  696. package/dist/core/pack/joins.js.map +1 -0
  697. package/dist/core/pack/living.js +137 -0
  698. package/dist/core/pack/living.js.map +1 -0
  699. package/dist/core/pack/pack.js +76 -0
  700. package/dist/core/pack/pack.js.map +1 -0
  701. package/dist/core/permissions/permissions.js +87 -0
  702. package/dist/core/permissions/permissions.js.map +1 -0
  703. package/dist/core/projection/api.js +84 -0
  704. package/dist/core/projection/api.js.map +1 -0
  705. package/dist/core/projection/arch-slice.js +63 -0
  706. package/dist/core/projection/arch-slice.js.map +1 -0
  707. package/dist/core/projection/events.js +34 -0
  708. package/dist/core/projection/events.js.map +1 -0
  709. package/dist/core/provenance/findings.js +208 -0
  710. package/dist/core/provenance/findings.js.map +1 -0
  711. package/dist/core/provenance/git.js +225 -0
  712. package/dist/core/provenance/git.js.map +1 -0
  713. package/dist/core/provenance/gitq/moves.js +182 -0
  714. package/dist/core/provenance/gitq/moves.js.map +1 -0
  715. package/dist/core/provenance/gitq/vouched-ancestor.js +179 -0
  716. package/dist/core/provenance/gitq/vouched-ancestor.js.map +1 -0
  717. package/dist/core/provenance/sample/scope.js +238 -0
  718. package/dist/core/provenance/sample/scope.js.map +1 -0
  719. package/dist/core/provenance/sample/sections.js +61 -0
  720. package/dist/core/provenance/sample/sections.js.map +1 -0
  721. package/dist/core/provenance/sources.js +263 -0
  722. package/dist/core/provenance/sources.js.map +1 -0
  723. package/dist/core/provenance/stamp.js +232 -0
  724. package/dist/core/provenance/stamp.js.map +1 -0
  725. package/dist/core/provenance/walk.js +157 -0
  726. package/dist/core/provenance/walk.js.map +1 -0
  727. package/dist/core/repo/authored/paths.js +210 -0
  728. package/dist/core/repo/authored/paths.js.map +1 -0
  729. package/dist/core/repo/entries.js +126 -0
  730. package/dist/core/repo/entries.js.map +1 -0
  731. package/dist/core/repo/paths.js +277 -0
  732. package/dist/core/repo/paths.js.map +1 -0
  733. package/dist/core/repo/repo.js +248 -0
  734. package/dist/core/repo/repo.js.map +1 -0
  735. package/dist/core/repo/service-target.js +153 -0
  736. package/dist/core/repo/service-target.js.map +1 -0
  737. package/dist/core/repo/state.js +58 -0
  738. package/dist/core/repo/state.js.map +1 -0
  739. package/dist/core/repo/tree/find.js +52 -0
  740. package/dist/core/repo/tree/find.js.map +1 -0
  741. package/dist/core/repo/tree/fs.js +64 -0
  742. package/dist/core/repo/tree/fs.js.map +1 -0
  743. package/dist/core/repo/tree/marker.js +61 -0
  744. package/dist/core/repo/tree/marker.js.map +1 -0
  745. package/dist/core/repo/tree/views.js +172 -0
  746. package/dist/core/repo/tree/views.js.map +1 -0
  747. package/dist/core/repo/tree/walk.js +234 -0
  748. package/dist/core/repo/tree/walk.js.map +1 -0
  749. package/dist/core/results.js +99 -2
  750. package/dist/core/results.js.map +1 -1
  751. package/dist/core/scaffold/landscape.js +131 -0
  752. package/dist/core/scaffold/landscape.js.map +1 -0
  753. package/dist/core/scaffold/readme.js +84 -0
  754. package/dist/core/scaffold/readme.js.map +1 -0
  755. package/dist/core/staging/commit.js +241 -0
  756. package/dist/core/staging/commit.js.map +1 -0
  757. package/dist/core/staging/interrupted.js +96 -0
  758. package/dist/core/staging/interrupted.js.map +1 -0
  759. package/dist/core/staging/lock.js +206 -0
  760. package/dist/core/staging/lock.js.map +1 -0
  761. package/dist/core/staging/recovery/finding.js +35 -0
  762. package/dist/core/staging/recovery/finding.js.map +1 -0
  763. package/dist/core/staging/recovery/intent.js +98 -0
  764. package/dist/core/staging/recovery/intent.js.map +1 -0
  765. package/dist/core/staging/recovery/recover.js +126 -0
  766. package/dist/core/staging/recovery/recover.js.map +1 -0
  767. package/dist/core/staging/recovery/residue.js +62 -0
  768. package/dist/core/staging/recovery/residue.js.map +1 -0
  769. package/dist/core/staging/snapshot.js +202 -0
  770. package/dist/core/staging/snapshot.js.map +1 -0
  771. package/dist/core/staging/txn/forward.js +171 -0
  772. package/dist/core/staging/txn/forward.js.map +1 -0
  773. package/dist/core/staging/txn/journal.js +139 -0
  774. package/dist/core/staging/txn/journal.js.map +1 -0
  775. package/dist/core/staging/txn/transaction.js +75 -0
  776. package/dist/core/staging/txn/transaction.js.map +1 -0
  777. package/dist/core/staging/writes.js +113 -0
  778. package/dist/core/staging/writes.js.map +1 -0
  779. package/dist/core/status/actions/execution.js +49 -0
  780. package/dist/core/status/actions/execution.js.map +1 -0
  781. package/dist/core/status/contracts.js +102 -0
  782. package/dist/core/status/contracts.js.map +1 -0
  783. package/dist/core/status/feature/artifacts.js +196 -0
  784. package/dist/core/status/feature/artifacts.js.map +1 -0
  785. package/dist/core/status/feature/feature.js +207 -0
  786. package/dist/core/status/feature/feature.js.map +1 -0
  787. package/dist/core/status/feature/next.js +150 -0
  788. package/dist/core/status/feature/next.js.map +1 -0
  789. package/dist/core/status/feature/state.js +21 -0
  790. package/dist/core/status/feature/state.js.map +1 -0
  791. package/dist/core/status/fleet/fleet.js +197 -0
  792. package/dist/core/status/fleet/fleet.js.map +1 -0
  793. package/dist/core/status/fleet/next.js +207 -0
  794. package/dist/core/status/fleet/next.js.map +1 -0
  795. package/dist/core/status/interrupted.js +97 -0
  796. package/dist/core/status/interrupted.js.map +1 -0
  797. package/dist/core/status/report.js +31 -0
  798. package/dist/core/status/report.js.map +1 -0
  799. package/dist/core/status/scan.js +41 -0
  800. package/dist/core/status/scan.js.map +1 -0
  801. package/dist/core/status/verification.js +201 -0
  802. package/dist/core/status/verification.js.map +1 -0
  803. package/dist/core/usecases/capability.js +169 -0
  804. package/dist/core/usecases/capability.js.map +1 -0
  805. package/dist/core/usecases/delta/claims.js +116 -0
  806. package/dist/core/usecases/delta/claims.js.map +1 -0
  807. package/dist/core/usecases/delta/flows.js +103 -0
  808. package/dist/core/usecases/delta/flows.js.map +1 -0
  809. package/dist/core/usecases/delta/overlay.js +72 -0
  810. package/dist/core/usecases/delta/overlay.js.map +1 -0
  811. package/dist/core/usecases/fleet.js +137 -0
  812. package/dist/core/usecases/fleet.js.map +1 -0
  813. package/dist/core/usecases/operations.js +111 -0
  814. package/dist/core/usecases/operations.js.map +1 -0
  815. package/dist/core/usecases/place.js +44 -0
  816. package/dist/core/usecases/place.js.map +1 -0
  817. package/dist/core/usecases/touch.js +101 -0
  818. package/dist/core/usecases/touch.js.map +1 -0
  819. package/dist/core/verify/answers.js +173 -0
  820. package/dist/core/verify/answers.js.map +1 -0
  821. package/dist/core/verify/build.js +150 -0
  822. package/dist/core/verify/build.js.map +1 -0
  823. package/dist/core/verify/checklist.js +201 -0
  824. package/dist/core/verify/checklist.js.map +1 -0
  825. package/dist/core/verify/claims/identity.js +61 -0
  826. package/dist/core/verify/claims/identity.js.map +1 -0
  827. package/dist/core/verify/cross/diff.js +97 -0
  828. package/dist/core/verify/cross/diff.js.map +1 -0
  829. package/dist/core/verify/evidence/contract.js +169 -0
  830. package/dist/core/verify/evidence/contract.js.map +1 -0
  831. package/dist/core/verify/file.js +257 -0
  832. package/dist/core/verify/file.js.map +1 -0
  833. package/dist/core/verify/pins/lint.js +157 -0
  834. package/dist/core/verify/pins/lint.js.map +1 -0
  835. package/dist/core/verify/pins/pin.js +95 -0
  836. package/dist/core/verify/pins/pin.js.map +1 -0
  837. package/dist/core/verify/record.js +142 -0
  838. package/dist/core/verify/record.js.map +1 -0
  839. package/dist/core/verify/store/commit.js +89 -0
  840. package/dist/core/verify/store/commit.js.map +1 -0
  841. package/dist/core/verify/store/render.js +57 -0
  842. package/dist/core/verify/store/render.js.map +1 -0
  843. package/dist/core/vocabulary/health.js +91 -0
  844. package/dist/core/vocabulary/health.js.map +1 -0
  845. package/dist/core/vocabulary/issue.js +58 -0
  846. package/dist/core/vocabulary/issue.js.map +1 -0
  847. package/dist/core/vocabulary/maturity.js +145 -0
  848. package/dist/core/vocabulary/maturity.js.map +1 -0
  849. package/dist/core/{report.js → vocabulary/report.js} +30 -2
  850. package/dist/core/vocabulary/report.js.map +1 -0
  851. package/dist/core/vocabulary/steps.js +266 -0
  852. package/dist/core/vocabulary/steps.js.map +1 -0
  853. package/dist/core/workspace/discover.js +239 -0
  854. package/dist/core/workspace/discover.js.map +1 -0
  855. package/dist/core/workspace/render.js +52 -0
  856. package/dist/core/workspace/render.js.map +1 -0
  857. package/examples/README.md +189 -0
  858. package/examples/docs/architecture/adrs/0001-transactional-outbox.md +33 -0
  859. package/examples/docs/architecture/capabilities.yaml +31 -0
  860. package/examples/docs/architecture/landscape.likec4 +280 -0
  861. package/examples/docs/architecture/obligations.yaml +23 -0
  862. package/examples/docs/architecture/permissions.yaml +50 -0
  863. package/examples/docs/architecture/subsystems.likec4 +11 -0
  864. package/examples/docs/architecture/usecases/order-notification.likec4 +65 -0
  865. package/examples/docs/capabilities/checkout/spec.md +55 -0
  866. package/examples/docs/capabilities/identity/tokens/spec.md +42 -0
  867. package/examples/docs/capabilities/order-notifications/spec.md +43 -0
  868. package/examples/docs/features/FEAT-101-payment-splitting/adrs/0001-dedicated-split-service.md +18 -0
  869. package/examples/docs/features/FEAT-101-payment-splitting/delta.likec4 +94 -0
  870. package/examples/docs/features/FEAT-101-payment-splitting/intent.md +44 -0
  871. package/examples/docs/features/FEAT-101-payment-splitting/specs/checkout-web/spec.md +21 -0
  872. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-service/asyncapi.yaml +129 -0
  873. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-service/spec.md +36 -0
  874. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/arch.spec.md +40 -0
  875. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/openapi.yaml +116 -0
  876. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/spec.md +55 -0
  877. package/examples/docs/features/FEAT-112-retire-order-v1/intent.md +35 -0
  878. package/examples/docs/features/FEAT-112-retire-order-v1/specs/order-service/openapi.yaml +28 -0
  879. package/examples/docs/features/FEAT-112-retire-order-v1/specs/order-service/spec.md +17 -0
  880. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/architecture/landscape.likec4 +253 -0
  881. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/services/order-service/spec.md +121 -0
  882. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/services/payment-service/openapi.yaml +111 -0
  883. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/services/payment-service/spec.md +58 -0
  884. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/manifest.json +32 -0
  885. package/examples/docs/features/archive/FEAT-088-refunds/adrs/0001-refunds-stay-in-payment-service.md +26 -0
  886. package/examples/docs/features/archive/FEAT-088-refunds/delta.likec4 +28 -0
  887. package/examples/docs/features/archive/FEAT-088-refunds/intent.md +26 -0
  888. package/examples/docs/features/archive/FEAT-088-refunds/specs/order-service/spec.md +37 -0
  889. package/examples/docs/features/archive/FEAT-088-refunds/specs/payment-service/openapi.yaml +70 -0
  890. package/examples/docs/features/archive/FEAT-088-refunds/specs/payment-service/spec.md +23 -0
  891. package/examples/docs/features/archive/FEAT-088-refunds/verification.yaml +76 -0
  892. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/architecture/landscape.likec4 +275 -0
  893. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/payment-service/asyncapi.yaml +96 -0
  894. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/payment-service/spec.md +82 -0
  895. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/platform/notification-service/asyncapi.yaml +164 -0
  896. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/platform/notification-service/spec.md +91 -0
  897. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/manifest.json +46 -0
  898. package/examples/docs/features/archive/FEAT-120-refund-notification/delta.likec4 +36 -0
  899. package/examples/docs/features/archive/FEAT-120-refund-notification/intent.md +22 -0
  900. package/examples/docs/features/archive/FEAT-120-refund-notification/scenario-report.json +10 -0
  901. package/examples/docs/features/archive/FEAT-120-refund-notification/specs/notification-service/asyncapi.yaml +208 -0
  902. package/examples/docs/features/archive/FEAT-120-refund-notification/specs/notification-service/spec.md +24 -0
  903. package/examples/docs/features/archive/FEAT-120-refund-notification/specs/payment-service/asyncapi.yaml +137 -0
  904. package/examples/docs/features/archive/FEAT-120-refund-notification/specs/payment-service/spec.md +31 -0
  905. package/examples/docs/features/archive/FEAT-120-refund-notification/verification.yaml +84 -0
  906. package/examples/docs/glossary/order.md +15 -0
  907. package/examples/docs/glossary/payments/authorization.md +14 -0
  908. package/examples/docs/likec4.config.json +9 -0
  909. package/examples/docs/loam.json +3 -0
  910. package/examples/docs/services/checkout-web/model.likec4 +109 -0
  911. package/examples/docs/services/checkout-web/spec.md +91 -0
  912. package/examples/docs/services/checkout-web/ui/pages/checkout.page.yaml +40 -0
  913. package/examples/docs/services/checkout-web/ui/pages/order-status.page.yaml +24 -0
  914. package/examples/docs/services/checkout-web/ui/pages/split-payment.page.yaml +26 -0
  915. package/examples/docs/services/order-service/adrs/0001-orchestrated-order-lifecycle.md +52 -0
  916. package/examples/docs/services/order-service/arch.spec.md +127 -0
  917. package/examples/docs/services/order-service/asyncapi.yaml +108 -0
  918. package/examples/docs/services/order-service/health.yaml +57 -0
  919. package/examples/docs/services/order-service/model.likec4 +138 -0
  920. package/examples/docs/services/order-service/openapi.yaml +257 -0
  921. package/examples/docs/services/order-service/runbook.md +62 -0
  922. package/examples/docs/services/order-service/spec.md +134 -0
  923. package/examples/docs/services/payment-service/adrs/0001-payments-outbox.md +18 -0
  924. package/examples/docs/services/payment-service/adrs/0002-idempotency-keys-on-authorization.md +27 -0
  925. package/examples/docs/services/payment-service/arch.spec.md +73 -0
  926. package/examples/docs/services/payment-service/asyncapi.yaml +130 -0
  927. package/examples/docs/services/payment-service/health.yaml +39 -0
  928. package/examples/docs/services/payment-service/model.likec4 +67 -0
  929. package/examples/docs/services/payment-service/openapi.yaml +151 -0
  930. package/examples/docs/services/payment-service/runbook.md +37 -0
  931. package/examples/docs/services/payment-service/spec.md +88 -0
  932. package/examples/docs/services/platform/identity-service/adrs/0001-token-introspection-over-local-validation.md +60 -0
  933. package/examples/docs/services/platform/identity-service/arch.spec.md +117 -0
  934. package/examples/docs/services/platform/identity-service/health.yaml +70 -0
  935. package/examples/docs/services/platform/identity-service/model.likec4 +83 -0
  936. package/examples/docs/services/platform/identity-service/openapi.yaml +197 -0
  937. package/examples/docs/services/platform/identity-service/runbook.md +95 -0
  938. package/examples/docs/services/platform/identity-service/spec.md +119 -0
  939. package/examples/docs/services/platform/notification-service/asyncapi.yaml +199 -0
  940. package/examples/docs/services/platform/notification-service/health.yaml +35 -0
  941. package/examples/docs/services/platform/notification-service/model.likec4 +118 -0
  942. package/examples/docs/services/platform/notification-service/runbook.md +48 -0
  943. package/examples/docs/services/platform/notification-service/spec.md +112 -0
  944. package/examples/docs/services/platform/subsystem.yaml +2 -0
  945. package/examples/fleet.yaml +57 -0
  946. package/package.json +19 -6
  947. package/dist/commands/adopt.js +0 -240
  948. package/dist/commands/adopt.js.map +0 -1
  949. package/dist/commands/archive.js +0 -1313
  950. package/dist/commands/archive.js.map +0 -1
  951. package/dist/commands/delta.js +0 -388
  952. package/dist/commands/delta.js.map +0 -1
  953. package/dist/commands/docs-repo-gate.js.map +0 -1
  954. package/dist/commands/format.js +0 -17
  955. package/dist/commands/format.js.map +0 -1
  956. package/dist/commands/gherkin.js +0 -309
  957. package/dist/commands/gherkin.js.map +0 -1
  958. package/dist/commands/init.js.map +0 -1
  959. package/dist/commands/list.js +0 -295
  960. package/dist/commands/list.js.map +0 -1
  961. package/dist/commands/migrate-openspec.js +0 -950
  962. package/dist/commands/migrate-openspec.js.map +0 -1
  963. package/dist/commands/new.js +0 -413
  964. package/dist/commands/new.js.map +0 -1
  965. package/dist/commands/rebase.js +0 -356
  966. package/dist/commands/rebase.js.map +0 -1
  967. package/dist/commands/show.js.map +0 -1
  968. package/dist/commands/status.js +0 -262
  969. package/dist/commands/status.js.map +0 -1
  970. package/dist/commands/unarchive.js.map +0 -1
  971. package/dist/commands/validate.js +0 -1773
  972. package/dist/commands/validate.js.map +0 -1
  973. package/dist/commands/verify.js +0 -775
  974. package/dist/commands/verify.js.map +0 -1
  975. package/dist/commands/vouch.js +0 -421
  976. package/dist/commands/vouch.js.map +0 -1
  977. package/dist/core/agent.js +0 -2173
  978. package/dist/core/agent.js.map +0 -1
  979. package/dist/core/agents-stamp.js.map +0 -1
  980. package/dist/core/arch.js +0 -130
  981. package/dist/core/arch.js.map +0 -1
  982. package/dist/core/asyncapi.js.map +0 -1
  983. package/dist/core/brief.js +0 -755
  984. package/dist/core/brief.js.map +0 -1
  985. package/dist/core/coherence.js +0 -577
  986. package/dist/core/coherence.js.map +0 -1
  987. package/dist/core/concurrency.js.map +0 -1
  988. package/dist/core/config.js.map +0 -1
  989. package/dist/core/delta.js +0 -476
  990. package/dist/core/delta.js.map +0 -1
  991. package/dist/core/dependencies.js +0 -356
  992. package/dist/core/dependencies.js.map +0 -1
  993. package/dist/core/doctor.js +0 -596
  994. package/dist/core/doctor.js.map +0 -1
  995. package/dist/core/document-bytes.js.map +0 -1
  996. package/dist/core/explore.js.map +0 -1
  997. package/dist/core/frontmatter.js.map +0 -1
  998. package/dist/core/gherkin.js +0 -463
  999. package/dist/core/gherkin.js.map +0 -1
  1000. package/dist/core/health.js +0 -67
  1001. package/dist/core/health.js.map +0 -1
  1002. package/dist/core/ids.js +0 -122
  1003. package/dist/core/ids.js.map +0 -1
  1004. package/dist/core/issue.js +0 -9
  1005. package/dist/core/issue.js.map +0 -1
  1006. package/dist/core/json.js +0 -74
  1007. package/dist/core/json.js.map +0 -1
  1008. package/dist/core/likec4.js +0 -489
  1009. package/dist/core/likec4.js.map +0 -1
  1010. package/dist/core/maturity.js +0 -66
  1011. package/dist/core/maturity.js.map +0 -1
  1012. package/dist/core/openapi-merge.js +0 -552
  1013. package/dist/core/openapi-merge.js.map +0 -1
  1014. package/dist/core/openapi.js.map +0 -1
  1015. package/dist/core/openspec-inventory.js +0 -1440
  1016. package/dist/core/openspec-inventory.js.map +0 -1
  1017. package/dist/core/path-safety.js.map +0 -1
  1018. package/dist/core/provenance.js +0 -787
  1019. package/dist/core/provenance.js.map +0 -1
  1020. package/dist/core/records.js.map +0 -1
  1021. package/dist/core/repo.js +0 -438
  1022. package/dist/core/repo.js.map +0 -1
  1023. package/dist/core/report.js.map +0 -1
  1024. package/dist/core/spec.js +0 -505
  1025. package/dist/core/spec.js.map +0 -1
  1026. package/dist/core/staging.js +0 -890
  1027. package/dist/core/staging.js.map +0 -1
  1028. package/dist/core/status.js +0 -1132
  1029. package/dist/core/status.js.map +0 -1
  1030. package/dist/core/steps.js +0 -72
  1031. package/dist/core/steps.js.map +0 -1
  1032. package/dist/core/verify.js +0 -807
  1033. package/dist/core/verify.js.map +0 -1
  1034. package/dist/core/version.js.map +0 -1
  1035. /package/dist/core/{concurrency.js → kernel/concurrency.js} +0 -0
  1036. /package/dist/core/{records.js → kernel/records.js} +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/core/doctor.ts"],"names":[],"mappings":"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","sourcesContent":["/** Read-only installation/repository diagnostics for `loam doctor`. */\nimport { constants, existsSync } from \"node:fs\";\nimport { access, readFile } from \"node:fs/promises\";\nimport { dirname, isAbsolute, join, relative, resolve } from \"node:path\";\nimport { CONFIG_FILENAME, configPath, parseConfig, type LoamConfig } from \"./config.js\";\nimport { LOAM_VERSION } from \"./version.js\";\nimport { agentsPath, docsRepoState, landscapePath, listFeatures, listServices } from \"./repo.js\";\nimport { loadFile } from \"./likec4.js\";\nimport { LIKEC4_PROJECT_CONFIG, LIKEC4_PROJECT_FILENAME } from \"./docs.js\";\nimport { conflictMarkerLines } from \"./fleet-context.js\";\nimport { AGENT_TOOLS, DELIVERIES, plannedCommandFiles, type Delivery } from \"./agent.js\";\nimport {\n agentsStaleFinding,\n agentsStampLine,\n agentsStampVersion,\n versionTrails,\n} from \"./agents-stamp.js\";\nimport { scanWritePathResidue, type WritePathResidue } from \"./staging.js\";\n\nexport type DoctorSeverity = \"blocker\" | \"warning\";\n\nexport interface DoctorFinding {\n severity: DoctorSeverity;\n code: string;\n message: string;\n /**\n * The next command or edit that clears this finding. Mandatory, not optional:\n * a diagnostic that names a problem without naming its fix is a diagnostic\n * the reader has to research, and `doctor` is what someone runs precisely\n * because they do not yet know what loam wants from them.\n */\n fix: string;\n}\n\nexport interface DoctorReport {\n healthy: boolean;\n runtime: {\n package: \"@ybotok/loam\";\n version: string;\n node: string;\n platform: NodeJS.Platform;\n arch: string;\n };\n config: {\n path: string;\n status: \"missing\" | \"invalid\" | \"valid\";\n error: string | null;\n };\n docs: {\n path: string | null;\n exists: boolean;\n readable: boolean;\n writable: boolean;\n servicesDir: boolean;\n landscape: boolean;\n };\n counts: { services: number; activeFeatures: number };\n currentService: {\n configured: string | null;\n status: \"unbound\" | \"matched\" | \"unknown\";\n };\n /** The agent surface of this repo — see `inspectAgentSurface`. */\n agents: AgentSurface;\n /**\n * What a write that did not finish left in the docs repo, or null when\n * `docsDir` never resolved. Reported as state, like `docs` and `counts`: a\n * lock somebody is legitimately holding right now is a fact, not a complaint.\n */\n writePath: WritePathResidue | null;\n findings: DoctorFinding[];\n}\n\nexport interface AgentSurface {\n /** Tool ids this repo has an agent surface for. Empty is legal (`init --no-commands`). */\n tools: string[];\n /** Whether `tools` came from loam.json's own record or from what is on disk. */\n toolsSource: \"config\" | \"disk\";\n /** How many files the running binary would lay down for `tools`. */\n plannedFiles: number;\n /** Repo-relative paths of those files that are not there. */\n missingFiles: string[];\n /**\n * Repo-relative paths of the ones that ARE there carrying no version stamp,\n * or one older than this binary — see `staleAgentFiles`.\n */\n staleFiles: string[];\n stamp: {\n /** Where the docs repo's AGENTS.md is, or null when `docsDir` did not resolve. */\n path: string | null;\n /** Whether it could be read at all — absent and unstamped are different facts. */\n present: boolean;\n /** The version the stamp names, null when there is none (or an unparseable one). */\n version: string | null;\n /** Whether `agents.stale` fired: the stamp is missing or trails this binary. */\n stale: boolean;\n };\n}\n\ninterface ConfigInspection {\n status: DoctorReport[\"config\"][\"status\"];\n config: LoamConfig | null;\n error: string | null;\n}\n\n/**\n * Read and validate the config the way every other command does — through\n * `parseConfig`, never through a second implementation.\n *\n * doctor used to carry its own validator. It agreed with `loadConfig` on the\n * fields both happened to check and disagreed everywhere else: doctor accepted\n * a `gherkinDir` of `\"../shared\"` that `loadConfig` refused outright, so\n * `doctor` reported a healthy repo in which no command could run. Two\n * validators are two opinions about the same file, and the one the user reads\n * is never the one the commands obey.\n */\nasync function inspectConfig(cwd: string): Promise<ConfigInspection> {\n const path = configPath(cwd);\n let raw: string;\n try {\n raw = await readFile(path, \"utf8\");\n } catch (error) {\n const code = (error as NodeJS.ErrnoException).code;\n if (code === \"ENOENT\") return { status: \"missing\", config: null, error: null };\n return {\n status: \"invalid\",\n config: null,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n\n try {\n return { status: \"valid\", error: null, config: parseConfig(raw, dirname(path)) };\n } catch (error) {\n return {\n status: \"invalid\",\n config: null,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n}\n\nasync function canAccess(path: string, mode: number): Promise<boolean> {\n try {\n await access(path, mode);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Read the landscape, don't just stat it. `doctor` reported `landscape: yes`\n * for a file full of conflict markers — the check answered \"is there a file\",\n * which is not the question anyone runs doctor to ask.\n */\nasync function inspectLandscape(path: string, findings: DoctorFinding[]): Promise<void> {\n let source: string;\n try {\n source = await readFile(path, \"utf8\");\n } catch (error) {\n findings.push({\n severity: \"blocker\",\n code: \"doctor.landscape-unreadable\",\n message: `${path} exists but could not be read: ${error instanceof Error ? error.message : String(error)}`,\n fix: `Check permissions on ${path}.`,\n });\n return;\n }\n\n // The three-way merge left its markers in the file. Checked BEFORE the\n // parser, because a conflicted landscape does parse sometimes — both sides of\n // a conflict can be syntactically valid LikeC4 — and \"your map contains two\n // halves of two different maps\" is a more useful sentence than any parser\n // error. This is the failure mode of onboarding a fleet: ten people adopt ten\n // services into one landscape.likec4 in the same week.\n //\n // The scan itself is fleet-context's, which is where the same rule already\n // grades every other document loam reads. doctor kept a second copy of it,\n // and a second copy of a rule is a second chance to spell it differently;\n // what doctor owns is what a conflicted landscape COSTS, which is the finding\n // below and not the search.\n const conflicted = conflictMarkerLines(source);\n if (conflicted.length > 0) {\n findings.push({\n severity: \"blocker\",\n code: \"doctor.landscape-merge-conflict\",\n message:\n `architecture/landscape.likec4 still contains merge conflict markers ` +\n `(line${conflicted.length === 1 ? \"\" : \"s\"} ${conflicted.join(\", \")}).`,\n fix: `Resolve the conflict in ${path} — keep BOTH services' elements and edges, then re-run \\`loam doctor\\`.`,\n });\n return;\n }\n\n const doc = await loadFile(path);\n if (doc.errors.length > 0) {\n const first = doc.errors[0]!;\n findings.push({\n severity: \"blocker\",\n code: \"doctor.landscape-invalid\",\n message:\n `architecture/landscape.likec4 does not parse: ${first.message}` +\n (first.line === undefined ? \"\" : ` (line ${first.line})`) +\n (doc.errors.length > 1 ? ` — and ${doc.errors.length - 1} more` : \"\"),\n fix: `Fix ${path}; every fleet-wide check is blind until it parses.`,\n });\n }\n}\n\n/**\n * The tool ids loam.json records `init` as having written files for, or null\n * when it records none we can plan for.\n *\n * `parseConfig` checks `agentTools`' SHAPE and deliberately not its contents —\n * a config written by a newer binary may name a tool this one has never heard\n * of, and refusing to load it would break every command, not just this check.\n * So the registry filter belongs here: `plannedCommandFiles` throws on an id it\n * does not know, and a config from the future must not turn the read-only\n * preflight into a crash. A tool we cannot plan files for is a tool we have\n * nothing to say about.\n */\nfunction recordedTools(config: LoamConfig | null): string[] | null {\n const ids = (config?.agentTools ?? []).filter((t) => t in AGENT_TOOLS);\n return ids.length === 0 ? null : ids;\n}\n\n/**\n * Which tools this repo has agent files for, asked of the layout itself: a tool\n * counts when any file it would be given is already there.\n *\n * The fallback for a loam.json written before `agentTools` existed, and the\n * only answer a hand-written one can have — so its absence must never be the\n * thing that reports a problem. This asks a narrower question than `init`'s\n * own scan, and on purpose: init scans for a tool's dot-directory to decide\n * what a repo would LIKE, while doctor grades what loam has already put there.\n * A repo that runs Claude Code and took `--no-commands --no-skills` has chosen\n * to have no loam files, and is not behind the binary for it.\n */\nfunction detectedTools(repoRoot: string): string[] {\n return Object.keys(AGENT_TOOLS).filter((id) =>\n plannedCommandFiles(repoRoot, [id]).some((f) => existsSync(f.path)));\n}\n\n/**\n * Which deliveries this repo actually HOLDS for one tool — a delivery counts\n * when at least one of its files is on disk.\n *\n * `loam init --no-skills` (or `--no-commands`) records the tool in `agentTools`\n * and writes one delivery, so planning both and subtracting what exists reported\n * every skill file as missing on a brand-new repo — under a message saying it\n * \"was initialized by an older loam\" and a `fix` that re-runs init without the\n * flag that was the whole point. Which deliveries a repo asked for is written\n * down nowhere, and must not be: the files ARE the record (there is no state\n * file loam can disagree with). So the question is asked of them.\n *\n * A tool with NO files at all is the other story — recorded, then deleted — and\n * the caller falls back to the full plan there, which is what the finding's\n * \"or they were deleted\" already says.\n */\nfunction heldDeliveries(repoRoot: string, tool: string): readonly Delivery[] {\n const held = DELIVERIES.filter((d) =>\n plannedCommandFiles(repoRoot, [tool], [d]).some((f) => existsSync(f.path)));\n return held.length > 0 ? held : DELIVERIES;\n}\n\n/**\n * Of the planned files that ARE here, the ones whose stamp is missing or older\n * than this binary.\n *\n * The stamp is the ONLY thing read out of a generated file — never the body.\n * Comparing bodies would yield \"your file differs from the template\", one step\n * from offering to rewrite it, which is the thing loam refuses: a team's edits\n * to a generated file outrank ours. A stamp is a different claim — it says\n * which loam wrote these instructions — and it can be false while every edit\n * around it is legitimate. Same doctrine as AGENTS.md (agents-stamp.ts), same\n * repair: a human looks, and bumps the stamp or deletes the file so a re-run of\n * `loam init` lays down the current one.\n *\n * Absence of a stamp counts, because that is what every file written before\n * stamping existed looks like — precisely the \"initialized by an older loam\"\n * population this check is for.\n */\nasync function staleAgentFiles(\n repoRoot: string,\n planned: Array<{ path: string }>,\n): Promise<string[]> {\n // Read them together rather than one after another. `planned` is bounded by\n // the tool registry — every delivery of every tool loam knows, a couple of\n // hundred small files — so there is nothing here worth a concurrency cap, and\n // `Promise.all` preserves input order, which is the only property the caller\n // asks of the list it gets back.\n const graded = await Promise.all(planned.map(async (file): Promise<string | null> => {\n let text: string;\n try {\n text = await readFile(file.path, \"utf8\");\n } catch {\n // Unreadable is not stale: it is either the missing-file finding above or\n // a permissions problem, and neither is answered by editing a stamp.\n return null;\n }\n const stamp = agentsStampVersion(text);\n if (stamp === null || versionTrails(stamp, LOAM_VERSION)) {\n return relative(repoRoot, file.path).split(/[\\\\/]/).join(\"/\");\n }\n return null;\n }));\n return graded.filter((p) => p !== null);\n}\n\n/**\n * What the running binary would write for this repo's tools that is not here,\n * and what is here under an older loam's name.\n *\n * Presence is `existsSync`, the same probe `init` uses to compute its `skipped`\n * list, so doctor cannot disagree with init about which files init would write.\n */\nasync function inspectAgentSurface(\n repoRoot: string,\n config: LoamConfig | null,\n docsDir: string | null,\n findings: DoctorFinding[],\n): Promise<AgentSurface> {\n const recorded = recordedTools(config);\n const tools = recorded ?? detectedTools(repoRoot);\n const planned = tools.flatMap((id) =>\n plannedCommandFiles(repoRoot, [id], heldDeliveries(repoRoot, id)));\n const present = planned.filter((f) => existsSync(f.path));\n const missingFiles = planned\n .filter((f) => !existsSync(f.path))\n .map((f) => relative(repoRoot, f.path).split(/[\\\\/]/).join(\"/\"));\n const staleFiles = await staleAgentFiles(repoRoot, present);\n\n if (missingFiles.length > 0) {\n // A warning, never a blocker: an out-of-date command set is a repo whose\n // agents have fewer entry points than they could, not one where anything\n // refuses to run. doctor's blockers are for the second kind.\n //\n // The fix spells `--docs` and `--tools` and deliberately NOT `--service`:\n // `init` spreads the committed config forward, and a `--docs`-less re-run\n // keeps the pointer the repo already commits, so the binding survives\n // untouched. Every interpolation here stands for exactly one argument —\n // test/agent-commands-runnable.test.ts parses this string, and a `${flags}`\n // holding three of them is a command it cannot check.\n findings.push({\n severity: \"warning\",\n code: \"doctor.agent-files-missing\",\n message:\n `${missingFiles.length} of the ${planned.length} command and skill files loam v${LOAM_VERSION} `\n + `lays down for ${tools.join(\", \")} are not in this repo — it was initialized by an older loam, `\n + `or they were deleted: ${missingFiles.join(\", \")}`,\n fix:\n `Re-run \\`loam init --docs ${config?.docsDirAsWritten ?? \"<dir>\"} --tools ${tools.join(\",\")}\\` `\n + \"here — it writes only the files that are absent and leaves every existing one untouched, and \"\n + \"it keeps this repo's service binding. Nothing is regenerated, so leaving this standing costs \"\n + \"entry points and nothing else.\",\n });\n }\n\n if (staleFiles.length > 0) {\n // Also a warning, and for a stronger reason than the one above: these files\n // are the team's now. Only a person can say whether their edits still mean\n // what the current binary's tables say, so loam reports and stops.\n findings.push({\n severity: \"warning\",\n code: \"doctor.agent-files-stale\",\n message:\n `${staleFiles.length} of the ${planned.length} command and skill files here carry no `\n + `\\`${agentsStampLine(LOAM_VERSION)}\\` stamp, or one older than this loam — the protocol and `\n + `code tables they instruct an agent with may describe a loam that no longer exists: `\n + `${staleFiles.join(\", \")}`,\n fix:\n \"Read each against the body this loam writes, then set its stamp line to \"\n + `\\`${agentsStampLine(LOAM_VERSION)}\\`; or delete the file and re-run \\`loam init\\` to lay `\n + \"down the current one. loam never rewrites a file that exists — your edits outrank the \"\n + \"template, which is why the stamp is a human's claim and not a refresh.\",\n });\n }\n\n // AGENTS.md lives in the DOCS repo, not here: it travels with the thing it\n // describes. The comparison is `agentsStaleFinding`'s, not a second copy of\n // it — doctor only adds the `fix` column its own findings owe the reader.\n const agentsFile = docsDir === null ? null : agentsPath(docsDir);\n let agentsText: string | null = null;\n if (agentsFile !== null) {\n try {\n agentsText = await readFile(agentsFile, \"utf8\");\n } catch {\n // Unreadable reads as absent, exactly as `validate --all` treats it: no\n // file, no contract to have drifted. An unreadable docs repo is already\n // its own finding.\n }\n }\n const stale = agentsStaleFinding(agentsText, LOAM_VERSION);\n if (stale !== null) {\n findings.push({\n severity: \"warning\",\n code: stale.code,\n message: stale.message,\n fix:\n `Review ${agentsFile} against the current \\`loam --help\\`, then set its stamp line to `\n + `\\`${agentsStampLine(LOAM_VERSION)}\\`. loam never rewrites that file — bumping the stamp IS `\n + \"the record that somebody looked.\",\n });\n }\n\n return {\n tools,\n toolsSource: recorded === null ? \"disk\" : \"config\",\n plannedFiles: planned.length,\n missingFiles,\n staleFiles,\n stamp: {\n path: agentsFile,\n present: agentsText !== null,\n version: agentsText === null ? null : agentsStampVersion(agentsText),\n stale: stale !== null,\n },\n };\n}\n\n/**\n * Grade what a write that did not finish left in the docs repo.\n *\n * Three of the four are blockers, which is unusual for doctor and deliberate:\n * they are not \"you have fewer entry points than you could\", they are \"the\n * living docs may be half-written and the next reader cannot tell\". Before this\n * existed, a SIGKILL between two of archive's renames left `doctor: healthy:\n * true` over merged spec.md + openapi.yaml and an unmerged landscape, and the\n * next `loam archive` reported loam's own half-merge as the author's bug.\n *\n * The temp files are the exception: a `.loam-*.tmp` was never linked into place,\n * so nothing reads it and nothing depends on it. It is litter, not damage.\n */\nfunction gradeWritePathResidue(\n docsDir: string,\n residue: WritePathResidue,\n findings: DoctorFinding[],\n): void {\n if (residue.lock !== null) {\n const lockFile = join(docsDir, residue.lock.path);\n findings.push({\n // Held by a live process is a fact about right now — wait and re-run.\n // Held by a process that no longer exists is damage: nothing will ever\n // release it, and every archive and unarchive refuses `docs-busy` until\n // somebody deletes it.\n severity: residue.lock.stale ? \"blocker\" : \"warning\",\n code: \"doctor.docs-locked\",\n message: residue.lock.stale\n ? `${residue.lock.path} is held by ${residue.lock.holder}, a process that no longer exists on this host — every \\`loam archive\\` and \\`loam unarchive\\` will refuse with \\`docs-busy\\` until it is gone.`\n : `${residue.lock.path} is held by ${residue.lock.holder}; another archive or unarchive is running against this docs repo.`,\n fix: residue.lock.stale\n ? `Delete ${lockFile} — its holder is dead, so nothing is going to release it. Check \\`loam doctor\\` again afterwards for an interrupted commit.`\n : \"Wait for it to finish and re-run; nothing is read or written while it is held.\",\n });\n }\n\n if (residue.intentUnreadable) {\n findings.push({\n severity: \"blocker\",\n code: \"doctor.commit-unreadable\",\n message: `${docsDir} holds a .loam-commit that cannot be read — a commit was interrupted and the one record of which files it had already written is unreadable.`,\n fix: \"Hand this to a human: compare the living docs against version control before running any loam command that writes. `loam archive` and `loam unarchive` both refuse with `commit-interrupted` while it is there.\",\n });\n } else if (residue.intent !== null) {\n const i = residue.intent;\n // The command is spelled out per branch rather than interpolated into one\n // sentence: `loam ${i.command} ${i.feature}` reads fine to a person and is\n // opaque to test/agent-commands-runnable.test.ts, which parses the commands\n // loam prints against the real program. Same discipline as spelling `code:`\n // literally — be visible to your own guard.\n const repair = i.command === \"archive\"\n ? `\\`loam archive ${i.feature}\\` — it recovers first, under the lock, putting the half-written files back from the snapshot`\n : `\\`loam unarchive ${i.feature}\\` — it recovers first, under the lock, finishing the restore (an interrupted restore is FINISHED, never undone: the merged text it was replacing is written down nowhere)`;\n findings.push({\n severity: \"blocker\",\n code: \"doctor.commit-interrupted\",\n message:\n `A ${i.command === \"archive\" ? `\\`loam archive ${i.feature}\\`` : `\\`loam unarchive ${i.feature}\\``} `\n + `was killed mid-commit (${i.host}, pid ${i.pid}, ${i.at}) — `\n + `${i.files.length} file(s) may be half-written: ${i.files.map((f) => f.path).join(\", \")}`,\n fix: `Re-run ${repair}, and refuses with \\`commit-interrupted\\` rather than guessing if a file has been edited since.`,\n });\n }\n\n if (residue.temps.length > 0) {\n findings.push({\n severity: \"warning\",\n code: \"doctor.staging-temps\",\n message: `${residue.temps.length} orphaned staging file(s) under ${docsDir}: ${residue.temps.join(\", \")} — a killed writer's scratch, never linked into place.`,\n fix: \"The next `loam archive` or `loam unarchive` removes its own; delete any that remain. Nothing reads them, so they cost disk and nothing else.\",\n });\n }\n}\n\nexport async function diagnose(cwd = process.cwd()): Promise<DoctorReport> {\n const inspected = await inspectConfig(cwd);\n const path = configPath(cwd);\n const findings: DoctorFinding[] = [];\n if (inspected.status === \"missing\") {\n findings.push({\n severity: \"blocker\",\n code: \"doctor.config-missing\",\n message: `No ${CONFIG_FILENAME} found at or above ${cwd}.`,\n fix: \"Run `loam init --docs <path-to-docs-repo>` here (add `--create` to make a new docs repo).\",\n });\n } else if (inspected.status === \"invalid\") {\n findings.push({\n severity: \"blocker\",\n code: \"doctor.config-invalid\",\n message: `Invalid ${CONFIG_FILENAME}: ${inspected.error ?? \"unknown error\"}`,\n fix: `Repair ${path} — or delete it and re-run \\`loam init\\`.`,\n });\n }\n\n const docsDir = inspected.config?.docsDir ?? null;\n const state = docsDir === null ? null : docsRepoState(docsDir);\n const exists = state !== null && state.kind !== \"missing\";\n const readable = exists && docsDir !== null ? await canAccess(docsDir, constants.R_OK) : false;\n const writable = exists && docsDir !== null ? await canAccess(docsDir, constants.W_OK) : false;\n const servicesDir = state?.kind === \"ok\";\n const landscapeFile = docsDir === null ? null : landscapePath(docsDir);\n const landscape = landscapeFile === null ? false : await canAccess(landscapeFile, constants.F_OK);\n\n // The docs-repo verdict comes from `docsRepoState`, the same function\n // `listServices` refuses on, so doctor cannot call a repo healthy that the\n // enumeration will not read.\n if (state?.kind === \"missing\") {\n findings.push({\n severity: \"blocker\",\n code: \"doctor.docs-missing\",\n message: `Configured docsDir is missing or is not a directory: ${docsDir}`,\n fix: `Fix \"docsDir\" in ${path}, clone the docs repo to ${docsDir}, or run \\`loam init --docs <dir> --create\\`.`,\n });\n } else if (state?.kind === \"no-services\") {\n findings.push({\n severity: \"blocker\",\n code: \"doctor.services-missing\",\n message: `Required services/ directory is missing under ${docsDir} — that path is not a docs repo.`,\n fix: `Point \"docsDir\" in ${path} at the shared docs repo, or run \\`loam init --docs ${docsDir} --create\\`.`,\n });\n }\n\n // An absolute docsDir in a committed config names a directory that exists on\n // exactly one machine. It is a warning and not a blocker because it works\n // perfectly — for the person who ran `loam init`, and for nobody who clones\n // the repo afterwards.\n const asWritten = inspected.config?.docsDirAsWritten;\n const configRoot = inspected.config?.root;\n if (\n asWritten !== undefined\n && configRoot !== undefined\n && isAbsolute(asWritten)\n && resolve(asWritten) !== resolve(configRoot)\n ) {\n findings.push({\n severity: \"warning\",\n code: \"doctor.docs-absolute\",\n message:\n `\"docsDir\" is stored as an absolute path (${asWritten}); ` +\n `${CONFIG_FILENAME} is committed, so it will not resolve on anyone else's machine.`,\n fix: `Rewrite \"docsDir\" in ${path} as a path relative to that file (e.g. \"../docs\").`,\n });\n }\n\n if (exists && !readable) {\n findings.push({\n severity: \"warning\",\n code: \"doctor.docs-unreadable\",\n message: `docsDir is not readable by this process: ${docsDir}`,\n fix: `Grant read access to ${docsDir} (check ownership and mode).`,\n });\n }\n if (exists && !writable) {\n findings.push({\n severity: \"warning\",\n code: \"doctor.docs-readonly\",\n message: `docsDir is not writable; read-only commands work, archive/init do not: ${docsDir}`,\n fix: `Grant write access to ${docsDir} if you need \\`loam new\\`, \\`loam adopt\\` or \\`loam archive\\`.`,\n });\n }\n if (exists && !landscape) {\n findings.push({\n severity: \"warning\",\n code: \"doctor.landscape-missing\",\n message: `${landscapeFile} is missing — nothing cross-service can be checked without it.`,\n fix: \"Create architecture/landscape.likec4 with one element per service and an edge per call (`loam init --create` writes the empty map).\",\n });\n } else if (exists && landscapeFile !== null && readable) {\n await inspectLandscape(landscapeFile, findings);\n }\n\n // The renderer's view of the repo, which is not loam's. loam parses every\n // `.likec4` file ALONE, so each one declares its own `specification` block and\n // re-declares whatever elements it names; LikeC4's own workspace loader merges\n // the whole tree into one model, and those declarations then collide. The\n // result was two tools disagreeing in the most confusing possible direction:\n // `loam validate --all` reported zero errors on a tree where `npx likec4\n // start` — the command loam's own brief recommends — refused to load at all.\n // `loam init --create` writes the project file that scopes the root project to\n // the landscape; a docs repo created before it exists has to be told, because\n // nothing else will ever mention it. A warning, not a blocker: no loam check\n // reads this file, and a repo without it is only unrenderable.\n if (docsDir !== null && exists && readable && !existsSync(join(docsDir, LIKEC4_PROJECT_FILENAME))) {\n findings.push({\n severity: \"warning\",\n code: \"doctor.likec4-config-missing\",\n message:\n `${docsDir}/${LIKEC4_PROJECT_FILENAME} is missing, so this tree is not a loadable LikeC4 workspace — `\n + \"every service model and feature delta declares its own `specification` block, and pointing a \"\n + \"renderer at the repo root merges them into one model and reports every declaration as a duplicate.\",\n fix:\n `Write ${docsDir}/${LIKEC4_PROJECT_FILENAME} with:\\n${LIKEC4_PROJECT_CONFIG.trimEnd()}\\n`\n + \"That scopes the root project to architecture/, so `npx likec4 start` in the docs repo renders \"\n + \"the fleet map. A service model or feature delta is rendered by pointing the renderer at its own \"\n + \"directory (`npx likec4 start services/<id>`) — being readable alone is what those files are for.\",\n });\n }\n\n // What a killed writer left behind. Read from `scanWritePathResidue`, whose\n // spellings of `.loam-lock` / `.loam-commit` / the temp-file pattern are\n // staging's own — doctor grades, it does not re-spell. This is the surface\n // that used to report `healthy: true` over half-merged docs.\n const writePath = docsDir !== null && exists && readable\n ? await scanWritePathResidue(docsDir)\n : null;\n if (docsDir !== null && writePath !== null) gradeWritePathResidue(docsDir, writePath, findings);\n\n let services: Awaited<ReturnType<typeof listServices>> = [];\n let activeFeatures: Awaited<ReturnType<typeof listFeatures>> = [];\n // Whether the fleet was actually READ, which is a narrower question than\n // whether reading it was attempted — hence set inside the try and not from\n // the guard, so an enumeration that threw leaves this false alongside its own\n // `doctor.inventory-unreadable`.\n let inventoried = false;\n if (docsDir !== null && readable && servicesDir) {\n try {\n [services, activeFeatures] = await Promise.all([\n listServices(docsDir),\n listFeatures(docsDir),\n ]);\n inventoried = true;\n } catch (error) {\n findings.push({\n severity: \"warning\",\n code: \"doctor.inventory-unreadable\",\n message: `Could not inventory the docs repo: ${error instanceof Error ? error.message : String(error)}`,\n fix: `Check that ${docsDir}/services and ${docsDir}/features are readable directories.`,\n });\n }\n }\n\n const configuredService = inspected.config?.service ?? null;\n const currentService: DoctorReport[\"currentService\"] = configuredService === null\n ? { configured: null, status: \"unbound\" }\n : services.some((service) => service.id === configuredService)\n ? { configured: configuredService, status: \"matched\" }\n : { configured: configuredService, status: \"unknown\" };\n // Standing INSIDE the docs repo, an absent service binding is the correct\n // state, not a gap: the docs repo is the fleet, it is not any one service, and\n // the fix this finding prints — `loam init --service <id>` — would bind the\n // shared repo to one of the services it holds, which is not a thing loam has\n // a meaning for. doctor already knew where it was standing (it prints the\n // fleet count two lines up) and reported the warning anyway, so the first\n // preflight anyone ran in a freshly created docs repo came back yellow with\n // advice that made it worse. The docs repo's own loam.json is the one that\n // resolves `docsDir` to the directory holding it — that identity, not a\n // filename, is the test.\n const inDocsRepo = configRoot !== undefined && docsDir !== null\n && resolve(configRoot) === resolve(docsDir);\n if (currentService.status === \"unbound\" && !inDocsRepo) {\n findings.push({\n severity: \"warning\",\n code: \"doctor.service-unbound\",\n message: \"loam.json has no service binding; service-repo checks need `service`.\",\n fix: `Run \\`loam init --docs ${inspected.config?.docsDirAsWritten ?? \"<dir>\"} --service <id>\\` here.`,\n });\n } else if (currentService.status === \"unknown\" && inventoried) {\n // Only when there was an inventory to be absent from. This finding is a\n // claim about a fleet that was read; with no docsDir, an unreadable one, or\n // an enumeration that threw, `services` is empty for a reason that has\n // nothing to do with `service`, and doctor pointed the reader at the one\n // config field that was fine while the blocker it had already filed named\n // the real one. `currentService.status` still reports `unknown` — the\n // envelope describes what loam could and could not match, and an unread\n // fleet matches nothing.\n findings.push({\n severity: \"warning\",\n code: \"doctor.service-unknown\",\n message: `Configured service '${configuredService}' is not present under services/.`,\n // `--service <id>`, not a positional: `loam adopt` takes no argument, so\n // the spelling this finding used to print was refused by commander with\n // \"too many arguments\" — as the FIRST instruction a freshly bound service\n // repo ever receives. test/agent-commands-runnable.test.ts parses every\n // `loam …` loam prints against the real program so it cannot recur.\n fix: `Run \\`loam adopt --service ${configuredService}\\` to onboard it, or fix \"service\" in ${path}.`,\n });\n }\n\n // The slash commands (and everything else `init` lays down for a tool) belong\n // to the repo `init` ran in — the directory holding loam.json, which is not\n // the cwd now that config discovery walks upward.\n const agents = await inspectAgentSurface(dirname(path), inspected.config, docsDir, findings);\n\n return {\n healthy: !findings.some((finding) => finding.severity === \"blocker\"),\n runtime: {\n package: \"@ybotok/loam\",\n version: LOAM_VERSION,\n node: process.version,\n platform: process.platform,\n arch: process.arch,\n },\n config: { path, status: inspected.status, error: inspected.error },\n docs: {\n path: docsDir,\n exists,\n readable,\n writable,\n servicesDir,\n landscape,\n },\n counts: { services: services.length, activeFeatures: activeFeatures.length },\n currentService,\n agents,\n writePath,\n findings,\n };\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"document-bytes.js","sourceRoot":"","sources":["../../src/core/document-bytes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC;;;;;;;;;;;;;;GAcG;AACH,MAAM,OAAO,oBAAqB,SAAQ,KAAK;IAIlC,IAAI;IAHG,IAAI,GAAG,sBAAsB,CAAC;IAEhD,YACW,IAAY,EACrB,MAAc;QAEd,KAAK,CACH,GAAG,IAAI,mCAAmC,MAAM,6DAA6D;YAC3G,+GAA+G;YAC/G,8GAA8G;YAC9G,2DAA2D,CAC9D,CAAC;oBARO,IAAI;IASf,CAAC;CACF;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,cAAc,CAAC,KAAa,EAAE,IAAY;IACxD,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC;QAAE,MAAM,IAAI,oBAAoB,CAAC,IAAI,EAAE,0CAA0C,CAAC,CAAC;IACrG,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IACpC,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,oBAAoB,CAC5B,IAAI,EACJ,iHAAiH,CAClH,CAAC;IACJ,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC","sourcesContent":["/**\n * Decode the bytes of a document loam is about to parse, or refuse naming it.\n *\n * The rule belongs to every module that turns a markdown artifact into text —\n * the frontmatter reader, the requirement parser, the fleet-wide read index and\n * three commands that read a single file directly. It lived beside the read\n * index, so each of those imported the whole index (and through it repo.ts,\n * openapi.ts and spec.ts) to reach a dozen lines of decoding, and several of\n * them closed an import cycle doing it. A leaf whose only dependency is\n * `node:buffer` costs nothing to import and can be reached from anywhere.\n */\nimport { isUtf8 } from \"node:buffer\";\n\n/**\n * A document loam was about to parse that is not UTF-8 text.\n *\n * Thrown rather than returned, and named as the file rather than as an empty\n * document, because every parser in the codebase reads \"no requirements, no\n * frontmatter\" as a legitimate state — a fresh baseline looks exactly like it.\n * A `spec.md` saved as UTF-16 (PowerShell's `>` writes UTF-16LE by default)\n * therefore validated green, with every requirement in it invisible.\n *\n * `path` is spelled the way Node spells it on an ErrnoException so that\n * validate's per-target guard names the file without knowing this type; the\n * write path makes the same two tests for the same reasons (staging.ts's\n * `decodeUtf8`), and its messages differ only in saying what a rewrite would\n * additionally destroy, which is not what a reader needs to hear.\n */\nexport class NotUtf8DocumentError extends Error {\n override readonly name = \"NotUtf8DocumentError\";\n\n constructor(\n readonly path: string,\n reason: string,\n ) {\n super(\n `${path} is not a UTF-8 text document — ${reason}. Read as UTF-8 its requirements, frontmatter and headings ` +\n `all come out absent rather than wrong, so the file grades as an empty baseline instead of an unreadable one. ` +\n `Nothing here was checked. Re-save it as UTF-8 (PowerShell's \\`>\\` and \\`Out-File\\` write UTF-16 unless told ` +\n `otherwise: use \\`Out-File -Encoding utf8\\`), then re-run.`,\n );\n }\n}\n\n/**\n * Decode a document loam is about to parse, or refuse naming it.\n *\n * Two tests, because one is not enough. `isUtf8` catches the byte sequences\n * that cannot be UTF-8 at all — which is what a byte-order mark makes UTF-16\n * into, and PowerShell writes one. Without a BOM, UTF-16LE of ASCII is a\n * sequence of valid UTF-8 bytes: every other byte is NUL, which decodes to\n * U+0000 and nothing complains. That file parsed as zero requirements and no\n * frontmatter, and validated green. A NUL in a markdown document loam owns has\n * no legitimate spelling, so it is the second test.\n */\nexport function decodeDocument(bytes: Buffer, path: string): string {\n if (!isUtf8(bytes)) throw new NotUtf8DocumentError(path, \"its bytes are not a valid UTF-8 sequence\");\n const text = bytes.toString(\"utf8\");\n if (text.includes(\"\\u0000\")) {\n throw new NotUtf8DocumentError(\n path,\n \"it holds NUL characters, which no markdown document does — almost always UTF-16 saved without a byte-order mark\",\n );\n }\n return text;\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"explore.js","sourceRoot":"","sources":["../../src/core/explore.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The blast radius of a change nobody has written down yet.\n *\n * Everything else in loam answers a question about documents that exist. This\n * module answers the one that comes BEFORE the first document: which services\n * does this feature actually touch? On a fleet of a hundred that call is the\n * hardest one in the cycle and the only one made with no tool in hand —\n * `loam new FEAT-101 --touches a --touches b` takes the answer as an argument\n * and scaffolds whatever it was told. A `--touches` list short by one service\n * is not caught by anything: the feature validates, archives, and ships with a\n * consumer nobody updated.\n *\n * So this states the work the same way `brief.ts` does. It reads the fleet map\n * and the living contracts, reports the ring of services around the seeds, the\n * features already in flight over the same ground, and how far each service's\n * documentation has got — and stops. Which of those neighbours the feature\n * really touches is a judgement about intent, and loam does not make those.\n *\n * The landscape is parsed ONCE for the whole exploration. Per-service reads of\n * it exist (`brief.ts`'s `landscapeContext`) and are correct for one service;\n * calling one of those per seed is how `validate --all` came to cost 13 seconds\n * on 120 services, and this command sits in front of authoring, where that is\n * the difference between a habit and a thing people skip.\n */\nimport { existsSync } from \"node:fs\";\nimport { FleetContext } from \"./fleet-context.js\";\nimport { serviceResolver, type Elem, type Rel } from \"./likec4.js\";\nimport {\n maturityGaps,\n serviceMaturity,\n type Maturity,\n} from \"./maturity.js\";\nimport {\n compareIds,\n landscapePath,\n nearestIds,\n servicePaths,\n type ServiceEntry,\n} from \"./repo.js\";\n\n/** One end of a call the fleet map already draws. */\nexport interface ExploreEdge {\n /** The service at the other end. */\n service: string;\n /** The operationId the call uses, or null for an edge nobody tied to one. */\n op: string | null;\n title: string | null;\n}\n\n/**\n * Why a service is in the answer. Seeds were asked for; the rest were derived.\n *\n * A neighbour on both sides of a seed reports `calls-seed` — see the overlap\n * rule in `explore`. The field is a hint about where to look, not a complete\n * description of the edges; `inbound`/`outbound` are that.\n */\nexport type ExploreReason = \"seed\" | \"calls-seed\" | \"called-by-seed\";\n\nexport interface ExploreService {\n id: string;\n reason: ExploreReason;\n /** Whether `services/<id>/` exists at all. */\n known: boolean;\n /**\n * How far this service's documentation has got, or null when it does not\n * exist yet. A `--touches` naming a service at `empty` or `partial` is a\n * different job from one naming a vouched service, and the difference decides\n * whether the feature starts with `loam adopt`.\n */\n maturity: Maturity | null;\n /** What stands between it and `vouched` — `maturityGaps`, so it matches `list --needs-work`. */\n missing: string[];\n /** Whether anything in the fleet map resolves to it. */\n modelled: boolean;\n /** operationIds its living contract exposes today, `x-loam-remove` markers excluded. */\n operations: string[];\n /**\n * Whether that contract could be read at all, beside the `error` the parser\n * gave when it could not.\n *\n * It rides next to `operations` rather than inside it for the reason `delta`\n * carries the same pair: an unreadable contract yields an EMPTY operation\n * list, indistinguishable from a service with no endpoints — and this is the\n * field the workflow tells an agent to read before deciding whether an\n * operation it is about to add already exists. Answering `[]` over a YAML\n * error is how a MODIFIED requirement gets authored as ADDED.\n */\n openapi: { unreadable: boolean; error?: string };\n inbound: ExploreEdge[];\n outbound: ExploreEdge[];\n}\n\n/** An active feature already working over ground the exploration covers. */\nexport interface ExploreOverlap {\n feature: string;\n /** The explored services it already carries a delta for. */\n services: string[];\n}\n\nexport interface Exploration {\n /** The seed ids, as asked for. */\n seeds: string[];\n /**\n * Seeds that name no `services/<id>/`, each with the closest real ids. A seed\n * may legitimately be a service the feature INTRODUCES, so this is reported\n * rather than refused — but a typo produces exactly the same shape, and the\n * near-miss list is what tells the two apart.\n */\n unknown: Array<{ id: string; nearest: string[] }>;\n /** Operation seeds that resolved to no service's living contract. */\n unresolvedOperations: string[];\n /** Seeds first, then the ring, each in id order. */\n services: ExploreService[];\n /** Ids the ring added that were not asked for — the candidates to weigh. */\n neighbours: string[];\n overlaps: ExploreOverlap[];\n landscape: { present: boolean; parses: boolean };\n /**\n * The literal `loam new` line the seeds imply — seeds only. The ring is\n * deliberately NOT folded in: this module's whole claim is that it does not\n * know which neighbours the feature touches, and a command line that quietly\n * included them would make the guess on the reader's behalf and look derived\n * while doing it.\n *\n * Named for what it does rather than `command`, which is the envelope's key\n * for the command that RAN. The rename is not cosmetic: `emitJson` spreads\n * the payload LAST, so a payload field called `command` would silently\n * OVERRIDE the envelope's — `command` would come back as\n * `\"loam new FEAT-000 …\"`, and every consumer branching on\n * `command === \"explore\"` (the same key `status`, `doctor`, `dependencies`,\n * `archive` and `unarchive` emit) would quietly stop matching, with tsc and\n * the linter green throughout.\n */\n scaffold: string;\n}\n\nexport interface ExploreRequest {\n docsDir: string;\n /** Service ids to explore around. */\n services: string[];\n /** operationIds to explore around; each resolves to the service that defines it. */\n operations: string[];\n /** Placeholder feature id for the suggested command line. */\n featureId: string;\n context?: FleetContext;\n}\n\n/**\n * Read the fleet around a proposed change. Reads only; writes nothing, and\n * refuses nothing — every miss is reported as a field.\n */\nexport async function explore(req: ExploreRequest): Promise<Exploration> {\n const { docsDir, featureId } = req;\n const context = req.context ?? new FleetContext();\n const entries = await context.listServices(docsDir);\n const byId = new Map(entries.map((e) => [e.id, e]));\n const known = new Set(byId.keys());\n\n const landPath = landscapePath(docsDir);\n const present = existsSync(landPath);\n const land = present ? await context.loadLikeC4(landPath) : null;\n const parses = land !== null && land.errors.length === 0;\n const elements = parses ? land.elements : [];\n const relationships: Rel[] = parses ? land.relationships : [];\n // One resolver for the whole scan, built with the real service ids so an edge\n // drawn into a modelled container (`paymentService.api`) counts for the\n // service that owns it — the same resolution `list`, `show` and `validate`\n // use, so no two commands can disagree about who calls whom.\n const svcOf = serviceResolver(elements, known);\n\n // Operation seeds resolve through the living contracts, not the map: the map\n // says who CALLS an operation, and the question here is who DEFINES it.\n const opSeeds: string[] = [];\n const unresolvedOperations: string[] = [];\n for (const op of req.operations) {\n const owner = await operationOwner(docsDir, entries, op, context);\n if (owner === null) unresolvedOperations.push(op);\n else opSeeds.push(owner);\n }\n\n const seeds = [...new Set([...req.services, ...opSeeds])];\n const unknown = seeds\n .filter((id) => !known.has(id))\n .map((id) => ({ id, nearest: nearestIds(id, [...known]) }));\n\n // The ring: one hop, both directions. A seed that is not modelled contributes\n // nothing here and that is the honest answer — an invisible service has no\n // neighbours anyone can derive, which is what `landscape.service-unmodelled`\n // is about.\n //\n // The two directions are collected separately rather than written into one\n // map as the loop goes, because a neighbour can be BOTH — it calls a seed and\n // the seed calls it — and a single-map version answers whichever edge the\n // parser happened to yield last. That is a field whose value depends on the\n // order lines appear in a `.likec4` file, which is the kind of answer that\n // reads as derived and is not.\n const seedSet = new Set(seeds);\n const callsSeed = new Set<string>();\n const calledBySeed = new Set<string>();\n for (const r of relationships) {\n const from = svcOf(r.source);\n const to = svcOf(r.target);\n if (seedSet.has(from) && !seedSet.has(to)) calledBySeed.add(to);\n if (seedSet.has(to) && !seedSet.has(from)) callsSeed.add(from);\n }\n\n // `calls-seed` wins the overlap, deterministically. Of the two directions it\n // is the one that more often has to be touched: a consumer depends on the\n // seed's contract, so a change to that contract is what breaks it, while a\n // provider the seed merely calls is usually unaffected by the seed changing.\n const ring = new Map<string, ExploreReason>([\n ...[...calledBySeed].map((id) => [id, \"called-by-seed\" as const] as const),\n ...[...callsSeed].map((id) => [id, \"calls-seed\" as const] as const),\n ]);\n\n const ordered: Array<{ id: string; reason: ExploreReason }> = [\n ...[...seeds].sort(compareIds).map((id) => ({ id, reason: \"seed\" as const })),\n ...[...ring]\n .sort(([a], [b]) => compareIds(a, b))\n .map(([id, reason]) => ({ id, reason })),\n ];\n\n const services: ExploreService[] = [];\n for (const { id, reason } of ordered) {\n services.push(\n await describe({\n id,\n reason,\n entry: byId.get(id),\n docsDir,\n relationships,\n svcOf,\n elements,\n parses,\n context,\n }),\n );\n }\n\n const covered = new Set(services.map((s) => s.id));\n const features = await context.listFeatures(docsDir);\n const overlaps: ExploreOverlap[] = features\n .map((f) => ({ feature: f.id, services: f.services.filter((s) => covered.has(s)) }))\n .filter((o) => o.services.length > 0)\n .sort((a, b) => compareIds(a.feature, b.feature));\n\n return {\n seeds,\n unknown,\n unresolvedOperations,\n services,\n neighbours: [...ring.keys()].sort(compareIds),\n overlaps,\n landscape: { present, parses },\n scaffold: newCommand(featureId, seeds, known),\n };\n}\n\n/* ------------------------------------------------------------------ */\n\ninterface DescribeRequest {\n id: string;\n reason: ExploreReason;\n entry: ServiceEntry | undefined;\n docsDir: string;\n relationships: Rel[];\n svcOf: (id: string) => string;\n elements: Elem[];\n /** Whether the landscape parsed — what makes its silence evidence rather than absence. */\n parses: boolean;\n context: FleetContext;\n}\n\nasync function describe(req: DescribeRequest): Promise<ExploreService> {\n const { id, reason, entry, docsDir, relationships, svcOf } = req;\n\n const inbound: ExploreEdge[] = [];\n const outbound: ExploreEdge[] = [];\n for (const r of relationships) {\n const edge = { op: r.op ?? null, title: r.title ?? null };\n if (svcOf(r.target) === id) inbound.push({ service: svcOf(r.source), ...edge });\n else if (svcOf(r.source) === id) outbound.push({ service: svcOf(r.target), ...edge });\n }\n const modelled = req.elements.some((e) => svcOf(e.id) === id);\n\n // A service that does not exist has no rung: `empty` would be a claim about a\n // directory nobody has made, and it reads as \"exists, nothing in it\" — the\n // one state a caller most needs to tell it apart from.\n if (entry === undefined) {\n return {\n id,\n reason,\n known: false,\n maturity: null,\n missing: [],\n modelled,\n operations: [],\n // Not `unreadable`: there is no contract here to fail to read. A service\n // with no directory owes nothing, and reporting a parse failure over an\n // absent file would send a reader looking for a document to fix.\n openapi: { unreadable: false },\n inbound,\n outbound,\n };\n }\n\n const archSpec = existsSync(servicePaths(docsDir, id).archSpec);\n // Positive evidence only, and the rule is `list`'s verbatim: an inbound edge\n // carrying an operation is proof somebody calls this service, while a\n // landscape that is absent or does not parse proves nothing about who calls\n // it — so the contract is still owed. Spelling this differently here is how\n // the same service would grade `partial` in one command and `vouched` in the\n // other.\n const apiExpected = !req.parses || inbound.some((e) => e.op !== null);\n const input = { entry, archSpec, apiExpected };\n\n // `readOpenapi`, not `operationIds`: a contract that exists but does not\n // parse comes back from the id list as an EMPTY set, indistinguishable from a\n // service with no endpoints — and \"this service offers nothing\" is the worst\n // possible lie to tell somebody deciding whether to call it.\n const api = await req.context.readOpenapi(servicePaths(docsDir, id).openapi);\n const operations = api.ops.filter((o) => !o.remove).map((o) => o.id);\n\n return {\n id,\n reason,\n known: true,\n maturity: serviceMaturity(input),\n missing: maturityGaps(input),\n modelled,\n operations,\n openapi: {\n unreadable: api.unreadable,\n ...(api.error === undefined ? {} : { error: api.error }),\n },\n inbound,\n outbound,\n };\n}\n\n/**\n * The service whose living contract defines an operationId, or null.\n *\n * Reads every service's `openapi.yaml`, which is the cost of asking a question\n * nothing indexes. It is YAML, not LikeC4 — the expensive parse in this\n * codebase — and it happens only when somebody passes `--op`.\n */\nasync function operationOwner(\n docsDir: string,\n entries: ServiceEntry[],\n op: string,\n context: FleetContext,\n): Promise<string | null> {\n for (const entry of entries) {\n if (!entry.has.openapi) continue;\n const api = await context.readOpenapi(servicePaths(docsDir, entry.id).openapi);\n if (api.ops.some((o) => o.id === op && !o.remove)) return entry.id;\n }\n return null;\n}\n\n/**\n * The `loam new` line the seeds imply. A seed that names no existing service is\n * `--new-service`, not `--touches`: those are different scaffolds, and getting\n * it wrong is what leaves a feature with a requirement delta for a service that\n * has no directory to archive into.\n */\nfunction newCommand(featureId: string, seeds: string[], known: ReadonlySet<string>): string {\n const flags = [...seeds]\n .sort(compareIds)\n .map((id) => (known.has(id) ? `--touches ${id}` : `--new-service ${id}`));\n return `loam new ${featureId}${flags.length > 0 ? ` ${flags.join(\" \")}` : \"\"}`;\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"frontmatter.js","sourceRoot":"","sources":["../../src/core/frontmatter.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * YAML frontmatter — the provenance of an artifact.\n *\n * `status` says whether a human has vouched for the document, `sources` says\n * which code it was written from. When the prose is written by an agent, these\n * are the only deterministic tie to reality: everything else loam checks is\n * internal consistency, which a fluent enough fiction satisfies perfectly.\n */\nimport { existsSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport { isMap, parse, parseDocument } from \"yaml\";\nimport { decodeDocument, NotUtf8DocumentError } from \"./document-bytes.js\";\n\nexport interface Frontmatter {\n /** True when a terminated `---` block was found, even if it was empty. */\n present: boolean;\n /**\n * True when the block was found but its YAML cannot be read as a mapping —\n * a parse error, or a scalar/sequence document. `data` is then {}, which is\n * NOT the same fact as an empty header: the fields are unreadable, not\n * absent, and a checker that grades them \"missing\" sends the author adding\n * lines to a block YAML refuses to parse. Validate turns this flag into\n * `frontmatter.malformed`; the writer (withFrontmatterFields) has its own\n * replace-don't-merge rule for the same state.\n */\n malformed: boolean;\n /**\n * Why the FILE could not be read as text at all, or absent when it could —\n * set only by `readFrontmatter`, since a caller that already holds a string\n * has nothing left to decode.\n *\n * A third state, not a shade of the other two: `present: false` here means\n * nobody could look, where everywhere else it means nobody wrote a header.\n * A checker must ask this first, or it reports \"owner/status/sources missing\"\n * over a file whose lines are right there — the same false cascade\n * `malformed` exists to stop, one layer lower down.\n */\n unreadable?: string;\n /** The parsed mapping, or {} when absent or malformed. */\n data: Record<string, unknown>;\n /** The document with the frontmatter removed. */\n body: string;\n}\n\n/** Where the header sits in the raw text. */\ninterface Bounds {\n /** First character of the YAML text. */\n start: number;\n /** One past its last character — the newline before the closing fence included. */\n end: number;\n /** First character of the body. */\n bodyStart: number;\n}\n\n/**\n * Drop a leading byte-order mark.\n *\n * With one in front, the opening `---` is no longer at position 0, so the whole\n * header reads as absent: a documented artifact silently becomes an\n * undocumented one — no owner, no status, no `sources` — and nothing says why.\n * The same blindness `spec.ts` had at `^##`.\n *\n * Only at position 0: elsewhere U+FEFF is a zero-width no-break space and is the\n * author's content. Callers strip before measuring, so the offsets `bounds`\n * returns index the same string the caller then slices.\n */\nfunction stripBom(text: string): string {\n return text.charCodeAt(0) === 0xfeff ? text.slice(1) : text;\n}\n\n/**\n * A fence is a LINE of exactly three dashes. Trailing whitespace is tolerated\n * (`\\s` also swallows the CR of a CRLF file), trailing text is not: `--- title`\n * is prose, `----` is a horizontal rule. Matching the substring `---` instead —\n * as this used to — made both of those fences, so a stray rule closed the\n * header early and a `--- note` closer silently ate its own trailing text.\n */\nconst FENCE_RE = /^---\\s*$/;\n\n/**\n * Locate the frontmatter block. The opener is the very first line, the closer\n * the first subsequent fence line — a later horizontal rule is body, not a\n * second fence. No closer means an unterminated opener: not frontmatter at all.\n *\n * The reader and the writer both go through this, so they can never disagree\n * about which bytes are the header — the writer's promise to leave the body\n * untouched depends on that being one decision, not two.\n */\nfunction bounds(md: string): Bounds | null {\n const firstNl = md.indexOf(\"\\n\");\n if (!FENCE_RE.test(firstNl === -1 ? md : md.slice(0, firstNl))) return null;\n // A lone `---` with nothing after it is an unterminated opener.\n if (firstNl === -1) return null;\n const start = firstNl + 1;\n for (let lineStart = start; ; ) {\n const nl = md.indexOf(\"\\n\", lineStart);\n const line = nl === -1 ? md.slice(lineStart) : md.slice(lineStart, nl);\n if (FENCE_RE.test(line)) {\n // An empty block (`---\\n---`) has no text between the fences: start === end.\n return { start, end: lineStart, bodyStart: nl === -1 ? md.length : nl + 1 };\n }\n if (nl === -1) return null;\n lineStart = nl + 1;\n }\n}\n\n/**\n * Split a markdown document into its frontmatter and body. A document with no\n * frontmatter is returned whole rather than truncated.\n */\nexport function parseFrontmatter(source: string): Frontmatter {\n const md = stripBom(source);\n const at = bounds(md);\n if (at === null) return { present: false, malformed: false, data: {}, body: md };\n\n const yamlText = md.slice(at.start, at.end);\n const body = md.slice(at.bodyStart).trimStart();\n\n let data: Record<string, unknown> = {};\n let malformed = false;\n try {\n const parsed: unknown = parse(yamlText);\n if (parsed && typeof parsed === \"object\" && !Array.isArray(parsed)) {\n data = parsed as Record<string, unknown>;\n } else if (parsed !== null) {\n // A scalar or sequence header holds no fields to read — as unreadable as\n // broken YAML. null is the empty block (`---\\n---`): legal, and empty.\n malformed = true;\n }\n } catch {\n // A bad header must not make the document unreadable (the body is still the\n // body, and never crashes a command) — but the failure travels as a flag,\n // so the caller can say `frontmatter.malformed` instead of the false\n // cascade \"owner/status missing\" the silent {} used to produce.\n malformed = true;\n }\n return { present: true, malformed, data, body };\n}\n\n/** A field as text. Non-string scalars (a bare date, a number) are stringified. */\nexport function stringField(fm: Frontmatter, key: string): string | undefined {\n const v = fm.data[key];\n if (v === undefined || v === null) return undefined;\n if (typeof v === \"string\") return v;\n if (typeof v === \"number\" || typeof v === \"boolean\") return String(v);\n if (v instanceof Date) return v.toISOString().slice(0, 10);\n return undefined;\n}\n\n/** A field as a list. A lone scalar counts as a list of one. */\nexport function listField(fm: Frontmatter, key: string): string[] {\n const v = fm.data[key];\n if (v === undefined || v === null) return [];\n if (Array.isArray(v)) return v.map((x) => String(x)).filter((s) => s.length > 0);\n const one = stringField(fm, key);\n return one === undefined ? [] : [one];\n}\n\n/**\n * Return `md` with these frontmatter fields set and everything below the closing\n * fence byte-identical.\n *\n * The header is edited through yaml's document model rather than rebuilt from\n * the parsed data: keys keep their order and their comments, fields nobody named\n * are left exactly as they were, and a value that would read back as something\n * else — a digest of all digits, say — gets quoted for us. Stamping a document\n * is not a licence to reformat it: the diff a reviewer sees should be the lines\n * that changed, and nothing else.\n *\n * A document with no frontmatter gets one, and the text that was there becomes\n * the body. A header that does not parse (or is not a mapping) is replaced\n * rather than merged into — it cannot be edited without guessing what it meant.\n */\nexport function withFrontmatterFields(source: string, fields: Record<string, string>): string {\n // Stamping a BOM-prefixed document drops the BOM. It sits above the header, so\n // the promise about the body still holds — and leaving it would re-break the\n // file for every parser anchored at position 0, including ours.\n const md = stripBom(source);\n const at = bounds(md);\n const parsed = parseDocument(at === null ? \"\" : md.slice(at.start, at.end));\n const editable = parsed.errors.length === 0 && (parsed.contents === null || isMap(parsed.contents));\n const doc = editable ? parsed : parseDocument(\"\");\n\n for (const [key, value] of Object.entries(fields)) doc.set(key, value);\n const yamlText = doc.toString();\n\n if (at === null) return `---\\n${yamlText}---\\n\\n${md}`;\n return md.slice(0, at.start) + yamlText + md.slice(at.end);\n}\n\n/**\n * The document's body, byte-exact: everything after the frontmatter block —\n * the closing `---` line and its newline belong to the HEADER, every byte\n * after them (blank lines included) is body. A document with no frontmatter is\n * all body. This is what `content_digest` hashes, and it deliberately does NOT\n * go through `parseFrontmatter` (whose `body` is trimmed for callers that want\n * text): the digest's writer and its checker must slice the same bytes, so\n * both go through here.\n */\nexport function rawBody(source: string): string {\n const md = stripBom(source);\n const at = bounds(md);\n return at === null ? md : md.slice(at.bodyStart);\n}\n\n/**\n * Read a markdown file's frontmatter; a missing file reads as absent.\n *\n * Bytes in, decoded through `decodeDocument`, because `readFile(path, \"utf8\")`\n * turns a UTF-16 spec.md into mojibake whose opening `---` is no longer at\n * position 0 — so the header reads as ABSENT, and `status`, `owner` and\n * `sources` all come back missing over a file that spells every one of them.\n * The same blindness `stripBom` exists to stop, one encoding wider.\n *\n * The failure travels as a FLAG rather than an exception, which is how every\n * reader here degrades (`readOpenapi`'s `unreadable`) and is load-bearing at\n * exactly this call: this is the read behind the fleet ENUMERATION\n * (repo.ts `listServices`), so throwing would turn one PowerShell-saved file\n * into a `loam list` that reports nothing about the other 119 services.\n * Parsers never diagnose; a checker grades the flag.\n */\nexport async function readFrontmatter(path: string): Promise<Frontmatter> {\n if (!existsSync(path)) return { present: false, malformed: false, data: {}, body: \"\" };\n let text: string;\n try {\n text = decodeDocument(await readFile(path), path);\n } catch (err) {\n if (!(err instanceof NotUtf8DocumentError)) throw err;\n return { present: false, malformed: false, unreadable: err.message, data: {}, body: \"\" };\n }\n return parseFrontmatter(text);\n}\n\n/** The statuses each kind of artifact may carry. */\nexport const SERVICE_STATUSES = [\"draft\", \"verified\"] as const;\nexport const FEATURE_STATUSES = [\"proposed\", \"in_progress\", \"built\", \"done\"] as const;\n"]}