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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (901) hide show
  1. package/CHANGELOG.md +3448 -0
  2. package/COMPARISON.md +91 -3
  3. package/CONTRIBUTING.md +37 -0
  4. package/MIGRATING-from-OpenSpec.md +47 -23
  5. package/QUICKSTART.md +189 -12
  6. package/README.md +274 -65
  7. package/ROADMAP.md +572 -31
  8. package/SCHEMA.md +1709 -155
  9. package/WORKFLOW.md +298 -72
  10. package/dist/cli.js +26 -8
  11. package/dist/cli.js.map +1 -1
  12. package/dist/commands/adopt/adopt.js +5 -10
  13. package/dist/commands/adopt/adopt.js.map +1 -1
  14. package/dist/commands/adopt/render.js +50 -9
  15. package/dist/commands/adopt/render.js.map +1 -1
  16. package/dist/commands/archive/archive.js +16 -19
  17. package/dist/commands/archive/archive.js.map +1 -1
  18. package/dist/commands/archive/closing.js +42 -0
  19. package/dist/commands/archive/closing.js.map +1 -0
  20. package/dist/commands/archive/plan/contracts/asyncapi.js +36 -42
  21. package/dist/commands/archive/plan/contracts/asyncapi.js.map +1 -1
  22. package/dist/commands/archive/plan/contracts/consumers.js +56 -0
  23. package/dist/commands/archive/plan/contracts/consumers.js.map +1 -0
  24. package/dist/commands/archive/plan/contracts/openapi.js +77 -43
  25. package/dist/commands/archive/plan/contracts/openapi.js.map +1 -1
  26. package/dist/commands/archive/plan/contracts/verdict-lines.js +103 -0
  27. package/dist/commands/archive/plan/contracts/verdict-lines.js.map +1 -0
  28. package/dist/commands/archive/plan/document/head.js +151 -0
  29. package/dist/commands/archive/plan/document/head.js.map +1 -0
  30. package/dist/commands/archive/plan/document/links.js +284 -0
  31. package/dist/commands/archive/plan/document/links.js.map +1 -0
  32. package/dist/commands/archive/plan/document/run.js +136 -0
  33. package/dist/commands/archive/plan/document/run.js.map +1 -0
  34. package/dist/commands/archive/plan/gate.js +21 -19
  35. package/dist/commands/archive/plan/gate.js.map +1 -1
  36. package/dist/commands/archive/plan/landscape.js +167 -30
  37. package/dist/commands/archive/plan/landscape.js.map +1 -1
  38. package/dist/commands/archive/plan/model/extending.js +85 -0
  39. package/dist/commands/archive/plan/model/extending.js.map +1 -0
  40. package/dist/commands/archive/plan/refusal.js +14 -19
  41. package/dist/commands/archive/plan/refusal.js.map +1 -1
  42. package/dist/commands/archive/plan/specs.js +137 -56
  43. package/dist/commands/archive/plan/specs.js.map +1 -1
  44. package/dist/commands/archive/plan/state.js +3 -0
  45. package/dist/commands/archive/plan/state.js.map +1 -1
  46. package/dist/commands/archive/run.js +134 -30
  47. package/dist/commands/archive/run.js.map +1 -1
  48. package/dist/commands/archive/shipped.js +49 -0
  49. package/dist/commands/archive/shipped.js.map +1 -0
  50. package/dist/commands/context/context.js +85 -18
  51. package/dist/commands/context/context.js.map +1 -1
  52. package/dist/commands/context/print.js +29 -7
  53. package/dist/commands/context/print.js.map +1 -1
  54. package/dist/commands/delta/delta.js +102 -14
  55. package/dist/commands/delta/delta.js.map +1 -1
  56. package/dist/commands/delta/print.js +17 -1
  57. package/dist/commands/delta/print.js.map +1 -1
  58. package/dist/commands/dependencies.js +3 -7
  59. package/dist/commands/dependencies.js.map +1 -1
  60. package/dist/commands/diff/diff.js +20 -27
  61. package/dist/commands/diff/diff.js.map +1 -1
  62. package/dist/commands/doctor.js +60 -1
  63. package/dist/commands/doctor.js.map +1 -1
  64. package/dist/commands/explain/explain.js +89 -13
  65. package/dist/commands/explain/explain.js.map +1 -1
  66. package/dist/commands/explore.js +16 -10
  67. package/dist/commands/explore.js.map +1 -1
  68. package/dist/commands/gate/gate.js +45 -8
  69. package/dist/commands/gate/gate.js.map +1 -1
  70. package/dist/commands/gate/print.js +15 -3
  71. package/dist/commands/gate/print.js.map +1 -1
  72. package/dist/commands/gherkin/commit.js +13 -54
  73. package/dist/commands/gherkin/commit.js.map +1 -1
  74. package/dist/commands/gherkin/gherkin.js +36 -20
  75. package/dist/commands/gherkin/gherkin.js.map +1 -1
  76. package/dist/commands/gherkin/reconcile.js +10 -13
  77. package/dist/commands/gherkin/reconcile.js.map +1 -1
  78. package/dist/commands/init/first-hour.js +44 -0
  79. package/dist/commands/init/first-hour.js.map +1 -1
  80. package/dist/commands/init/init.js +18 -22
  81. package/dist/commands/init/init.js.map +1 -1
  82. package/dist/commands/list/campaign/campaign.js +4 -6
  83. package/dist/commands/list/campaign/campaign.js.map +1 -1
  84. package/dist/commands/list/json.js +5 -7
  85. package/dist/commands/list/json.js.map +1 -1
  86. package/dist/commands/list/list.js +44 -29
  87. package/dist/commands/list/list.js.map +1 -1
  88. package/dist/commands/list/print.js +52 -9
  89. package/dist/commands/list/print.js.map +1 -1
  90. package/dist/commands/list/suites/suites.js +140 -0
  91. package/dist/commands/list/suites/suites.js.map +1 -0
  92. package/dist/commands/list/views.js +37 -34
  93. package/dist/commands/list/views.js.map +1 -1
  94. package/dist/commands/mcp/dispatch.js +91 -36
  95. package/dist/commands/mcp/dispatch.js.map +1 -1
  96. package/dist/commands/mcp/mcp.js +56 -15
  97. package/dist/commands/mcp/mcp.js.map +1 -1
  98. package/dist/commands/mcp/serve.js.map +1 -1
  99. package/dist/commands/migrate-openspec/materialize/active.js +27 -22
  100. package/dist/commands/migrate-openspec/materialize/active.js.map +1 -1
  101. package/dist/commands/migrate-openspec/materialize/stage.js +4 -3
  102. package/dist/commands/migrate-openspec/materialize/stage.js.map +1 -1
  103. package/dist/commands/migrate-openspec/materialize/target.js +2 -2
  104. package/dist/commands/migrate-openspec/materialize/target.js.map +1 -1
  105. package/dist/commands/migrate-openspec/openspec/decisions.js +9 -14
  106. package/dist/commands/migrate-openspec/openspec/decisions.js.map +1 -1
  107. package/dist/commands/migrate-openspec/openspec/error.js +7 -8
  108. package/dist/commands/migrate-openspec/openspec/error.js.map +1 -1
  109. package/dist/commands/migrate-openspec/openspec/mapping.js +1 -9
  110. package/dist/commands/migrate-openspec/openspec/mapping.js.map +1 -1
  111. package/dist/commands/migrate-openspec/openspec/paths.js +3 -6
  112. package/dist/commands/migrate-openspec/openspec/paths.js.map +1 -1
  113. package/dist/commands/new/capability-template.js +118 -0
  114. package/dist/commands/new/capability-template.js.map +1 -0
  115. package/dist/commands/new/commit.js +8 -22
  116. package/dist/commands/new/commit.js.map +1 -1
  117. package/dist/commands/new/modifies.js +206 -0
  118. package/dist/commands/new/modifies.js.map +1 -0
  119. package/dist/commands/new/new.js +59 -14
  120. package/dist/commands/new/new.js.map +1 -1
  121. package/dist/commands/new/templates.js +48 -124
  122. package/dist/commands/new/templates.js.map +1 -1
  123. package/dist/commands/open.js +3 -7
  124. package/dist/commands/open.js.map +1 -1
  125. package/dist/commands/policy/gate.js +27 -0
  126. package/dist/commands/policy/gate.js.map +1 -1
  127. package/dist/commands/rebase/plan.js +2 -2
  128. package/dist/commands/rebase/plan.js.map +1 -1
  129. package/dist/commands/rebase/rebase.js +60 -35
  130. package/dist/commands/rebase/rebase.js.map +1 -1
  131. package/dist/commands/seed/commit.js +55 -26
  132. package/dist/commands/seed/commit.js.map +1 -1
  133. package/dist/commands/seed/plan.js +158 -13
  134. package/dist/commands/seed/plan.js.map +1 -1
  135. package/dist/commands/seed/seed.js +13 -11
  136. package/dist/commands/seed/seed.js.map +1 -1
  137. package/dist/commands/show/feature.js +9 -5
  138. package/dist/commands/show/feature.js.map +1 -1
  139. package/dist/commands/show/introduced.js +157 -0
  140. package/dist/commands/show/introduced.js.map +1 -0
  141. package/dist/commands/show/marks.js +35 -6
  142. package/dist/commands/show/marks.js.map +1 -1
  143. package/dist/commands/show/service.js +41 -33
  144. package/dist/commands/show/service.js.map +1 -1
  145. package/dist/commands/show/show.js +17 -7
  146. package/dist/commands/show/show.js.map +1 -1
  147. package/dist/commands/status/fleet-next.js +90 -0
  148. package/dist/commands/status/fleet-next.js.map +1 -0
  149. package/dist/commands/status/json.js +2 -0
  150. package/dist/commands/status/json.js.map +1 -1
  151. package/dist/commands/status/print.js +89 -37
  152. package/dist/commands/status/print.js.map +1 -1
  153. package/dist/commands/status/status.js +3 -7
  154. package/dist/commands/status/status.js.map +1 -1
  155. package/dist/commands/steps/steps.js +103 -23
  156. package/dist/commands/steps/steps.js.map +1 -1
  157. package/dist/commands/subsystem/edit.js +7 -7
  158. package/dist/commands/subsystem/edit.js.map +1 -1
  159. package/dist/commands/subsystem/move.js +106 -46
  160. package/dist/commands/subsystem/move.js.map +1 -1
  161. package/dist/commands/subsystem/query.js +2 -4
  162. package/dist/commands/subsystem/query.js.map +1 -1
  163. package/dist/commands/subsystem/subsystem.js +4 -7
  164. package/dist/commands/subsystem/subsystem.js.map +1 -1
  165. package/dist/commands/subsystem/sync.js +289 -74
  166. package/dist/commands/subsystem/sync.js.map +1 -1
  167. package/dist/commands/subsystem/txn/exclude.js +132 -0
  168. package/dist/commands/subsystem/txn/exclude.js.map +1 -0
  169. package/dist/commands/subsystem/txn/links.js +128 -0
  170. package/dist/commands/subsystem/txn/links.js.map +1 -0
  171. package/dist/commands/subsystem/txn/report.js +174 -0
  172. package/dist/commands/subsystem/txn/report.js.map +1 -0
  173. package/dist/commands/subsystem/txn/txn.js +147 -45
  174. package/dist/commands/subsystem/txn/txn.js.map +1 -1
  175. package/dist/commands/subsystem/txn/views.js +200 -21
  176. package/dist/commands/subsystem/txn/views.js.map +1 -1
  177. package/dist/commands/tasks/actions.js +107 -0
  178. package/dist/commands/tasks/actions.js.map +1 -0
  179. package/dist/commands/tasks/render.js +253 -0
  180. package/dist/commands/tasks/render.js.map +1 -0
  181. package/dist/commands/tasks/tasks.js +119 -0
  182. package/dist/commands/tasks/tasks.js.map +1 -0
  183. package/dist/commands/unarchive/manifest.js +42 -26
  184. package/dist/commands/unarchive/manifest.js.map +1 -1
  185. package/dist/commands/unarchive/restore.js +83 -33
  186. package/dist/commands/unarchive/restore.js.map +1 -1
  187. package/dist/commands/unarchive/unarchive.js +22 -30
  188. package/dist/commands/unarchive/unarchive.js.map +1 -1
  189. package/dist/commands/validate/arch-coverage.js +78 -27
  190. package/dist/commands/validate/arch-coverage.js.map +1 -1
  191. package/dist/commands/validate/checks/fleet-shape.js +34 -126
  192. package/dist/commands/validate/checks/fleet-shape.js.map +1 -1
  193. package/dist/commands/validate/checks/health-deps.js +9 -6
  194. package/dist/commands/validate/checks/health-deps.js.map +1 -1
  195. package/dist/commands/validate/checks/introduced.js +102 -0
  196. package/dist/commands/validate/checks/introduced.js.map +1 -0
  197. package/dist/commands/validate/checks/requirements.js +18 -8
  198. package/dist/commands/validate/checks/requirements.js.map +1 -1
  199. package/dist/commands/validate/checks/sources.js +11 -2
  200. package/dist/commands/validate/checks/sources.js.map +1 -1
  201. package/dist/commands/validate/coverage/covers-after.js +105 -0
  202. package/dist/commands/validate/coverage/covers-after.js.map +1 -0
  203. package/dist/commands/validate/feature.js +26 -20
  204. package/dist/commands/validate/feature.js.map +1 -1
  205. package/dist/commands/validate/fleet/census.js +37 -13
  206. package/dist/commands/validate/fleet/census.js.map +1 -1
  207. package/dist/commands/validate/fleet/landscape.js +144 -126
  208. package/dist/commands/validate/fleet/landscape.js.map +1 -1
  209. package/dist/commands/validate/fleet/load.js +66 -0
  210. package/dist/commands/validate/fleet/load.js.map +1 -1
  211. package/dist/commands/validate/fleet/map/attest.js +98 -0
  212. package/dist/commands/validate/fleet/map/attest.js.map +1 -0
  213. package/dist/commands/validate/fleet/map/bindings.js +107 -0
  214. package/dist/commands/validate/fleet/map/bindings.js.map +1 -0
  215. package/dist/commands/validate/fleet/map/consumers.js +244 -0
  216. package/dist/commands/validate/fleet/map/consumers.js.map +1 -0
  217. package/dist/commands/validate/fleet/map/isolation.js +116 -0
  218. package/dist/commands/validate/fleet/map/isolation.js.map +1 -0
  219. package/dist/commands/validate/fleet/map/usecases.js +54 -0
  220. package/dist/commands/validate/fleet/map/usecases.js.map +1 -0
  221. package/dist/commands/validate/fleet/obligations.js +44 -14
  222. package/dist/commands/validate/fleet/obligations.js.map +1 -1
  223. package/dist/commands/validate/fleet/scorecard/print.js +10 -2
  224. package/dist/commands/validate/fleet/scorecard/print.js.map +1 -1
  225. package/dist/commands/validate/fleet/scorecard/scorecard.js +17 -11
  226. package/dist/commands/validate/fleet/scorecard/scorecard.js.map +1 -1
  227. package/dist/commands/validate/fleet/usecases/place.js.map +1 -1
  228. package/dist/commands/validate/fleet/views/fleet-project.js +217 -0
  229. package/dist/commands/validate/fleet/views/fleet-project.js.map +1 -0
  230. package/dist/commands/validate/fleet/views/ids.js +50 -15
  231. package/dist/commands/validate/fleet/views/ids.js.map +1 -1
  232. package/dist/commands/validate/fleet/views/projects.js +278 -0
  233. package/dist/commands/validate/fleet/views/projects.js.map +1 -0
  234. package/dist/commands/validate/fleet/views/root-documents.js +83 -0
  235. package/dist/commands/validate/fleet/views/root-documents.js.map +1 -0
  236. package/dist/commands/validate/fleet/views/stale.js +40 -47
  237. package/dist/commands/validate/fleet/views/stale.js.map +1 -1
  238. package/dist/commands/validate/links/corpus.js +1 -4
  239. package/dist/commands/validate/links/corpus.js.map +1 -1
  240. package/dist/commands/validate/links/glossary.js.map +1 -1
  241. package/dist/commands/validate/render/repeats.js +63 -0
  242. package/dist/commands/validate/render/repeats.js.map +1 -0
  243. package/dist/commands/validate/render/rollups.js +115 -0
  244. package/dist/commands/validate/render/rollups.js.map +1 -0
  245. package/dist/commands/validate/render/text.js +199 -0
  246. package/dist/commands/validate/render/text.js.map +1 -0
  247. package/dist/commands/validate/report.js +36 -160
  248. package/dist/commands/validate/report.js.map +1 -1
  249. package/dist/commands/validate/scope.js +113 -0
  250. package/dist/commands/validate/scope.js.map +1 -0
  251. package/dist/commands/validate/service/api.js +21 -107
  252. package/dist/commands/validate/service/api.js.map +1 -1
  253. package/dist/commands/validate/service/contracts/generated.js +134 -0
  254. package/dist/commands/validate/service/contracts/generated.js.map +1 -0
  255. package/dist/commands/validate/service/events/events.js +36 -14
  256. package/dist/commands/validate/service/events/events.js.map +1 -1
  257. package/dist/commands/validate/service/events/message-producers.js +1 -1
  258. package/dist/commands/validate/service/events/message-producers.js.map +1 -1
  259. package/dist/commands/validate/service/evidence-pins.js +56 -10
  260. package/dist/commands/validate/service/evidence-pins.js.map +1 -1
  261. package/dist/commands/validate/service/model/diverged.js +226 -0
  262. package/dist/commands/validate/service/model/diverged.js.map +1 -0
  263. package/dist/commands/validate/service/model/grade.js +163 -0
  264. package/dist/commands/validate/service/model/grade.js.map +1 -0
  265. package/dist/commands/validate/service/service.js +121 -61
  266. package/dist/commands/validate/service/service.js.map +1 -1
  267. package/dist/commands/validate/service/specs.js +88 -28
  268. package/dist/commands/validate/service/specs.js.map +1 -1
  269. package/dist/commands/validate/service/spine.js +38 -3
  270. package/dist/commands/validate/service/spine.js.map +1 -1
  271. package/dist/commands/validate/service/usecases/tags.js +113 -0
  272. package/dist/commands/validate/service/usecases/tags.js.map +1 -0
  273. package/dist/commands/validate/service/usecases/usecases.js +209 -0
  274. package/dist/commands/validate/service/usecases/usecases.js.map +1 -0
  275. package/dist/commands/validate/validate.js +85 -60
  276. package/dist/commands/validate/validate.js.map +1 -1
  277. package/dist/commands/verify/cross/diff.js +2 -6
  278. package/dist/commands/verify/cross/diff.js.map +1 -1
  279. package/dist/commands/verify/evidence/contract.js +1 -1
  280. package/dist/commands/verify/evidence/contract.js.map +1 -1
  281. package/dist/commands/verify/evidence/read.js +12 -3
  282. package/dist/commands/verify/evidence/read.js.map +1 -1
  283. package/dist/commands/verify/frozen.js +45 -23
  284. package/dist/commands/verify/frozen.js.map +1 -1
  285. package/dist/commands/verify/record.js +69 -17
  286. package/dist/commands/verify/record.js.map +1 -1
  287. package/dist/commands/verify/report.js +27 -44
  288. package/dist/commands/verify/report.js.map +1 -1
  289. package/dist/commands/verify/results.js +112 -30
  290. package/dist/commands/verify/results.js.map +1 -1
  291. package/dist/commands/verify/verify.js +55 -52
  292. package/dist/commands/verify/verify.js.map +1 -1
  293. package/dist/commands/vouch/pack/pack.js +2 -2
  294. package/dist/commands/vouch/pack/pack.js.map +1 -1
  295. package/dist/commands/vouch/pack/print.js +1 -6
  296. package/dist/commands/vouch/pack/print.js.map +1 -1
  297. package/dist/commands/vouch/pack/sections.js +1 -2
  298. package/dist/commands/vouch/pack/sections.js.map +1 -1
  299. package/dist/commands/vouch/run.js +26 -81
  300. package/dist/commands/vouch/run.js.map +1 -1
  301. package/dist/commands/vouch/sample/plan.js +20 -34
  302. package/dist/commands/vouch/sample/plan.js.map +1 -1
  303. package/dist/commands/vouch/vet/verify.js +39 -7
  304. package/dist/commands/vouch/vet/verify.js.map +1 -1
  305. package/dist/commands/vouch/vouch.js +10 -17
  306. package/dist/commands/vouch/vouch.js.map +1 -1
  307. package/dist/core/agent/agents-md/command-map.js +81 -106
  308. package/dist/core/agent/agents-md/command-map.js.map +1 -1
  309. package/dist/core/agent/agents-md/map/explain.js +21 -9
  310. package/dist/core/agent/agents-md/map/explain.js.map +1 -1
  311. package/dist/core/agent/agents-md/map/lenses/context.js +17 -8
  312. package/dist/core/agent/agents-md/map/lenses/context.js.map +1 -1
  313. package/dist/core/agent/agents-md/map/lenses/diff.js +33 -20
  314. package/dist/core/agent/agents-md/map/lenses/diff.js.map +1 -1
  315. package/dist/core/agent/agents-md/map/lenses/gate.js +13 -5
  316. package/dist/core/agent/agents-md/map/lenses/gate.js.map +1 -1
  317. package/dist/core/agent/agents-md/map/mcp.js +10 -7
  318. package/dist/core/agent/agents-md/map/mcp.js.map +1 -1
  319. package/dist/core/agent/agents-md/map/status.js +24 -8
  320. package/dist/core/agent/agents-md/map/status.js.map +1 -1
  321. package/dist/core/agent/agents-md/map/subsystem.js +80 -8
  322. package/dist/core/agent/agents-md/map/subsystem.js.map +1 -1
  323. package/dist/core/agent/agents-md/map/usecases.js +88 -10
  324. package/dist/core/agent/agents-md/map/usecases.js.map +1 -1
  325. package/dist/core/agent/agents-md/refusals.js +49 -22
  326. package/dist/core/agent/agents-md/refusals.js.map +1 -1
  327. package/dist/core/agent/agents-md.js +39 -6
  328. package/dist/core/agent/agents-md.js.map +1 -1
  329. package/dist/core/agent/agents-stamp.js +10 -0
  330. package/dist/core/agent/agents-stamp.js.map +1 -1
  331. package/dist/core/agent/protocol.js +1 -1
  332. package/dist/core/agent/protocol.js.map +1 -1
  333. package/dist/core/agent/scaffold.js +10 -15
  334. package/dist/core/agent/scaffold.js.map +1 -1
  335. package/dist/core/agent/support/report.js +46 -5
  336. package/dist/core/agent/support/report.js.map +1 -1
  337. package/dist/core/agent/tools/dialects.js +1 -0
  338. package/dist/core/agent/tools/dialects.js.map +1 -1
  339. package/dist/core/agent/tools/registry.js +41 -76
  340. package/dist/core/agent/tools/registry.js.map +1 -1
  341. package/dist/core/agent/workflows/adopt.js +158 -11
  342. package/dist/core/agent/workflows/adopt.js.map +1 -1
  343. package/dist/core/agent/workflows/check.js +78 -39
  344. package/dist/core/agent/workflows/check.js.map +1 -1
  345. package/dist/core/agent/workflows/closing.js +88 -27
  346. package/dist/core/agent/workflows/closing.js.map +1 -1
  347. package/dist/core/agent/workflows/feature.js +128 -13
  348. package/dist/core/agent/workflows/feature.js.map +1 -1
  349. package/dist/core/agent/workflows/implement.js +96 -13
  350. package/dist/core/agent/workflows/implement.js.map +1 -1
  351. package/dist/core/agent/workflows/reference/authoring.js +106 -4
  352. package/dist/core/agent/workflows/reference/authoring.js.map +1 -1
  353. package/dist/core/agent/workflows/reference/codes.js +8 -6
  354. package/dist/core/agent/workflows/reference/codes.js.map +1 -1
  355. package/dist/core/agent/workflows/reference/done-check.js +37 -15
  356. package/dist/core/agent/workflows/reference/done-check.js.map +1 -1
  357. package/dist/core/agent/workflows/reference/drawing/drawing.js +253 -0
  358. package/dist/core/agent/workflows/reference/drawing/drawing.js.map +1 -0
  359. package/dist/core/agent/workflows/reference/reference.js +6 -3
  360. package/dist/core/agent/workflows/reference/reference.js.map +1 -1
  361. package/dist/core/agent/workflows/reference/spine.js +68 -27
  362. package/dist/core/agent/workflows/reference/spine.js.map +1 -1
  363. package/dist/core/asyncapi/baseline/plan.js +14 -81
  364. package/dist/core/asyncapi/baseline/plan.js.map +1 -1
  365. package/dist/core/asyncapi/digest.js +30 -25
  366. package/dist/core/asyncapi/digest.js.map +1 -1
  367. package/dist/core/asyncapi/merge/components.js +5 -4
  368. package/dist/core/asyncapi/merge/components.js.map +1 -1
  369. package/dist/core/asyncapi/merge/error.js +7 -2
  370. package/dist/core/asyncapi/merge/error.js.map +1 -1
  371. package/dist/core/asyncapi/merge/markers.js +32 -50
  372. package/dist/core/asyncapi/merge/markers.js.map +1 -1
  373. package/dist/core/asyncapi/merge/merge.js +33 -53
  374. package/dist/core/asyncapi/merge/merge.js.map +1 -1
  375. package/dist/core/asyncapi/merge/pin.js +12 -36
  376. package/dist/core/asyncapi/merge/pin.js.map +1 -1
  377. package/dist/core/asyncapi/model.js.map +1 -1
  378. package/dist/core/asyncapi/read.js +36 -12
  379. package/dist/core/asyncapi/read.js.map +1 -1
  380. package/dist/core/brief/brief.js +96 -36
  381. package/dist/core/brief/brief.js.map +1 -1
  382. package/dist/core/brief/checks.js +138 -3
  383. package/dist/core/brief/checks.js.map +1 -1
  384. package/dist/core/brief/landscape.js +209 -130
  385. package/dist/core/brief/landscape.js.map +1 -1
  386. package/dist/core/brief/map/extend.js +84 -0
  387. package/dist/core/brief/map/extend.js.map +1 -0
  388. package/dist/core/brief/map/owed.js +266 -0
  389. package/dist/core/brief/map/owed.js.map +1 -0
  390. package/dist/core/brief/targets.js +109 -31
  391. package/dist/core/brief/targets.js.map +1 -1
  392. package/dist/core/brief/unchecked.js +14 -3
  393. package/dist/core/brief/unchecked.js.map +1 -1
  394. package/dist/core/c4/arch.js +90 -182
  395. package/dist/core/c4/arch.js.map +1 -1
  396. package/dist/core/c4/direction/direction.js +114 -0
  397. package/dist/core/c4/direction/direction.js.map +1 -0
  398. package/dist/core/c4/likec4.js +169 -14
  399. package/dist/core/c4/likec4.js.map +1 -1
  400. package/dist/core/c4/locate/unlocated.js +150 -0
  401. package/dist/core/c4/locate/unlocated.js.map +1 -0
  402. package/dist/core/c4/parsed/deployment.js +160 -0
  403. package/dist/core/c4/parsed/deployment.js.map +1 -0
  404. package/dist/core/c4/parsed/dynamic-views.js.map +1 -1
  405. package/dist/core/c4/parsed/values.js +54 -1
  406. package/dist/core/c4/parsed/values.js.map +1 -1
  407. package/dist/core/c4/parsed/view-ids.js +39 -1
  408. package/dist/core/c4/parsed/view-ids.js.map +1 -1
  409. package/dist/core/c4/prefetch/fleet.js +134 -0
  410. package/dist/core/c4/prefetch/fleet.js.map +1 -0
  411. package/dist/core/c4/project/architecture.js +123 -7
  412. package/dist/core/c4/project/architecture.js.map +1 -1
  413. package/dist/core/c4/project/batch.js +140 -0
  414. package/dist/core/c4/project/batch.js.map +1 -0
  415. package/dist/core/c4/project/documents.js +43 -12
  416. package/dist/core/c4/project/documents.js.map +1 -1
  417. package/dist/core/c4/project/load.js +79 -43
  418. package/dist/core/c4/project/load.js.map +1 -1
  419. package/dist/core/c4/project/staged.js +277 -0
  420. package/dist/core/c4/project/staged.js.map +1 -0
  421. package/dist/core/c4/resolve/attested.js +0 -0
  422. package/dist/core/c4/resolve/attested.js.map +1 -0
  423. package/dist/core/c4/resolve/external.js +51 -0
  424. package/dist/core/c4/resolve/external.js.map +1 -0
  425. package/dist/core/c4/resolve/service.js +78 -17
  426. package/dist/core/c4/resolve/service.js.map +1 -1
  427. package/dist/core/c4/resolve/steps.js +290 -0
  428. package/dist/core/c4/resolve/steps.js.map +1 -0
  429. package/dist/core/c4/resolve/systems.js +154 -0
  430. package/dist/core/c4/resolve/systems.js.map +1 -0
  431. package/dist/core/c4/root-project/exclude.js +352 -0
  432. package/dist/core/c4/root-project/exclude.js.map +1 -0
  433. package/dist/core/c4/seed/template.js +65 -1
  434. package/dist/core/c4/seed/template.js.map +1 -1
  435. package/dist/core/c4/service-model/created/models.js +96 -0
  436. package/dist/core/c4/service-model/created/models.js.map +1 -0
  437. package/dist/core/c4/service-model/documents.js +47 -0
  438. package/dist/core/c4/service-model/documents.js.map +1 -0
  439. package/dist/core/c4/service-model/fleet/extending.js +82 -0
  440. package/dist/core/c4/service-model/fleet/extending.js.map +1 -0
  441. package/dist/core/c4/service-model/load.js +165 -0
  442. package/dist/core/c4/service-model/load.js.map +1 -0
  443. package/dist/core/c4/service-model/renderer.js +128 -0
  444. package/dist/core/c4/service-model/renderer.js.map +1 -0
  445. package/dist/core/c4/service-model/shape.js +106 -0
  446. package/dist/core/c4/service-model/shape.js.map +1 -0
  447. package/dist/core/c4/service-model/slice.js +188 -0
  448. package/dist/core/c4/service-model/slice.js.map +1 -0
  449. package/dist/core/c4/source-mask.js +297 -10
  450. package/dist/core/c4/source-mask.js.map +1 -1
  451. package/dist/core/c4/source-scan.js +222 -141
  452. package/dist/core/c4/source-scan.js.map +1 -1
  453. package/dist/core/c4/splice/authored-source.js +79 -13
  454. package/dist/core/c4/splice/authored-source.js.map +1 -1
  455. package/dist/core/c4/splice/contract.js +20 -0
  456. package/dist/core/c4/splice/contract.js.map +1 -1
  457. package/dist/core/c4/splice/delta-blocks.js +20 -20
  458. package/dist/core/c4/splice/delta-blocks.js.map +1 -1
  459. package/dist/core/c4/splice/identity/declared.js +87 -0
  460. package/dist/core/c4/splice/identity/declared.js.map +1 -0
  461. package/dist/core/c4/splice/identity/edges.js +37 -0
  462. package/dist/core/c4/splice/identity/edges.js.map +1 -1
  463. package/dist/core/c4/splice/identity/existing.js +80 -0
  464. package/dist/core/c4/splice/identity/existing.js.map +1 -0
  465. package/dist/core/c4/splice/identity/interior.js +80 -0
  466. package/dist/core/c4/splice/identity/interior.js.map +1 -0
  467. package/dist/core/c4/splice/identity/owner.js +50 -0
  468. package/dist/core/c4/splice/identity/owner.js.map +1 -0
  469. package/dist/core/c4/splice/landscape-merge.js +182 -114
  470. package/dist/core/c4/splice/landscape-merge.js.map +1 -1
  471. package/dist/core/c4/splice/model/merge.js +151 -0
  472. package/dist/core/c4/splice/model/merge.js.map +1 -0
  473. package/dist/core/c4/splice/placement.js +160 -56
  474. package/dist/core/c4/splice/placement.js.map +1 -1
  475. package/dist/core/c4/splice/text/spot.js +131 -0
  476. package/dist/core/c4/splice/text/spot.js.map +1 -0
  477. package/dist/core/c4/workspace.js +13 -19
  478. package/dist/core/c4/workspace.js.map +1 -1
  479. package/dist/core/capabilities/capabilities.js +6 -6
  480. package/dist/core/capabilities/capabilities.js.map +1 -1
  481. package/dist/core/capabilities/delta/doc.js +7 -10
  482. package/dist/core/capabilities/delta/doc.js.map +1 -1
  483. package/dist/core/capabilities/delta/uncovered.js +2 -2
  484. package/dist/core/capabilities/delta/uncovered.js.map +1 -1
  485. package/dist/core/capabilities/findings.js +18 -22
  486. package/dist/core/capabilities/findings.js.map +1 -1
  487. package/dist/core/capabilities/realizes/findings.js +12 -19
  488. package/dist/core/capabilities/realizes/findings.js.map +1 -1
  489. package/dist/core/capabilities/realizes/join.js +0 -20
  490. package/dist/core/capabilities/realizes/join.js.map +1 -1
  491. package/dist/core/capabilities/rollup.js +6 -0
  492. package/dist/core/capabilities/rollup.js.map +1 -1
  493. package/dist/core/capabilities/tree.js +6 -28
  494. package/dist/core/capabilities/tree.js.map +1 -1
  495. package/dist/core/capabilities/usecase-join.js +3 -13
  496. package/dist/core/capabilities/usecase-join.js.map +1 -1
  497. package/dist/core/coherence/authoring/scaffold.js +11 -3
  498. package/dist/core/coherence/authoring/scaffold.js.map +1 -1
  499. package/dist/core/coherence/authoring/sentinels.js +2 -1
  500. package/dist/core/coherence/authoring/sentinels.js.map +1 -1
  501. package/dist/core/coherence/calls/called.js +52 -0
  502. package/dist/core/coherence/calls/called.js.map +1 -0
  503. package/dist/core/coherence/coherence.js +103 -22
  504. package/dist/core/coherence/coherence.js.map +1 -1
  505. package/dist/core/coherence/consumed/operations.js +70 -0
  506. package/dist/core/coherence/consumed/operations.js.map +1 -0
  507. package/dist/core/coherence/consumed/refusal.js +38 -0
  508. package/dist/core/coherence/consumed/refusal.js.map +1 -0
  509. package/dist/core/coherence/covers/health.js +85 -0
  510. package/dist/core/coherence/covers/health.js.map +1 -0
  511. package/dist/core/coherence/declared.js +60 -34
  512. package/dist/core/coherence/declared.js.map +1 -1
  513. package/dist/core/coherence/events/declared.js +44 -59
  514. package/dist/core/coherence/events/declared.js.map +1 -1
  515. package/dist/core/coherence/events/events.js +147 -16
  516. package/dist/core/coherence/events/events.js.map +1 -1
  517. package/dist/core/coherence/events/grades.js +31 -8
  518. package/dist/core/coherence/events/grades.js.map +1 -1
  519. package/dist/core/coherence/events/lookups.js +28 -87
  520. package/dist/core/coherence/events/lookups.js.map +1 -1
  521. package/dist/core/coherence/events/produced.js +100 -0
  522. package/dist/core/coherence/events/produced.js.map +1 -0
  523. package/dist/core/coherence/lookups.js +18 -78
  524. package/dist/core/coherence/lookups.js.map +1 -1
  525. package/dist/core/coherence/retired/archived.js +285 -0
  526. package/dist/core/coherence/retired/archived.js.map +1 -0
  527. package/dist/core/coherence/retired/event-pair.js +62 -0
  528. package/dist/core/coherence/retired/event-pair.js.map +1 -0
  529. package/dist/core/coherence/retired/merged.js +79 -0
  530. package/dist/core/coherence/retired/merged.js.map +1 -0
  531. package/dist/core/coherence/retired/retirement.js +49 -0
  532. package/dist/core/coherence/retired/retirement.js.map +1 -0
  533. package/dist/core/coherence/retired/revival/arrivals.js +131 -0
  534. package/dist/core/coherence/retired/revival/arrivals.js.map +1 -0
  535. package/dist/core/coherence/retired/revival/revived.js +297 -0
  536. package/dist/core/coherence/retired/revival/revived.js.map +1 -0
  537. package/dist/core/consumers/after.js +113 -0
  538. package/dist/core/consumers/after.js.map +1 -0
  539. package/dist/core/consumers/consumers.js +296 -0
  540. package/dist/core/consumers/consumers.js.map +1 -0
  541. package/dist/core/consumers/current.js +211 -0
  542. package/dist/core/consumers/current.js.map +1 -0
  543. package/dist/core/consumers/scan.js +46 -0
  544. package/dist/core/consumers/scan.js.map +1 -0
  545. package/dist/core/consumers/state.js +27 -0
  546. package/dist/core/consumers/state.js.map +1 -0
  547. package/dist/core/delta/delta.js +51 -6
  548. package/dist/core/delta/delta.js.map +1 -1
  549. package/dist/core/dependencies/fanin.js +2 -2
  550. package/dist/core/dependencies/fanin.js.map +1 -1
  551. package/dist/core/deployment/delta.js +191 -0
  552. package/dist/core/deployment/delta.js.map +1 -0
  553. package/dist/core/deployment/objects.js +145 -0
  554. package/dist/core/deployment/objects.js.map +1 -0
  555. package/dist/core/diff/base-git.js +94 -12
  556. package/dist/core/diff/base-git.js.map +1 -1
  557. package/dist/core/diff/base-state.js +49 -21
  558. package/dist/core/diff/base-state.js.map +1 -1
  559. package/dist/core/diff/joins.js +136 -0
  560. package/dist/core/diff/joins.js.map +1 -0
  561. package/dist/core/diff/scope/changed-paths.js +22 -6
  562. package/dist/core/diff/scope/changed-paths.js.map +1 -1
  563. package/dist/core/diff/scope/edges.js +82 -0
  564. package/dist/core/diff/scope/edges.js.map +1 -0
  565. package/dist/core/diff/semantic.js +100 -31
  566. package/dist/core/diff/semantic.js.map +1 -1
  567. package/dist/core/docs.js +31 -22
  568. package/dist/core/docs.js.map +1 -1
  569. package/dist/core/doctor/agents.js +34 -18
  570. package/dist/core/doctor/agents.js.map +1 -1
  571. package/dist/core/doctor/config.js +7 -3
  572. package/dist/core/doctor/config.js.map +1 -1
  573. package/dist/core/doctor/doctor.js +91 -11
  574. package/dist/core/doctor/doctor.js.map +1 -1
  575. package/dist/core/doctor/report.js.map +1 -1
  576. package/dist/core/doctor/reports/scan.js +242 -0
  577. package/dist/core/doctor/reports/scan.js.map +1 -0
  578. package/dist/core/document/apply.js +158 -11
  579. package/dist/core/document/apply.js.map +1 -1
  580. package/dist/core/document/frontmatter.js +55 -0
  581. package/dist/core/document/frontmatter.js.map +1 -1
  582. package/dist/core/document/parse.js +29 -6
  583. package/dist/core/document/parse.js.map +1 -1
  584. package/dist/core/document/scenarios.js +17 -0
  585. package/dist/core/document/scenarios.js.map +1 -1
  586. package/dist/core/document/spec.js +4 -11
  587. package/dist/core/document/spec.js.map +1 -1
  588. package/dist/core/envelope/config.js +10 -0
  589. package/dist/core/envelope/config.js.map +1 -1
  590. package/dist/core/envelope/json.js +34 -0
  591. package/dist/core/envelope/json.js.map +1 -1
  592. package/dist/core/explain/families.js +26 -21
  593. package/dist/core/explain/families.js.map +1 -1
  594. package/dist/core/explain/lookup.js +14 -1
  595. package/dist/core/explain/lookup.js.map +1 -1
  596. package/dist/core/explain/refusals.js +5 -5
  597. package/dist/core/explain/refusals.js.map +1 -1
  598. package/dist/core/explain/terms/documents.js +227 -0
  599. package/dist/core/explain/terms/documents.js.map +1 -0
  600. package/dist/core/explain/terms/done-check.js +144 -0
  601. package/dist/core/explain/terms/done-check.js.map +1 -0
  602. package/dist/core/explain/terms/entry.js +14 -0
  603. package/dist/core/explain/terms/entry.js.map +1 -0
  604. package/dist/core/explain/terms/stages.js +71 -0
  605. package/dist/core/explain/terms/stages.js.map +1 -0
  606. package/dist/core/explain/terms/tasks.js +97 -0
  607. package/dist/core/explain/terms/tasks.js.map +1 -0
  608. package/dist/core/explain/terms.js +68 -109
  609. package/dist/core/explain/terms.js.map +1 -1
  610. package/dist/core/explore/explore.js +40 -10
  611. package/dist/core/explore/explore.js.map +1 -1
  612. package/dist/core/fleet-context.js +81 -95
  613. package/dist/core/fleet-context.js.map +1 -1
  614. package/dist/core/gate/checks.js +11 -4
  615. package/dist/core/gate/checks.js.map +1 -1
  616. package/dist/core/gate/partners.js +69 -28
  617. package/dist/core/gate/partners.js.map +1 -1
  618. package/dist/core/gate/report.js.map +1 -1
  619. package/dist/core/gate/verification.js +75 -12
  620. package/dist/core/gate/verification.js.map +1 -1
  621. package/dist/core/gherkin/stale.js +13 -37
  622. package/dist/core/gherkin/stale.js.map +1 -1
  623. package/dist/core/glossary/delta.js +10 -7
  624. package/dist/core/glossary/delta.js.map +1 -1
  625. package/dist/core/glossary/tree.js +6 -19
  626. package/dist/core/glossary/tree.js.map +1 -1
  627. package/dist/core/kernel/concurrency.js +19 -0
  628. package/dist/core/kernel/concurrency.js.map +1 -1
  629. package/dist/core/kernel/ids/fqn/ancestors.js +65 -0
  630. package/dist/core/kernel/ids/fqn/ancestors.js.map +1 -0
  631. package/dist/core/kernel/path-safety.js +38 -0
  632. package/dist/core/kernel/path-safety.js.map +1 -1
  633. package/dist/core/kernel/records.js +11 -0
  634. package/dist/core/kernel/records.js.map +1 -1
  635. package/dist/core/links/backlinks.js +1 -3
  636. package/dist/core/links/backlinks.js.map +1 -1
  637. package/dist/core/links/corpus.js +51 -37
  638. package/dist/core/links/corpus.js.map +1 -1
  639. package/dist/core/links/findings.js.map +1 -1
  640. package/dist/core/links/parse.js +38 -9
  641. package/dist/core/links/parse.js.map +1 -1
  642. package/dist/core/mcp/argv.js +101 -0
  643. package/dist/core/mcp/argv.js.map +1 -1
  644. package/dist/core/mcp/author-tools.js +2 -1
  645. package/dist/core/mcp/author-tools.js.map +1 -1
  646. package/dist/core/mcp/protocol.js +2 -2
  647. package/dist/core/mcp/protocol.js.map +1 -1
  648. package/dist/core/mcp/tools.js +43 -33
  649. package/dist/core/mcp/tools.js.map +1 -1
  650. package/dist/core/openapi/baseline/gate.js +53 -12
  651. package/dist/core/openapi/baseline/gate.js.map +1 -1
  652. package/dist/core/openapi/baseline/plan.js +40 -10
  653. package/dist/core/openapi/baseline/plan.js.map +1 -1
  654. package/dist/core/openapi/baseline/record.js +0 -1
  655. package/dist/core/openapi/baseline/record.js.map +1 -1
  656. package/dist/core/openapi/contract-text.js +33 -0
  657. package/dist/core/openapi/contract-text.js.map +1 -0
  658. package/dist/core/openapi/contract-tree.js +301 -0
  659. package/dist/core/openapi/contract-tree.js.map +1 -0
  660. package/dist/core/openapi/depth.js +38 -24
  661. package/dist/core/openapi/depth.js.map +1 -1
  662. package/dist/core/openapi/digest.js +52 -2
  663. package/dist/core/openapi/digest.js.map +1 -1
  664. package/dist/core/openapi/doc.js +12 -4
  665. package/dist/core/openapi/doc.js.map +1 -1
  666. package/dist/core/openapi/merge/components.js +25 -60
  667. package/dist/core/openapi/merge/components.js.map +1 -1
  668. package/dist/core/openapi/merge/error.js +3 -13
  669. package/dist/core/openapi/merge/error.js.map +1 -1
  670. package/dist/core/openapi/merge/markers.js +26 -30
  671. package/dist/core/openapi/merge/markers.js.map +1 -1
  672. package/dist/core/openapi/merge/merge.js +28 -52
  673. package/dist/core/openapi/merge/merge.js.map +1 -1
  674. package/dist/core/openapi/merge/pin.js +17 -35
  675. package/dist/core/openapi/merge/pin.js.map +1 -1
  676. package/dist/core/openspec/decide/verdict.js.map +1 -1
  677. package/dist/core/openspec/inventory.js +4 -5
  678. package/dist/core/openspec/inventory.js.map +1 -1
  679. package/dist/core/openspec/model/mapping.js +30 -28
  680. package/dist/core/openspec/model/mapping.js.map +1 -1
  681. package/dist/core/openspec/model/model.js +12 -7
  682. package/dist/core/openspec/model/model.js.map +1 -1
  683. package/dist/core/openspec/scan/changes.js +10 -4
  684. package/dist/core/openspec/scan/changes.js.map +1 -1
  685. package/dist/core/openspec/scan/config.js +7 -16
  686. package/dist/core/openspec/scan/config.js.map +1 -1
  687. package/dist/core/openspec/scan/shape.js +63 -19
  688. package/dist/core/openspec/scan/shape.js.map +1 -1
  689. package/dist/core/openspec/scan/walk.js +21 -38
  690. package/dist/core/openspec/scan/walk.js.map +1 -1
  691. package/dist/core/pack/living.js +43 -4
  692. package/dist/core/pack/living.js.map +1 -1
  693. package/dist/core/pack/pack.js +50 -6
  694. package/dist/core/pack/pack.js.map +1 -1
  695. package/dist/core/projection/arch-slice.js +2 -2
  696. package/dist/core/projection/arch-slice.js.map +1 -1
  697. package/dist/core/projection/introduced.js +14 -0
  698. package/dist/core/projection/introduced.js.map +1 -0
  699. package/dist/core/provenance/findings.js +48 -12
  700. package/dist/core/provenance/findings.js.map +1 -1
  701. package/dist/core/provenance/git.js +33 -57
  702. package/dist/core/provenance/git.js.map +1 -1
  703. package/dist/core/provenance/gitq/moves.js +71 -114
  704. package/dist/core/provenance/gitq/moves.js.map +1 -1
  705. package/dist/core/provenance/gitq/vouched-ancestor.js +2 -2
  706. package/dist/core/provenance/gitq/vouched-ancestor.js.map +1 -1
  707. package/dist/core/provenance/sources.js +23 -6
  708. package/dist/core/provenance/sources.js.map +1 -1
  709. package/dist/core/provenance/stamp.js +5 -17
  710. package/dist/core/provenance/stamp.js.map +1 -1
  711. package/dist/core/repo/authored/paths.js +18 -0
  712. package/dist/core/repo/authored/paths.js.map +1 -1
  713. package/dist/core/repo/entries.js.map +1 -1
  714. package/dist/core/repo/paths.js +92 -6
  715. package/dist/core/repo/paths.js.map +1 -1
  716. package/dist/core/repo/repo.js +74 -14
  717. package/dist/core/repo/repo.js.map +1 -1
  718. package/dist/core/repo/tree/find.js +12 -3
  719. package/dist/core/repo/tree/find.js.map +1 -1
  720. package/dist/core/repo/tree/fs.js +27 -1
  721. package/dist/core/repo/tree/fs.js.map +1 -1
  722. package/dist/core/repo/tree/render/body.js +258 -0
  723. package/dist/core/repo/tree/render/body.js.map +1 -0
  724. package/dist/core/repo/tree/render/projects.js +182 -0
  725. package/dist/core/repo/tree/render/projects.js.map +1 -0
  726. package/dist/core/repo/tree/render/service/header.js +125 -0
  727. package/dist/core/repo/tree/render/service/header.js.map +1 -0
  728. package/dist/core/repo/tree/render/service/peers.js +28 -0
  729. package/dist/core/repo/tree/render/service/peers.js.map +1 -0
  730. package/dist/core/repo/tree/render/service/view-id.js +67 -0
  731. package/dist/core/repo/tree/render/service/view-id.js.map +1 -0
  732. package/dist/core/repo/tree/render/service/views.js +78 -0
  733. package/dist/core/repo/tree/render/service/views.js.map +1 -0
  734. package/dist/core/repo/tree/render/stale.js +42 -0
  735. package/dist/core/repo/tree/render/stale.js.map +1 -0
  736. package/dist/core/repo/tree/render/text.js +84 -0
  737. package/dist/core/repo/tree/render/text.js.map +1 -0
  738. package/dist/core/repo/tree/render/views.js +293 -0
  739. package/dist/core/repo/tree/render/views.js.map +1 -0
  740. package/dist/core/repo/tree/walk.js +53 -32
  741. package/dist/core/repo/tree/walk.js.map +1 -1
  742. package/dist/core/results.js +47 -12
  743. package/dist/core/results.js.map +1 -1
  744. package/dist/core/scaffold/landscape.js +121 -13
  745. package/dist/core/scaffold/landscape.js.map +1 -1
  746. package/dist/core/scaffold/legacy.js +271 -0
  747. package/dist/core/scaffold/legacy.js.map +1 -0
  748. package/dist/core/staging/commit.js +26 -15
  749. package/dist/core/staging/commit.js.map +1 -1
  750. package/dist/core/staging/lock.js +74 -12
  751. package/dist/core/staging/lock.js.map +1 -1
  752. package/dist/core/staging/recovery/intent.js +2 -5
  753. package/dist/core/staging/recovery/intent.js.map +1 -1
  754. package/dist/core/staging/recovery/recover.js +84 -6
  755. package/dist/core/staging/recovery/recover.js.map +1 -1
  756. package/dist/core/staging/snapshot/manifest.js +188 -0
  757. package/dist/core/staging/snapshot/manifest.js.map +1 -0
  758. package/dist/core/staging/{snapshot.js → snapshot/snapshot.js} +39 -45
  759. package/dist/core/staging/snapshot/snapshot.js.map +1 -0
  760. package/dist/core/staging/txn/forward.js +24 -14
  761. package/dist/core/staging/txn/forward.js.map +1 -1
  762. package/dist/core/staging/writes.js.map +1 -1
  763. package/dist/core/status/actions/execution.js +11 -0
  764. package/dist/core/status/actions/execution.js.map +1 -1
  765. package/dist/core/status/contracts.js +39 -15
  766. package/dist/core/status/contracts.js.map +1 -1
  767. package/dist/core/status/feature/artifacts.js +33 -8
  768. package/dist/core/status/feature/artifacts.js.map +1 -1
  769. package/dist/core/status/feature/feature.js +24 -17
  770. package/dist/core/status/feature/feature.js.map +1 -1
  771. package/dist/core/status/feature/next.js +20 -7
  772. package/dist/core/status/feature/next.js.map +1 -1
  773. package/dist/core/status/feature/words.js +96 -0
  774. package/dist/core/status/feature/words.js.map +1 -0
  775. package/dist/core/status/fleet/fleet.js +43 -14
  776. package/dist/core/status/fleet/fleet.js.map +1 -1
  777. package/dist/core/status/fleet/next.js +153 -58
  778. package/dist/core/status/fleet/next.js.map +1 -1
  779. package/dist/core/status/report.js.map +1 -1
  780. package/dist/core/status/scan.js.map +1 -1
  781. package/dist/core/status/verification.js +30 -15
  782. package/dist/core/status/verification.js.map +1 -1
  783. package/dist/core/tasks/packet.js +199 -0
  784. package/dist/core/tasks/packet.js.map +1 -0
  785. package/dist/core/tasks/record.js +43 -0
  786. package/dist/core/tasks/record.js.map +1 -0
  787. package/dist/core/tasks/sources.js +181 -0
  788. package/dist/core/tasks/sources.js.map +1 -0
  789. package/dist/core/tasks/stamps.js +76 -0
  790. package/dist/core/tasks/stamps.js.map +1 -0
  791. package/dist/core/tasks/unit.js +0 -0
  792. package/dist/core/tasks/unit.js.map +1 -0
  793. package/dist/core/usecases/capability.js +11 -14
  794. package/dist/core/usecases/capability.js.map +1 -1
  795. package/dist/core/usecases/delta/claims.js +31 -7
  796. package/dist/core/usecases/delta/claims.js.map +1 -1
  797. package/dist/core/usecases/delta/flows.js +5 -7
  798. package/dist/core/usecases/delta/flows.js.map +1 -1
  799. package/dist/core/usecases/delta/modified.js +315 -0
  800. package/dist/core/usecases/delta/modified.js.map +1 -0
  801. package/dist/core/usecases/delta/overlay.js +32 -191
  802. package/dist/core/usecases/delta/overlay.js.map +1 -1
  803. package/dist/core/usecases/fleet.js +195 -36
  804. package/dist/core/usecases/fleet.js.map +1 -1
  805. package/dist/{commands/validate/fleet/usecases → core/usecases/grade}/capability-tag.js +8 -9
  806. package/dist/core/usecases/grade/capability-tag.js.map +1 -0
  807. package/dist/core/usecases/grade/feature.js +88 -0
  808. package/dist/core/usecases/grade/feature.js.map +1 -0
  809. package/dist/{commands/validate/fleet/usecases → core/usecases/grade}/requirement-tag.js +3 -4
  810. package/dist/core/usecases/grade/requirement-tag.js.map +1 -0
  811. package/dist/{commands/validate/fleet/usecases → core/usecases/grade}/steps.js +102 -33
  812. package/dist/core/usecases/grade/steps.js.map +1 -0
  813. package/dist/{commands/validate/fleet/usecases → core/usecases/grade}/usecases.js +23 -10
  814. package/dist/core/usecases/grade/usecases.js.map +1 -0
  815. package/dist/core/usecases/operations.js +26 -14
  816. package/dist/core/usecases/operations.js.map +1 -1
  817. package/dist/core/usecases/place.js.map +1 -1
  818. package/dist/core/usecases/service/exclude.js +119 -0
  819. package/dist/core/usecases/service/exclude.js.map +1 -0
  820. package/dist/core/usecases/service/flows.js +164 -0
  821. package/dist/core/usecases/service/flows.js.map +1 -0
  822. package/dist/core/usecases/suites/participants.js +83 -0
  823. package/dist/core/usecases/suites/participants.js.map +1 -0
  824. package/dist/core/usecases/suites/suites.js +45 -0
  825. package/dist/core/usecases/suites/suites.js.map +1 -0
  826. package/dist/core/verify/answers.js +12 -5
  827. package/dist/core/verify/answers.js.map +1 -1
  828. package/dist/core/verify/build.js +102 -82
  829. package/dist/core/verify/build.js.map +1 -1
  830. package/dist/core/verify/checklist.js +70 -12
  831. package/dist/core/verify/checklist.js.map +1 -1
  832. package/dist/core/verify/location.js +67 -0
  833. package/dist/core/verify/location.js.map +1 -0
  834. package/dist/core/verify/pins/lint.js +3 -2
  835. package/dist/core/verify/pins/lint.js.map +1 -1
  836. package/dist/core/verify/pins/pin.js +1 -1
  837. package/dist/core/verify/pins/pin.js.map +1 -1
  838. package/dist/core/verify/read/file.js +224 -0
  839. package/dist/core/verify/read/file.js.map +1 -0
  840. package/dist/core/verify/{file.js → read/shape.js} +16 -104
  841. package/dist/core/verify/read/shape.js.map +1 -0
  842. package/dist/core/verify/read/union.js +105 -0
  843. package/dist/core/verify/read/union.js.map +1 -0
  844. package/dist/core/verify/record.js +35 -12
  845. package/dist/core/verify/record.js.map +1 -1
  846. package/dist/core/verify/store/commit.js +40 -30
  847. package/dist/core/verify/store/commit.js.map +1 -1
  848. package/dist/core/verify/store/render.js +8 -4
  849. package/dist/core/verify/store/render.js.map +1 -1
  850. package/dist/core/vocabulary/issue.js +4 -0
  851. package/dist/core/vocabulary/issue.js.map +1 -1
  852. package/dist/core/vocabulary/maturity.js +75 -4
  853. package/dist/core/vocabulary/maturity.js.map +1 -1
  854. package/dist/core/vocabulary/report.js +16 -1
  855. package/dist/core/vocabulary/report.js.map +1 -1
  856. package/examples/README.md +54 -11
  857. package/examples/docs/architecture/landscape.likec4 +62 -6
  858. package/examples/docs/architecture/services.likec4 +70 -0
  859. package/examples/docs/architecture/subsystems.likec4 +7 -0
  860. package/examples/docs/architecture/usecases/order-notification.likec4 +16 -7
  861. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-service/asyncapi.yaml +11 -8
  862. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/openapi.yaml +6 -6
  863. package/examples/docs/features/FEAT-112-retire-order-v1/specs/order-service/openapi.yaml +4 -1
  864. package/examples/docs/features/archive/FEAT-088-refunds/specs/payment-service/openapi.yaml +13 -10
  865. package/examples/docs/likec4.config.json +0 -1
  866. package/examples/docs/services/checkout-web/model.likec4 +39 -56
  867. package/examples/docs/services/order-service/arch.spec.md +13 -6
  868. package/examples/docs/services/order-service/asyncapi.yaml +3 -2
  869. package/examples/docs/services/order-service/model.likec4 +58 -70
  870. package/examples/docs/services/payment-service/arch.spec.md +7 -4
  871. package/examples/docs/services/payment-service/model.likec4 +38 -37
  872. package/examples/docs/services/platform/identity-service/arch.spec.md +7 -4
  873. package/examples/docs/services/platform/identity-service/model.likec4 +35 -37
  874. package/examples/docs/services/platform/notification-service/asyncapi.yaml +2 -1
  875. package/examples/docs/services/platform/notification-service/health.yaml +8 -3
  876. package/examples/docs/services/platform/notification-service/model.likec4 +43 -64
  877. package/package.json +1 -1
  878. package/dist/commands/validate/checks/vocabulary.js +0 -31
  879. package/dist/commands/validate/checks/vocabulary.js.map +0 -1
  880. package/dist/commands/validate/fleet/usecases/capability-tag.js.map +0 -1
  881. package/dist/commands/validate/fleet/usecases/requirement-tag.js.map +0 -1
  882. package/dist/commands/validate/fleet/usecases/steps.js.map +0 -1
  883. package/dist/commands/validate/fleet/usecases/usecases.js.map +0 -1
  884. package/dist/core/agent/agents-md/artifacts.js +0 -220
  885. package/dist/core/agent/agents-md/artifacts.js.map +0 -1
  886. package/dist/core/agent/agents-md/cycle.js +0 -165
  887. package/dist/core/agent/agents-md/cycle.js.map +0 -1
  888. package/dist/core/agent/agents-md/shipped/archive-gate.js +0 -98
  889. package/dist/core/agent/agents-md/shipped/archive-gate.js.map +0 -1
  890. package/dist/core/agent/agents-md/spine.js +0 -40
  891. package/dist/core/agent/agents-md/spine.js.map +0 -1
  892. package/dist/core/coherence/events/merged.js +0 -40
  893. package/dist/core/coherence/events/merged.js.map +0 -1
  894. package/dist/core/diff/current-state.js +0 -96
  895. package/dist/core/diff/current-state.js.map +0 -1
  896. package/dist/core/diff/victims.js +0 -247
  897. package/dist/core/diff/victims.js.map +0 -1
  898. package/dist/core/repo/tree/views.js +0 -172
  899. package/dist/core/repo/tree/views.js.map +0 -1
  900. package/dist/core/staging/snapshot.js.map +0 -1
  901. package/dist/core/verify/file.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"next.js","sourceRoot":"","sources":["../../../../src/core/status/feature/next.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `next[]` — one feature.\n *\n * The payload's reason to exist. Each entry carries a stable `code` to branch\n * on, one sentence a person can read, and the literal command to run — ordered,\n * first entry first. `command` is the loam invocation that carries the step\n * forward: the one that does the work where loam does it (`rebase`, `archive`),\n * and the one that states or grades the work where the author does it (`delta`,\n * `validate`, `verify`). It is never a command that would write the artifact\n * behind the author's back — loam does not author.\n *\n * `next` is never empty. A feature with nothing outstanding still has a next\n * step (ship it), and a repository with nothing outstanding still has one (keep\n * the fleet green) — an empty array would be indistinguishable from a bug in\n * the caller's own parsing.\n */\nimport type { Finding } from \"../../vocabulary/report.js\";\nimport { recoverStep } from \"../interrupted.js\";\nimport type { ArtifactId, ArtifactState, NextStep } from \"../report.js\";\nimport { testStep, verifyStep } from \"../verification.js\";\nimport { type FeatureState } from \"./state.js\";\n\n/**\n * Would either gate refuse this? Severity answers `validate`'s question and\n * `gates` answers archive's; a finding that fails EITHER is one an author has\n * work to do about, and collapsing them to `severity === \"error\"` is how\n * `status` came to print \"ship it\" beside a warning archive exits 1 on.\n */\nexport function unshippable(f: Finding): boolean {\n return f.severity === \"error\" || f.gates === true;\n}\n\n/** Codes whose one fix is `loam rebase`: a pin nobody ever wrote, on any of the three axes. */\nconst UNPINNED = new Set([\"delta.baseline-missing\", \"openapi.baseline-missing\", \"asyncapi.baseline-missing\"]);\n\nexport function featureNext(state: FeatureState, boundService: string | undefined): NextStep[] {\n const { feature, services, artifacts, findings, blockedBy, verification, scans, interrupted } = state;\n const id = feature.id;\n // Before the archived shortcut: the interrupted commit may be this feature's\n // own, and \"it shipped\" is not a thing to tell somebody whose living docs are\n // half-written.\n const first = interrupted === null ? [] : [recoverStep(interrupted)];\n if (feature.archived) {\n return [\n ...first,\n {\n code: \"next.archived\",\n statement: `${id} is archived — it shipped, and its delta is already folded into the living docs.`,\n command: `loam show ${id} --json`,\n },\n ];\n }\n\n const steps: NextStep[] = [...first];\n const owed = (kind: ArtifactId, service?: string): ArtifactState | undefined =>\n artifacts.find(\n (a) => a.id === kind && a.status === \"missing\" && (service === undefined || a.service === service),\n );\n\n const intent = owed(\"intent\");\n if (intent !== undefined) {\n steps.push({\n code: \"next.author-intent\",\n statement: `Write ${intent.path} — what ${id} is for, in prose, before anything is derived from it.`,\n command: `loam validate ${id} --json`,\n artifact: \"intent\",\n path: intent.path,\n });\n }\n\n if (services.length === 0) {\n steps.push({\n code: \"next.touch-service\",\n statement: `${id} carries no per-service delta — add specs/<service>/spec.md for every service it changes.`,\n command: \"loam list services --json\",\n });\n }\n\n for (const svc of services) {\n const spec = owed(\"spec\", svc);\n if (spec !== undefined) {\n steps.push({\n code: \"next.author-spec\",\n statement: `Write ${spec.path} — the ADDED/MODIFIED/REMOVED requirements ${id} makes to ${svc}, each with a scenario.`,\n command: `loam delta ${id} --service ${svc} --json`,\n artifact: \"spec\",\n service: svc,\n path: spec.path,\n });\n }\n const api = owed(\"openapi\", svc);\n if (api !== undefined) {\n steps.push({\n code: \"next.author-openapi\",\n // Not \"the service is not in the living docs\": a service adopted\n // without a contract is the commoner case, and that wording sent a\n // reader looking for a directory that was right there. And not \"the\n // operations it governs\" either — this step also fires for a service\n // the feature INTRODUCES, where owesContract asks nothing about\n // operations and the delta may tag none, so naming them promised the\n // author a list they would go looking for and not find.\n statement: `Write ${api.path} — nothing gives ${svc} a living openapi.yaml, so this feature is the only thing that can write down its API surface.`,\n command: `loam delta ${id} --service ${svc} --json`,\n artifact: \"openapi\",\n service: svc,\n path: api.path,\n });\n }\n }\n\n // A requirement with no scenario yields no generated .feature and no\n // scenario.tested claim: a promise that reaches neither the suite nor the\n // done-check, and that nothing downstream will ever mention again. One entry\n // per service rather than per requirement — a delta with forty bare\n // requirements would otherwise BE the payload (validate caps its details for\n // the same reason).\n for (const gap of scans) {\n if (gap.bare.length === 0 || !services.includes(gap.service)) continue;\n steps.push({\n code: \"next.author-scenarios\",\n statement:\n `${gap.bare.length} requirement(s) in ${gap.service}'s delta have no '#### Scenario:' ` +\n `(starting with '${gap.bare[0]!.name}') — they generate no test and no verify claim.`,\n command: `loam delta ${id} --service ${gap.service} --json`,\n artifact: \"spec\",\n service: gap.service,\n path: gap.path,\n });\n }\n\n if (findings.some((f) => UNPINNED.has(f.code))) {\n steps.push({\n code: \"next.rebase\",\n statement: `${id} carries requirements or operations with no baseline pin — until they have one the merge cannot tell what it EDITS from what it merely quotes.`,\n command: `loam rebase ${id}`,\n });\n }\n\n if (blockedBy.length > 0) {\n steps.push({\n code: \"next.archive-first\",\n statement: `${id} builds on ${blockedBy.join(\", \")}, which ${blockedBy.length === 1 ? \"has\" : \"have\"} to archive first.`,\n command: `loam dependencies ${id} --json`,\n });\n }\n\n // Everything either gate refuses on, not just the errors: a warning marked\n // `gates: true` stops archive exactly as hard, and leaving it out of the\n // steps was the other half of leaving it out of the stage.\n const blocking = findings.filter(unshippable);\n if (blocking.length > 0) {\n const gating = blocking.filter((f) => f.gates === true && f.severity !== \"error\").length;\n steps.push({\n code: \"next.fix-coherence\",\n statement:\n `${id} has ${blocking.length} finding(s) that stop it, starting with ${blocking[0]!.code}` +\n (gating > 0\n ? ` — ${gating} of them ${gating === 1 ? \"is a warning that GATES\" : \"are warnings that GATE\"} archive, ` +\n \"which `validate` grades valid, so its exit code alone will not show you why archive refuses.\"\n : \" — the axes disagree, and archive refuses.\"),\n command: `loam validate ${id} --json`,\n });\n }\n\n // The implementation half of the forward flow, which next[] never named at\n // all: an agent read \"author the spec\" and then \"record the verification\",\n // with nothing in between saying where a test comes from — so the only way\n // left to answer a scenario claim was its own word, through `--record`.\n steps.push(...testStep(id, verification, { services, scans, boundService }));\n steps.push(...verifyStep(id, verification, { artifacts, services, boundService }));\n\n // Always last, and always present: a feature whose every artifact holds and\n // whose record is complete still has one thing left to do, and an empty\n // `next[]` would leave a caller unable to tell \"finished\" from \"this command\n // had nothing to say\".\n steps.push({\n code: \"next.archive\",\n statement:\n steps.length === 0\n ? `${id} is authored, coherent and verified — ship it.`\n : `${id} ships once everything above is done; the dry run writes nothing and lists every file the merge would touch.`,\n command: `loam archive ${id} --dry-run --json`,\n });\n return steps;\n}\n"]}
