@ybotok/loam 0.2.0-alpha.1 → 0.2.0-alpha.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (901) hide show
  1. package/CHANGELOG.md +3448 -0
  2. package/COMPARISON.md +91 -3
  3. package/CONTRIBUTING.md +37 -0
  4. package/MIGRATING-from-OpenSpec.md +47 -23
  5. package/QUICKSTART.md +189 -12
  6. package/README.md +274 -65
  7. package/ROADMAP.md +572 -31
  8. package/SCHEMA.md +1709 -155
  9. package/WORKFLOW.md +298 -72
  10. package/dist/cli.js +26 -8
  11. package/dist/cli.js.map +1 -1
  12. package/dist/commands/adopt/adopt.js +5 -10
  13. package/dist/commands/adopt/adopt.js.map +1 -1
  14. package/dist/commands/adopt/render.js +50 -9
  15. package/dist/commands/adopt/render.js.map +1 -1
  16. package/dist/commands/archive/archive.js +16 -19
  17. package/dist/commands/archive/archive.js.map +1 -1
  18. package/dist/commands/archive/closing.js +42 -0
  19. package/dist/commands/archive/closing.js.map +1 -0
  20. package/dist/commands/archive/plan/contracts/asyncapi.js +36 -42
  21. package/dist/commands/archive/plan/contracts/asyncapi.js.map +1 -1
  22. package/dist/commands/archive/plan/contracts/consumers.js +56 -0
  23. package/dist/commands/archive/plan/contracts/consumers.js.map +1 -0
  24. package/dist/commands/archive/plan/contracts/openapi.js +77 -43
  25. package/dist/commands/archive/plan/contracts/openapi.js.map +1 -1
  26. package/dist/commands/archive/plan/contracts/verdict-lines.js +103 -0
  27. package/dist/commands/archive/plan/contracts/verdict-lines.js.map +1 -0
  28. package/dist/commands/archive/plan/document/head.js +151 -0
  29. package/dist/commands/archive/plan/document/head.js.map +1 -0
  30. package/dist/commands/archive/plan/document/links.js +284 -0
  31. package/dist/commands/archive/plan/document/links.js.map +1 -0
  32. package/dist/commands/archive/plan/document/run.js +136 -0
  33. package/dist/commands/archive/plan/document/run.js.map +1 -0
  34. package/dist/commands/archive/plan/gate.js +21 -19
  35. package/dist/commands/archive/plan/gate.js.map +1 -1
  36. package/dist/commands/archive/plan/landscape.js +167 -30
  37. package/dist/commands/archive/plan/landscape.js.map +1 -1
  38. package/dist/commands/archive/plan/model/extending.js +85 -0
  39. package/dist/commands/archive/plan/model/extending.js.map +1 -0
  40. package/dist/commands/archive/plan/refusal.js +14 -19
  41. package/dist/commands/archive/plan/refusal.js.map +1 -1
  42. package/dist/commands/archive/plan/specs.js +137 -56
  43. package/dist/commands/archive/plan/specs.js.map +1 -1
  44. package/dist/commands/archive/plan/state.js +3 -0
  45. package/dist/commands/archive/plan/state.js.map +1 -1
  46. package/dist/commands/archive/run.js +134 -30
  47. package/dist/commands/archive/run.js.map +1 -1
  48. package/dist/commands/archive/shipped.js +49 -0
  49. package/dist/commands/archive/shipped.js.map +1 -0
  50. package/dist/commands/context/context.js +85 -18
  51. package/dist/commands/context/context.js.map +1 -1
  52. package/dist/commands/context/print.js +29 -7
  53. package/dist/commands/context/print.js.map +1 -1
  54. package/dist/commands/delta/delta.js +102 -14
  55. package/dist/commands/delta/delta.js.map +1 -1
  56. package/dist/commands/delta/print.js +17 -1
  57. package/dist/commands/delta/print.js.map +1 -1
  58. package/dist/commands/dependencies.js +3 -7
  59. package/dist/commands/dependencies.js.map +1 -1
  60. package/dist/commands/diff/diff.js +20 -27
  61. package/dist/commands/diff/diff.js.map +1 -1
  62. package/dist/commands/doctor.js +60 -1
  63. package/dist/commands/doctor.js.map +1 -1
  64. package/dist/commands/explain/explain.js +89 -13
  65. package/dist/commands/explain/explain.js.map +1 -1
  66. package/dist/commands/explore.js +16 -10
  67. package/dist/commands/explore.js.map +1 -1
  68. package/dist/commands/gate/gate.js +45 -8
  69. package/dist/commands/gate/gate.js.map +1 -1
  70. package/dist/commands/gate/print.js +15 -3
  71. package/dist/commands/gate/print.js.map +1 -1
  72. package/dist/commands/gherkin/commit.js +13 -54
  73. package/dist/commands/gherkin/commit.js.map +1 -1
  74. package/dist/commands/gherkin/gherkin.js +36 -20
  75. package/dist/commands/gherkin/gherkin.js.map +1 -1
  76. package/dist/commands/gherkin/reconcile.js +10 -13
  77. package/dist/commands/gherkin/reconcile.js.map +1 -1
  78. package/dist/commands/init/first-hour.js +44 -0
  79. package/dist/commands/init/first-hour.js.map +1 -1
  80. package/dist/commands/init/init.js +18 -22
  81. package/dist/commands/init/init.js.map +1 -1
  82. package/dist/commands/list/campaign/campaign.js +4 -6
  83. package/dist/commands/list/campaign/campaign.js.map +1 -1
  84. package/dist/commands/list/json.js +5 -7
  85. package/dist/commands/list/json.js.map +1 -1
  86. package/dist/commands/list/list.js +44 -29
  87. package/dist/commands/list/list.js.map +1 -1
  88. package/dist/commands/list/print.js +52 -9
  89. package/dist/commands/list/print.js.map +1 -1
  90. package/dist/commands/list/suites/suites.js +140 -0
  91. package/dist/commands/list/suites/suites.js.map +1 -0
  92. package/dist/commands/list/views.js +37 -34
  93. package/dist/commands/list/views.js.map +1 -1
  94. package/dist/commands/mcp/dispatch.js +91 -36
  95. package/dist/commands/mcp/dispatch.js.map +1 -1
  96. package/dist/commands/mcp/mcp.js +56 -15
  97. package/dist/commands/mcp/mcp.js.map +1 -1
  98. package/dist/commands/mcp/serve.js.map +1 -1
  99. package/dist/commands/migrate-openspec/materialize/active.js +27 -22
  100. package/dist/commands/migrate-openspec/materialize/active.js.map +1 -1
  101. package/dist/commands/migrate-openspec/materialize/stage.js +4 -3
  102. package/dist/commands/migrate-openspec/materialize/stage.js.map +1 -1
  103. package/dist/commands/migrate-openspec/materialize/target.js +2 -2
  104. package/dist/commands/migrate-openspec/materialize/target.js.map +1 -1
  105. package/dist/commands/migrate-openspec/openspec/decisions.js +9 -14
  106. package/dist/commands/migrate-openspec/openspec/decisions.js.map +1 -1
  107. package/dist/commands/migrate-openspec/openspec/error.js +7 -8
  108. package/dist/commands/migrate-openspec/openspec/error.js.map +1 -1
  109. package/dist/commands/migrate-openspec/openspec/mapping.js +1 -9
  110. package/dist/commands/migrate-openspec/openspec/mapping.js.map +1 -1
  111. package/dist/commands/migrate-openspec/openspec/paths.js +3 -6
  112. package/dist/commands/migrate-openspec/openspec/paths.js.map +1 -1
  113. package/dist/commands/new/capability-template.js +118 -0
  114. package/dist/commands/new/capability-template.js.map +1 -0
  115. package/dist/commands/new/commit.js +8 -22
  116. package/dist/commands/new/commit.js.map +1 -1
  117. package/dist/commands/new/modifies.js +206 -0
  118. package/dist/commands/new/modifies.js.map +1 -0
  119. package/dist/commands/new/new.js +59 -14
  120. package/dist/commands/new/new.js.map +1 -1
  121. package/dist/commands/new/templates.js +48 -124
  122. package/dist/commands/new/templates.js.map +1 -1
  123. package/dist/commands/open.js +3 -7
  124. package/dist/commands/open.js.map +1 -1
  125. package/dist/commands/policy/gate.js +27 -0
  126. package/dist/commands/policy/gate.js.map +1 -1
  127. package/dist/commands/rebase/plan.js +2 -2
  128. package/dist/commands/rebase/plan.js.map +1 -1
  129. package/dist/commands/rebase/rebase.js +60 -35
  130. package/dist/commands/rebase/rebase.js.map +1 -1
  131. package/dist/commands/seed/commit.js +55 -26
  132. package/dist/commands/seed/commit.js.map +1 -1
  133. package/dist/commands/seed/plan.js +158 -13
  134. package/dist/commands/seed/plan.js.map +1 -1
  135. package/dist/commands/seed/seed.js +13 -11
  136. package/dist/commands/seed/seed.js.map +1 -1
  137. package/dist/commands/show/feature.js +9 -5
  138. package/dist/commands/show/feature.js.map +1 -1
  139. package/dist/commands/show/introduced.js +157 -0
  140. package/dist/commands/show/introduced.js.map +1 -0
  141. package/dist/commands/show/marks.js +35 -6
  142. package/dist/commands/show/marks.js.map +1 -1
  143. package/dist/commands/show/service.js +41 -33
  144. package/dist/commands/show/service.js.map +1 -1
  145. package/dist/commands/show/show.js +17 -7
  146. package/dist/commands/show/show.js.map +1 -1
  147. package/dist/commands/status/fleet-next.js +90 -0
  148. package/dist/commands/status/fleet-next.js.map +1 -0
  149. package/dist/commands/status/json.js +2 -0
  150. package/dist/commands/status/json.js.map +1 -1
  151. package/dist/commands/status/print.js +89 -37
  152. package/dist/commands/status/print.js.map +1 -1
  153. package/dist/commands/status/status.js +3 -7
  154. package/dist/commands/status/status.js.map +1 -1
  155. package/dist/commands/steps/steps.js +103 -23
  156. package/dist/commands/steps/steps.js.map +1 -1
  157. package/dist/commands/subsystem/edit.js +7 -7
  158. package/dist/commands/subsystem/edit.js.map +1 -1
  159. package/dist/commands/subsystem/move.js +106 -46
  160. package/dist/commands/subsystem/move.js.map +1 -1
  161. package/dist/commands/subsystem/query.js +2 -4
  162. package/dist/commands/subsystem/query.js.map +1 -1
  163. package/dist/commands/subsystem/subsystem.js +4 -7
  164. package/dist/commands/subsystem/subsystem.js.map +1 -1
  165. package/dist/commands/subsystem/sync.js +289 -74
  166. package/dist/commands/subsystem/sync.js.map +1 -1
  167. package/dist/commands/subsystem/txn/exclude.js +132 -0
  168. package/dist/commands/subsystem/txn/exclude.js.map +1 -0
  169. package/dist/commands/subsystem/txn/links.js +128 -0
  170. package/dist/commands/subsystem/txn/links.js.map +1 -0
  171. package/dist/commands/subsystem/txn/report.js +174 -0
  172. package/dist/commands/subsystem/txn/report.js.map +1 -0
  173. package/dist/commands/subsystem/txn/txn.js +147 -45
  174. package/dist/commands/subsystem/txn/txn.js.map +1 -1
  175. package/dist/commands/subsystem/txn/views.js +200 -21
  176. package/dist/commands/subsystem/txn/views.js.map +1 -1
  177. package/dist/commands/tasks/actions.js +107 -0
  178. package/dist/commands/tasks/actions.js.map +1 -0
  179. package/dist/commands/tasks/render.js +253 -0
  180. package/dist/commands/tasks/render.js.map +1 -0
  181. package/dist/commands/tasks/tasks.js +119 -0
  182. package/dist/commands/tasks/tasks.js.map +1 -0
  183. package/dist/commands/unarchive/manifest.js +42 -26
  184. package/dist/commands/unarchive/manifest.js.map +1 -1
  185. package/dist/commands/unarchive/restore.js +83 -33
  186. package/dist/commands/unarchive/restore.js.map +1 -1
  187. package/dist/commands/unarchive/unarchive.js +22 -30
  188. package/dist/commands/unarchive/unarchive.js.map +1 -1
  189. package/dist/commands/validate/arch-coverage.js +78 -27
  190. package/dist/commands/validate/arch-coverage.js.map +1 -1
  191. package/dist/commands/validate/checks/fleet-shape.js +34 -126
  192. package/dist/commands/validate/checks/fleet-shape.js.map +1 -1
  193. package/dist/commands/validate/checks/health-deps.js +9 -6
  194. package/dist/commands/validate/checks/health-deps.js.map +1 -1
  195. package/dist/commands/validate/checks/introduced.js +102 -0
  196. package/dist/commands/validate/checks/introduced.js.map +1 -0
  197. package/dist/commands/validate/checks/requirements.js +18 -8
  198. package/dist/commands/validate/checks/requirements.js.map +1 -1
  199. package/dist/commands/validate/checks/sources.js +11 -2
  200. package/dist/commands/validate/checks/sources.js.map +1 -1
  201. package/dist/commands/validate/coverage/covers-after.js +105 -0
  202. package/dist/commands/validate/coverage/covers-after.js.map +1 -0
  203. package/dist/commands/validate/feature.js +26 -20
  204. package/dist/commands/validate/feature.js.map +1 -1
  205. package/dist/commands/validate/fleet/census.js +37 -13
  206. package/dist/commands/validate/fleet/census.js.map +1 -1
  207. package/dist/commands/validate/fleet/landscape.js +144 -126
  208. package/dist/commands/validate/fleet/landscape.js.map +1 -1
  209. package/dist/commands/validate/fleet/load.js +66 -0
  210. package/dist/commands/validate/fleet/load.js.map +1 -1
  211. package/dist/commands/validate/fleet/map/attest.js +98 -0
  212. package/dist/commands/validate/fleet/map/attest.js.map +1 -0
  213. package/dist/commands/validate/fleet/map/bindings.js +107 -0
  214. package/dist/commands/validate/fleet/map/bindings.js.map +1 -0
  215. package/dist/commands/validate/fleet/map/consumers.js +244 -0
  216. package/dist/commands/validate/fleet/map/consumers.js.map +1 -0
  217. package/dist/commands/validate/fleet/map/isolation.js +116 -0
  218. package/dist/commands/validate/fleet/map/isolation.js.map +1 -0
  219. package/dist/commands/validate/fleet/map/usecases.js +54 -0
  220. package/dist/commands/validate/fleet/map/usecases.js.map +1 -0
  221. package/dist/commands/validate/fleet/obligations.js +44 -14
  222. package/dist/commands/validate/fleet/obligations.js.map +1 -1
  223. package/dist/commands/validate/fleet/scorecard/print.js +10 -2
  224. package/dist/commands/validate/fleet/scorecard/print.js.map +1 -1
  225. package/dist/commands/validate/fleet/scorecard/scorecard.js +17 -11
  226. package/dist/commands/validate/fleet/scorecard/scorecard.js.map +1 -1
  227. package/dist/commands/validate/fleet/usecases/place.js.map +1 -1
  228. package/dist/commands/validate/fleet/views/fleet-project.js +217 -0
  229. package/dist/commands/validate/fleet/views/fleet-project.js.map +1 -0
  230. package/dist/commands/validate/fleet/views/ids.js +50 -15
  231. package/dist/commands/validate/fleet/views/ids.js.map +1 -1
  232. package/dist/commands/validate/fleet/views/projects.js +278 -0
  233. package/dist/commands/validate/fleet/views/projects.js.map +1 -0
  234. package/dist/commands/validate/fleet/views/root-documents.js +83 -0
  235. package/dist/commands/validate/fleet/views/root-documents.js.map +1 -0
  236. package/dist/commands/validate/fleet/views/stale.js +40 -47
  237. package/dist/commands/validate/fleet/views/stale.js.map +1 -1
  238. package/dist/commands/validate/links/corpus.js +1 -4
  239. package/dist/commands/validate/links/corpus.js.map +1 -1
  240. package/dist/commands/validate/links/glossary.js.map +1 -1
  241. package/dist/commands/validate/render/repeats.js +63 -0
  242. package/dist/commands/validate/render/repeats.js.map +1 -0
  243. package/dist/commands/validate/render/rollups.js +115 -0
  244. package/dist/commands/validate/render/rollups.js.map +1 -0
  245. package/dist/commands/validate/render/text.js +199 -0
  246. package/dist/commands/validate/render/text.js.map +1 -0
  247. package/dist/commands/validate/report.js +36 -160
  248. package/dist/commands/validate/report.js.map +1 -1
  249. package/dist/commands/validate/scope.js +113 -0
  250. package/dist/commands/validate/scope.js.map +1 -0
  251. package/dist/commands/validate/service/api.js +21 -107
  252. package/dist/commands/validate/service/api.js.map +1 -1
  253. package/dist/commands/validate/service/contracts/generated.js +134 -0
  254. package/dist/commands/validate/service/contracts/generated.js.map +1 -0
  255. package/dist/commands/validate/service/events/events.js +36 -14
  256. package/dist/commands/validate/service/events/events.js.map +1 -1
  257. package/dist/commands/validate/service/events/message-producers.js +1 -1
  258. package/dist/commands/validate/service/events/message-producers.js.map +1 -1
  259. package/dist/commands/validate/service/evidence-pins.js +56 -10
  260. package/dist/commands/validate/service/evidence-pins.js.map +1 -1
  261. package/dist/commands/validate/service/model/diverged.js +226 -0
  262. package/dist/commands/validate/service/model/diverged.js.map +1 -0
  263. package/dist/commands/validate/service/model/grade.js +163 -0
  264. package/dist/commands/validate/service/model/grade.js.map +1 -0
  265. package/dist/commands/validate/service/service.js +121 -61
  266. package/dist/commands/validate/service/service.js.map +1 -1
  267. package/dist/commands/validate/service/specs.js +88 -28
  268. package/dist/commands/validate/service/specs.js.map +1 -1
  269. package/dist/commands/validate/service/spine.js +38 -3
  270. package/dist/commands/validate/service/spine.js.map +1 -1
  271. package/dist/commands/validate/service/usecases/tags.js +113 -0
  272. package/dist/commands/validate/service/usecases/tags.js.map +1 -0
  273. package/dist/commands/validate/service/usecases/usecases.js +209 -0
  274. package/dist/commands/validate/service/usecases/usecases.js.map +1 -0
  275. package/dist/commands/validate/validate.js +85 -60
  276. package/dist/commands/validate/validate.js.map +1 -1
  277. package/dist/commands/verify/cross/diff.js +2 -6
  278. package/dist/commands/verify/cross/diff.js.map +1 -1
  279. package/dist/commands/verify/evidence/contract.js +1 -1
  280. package/dist/commands/verify/evidence/contract.js.map +1 -1
  281. package/dist/commands/verify/evidence/read.js +12 -3
  282. package/dist/commands/verify/evidence/read.js.map +1 -1
  283. package/dist/commands/verify/frozen.js +45 -23
  284. package/dist/commands/verify/frozen.js.map +1 -1
  285. package/dist/commands/verify/record.js +69 -17
  286. package/dist/commands/verify/record.js.map +1 -1
  287. package/dist/commands/verify/report.js +27 -44
  288. package/dist/commands/verify/report.js.map +1 -1
  289. package/dist/commands/verify/results.js +112 -30
  290. package/dist/commands/verify/results.js.map +1 -1
  291. package/dist/commands/verify/verify.js +55 -52
  292. package/dist/commands/verify/verify.js.map +1 -1
  293. package/dist/commands/vouch/pack/pack.js +2 -2
  294. package/dist/commands/vouch/pack/pack.js.map +1 -1
  295. package/dist/commands/vouch/pack/print.js +1 -6
  296. package/dist/commands/vouch/pack/print.js.map +1 -1
  297. package/dist/commands/vouch/pack/sections.js +1 -2
  298. package/dist/commands/vouch/pack/sections.js.map +1 -1
  299. package/dist/commands/vouch/run.js +26 -81
  300. package/dist/commands/vouch/run.js.map +1 -1
  301. package/dist/commands/vouch/sample/plan.js +20 -34
  302. package/dist/commands/vouch/sample/plan.js.map +1 -1
  303. package/dist/commands/vouch/vet/verify.js +39 -7
  304. package/dist/commands/vouch/vet/verify.js.map +1 -1
  305. package/dist/commands/vouch/vouch.js +10 -17
  306. package/dist/commands/vouch/vouch.js.map +1 -1
  307. package/dist/core/agent/agents-md/command-map.js +81 -106
  308. package/dist/core/agent/agents-md/command-map.js.map +1 -1
  309. package/dist/core/agent/agents-md/map/explain.js +21 -9
  310. package/dist/core/agent/agents-md/map/explain.js.map +1 -1
  311. package/dist/core/agent/agents-md/map/lenses/context.js +17 -8
  312. package/dist/core/agent/agents-md/map/lenses/context.js.map +1 -1
  313. package/dist/core/agent/agents-md/map/lenses/diff.js +33 -20
  314. package/dist/core/agent/agents-md/map/lenses/diff.js.map +1 -1
  315. package/dist/core/agent/agents-md/map/lenses/gate.js +13 -5
  316. package/dist/core/agent/agents-md/map/lenses/gate.js.map +1 -1
  317. package/dist/core/agent/agents-md/map/mcp.js +10 -7
  318. package/dist/core/agent/agents-md/map/mcp.js.map +1 -1
  319. package/dist/core/agent/agents-md/map/status.js +24 -8
  320. package/dist/core/agent/agents-md/map/status.js.map +1 -1
  321. package/dist/core/agent/agents-md/map/subsystem.js +80 -8
  322. package/dist/core/agent/agents-md/map/subsystem.js.map +1 -1
  323. package/dist/core/agent/agents-md/map/usecases.js +88 -10
  324. package/dist/core/agent/agents-md/map/usecases.js.map +1 -1
  325. package/dist/core/agent/agents-md/refusals.js +49 -22
  326. package/dist/core/agent/agents-md/refusals.js.map +1 -1
  327. package/dist/core/agent/agents-md.js +39 -6
  328. package/dist/core/agent/agents-md.js.map +1 -1
  329. package/dist/core/agent/agents-stamp.js +10 -0
  330. package/dist/core/agent/agents-stamp.js.map +1 -1
  331. package/dist/core/agent/protocol.js +1 -1
  332. package/dist/core/agent/protocol.js.map +1 -1
  333. package/dist/core/agent/scaffold.js +10 -15
  334. package/dist/core/agent/scaffold.js.map +1 -1
  335. package/dist/core/agent/support/report.js +46 -5
  336. package/dist/core/agent/support/report.js.map +1 -1
  337. package/dist/core/agent/tools/dialects.js +1 -0
  338. package/dist/core/agent/tools/dialects.js.map +1 -1
  339. package/dist/core/agent/tools/registry.js +41 -76
  340. package/dist/core/agent/tools/registry.js.map +1 -1
  341. package/dist/core/agent/workflows/adopt.js +158 -11
  342. package/dist/core/agent/workflows/adopt.js.map +1 -1
  343. package/dist/core/agent/workflows/check.js +78 -39
  344. package/dist/core/agent/workflows/check.js.map +1 -1
  345. package/dist/core/agent/workflows/closing.js +88 -27
  346. package/dist/core/agent/workflows/closing.js.map +1 -1
  347. package/dist/core/agent/workflows/feature.js +128 -13
  348. package/dist/core/agent/workflows/feature.js.map +1 -1
  349. package/dist/core/agent/workflows/implement.js +96 -13
  350. package/dist/core/agent/workflows/implement.js.map +1 -1
  351. package/dist/core/agent/workflows/reference/authoring.js +106 -4
  352. package/dist/core/agent/workflows/reference/authoring.js.map +1 -1
  353. package/dist/core/agent/workflows/reference/codes.js +8 -6
  354. package/dist/core/agent/workflows/reference/codes.js.map +1 -1
  355. package/dist/core/agent/workflows/reference/done-check.js +37 -15
  356. package/dist/core/agent/workflows/reference/done-check.js.map +1 -1
  357. package/dist/core/agent/workflows/reference/drawing/drawing.js +253 -0
  358. package/dist/core/agent/workflows/reference/drawing/drawing.js.map +1 -0
  359. package/dist/core/agent/workflows/reference/reference.js +6 -3
  360. package/dist/core/agent/workflows/reference/reference.js.map +1 -1
  361. package/dist/core/agent/workflows/reference/spine.js +68 -27
  362. package/dist/core/agent/workflows/reference/spine.js.map +1 -1
  363. package/dist/core/asyncapi/baseline/plan.js +14 -81
  364. package/dist/core/asyncapi/baseline/plan.js.map +1 -1
  365. package/dist/core/asyncapi/digest.js +30 -25
  366. package/dist/core/asyncapi/digest.js.map +1 -1
  367. package/dist/core/asyncapi/merge/components.js +5 -4
  368. package/dist/core/asyncapi/merge/components.js.map +1 -1
  369. package/dist/core/asyncapi/merge/error.js +7 -2
  370. package/dist/core/asyncapi/merge/error.js.map +1 -1
  371. package/dist/core/asyncapi/merge/markers.js +32 -50
  372. package/dist/core/asyncapi/merge/markers.js.map +1 -1
  373. package/dist/core/asyncapi/merge/merge.js +33 -53
  374. package/dist/core/asyncapi/merge/merge.js.map +1 -1
  375. package/dist/core/asyncapi/merge/pin.js +12 -36
  376. package/dist/core/asyncapi/merge/pin.js.map +1 -1
  377. package/dist/core/asyncapi/model.js.map +1 -1
  378. package/dist/core/asyncapi/read.js +36 -12
  379. package/dist/core/asyncapi/read.js.map +1 -1
  380. package/dist/core/brief/brief.js +96 -36
  381. package/dist/core/brief/brief.js.map +1 -1
  382. package/dist/core/brief/checks.js +138 -3
  383. package/dist/core/brief/checks.js.map +1 -1
  384. package/dist/core/brief/landscape.js +209 -130
  385. package/dist/core/brief/landscape.js.map +1 -1
  386. package/dist/core/brief/map/extend.js +84 -0
  387. package/dist/core/brief/map/extend.js.map +1 -0
  388. package/dist/core/brief/map/owed.js +266 -0
  389. package/dist/core/brief/map/owed.js.map +1 -0
  390. package/dist/core/brief/targets.js +109 -31
  391. package/dist/core/brief/targets.js.map +1 -1
  392. package/dist/core/brief/unchecked.js +14 -3
  393. package/dist/core/brief/unchecked.js.map +1 -1
  394. package/dist/core/c4/arch.js +90 -182
  395. package/dist/core/c4/arch.js.map +1 -1
  396. package/dist/core/c4/direction/direction.js +114 -0
  397. package/dist/core/c4/direction/direction.js.map +1 -0
  398. package/dist/core/c4/likec4.js +169 -14
  399. package/dist/core/c4/likec4.js.map +1 -1
  400. package/dist/core/c4/locate/unlocated.js +150 -0
  401. package/dist/core/c4/locate/unlocated.js.map +1 -0
  402. package/dist/core/c4/parsed/deployment.js +160 -0
  403. package/dist/core/c4/parsed/deployment.js.map +1 -0
  404. package/dist/core/c4/parsed/dynamic-views.js.map +1 -1
  405. package/dist/core/c4/parsed/values.js +54 -1
  406. package/dist/core/c4/parsed/values.js.map +1 -1
  407. package/dist/core/c4/parsed/view-ids.js +39 -1
  408. package/dist/core/c4/parsed/view-ids.js.map +1 -1
  409. package/dist/core/c4/prefetch/fleet.js +134 -0
  410. package/dist/core/c4/prefetch/fleet.js.map +1 -0
  411. package/dist/core/c4/project/architecture.js +123 -7
  412. package/dist/core/c4/project/architecture.js.map +1 -1
  413. package/dist/core/c4/project/batch.js +140 -0
  414. package/dist/core/c4/project/batch.js.map +1 -0
  415. package/dist/core/c4/project/documents.js +43 -12
  416. package/dist/core/c4/project/documents.js.map +1 -1
  417. package/dist/core/c4/project/load.js +79 -43
  418. package/dist/core/c4/project/load.js.map +1 -1
  419. package/dist/core/c4/project/staged.js +277 -0
  420. package/dist/core/c4/project/staged.js.map +1 -0
  421. package/dist/core/c4/resolve/attested.js +0 -0
  422. package/dist/core/c4/resolve/attested.js.map +1 -0
  423. package/dist/core/c4/resolve/external.js +51 -0
  424. package/dist/core/c4/resolve/external.js.map +1 -0
  425. package/dist/core/c4/resolve/service.js +78 -17
  426. package/dist/core/c4/resolve/service.js.map +1 -1
  427. package/dist/core/c4/resolve/steps.js +290 -0
  428. package/dist/core/c4/resolve/steps.js.map +1 -0
  429. package/dist/core/c4/resolve/systems.js +154 -0
  430. package/dist/core/c4/resolve/systems.js.map +1 -0
  431. package/dist/core/c4/root-project/exclude.js +352 -0
  432. package/dist/core/c4/root-project/exclude.js.map +1 -0
  433. package/dist/core/c4/seed/template.js +65 -1
  434. package/dist/core/c4/seed/template.js.map +1 -1
  435. package/dist/core/c4/service-model/created/models.js +96 -0
  436. package/dist/core/c4/service-model/created/models.js.map +1 -0
  437. package/dist/core/c4/service-model/documents.js +47 -0
  438. package/dist/core/c4/service-model/documents.js.map +1 -0
  439. package/dist/core/c4/service-model/fleet/extending.js +82 -0
  440. package/dist/core/c4/service-model/fleet/extending.js.map +1 -0
  441. package/dist/core/c4/service-model/load.js +165 -0
  442. package/dist/core/c4/service-model/load.js.map +1 -0
  443. package/dist/core/c4/service-model/renderer.js +128 -0
  444. package/dist/core/c4/service-model/renderer.js.map +1 -0
  445. package/dist/core/c4/service-model/shape.js +106 -0
  446. package/dist/core/c4/service-model/shape.js.map +1 -0
  447. package/dist/core/c4/service-model/slice.js +188 -0
  448. package/dist/core/c4/service-model/slice.js.map +1 -0
  449. package/dist/core/c4/source-mask.js +297 -10
  450. package/dist/core/c4/source-mask.js.map +1 -1
  451. package/dist/core/c4/source-scan.js +222 -141
  452. package/dist/core/c4/source-scan.js.map +1 -1
  453. package/dist/core/c4/splice/authored-source.js +79 -13
  454. package/dist/core/c4/splice/authored-source.js.map +1 -1
  455. package/dist/core/c4/splice/contract.js +20 -0
  456. package/dist/core/c4/splice/contract.js.map +1 -1
  457. package/dist/core/c4/splice/delta-blocks.js +20 -20
  458. package/dist/core/c4/splice/delta-blocks.js.map +1 -1
  459. package/dist/core/c4/splice/identity/declared.js +87 -0
  460. package/dist/core/c4/splice/identity/declared.js.map +1 -0
  461. package/dist/core/c4/splice/identity/edges.js +37 -0
  462. package/dist/core/c4/splice/identity/edges.js.map +1 -1
  463. package/dist/core/c4/splice/identity/existing.js +80 -0
  464. package/dist/core/c4/splice/identity/existing.js.map +1 -0
  465. package/dist/core/c4/splice/identity/interior.js +80 -0
  466. package/dist/core/c4/splice/identity/interior.js.map +1 -0
  467. package/dist/core/c4/splice/identity/owner.js +50 -0
  468. package/dist/core/c4/splice/identity/owner.js.map +1 -0
  469. package/dist/core/c4/splice/landscape-merge.js +182 -114
  470. package/dist/core/c4/splice/landscape-merge.js.map +1 -1
  471. package/dist/core/c4/splice/model/merge.js +151 -0
  472. package/dist/core/c4/splice/model/merge.js.map +1 -0
  473. package/dist/core/c4/splice/placement.js +160 -56
  474. package/dist/core/c4/splice/placement.js.map +1 -1
  475. package/dist/core/c4/splice/text/spot.js +131 -0
  476. package/dist/core/c4/splice/text/spot.js.map +1 -0
  477. package/dist/core/c4/workspace.js +13 -19
  478. package/dist/core/c4/workspace.js.map +1 -1
  479. package/dist/core/capabilities/capabilities.js +6 -6
  480. package/dist/core/capabilities/capabilities.js.map +1 -1
  481. package/dist/core/capabilities/delta/doc.js +7 -10
  482. package/dist/core/capabilities/delta/doc.js.map +1 -1
  483. package/dist/core/capabilities/delta/uncovered.js +2 -2
  484. package/dist/core/capabilities/delta/uncovered.js.map +1 -1
  485. package/dist/core/capabilities/findings.js +18 -22
  486. package/dist/core/capabilities/findings.js.map +1 -1
  487. package/dist/core/capabilities/realizes/findings.js +12 -19
  488. package/dist/core/capabilities/realizes/findings.js.map +1 -1
  489. package/dist/core/capabilities/realizes/join.js +0 -20
  490. package/dist/core/capabilities/realizes/join.js.map +1 -1
  491. package/dist/core/capabilities/rollup.js +6 -0
  492. package/dist/core/capabilities/rollup.js.map +1 -1
  493. package/dist/core/capabilities/tree.js +6 -28
  494. package/dist/core/capabilities/tree.js.map +1 -1
  495. package/dist/core/capabilities/usecase-join.js +3 -13
  496. package/dist/core/capabilities/usecase-join.js.map +1 -1
  497. package/dist/core/coherence/authoring/scaffold.js +11 -3
  498. package/dist/core/coherence/authoring/scaffold.js.map +1 -1
  499. package/dist/core/coherence/authoring/sentinels.js +2 -1
  500. package/dist/core/coherence/authoring/sentinels.js.map +1 -1
  501. package/dist/core/coherence/calls/called.js +52 -0
  502. package/dist/core/coherence/calls/called.js.map +1 -0
  503. package/dist/core/coherence/coherence.js +103 -22
  504. package/dist/core/coherence/coherence.js.map +1 -1
  505. package/dist/core/coherence/consumed/operations.js +70 -0
  506. package/dist/core/coherence/consumed/operations.js.map +1 -0
  507. package/dist/core/coherence/consumed/refusal.js +38 -0
  508. package/dist/core/coherence/consumed/refusal.js.map +1 -0
  509. package/dist/core/coherence/covers/health.js +85 -0
  510. package/dist/core/coherence/covers/health.js.map +1 -0
  511. package/dist/core/coherence/declared.js +60 -34
  512. package/dist/core/coherence/declared.js.map +1 -1
  513. package/dist/core/coherence/events/declared.js +44 -59
  514. package/dist/core/coherence/events/declared.js.map +1 -1
  515. package/dist/core/coherence/events/events.js +147 -16
  516. package/dist/core/coherence/events/events.js.map +1 -1
  517. package/dist/core/coherence/events/grades.js +31 -8
  518. package/dist/core/coherence/events/grades.js.map +1 -1
  519. package/dist/core/coherence/events/lookups.js +28 -87
  520. package/dist/core/coherence/events/lookups.js.map +1 -1
  521. package/dist/core/coherence/events/produced.js +100 -0
  522. package/dist/core/coherence/events/produced.js.map +1 -0
  523. package/dist/core/coherence/lookups.js +18 -78
  524. package/dist/core/coherence/lookups.js.map +1 -1
  525. package/dist/core/coherence/retired/archived.js +285 -0
  526. package/dist/core/coherence/retired/archived.js.map +1 -0
  527. package/dist/core/coherence/retired/event-pair.js +62 -0
  528. package/dist/core/coherence/retired/event-pair.js.map +1 -0
  529. package/dist/core/coherence/retired/merged.js +79 -0
  530. package/dist/core/coherence/retired/merged.js.map +1 -0
  531. package/dist/core/coherence/retired/retirement.js +49 -0
  532. package/dist/core/coherence/retired/retirement.js.map +1 -0
  533. package/dist/core/coherence/retired/revival/arrivals.js +131 -0
  534. package/dist/core/coherence/retired/revival/arrivals.js.map +1 -0
  535. package/dist/core/coherence/retired/revival/revived.js +297 -0
  536. package/dist/core/coherence/retired/revival/revived.js.map +1 -0
  537. package/dist/core/consumers/after.js +113 -0
  538. package/dist/core/consumers/after.js.map +1 -0
  539. package/dist/core/consumers/consumers.js +296 -0
  540. package/dist/core/consumers/consumers.js.map +1 -0
  541. package/dist/core/consumers/current.js +211 -0
  542. package/dist/core/consumers/current.js.map +1 -0
  543. package/dist/core/consumers/scan.js +46 -0
  544. package/dist/core/consumers/scan.js.map +1 -0
  545. package/dist/core/consumers/state.js +27 -0
  546. package/dist/core/consumers/state.js.map +1 -0
  547. package/dist/core/delta/delta.js +51 -6
  548. package/dist/core/delta/delta.js.map +1 -1
  549. package/dist/core/dependencies/fanin.js +2 -2
  550. package/dist/core/dependencies/fanin.js.map +1 -1
  551. package/dist/core/deployment/delta.js +191 -0
  552. package/dist/core/deployment/delta.js.map +1 -0
  553. package/dist/core/deployment/objects.js +145 -0
  554. package/dist/core/deployment/objects.js.map +1 -0
  555. package/dist/core/diff/base-git.js +94 -12
  556. package/dist/core/diff/base-git.js.map +1 -1
  557. package/dist/core/diff/base-state.js +49 -21
  558. package/dist/core/diff/base-state.js.map +1 -1
  559. package/dist/core/diff/joins.js +136 -0
  560. package/dist/core/diff/joins.js.map +1 -0
  561. package/dist/core/diff/scope/changed-paths.js +22 -6
  562. package/dist/core/diff/scope/changed-paths.js.map +1 -1
  563. package/dist/core/diff/scope/edges.js +82 -0
  564. package/dist/core/diff/scope/edges.js.map +1 -0
  565. package/dist/core/diff/semantic.js +100 -31
  566. package/dist/core/diff/semantic.js.map +1 -1
  567. package/dist/core/docs.js +31 -22
  568. package/dist/core/docs.js.map +1 -1
  569. package/dist/core/doctor/agents.js +34 -18
  570. package/dist/core/doctor/agents.js.map +1 -1
  571. package/dist/core/doctor/config.js +7 -3
  572. package/dist/core/doctor/config.js.map +1 -1
  573. package/dist/core/doctor/doctor.js +91 -11
  574. package/dist/core/doctor/doctor.js.map +1 -1
  575. package/dist/core/doctor/report.js.map +1 -1
  576. package/dist/core/doctor/reports/scan.js +242 -0
  577. package/dist/core/doctor/reports/scan.js.map +1 -0
  578. package/dist/core/document/apply.js +158 -11
  579. package/dist/core/document/apply.js.map +1 -1
  580. package/dist/core/document/frontmatter.js +55 -0
  581. package/dist/core/document/frontmatter.js.map +1 -1
  582. package/dist/core/document/parse.js +29 -6
  583. package/dist/core/document/parse.js.map +1 -1
  584. package/dist/core/document/scenarios.js +17 -0
  585. package/dist/core/document/scenarios.js.map +1 -1
  586. package/dist/core/document/spec.js +4 -11
  587. package/dist/core/document/spec.js.map +1 -1
  588. package/dist/core/envelope/config.js +10 -0
  589. package/dist/core/envelope/config.js.map +1 -1
  590. package/dist/core/envelope/json.js +34 -0
  591. package/dist/core/envelope/json.js.map +1 -1
  592. package/dist/core/explain/families.js +26 -21
  593. package/dist/core/explain/families.js.map +1 -1
  594. package/dist/core/explain/lookup.js +14 -1
  595. package/dist/core/explain/lookup.js.map +1 -1
  596. package/dist/core/explain/refusals.js +5 -5
  597. package/dist/core/explain/refusals.js.map +1 -1
  598. package/dist/core/explain/terms/documents.js +227 -0
  599. package/dist/core/explain/terms/documents.js.map +1 -0
  600. package/dist/core/explain/terms/done-check.js +144 -0
  601. package/dist/core/explain/terms/done-check.js.map +1 -0
  602. package/dist/core/explain/terms/entry.js +14 -0
  603. package/dist/core/explain/terms/entry.js.map +1 -0
  604. package/dist/core/explain/terms/stages.js +71 -0
  605. package/dist/core/explain/terms/stages.js.map +1 -0
  606. package/dist/core/explain/terms/tasks.js +97 -0
  607. package/dist/core/explain/terms/tasks.js.map +1 -0
  608. package/dist/core/explain/terms.js +68 -109
  609. package/dist/core/explain/terms.js.map +1 -1
  610. package/dist/core/explore/explore.js +40 -10
  611. package/dist/core/explore/explore.js.map +1 -1
  612. package/dist/core/fleet-context.js +81 -95
  613. package/dist/core/fleet-context.js.map +1 -1
  614. package/dist/core/gate/checks.js +11 -4
  615. package/dist/core/gate/checks.js.map +1 -1
  616. package/dist/core/gate/partners.js +69 -28
  617. package/dist/core/gate/partners.js.map +1 -1
  618. package/dist/core/gate/report.js.map +1 -1
  619. package/dist/core/gate/verification.js +75 -12
  620. package/dist/core/gate/verification.js.map +1 -1
  621. package/dist/core/gherkin/stale.js +13 -37
  622. package/dist/core/gherkin/stale.js.map +1 -1
  623. package/dist/core/glossary/delta.js +10 -7
  624. package/dist/core/glossary/delta.js.map +1 -1
  625. package/dist/core/glossary/tree.js +6 -19
  626. package/dist/core/glossary/tree.js.map +1 -1
  627. package/dist/core/kernel/concurrency.js +19 -0
  628. package/dist/core/kernel/concurrency.js.map +1 -1
  629. package/dist/core/kernel/ids/fqn/ancestors.js +65 -0
  630. package/dist/core/kernel/ids/fqn/ancestors.js.map +1 -0
  631. package/dist/core/kernel/path-safety.js +38 -0
  632. package/dist/core/kernel/path-safety.js.map +1 -1
  633. package/dist/core/kernel/records.js +11 -0
  634. package/dist/core/kernel/records.js.map +1 -1
  635. package/dist/core/links/backlinks.js +1 -3
  636. package/dist/core/links/backlinks.js.map +1 -1
  637. package/dist/core/links/corpus.js +51 -37
  638. package/dist/core/links/corpus.js.map +1 -1
  639. package/dist/core/links/findings.js.map +1 -1
  640. package/dist/core/links/parse.js +38 -9
  641. package/dist/core/links/parse.js.map +1 -1
  642. package/dist/core/mcp/argv.js +101 -0
  643. package/dist/core/mcp/argv.js.map +1 -1
  644. package/dist/core/mcp/author-tools.js +2 -1
  645. package/dist/core/mcp/author-tools.js.map +1 -1
  646. package/dist/core/mcp/protocol.js +2 -2
  647. package/dist/core/mcp/protocol.js.map +1 -1
  648. package/dist/core/mcp/tools.js +43 -33
  649. package/dist/core/mcp/tools.js.map +1 -1
  650. package/dist/core/openapi/baseline/gate.js +53 -12
  651. package/dist/core/openapi/baseline/gate.js.map +1 -1
  652. package/dist/core/openapi/baseline/plan.js +40 -10
  653. package/dist/core/openapi/baseline/plan.js.map +1 -1
  654. package/dist/core/openapi/baseline/record.js +0 -1
  655. package/dist/core/openapi/baseline/record.js.map +1 -1
  656. package/dist/core/openapi/contract-text.js +33 -0
  657. package/dist/core/openapi/contract-text.js.map +1 -0
  658. package/dist/core/openapi/contract-tree.js +301 -0
  659. package/dist/core/openapi/contract-tree.js.map +1 -0
  660. package/dist/core/openapi/depth.js +38 -24
  661. package/dist/core/openapi/depth.js.map +1 -1
  662. package/dist/core/openapi/digest.js +52 -2
  663. package/dist/core/openapi/digest.js.map +1 -1
  664. package/dist/core/openapi/doc.js +12 -4
  665. package/dist/core/openapi/doc.js.map +1 -1
  666. package/dist/core/openapi/merge/components.js +25 -60
  667. package/dist/core/openapi/merge/components.js.map +1 -1
  668. package/dist/core/openapi/merge/error.js +3 -13
  669. package/dist/core/openapi/merge/error.js.map +1 -1
  670. package/dist/core/openapi/merge/markers.js +26 -30
  671. package/dist/core/openapi/merge/markers.js.map +1 -1
  672. package/dist/core/openapi/merge/merge.js +28 -52
  673. package/dist/core/openapi/merge/merge.js.map +1 -1
  674. package/dist/core/openapi/merge/pin.js +17 -35
  675. package/dist/core/openapi/merge/pin.js.map +1 -1
  676. package/dist/core/openspec/decide/verdict.js.map +1 -1
  677. package/dist/core/openspec/inventory.js +4 -5
  678. package/dist/core/openspec/inventory.js.map +1 -1
  679. package/dist/core/openspec/model/mapping.js +30 -28
  680. package/dist/core/openspec/model/mapping.js.map +1 -1
  681. package/dist/core/openspec/model/model.js +12 -7
  682. package/dist/core/openspec/model/model.js.map +1 -1
  683. package/dist/core/openspec/scan/changes.js +10 -4
  684. package/dist/core/openspec/scan/changes.js.map +1 -1
  685. package/dist/core/openspec/scan/config.js +7 -16
  686. package/dist/core/openspec/scan/config.js.map +1 -1
  687. package/dist/core/openspec/scan/shape.js +63 -19
  688. package/dist/core/openspec/scan/shape.js.map +1 -1
  689. package/dist/core/openspec/scan/walk.js +21 -38
  690. package/dist/core/openspec/scan/walk.js.map +1 -1
  691. package/dist/core/pack/living.js +43 -4
  692. package/dist/core/pack/living.js.map +1 -1
  693. package/dist/core/pack/pack.js +50 -6
  694. package/dist/core/pack/pack.js.map +1 -1
  695. package/dist/core/projection/arch-slice.js +2 -2
  696. package/dist/core/projection/arch-slice.js.map +1 -1
  697. package/dist/core/projection/introduced.js +14 -0
  698. package/dist/core/projection/introduced.js.map +1 -0
  699. package/dist/core/provenance/findings.js +48 -12
  700. package/dist/core/provenance/findings.js.map +1 -1
  701. package/dist/core/provenance/git.js +33 -57
  702. package/dist/core/provenance/git.js.map +1 -1
  703. package/dist/core/provenance/gitq/moves.js +71 -114
  704. package/dist/core/provenance/gitq/moves.js.map +1 -1
  705. package/dist/core/provenance/gitq/vouched-ancestor.js +2 -2
  706. package/dist/core/provenance/gitq/vouched-ancestor.js.map +1 -1
  707. package/dist/core/provenance/sources.js +23 -6
  708. package/dist/core/provenance/sources.js.map +1 -1
  709. package/dist/core/provenance/stamp.js +5 -17
  710. package/dist/core/provenance/stamp.js.map +1 -1
  711. package/dist/core/repo/authored/paths.js +18 -0
  712. package/dist/core/repo/authored/paths.js.map +1 -1
  713. package/dist/core/repo/entries.js.map +1 -1
  714. package/dist/core/repo/paths.js +92 -6
  715. package/dist/core/repo/paths.js.map +1 -1
  716. package/dist/core/repo/repo.js +74 -14
  717. package/dist/core/repo/repo.js.map +1 -1
  718. package/dist/core/repo/tree/find.js +12 -3
  719. package/dist/core/repo/tree/find.js.map +1 -1
  720. package/dist/core/repo/tree/fs.js +27 -1
  721. package/dist/core/repo/tree/fs.js.map +1 -1
  722. package/dist/core/repo/tree/render/body.js +258 -0
  723. package/dist/core/repo/tree/render/body.js.map +1 -0
  724. package/dist/core/repo/tree/render/projects.js +182 -0
  725. package/dist/core/repo/tree/render/projects.js.map +1 -0
  726. package/dist/core/repo/tree/render/service/header.js +125 -0
  727. package/dist/core/repo/tree/render/service/header.js.map +1 -0
  728. package/dist/core/repo/tree/render/service/peers.js +28 -0
  729. package/dist/core/repo/tree/render/service/peers.js.map +1 -0
  730. package/dist/core/repo/tree/render/service/view-id.js +67 -0
  731. package/dist/core/repo/tree/render/service/view-id.js.map +1 -0
  732. package/dist/core/repo/tree/render/service/views.js +78 -0
  733. package/dist/core/repo/tree/render/service/views.js.map +1 -0
  734. package/dist/core/repo/tree/render/stale.js +42 -0
  735. package/dist/core/repo/tree/render/stale.js.map +1 -0
  736. package/dist/core/repo/tree/render/text.js +84 -0
  737. package/dist/core/repo/tree/render/text.js.map +1 -0
  738. package/dist/core/repo/tree/render/views.js +293 -0
  739. package/dist/core/repo/tree/render/views.js.map +1 -0
  740. package/dist/core/repo/tree/walk.js +53 -32
  741. package/dist/core/repo/tree/walk.js.map +1 -1
  742. package/dist/core/results.js +47 -12
  743. package/dist/core/results.js.map +1 -1
  744. package/dist/core/scaffold/landscape.js +121 -13
  745. package/dist/core/scaffold/landscape.js.map +1 -1
  746. package/dist/core/scaffold/legacy.js +271 -0
  747. package/dist/core/scaffold/legacy.js.map +1 -0
  748. package/dist/core/staging/commit.js +26 -15
  749. package/dist/core/staging/commit.js.map +1 -1
  750. package/dist/core/staging/lock.js +74 -12
  751. package/dist/core/staging/lock.js.map +1 -1
  752. package/dist/core/staging/recovery/intent.js +2 -5
  753. package/dist/core/staging/recovery/intent.js.map +1 -1
  754. package/dist/core/staging/recovery/recover.js +84 -6
  755. package/dist/core/staging/recovery/recover.js.map +1 -1
  756. package/dist/core/staging/snapshot/manifest.js +188 -0
  757. package/dist/core/staging/snapshot/manifest.js.map +1 -0
  758. package/dist/core/staging/{snapshot.js → snapshot/snapshot.js} +39 -45
  759. package/dist/core/staging/snapshot/snapshot.js.map +1 -0
  760. package/dist/core/staging/txn/forward.js +24 -14
  761. package/dist/core/staging/txn/forward.js.map +1 -1
  762. package/dist/core/staging/writes.js.map +1 -1
  763. package/dist/core/status/actions/execution.js +11 -0
  764. package/dist/core/status/actions/execution.js.map +1 -1
  765. package/dist/core/status/contracts.js +39 -15
  766. package/dist/core/status/contracts.js.map +1 -1
  767. package/dist/core/status/feature/artifacts.js +33 -8
  768. package/dist/core/status/feature/artifacts.js.map +1 -1
  769. package/dist/core/status/feature/feature.js +24 -17
  770. package/dist/core/status/feature/feature.js.map +1 -1
  771. package/dist/core/status/feature/next.js +20 -7
  772. package/dist/core/status/feature/next.js.map +1 -1
  773. package/dist/core/status/feature/words.js +96 -0
  774. package/dist/core/status/feature/words.js.map +1 -0
  775. package/dist/core/status/fleet/fleet.js +43 -14
  776. package/dist/core/status/fleet/fleet.js.map +1 -1
  777. package/dist/core/status/fleet/next.js +153 -58
  778. package/dist/core/status/fleet/next.js.map +1 -1
  779. package/dist/core/status/report.js.map +1 -1
  780. package/dist/core/status/scan.js.map +1 -1
  781. package/dist/core/status/verification.js +30 -15
  782. package/dist/core/status/verification.js.map +1 -1
  783. package/dist/core/tasks/packet.js +199 -0
  784. package/dist/core/tasks/packet.js.map +1 -0
  785. package/dist/core/tasks/record.js +43 -0
  786. package/dist/core/tasks/record.js.map +1 -0
  787. package/dist/core/tasks/sources.js +181 -0
  788. package/dist/core/tasks/sources.js.map +1 -0
  789. package/dist/core/tasks/stamps.js +76 -0
  790. package/dist/core/tasks/stamps.js.map +1 -0
  791. package/dist/core/tasks/unit.js +0 -0
  792. package/dist/core/tasks/unit.js.map +1 -0
  793. package/dist/core/usecases/capability.js +11 -14
  794. package/dist/core/usecases/capability.js.map +1 -1
  795. package/dist/core/usecases/delta/claims.js +31 -7
  796. package/dist/core/usecases/delta/claims.js.map +1 -1
  797. package/dist/core/usecases/delta/flows.js +5 -7
  798. package/dist/core/usecases/delta/flows.js.map +1 -1
  799. package/dist/core/usecases/delta/modified.js +315 -0
  800. package/dist/core/usecases/delta/modified.js.map +1 -0
  801. package/dist/core/usecases/delta/overlay.js +32 -191
  802. package/dist/core/usecases/delta/overlay.js.map +1 -1
  803. package/dist/core/usecases/fleet.js +195 -36
  804. package/dist/core/usecases/fleet.js.map +1 -1
  805. package/dist/{commands/validate/fleet/usecases → core/usecases/grade}/capability-tag.js +8 -9
  806. package/dist/core/usecases/grade/capability-tag.js.map +1 -0
  807. package/dist/core/usecases/grade/feature.js +88 -0
  808. package/dist/core/usecases/grade/feature.js.map +1 -0
  809. package/dist/{commands/validate/fleet/usecases → core/usecases/grade}/requirement-tag.js +3 -4
  810. package/dist/core/usecases/grade/requirement-tag.js.map +1 -0
  811. package/dist/{commands/validate/fleet/usecases → core/usecases/grade}/steps.js +102 -33
  812. package/dist/core/usecases/grade/steps.js.map +1 -0
  813. package/dist/{commands/validate/fleet/usecases → core/usecases/grade}/usecases.js +23 -10
  814. package/dist/core/usecases/grade/usecases.js.map +1 -0
  815. package/dist/core/usecases/operations.js +26 -14
  816. package/dist/core/usecases/operations.js.map +1 -1
  817. package/dist/core/usecases/place.js.map +1 -1
  818. package/dist/core/usecases/service/exclude.js +119 -0
  819. package/dist/core/usecases/service/exclude.js.map +1 -0
  820. package/dist/core/usecases/service/flows.js +164 -0
  821. package/dist/core/usecases/service/flows.js.map +1 -0
  822. package/dist/core/usecases/suites/participants.js +83 -0
  823. package/dist/core/usecases/suites/participants.js.map +1 -0
  824. package/dist/core/usecases/suites/suites.js +45 -0
  825. package/dist/core/usecases/suites/suites.js.map +1 -0
  826. package/dist/core/verify/answers.js +12 -5
  827. package/dist/core/verify/answers.js.map +1 -1
  828. package/dist/core/verify/build.js +102 -82
  829. package/dist/core/verify/build.js.map +1 -1
  830. package/dist/core/verify/checklist.js +70 -12
  831. package/dist/core/verify/checklist.js.map +1 -1
  832. package/dist/core/verify/location.js +67 -0
  833. package/dist/core/verify/location.js.map +1 -0
  834. package/dist/core/verify/pins/lint.js +3 -2
  835. package/dist/core/verify/pins/lint.js.map +1 -1
  836. package/dist/core/verify/pins/pin.js +1 -1
  837. package/dist/core/verify/pins/pin.js.map +1 -1
  838. package/dist/core/verify/read/file.js +224 -0
  839. package/dist/core/verify/read/file.js.map +1 -0
  840. package/dist/core/verify/{file.js → read/shape.js} +16 -104
  841. package/dist/core/verify/read/shape.js.map +1 -0
  842. package/dist/core/verify/read/union.js +105 -0
  843. package/dist/core/verify/read/union.js.map +1 -0
  844. package/dist/core/verify/record.js +35 -12
  845. package/dist/core/verify/record.js.map +1 -1
  846. package/dist/core/verify/store/commit.js +40 -30
  847. package/dist/core/verify/store/commit.js.map +1 -1
  848. package/dist/core/verify/store/render.js +8 -4
  849. package/dist/core/verify/store/render.js.map +1 -1
  850. package/dist/core/vocabulary/issue.js +4 -0
  851. package/dist/core/vocabulary/issue.js.map +1 -1
  852. package/dist/core/vocabulary/maturity.js +75 -4
  853. package/dist/core/vocabulary/maturity.js.map +1 -1
  854. package/dist/core/vocabulary/report.js +16 -1
  855. package/dist/core/vocabulary/report.js.map +1 -1
  856. package/examples/README.md +54 -11
  857. package/examples/docs/architecture/landscape.likec4 +62 -6
  858. package/examples/docs/architecture/services.likec4 +70 -0
  859. package/examples/docs/architecture/subsystems.likec4 +7 -0
  860. package/examples/docs/architecture/usecases/order-notification.likec4 +16 -7
  861. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-service/asyncapi.yaml +11 -8
  862. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/openapi.yaml +6 -6
  863. package/examples/docs/features/FEAT-112-retire-order-v1/specs/order-service/openapi.yaml +4 -1
  864. package/examples/docs/features/archive/FEAT-088-refunds/specs/payment-service/openapi.yaml +13 -10
  865. package/examples/docs/likec4.config.json +0 -1
  866. package/examples/docs/services/checkout-web/model.likec4 +39 -56
  867. package/examples/docs/services/order-service/arch.spec.md +13 -6
  868. package/examples/docs/services/order-service/asyncapi.yaml +3 -2
  869. package/examples/docs/services/order-service/model.likec4 +58 -70
  870. package/examples/docs/services/payment-service/arch.spec.md +7 -4
  871. package/examples/docs/services/payment-service/model.likec4 +38 -37
  872. package/examples/docs/services/platform/identity-service/arch.spec.md +7 -4
  873. package/examples/docs/services/platform/identity-service/model.likec4 +35 -37
  874. package/examples/docs/services/platform/notification-service/asyncapi.yaml +2 -1
  875. package/examples/docs/services/platform/notification-service/health.yaml +8 -3
  876. package/examples/docs/services/platform/notification-service/model.likec4 +43 -64
  877. package/package.json +1 -1
  878. package/dist/commands/validate/checks/vocabulary.js +0 -31
  879. package/dist/commands/validate/checks/vocabulary.js.map +0 -1
  880. package/dist/commands/validate/fleet/usecases/capability-tag.js.map +0 -1
  881. package/dist/commands/validate/fleet/usecases/requirement-tag.js.map +0 -1
  882. package/dist/commands/validate/fleet/usecases/steps.js.map +0 -1
  883. package/dist/commands/validate/fleet/usecases/usecases.js.map +0 -1
  884. package/dist/core/agent/agents-md/artifacts.js +0 -220
  885. package/dist/core/agent/agents-md/artifacts.js.map +0 -1
  886. package/dist/core/agent/agents-md/cycle.js +0 -165
  887. package/dist/core/agent/agents-md/cycle.js.map +0 -1
  888. package/dist/core/agent/agents-md/shipped/archive-gate.js +0 -98
  889. package/dist/core/agent/agents-md/shipped/archive-gate.js.map +0 -1
  890. package/dist/core/agent/agents-md/spine.js +0 -40
  891. package/dist/core/agent/agents-md/spine.js.map +0 -1
  892. package/dist/core/coherence/events/merged.js +0 -40
  893. package/dist/core/coherence/events/merged.js.map +0 -1
  894. package/dist/core/diff/current-state.js +0 -96
  895. package/dist/core/diff/current-state.js.map +0 -1
  896. package/dist/core/diff/victims.js +0 -247
  897. package/dist/core/diff/victims.js.map +0 -1
  898. package/dist/core/repo/tree/views.js +0 -172
  899. package/dist/core/repo/tree/views.js.map +0 -1
  900. package/dist/core/staging/snapshot.js.map +0 -1
  901. package/dist/core/verify/file.js.map +0 -1
