@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
@@ -0,0 +1,107 @@
1
+ /** The scenario's own name, when the packet found the words the claim was minted from. */
2
+ function scenarioOf(unit) {
3
+ const source = unit.source;
4
+ return source !== undefined && "scenario" in source ? source.scenario : undefined;
5
+ }
6
+ /**
7
+ * A scenario action, with the claim appended when the name is missing. A
8
+ * scenario unit has no source only when the digest belt in core/tasks/packet.ts
9
+ * refused somebody else's words — rare, and then "make it pass" alone would be
10
+ * an instruction about nothing in particular.
11
+ */
12
+ function aboutScenario(unit, phrase) {
13
+ const name = scenarioOf(unit);
14
+ return name === undefined ? `${phrase("it")}: ${unit.claim}` : phrase(`scenario '${name}'`);
15
+ }
16
+ /** `sends` or `receives`, out of the claim's prose — display only, see the header. */
17
+ const DIRECTION = / declares it (sends|receives) message /;
18
+ /** The provider at the end of `<from> calls '<op>' on <to>` — display only, see the header. */
19
+ const CALLEE = / on (\S+)$/;
20
+ /** What a unit waiting at `implement` asks for, by kind. */
21
+ function implementAction(unit) {
22
+ switch (unit.kind) {
23
+ case "scenario.tested":
24
+ return aboutScenario(unit, (what) => `make ${what} pass, then record the run`);
25
+ case "api.exposes":
26
+ // Named because its channel is the unusual one: its done check asks for
27
+ // a contract-test report (`--contract-results`), not a cucumber run.
28
+ return unit.operation === undefined
29
+ ? unit.claim
30
+ : `expose operation '${unit.operation}' (contract-test evidence closes it)`;
31
+ case "event.declares": {
32
+ const direction = DIRECTION.exec(unit.claim)?.[1];
33
+ if (unit.token === undefined || direction === undefined)
34
+ return unit.claim;
35
+ return `${direction === "sends" ? "send" : "receive"} message '${unit.token}'`;
36
+ }
37
+ case "c4.calls": {
38
+ const callee = CALLEE.exec(unit.claim)?.[1];
39
+ if (unit.token === undefined || callee === undefined)
40
+ return unit.claim;
41
+ return `call '${unit.token}' on ${callee}`;
42
+ }
43
+ case "service.exists":
44
+ return `create service '${unit.subject}'`;
45
+ default:
46
+ // A kind added to the vocabulary after this was written still prints
47
+ // something true rather than nothing.
48
+ return unit.claim;
49
+ }
50
+ }
51
+ /**
52
+ * The unit as an action. `feature` is spelled into the one arm that names a
53
+ * command, because a reader handed "run the generator" with no id has to go and
54
+ * find out which feature they are looking at.
55
+ */
56
+ export function actionOf(unit, feature) {
57
+ switch (unit.at) {
58
+ case "describe":
59
+ return unit.source === undefined
60
+ ? unit.claim
61
+ : `write the scenarios for requirement '${unit.source.requirement}' — at least one Given/When/Then, in the docs repo`;
62
+ case "generate":
63
+ return aboutScenario(unit, (what) => `generate the test for ${what} (loam gherkin ${feature})`);
64
+ case "attested":
65
+ return aboutScenario(unit, (what) => `re-answer ${what} from a test run — it rests on an agent's word`);
66
+ case "implement":
67
+ return implementAction(unit);
68
+ default: {
69
+ const unreachable = unit.at;
70
+ return unreachable;
71
+ }
72
+ }
73
+ }
74
+ /** The kinds a contract delta promises — openapi.yaml and asyncapi.yaml. */
75
+ const CONTRACT_KINDS = new Set(["api.exposes", "event.declares"]);
76
+ /** The kinds delta.likec4 promises — a service drawn, an edge between two. */
77
+ const ARCHITECTURE_KINDS = new Set(["service.exists", "c4.calls"]);
78
+ /**
79
+ * The heading a unit is filed under inside its service.
80
+ *
81
+ * A requirement's units sit under the requirement, which is where a person
82
+ * opens the file — and the path is printed ONCE there rather than on every
83
+ * row, which is most of what made the old view unreadable. The key carries the
84
+ * path as well as the requirement: one name may legitimately appear on both
85
+ * axes (`spec.md` and `arch.spec.md`), and those are two requirements.
86
+ *
87
+ * A describe unit's line IS the requirement heading's, so it rides on the
88
+ * heading; a scenario's line is its own and is printed on its row.
89
+ */
90
+ export function groupOf(unit) {
91
+ if (CONTRACT_KINDS.has(unit.kind))
92
+ return { key: "contract", heading: "contract — operations and messages" };
93
+ if (ARCHITECTURE_KINDS.has(unit.kind))
94
+ return { key: "architecture", heading: "architecture — delta.likec4" };
95
+ const source = unit.source;
96
+ if (source === undefined) {
97
+ return { key: "unplaced", heading: "scenarios loam could not match to their words — each row quotes its claim" };
98
+ }
99
+ const label = source.path.endsWith("arch.spec.md") ? "arch requirement" : "requirement";
100
+ const id = source.requirementId === undefined ? "" : ` [${source.requirementId}]`;
101
+ const line = unit.at === "describe" && source.line !== undefined ? `:${source.line}` : "";
102
+ return {
103
+ key: ["requirement", source.path, source.requirementId ?? "", source.requirement].join("\0"),
104
+ heading: `${label} '${source.requirement}'${id} — ${source.path}${line}`,
105
+ };
106
+ }
107
+ //# sourceMappingURL=actions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"actions.js","sourceRoot":"","sources":["../../../src/commands/tasks/actions.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * A unit said as something a person does, and the heading it is filed under.\n *\n * The packet's `claim` is the QUESTION `loam verify` asks — \"scenario 'X' of\n * requirement 'Y' (svc) is covered by a test\" — and a list of questions reads as\n * a claim ledger rather than a to-do list: the step a unit waits at used to be a\n * bracketed tag in front of a sentence that never changed with it. Here the step\n * and the kind together pick the verb, so a unit at `generate` says \"generate\n * the test\" and the same scenario at `implement` says \"make it pass\". The claim\n * stays on the payload and in `--next`, verbatim; this is a rendering, and\n * nothing ever reads it back.\n *\n * Two facts the phrasing wants live only in the claim's prose — which way an\n * event.declares message goes, and which service a c4.calls edge lands on:\n * `featureChecklist` (core/verify/checklist.ts) spells both into the sentence\n * and carries neither as a field. They are read out of the prose for DISPLAY\n * only, and a reworded claim falls back to the claim itself, which is always\n * true: no join key, count or verdict comes from here, which is the line\n * `Claim.operation`'s docblock draws against parsing claim prose.\n */\nimport type { TaskUnit } from \"../../core/tasks/unit.js\";\n\n/** The scenario's own name, when the packet found the words the claim was minted from. */\nfunction scenarioOf(unit: TaskUnit): string | undefined {\n const source = unit.source;\n return source !== undefined && \"scenario\" in source ? source.scenario : undefined;\n}\n\n/**\n * A scenario action, with the claim appended when the name is missing. A\n * scenario unit has no source only when the digest belt in core/tasks/packet.ts\n * refused somebody else's words — rare, and then \"make it pass\" alone would be\n * an instruction about nothing in particular.\n */\nfunction aboutScenario(unit: TaskUnit, phrase: (what: string) => string): string {\n const name = scenarioOf(unit);\n return name === undefined ? `${phrase(\"it\")}: ${unit.claim}` : phrase(`scenario '${name}'`);\n}\n\n/** `sends` or `receives`, out of the claim's prose — display only, see the header. */\nconst DIRECTION = / declares it (sends|receives) message /;\n\n/** The provider at the end of `<from> calls '<op>' on <to>` — display only, see the header. */\nconst CALLEE = / on (\\S+)$/;\n\n/** What a unit waiting at `implement` asks for, by kind. */\nfunction implementAction(unit: TaskUnit): string {\n switch (unit.kind) {\n case \"scenario.tested\":\n return aboutScenario(unit, (what) => `make ${what} pass, then record the run`);\n case \"api.exposes\":\n // Named because its channel is the unusual one: its done check asks for\n // a contract-test report (`--contract-results`), not a cucumber run.\n return unit.operation === undefined\n ? unit.claim\n : `expose operation '${unit.operation}' (contract-test evidence closes it)`;\n case \"event.declares\": {\n const direction = DIRECTION.exec(unit.claim)?.[1];\n if (unit.token === undefined || direction === undefined) return unit.claim;\n return `${direction === \"sends\" ? \"send\" : \"receive\"} message '${unit.token}'`;\n }\n case \"c4.calls\": {\n const callee = CALLEE.exec(unit.claim)?.[1];\n if (unit.token === undefined || callee === undefined) return unit.claim;\n return `call '${unit.token}' on ${callee}`;\n }\n case \"service.exists\":\n return `create service '${unit.subject}'`;\n default:\n // A kind added to the vocabulary after this was written still prints\n // something true rather than nothing.\n return unit.claim;\n }\n}\n\n/**\n * The unit as an action. `feature` is spelled into the one arm that names a\n * command, because a reader handed \"run the generator\" with no id has to go and\n * find out which feature they are looking at.\n */\nexport function actionOf(unit: TaskUnit, feature: string): string {\n switch (unit.at) {\n case \"describe\":\n return unit.source === undefined\n ? unit.claim\n : `write the scenarios for requirement '${unit.source.requirement}' — at least one Given/When/Then, in the docs repo`;\n case \"generate\":\n return aboutScenario(unit, (what) => `generate the test for ${what} (loam gherkin ${feature})`);\n case \"attested\":\n return aboutScenario(unit, (what) => `re-answer ${what} from a test run — it rests on an agent's word`);\n case \"implement\":\n return implementAction(unit);\n default: {\n const unreachable: never = unit.at;\n return unreachable;\n }\n }\n}\n\n/** The kinds a contract delta promises — openapi.yaml and asyncapi.yaml. */\nconst CONTRACT_KINDS: ReadonlySet<string> = new Set([\"api.exposes\", \"event.declares\"]);\n\n/** The kinds delta.likec4 promises — a service drawn, an edge between two. */\nconst ARCHITECTURE_KINDS: ReadonlySet<string> = new Set([\"service.exists\", \"c4.calls\"]);\n\nexport interface UnitGroup {\n /** What makes two units one group: the same document and the same requirement in it. */\n key: string;\n heading: string;\n}\n\n/**\n * The heading a unit is filed under inside its service.\n *\n * A requirement's units sit under the requirement, which is where a person\n * opens the file — and the path is printed ONCE there rather than on every\n * row, which is most of what made the old view unreadable. The key carries the\n * path as well as the requirement: one name may legitimately appear on both\n * axes (`spec.md` and `arch.spec.md`), and those are two requirements.\n *\n * A describe unit's line IS the requirement heading's, so it rides on the\n * heading; a scenario's line is its own and is printed on its row.\n */\nexport function groupOf(unit: TaskUnit): UnitGroup {\n if (CONTRACT_KINDS.has(unit.kind)) return { key: \"contract\", heading: \"contract — operations and messages\" };\n if (ARCHITECTURE_KINDS.has(unit.kind)) return { key: \"architecture\", heading: \"architecture — delta.likec4\" };\n const source = unit.source;\n if (source === undefined) {\n return { key: \"unplaced\", heading: \"scenarios loam could not match to their words — each row quotes its claim\" };\n }\n const label = source.path.endsWith(\"arch.spec.md\") ? \"arch requirement\" : \"requirement\";\n const id = source.requirementId === undefined ? \"\" : ` [${source.requirementId}]`;\n const line = unit.at === \"describe\" && source.line !== undefined ? `:${source.line}` : \"\";\n return {\n key: [\"requirement\", source.path, source.requirementId ?? \"\", source.requirement].join(\"\\0\"),\n heading: `${label} '${source.requirement}'${id} — ${source.path}${line}`,\n };\n}\n"]}
@@ -0,0 +1,253 @@
1
+ import { actionOf, groupOf } from "./actions.js";
2
+ /**
3
+ * How many units one service shows in the WHOLE-feature view before the rest
4
+ * are elided behind its own lens. Under a lens nothing is elided: the lens IS
5
+ * the full listing, and pointing a person who already asked for one service at
6
+ * `--json` to see the rest of it sent them to the one view not written for them.
7
+ */
8
+ const PER_SERVICE_LIMIT = 12;
9
+ /** What each record state means for the list below it, in the words a reader acts on. */
10
+ const RECORD_MEANING = {
11
+ absent: "no verification record yet, so nothing counts as done",
12
+ recorded: "the verification record answers this checklist; what it confirmed is off this list, bar attested scenarios",
13
+ stale: "the verification record answers an older question set, so it closes nothing until it is re-recorded",
14
+ unreadable: "the verification record could not be read, so it closes nothing",
15
+ };
16
+ /**
17
+ * What the stamps reading means, which turns on WHERE loam is standing.
18
+ *
19
+ * The stamps are read from this repository's generated suite and nobody else's
20
+ * (core/tasks/stamps.ts). So a scenario owned by another service reads
21
+ * `implement` whatever its own repository holds — the packet's honest answer,
22
+ * because nothing here looked — and the header says so whenever such a unit is
23
+ * on screen, or a person reads "implement" as "the test exists".
24
+ */
25
+ function stampsMeaning(packet, view) {
26
+ if (packet.stamps === "unknown") {
27
+ return view.bound === undefined
28
+ ? "this is not a service repository bound with loam.json, so loam cannot see which tests were generated — " +
29
+ "run it in the service's repo to tell 'generate' from 'implement'"
30
+ : `this repository's generated suite (${view.bound}) could not be read — an unreadable directory, ` +
31
+ "or a gherkinDir outside the repository — so no scenario reads 'generate'";
32
+ }
33
+ const own = `from this repository's generated suite${view.bound === undefined ? "" : ` (${view.bound})`}`;
34
+ const elsewhere = [
35
+ ...new Set(packet.units.filter((unit) => unit.kind === "scenario.tested" && unit.subject !== view.bound).map((u) => u.subject)),
36
+ ];
37
+ if (elsewhere.length === 0)
38
+ return own;
39
+ const one = elsewhere.length === 1;
40
+ return (`${own}; ${elsewhere.join(", ")} ${one ? "keeps its tests in its own repository" : "keep their tests in their own repositories"}, ` +
41
+ `so ${one ? "its" : "their"} scenarios read 'implement' whatever is generated there — ` +
42
+ `run loam tasks in ${one ? "that repository" : "those repositories"}`);
43
+ }
44
+ /** Which slice of the feature this is, and how to get another. */
45
+ function lensLine(packet, view) {
46
+ const lens = packet.service;
47
+ if (lens !== null && view.explicitLens)
48
+ return `lens: ${lens} — its units only, every one listed`;
49
+ if (lens !== null)
50
+ return `lens: ${lens} — this repository's service (loam.json); pass --service <id> for another`;
51
+ const among = packet.services.length === 0 ? "" : ` (${packet.services.join(", ")})`;
52
+ return view.bound === undefined
53
+ ? `view: the whole feature${among} — --service <id> narrows it to one service`
54
+ : `view: the whole feature${among} — this repository's service, ${view.bound}, is not one ${packet.feature} touches`;
55
+ }
56
+ /** The lines under the title both views share: what the record and the stamps MEAN, the lens, the blind spots. */
57
+ function header(packet, view) {
58
+ console.log(` record: ${packet.record} — ${RECORD_MEANING[packet.record]}`);
59
+ console.log(` stamps: ${packet.stamps} — ${stampsMeaning(packet, view)}`);
60
+ console.log(` ${lensLine(packet, view)}`);
61
+ // The blind spots straight after, and before any list: an empty packet over a
62
+ // document nobody could read is the one output an implementer must never take
63
+ // at face value, and a warning under fifty lines of units is one nobody reads.
64
+ for (const warning of blindSpots(packet))
65
+ console.log(` ⚠ ${warning}`);
66
+ }
67
+ /** The step tag, padded so the actions line up: `[implement]` is the widest. */
68
+ function tag(step) {
69
+ return `[${step}]`.padEnd("[implement]".length);
70
+ }
71
+ /** One row: the step, the action, the scenario's own line when it has one, and the id an agent hands on. */
72
+ function row(unit, feature) {
73
+ const source = unit.source;
74
+ const line = source !== undefined && "scenario" in source && source.line !== undefined ? ` · line ${source.line}` : "";
75
+ return ` ${tag(unit.at)} ${actionOf(unit, feature)}${line} · ${unit.id}`;
76
+ }
77
+ /** Units filed under their heading, in the order the packet already sorted them — first appearance wins. */
78
+ function grouped(units) {
79
+ const groups = new Map();
80
+ for (const unit of units) {
81
+ const group = groupOf(unit);
82
+ const existing = groups.get(group.key);
83
+ if (existing === undefined)
84
+ groups.set(group.key, { ...group, units: [unit] });
85
+ else
86
+ existing.units.push(unit);
87
+ }
88
+ return [...groups.values()];
89
+ }
90
+ /** `9 open`, plus the attested ones when there are any — those are listed, and are not work. */
91
+ function tally(units) {
92
+ const attested = units.filter((unit) => unit.at === "attested").length;
93
+ return `${units.length - attested} open${attested === 0 ? "" : ` · ${attested} attested`}`;
94
+ }
95
+ /** The `--next` invocation for this packet's own slice — the flag carried only when the reader typed it. */
96
+ function nextCommand(packet, view) {
97
+ const lens = view.explicitLens && packet.service !== null ? ` --service ${packet.service}` : "";
98
+ return `loam tasks ${packet.feature}${lens} --next`;
99
+ }
100
+ /**
101
+ * The frontier as a person reads it: the head's action first, then the ids.
102
+ * A bare list of ten hashes said what to do to nobody; the ids stay, because
103
+ * they are the order an orchestrator hands units out in.
104
+ */
105
+ function frontierLines(packet, view) {
106
+ const headId = packet.frontier[0];
107
+ if (headId === undefined)
108
+ return [];
109
+ const head = packet.units.find((unit) => unit.id === headId);
110
+ const more = packet.frontierElided > 0 ? ` (+${packet.frontierElided} more open)` : "";
111
+ return [
112
+ head === undefined
113
+ ? ` next up: ${headId}`
114
+ : ` next up (${head.subject}): ${actionOf(head, packet.feature)} · ${headId}`,
115
+ ` ${nextCommand(packet, view)} prints it in full, with what closes it`,
116
+ ` frontier, the order to take open units in: ${packet.frontier.join(", ")}${more}`,
117
+ ];
118
+ }
119
+ export function renderPacket(packet, view) {
120
+ // Attested is the one count whose word misleads: it reads like "done", and
121
+ // it is the opposite — complete work resting on an assertion, still listed.
122
+ const attested = packet.counts.attested === 0 ? "" : " (confirmed on an agent's word, not a run — still listed)";
123
+ console.log(`${packet.feature} — ${packet.counts.open} open · ${packet.counts.done} done · ${packet.counts.attested} attested${attested}`);
124
+ header(packet, view);
125
+ console.log("");
126
+ if (packet.units.length === 0) {
127
+ console.log(packet.counts.attested > 0 || packet.counts.done > 0
128
+ ? " Nothing open. Every unit is recorded confirmed, or attested and waiting on a run."
129
+ : " Nothing open — this feature's delta, specs and contracts promise nothing yet.");
130
+ }
131
+ const capped = packet.service === null;
132
+ for (const subject of new Set(packet.units.map((unit) => unit.subject))) {
133
+ const units = packet.units.filter((unit) => unit.subject === subject);
134
+ const shown = capped ? units.slice(0, PER_SERVICE_LIMIT) : units;
135
+ console.log(` ${subject} — ${tally(units)}`);
136
+ for (const group of grouped(shown)) {
137
+ console.log(` ${group.heading}`);
138
+ for (const unit of group.units)
139
+ console.log(row(unit, packet.feature));
140
+ }
141
+ if (shown.length < units.length) {
142
+ console.log(` +${units.length - shown.length} more — \`loam tasks ${packet.feature} --service ${subject}\` lists every one`);
143
+ }
144
+ console.log("");
145
+ }
146
+ for (const line of frontierLines(packet, view))
147
+ console.log(line);
148
+ for (const waiting of packet.waitingOn ?? []) {
149
+ console.log(` waiting on ${waiting.subject}: ${waiting.claim} · ${waiting.id}, still open there`);
150
+ }
151
+ if (packet.units.length > 0) {
152
+ console.log("\n [step] is where a unit waits: describe → generate → implement, or attested. " +
153
+ "`loam explain <word>` defines each of those, and frontier.");
154
+ }
155
+ console.log("\n Review:");
156
+ for (const note of packet.review)
157
+ console.log(` - ${note}`);
158
+ }
159
+ /**
160
+ * The leaf, in full. The follow-up command is literal rather than a shape to
161
+ * fill in, because the reader is usually a model cheap enough that "the
162
+ * appropriate verify invocation" is a guess it will get wrong.
163
+ */
164
+ export function renderNext(packet, view) {
165
+ const unit = packet.units[0];
166
+ if (unit === undefined) {
167
+ console.log(`${packet.feature} — nothing open (${packet.counts.done} done · ${packet.counts.attested} attested)`);
168
+ header(packet, view);
169
+ return;
170
+ }
171
+ console.log(`${packet.feature} — next: ${unit.id}`);
172
+ console.log(` ${actionOf(unit, packet.feature)}`);
173
+ // The lens only when the binding chose it: a reader who typed --service knows
174
+ // which slice this is, and one who did not would otherwise be handed another
175
+ // service's head with no word on why it is this one.
176
+ if (packet.service !== null && !view.explicitLens)
177
+ console.log(` ${lensLine(packet, view)}`);
178
+ for (const warning of blindSpots(packet))
179
+ console.log(` ⚠ ${warning}`);
180
+ const ungraded = ungradedScenario(packet, view, unit);
181
+ if (ungraded !== undefined)
182
+ console.log(` ⚠ ${ungraded}`);
183
+ console.log("");
184
+ console.log(` [${unit.at}] ${unit.kind} [${unit.subject}]`);
185
+ console.log(` ${unit.claim}`);
186
+ const source = unit.source;
187
+ if (source !== undefined) {
188
+ console.log(` ${source.path}${source.line === undefined ? "" : `:${source.line}`}`);
189
+ // Verbatim, never reflowed: these are the bytes the scenario digest was
190
+ // taken over, and a test written from reworded criteria answers a claim
191
+ // nobody made.
192
+ if ("lines" in source)
193
+ for (const body of source.lines)
194
+ console.log(` ${body}`);
195
+ }
196
+ if (unit.dependsOn.length > 0)
197
+ console.log(` depends on: ${unit.dependsOn.join(", ")}`);
198
+ console.log(`\n done: ${unit.done.check}`);
199
+ console.log(`\n ${followUp(packet.feature, unit)}`);
200
+ }
201
+ /**
202
+ * The caveat a scenario at `implement` needs when nobody looked for its
203
+ * generated test: `implement` is also what a scenario reads when the stamps
204
+ * could not be read, or belong to another repository, and handing a worker
205
+ * "make it pass" for a test that was never generated sends them to write one by
206
+ * hand — the paraphrase the generated suite exists to prevent.
207
+ */
208
+ function ungradedScenario(packet, view, unit) {
209
+ if (unit.kind !== "scenario.tested" || unit.at !== "implement")
210
+ return undefined;
211
+ if (packet.stamps === "read" && unit.subject === view.bound)
212
+ return undefined;
213
+ if (unit.subject === view.bound) {
214
+ return ("whether this scenario's test was generated is unknown — this repository's generated suite could not be read; " +
215
+ `if loam gherkin ${packet.feature} has not run here, run it first`);
216
+ }
217
+ return (`whether this scenario's test was generated is unknown here — its suite lives in ${unit.subject}'s repository; ` +
218
+ `run loam tasks there, or loam gherkin ${packet.feature} there first if it has not run`);
219
+ }
220
+ /**
221
+ * The command that closes this unit.
222
+ *
223
+ * A `describe` unit is the one arm that is NOT a `loam verify --record`: there
224
+ * is no claim to answer, because a requirement with no scenario asks no
225
+ * question — the work is writing the Given/When/Then into the file named above,
226
+ * and `loam validate --feature` is what grades that it landed. Pointing it at
227
+ * `--record` would invite an answer to a question the checklist does not carry.
228
+ */
229
+ function followUp(feature, unit) {
230
+ if (unit.at === "describe")
231
+ return `loam validate --feature ${feature}`;
232
+ if (unit.at === "generate")
233
+ return `loam gherkin ${feature}`;
234
+ if (unit.kind === "scenario.tested") {
235
+ return `loam verify ${feature} --service ${unit.subject} --results report.json`;
236
+ }
237
+ return `loam verify ${feature} --record answers.json --service ${unit.subject}`;
238
+ }
239
+ /** What the packet could not look at — one sentence per document class. */
240
+ function blindSpots(packet) {
241
+ const out = [];
242
+ if (packet.unreadable.architecture !== undefined) {
243
+ out.push(`delta.likec4 does not parse (${packet.unreadable.architecture}) — no c4.calls unit could be derived, ` +
244
+ "so this list is short because loam could not look, not because the work is done");
245
+ }
246
+ const contracts = packet.unreadable.contracts;
247
+ if (contracts !== undefined) {
248
+ out.push(`contract delta unreadable for ${contracts.join(", ")} — operations and messages are missing from this packet, ` +
249
+ "not absent from the feature");
250
+ }
251
+ return out;
252
+ }
253
+ //# sourceMappingURL=render.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.js","sourceRoot":"","sources":["../../../src/commands/tasks/render.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The terminal view of a work packet.\n *\n * Two shapes for two readers. The whole packet is a person's orientation — how\n * much is open, filed under which service and which requirement, what each unit\n * asks them to DO, and which unit leads — so every row is an action rather than\n * the claim it answers, and the requirement's file is printed once over its\n * scenarios rather than on each of them. `--next` is the opposite: a single\n * leaf, printed in full, including the scenario's Given/When/Then VERBATIM,\n * because that text is the acceptance criterion and the exact words the digest\n * was taken over. Paraphrasing it into a summary is the one thing the digest\n * chain exists to prevent.\n *\n * Every row keeps its unit id. The id is what an agent hands `loam verify`, and\n * a view that dropped it to read better would turn the human listing into one\n * nobody can act on without a second, `--json`, run.\n *\n * Every `loam …` line printed here parses against the real CLI —\n * `test/agent-commands-runnable.test.ts` is the consumer, and an instruction\n * loam prints that does not parse is a defect rather than a typo.\n */\nimport type { WorkPacket } from \"../../core/tasks/packet.js\";\nimport type { RecordState } from \"../../core/tasks/record.js\";\nimport type { TaskStep, TaskUnit } from \"../../core/tasks/unit.js\";\nimport { actionOf, groupOf, type UnitGroup } from \"./actions.js\";\n\n/** What the command knows and the packet does not: where the lens came from, and which repository this is. */\nexport interface TasksView {\n /** True when `--service` named the lens; false when it came from the binding, or there is none. */\n explicitLens: boolean;\n /** loam.json's `service` — set only when standing in a service repository. */\n bound: string | undefined;\n}\n\n/**\n * How many units one service shows in the WHOLE-feature view before the rest\n * are elided behind its own lens. Under a lens nothing is elided: the lens IS\n * the full listing, and pointing a person who already asked for one service at\n * `--json` to see the rest of it sent them to the one view not written for them.\n */\nconst PER_SERVICE_LIMIT = 12;\n\n/** What each record state means for the list below it, in the words a reader acts on. */\nconst RECORD_MEANING: Record<RecordState, string> = {\n absent: \"no verification record yet, so nothing counts as done\",\n recorded: \"the verification record answers this checklist; what it confirmed is off this list, bar attested scenarios\",\n stale: \"the verification record answers an older question set, so it closes nothing until it is re-recorded\",\n unreadable: \"the verification record could not be read, so it closes nothing\",\n};\n\n/**\n * What the stamps reading means, which turns on WHERE loam is standing.\n *\n * The stamps are read from this repository's generated suite and nobody else's\n * (core/tasks/stamps.ts). So a scenario owned by another service reads\n * `implement` whatever its own repository holds — the packet's honest answer,\n * because nothing here looked — and the header says so whenever such a unit is\n * on screen, or a person reads \"implement\" as \"the test exists\".\n */\nfunction stampsMeaning(packet: WorkPacket, view: TasksView): string {\n if (packet.stamps === \"unknown\") {\n return view.bound === undefined\n ? \"this is not a service repository bound with loam.json, so loam cannot see which tests were generated — \" +\n \"run it in the service's repo to tell 'generate' from 'implement'\"\n : `this repository's generated suite (${view.bound}) could not be read — an unreadable directory, ` +\n \"or a gherkinDir outside the repository — so no scenario reads 'generate'\";\n }\n const own = `from this repository's generated suite${view.bound === undefined ? \"\" : ` (${view.bound})`}`;\n const elsewhere = [\n ...new Set(packet.units.filter((unit) => unit.kind === \"scenario.tested\" && unit.subject !== view.bound).map((u) => u.subject)),\n ];\n if (elsewhere.length === 0) return own;\n const one = elsewhere.length === 1;\n return (\n `${own}; ${elsewhere.join(\", \")} ${one ? \"keeps its tests in its own repository\" : \"keep their tests in their own repositories\"}, ` +\n `so ${one ? \"its\" : \"their\"} scenarios read 'implement' whatever is generated there — ` +\n `run loam tasks in ${one ? \"that repository\" : \"those repositories\"}`\n );\n}\n\n/** Which slice of the feature this is, and how to get another. */\nfunction lensLine(packet: WorkPacket, view: TasksView): string {\n const lens = packet.service;\n if (lens !== null && view.explicitLens) return `lens: ${lens} — its units only, every one listed`;\n if (lens !== null) return `lens: ${lens} — this repository's service (loam.json); pass --service <id> for another`;\n const among = packet.services.length === 0 ? \"\" : ` (${packet.services.join(\", \")})`;\n return view.bound === undefined\n ? `view: the whole feature${among} — --service <id> narrows it to one service`\n : `view: the whole feature${among} — this repository's service, ${view.bound}, is not one ${packet.feature} touches`;\n}\n\n/** The lines under the title both views share: what the record and the stamps MEAN, the lens, the blind spots. */\nfunction header(packet: WorkPacket, view: TasksView): void {\n console.log(` record: ${packet.record} — ${RECORD_MEANING[packet.record]}`);\n console.log(` stamps: ${packet.stamps} — ${stampsMeaning(packet, view)}`);\n console.log(` ${lensLine(packet, view)}`);\n // The blind spots straight after, and before any list: an empty packet over a\n // document nobody could read is the one output an implementer must never take\n // at face value, and a warning under fifty lines of units is one nobody reads.\n for (const warning of blindSpots(packet)) console.log(` ⚠ ${warning}`);\n}\n\n/** The step tag, padded so the actions line up: `[implement]` is the widest. */\nfunction tag(step: TaskStep): string {\n return `[${step}]`.padEnd(\"[implement]\".length);\n}\n\n/** One row: the step, the action, the scenario's own line when it has one, and the id an agent hands on. */\nfunction row(unit: TaskUnit, feature: string): string {\n const source = unit.source;\n const line = source !== undefined && \"scenario\" in source && source.line !== undefined ? ` · line ${source.line}` : \"\";\n return ` ${tag(unit.at)} ${actionOf(unit, feature)}${line} · ${unit.id}`;\n}\n\n/** Units filed under their heading, in the order the packet already sorted them — first appearance wins. */\nfunction grouped(units: readonly TaskUnit[]): Array<UnitGroup & { units: TaskUnit[] }> {\n const groups = new Map<string, UnitGroup & { units: TaskUnit[] }>();\n for (const unit of units) {\n const group = groupOf(unit);\n const existing = groups.get(group.key);\n if (existing === undefined) groups.set(group.key, { ...group, units: [unit] });\n else existing.units.push(unit);\n }\n return [...groups.values()];\n}\n\n/** `9 open`, plus the attested ones when there are any — those are listed, and are not work. */\nfunction tally(units: readonly TaskUnit[]): string {\n const attested = units.filter((unit) => unit.at === \"attested\").length;\n return `${units.length - attested} open${attested === 0 ? \"\" : ` · ${attested} attested`}`;\n}\n\n/** The `--next` invocation for this packet's own slice — the flag carried only when the reader typed it. */\nfunction nextCommand(packet: WorkPacket, view: TasksView): string {\n const lens = view.explicitLens && packet.service !== null ? ` --service ${packet.service}` : \"\";\n return `loam tasks ${packet.feature}${lens} --next`;\n}\n\n/**\n * The frontier as a person reads it: the head's action first, then the ids.\n * A bare list of ten hashes said what to do to nobody; the ids stay, because\n * they are the order an orchestrator hands units out in.\n */\nfunction frontierLines(packet: WorkPacket, view: TasksView): string[] {\n const headId = packet.frontier[0];\n if (headId === undefined) return [];\n const head = packet.units.find((unit) => unit.id === headId);\n const more = packet.frontierElided > 0 ? ` (+${packet.frontierElided} more open)` : \"\";\n return [\n head === undefined\n ? ` next up: ${headId}`\n : ` next up (${head.subject}): ${actionOf(head, packet.feature)} · ${headId}`,\n ` ${nextCommand(packet, view)} prints it in full, with what closes it`,\n ` frontier, the order to take open units in: ${packet.frontier.join(\", \")}${more}`,\n ];\n}\n\nexport function renderPacket(packet: WorkPacket, view: TasksView): void {\n // Attested is the one count whose word misleads: it reads like \"done\", and\n // it is the opposite — complete work resting on an assertion, still listed.\n const attested = packet.counts.attested === 0 ? \"\" : \" (confirmed on an agent's word, not a run — still listed)\";\n console.log(\n `${packet.feature} — ${packet.counts.open} open · ${packet.counts.done} done · ${packet.counts.attested} attested${attested}`,\n );\n header(packet, view);\n console.log(\"\");\n\n if (packet.units.length === 0) {\n console.log(\n packet.counts.attested > 0 || packet.counts.done > 0\n ? \" Nothing open. Every unit is recorded confirmed, or attested and waiting on a run.\"\n : \" Nothing open — this feature's delta, specs and contracts promise nothing yet.\",\n );\n }\n const capped = packet.service === null;\n for (const subject of new Set(packet.units.map((unit) => unit.subject))) {\n const units = packet.units.filter((unit) => unit.subject === subject);\n const shown = capped ? units.slice(0, PER_SERVICE_LIMIT) : units;\n console.log(` ${subject} — ${tally(units)}`);\n for (const group of grouped(shown)) {\n console.log(` ${group.heading}`);\n for (const unit of group.units) console.log(row(unit, packet.feature));\n }\n if (shown.length < units.length) {\n console.log(\n ` +${units.length - shown.length} more — \\`loam tasks ${packet.feature} --service ${subject}\\` lists every one`,\n );\n }\n console.log(\"\");\n }\n\n for (const line of frontierLines(packet, view)) console.log(line);\n for (const waiting of packet.waitingOn ?? []) {\n console.log(` waiting on ${waiting.subject}: ${waiting.claim} · ${waiting.id}, still open there`);\n }\n if (packet.units.length > 0) {\n console.log(\n \"\\n [step] is where a unit waits: describe → generate → implement, or attested. \" +\n \"`loam explain <word>` defines each of those, and frontier.\",\n );\n }\n console.log(\"\\n Review:\");\n for (const note of packet.review) console.log(` - ${note}`);\n}\n\n/**\n * The leaf, in full. The follow-up command is literal rather than a shape to\n * fill in, because the reader is usually a model cheap enough that \"the\n * appropriate verify invocation\" is a guess it will get wrong.\n */\nexport function renderNext(packet: WorkPacket, view: TasksView): void {\n const unit = packet.units[0];\n if (unit === undefined) {\n console.log(`${packet.feature} — nothing open (${packet.counts.done} done · ${packet.counts.attested} attested)`);\n header(packet, view);\n return;\n }\n console.log(`${packet.feature} — next: ${unit.id}`);\n console.log(` ${actionOf(unit, packet.feature)}`);\n // The lens only when the binding chose it: a reader who typed --service knows\n // which slice this is, and one who did not would otherwise be handed another\n // service's head with no word on why it is this one.\n if (packet.service !== null && !view.explicitLens) console.log(` ${lensLine(packet, view)}`);\n for (const warning of blindSpots(packet)) console.log(` ⚠ ${warning}`);\n const ungraded = ungradedScenario(packet, view, unit);\n if (ungraded !== undefined) console.log(` ⚠ ${ungraded}`);\n console.log(\"\");\n console.log(` [${unit.at}] ${unit.kind} [${unit.subject}]`);\n console.log(` ${unit.claim}`);\n const source = unit.source;\n if (source !== undefined) {\n console.log(` ${source.path}${source.line === undefined ? \"\" : `:${source.line}`}`);\n // Verbatim, never reflowed: these are the bytes the scenario digest was\n // taken over, and a test written from reworded criteria answers a claim\n // nobody made.\n if (\"lines\" in source) for (const body of source.lines) console.log(` ${body}`);\n }\n if (unit.dependsOn.length > 0) console.log(` depends on: ${unit.dependsOn.join(\", \")}`);\n console.log(`\\n done: ${unit.done.check}`);\n console.log(`\\n ${followUp(packet.feature, unit)}`);\n}\n\n/**\n * The caveat a scenario at `implement` needs when nobody looked for its\n * generated test: `implement` is also what a scenario reads when the stamps\n * could not be read, or belong to another repository, and handing a worker\n * \"make it pass\" for a test that was never generated sends them to write one by\n * hand — the paraphrase the generated suite exists to prevent.\n */\nfunction ungradedScenario(packet: WorkPacket, view: TasksView, unit: TaskUnit): string | undefined {\n if (unit.kind !== \"scenario.tested\" || unit.at !== \"implement\") return undefined;\n if (packet.stamps === \"read\" && unit.subject === view.bound) return undefined;\n if (unit.subject === view.bound) {\n return (\n \"whether this scenario's test was generated is unknown — this repository's generated suite could not be read; \" +\n `if loam gherkin ${packet.feature} has not run here, run it first`\n );\n }\n return (\n `whether this scenario's test was generated is unknown here — its suite lives in ${unit.subject}'s repository; ` +\n `run loam tasks there, or loam gherkin ${packet.feature} there first if it has not run`\n );\n}\n\n/**\n * The command that closes this unit.\n *\n * A `describe` unit is the one arm that is NOT a `loam verify --record`: there\n * is no claim to answer, because a requirement with no scenario asks no\n * question — the work is writing the Given/When/Then into the file named above,\n * and `loam validate --feature` is what grades that it landed. Pointing it at\n * `--record` would invite an answer to a question the checklist does not carry.\n */\nfunction followUp(feature: string, unit: TaskUnit): string {\n if (unit.at === \"describe\") return `loam validate --feature ${feature}`;\n if (unit.at === \"generate\") return `loam gherkin ${feature}`;\n if (unit.kind === \"scenario.tested\") {\n return `loam verify ${feature} --service ${unit.subject} --results report.json`;\n }\n return `loam verify ${feature} --record answers.json --service ${unit.subject}`;\n}\n\n/** What the packet could not look at — one sentence per document class. */\nfunction blindSpots(packet: WorkPacket): string[] {\n const out: string[] = [];\n if (packet.unreadable.architecture !== undefined) {\n out.push(\n `delta.likec4 does not parse (${packet.unreadable.architecture}) — no c4.calls unit could be derived, ` +\n \"so this list is short because loam could not look, not because the work is done\",\n );\n }\n const contracts = packet.unreadable.contracts;\n if (contracts !== undefined) {\n out.push(\n `contract delta unreadable for ${contracts.join(\", \")} — operations and messages are missing from this packet, ` +\n \"not absent from the feature\",\n );\n }\n return out;\n}\n"]}
@@ -0,0 +1,119 @@
1
+ import { configOrRefuse, emitJson, fail } from "../../core/envelope/json.js";
2
+ import { InvalidIdError, assertServiceId } from "../../core/kernel/ids/service.js";
3
+ import { livingServices } from "../../core/projection/arch-slice.js";
4
+ import { nearestIds } from "../../core/repo/entries.js";
5
+ import { missingFeatureMessage, resolveFeature } from "../../core/repo/repo.js";
6
+ import { workPacket } from "../../core/tasks/packet.js";
7
+ import { renderNext, renderPacket } from "./render.js";
8
+ export function registerTasks(program) {
9
+ program
10
+ .command("tasks")
11
+ .argument("<featureId>", "feature id, e.g. FEAT-101")
12
+ .description("What is still open on a feature, at which step, and what closes each unit — read-only")
13
+ .option("--service <id>", "narrow the packet to the units one service owns (a lens: no binding needed)")
14
+ .option("--next", "the frontier head alone — the single leaf to hand to a worker")
15
+ .option("--json", "emit the machine contract instead of the human view")
16
+ .action(async (featureId, opts) => {
17
+ const json = opts.json === true;
18
+ const config = await configOrRefuse(json);
19
+ if (config === null)
20
+ return;
21
+ // The id grammar first, and on the RAW argument, exactly as `loam delta`
22
+ // does: `--service ../../etc` reaches `featureSpecPaths` and reads from
23
+ // outside the feature directory. One grammar for the whole tool.
24
+ if (opts.service !== undefined) {
25
+ try {
26
+ assertServiceId(opts.service, "--service");
27
+ }
28
+ catch (err) {
29
+ if (!(err instanceof InvalidIdError))
30
+ throw err;
31
+ fail(json, "invalid-option", err.message);
32
+ return;
33
+ }
34
+ }
35
+ // "exclude", so an ARCHIVED feature gets the shared missing-feature
36
+ // message rather than a packet. This is refusal by honesty: archive merges
37
+ // a feature's operations into the living contracts, so a re-derived
38
+ // checklist over an archived feature mismatches BY CONSTRUCTION — every
39
+ // api.exposes claim it once made now reads as already-living and is never
40
+ // minted. A packet over that is not a short list, it is an invented one.
41
+ // `loam verify <id>` still reads the frozen record, and the message says so.
42
+ const feature = await resolveFeature(config.docsDir, featureId, "exclude");
43
+ if (!feature) {
44
+ fail(json, "unknown-target", await missingFeatureMessage(config.docsDir, featureId));
45
+ return;
46
+ }
47
+ // Only the flag's lens is passed. Without one, the packet narrows itself to
48
+ // the bound service when the feature touches it (`lensOf` in
49
+ // core/tasks/packet.ts says why, and why it is decided there), and
50
+ // `packet.service` is what reports the lens actually applied.
51
+ const lens = opts.service ?? null;
52
+ const packet = await workPacket({
53
+ docsDir: config.docsDir,
54
+ feature,
55
+ lens,
56
+ // `config.root`, never the cwd: loam.json discovery walks upward, and a
57
+ // run from `src/deep/` must read the same generated suite as one from
58
+ // the root. The same reasoning `loam gherkin` records for its writes.
59
+ binding: {
60
+ repoDir: config.root ?? process.cwd(),
61
+ ...(config.service === undefined ? {} : { service: config.service }),
62
+ ...(config.gherkinDir === undefined ? {} : { gherkinDir: config.gherkinDir }),
63
+ },
64
+ });
65
+ // The lens is checked AFTER the derivation, and on the packet's own
66
+ // service list, because that list is the feature's claim subjects — which
67
+ // includes a service the C4 delta introduces and no `specs/` directory
68
+ // names. Checking first would need a second LikeC4 parse of the same
69
+ // delta to learn the same answer. A typo must never be indistinguishable
70
+ // from a finished service: `--service paymnt-service` produces a
71
+ // perfectly plausible EMPTY packet, and an agent reads that as "nothing
72
+ // to do here". Only an EXPLICIT lens is checked: the bound service is
73
+ // applied only when the packet already lists it, so it cannot be a typo.
74
+ if (lens !== null && !packet.services.includes(lens)) {
75
+ const living = await livingServices(config.docsDir);
76
+ if (!living.includes(lens)) {
77
+ const near = nearestIds(lens, [...new Set([...packet.services, ...living])]);
78
+ fail(json, "unknown-target", `No service '${lens}': it is neither a services/${lens}/ in the docs repo nor a service ${feature.id} touches` +
79
+ (packet.services.length === 0 ? "" : ` (${packet.services.join(", ")})`) +
80
+ (near.length === 0 ? "." : ` — did you mean ${near.map((n) => `'${n}'`).join(" or ")}?`));
81
+ return;
82
+ }
83
+ }
84
+ // A feeder that could not be read empties the packet, and an agent
85
+ // consuming this as a task list reads an empty packet as "nothing to do":
86
+ // the vacuously-green pattern `loam delta` guards against on the same
87
+ // three documents. The payload stays as informative as ever and `ok`
88
+ // stays true under --json — the command ran — and the exit code is what
89
+ // stops a pipeline from building on it. Set BEFORE the format fork: the
90
+ // guard is about the documents, not about how they are rendered.
91
+ const blind = Object.keys(packet.unreadable).length > 0;
92
+ if (blind)
93
+ process.exitCode = 1;
94
+ const shown = opts.next === true ? leaf(packet) : packet;
95
+ if (json) {
96
+ emitJson({ command: "tasks", ...shown });
97
+ return;
98
+ }
99
+ const view = { explicitLens: opts.service !== undefined, bound: config.service };
100
+ if (opts.next === true)
101
+ renderNext(shown, view);
102
+ else
103
+ renderPacket(shown, view);
104
+ });
105
+ }
106
+ /**
107
+ * The leaf packet: the same payload with `units` narrowed to the frontier head.
108
+ *
109
+ * Everything else is left whole on purpose — the counts, the frontier and the
110
+ * review notes are the context that stops a cheap model handed one unit from
111
+ * believing it is the whole job. An empty `units` when nothing is open is the
112
+ * honest answer and not an error: the feature's open work is done, or the
113
+ * record says why the packet cannot see it.
114
+ */
115
+ function leaf(packet) {
116
+ const head = packet.frontier[0];
117
+ return { ...packet, units: packet.units.filter((unit) => unit.id === head) };
118
+ }
119
+ //# sourceMappingURL=tasks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tasks.js","sourceRoot":"","sources":["../../../src/commands/tasks/tasks.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `loam tasks` — the third rendering of one ledger, and a pure read.\n *\n * `loam verify` answers \"answered by whom\". `loam status` answers \"which\n * artifact is at which rung\". This answers the question an implementer actually\n * holds: what is still open, at which step, and what closes it. Nothing is\n * written, nothing is cached, and there is no state that says a unit is\n * finished — done is \"the unit no longer appears\", so the list cannot be\n * falsified by editing a checkbox. Everything in it re-derives from the tree, so\n * an orchestrator can ask again and compare rather than trusting a report.\n *\n * THE DOCS-REPO GATE IS DELIBERATELY ABSENT, following `loam delta` rather than\n * `loam verify`. This command is delta's sibling — a projection of ONE feature's\n * own documents — and its first act is `resolveFeature`, whose enumeration\n * carries the docs-repo precondition itself. Adding `docsRepoReady(json, …,\n * \"services\")` here would also refuse a features-only docs repo that `delta`\n * reads perfectly well today, which would be a new gate wearing the clothes of a\n * new command.\n */\nimport type { Command } from \"commander\";\nimport { configOrRefuse, emitJson, fail } from \"../../core/envelope/json.js\";\nimport { InvalidIdError, assertServiceId } from \"../../core/kernel/ids/service.js\";\nimport { livingServices } from \"../../core/projection/arch-slice.js\";\nimport { nearestIds } from \"../../core/repo/entries.js\";\nimport { missingFeatureMessage, resolveFeature } from \"../../core/repo/repo.js\";\nimport { workPacket, type WorkPacket } from \"../../core/tasks/packet.js\";\nimport { renderNext, renderPacket } from \"./render.js\";\n\ninterface TasksOptions {\n service?: string;\n next?: boolean;\n json?: boolean;\n}\n\nexport function registerTasks(program: Command): void {\n program\n .command(\"tasks\")\n .argument(\"<featureId>\", \"feature id, e.g. FEAT-101\")\n .description(\"What is still open on a feature, at which step, and what closes each unit — read-only\")\n .option(\"--service <id>\", \"narrow the packet to the units one service owns (a lens: no binding needed)\")\n .option(\"--next\", \"the frontier head alone — the single leaf to hand to a worker\")\n .option(\"--json\", \"emit the machine contract instead of the human view\")\n .action(async (featureId: string, opts: TasksOptions) => {\n const json = opts.json === true;\n const config = await configOrRefuse(json);\n if (config === null) return;\n\n // The id grammar first, and on the RAW argument, exactly as `loam delta`\n // does: `--service ../../etc` reaches `featureSpecPaths` and reads from\n // outside the feature directory. One grammar for the whole tool.\n if (opts.service !== undefined) {\n try {\n assertServiceId(opts.service, \"--service\");\n } catch (err) {\n if (!(err instanceof InvalidIdError)) throw err;\n fail(json, \"invalid-option\", err.message);\n return;\n }\n }\n\n // \"exclude\", so an ARCHIVED feature gets the shared missing-feature\n // message rather than a packet. This is refusal by honesty: archive merges\n // a feature's operations into the living contracts, so a re-derived\n // checklist over an archived feature mismatches BY CONSTRUCTION — every\n // api.exposes claim it once made now reads as already-living and is never\n // minted. A packet over that is not a short list, it is an invented one.\n // `loam verify <id>` still reads the frozen record, and the message says so.\n const feature = await resolveFeature(config.docsDir, featureId, \"exclude\");\n if (!feature) {\n fail(json, \"unknown-target\", await missingFeatureMessage(config.docsDir, featureId));\n return;\n }\n\n // Only the flag's lens is passed. Without one, the packet narrows itself to\n // the bound service when the feature touches it (`lensOf` in\n // core/tasks/packet.ts says why, and why it is decided there), and\n // `packet.service` is what reports the lens actually applied.\n const lens = opts.service ?? null;\n const packet = await workPacket({\n docsDir: config.docsDir,\n feature,\n lens,\n // `config.root`, never the cwd: loam.json discovery walks upward, and a\n // run from `src/deep/` must read the same generated suite as one from\n // the root. The same reasoning `loam gherkin` records for its writes.\n binding: {\n repoDir: config.root ?? process.cwd(),\n ...(config.service === undefined ? {} : { service: config.service }),\n ...(config.gherkinDir === undefined ? {} : { gherkinDir: config.gherkinDir }),\n },\n });\n\n // The lens is checked AFTER the derivation, and on the packet's own\n // service list, because that list is the feature's claim subjects — which\n // includes a service the C4 delta introduces and no `specs/` directory\n // names. Checking first would need a second LikeC4 parse of the same\n // delta to learn the same answer. A typo must never be indistinguishable\n // from a finished service: `--service paymnt-service` produces a\n // perfectly plausible EMPTY packet, and an agent reads that as \"nothing\n // to do here\". Only an EXPLICIT lens is checked: the bound service is\n // applied only when the packet already lists it, so it cannot be a typo.\n if (lens !== null && !packet.services.includes(lens)) {\n const living = await livingServices(config.docsDir);\n if (!living.includes(lens)) {\n const near = nearestIds(lens, [...new Set([...packet.services, ...living])]);\n fail(\n json,\n \"unknown-target\",\n `No service '${lens}': it is neither a services/${lens}/ in the docs repo nor a service ${feature.id} touches` +\n (packet.services.length === 0 ? \"\" : ` (${packet.services.join(\", \")})`) +\n (near.length === 0 ? \".\" : ` — did you mean ${near.map((n) => `'${n}'`).join(\" or \")}?`),\n );\n return;\n }\n }\n\n // A feeder that could not be read empties the packet, and an agent\n // consuming this as a task list reads an empty packet as \"nothing to do\":\n // the vacuously-green pattern `loam delta` guards against on the same\n // three documents. The payload stays as informative as ever and `ok`\n // stays true under --json — the command ran — and the exit code is what\n // stops a pipeline from building on it. Set BEFORE the format fork: the\n // guard is about the documents, not about how they are rendered.\n const blind = Object.keys(packet.unreadable).length > 0;\n if (blind) process.exitCode = 1;\n\n const shown = opts.next === true ? leaf(packet) : packet;\n if (json) {\n emitJson({ command: \"tasks\", ...shown });\n return;\n }\n const view = { explicitLens: opts.service !== undefined, bound: config.service };\n if (opts.next === true) renderNext(shown, view);\n else renderPacket(shown, view);\n });\n}\n\n/**\n * The leaf packet: the same payload with `units` narrowed to the frontier head.\n *\n * Everything else is left whole on purpose — the counts, the frontier and the\n * review notes are the context that stops a cheap model handed one unit from\n * believing it is the whole job. An empty `units` when nothing is open is the\n * honest answer and not an error: the feature's open work is done, or the\n * record says why the packet cannot see it.\n */\nfunction leaf(packet: WorkPacket): WorkPacket {\n const head = packet.frontier[0];\n return { ...packet, units: packet.units.filter((unit) => unit.id === head) };\n}\n"]}