1
+ {"version":3,"file":"next.js","sourceRoot":"","sources":["../../../../src/core/status/feature/next.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `next[]` — one feature.\n *\n * The payload's reason to exist. Each entry carries a stable `code` to branch\n * on, one sentence a person can read, and the literal command to run — ordered,\n * first entry first. `command` is the loam invocation that carries the step\n * forward: the one that does the work where loam does it (`rebase`, `archive`),\n * and the one that states or grades the work where the author does it (`delta`,\n * `validate`, `verify`). It is never a command that would write the artifact\n * behind the author's back — loam does not author.\n *\n * `next` is never empty. A feature with nothing outstanding still has a next\n * step (archive it), and a repository with nothing outstanding still has one (keep\n * the fleet green) — an empty array would be indistinguishable from a bug in\n * the caller's own parsing.\n */\nimport type { Finding } from \"../../vocabulary/report.js\";\nimport { recoverStep } from \"../interrupted.js\";\nimport type { ArtifactId, ArtifactState, NextStep } from \"../report.js\";\nimport { testStep, verifyStep } from \"../verification.js\";\nimport { type FeatureState } from \"./state.js\";\nimport { archivedVerification } from \"./words.js\";\n\n/**\n * Would either gate refuse this? Severity answers `validate`'s question and\n * `gates` answers archive's; a finding that fails EITHER is one an author has\n * work to do about, and collapsing them to `severity === \"error\"` is how\n * `status` came to print \"ship it\" beside a warning archive exits 1 on.\n */\nexport function unshippable(f: Finding): boolean {\n return f.severity === \"error\" || f.gates === true;\n}\n\n/** Codes whose one fix is `loam rebase`: a pin nobody ever wrote, on any of the three axes. */\nconst UNPINNED = new Set([\"delta.baseline-missing\", \"openapi.baseline-missing\", \"asyncapi.baseline-missing\"]);\n\nexport function featureNext(state: FeatureState, boundService: string | undefined): NextStep[] {\n const { feature, services, artifacts, findings, blockedBy, verification, scans, interrupted } = state;\n const id = feature.id;\n // Before the archived shortcut: the interrupted commit may be this feature's\n // own, and \"it shipped\" is not a thing to tell somebody whose living docs are\n // half-written.\n const first = interrupted === null ? [] : [recoverStep(interrupted)];\n if (feature.archived) {\n return [\n ...first,\n {\n code: \"next.archived\",\n // Not \"it shipped\": archive folds documents and checks no code and no\n // evidence, so the sentence says what archiving did and then, in the\n // done-check's own words, whether anybody verified it.\n statement:\n `${id} is archived — its deltas are folded into the living docs. Archiving checks documents, not code: ` +\n `${id} is ${archivedVerification(verification)}.`,\n command: `loam show ${id} --json`,\n },\n ];\n }\n\n const steps: NextStep[] = [...first];\n const owed = (kind: ArtifactId, service?: string): ArtifactState | undefined =>\n artifacts.find(\n (a) => a.id === kind && a.status === \"missing\" && (service === undefined || a.service === service),\n );\n\n const intent = owed(\"intent\");\n if (intent !== undefined) {\n steps.push({\n code: \"next.author-intent\",\n statement: `Write ${intent.path} — what ${id} is for, in prose, before anything is derived from it.`,\n command: `loam validate ${id} --json`,\n artifact: \"intent\",\n path: intent.path,\n });\n }\n\n if (services.length === 0) {\n steps.push({\n code: \"next.touch-service\",\n statement: `${id} carries no per-service delta — add specs/<service>/spec.md for every service it changes.`,\n command: \"loam list services --json\",\n });\n }\n\n for (const svc of services) {\n const spec = owed(\"spec\", svc);\n if (spec !== undefined) {\n steps.push({\n code: \"next.author-spec\",\n statement: `Write ${spec.path} — the ADDED/MODIFIED/REMOVED requirements ${id} makes to ${svc}, each with a scenario.`,\n command: `loam delta ${id} --service ${svc} --json`,\n artifact: \"spec\",\n service: svc,\n path: spec.path,\n });\n }\n const api = owed(\"openapi\", svc);\n if (api !== undefined) {\n steps.push({\n code: \"next.author-openapi\",\n // Not \"the service is not in the living docs\": a service adopted\n // without a contract is the commoner case, and that wording sent a\n // reader looking for a directory that was right there. And not \"the\n // operations it governs\" either — what owes the file may be an edge\n // the delta draws INTO the service rather than any `Operations:` line\n // (owesContract), so naming governed operations promised the author a\n // list they would go looking for and not find.\n statement: `Write ${api.path} — nothing gives ${svc} a living openapi.yaml, so this feature is the only thing that can write down its API surface.`,\n command: `loam delta ${id} --service ${svc} --json`,\n artifact: \"openapi\",\n service: svc,\n path: api.path,\n });\n }\n }\n\n // A requirement with no scenario yields no generated .feature and no\n // scenario.tested claim: a promise that reaches neither the suite nor the\n // done-check, and that nothing downstream will ever mention again. One entry\n // per service rather than per requirement — a delta with forty bare\n // requirements would otherwise BE the payload (validate caps its details for\n // the same reason).\n for (const gap of scans) {\n if (gap.bare.length === 0 || !services.includes(gap.service)) continue;\n steps.push({\n code: \"next.author-scenarios\",\n statement:\n `${gap.bare.length} requirement(s) in ${gap.service}'s delta have no '#### Scenario:' ` +\n `(starting with '${gap.bare[0]!.name}') — they generate no test and no verify claim.`,\n command: `loam delta ${id} --service ${gap.service} --json`,\n artifact: \"spec\",\n service: gap.service,\n path: gap.path,\n });\n }\n\n if (findings.some((f) => UNPINNED.has(f.code))) {\n steps.push({\n code: \"next.rebase\",\n statement: `${id} carries requirements or operations with no baseline pin — until they have one the merge cannot tell what it EDITS from what it merely quotes.`,\n command: `loam rebase ${id}`,\n });\n }\n\n if (blockedBy.length > 0) {\n steps.push({\n code: \"next.archive-first\",\n statement: `${id} builds on ${blockedBy.join(\", \")}, which ${blockedBy.length === 1 ? \"has\" : \"have\"} to archive first.`,\n command: `loam dependencies ${id} --json`,\n });\n }\n\n // Everything either gate refuses on, not just the errors: a warning marked\n // `gates: true` stops archive exactly as hard, and leaving it out of the\n // steps was the other half of leaving it out of the stage.\n const blocking = findings.filter(unshippable);\n if (blocking.length > 0) {\n const gating = blocking.filter((f) => f.gates === true && f.severity !== \"error\").length;\n steps.push({\n code: \"next.fix-coherence\",\n statement:\n `${id} has ${blocking.length} finding(s) that stop it, starting with ${blocking[0]!.code}` +\n (gating > 0\n ? ` — ${gating} of them ${gating === 1 ? \"is a warning that GATES\" : \"are warnings that GATE\"} archive, ` +\n \"which `validate` grades valid, so its exit code alone will not show you why archive refuses.\"\n : \" — the axes disagree, and archive refuses.\"),\n command: `loam validate ${id} --json`,\n });\n }\n\n // The implementation half of the forward flow, which next[] never named at\n // all: an agent read \"author the spec\" and then \"record the verification\",\n // with nothing in between saying where a test comes from — so the only way\n // left to answer a scenario claim was its own word, through `--record`.\n steps.push(...testStep(id, verification, { services, scans, boundService }));\n steps.push(...verifyStep(id, verification, { artifacts, services, boundService }));\n\n // Always last, and always present: a feature whose every artifact holds and\n // whose record is complete still has one thing left to do, and an empty\n // `next[]` would leave a caller unable to tell \"finished\" from \"this command\n // had nothing to say\".\n //\n // The sentence used to say the feature \"ships once everything above is\n // done\", which promised a check archive never makes: it refuses on the\n // documents (coherence, the gating warnings) and looks at neither the code\n // nor the verification record. So it says what archive does, and what it\n // does not, in the order a reader decides in.\n steps.push({\n code: \"next.archive\",\n statement:\n steps.length === 0\n ? `${id} is authored, coherent and verified — archive it to fold its deltas into the living docs.`\n : `Archive ${id} once the steps above are done. Archive merges its deltas into the living docs and checks only ` +\n \"the documents — not the code, not the verification record — so it will not stop you archiving work nobody \" +\n \"built. The dry run writes nothing and lists every file the merge would touch.\",\n command: `loam archive ${id} --dry-run --json`,\n });\n return steps;\n}\n"]}
@@ -0,0 +1,96 @@
1
+ /** `docs ready — nothing verified yet (0 of 19 claims answered)` and its siblings. */
2
+ export function stageWords(f) {
3
+ // Ahead of `archived`, and ahead of `blockedBy`: an interrupted commit blocks
4
+ // even a feature that archived (the files that say so may be half-written),
5
+ // and a feature also waiting on another one cannot move until the repair
6
+ // either — that one cannot archive past the journal any more than this can.
7
+ if (f.stage === "blocked" && f.interrupted) {
8
+ return "blocked — an interrupted archive or unarchive has to be recovered first";
9
+ }
10
+ if (f.archived)
11
+ return `archived — ${archivedVerification(f.verification)}`;
12
+ switch (f.stage) {
13
+ case "blocked":
14
+ return `blocked — waiting on ${f.blockedBy.join(", ")} to archive first`;
15
+ case "missing":
16
+ return `being written — ${missingWords(f)}`;
17
+ case "draft":
18
+ return `the docs need fixing — ${f.blocking ?? "some"} finding(s) stop it`;
19
+ case "ready":
20
+ return `docs ready — ${openVerification(f.verification, f.asked)}`;
21
+ case "done":
22
+ // The fleet form grades nothing, so it cannot say archive will take it —
23
+ // only that the record is verified. The feature's own status can.
24
+ return f.blocking === null
25
+ ? "verified — every claim confirmed by evidence; its own status says whether archive will take it"
26
+ : "verified — every claim confirmed by evidence; ready to archive";
27
+ }
28
+ }
29
+ /** `FEAT-101 (Payment splitting)` — the id a machine keys on, and the words a person recognises. */
30
+ export function featureLabel(f) {
31
+ return f.title === null ? f.id : `${f.id} (${f.title})`;
32
+ }
33
+ /** The fleet form's facts: presence and an existing record only, graded nothing. */
34
+ export function fleetStageWords(f, interrupted) {
35
+ return stageWords({
36
+ stage: f.stage,
37
+ archived: false,
38
+ verification: f.verification,
39
+ asked: null,
40
+ missing: f.missing,
41
+ narrowed: false,
42
+ services: f.services.length,
43
+ blockedBy: f.blockedBy,
44
+ interrupted,
45
+ blocking: null,
46
+ });
47
+ }
48
+ /** What is not written yet — the whole feature's list, or as much of it as a `--service` view can see. */
49
+ function missingWords(f) {
50
+ const owed = f.missing.length > 0 ? `not written yet: ${f.missing.join(", ")}` : "";
51
+ if (f.services === 0)
52
+ return owed === "" ? "no service delta yet" : `no service delta yet; ${owed}`;
53
+ // Only a narrowed view can reach a `missing` stage with nothing missing in it:
54
+ // the stage is the whole feature's, the rows are the lens's.
55
+ if (owed === "")
56
+ return "another service's artifacts are not written yet (drop --service to see which)";
57
+ return f.narrowed ? `${owed} (in this --service view; drop --service for the whole feature)` : owed;
58
+ }
59
+ /** Where an in-flight feature's verification stands, counted. */
60
+ function openVerification(v, asked) {
61
+ if (v.state === "absent") {
62
+ return asked === null
63
+ ? "nothing verified yet (no verification record)"
64
+ : `nothing verified yet (0 of ${asked} claim(s) answered)`;
65
+ }
66
+ if (v.state === "unreadable")
67
+ return "its verification record does not read";
68
+ if (v.state === "stale")
69
+ return "its verification record is stale — it answers an older checklist than the one asked now";
70
+ const open = v.unconfirmed + v.unanswered;
71
+ if (v.verdict === "attested") {
72
+ return `every claim answered, but ${v.attested} scenario(s) rest on an agent's word, not a test run (attested)`;
73
+ }
74
+ if (v.claims === 0)
75
+ return "its verification record answers no claims";
76
+ return `${v.confirmed} of ${v.claims} claim(s) confirmed${open > 0 ? `, ${open} open` : ""}`;
77
+ }
78
+ /**
79
+ * An archived feature's verification, said plainly. Archive merges documents
80
+ * and checks no code and no evidence, so this sentence — not the word
81
+ * `archived`, and not the stage `done` — is what says whether anybody verified
82
+ * the thing that shipped.
83
+ */
84
+ export function archivedVerification(v) {
85
+ if (v.state === "absent")
86
+ return "never verified (no verification record)";
87
+ if (v.state === "unreadable")
88
+ return "its verification record does not read";
89
+ if (v.verdict === "verified")
90
+ return `verified (${v.confirmed} of ${v.claims} claim(s) confirmed)`;
91
+ if (v.verdict === "attested") {
92
+ return `attested, not verified: ${v.attested} scenario(s) rest on an agent's word (${v.confirmed} of ${v.claims} claim(s) confirmed)`;
93
+ }
94
+ return `not fully verified (${v.confirmed} of ${v.claims} claim(s) confirmed)`;
95
+ }
96
+ //# sourceMappingURL=words.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"words.js","sourceRoot":"","sources":["../../../../src/core/status/feature/words.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The stage, said in words a person can act on.\n *\n * `stage` is a closed vocabulary an agent branches on (../report.ts), and it is\n * frozen: renaming `ready` would break every script that reads it. What was\n * wrong was printing it BARE. `ready` means the documents are written and pass\n * the shared checks — nothing about code — and `loam status FEAT-1 — ready`\n * over a feature nobody had built or verified read as \"ready to ship\". `done\n * (archived)` over a feature that was never verified read as \"shipped and\n * checked\", when archive checks documents and nothing else.\n *\n * So the machine value stays exactly what it was, and every human surface\n * (the status header and rows, the `next[]` statements that quote a stage)\n * says it through this one module, with the counts that make it true: how\n * many claims were answered of how many asked. One module, because a second\n * spelling of \"what does ready mean\" is the drift that made the first one\n * misleading.\n */\nimport type { ArtifactStatus, FleetFeatureState, VerificationState } from \"../report.js\";\n\n/**\n * What a stage sentence needs to be honest — every field a fact somebody\n * measured, never one inferred from another field being empty. The sentence\n * used to guess \"interrupted commit\" from an empty `blockedBy` and \"no service\n * delta\" from an empty `missing`, and both guesses were wrong in a state the\n * report could reach.\n */\nexport interface StageFacts {\n stage: ArtifactStatus;\n archived: boolean;\n verification: VerificationState;\n /** Claims the checklist asks now — the single-feature form derives it; null where nothing was derived. */\n asked: number | null;\n /** The owed artifacts not written yet (labels), for `missing`. */\n missing: string[];\n /** True when `missing` was read off a `--service` view rather than the whole feature. */\n narrowed: boolean;\n /** How many services the feature carries a delta for. */\n services: number;\n /** Features that must archive first, for `blocked`. */\n blockedBy: string[];\n /** A `.loam-commit` journal is present: some writer was killed mid-commit. */\n interrupted: boolean;\n /** Findings that stop the feature; null where nothing was graded (the fleet form). */\n blocking: number | null;\n}\n\n/** `docs ready — nothing verified yet (0 of 19 claims answered)` and its siblings. */\nexport function stageWords(f: StageFacts): string {\n // Ahead of `archived`, and ahead of `blockedBy`: an interrupted commit blocks\n // even a feature that archived (the files that say so may be half-written),\n // and a feature also waiting on another one cannot move until the repair\n // either — that one cannot archive past the journal any more than this can.\n if (f.stage === \"blocked\" && f.interrupted) {\n return \"blocked — an interrupted archive or unarchive has to be recovered first\";\n }\n if (f.archived) return `archived — ${archivedVerification(f.verification)}`;\n switch (f.stage) {\n case \"blocked\":\n return `blocked — waiting on ${f.blockedBy.join(\", \")} to archive first`;\n case \"missing\":\n return `being written — ${missingWords(f)}`;\n case \"draft\":\n return `the docs need fixing — ${f.blocking ?? \"some\"} finding(s) stop it`;\n case \"ready\":\n return `docs ready — ${openVerification(f.verification, f.asked)}`;\n case \"done\":\n // The fleet form grades nothing, so it cannot say archive will take it —\n // only that the record is verified. The feature's own status can.\n return f.blocking === null\n ? \"verified — every claim confirmed by evidence; its own status says whether archive will take it\"\n : \"verified — every claim confirmed by evidence; ready to archive\";\n }\n}\n\n/** `FEAT-101 (Payment splitting)` — the id a machine keys on, and the words a person recognises. */\nexport function featureLabel(f: { id: string; title: string | null }): string {\n return f.title === null ? f.id : `${f.id} (${f.title})`;\n}\n\n/** The fleet form's facts: presence and an existing record only, graded nothing. */\nexport function fleetStageWords(f: FleetFeatureState, interrupted: boolean): string {\n return stageWords({\n stage: f.stage,\n archived: false,\n verification: f.verification,\n asked: null,\n missing: f.missing,\n narrowed: false,\n services: f.services.length,\n blockedBy: f.blockedBy,\n interrupted,\n blocking: null,\n });\n}\n\n/** What is not written yet — the whole feature's list, or as much of it as a `--service` view can see. */\nfunction missingWords(f: StageFacts): string {\n const owed = f.missing.length > 0 ? `not written yet: ${f.missing.join(\", \")}` : \"\";\n if (f.services === 0) return owed === \"\" ? \"no service delta yet\" : `no service delta yet; ${owed}`;\n // Only a narrowed view can reach a `missing` stage with nothing missing in it:\n // the stage is the whole feature's, the rows are the lens's.\n if (owed === \"\") return \"another service's artifacts are not written yet (drop --service to see which)\";\n return f.narrowed ? `${owed} (in this --service view; drop --service for the whole feature)` : owed;\n}\n\n/** Where an in-flight feature's verification stands, counted. */\nfunction openVerification(v: VerificationState, asked: number | null): string {\n if (v.state === \"absent\") {\n return asked === null\n ? \"nothing verified yet (no verification record)\"\n : `nothing verified yet (0 of ${asked} claim(s) answered)`;\n }\n if (v.state === \"unreadable\") return \"its verification record does not read\";\n if (v.state === \"stale\") return \"its verification record is stale — it answers an older checklist than the one asked now\";\n const open = v.unconfirmed + v.unanswered;\n if (v.verdict === \"attested\") {\n return `every claim answered, but ${v.attested} scenario(s) rest on an agent's word, not a test run (attested)`;\n }\n if (v.claims === 0) return \"its verification record answers no claims\";\n return `${v.confirmed} of ${v.claims} claim(s) confirmed${open > 0 ? `, ${open} open` : \"\"}`;\n}\n\n/**\n * An archived feature's verification, said plainly. Archive merges documents\n * and checks no code and no evidence, so this sentence — not the word\n * `archived`, and not the stage `done` — is what says whether anybody verified\n * the thing that shipped.\n */\nexport function archivedVerification(v: VerificationState): string {\n if (v.state === \"absent\") return \"never verified (no verification record)\";\n if (v.state === \"unreadable\") return \"its verification record does not read\";\n if (v.verdict === \"verified\") return `verified (${v.confirmed} of ${v.claims} claim(s) confirmed)`;\n if (v.verdict === \"attested\") {\n return `attested, not verified: ${v.attested} scenario(s) rest on an agent's word (${v.confirmed} of ${v.claims} claim(s) confirmed)`;\n }\n return `not fully verified (${v.confirmed} of ${v.claims} claim(s) confirmed)`;\n}\n"]}
@@ -19,13 +19,14 @@ import { repoPath } from "../../envelope/json.js";
19
19
  import { FleetContext } from "../../fleet-context.js";