@@ -4,8 +4,19 @@
4
4
  * Separate from `./json.ts` because the two answer different readers and only
5
5
  * one of them is a contract. This side may be reworded freely; the payload
6
6
  * beside it may not.
7
+ *
8
+ * Which is also why no bare stage word leads a line here any more. `stage` is a
9
+ * value an agent branches on, and `ready` printed alone over a feature with
10
+ * nothing built read to a person as "ready to ship". The sentence comes from
11
+ * `stageWords` (core/status/feature/words.ts) — the same one the `next[]`
12
+ * statements quote — with the counts that make it true, and the machine value
13
+ * rides in its own row for whoever needs to map the two.
7
14
  */
15
+ import { answeredSplit } from "../../core/verify/record.js";
8
16
  import { SEVERITY_MARK } from "../../core/vocabulary/report.js";
17
+ import { unshippable } from "../../core/status/feature/next.js";
18
+ import { featureLabel, fleetStageWords, stageWords } from "../../core/status/feature/words.js";
19
+ import { printFleetNext, printNext } from "./fleet-next.js";
9
20
  function pad(values) {
10
21
  return Math.max(0, ...values.map((v) => v.length));
11
22
  }
@@ -27,36 +38,58 @@ function printInterrupted(i) {
27
38
  function artifactLabel(a) {
28
39
  return a.service === null ? a.id : `${a.id} (${a.service})`;
29
40
  }
41
+ /**
42
+ * An artifact row's status, in words. The machine value is `done` for a file
43
+ * that is written AND for one the feature does not owe, and `ready` for a
44
+ * verification record whose claims are still open — three readings a person
45
+ * cannot tell apart from one word, and the reason a table of `done` rows read
46
+ * as finished work over a feature nobody had built.
47
+ */
48
+ function artifactWord(a, v) {
49
+ if (a.id === "verification") {
50
+ if (a.status === "missing")
51
+ return "none yet";
52
+ // An attested record is complete and rests on an agent's word; "open"
53
+ // over it contradicted the header that says every claim is answered.
54
+ if (a.status === "ready")
55
+ return v.verdict === "attested" ? "attested" : "open";
56
+ if (a.status === "done")
57
+ return "verified";
58
+ if (a.status === "draft")
59
+ return v.state === "stale" ? "stale" : "unreadable";
60
+ return a.status;
61
+ }
62
+ if (a.status === "done")
63
+ return a.exists ? "written" : "not owed";
64
+ if (a.status === "draft")
65
+ return "has errors";
66
+ return a.status;
67
+ }
30
68
  /**
31
69
  * The counts come from the record's `claims:` array (verify's `tallyRecord`),
32
70
  * never from its `summary:` block. The verdict is printed beside the state
33
71
  * because they answer different questions and only together are they honest:
34
72
  * `recorded 4/4 confirmed` used to be the whole line for a feature `verify`
35
73
  * calls `attested` — complete, and resting on somebody's word about a test.
74
+ * Who answered the confirmed ones rides right after the count for the same
75
+ * reason one step further: `verified` turns on the scenario claims alone, and
76
+ * `verified 19/19 confirmed` read as nineteen runs over a record where six
77
+ * answers were an agent's word about a permission or an edge.
78
+ *
79
+ * With no record, the line says how many claims there ARE to answer, when the
80
+ * report knows (`checklist`): "none" alone read as "nothing to do".
36
81
  */
37
- function verificationLine(v) {
82
+ function verificationLine(v, asked) {
38
83
  if (v.state === "absent")
39
- return "none";
84
+ return asked === null ? "none — no record" : `none yet — ${asked} claim(s) to answer`;
40
85
  if (v.state === "unreadable")
41
86
  return "unreadable";
42
87
  return (`${v.state} · ${v.verdict} ${v.confirmed}/${v.claims} confirmed` +
88
+ (v.confirmed > 0 ? ` (${answeredSplit(v.answered)})` : "") +
43
89
  (v.unanswered > 0 ? ` · ${v.unanswered} unanswered` : "") +
44
90
  (v.attested > 0 ? ` · ${v.attested} scenario(s) on an agent's word, not a test run` : "") +
45
91
  ` (recorded ${v.recorded ?? "?"})`);
46
92
  }
47
- /**
48
- * The steps, numbered, with the command on its own indented line — doctor's
49
- * layout, for doctor's reason: what to do and what to type are two different
50
- * sentences, and someone scanning a half-built feature reads down the `run:`
51
- * column.
52
- */
53
- function printNext(steps) {
54
- console.log("\n next");
55
- for (const [i, step] of steps.entries()) {
56
- console.log(` ${i + 1}. ${step.code}: ${step.statement}`);
57
- console.log(` run: ${step.command}`);
58
- }
59
- }
60
93
  /**
61
94
  * The business flows the services in view already appear in.
62
95
  *
@@ -86,7 +119,23 @@ export function printFeature(r, ambiguous) {
86
119
  if (r.interrupted !== null)
87
120
  printInterrupted(r.interrupted);
88
121
  const f = r.feature;
89
- console.log(`loam status ${f.id} — ${f.stage}${f.archived ? " (archived)" : ""}`);
122
+ // `unshippable`'s count, not `gating`'s: archive's pre-plan refusals carry no
123
+ // `gates`, so "N would stop archive" read 0 over a feature archive refuses.
124
+ const blocking = r.checks.issues.filter(unshippable).length;
125
+ const words = stageWords({
126
+ stage: f.stage,
127
+ archived: f.archived,
128
+ verification: r.verification,
129
+ asked: r.checklist?.claims ?? null,
130
+ missing: r.artifacts.filter((a) => a.status === "missing" && a.id !== "verification").map(artifactLabel),
131
+ narrowed: r.service !== null,
132
+ services: f.services.length,
133
+ blockedBy: f.blockedBy,
134
+ interrupted: r.interrupted !== null,
135
+ blocking,
136
+ });
137
+ console.log(`loam status ${featureLabel(f)}: ${words}`);
138
+ console.log(` stage ${f.stage} (\`loam explain ${f.stage}\` says what it promises and what it does not)`);
90
139
  console.log(` feature ${f.dirName} ${f.path}`);
91
140
  console.log(` services ${f.services.length > 0 ? f.services.join(", ") : "(none)"}`);
92
141
  if (r.service !== null)
@@ -94,27 +143,28 @@ export function printFeature(r, ambiguous) {
94
143
  if (f.blockedBy.length > 0)
95
144
  console.log(` waiting on ${f.blockedBy.join(", ")}`);
96
145
  console.log(` coherence ${r.checks.ran
97
- ? `${r.checks.errors} error(s) · ${r.checks.warnings} warning(s) · ${r.checks.gating} gate archive`
98
- : "not run (archived)"}`);
99
- console.log(` verification ${verificationLine(r.verification)}`);
146
+ ? `${r.checks.errors} error(s) · ${r.checks.warnings} warning(s) · ${blocking} stop it (validate --feature or archive refuses on each)`
147
+ : "not run — an archived feature is history, already merged"}`);
148
+ console.log(` verification ${verificationLine(r.verification, r.checklist?.claims ?? null)}`);
100
149
  if (ambiguous.length > 0) {
101
150
  console.log(` note '${f.id}' also names ${ambiguous.filter((d) => d !== f.dirName).join(", ")}`);
102
151
  }
103
152
  console.log("\n artifacts");
104
153
  const labels = r.artifacts.map(artifactLabel);
105
154
  const labelWidth = pad(labels);
106
- const statusWidth = pad(r.artifacts.map((a) => a.status));
155
+ const statuses = r.artifacts.map((a) => artifactWord(a, r.verification));
156
+ const statusWidth = pad(statuses);
107
157
  for (const [i, a] of r.artifacts.entries()) {
108
- // `done` on a file that is not there is the one row a reader misreads: it
109
- // means the feature owes no such artifact, not that one was written. The
110
- // JSON contract says it with `exists`; the human view has to say it in
158
+ // A row for a file that is not there is the one a reader misreads: `not
159
+ // owed` means the feature owes no such artifact, not that one was written.
160
+ // The JSON contract says it with `exists`; the human view says it in
111
161
  // words, or the table quietly claims files that do not exist.
112
162
  const note = a.blockedBy.length > 0
113
163
  ? ` (needs ${a.blockedBy.join(", ")})`
114
164
  : !a.exists && a.status === "done"
115
- ? " (not written — none owed)"
165
+ ? " (not written)"
116
166
  : "";
117
- console.log(` ${a.status.padEnd(statusWidth)} ${labels[i].padEnd(labelWidth)} ${a.path}${note}`.trimEnd());
167
+ console.log(` ${statuses[i].padEnd(statusWidth)} ${labels[i].padEnd(labelWidth)} ${a.path}${note}`.trimEnd());
118
168
  }
119
169
  if (r.checks.issues.length > 0) {
120
170
  console.log("\n findings");
@@ -130,28 +180,30 @@ export function printFleet(r) {
130
180
  printInterrupted(r.interrupted);
131
181
  const s = r.services;
132
182
  console.log(`loam status — ${s.total} service(s) · ${r.features.length} feature(s) in flight`);
133
- console.log(
134
- // The sampled count inside the vouched one, the scorecard's own layout: a
135
- // reader who stops at the first number must not have been told the
183
+ // The sampled and stale counts inside the vouched one, the scorecard's own
184
+ // layout: a reader who stops at the first number must not have been told the
136
185
  // stronger of the two.
137
- ` services ${s.undocumented} undocumented · ${s.draft} draft · ${s.vouched} vouched${s.sampledVouched > 0 ? ` (${s.sampledVouched} sampled)` : ""}`);
186
+ const notes = [
187
+ ...(s.sampledVouched > 0 ? [`${s.sampledVouched} sampled`] : []),
188
+ ...(s.contentStale > 0 ? [`${s.contentStale} stale`] : []),
189
+ ];
190
+ console.log(` services ${s.undocumented} undocumented · ${s.draft} draft · ${s.vouched} vouched${notes.length > 0 ? ` (${notes.join(", ")})` : ""}`);
138
191
  if (r.service !== null)
139
192
  console.log(` narrowed to ${r.service}`);
140
193
  if (r.order.length > 1)
141
194
  console.log(` order ${r.order.join(" → ")}`);
195
+ // Two lines a feature: the id and what it is CALLED, then where it stands in
196
+ // words. The fleet form grades nothing (no coherence run, no checklist), so
197
+ // its sentence can only count what a record already says — and says so.
142
198
  if (r.features.length > 0) {
143
199
  console.log("\n features");
144
200
  const ids = pad(r.features.map((f) => f.id));
145
- const stages = pad(r.features.map((f) => f.stage));
146
201
  for (const f of r.features) {
147
- const detail = f.blockedBy.length > 0
148
- ? `waiting on ${f.blockedBy.join(", ")}`
149
- : f.missing.length > 0
150
- ? `missing ${f.missing.join(", ")}`
151
- : f.services.join(", ");
152
- console.log(` ${f.stage.padEnd(stages)} ${f.id.padEnd(ids)} ${detail}`.trimEnd());
202
+ console.log(` ${f.id.padEnd(ids)} ${f.title ?? ""}`.trimEnd());
203
+ const where = fleetStageWords(f, r.interrupted !== null);
204
+ console.log(` ${" ".repeat(ids)} ${where} · ${f.services.length > 0 ? f.services.join(", ") : "no service yet"}`);
153
205
  }
154
206
  }
155
- printNext(r.next);
207
+ printFleetNext(r);
156
208
  }
157
209
  //# sourceMappingURL=print.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"print.js","sourceRoot":"","sources":["../../../src/commands/status/print.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The human view of a status: one feature, or the whole fleet.\n *\n * Separate from `./json.ts` because the two answer different readers and only\n * one of them is a contract. This side may be reworded freely; the payload\n * beside it may not.\n */\nimport { SEVERITY_MARK } from \"../../core/vocabulary/report.js\";\nimport type {\n ArtifactState,\n FeatureStatusReport,\n FleetStatusReport,\n InterruptedCommit,\n NextStep,\n VerificationState,\n} from \"../../core/status/report.js\";\n\nfunction pad(values: string[]): number {\n return Math.max(0, ...values.map((v) => v.length));\n}\n\n/**\n * The half-merged-repo banner, printed FIRST and on stderr.\n *\n * stderr, alone among this command's output, because it is not part of the\n * answer: it is the reason the answer may be wrong. A reader piping `status`\n * into a pager still sees it, and the human view stays the shape every other\n * run has. `--json` carries the same fact in `interrupted`.\n */\nfunction printInterrupted(i: InterruptedCommit): void {\n console.error(\n i.unreadable\n ? \"⚠ this docs repo holds a .loam-commit that cannot be read — a commit was interrupted and nothing here can be trusted until a human compares the living docs against version control.\"\n : `⚠ a \\`${i.recover}\\` was killed mid-commit (${i.host}, pid ${i.pid}, ${i.at}) — ${i.files.length} file(s) may be half-written: ${i.files.join(\", \")}. Everything below is derived from them.`,\n );\n console.error(\"\");\n}\n\n/** `spec (payment-service)` — the artifact id plus the service, when it has one. */\nfunction artifactLabel(a: ArtifactState): string {\n return a.service === null ? a.id : `${a.id} (${a.service})`;\n}\n\n/**\n * The counts come from the record's `claims:` array (verify's `tallyRecord`),\n * never from its `summary:` block. The verdict is printed beside the state\n * because they answer different questions and only together are they honest:\n * `recorded 4/4 confirmed` used to be the whole line for a feature `verify`\n * calls `attested` — complete, and resting on somebody's word about a test.\n */\nfunction verificationLine(v: VerificationState): string {\n if (v.state === \"absent\") return \"none\";\n if (v.state === \"unreadable\") return \"unreadable\";\n return (\n `${v.state} · ${v.verdict} ${v.confirmed}/${v.claims} confirmed` +\n (v.unanswered > 0 ? ` · ${v.unanswered} unanswered` : \"\") +\n (v.attested > 0 ? ` · ${v.attested} scenario(s) on an agent's word, not a test run` : \"\") +\n ` (recorded ${v.recorded ?? \"?\"})`\n );\n}\n\n/**\n * The steps, numbered, with the command on its own indented line — doctor's\n * layout, for doctor's reason: what to do and what to type are two different\n * sentences, and someone scanning a half-built feature reads down the `run:`\n * column.\n */\nfunction printNext(steps: NextStep[]): void {\n console.log(\"\\n next\");\n for (const [i, step] of steps.entries()) {\n console.log(` ${i + 1}. ${step.code}: ${step.statement}`);\n console.log(` run: ${step.command}`);\n }\n}\n\n/**\n * The business flows the services in view already appear in.\n *\n * Silent when the fleet declares none, unlike the delta brief's version of the\n * same section: this report is a table of what is OWED, and a \"(none)\" row for\n * a fleet that has never drawn a use case would be one more line between the\n * reader and the next step. The unreadable arm is not silent, because that one\n * is a hole rather than an absence.\n */\nfunction printUseCases(u: FeatureStatusReport[\"useCases\"]): void {\n if (u.unreadable) {\n console.log(\"\\n use cases architecture/ does not parse, so the flows through these services could not be read\");\n return;\n }\n if (u.flows.length === 0) return;\n console.log(\"\\n use cases\");\n for (const flow of u.flows) {\n console.log(` ${flow.title ?? flow.id} [${flow.id}] ${flow.file}`);\n for (const step of flow.steps) {\n const label = step.title === undefined ? \"\" : ` '${step.title}'`;\n console.log(` step ${step.ordinal}${label}: ${step.source} -> ${step.target}`);\n }\n }\n}\n\nexport function printFeature(r: FeatureStatusReport, ambiguous: string[]): void {\n if (r.interrupted !== null) printInterrupted(r.interrupted);\n const f = r.feature;\n console.log(`loam status ${f.id} — ${f.stage}${f.archived ? \" (archived)\" : \"\"}`);\n console.log(` feature ${f.dirName} ${f.path}`);\n console.log(` services ${f.services.length > 0 ? f.services.join(\", \") : \"(none)\"}`);\n if (r.service !== null) console.log(` narrowed to ${r.service}`);\n if (f.blockedBy.length > 0) console.log(` waiting on ${f.blockedBy.join(\", \")}`);\n console.log(\n ` coherence ${\n r.checks.ran\n ? `${r.checks.errors} error(s) · ${r.checks.warnings} warning(s) · ${r.checks.gating} gate archive`\n : \"not run (archived)\"\n }`,\n );\n console.log(` verification ${verificationLine(r.verification)}`);\n if (ambiguous.length > 0) {\n console.log(` note '${f.id}' also names ${ambiguous.filter((d) => d !== f.dirName).join(\", \")}`);\n }\n\n console.log(\"\\n artifacts\");\n const labels = r.artifacts.map(artifactLabel);\n const labelWidth = pad(labels);\n const statusWidth = pad(r.artifacts.map((a) => a.status));\n for (const [i, a] of r.artifacts.entries()) {\n // `done` on a file that is not there is the one row a reader misreads: it\n // means the feature owes no such artifact, not that one was written. The\n // JSON contract says it with `exists`; the human view has to say it in\n // words, or the table quietly claims files that do not exist.\n const note =\n a.blockedBy.length > 0\n ? ` (needs ${a.blockedBy.join(\", \")})`\n : !a.exists && a.status === \"done\"\n ? \" (not written — none owed)\"\n : \"\";\n console.log(\n ` ${a.status.padEnd(statusWidth)} ${labels[i]!.padEnd(labelWidth)} ${a.path}${note}`.trimEnd(),\n );\n }\n\n if (r.checks.issues.length > 0) {\n console.log(\"\\n findings\");\n for (const issue of r.checks.issues) {\n console.log(` ${SEVERITY_MARK[issue.severity]} ${issue.code}: ${issue.message}`);\n }\n }\n\n printUseCases(r.useCases);\n printNext(r.next);\n}\n\nexport function printFleet(r: FleetStatusReport): void {\n if (r.interrupted !== null) printInterrupted(r.interrupted);\n const s = r.services;\n console.log(`loam status — ${s.total} service(s) · ${r.features.length} feature(s) in flight`);\n console.log(\n // The sampled count inside the vouched one, the scorecard's own layout: a\n // reader who stops at the first number must not have been told the\n // stronger of the two.\n ` services ${s.undocumented} undocumented · ${s.draft} draft · ${s.vouched} vouched${s.sampledVouched > 0 ? ` (${s.sampledVouched} sampled)` : \"\"}`,\n );\n if (r.service !== null) console.log(` narrowed to ${r.service}`);\n if (r.order.length > 1) console.log(` order ${r.order.join(\" → \")}`);\n\n if (r.features.length > 0) {\n console.log(\"\\n features\");\n const ids = pad(r.features.map((f) => f.id));\n const stages = pad(r.features.map((f) => f.stage));\n for (const f of r.features) {\n const detail =\n f.blockedBy.length > 0\n ? `waiting on ${f.blockedBy.join(\", \")}`\n : f.missing.length > 0\n ? `missing ${f.missing.join(\", \")}`\n : f.services.join(\", \");\n console.log(` ${f.stage.padEnd(stages)} ${f.id.padEnd(ids)} ${detail}`.trimEnd());\n }\n }\n\n printNext(r.next);\n}\n"]}