20
20
  import { compareIds } from "../../repo/entries.js";
21
21
  import { featurePaths, featureSpecPaths, landscapePath } from "../../repo/paths.js";
22
- import { listFeatures, listServices } from "../../repo/repo.js";
23
- import { contractOwners, contractsHeldElsewhere, owesContract } from "../contracts.js";
22
+ import { featureTitle, listFeatures, listServices } from "../../repo/repo.js";
23
+ import { introducingFeatures } from "../../projection/introduced.js";
24
+ import { contractEvidence, contractOwners, contractsHeldElsewhere, owesContract } from "../contracts.js";
24
25
  import { readInterruptedCommit } from "../interrupted.js";
25
26
  import { undocumented, vouched, } from "../report.js";
26
- import { governedServices, scanDeltas } from "../scan.js";
27
+ import { scanDeltas } from "../scan.js";
27
28
  import { fullyVerified, verificationState } from "../verification.js";
28
- import { fleetNext } from "./next.js";
29
+ import { fleetNext, groupServiceSteps, perServiceSteps } from "./next.js";
29
30
  /**
30
31
  * The fleet view: how much of `services/` anyone has written down, every
31
32
  * feature in flight with the stage it has reached, and the order they have to
@@ -33,8 +34,8 @@ import { fleetNext } from "./next.js";
33
34
  * are drawn from artifact presence and from a record that already exists, and
34
35
  * `next[]` hands off to `loam status <FEAT>` for everything else.
35
36
  */
36
- export async function fleetStatus(docsDir, opts = {}) {
37
- const context = opts.context ?? new FleetContext();
37
+ export async function fleetStatus(docsDir, opts) {
38
+ const { context } = opts;
38
39
  const interrupted = await readInterruptedCommit(docsDir);
39
40
  const narrowed = opts.service;
40
41
  const all = await listServices(docsDir, context);
@@ -48,7 +49,17 @@ export async function fleetStatus(docsDir, opts = {}) {
48
49
  // so the walk could see the repository it stands in only while that
49
50
  // repository was undocumented — and a developer in an adopted service repo
50
51
  // got the whole fleet's worklist with their own boundary buried in it.
51
- const binding = opts.bound === undefined ? null : { id: opts.bound, adopted: all.some((s) => s.id === opts.bound) };
52
+ //
53
+ // And the third fact: which feature in flight introduces it, when the fleet
54
+ // has no directory for it. Through the shared resolver, so `status` and
55
+ // `show`/`context`/`steps` agree on what "introduced" means.
56
+ const binding = opts.bound === undefined
57
+ ? null
58
+ : {
59
+ id: opts.bound,
60
+ adopted: all.some((s) => s.id === opts.bound),
61
+ introducedBy: (await introducingFeatures(docsDir, opts.bound, context)).map((f) => f.id),
62
+ };
52
63
  const graph = await analyzeDependencies(docsDir, undefined, context);
53
64
  const entries = await listFeatures(docsDir, {}, context);
54
65
  const inScope = narrowed === undefined ? entries : entries.filter((f) => f.services.some((s) => s === narrowed));
@@ -88,6 +99,10 @@ export async function fleetStatus(docsDir, opts = {}) {
88
99
  // headline, and "118 vouched" over a fleet where 90 of them were read
89
100
  // from a sample is the misreading the scope exists to prevent.
90
101
  sampledVouched: services.filter((s) => vouched(s) && s.vouchScope === "sampled").length,
102
+ // The other subset, for the same reason: "118 vouched" over a fleet where
103
+ // twenty documents were edited after the person read them is the
104
+ // trust headline lying by omission.
105
+ contentStale: services.filter((s) => vouched(s) && s.contentStale.length > 0).length,
91
106
  },
92
107
  features,
93
108
  order: graph.order.filter((id) => features.some((f) => f.id === id)),
@@ -102,6 +117,8 @@ export async function fleetStatus(docsDir, opts = {}) {
102
117
  // binding here costs the reader nothing and keeps `--service X` answering
103
118
  // only about X.
104
119
  next: fleetNext({ services, features, graph, interrupted, teaching }, narrowed === undefined ? binding : null),
120
+ // The same rungs `next[]` carries, from the same function, before the cap.
121
+ serviceSteps: groupServiceSteps(perServiceSteps(services, narrowed === undefined && binding?.adopted === true ? binding.id : null)),
105
122
  };
106
123
  }
107
124
  /**
@@ -136,18 +153,29 @@ async function fleetFeature(docsDir, feature, view) {
136
153
  missing.push("intent");
137
154
  if (feature.services.length === 0)
138
155
  missing.push("spec");
139
- // Requirement text, not a coherence run: `Operations:` lines are read off the
140
- // same cached parse `list` already pays for, and the contract question needs
141
- // them (owesContract). No LikeC4 workspace is spun here, which is the cost
142
- // this form actually refuses.
143
- const governs = governedServices(await scanDeltas(docsDir, feature, feature.services, context));
156
+ // Requirement text and the delta's op-linked edges, not a coherence run: the
157
+ // `Operations:` lines are read off the same cached parse `list` already pays
158
+ // for, and the delta off the parse the dependency graph above already made
159
+ // through this context — so the contract question (owesContract) spins no
160
+ // LikeC4 workspace of its own, which is the cost this form refuses.
161
+ const evidence = await contractEvidence(docsDir, feature, await scanDeltas(docsDir, feature, feature.services, context), context);
144
162
  for (const svc of feature.services) {
145
163
  const p = featureSpecPaths(feature.dir, svc);
146
- if (!existsSync(p.spec))
164
+ // EITHER corpus satisfies it. What a service delta owes is a requirement
165
+ // delta, and `arch.spec.md` is the other one — same grammar, same delta
166
+ // algebra, read by `featureChecklist` — so an architecture-only feature is
167
+ // complete and every gate already says so. This form asked for `spec.md`
168
+ // specifically, which broke the rule the comment two lines down states
169
+ // about the contract question: the two forms disagreed, `loam status`
170
+ // reporting `missing <svc>/spec` over a feature `loam status <FEAT>` and
171
+ // `loam validate --feature` both called complete. The name stays
172
+ // `<svc>/spec` when NEITHER exists, because the business delta is the one
173
+ // an author writes by default.
174
+ if (!existsSync(p.spec) && !existsSync(p.archSpec))
147
175
  missing.push(`${svc}/spec`);
148
176
  // The same question featureArtifacts asks, through the same function: the
149
177
  // two forms must never disagree about whether a feature owes a contract.
150
- if (owesContract(living.get(svc), contracted.has(svc), governs.has(svc)) && !existsSync(p.openapi)) {
178
+ if (owesContract(living.get(svc), contracted.has(svc), evidence(svc)) && !existsSync(p.openapi)) {
151
179
  missing.push(`${svc}/openapi`);
152
180
  }
153
181
  }
@@ -175,6 +203,7 @@ async function fleetFeature(docsDir, feature, view) {
175
203
  : "ready";
176
204
  return {
177
205
  id: feature.id,
206
+ title: await featureTitle(feature),
178
207
  dirName: feature.dirName,
179
208
  path: repoPath(docsDir, feature.dir),
180
209
  stage,
@@ -1 +1 @@
1
- {"version":3,"file":"fleet.js","sourceRoot":"","sources":["../../../../src/core/status/fleet/fleet.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AACzE,OAAO,EAAwB,MAAM,6BAA6B,CAAC;AACnE,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,UAAU,EAAwC,MAAM,uBAAuB,CAAC;AACzF,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpF,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,sBAAsB,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACvF,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,EACL,YAAY,EACZ,OAAO,GAKR,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACtE,OAAO,EAAE,SAAS,EAAgB,MAAM,WAAW,CAAC;AAGpD;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,OAAgB,EAChB,IAAI,GAAiE,EAAE;IAEvE,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,IAAI,YAAY,EAAE,CAAC;IACnD,MAAM,WAAW,GAAG,MAAM,qBAAqB,CAAC,OAAO,CAAC,CAAC;IACzD,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC;IAC9B,MAAM,GAAG,GAAG,MAAM,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACjD,MAAM,QAAQ,GAAG,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC;IACrF,6EAA6E;IAC7E,+EAA+E;IAC/E,0CAA0C;IAC1C,EAAE;IACF,6EAA6E;IAC7E,6EAA6E;IAC7E,oEAAoE;IACpE,2EAA2E;IAC3E,uEAAuE;IACvE,MAAM,OAAO,GACX,IAAI,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;IACtG,MAAM,KAAK,GAAG,MAAM,mBAAmB,CAAC,OAAO,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;IACrE,MAAM,OAAO,GAAG,MAAM,YAAY,CAAC,OAAO,EAAE,EAAE,EAAE,OAAO,CAAC,CAAC;IACzD,MAAM,OAAO,GAAG,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC;IACjH,2EAA2E;IAC3E,8EAA8E;IAC9E,6EAA6E;IAC7E,8EAA8E;IAC9E,yDAAyD;IACzD,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAEtD,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,GAAG,CAChC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAChB,YAAY,CAAC,OAAO,EAAE,CAAC,EAAE;QACvB,KAAK;QACL,UAAU,EAAE,sBAAsB,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC;QAChD,MAAM,EAAE,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;QAC1C,OAAO;QACP,WAAW;KACZ,CAAC,CACH,CACF,CAAC;IACF,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAEhD,2EAA2E;IAC3E,0EAA0E;IAC1E,wEAAwE;IACxE,wEAAwE;IACxE,gEAAgE;IAChE,yEAAyE;IACzE,MAAM,QAAQ,GACZ,QAAQ,KAAK,SAAS,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QACtE,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC,OAAO,CAAC,EAAE;QACjD,CAAC,CAAC,IAAI,CAAC;IAEX,OAAO;QACL,WAAW;QACX,QAAQ,EAAE;YACR,KAAK,EAAE,QAAQ,CAAC,MAAM;YACtB,YAAY,EAAE,QAAQ,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,MAAM;YAClD,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM;YACrE,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM;YACxC,mEAAmE;YACnE,sEAAsE;YACtE,gEAAgE;YAChE,sEAAsE;YACtE,+DAA+D;YAC/D,cAAc,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,MAAM;SACxF;QACD,QAAQ;QACR,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;QACpE,OAAO,EAAE,QAAQ,IAAI,IAAI;QACzB,4EAA4E;QAC5E,4EAA4E;QAC5E,0EAA0E;QAC1E,2EAA2E;QAC3E,4EAA4E;QAC5E,yEAAyE;QACzE,yEAAyE;QACzE,0EAA0E;QAC1E,gBAAgB;QAChB,IAAI,EAAE,SAAS,CACb,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,EACpD,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CACxC;KACF,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,KAAK,UAAU,iBAAiB,CAAC,OAAgB;IAC/C,MAAM,EAAE,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;IAClC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;QAAE,OAAO,SAAS,CAAC;IACtC,IAAI,CAAC;QACH,OAAO,eAAe,CAAC,MAAM,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC;IAC3E,CAAC;IAAC,MAAM,CAAC;QACP,0EAA0E;QAC1E,0EAA0E;QAC1E,2EAA2E;QAC3E,wEAAwE;QACxE,yEAAyE;QACzE,uEAAuE;QACvE,wEAAwE;QACxE,yEAAyE;QACzE,OAAO,UAAU,CAAC;IACpB,CAAC;AACH,CAAC;AAaD,KAAK,UAAU,YAAY,CACzB,OAAgB,EAChB,OAAqB,EACrB,IAAe;IAEf,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,IAAI,CAAC;IACjE,MAAM,KAAK,GAAG,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACxC,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,MAAM,CAAC;QAAE,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACtD,IAAI,OAAO,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACxD,8EAA8E;IAC9E,6EAA6E;IAC7E,2EAA2E;IAC3E,8BAA8B;IAC9B,MAAM,OAAO,GAAG,gBAAgB,CAAC,MAAM,UAAU,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;IAChG,KAAK,MAAM,GAAG,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;QACnC,MAAM,CAAC,GAAG,gBAAgB,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QAC7C,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC;YAAE,OAAO,CAAC,IAAI,CAAC,GAAG,GAAG,OAAO,CAAC,CAAC;QACrD,0EAA0E;QAC1E,yEAAyE;QACzE,IAAI,YAAY,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;YACnG,OAAO,CAAC,IAAI,CAAC,GAAG,GAAG,UAAU,CAAC,CAAC;QACjC,CAAC;IACH,CAAC;IACD,MAAM,YAAY,GAAG,CAAC,MAAM,iBAAiB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC;IACvE,MAAM,SAAS,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,OAAO,CAAC,EAAE,CAAC,EAAE,SAAS,IAAI,EAAE,CAAC;IAEhF,wEAAwE;IACxE,6EAA6E;IAC7E,mEAAmE;IACnE,EAAE;IACF,8EAA8E;IAC9E,4EAA4E;IAC5E,4EAA4E;IAC5E,2EAA2E;IAC3E,0EAA0E;IAC1E,0EAA0E;IAC1E,kEAAkE;IAClE,MAAM,KAAK,GACT,WAAW,KAAK,IAAI;QAClB,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC;YAClB,CAAC,CAAC,SAAS;YACX,CAAC,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC;gBACpB,CAAC,CAAC,SAAS;gBACX,CAAC,CAAC,aAAa,CAAC,YAAY,CAAC;oBAC3B,CAAC,CAAC,MAAM;oBACR,CAAC,CAAC,OAAO,CAAC;IAEpB,OAAO;QACL,EAAE,EAAE,OAAO,CAAC,EAAE;QACd,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,IAAI,EAAE,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC;QACpC,KAAK;QACL,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,SAAS;QACT,OAAO;QACP,YAAY;KACb,CAAC;AACJ,CAAC","sourcesContent":["/**\n * The whole repository — why the fleet form is cheaper than the feature form.\n *\n * `loam status` with no feature runs over every active feature, and deriving a\n * coherence report or a verification checklist per feature means spinning a\n * fresh LikeC4 workspace per feature. On a fleet-sized repository that is the\n * cost that gets a command switched off — `list` made the same call about its\n * verification column. So the fleet form grades nothing: it reports artifact\n * PRESENCE, the dependency order, and a verification record only where one\n * already exists, and its `next[]` hands off to `loam status <FEAT>`, which is\n * where the checks actually run.\n */\nimport { existsSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport { analyzeDependencies } from \"../../dependencies/dependencies.js\";\nimport { type DependencyGraph } from \"../../dependencies/facts.js\";\nimport { isLandscapeStub } from \"../../scaffold/landscape.js\";\nimport { repoPath } from \"../../envelope/json.js\";\nimport { FleetContext } from \"../../fleet-context.js\";\nimport { compareIds, type FeatureEntry, type ServiceEntry } from \"../../repo/entries.js\";\nimport { featurePaths, featureSpecPaths, landscapePath } from \"../../repo/paths.js\";\nimport { listFeatures, listServices } from \"../../repo/repo.js\";\nimport { contractOwners, contractsHeldElsewhere, owesContract } from \"../contracts.js\";\nimport { readInterruptedCommit } from \"../interrupted.js\";\nimport {\n undocumented,\n vouched,\n type ArtifactStatus,\n type FleetFeatureState,\n type FleetStatusReport,\n type InterruptedCommit,\n} from \"../report.js\";\nimport { governedServices, scanDeltas } from \"../scan.js\";\nimport { fullyVerified, verificationState } from \"../verification.js\";\nimport { fleetNext, type Binding } from \"./next.js\";\nimport type { DocsDir } from \"../../kernel/ids/dirs.js\";\n\n/**\n * The fleet view: how much of `services/` anyone has written down, every\n * feature in flight with the stage it has reached, and the order they have to\n * land in. Nothing here is graded — the module header says why — so the stages\n * are drawn from artifact presence and from a record that already exists, and\n * `next[]` hands off to `loam status <FEAT>` for everything else.\n */\nexport async function fleetStatus(\n docsDir: DocsDir,\n opts: { service?: string; bound?: string; context?: FleetContext } = {},\n): Promise<FleetStatusReport> {\n const context = opts.context ?? new FleetContext();\n const interrupted = await readInterruptedCommit(docsDir);\n const narrowed = opts.service;\n const all = await listServices(docsDir, context);\n const services = narrowed === undefined ? all : all.filter((s) => s.id === narrowed);\n // The service this repository says it IS, and whether the fleet has heard of\n // it. Asked against the UNNARROWED list, because \"is it adopted\" is a question\n // about the fleet and not about the view.\n //\n // Both facts travel, where only the unadopted case used to. This value was a\n // `string | null` that went null exactly when the service directory EXISTED,\n // so the walk could see the repository it stands in only while that\n // repository was undocumented — and a developer in an adopted service repo\n // got the whole fleet's worklist with their own boundary buried in it.\n const binding: Binding | null =\n opts.bound === undefined ? null : { id: opts.bound, adopted: all.some((s) => s.id === opts.bound) };\n const graph = await analyzeDependencies(docsDir, undefined, context);\n const entries = await listFeatures(docsDir, {}, context);\n const inScope = narrowed === undefined ? entries : entries.filter((f) => f.services.some((s) => s === narrowed));\n // Once for the fleet, not once per feature: which features hold a contract\n // for which service is one fact about the repository, and every feature below\n // reads its own row out of it. Built over the UNNARROWED list on purpose — a\n // `--service` view still has to know that a feature outside it discharges the\n // contract, or the narrowing would invent an obligation.\n const owners = await contractOwners(docsDir, context);\n\n const features = await Promise.all(\n inScope.map((f) =>\n fleetFeature(docsDir, f, {\n graph,\n contracted: contractsHeldElsewhere(owners, f.id),\n living: new Map(all.map((s) => [s.id, s])),\n context,\n interrupted,\n }),\n ),\n );\n features.sort((a, b) => compareIds(a.id, b.id));\n\n // The first-hour ladder's fact, computed exactly when the ladder can apply\n // — an unnarrowed run over a fleet with zero services and zero features —\n // so the read disappears from every repository that has anything in it.\n // Withheld on narrowed runs for the same reason the binding is withheld\n // below: `--service X` is an explicit question about X, and the\n // repository's onboarding ladder would be a different question's answer.\n const teaching =\n narrowed === undefined && services.length === 0 && features.length === 0\n ? { landscape: await landscapeTeaching(docsDir) }\n : null;\n\n return {\n interrupted,\n services: {\n total: services.length,\n undocumented: services.filter(undocumented).length,\n draft: services.filter((s) => !undocumented(s) && !vouched(s)).length,\n vouched: services.filter(vouched).length,\n // A subset of `vouched`, never a fourth bucket: those services ARE\n // vouched, and the three counts still sum to `total`. It rides beside\n // the count it qualifies because this line is the fleet's trust\n // headline, and \"118 vouched\" over a fleet where 90 of them were read\n // from a sample is the misreading the scope exists to prevent.\n sampledVouched: services.filter((s) => vouched(s) && s.vouchScope === \"sampled\").length,\n },\n features,\n order: graph.order.filter((id) => features.some((f) => f.id === id)),\n service: narrowed ?? null,\n // The binding is passed only when this run was NOT narrowed, and that guard\n // is unchanged now that the binding also decides ORDER. `--service X` is an\n // explicit question about X, and answering it with a step about whichever\n // service loam.json happens to name would be a different question's answer\n // at the top of the list — which is as true of a rung promoted to the front\n // as it was of `next.adopt-bound` emitted out of nowhere. A narrowed run\n // sees at most the one service it asked about anyway, so withholding the\n // binding here costs the reader nothing and keeps `--service X` answering\n // only about X.\n next: fleetNext(\n { services, features, graph, interrupted, teaching },\n narrowed === undefined ? binding : null,\n ),\n };\n}\n\n/**\n * Which first-hour state the fleet map is in: absent, still the scaffold's own\n * untouched bytes, or authored. One file read and a byte comparison — the\n * module header's cost rule stands, no LikeC4 workspace is spun here.\n */\nasync function landscapeTeaching(docsDir: DocsDir): Promise<\"missing\" | \"stub\" | \"authored\"> {\n const lp = landscapePath(docsDir);\n if (!existsSync(lp)) return \"missing\";\n try {\n return isLandscapeStub(await readFile(lp, \"utf8\")) ? \"stub\" : \"authored\";\n } catch {\n // Unreadable is not untouched. A map that cannot be read — a directory in\n // the file's place, a permission — must not be called the scaffold's stub\n // (\"missing\" and \"stub\" would each put a false statement in next[]), so it\n // reads as \"authored\", which only drops the one teaching step: the gate\n // entry still names `loam validate --all`, where an unreadable landscape\n // is actually graded, and letting this read throw would hand the whole\n // orientation surface — a command that reports and never gates — to the\n // repository-unavailable refusal over a file status does not even parse.\n return \"authored\";\n }\n}\n\n/** What a feature's fleet row needs about the fleet AROUND it. */\ninterface FleetView {\n graph: DependencyGraph;\n /** Operations some other feature's contract already holds. */\n contracted: ReadonlySet<string>;\n /** The enumeration's entries by id — where each living service is and what it has (owesContract reads both). */\n living: ReadonlyMap<string, ServiceEntry>;\n context: FleetContext;\n interrupted: InterruptedCommit | null;\n}\n\nasync function fleetFeature(\n docsDir: DocsDir,\n feature: FeatureEntry,\n view: FleetView,\n): Promise<FleetFeatureState> {\n const { graph, contracted, living, context, interrupted } = view;\n const paths = featurePaths(feature.dir);\n const missing: string[] = [];\n if (!existsSync(paths.intent)) missing.push(\"intent\");\n if (feature.services.length === 0) missing.push(\"spec\");\n // Requirement text, not a coherence run: `Operations:` lines are read off the\n // same cached parse `list` already pays for, and the contract question needs\n // them (owesContract). No LikeC4 workspace is spun here, which is the cost\n // this form actually refuses.\n const governs = governedServices(await scanDeltas(docsDir, feature, feature.services, context));\n for (const svc of feature.services) {\n const p = featureSpecPaths(feature.dir, svc);\n if (!existsSync(p.spec)) missing.push(`${svc}/spec`);\n // The same question featureArtifacts asks, through the same function: the\n // two forms must never disagree about whether a feature owes a contract.\n if (owesContract(living.get(svc), contracted.has(svc), governs.has(svc)) && !existsSync(p.openapi)) {\n missing.push(`${svc}/openapi`);\n }\n }\n const verification = (await verificationState(docsDir, feature)).state;\n const blockedBy = graph.nodes.find((n) => n.id === feature.id)?.dependsOn ?? [];\n\n // No `draft` here, ever: that verdict needs the coherence run this form\n // refuses to pay for, and inferring it from presence alone would be a second\n // opinion about validity — the one thing status must never invent.\n //\n // The interrupted commit leads, exactly as it does in the feature form: every\n // presence test below is a question about files a killed `archive` may have\n // half-written, so answering `done` from them is a claim about bytes nobody\n // has established. Without this the two forms contradicted each other over\n // one repository — `loam status --json` said `done` and offered \"ship it\"\n // while `loam status <FEAT>` said `blocked` — and the rule in report.ts's\n // header is that this projection is never greener than the gates.\n const stage: ArtifactStatus =\n interrupted !== null\n ? \"blocked\"\n : missing.length > 0\n ? \"missing\"\n : blockedBy.length > 0\n ? \"blocked\"\n : fullyVerified(verification)\n ? \"done\"\n : \"ready\";\n\n return {\n id: feature.id,\n dirName: feature.dirName,\n path: repoPath(docsDir, feature.dir),\n stage,\n services: feature.services,\n blockedBy,\n missing,\n verification,\n };\n}\n"]}
1
+ {"version":3,"file":"fleet.js","sourceRoot":"","sources":["../../../../src/core/status/fleet/fleet.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The whole repository — why the fleet form is cheaper than the feature form.\n *\n * `loam status` with no feature runs over every active feature, and deriving a\n * coherence report or a verification checklist per feature means spinning a\n * fresh LikeC4 workspace per feature. On a fleet-sized repository that is the\n * cost that gets a command switched off — `list` made the same call about its\n * verification column. So the fleet form grades nothing: it reports artifact\n * PRESENCE, the dependency order, and a verification record only where one\n * already exists, and its `next[]` hands off to `loam status <FEAT>`, which is\n * where the checks actually run.\n */\nimport { existsSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport { analyzeDependencies } from \"../../dependencies/dependencies.js\";\nimport { type DependencyGraph } from \"../../dependencies/facts.js\";\nimport { isLandscapeStub } from \"../../scaffold/landscape.js\";\nimport { repoPath } from \"../../envelope/json.js\";\nimport { FleetContext } from \"../../fleet-context.js\";\nimport { compareIds, type FeatureEntry, type ServiceEntry } from \"../../repo/entries.js\";\nimport { featurePaths, featureSpecPaths, landscapePath } from \"../../repo/paths.js\";\nimport { featureTitle, listFeatures, listServices } from \"../../repo/repo.js\";\nimport { introducingFeatures } from \"../../projection/introduced.js\";\nimport { contractEvidence, contractOwners, contractsHeldElsewhere, owesContract } from \"../contracts.js\";\nimport { readInterruptedCommit } from \"../interrupted.js\";\nimport {\n undocumented,\n vouched,\n type ArtifactStatus,\n type FleetFeatureState,\n type FleetStatusReport,\n type InterruptedCommit,\n} from \"../report.js\";\nimport { scanDeltas } from \"../scan.js\";\nimport { fullyVerified, verificationState } from \"../verification.js\";\nimport { fleetNext, groupServiceSteps, perServiceSteps, type Binding } from \"./next.js\";\nimport type { DocsDir } from \"../../kernel/ids/dirs.js\";\n\n/**\n * The fleet view: how much of `services/` anyone has written down, every\n * feature in flight with the stage it has reached, and the order they have to\n * land in. Nothing here is graded — the module header says why — so the stages\n * are drawn from artifact presence and from a record that already exists, and\n * `next[]` hands off to `loam status <FEAT>` for everything else.\n */\nexport async function fleetStatus(\n docsDir: DocsDir,\n opts: { service?: string; bound?: string; context: FleetContext },\n): Promise<FleetStatusReport> {\n const { context } = opts;\n const interrupted = await readInterruptedCommit(docsDir);\n const narrowed = opts.service;\n const all = await listServices(docsDir, context);\n const services = narrowed === undefined ? all : all.filter((s) => s.id === narrowed);\n // The service this repository says it IS, and whether the fleet has heard of\n // it. Asked against the UNNARROWED list, because \"is it adopted\" is a question\n // about the fleet and not about the view.\n //\n // Both facts travel, where only the unadopted case used to. This value was a\n // `string | null` that went null exactly when the service directory EXISTED,\n // so the walk could see the repository it stands in only while that\n // repository was undocumented — and a developer in an adopted service repo\n // got the whole fleet's worklist with their own boundary buried in it.\n //\n // And the third fact: which feature in flight introduces it, when the fleet\n // has no directory for it. Through the shared resolver, so `status` and\n // `show`/`context`/`steps` agree on what \"introduced\" means.\n const binding: Binding | null =\n opts.bound === undefined\n ? null\n : {\n id: opts.bound,\n adopted: all.some((s) => s.id === opts.bound),\n introducedBy: (await introducingFeatures(docsDir, opts.bound, context)).map((f) => f.id),\n };\n const graph = await analyzeDependencies(docsDir, undefined, context);\n const entries = await listFeatures(docsDir, {}, context);\n const inScope = narrowed === undefined ? entries : entries.filter((f) => f.services.some((s) => s === narrowed));\n // Once for the fleet, not once per feature: which features hold a contract\n // for which service is one fact about the repository, and every feature below\n // reads its own row out of it. Built over the UNNARROWED list on purpose — a\n // `--service` view still has to know that a feature outside it discharges the\n // contract, or the narrowing would invent an obligation.\n const owners = await contractOwners(docsDir, context);\n\n const features = await Promise.all(\n inScope.map((f) =>\n fleetFeature(docsDir, f, {\n graph,\n contracted: contractsHeldElsewhere(owners, f.id),\n living: new Map(all.map((s) => [s.id, s])),\n context,\n interrupted,\n }),\n ),\n );\n features.sort((a, b) => compareIds(a.id, b.id));\n\n // The first-hour ladder's fact, computed exactly when the ladder can apply\n // — an unnarrowed run over a fleet with zero services and zero features —\n // so the read disappears from every repository that has anything in it.\n // Withheld on narrowed runs for the same reason the binding is withheld\n // below: `--service X` is an explicit question about X, and the\n // repository's onboarding ladder would be a different question's answer.\n const teaching =\n narrowed === undefined && services.length === 0 && features.length === 0\n ? { landscape: await landscapeTeaching(docsDir) }\n : null;\n\n return {\n interrupted,\n services: {\n total: services.length,\n undocumented: services.filter(undocumented).length,\n draft: services.filter((s) => !undocumented(s) && !vouched(s)).length,\n vouched: services.filter(vouched).length,\n // A subset of `vouched`, never a fourth bucket: those services ARE\n // vouched, and the three counts still sum to `total`. It rides beside\n // the count it qualifies because this line is the fleet's trust\n // headline, and \"118 vouched\" over a fleet where 90 of them were read\n // from a sample is the misreading the scope exists to prevent.\n sampledVouched: services.filter((s) => vouched(s) && s.vouchScope === \"sampled\").length,\n // The other subset, for the same reason: \"118 vouched\" over a fleet where\n // twenty documents were edited after the person read them is the\n // trust headline lying by omission.\n contentStale: services.filter((s) => vouched(s) && s.contentStale.length > 0).length,\n },\n features,\n order: graph.order.filter((id) => features.some((f) => f.id === id)),\n service: narrowed ?? null,\n // The binding is passed only when this run was NOT narrowed, and that guard\n // is unchanged now that the binding also decides ORDER. `--service X` is an\n // explicit question about X, and answering it with a step about whichever\n // service loam.json happens to name would be a different question's answer\n // at the top of the list — which is as true of a rung promoted to the front\n // as it was of `next.adopt-bound` emitted out of nowhere. A narrowed run\n // sees at most the one service it asked about anyway, so withholding the\n // binding here costs the reader nothing and keeps `--service X` answering\n // only about X.\n next: fleetNext(\n { services, features, graph, interrupted, teaching },\n narrowed === undefined ? binding : null,\n ),\n // The same rungs `next[]` carries, from the same function, before the cap.\n serviceSteps: groupServiceSteps(\n perServiceSteps(services, narrowed === undefined && binding?.adopted === true ? binding.id : null),\n ),\n };\n}\n\n/**\n * Which first-hour state the fleet map is in: absent, still the scaffold's own\n * untouched bytes, or authored. One file read and a byte comparison — the\n * module header's cost rule stands, no LikeC4 workspace is spun here.\n */\nasync function landscapeTeaching(docsDir: DocsDir): Promise<\"missing\" | \"stub\" | \"authored\"> {\n const lp = landscapePath(docsDir);\n if (!existsSync(lp)) return \"missing\";\n try {\n return isLandscapeStub(await readFile(lp, \"utf8\")) ? \"stub\" : \"authored\";\n } catch {\n // Unreadable is not untouched. A map that cannot be read — a directory in\n // the file's place, a permission — must not be called the scaffold's stub\n // (\"missing\" and \"stub\" would each put a false statement in next[]), so it\n // reads as \"authored\", which only drops the one teaching step: the gate\n // entry still names `loam validate --all`, where an unreadable landscape\n // is actually graded, and letting this read throw would hand the whole\n // orientation surface — a command that reports and never gates — to the\n // repository-unavailable refusal over a file status does not even parse.\n return \"authored\";\n }\n}\n\n/** What a feature's fleet row needs about the fleet AROUND it. */\ninterface FleetView {\n graph: DependencyGraph;\n /** Operations some other feature's contract already holds. */\n contracted: ReadonlySet<string>;\n /** The enumeration's entries by id — where each living service is and what it has (owesContract reads both). */\n living: ReadonlyMap<string, ServiceEntry>;\n context: FleetContext;\n interrupted: InterruptedCommit | null;\n}\n\nasync function fleetFeature(\n docsDir: DocsDir,\n feature: FeatureEntry,\n view: FleetView,\n): Promise<FleetFeatureState> {\n const { graph, contracted, living, context, interrupted } = view;\n const paths = featurePaths(feature.dir);\n const missing: string[] = [];\n if (!existsSync(paths.intent)) missing.push(\"intent\");\n if (feature.services.length === 0) missing.push(\"spec\");\n // Requirement text and the delta's op-linked edges, not a coherence run: the\n // `Operations:` lines are read off the same cached parse `list` already pays\n // for, and the delta off the parse the dependency graph above already made\n // through this context — so the contract question (owesContract) spins no\n // LikeC4 workspace of its own, which is the cost this form refuses.\n const evidence = await contractEvidence(docsDir, feature, await scanDeltas(docsDir, feature, feature.services, context), context);\n for (const svc of feature.services) {\n const p = featureSpecPaths(feature.dir, svc);\n // EITHER corpus satisfies it. What a service delta owes is a requirement\n // delta, and `arch.spec.md` is the other one — same grammar, same delta\n // algebra, read by `featureChecklist` — so an architecture-only feature is\n // complete and every gate already says so. This form asked for `spec.md`\n // specifically, which broke the rule the comment two lines down states\n // about the contract question: the two forms disagreed, `loam status`\n // reporting `missing <svc>/spec` over a feature `loam status <FEAT>` and\n // `loam validate --feature` both called complete. The name stays\n // `<svc>/spec` when NEITHER exists, because the business delta is the one\n // an author writes by default.\n if (!existsSync(p.spec) && !existsSync(p.archSpec)) missing.push(`${svc}/spec`);\n // The same question featureArtifacts asks, through the same function: the\n // two forms must never disagree about whether a feature owes a contract.\n if (owesContract(living.get(svc), contracted.has(svc), evidence(svc)) && !existsSync(p.openapi)) {\n missing.push(`${svc}/openapi`);\n }\n }\n const verification = (await verificationState(docsDir, feature)).state;\n const blockedBy = graph.nodes.find((n) => n.id === feature.id)?.dependsOn ?? [];\n\n // No `draft` here, ever: that verdict needs the coherence run this form\n // refuses to pay for, and inferring it from presence alone would be a second\n // opinion about validity — the one thing status must never invent.\n //\n // The interrupted commit leads, exactly as it does in the feature form: every\n // presence test below is a question about files a killed `archive` may have\n // half-written, so answering `done` from them is a claim about bytes nobody\n // has established. Without this the two forms contradicted each other over\n // one repository — `loam status --json` said `done` and offered \"ship it\"\n // while `loam status <FEAT>` said `blocked` — and the rule in report.ts's\n // header is that this projection is never greener than the gates.\n const stage: ArtifactStatus =\n interrupted !== null\n ? \"blocked\"\n : missing.length > 0\n ? \"missing\"\n : blockedBy.length > 0\n ? \"blocked\"\n : fullyVerified(verification)\n ? \"done\"\n : \"ready\";\n\n return {\n id: feature.id,\n title: await featureTitle(feature),\n dirName: feature.dirName,\n path: repoPath(docsDir, feature.dir),\n stage,\n services: feature.services,\n blockedBy,\n missing,\n verification,\n };\n}\n"]}