1
+ {"version":3,"file":"print.js","sourceRoot":"","sources":["../../../src/commands/status/print.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The human view of a status: one feature, or the whole fleet.\n *\n * Separate from `./json.ts` because the two answer different readers and only\n * one of them is a contract. This side may be reworded freely; the payload\n * beside it may not.\n *\n * Which is also why no bare stage word leads a line here any more. `stage` is a\n * value an agent branches on, and `ready` printed alone over a feature with\n * nothing built read to a person as \"ready to ship\". The sentence comes from\n * `stageWords` (core/status/feature/words.ts) — the same one the `next[]`\n * statements quote — with the counts that make it true, and the machine value\n * rides in its own row for whoever needs to map the two.\n */\nimport { answeredSplit } from \"../../core/verify/record.js\";\nimport { SEVERITY_MARK } from \"../../core/vocabulary/report.js\";\nimport { unshippable } from \"../../core/status/feature/next.js\";\nimport { featureLabel, fleetStageWords, stageWords } from \"../../core/status/feature/words.js\";\nimport type {\n ArtifactState,\n FeatureStatusReport,\n FleetStatusReport,\n InterruptedCommit,\n VerificationState,\n} from \"../../core/status/report.js\";\nimport { printFleetNext, printNext } from \"./fleet-next.js\";\n\nfunction pad(values: string[]): number {\n return Math.max(0, ...values.map((v) => v.length));\n}\n\n/**\n * The half-merged-repo banner, printed FIRST and on stderr.\n *\n * stderr, alone among this command's output, because it is not part of the\n * answer: it is the reason the answer may be wrong. A reader piping `status`\n * into a pager still sees it, and the human view stays the shape every other\n * run has. `--json` carries the same fact in `interrupted`.\n */\nfunction printInterrupted(i: InterruptedCommit): void {\n console.error(\n i.unreadable\n ? \"⚠ this docs repo holds a .loam-commit that cannot be read — a commit was interrupted and nothing here can be trusted until a human compares the living docs against version control.\"\n : `⚠ a \\`${i.recover}\\` was killed mid-commit (${i.host}, pid ${i.pid}, ${i.at}) — ${i.files.length} file(s) may be half-written: ${i.files.join(\", \")}. Everything below is derived from them.`,\n );\n console.error(\"\");\n}\n\n/** `spec (payment-service)` — the artifact id plus the service, when it has one. */\nfunction artifactLabel(a: ArtifactState): string {\n return a.service === null ? a.id : `${a.id} (${a.service})`;\n}\n\n/**\n * An artifact row's status, in words. The machine value is `done` for a file\n * that is written AND for one the feature does not owe, and `ready` for a\n * verification record whose claims are still open — three readings a person\n * cannot tell apart from one word, and the reason a table of `done` rows read\n * as finished work over a feature nobody had built.\n */\nfunction artifactWord(a: ArtifactState, v: VerificationState): string {\n if (a.id === \"verification\") {\n if (a.status === \"missing\") return \"none yet\";\n // An attested record is complete and rests on an agent's word; \"open\"\n // over it contradicted the header that says every claim is answered.\n if (a.status === \"ready\") return v.verdict === \"attested\" ? \"attested\" : \"open\";\n if (a.status === \"done\") return \"verified\";\n if (a.status === \"draft\") return v.state === \"stale\" ? \"stale\" : \"unreadable\";\n return a.status;\n }\n if (a.status === \"done\") return a.exists ? \"written\" : \"not owed\";\n if (a.status === \"draft\") return \"has errors\";\n return a.status;\n}\n\n/**\n * The counts come from the record's `claims:` array (verify's `tallyRecord`),\n * never from its `summary:` block. The verdict is printed beside the state\n * because they answer different questions and only together are they honest:\n * `recorded 4/4 confirmed` used to be the whole line for a feature `verify`\n * calls `attested` — complete, and resting on somebody's word about a test.\n * Who answered the confirmed ones rides right after the count for the same\n * reason one step further: `verified` turns on the scenario claims alone, and\n * `verified 19/19 confirmed` read as nineteen runs over a record where six\n * answers were an agent's word about a permission or an edge.\n *\n * With no record, the line says how many claims there ARE to answer, when the\n * report knows (`checklist`): \"none\" alone read as \"nothing to do\".\n */\nfunction verificationLine(v: VerificationState, asked: number | null): string {\n if (v.state === \"absent\") return asked === null ? \"none — no record\" : `none yet — ${asked} claim(s) to answer`;\n if (v.state === \"unreadable\") return \"unreadable\";\n return (\n `${v.state} · ${v.verdict} ${v.confirmed}/${v.claims} confirmed` +\n (v.confirmed > 0 ? ` (${answeredSplit(v.answered)})` : \"\") +\n (v.unanswered > 0 ? ` · ${v.unanswered} unanswered` : \"\") +\n (v.attested > 0 ? ` · ${v.attested} scenario(s) on an agent's word, not a test run` : \"\") +\n ` (recorded ${v.recorded ?? \"?\"})`\n );\n}\n\n/**\n * The business flows the services in view already appear in.\n *\n * Silent when the fleet declares none, unlike the delta brief's version of the\n * same section: this report is a table of what is OWED, and a \"(none)\" row for\n * a fleet that has never drawn a use case would be one more line between the\n * reader and the next step. The unreadable arm is not silent, because that one\n * is a hole rather than an absence.\n */\nfunction printUseCases(u: FeatureStatusReport[\"useCases\"]): void {\n if (u.unreadable) {\n console.log(\"\\n use cases architecture/ does not parse, so the flows through these services could not be read\");\n return;\n }\n if (u.flows.length === 0) return;\n console.log(\"\\n use cases\");\n for (const flow of u.flows) {\n console.log(` ${flow.title ?? flow.id} [${flow.id}] ${flow.file}`);\n for (const step of flow.steps) {\n const label = step.title === undefined ? \"\" : ` '${step.title}'`;\n console.log(` step ${step.ordinal}${label}: ${step.source} -> ${step.target}`);\n }\n }\n}\n\nexport function printFeature(r: FeatureStatusReport, ambiguous: string[]): void {\n if (r.interrupted !== null) printInterrupted(r.interrupted);\n const f = r.feature;\n // `unshippable`'s count, not `gating`'s: archive's pre-plan refusals carry no\n // `gates`, so \"N would stop archive\" read 0 over a feature archive refuses.\n const blocking = r.checks.issues.filter(unshippable).length;\n const words = stageWords({\n stage: f.stage,\n archived: f.archived,\n verification: r.verification,\n asked: r.checklist?.claims ?? null,\n missing: r.artifacts.filter((a) => a.status === \"missing\" && a.id !== \"verification\").map(artifactLabel),\n narrowed: r.service !== null,\n services: f.services.length,\n blockedBy: f.blockedBy,\n interrupted: r.interrupted !== null,\n blocking,\n });\n console.log(`loam status ${featureLabel(f)}: ${words}`);\n console.log(` stage ${f.stage} (\\`loam explain ${f.stage}\\` says what it promises and what it does not)`);\n console.log(` feature ${f.dirName} ${f.path}`);\n console.log(` services ${f.services.length > 0 ? f.services.join(\", \") : \"(none)\"}`);\n if (r.service !== null) console.log(` narrowed to ${r.service}`);\n if (f.blockedBy.length > 0) console.log(` waiting on ${f.blockedBy.join(\", \")}`);\n console.log(\n ` coherence ${\n r.checks.ran\n ? `${r.checks.errors} error(s) · ${r.checks.warnings} warning(s) · ${blocking} stop it (validate --feature or archive refuses on each)`\n : \"not run — an archived feature is history, already merged\"\n }`,\n );\n console.log(` verification ${verificationLine(r.verification, r.checklist?.claims ?? null)}`);\n if (ambiguous.length > 0) {\n console.log(` note '${f.id}' also names ${ambiguous.filter((d) => d !== f.dirName).join(\", \")}`);\n }\n\n console.log(\"\\n artifacts\");\n const labels = r.artifacts.map(artifactLabel);\n const labelWidth = pad(labels);\n const statuses = r.artifacts.map((a) => artifactWord(a, r.verification));\n const statusWidth = pad(statuses);\n for (const [i, a] of r.artifacts.entries()) {\n // A row for a file that is not there is the one a reader misreads: `not\n // owed` means the feature owes no such artifact, not that one was written.\n // The JSON contract says it with `exists`; the human view says it in\n // words, or the table quietly claims files that do not exist.\n const note =\n a.blockedBy.length > 0\n ? ` (needs ${a.blockedBy.join(\", \")})`\n : !a.exists && a.status === \"done\"\n ? \" (not written)\"\n : \"\";\n console.log(\n ` ${statuses[i]!.padEnd(statusWidth)} ${labels[i]!.padEnd(labelWidth)} ${a.path}${note}`.trimEnd(),\n );\n }\n\n if (r.checks.issues.length > 0) {\n console.log(\"\\n findings\");\n for (const issue of r.checks.issues) {\n console.log(` ${SEVERITY_MARK[issue.severity]} ${issue.code}: ${issue.message}`);\n }\n }\n\n printUseCases(r.useCases);\n printNext(r.next);\n}\n\nexport function printFleet(r: FleetStatusReport): void {\n if (r.interrupted !== null) printInterrupted(r.interrupted);\n const s = r.services;\n console.log(`loam status — ${s.total} service(s) · ${r.features.length} feature(s) in flight`);\n // The sampled and stale counts inside the vouched one, the scorecard's own\n // layout: a reader who stops at the first number must not have been told the\n // stronger of the two.\n const notes = [\n ...(s.sampledVouched > 0 ? [`${s.sampledVouched} sampled`] : []),\n ...(s.contentStale > 0 ? [`${s.contentStale} stale`] : []),\n ];\n console.log(\n ` services ${s.undocumented} undocumented · ${s.draft} draft · ${s.vouched} vouched${notes.length > 0 ? ` (${notes.join(\", \")})` : \"\"}`,\n );\n if (r.service !== null) console.log(` narrowed to ${r.service}`);\n if (r.order.length > 1) console.log(` order ${r.order.join(\" → \")}`);\n\n // Two lines a feature: the id and what it is CALLED, then where it stands in\n // words. The fleet form grades nothing (no coherence run, no checklist), so\n // its sentence can only count what a record already says — and says so.\n if (r.features.length > 0) {\n console.log(\"\\n features\");\n const ids = pad(r.features.map((f) => f.id));\n for (const f of r.features) {\n console.log(` ${f.id.padEnd(ids)} ${f.title ?? \"\"}`.trimEnd());\n const where = fleetStageWords(f, r.interrupted !== null);\n console.log(` ${\" \".repeat(ids)} ${where} · ${f.services.length > 0 ? f.services.join(\", \") : \"no service yet\"}`);\n }\n }\n\n printFleetNext(r);\n}\n"]}
@@ -1,6 +1,5 @@
1
- import { loadConfig } from "../../core/envelope/config.js";
2
1
  import { FleetContext } from "../../core/fleet-context.js";
3
- import { emitJson, fail, reportNoConfig } from "../../core/envelope/json.js";
2
+ import { configOrRefuse, emitJson, fail } from "../../core/envelope/json.js";
4
3
  import { DocsRepoUnavailableError } from "../../core/repo/state.js";
5
4
  import { featureCandidates, missingFeatureMessage, resolveFeature } from "../../core/repo/repo.js";
6
5
  import { featureStatus } from "../../core/status/feature/feature.js";
@@ -17,12 +16,9 @@ export function registerStatus(program) {
17
16
  .option("--service <id>", "narrow the per-service view to one service")
18
17
  .action(async (featureArg, opts) => {
19
18
  const json = opts.json === true;
20
- const loaded = await loadConfig();
21
- if (loaded.kind !== "loaded") {
22
- reportNoConfig(json, loaded);
19
+ const config = await configOrRefuse(json);
20
+ if (config === null)
23
21
  return;
24
- }
25
- const config = loaded.config;
26
22
  const { docsDir } = config;
27
23
  // A docsDir that is not a docs repo is refused, never rendered as a repo
28
24
  // with nothing in it — the doctrine docs-repo-gate.ts's docsRepoReady exists
@@ -1 +1 @@
1
- {"version":3,"file":"status.js","sourceRoot":"","sources":["../../../src/commands/status/status.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Command } from \"commander\";\nimport { loadConfig } from \"../../core/envelope/config.js\";\nimport { FleetContext } from \"../../core/fleet-context.js\";\nimport { emitJson, fail, reportNoConfig } from \"../../core/envelope/json.js\";\nimport { DocsRepoUnavailableError } from \"../../core/repo/state.js\";\nimport { featureCandidates, missingFeatureMessage, resolveFeature } from \"../../core/repo/repo.js\";\nimport { featureStatus } from \"../../core/status/feature/feature.js\";\nimport { fleetStatus } from \"../../core/status/fleet/fleet.js\";\nimport { docsRepoReady, reportDocsRepoError, reportRepositoryUnavailable } from \"../policy/gate.js\";\nimport { featureJson, fleetJson } from \"./json.js\";\nimport { printFeature, printFleet } from \"./print.js\";\n\n/**\n * `loam status` — the read-only projection. Nothing here computes anything: the\n * derivation lives in core/status/ (and, underneath it, in the same coherence\n * and verification calls `validate`, `verify` and `archive` make). This file\n * resolves the target, refuses the arguments it cannot honour, and renders.\n *\n * It reports and does not gate, which is why it never sets a non-zero exit code\n * on a successful run — see `registerStatus`.\n */\n\ninterface StatusOptions {\n json?: boolean;\n service?: string;\n}\n\nexport function registerStatus(program: Command): void {\n program\n .command(\"status\")\n .argument(\"[feature]\", \"feature id or directory name; omit for the whole repository\")\n .description(\"Report where the work stands and what to do next, derived from the files\")\n .option(\"--json\", \"emit the machine contract instead of the human view\")\n .option(\"--service <id>\", \"narrow the per-service view to one service\")\n .action(async (featureArg: string | undefined, opts: StatusOptions) => {\n const json = opts.json === true;\n const loaded = await loadConfig();\n if (loaded.kind !== \"loaded\") {\n reportNoConfig(json, loaded);\n return;\n }\n const config = loaded.config;\n const { docsDir } = config;\n // A docsDir that is not a docs repo is refused, never rendered as a repo\n // with nothing in it — the doctrine docs-repo-gate.ts's docsRepoReady exists\n // for. `status` counts services, so it needs services/ in both modes.\n if (!docsRepoReady(json, docsDir, \"services\")) return;\n const context = new FleetContext();\n // What the refusal below says it was answering when it gave up.\n let scope = \"this repository\";\n\n try {\n if (featureArg === undefined) {\n // `bound` is what THIS repo says it is, which is a different fact from\n // `--service` (which narrows the view). Passing it is what lets the\n // fleet form notice that the repository it is standing in has never\n // been adopted — the one thing a fleet count cannot see.\n const report = await fleetStatus(docsDir, {\n service: opts.service,\n bound: config.service,\n context,\n });\n // A `--service` that names nothing is refused rather than answered\n // with an empty fleet: \"no services and no features\" and \"you\n // misspelled it\" are opposite facts, and only one of them is worth\n // acting on.\n if (opts.service !== undefined && report.services.total === 0) {\n fail(json, \"unknown-service\", `No service '${opts.service}' under ${docsDir}/services/.`);\n return;\n }\n if (json) emitJson({ command: \"status\", docsDir, scope: \"fleet\", ...fleetJson(report) });\n else printFleet(report);\n return;\n }\n\n // Archived features are IN scope: an agent asking where FEAT-101 stands\n // after it shipped deserves \"it shipped\", not \"no such feature\" — the\n // same reading `show` takes. An argument naming two directories is\n // still answered (status writes nothing), with the tie broken the way\n // resolveFeature always breaks it.\n const feature = await resolveFeature(docsDir, featureArg, \"include\", context);\n if (!feature) {\n fail(json, \"unknown-target\", await missingFeatureMessage(docsDir, featureArg, context));\n return;\n }\n scope = feature.id;\n // `config.service` is not a lens like `--service`: it says which\n // repository this IS, and three of the steps (`loam gherkin`, `verify\n // --record --service`) refuse anywhere else. Without it status handed a\n // docs-repo reader commands only a service repo can run, and never told\n // a service repo that the work in front of it was its own.\n const report = await featureStatus(docsDir, feature, {\n service: opts.service,\n boundService: config.service,\n context,\n });\n if (opts.service !== undefined && !report.feature.services.includes(opts.service)) {\n fail(\n json,\n \"unknown-service\",\n `${feature.id} carries no delta for '${opts.service}'. It touches: ${\n report.feature.services.length > 0 ? report.feature.services.join(\", \") : \"(no services)\"\n }.`,\n );\n return;\n }\n const ambiguous = await featureCandidates(docsDir, featureArg, \"include\", context);\n if (json) {\n emitJson({ command: \"status\", docsDir, scope: \"feature\", ...featureJson(report) });\n } else {\n printFeature(report, ambiguous.length > 1 ? ambiguous.map((c) => c.dirName) : []);\n }\n } catch (err) {\n if (err instanceof DocsRepoUnavailableError) {\n reportDocsRepoError(json, err);\n return;\n }\n // One unreadable artifact must not escape as a stack trace and an\n // `internal` envelope that names nothing: the projection is\n // all-or-nothing (a status missing one artifact reads as a feature that\n // does not owe it), so the honest answer is a refusal naming the path.\n // The errno-vs-path reading this branch depends on — the reason one\n // directory where a file belongs used to kill BOTH forms of status —\n // now lives once, with its reasoning, on the shared helper.\n reportRepositoryUnavailable(\n json,\n err,\n `the status of ${scope} would be missing an artifact`,\n docsDir,\n );\n }\n // No exit code is set on any path above that succeeded, deliberately.\n // `doctor` exits 1 because a broken installation makes every later\n // command lie, and `validate` exits 1 because it IS the fleet gate. This\n // command is a question, and its answer is equally true whether the\n // feature is finished or not — an agent runs it precisely BECAUSE work is\n // outstanding, and exiting 1 there would make every `set -e` script and\n // every CI step read \"there is work to do\" as a failure.\n });\n}\n\n/* ------------------------------------------------------------------ */\n/* JSON */\n/* ------------------------------------------------------------------ */\n"]}
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../../../src/commands/status/status.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Command } from \"commander\";\nimport { FleetContext } from \"../../core/fleet-context.js\";\nimport { configOrRefuse, emitJson, fail } from \"../../core/envelope/json.js\";\nimport { DocsRepoUnavailableError } from \"../../core/repo/state.js\";\nimport { featureCandidates, missingFeatureMessage, resolveFeature } from \"../../core/repo/repo.js\";\nimport { featureStatus } from \"../../core/status/feature/feature.js\";\nimport { fleetStatus } from \"../../core/status/fleet/fleet.js\";\nimport { docsRepoReady, reportDocsRepoError, reportRepositoryUnavailable } from \"../policy/gate.js\";\nimport { featureJson, fleetJson } from \"./json.js\";\nimport { printFeature, printFleet } from \"./print.js\";\n\n/**\n * `loam status` — the read-only projection. Nothing here computes anything: the\n * derivation lives in core/status/ (and, underneath it, in the same coherence\n * and verification calls `validate`, `verify` and `archive` make). This file\n * resolves the target, refuses the arguments it cannot honour, and renders.\n *\n * It reports and does not gate, which is why it never sets a non-zero exit code\n * on a successful run — see `registerStatus`.\n */\n\ninterface StatusOptions {\n json?: boolean;\n service?: string;\n}\n\nexport function registerStatus(program: Command): void {\n program\n .command(\"status\")\n .argument(\"[feature]\", \"feature id or directory name; omit for the whole repository\")\n .description(\"Report where the work stands and what to do next, derived from the files\")\n .option(\"--json\", \"emit the machine contract instead of the human view\")\n .option(\"--service <id>\", \"narrow the per-service view to one service\")\n .action(async (featureArg: string | undefined, opts: StatusOptions) => {\n const json = opts.json === true;\n const config = await configOrRefuse(json);\n if (config === null) return;\n const { docsDir } = config;\n // A docsDir that is not a docs repo is refused, never rendered as a repo\n // with nothing in it — the doctrine docs-repo-gate.ts's docsRepoReady exists\n // for. `status` counts services, so it needs services/ in both modes.\n if (!docsRepoReady(json, docsDir, \"services\")) return;\n const context = new FleetContext();\n // What the refusal below says it was answering when it gave up.\n let scope = \"this repository\";\n\n try {\n if (featureArg === undefined) {\n // `bound` is what THIS repo says it is, which is a different fact from\n // `--service` (which narrows the view). Passing it is what lets the\n // fleet form notice that the repository it is standing in has never\n // been adopted — the one thing a fleet count cannot see.\n const report = await fleetStatus(docsDir, {\n service: opts.service,\n bound: config.service,\n context,\n });\n // A `--service` that names nothing is refused rather than answered\n // with an empty fleet: \"no services and no features\" and \"you\n // misspelled it\" are opposite facts, and only one of them is worth\n // acting on.\n if (opts.service !== undefined && report.services.total === 0) {\n fail(json, \"unknown-service\", `No service '${opts.service}' under ${docsDir}/services/.`);\n return;\n }\n if (json) emitJson({ command: \"status\", docsDir, scope: \"fleet\", ...fleetJson(report) });\n else printFleet(report);\n return;\n }\n\n // Archived features are IN scope: an agent asking where FEAT-101 stands\n // after it shipped deserves \"it shipped\", not \"no such feature\" — the\n // same reading `show` takes. An argument naming two directories is\n // still answered (status writes nothing), with the tie broken the way\n // resolveFeature always breaks it.\n const feature = await resolveFeature(docsDir, featureArg, \"include\", context);\n if (!feature) {\n fail(json, \"unknown-target\", await missingFeatureMessage(docsDir, featureArg, context));\n return;\n }\n scope = feature.id;\n // `config.service` is not a lens like `--service`: it says which\n // repository this IS, and three of the steps (`loam gherkin`, `verify\n // --record --service`) refuse anywhere else. Without it status handed a\n // docs-repo reader commands only a service repo can run, and never told\n // a service repo that the work in front of it was its own.\n const report = await featureStatus(docsDir, feature, {\n service: opts.service,\n boundService: config.service,\n context,\n });\n if (opts.service !== undefined && !report.feature.services.includes(opts.service)) {\n fail(\n json,\n \"unknown-service\",\n `${feature.id} carries no delta for '${opts.service}'. It touches: ${\n report.feature.services.length > 0 ? report.feature.services.join(\", \") : \"(no services)\"\n }.`,\n );\n return;\n }\n const ambiguous = await featureCandidates(docsDir, featureArg, \"include\", context);\n if (json) {\n emitJson({ command: \"status\", docsDir, scope: \"feature\", ...featureJson(report) });\n } else {\n printFeature(report, ambiguous.length > 1 ? ambiguous.map((c) => c.dirName) : []);\n }\n } catch (err) {\n if (err instanceof DocsRepoUnavailableError) {\n reportDocsRepoError(json, err);\n return;\n }\n // One unreadable artifact must not escape as a stack trace and an\n // `internal` envelope that names nothing: the projection is\n // all-or-nothing (a status missing one artifact reads as a feature that\n // does not owe it), so the honest answer is a refusal naming the path.\n // The errno-vs-path reading this branch depends on — the reason one\n // directory where a file belongs used to kill BOTH forms of status —\n // now lives once, with its reasoning, on the shared helper.\n reportRepositoryUnavailable(\n json,\n err,\n `the status of ${scope} would be missing an artifact`,\n docsDir,\n );\n }\n // No exit code is set on any path above that succeeded, deliberately.\n // `doctor` exits 1 because a broken installation makes every later\n // command lie, and `validate` exits 1 because it IS the fleet gate. This\n // command is a question, and its answer is equally true whether the\n // feature is finished or not — an agent runs it precisely BECAUSE work is\n // outstanding, and exiting 1 there would make every `set -e` script and\n // every CI step read \"there is work to do\" as a failure.\n });\n}\n\n/* ------------------------------------------------------------------ */\n/* JSON */\n/* ------------------------------------------------------------------ */\n"]}
@@ -1,11 +1,12 @@
1
1
  import { existsSync } from "node:fs";
2
2
  import { readFile } from "node:fs/promises";
3
3
  import { relative } from "node:path";
4
- import { loadConfig } from "../../core/envelope/config.js";
5
4
  import { decodeDocument, NotUtf8DocumentError } from "../../core/kernel/document-bytes.js";
6
- import { emitJson, fail, NO_SERVICE_MESSAGE, reportNoConfig } from "../../core/envelope/json.js";
7
- import { SPEC_AXES } from "../../core/repo/paths.js";
5
+ import { configOrRefuse, emitJson, fail, NO_SERVICE_MESSAGE } from "../../core/envelope/json.js";
6
+ import { featureSpecPaths, SPEC_AXES, unfiledServicePaths } from "../../core/repo/paths.js";
8
7
  import { locateServicePaths, resolveServiceTarget } from "../../core/repo/service-target.js";
8
+ import {} from "../../core/repo/entries.js";
9
+ import { introducingFeatures } from "../../core/projection/introduced.js";
9
10
  import { parseRequirements } from "../../core/document/parse.js";
10
11
  import { axisLabel } from "../../core/gherkin/emit.js";
11
12
  import { coveringPhrases, stepInventory, } from "../../core/gherkin/steps/inventory.js";
@@ -19,12 +20,9 @@ export function registerSteps(program) {
19
20
  .option("--json", "emit the machine contract instead of the human view")
20
21
  .action(async (opts) => {
21
22
  const json = opts.json === true;
22
- const loaded = await loadConfig();
23
- if (loaded.kind !== "loaded") {
24
- reportNoConfig(json, loaded);
23
+ const config = await configOrRefuse(json);
24
+ if (config === null)
25
25
  return;
26
- }
27
- const config = loaded.config;
28
26
  const named = opts.service ?? config.service;
29
27
  if (named === undefined)
30
28
  return fail(json, "invalid-option", NO_SERVICE_MESSAGE);
@@ -33,17 +31,37 @@ export function registerSteps(program) {
33
31
  // the name pathable. Same resolution `validate --service` performs, so the
34
32
  // two commands cannot disagree about which directory a name means.
35
33
  const resolved = await resolveServiceTarget(config.docsDir, named, "--service");
36
- if (!resolved.ok)
37
- return fail(json, "invalid-option", resolved.problem);
38
- const service = resolved.id;
39
- const paths = await locateServicePaths(config.docsDir, service);
40
- if (!existsSync(paths.spec)) {
41
- return fail(json, "unknown-target", `No living spec at ${paths.spec}. Run \`loam adopt\` for '${service}' first.`);
34
+ // A name `services/` does not hold may still be a service an active
35
+ // feature INTRODUCES — the second enumeration, a readdir of the feature's
36
+ // own specs/, so it is asked before the grammar refusal too. Its phrases
37
+ // are the delta's: the implement protocol tells whoever builds a NEW
38
+ // service to run this before writing a single step definition, and the
39
+ // answer was "No living spec … run `loam adopt`" for code that does not
40
+ // exist yet. The bound service (`config.service`) takes the same road.
41
+ const introducing = resolved.ok && resolved.dir !== undefined ? [] : await introducingFeatures(config.docsDir, named);
42
+ const introducedId = introducing[0]?.services.find((s) => s === named);
43
+ let source;
44
+ if (introducedId !== undefined) {
45
+ source = introducedSource(config.docsDir, introducedId, introducing);
46
+ }
47
+ else {
48
+ if (!resolved.ok)
49
+ return fail(json, "invalid-option", resolved.problem);
50
+ const paths = await locateServicePaths(config.docsDir, resolved.id);
51
+ if (!existsSync(paths.spec)) {
52
+ return fail(json, "unknown-target", `No living spec at ${paths.spec}. Run \`loam adopt\` for '${resolved.id}' first.`);
53
+ }
54
+ source = {
55
+ service: resolved.id,
56
+ files: SPEC_AXES.map((axis) => ({ axis, path: paths[axis.key] })),
57
+ steps: paths.steps,
58
+ introducedBy: [],
59
+ };
42
60
  }
61
+ const { service } = source;
43
62
  const axes = [];
44
63
  try {
45
- for (const axis of SPEC_AXES) {
46
- const path = paths[axis.key];
64
+ for (const { axis, path } of source.files) {
47
65
  // An absent arch.spec.md is not a finding anywhere else and is not one
48
66
  // here: partial adoption is supported, and an empty axis contributes
49
67
  // no phrases rather than an empty section nobody asked for.
@@ -63,7 +81,7 @@ export function registerSteps(program) {
63
81
  // recomputation: without it every run says the same thing about a suite
64
82
  // whose glue somebody has already written. Absent is the ordinary state
65
83
  // and costs one `existsSync` (`core/gherkin/steps/catalogue.ts`).
66
- const catalogue = await readStepCatalogue(paths.steps);
84
+ const catalogue = await readStepCatalogue(source.steps);
67
85
  const against = catalogue.present && catalogue.unreadable === undefined
68
86
  ? compareToCatalogue(inv, catalogue)
69
87
  : null;
@@ -76,12 +94,23 @@ export function registerSteps(program) {
76
94
  // exist, and here that would be worse than cosmetic: `steps.yaml` is a
77
95
  // service artifact now, so an author who created the file where this told
78
96
  // them to would mint a second, empty service in the enumeration.
79
- const where = relative(config.docsDir, paths.steps).split(/[\\/]/).join("/");
97
+ const where = docsRelative(config.docsDir, source.steps);
98
+ const introducedBy = source.introducedBy.map((f) => f.id);
80
99
  if (json) {
81
100
  emitJson({
82
101
  command: "steps",
83
102
  docsDir: config.docsDir,
84
103
  service,
104
+ // Present only for a service a feature introduces, so a living
105
+ // service's payload stays byte-identical: `living: false` is the
106
+ // marker, and `specs` names the delta files the phrases came from.
107
+ ...(introducedBy.length === 0
108
+ ? {}
109
+ : {
110
+ living: false,
111
+ introducedBy,
112
+ specs: source.files.filter((f) => existsSync(f.path)).map((f) => docsRelative(config.docsDir, f.path)),
113
+ }),
85
114
  steps: inv.steps,
86
115
  phrases: inv.phrases.length,
87
116
  covering80: coveringPhrases(inv),
@@ -107,24 +136,66 @@ export function registerSteps(program) {
107
136
  });
108
137
  return;
109
138
  }
110
- print(inv, service, opts.duplicates === true);
111
- printCatalogue({ catalogue, against, where });
139
+ const origin = introducedBy.length === 0
140
+ ? null
141
+ : {
142
+ by: introducedBy.join(", "),
143
+ dirs: source.introducedBy.map((f) => `${docsRelative(config.docsDir, featureSpecPaths(f.dir, service).dir)}/`),
144
+ };
145
+ print(inv, { service, origin, duplicatesOnly: opts.duplicates === true });
146
+ printCatalogue({ catalogue, against, where, introducedBy });
112
147
  });
113
148
  }
149
+ /**
150
+ * Every introducing feature's spec pair, not just the first: with two features
151
+ * each introducing the service, the suite that exists once both merge needs the
152
+ * glue for both, and this command has no flag to choose one. The catalogue path
153
+ * is the unfiled spelling — where archive materialises a new service — and is
154
+ * reported, never written: `printCatalogue` says why nobody should create it
155
+ * yet.
156
+ */
157
+ function introducedSource(docsDir, service, introducedBy) {
158
+ return {
159
+ service,
160
+ files: introducedBy.flatMap((f) => {
161
+ const paths = featureSpecPaths(f.dir, service);
162
+ return SPEC_AXES.map((axis) => ({ axis, path: paths[axis.key] }));
163
+ }),
164
+ steps: unfiledServicePaths(docsDir, service).steps,
165
+ introducedBy,
166
+ };
167
+ }
168
+ /** A docs-relative POSIX path, the spelling every path in this command's output uses. */
169
+ function docsRelative(docsDir, path) {
170
+ return relative(docsDir, path).split(/[\\/]/).join("/");
171
+ }
114
172
  /**
115
173
  * The human view leads with the two numbers a team plans from — how many steps
116
174
  * are written, and how few definitions cover most of them — because the list
117
175
  * underneath is long by construction and the headline is what decides whether
118
176
  * anybody reads it.
177
+ *
178
+ * For an introduced service the source is said straight under the headline:
179
+ * the same numbers read off a delta are a proposal, and a reader who takes them
180
+ * for a living spec's would plan glue for scenarios review may still change.
119
181
  */
120
- function print(inv, service, duplicatesOnly) {
182
+ function print(inv, view) {
183
+ const { service, origin, duplicatesOnly } = view;
184
+ const from = origin === null
185
+ ? null
186
+ : ` read from the feature delta, not a living spec: ${origin.dirs.join(", ")} — ` +
187
+ `${service} is introduced by ${origin.by} and is not in the living docs until it archives`;
121
188
  if (inv.steps === 0) {
122
- console.log(`steps ${service} — the living specs hold no scenario steps yet.\n`);
189
+ console.log(origin === null
190
+ ? `steps ${service} — the living specs hold no scenario steps yet.\n`
191
+ : `steps ${service} — the delta introducing it holds no scenario steps yet.\n${from}\n`);
123
192
  return;
124
193
  }
125
194
  const covering = coveringPhrases(inv);
126
195
  const share = Math.round((100 * inv.phrases.reduce((a, p, i) => (i < covering ? a + p.count : a), 0)) / inv.steps);
127
196
  console.log(`steps ${service} — ${inv.steps} written step(s), ${inv.phrases.length} distinct phrase(s)`);
197
+ if (from !== null)
198
+ console.log(from);
128
199
  console.log(` ${covering} phrase(s) cover ${share}% of them — that is the size of the step-definition registry\n`);
129
200
  if (!duplicatesOnly) {
130
201
  for (const p of inv.phrases) {
@@ -158,7 +229,16 @@ function print(inv, service, duplicatesOnly) {
158
229
  * Nothing here is a finding and nothing changes the exit code. `loam steps` is a
159
230
  * read, and a phrase written before its glue is the normal order of work.
160
231
  */
161
- function printCatalogue({ catalogue, against, where }) {
232
+ function printCatalogue({ catalogue, against, where, introducedBy }) {
233
+ // A service still in flight gets the opposite advice. `steps.yaml` is a
234
+ // service artifact (repo/paths.ts), so writing one where it belongs mints the
235
+ // service's directory — and the service with it — before its feature merges,
236
+ // after which nothing reads the feature's specs/ as introducing it any more.
237
+ if (!catalogue.present && introducedBy.length > 0) {
238
+ console.log(`\n no catalogue yet — ${where} lands with the service when ${introducedBy.join(", ")} archives.`);
239
+ console.log(" Write it after the archive: a steps.yaml there now would put the service in the living docs before its feature merges.");
240
+ return;
241
+ }
162
242
  if (!catalogue.present) {
163
243
  console.log(`\n no ${where} — nothing records which phrases this suite has decided to define.`);
164
244
  console.log(" Write one (a `steps:` list of step texts) and this report becomes a diff instead of a recount.");