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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (901) hide show
  1. package/CHANGELOG.md +3448 -0
  2. package/COMPARISON.md +91 -3
  3. package/CONTRIBUTING.md +37 -0
  4. package/MIGRATING-from-OpenSpec.md +47 -23
  5. package/QUICKSTART.md +189 -12
  6. package/README.md +274 -65
  7. package/ROADMAP.md +572 -31
  8. package/SCHEMA.md +1709 -155
  9. package/WORKFLOW.md +298 -72
  10. package/dist/cli.js +26 -8
  11. package/dist/cli.js.map +1 -1
  12. package/dist/commands/adopt/adopt.js +5 -10
  13. package/dist/commands/adopt/adopt.js.map +1 -1
  14. package/dist/commands/adopt/render.js +50 -9
  15. package/dist/commands/adopt/render.js.map +1 -1
  16. package/dist/commands/archive/archive.js +16 -19
  17. package/dist/commands/archive/archive.js.map +1 -1
  18. package/dist/commands/archive/closing.js +42 -0
  19. package/dist/commands/archive/closing.js.map +1 -0
  20. package/dist/commands/archive/plan/contracts/asyncapi.js +36 -42
  21. package/dist/commands/archive/plan/contracts/asyncapi.js.map +1 -1
  22. package/dist/commands/archive/plan/contracts/consumers.js +56 -0
  23. package/dist/commands/archive/plan/contracts/consumers.js.map +1 -0
  24. package/dist/commands/archive/plan/contracts/openapi.js +77 -43
  25. package/dist/commands/archive/plan/contracts/openapi.js.map +1 -1
  26. package/dist/commands/archive/plan/contracts/verdict-lines.js +103 -0
  27. package/dist/commands/archive/plan/contracts/verdict-lines.js.map +1 -0
  28. package/dist/commands/archive/plan/document/head.js +151 -0
  29. package/dist/commands/archive/plan/document/head.js.map +1 -0
  30. package/dist/commands/archive/plan/document/links.js +284 -0
  31. package/dist/commands/archive/plan/document/links.js.map +1 -0
  32. package/dist/commands/archive/plan/document/run.js +136 -0
  33. package/dist/commands/archive/plan/document/run.js.map +1 -0
  34. package/dist/commands/archive/plan/gate.js +21 -19
  35. package/dist/commands/archive/plan/gate.js.map +1 -1
  36. package/dist/commands/archive/plan/landscape.js +167 -30
  37. package/dist/commands/archive/plan/landscape.js.map +1 -1
  38. package/dist/commands/archive/plan/model/extending.js +85 -0
  39. package/dist/commands/archive/plan/model/extending.js.map +1 -0
  40. package/dist/commands/archive/plan/refusal.js +14 -19
  41. package/dist/commands/archive/plan/refusal.js.map +1 -1
  42. package/dist/commands/archive/plan/specs.js +137 -56
  43. package/dist/commands/archive/plan/specs.js.map +1 -1
  44. package/dist/commands/archive/plan/state.js +3 -0
  45. package/dist/commands/archive/plan/state.js.map +1 -1
  46. package/dist/commands/archive/run.js +134 -30
  47. package/dist/commands/archive/run.js.map +1 -1
  48. package/dist/commands/archive/shipped.js +49 -0
  49. package/dist/commands/archive/shipped.js.map +1 -0
  50. package/dist/commands/context/context.js +85 -18
  51. package/dist/commands/context/context.js.map +1 -1
  52. package/dist/commands/context/print.js +29 -7
  53. package/dist/commands/context/print.js.map +1 -1
  54. package/dist/commands/delta/delta.js +102 -14
  55. package/dist/commands/delta/delta.js.map +1 -1
  56. package/dist/commands/delta/print.js +17 -1
  57. package/dist/commands/delta/print.js.map +1 -1
  58. package/dist/commands/dependencies.js +3 -7
  59. package/dist/commands/dependencies.js.map +1 -1
  60. package/dist/commands/diff/diff.js +20 -27
  61. package/dist/commands/diff/diff.js.map +1 -1
  62. package/dist/commands/doctor.js +60 -1
  63. package/dist/commands/doctor.js.map +1 -1
  64. package/dist/commands/explain/explain.js +89 -13
  65. package/dist/commands/explain/explain.js.map +1 -1
  66. package/dist/commands/explore.js +16 -10
  67. package/dist/commands/explore.js.map +1 -1
  68. package/dist/commands/gate/gate.js +45 -8
  69. package/dist/commands/gate/gate.js.map +1 -1
  70. package/dist/commands/gate/print.js +15 -3
  71. package/dist/commands/gate/print.js.map +1 -1
  72. package/dist/commands/gherkin/commit.js +13 -54
  73. package/dist/commands/gherkin/commit.js.map +1 -1
  74. package/dist/commands/gherkin/gherkin.js +36 -20
  75. package/dist/commands/gherkin/gherkin.js.map +1 -1
  76. package/dist/commands/gherkin/reconcile.js +10 -13
  77. package/dist/commands/gherkin/reconcile.js.map +1 -1
  78. package/dist/commands/init/first-hour.js +44 -0
  79. package/dist/commands/init/first-hour.js.map +1 -1
  80. package/dist/commands/init/init.js +18 -22
  81. package/dist/commands/init/init.js.map +1 -1
  82. package/dist/commands/list/campaign/campaign.js +4 -6
  83. package/dist/commands/list/campaign/campaign.js.map +1 -1
  84. package/dist/commands/list/json.js +5 -7
  85. package/dist/commands/list/json.js.map +1 -1
  86. package/dist/commands/list/list.js +44 -29
  87. package/dist/commands/list/list.js.map +1 -1
  88. package/dist/commands/list/print.js +52 -9
  89. package/dist/commands/list/print.js.map +1 -1
  90. package/dist/commands/list/suites/suites.js +140 -0
  91. package/dist/commands/list/suites/suites.js.map +1 -0
  92. package/dist/commands/list/views.js +37 -34
  93. package/dist/commands/list/views.js.map +1 -1
  94. package/dist/commands/mcp/dispatch.js +91 -36
  95. package/dist/commands/mcp/dispatch.js.map +1 -1
  96. package/dist/commands/mcp/mcp.js +56 -15
  97. package/dist/commands/mcp/mcp.js.map +1 -1
  98. package/dist/commands/mcp/serve.js.map +1 -1
  99. package/dist/commands/migrate-openspec/materialize/active.js +27 -22
  100. package/dist/commands/migrate-openspec/materialize/active.js.map +1 -1
  101. package/dist/commands/migrate-openspec/materialize/stage.js +4 -3
  102. package/dist/commands/migrate-openspec/materialize/stage.js.map +1 -1
  103. package/dist/commands/migrate-openspec/materialize/target.js +2 -2
  104. package/dist/commands/migrate-openspec/materialize/target.js.map +1 -1
  105. package/dist/commands/migrate-openspec/openspec/decisions.js +9 -14
  106. package/dist/commands/migrate-openspec/openspec/decisions.js.map +1 -1
  107. package/dist/commands/migrate-openspec/openspec/error.js +7 -8
  108. package/dist/commands/migrate-openspec/openspec/error.js.map +1 -1
  109. package/dist/commands/migrate-openspec/openspec/mapping.js +1 -9
  110. package/dist/commands/migrate-openspec/openspec/mapping.js.map +1 -1
  111. package/dist/commands/migrate-openspec/openspec/paths.js +3 -6
  112. package/dist/commands/migrate-openspec/openspec/paths.js.map +1 -1
  113. package/dist/commands/new/capability-template.js +118 -0
  114. package/dist/commands/new/capability-template.js.map +1 -0
  115. package/dist/commands/new/commit.js +8 -22
  116. package/dist/commands/new/commit.js.map +1 -1
  117. package/dist/commands/new/modifies.js +206 -0
  118. package/dist/commands/new/modifies.js.map +1 -0
  119. package/dist/commands/new/new.js +59 -14
  120. package/dist/commands/new/new.js.map +1 -1
  121. package/dist/commands/new/templates.js +48 -124
  122. package/dist/commands/new/templates.js.map +1 -1
  123. package/dist/commands/open.js +3 -7
  124. package/dist/commands/open.js.map +1 -1
  125. package/dist/commands/policy/gate.js +27 -0
  126. package/dist/commands/policy/gate.js.map +1 -1
  127. package/dist/commands/rebase/plan.js +2 -2
  128. package/dist/commands/rebase/plan.js.map +1 -1
  129. package/dist/commands/rebase/rebase.js +60 -35
  130. package/dist/commands/rebase/rebase.js.map +1 -1
  131. package/dist/commands/seed/commit.js +55 -26
  132. package/dist/commands/seed/commit.js.map +1 -1
  133. package/dist/commands/seed/plan.js +158 -13
  134. package/dist/commands/seed/plan.js.map +1 -1
  135. package/dist/commands/seed/seed.js +13 -11
  136. package/dist/commands/seed/seed.js.map +1 -1
  137. package/dist/commands/show/feature.js +9 -5
  138. package/dist/commands/show/feature.js.map +1 -1
  139. package/dist/commands/show/introduced.js +157 -0
  140. package/dist/commands/show/introduced.js.map +1 -0
  141. package/dist/commands/show/marks.js +35 -6
  142. package/dist/commands/show/marks.js.map +1 -1
  143. package/dist/commands/show/service.js +41 -33
  144. package/dist/commands/show/service.js.map +1 -1
  145. package/dist/commands/show/show.js +17 -7
  146. package/dist/commands/show/show.js.map +1 -1
  147. package/dist/commands/status/fleet-next.js +90 -0
  148. package/dist/commands/status/fleet-next.js.map +1 -0
  149. package/dist/commands/status/json.js +2 -0
  150. package/dist/commands/status/json.js.map +1 -1
  151. package/dist/commands/status/print.js +89 -37
  152. package/dist/commands/status/print.js.map +1 -1
  153. package/dist/commands/status/status.js +3 -7
  154. package/dist/commands/status/status.js.map +1 -1
  155. package/dist/commands/steps/steps.js +103 -23
  156. package/dist/commands/steps/steps.js.map +1 -1
  157. package/dist/commands/subsystem/edit.js +7 -7
  158. package/dist/commands/subsystem/edit.js.map +1 -1
  159. package/dist/commands/subsystem/move.js +106 -46
  160. package/dist/commands/subsystem/move.js.map +1 -1
  161. package/dist/commands/subsystem/query.js +2 -4
  162. package/dist/commands/subsystem/query.js.map +1 -1
  163. package/dist/commands/subsystem/subsystem.js +4 -7
  164. package/dist/commands/subsystem/subsystem.js.map +1 -1
  165. package/dist/commands/subsystem/sync.js +289 -74
  166. package/dist/commands/subsystem/sync.js.map +1 -1
  167. package/dist/commands/subsystem/txn/exclude.js +132 -0
  168. package/dist/commands/subsystem/txn/exclude.js.map +1 -0
  169. package/dist/commands/subsystem/txn/links.js +128 -0
  170. package/dist/commands/subsystem/txn/links.js.map +1 -0
  171. package/dist/commands/subsystem/txn/report.js +174 -0
  172. package/dist/commands/subsystem/txn/report.js.map +1 -0
  173. package/dist/commands/subsystem/txn/txn.js +147 -45
  174. package/dist/commands/subsystem/txn/txn.js.map +1 -1
  175. package/dist/commands/subsystem/txn/views.js +200 -21
  176. package/dist/commands/subsystem/txn/views.js.map +1 -1
  177. package/dist/commands/tasks/actions.js +107 -0
  178. package/dist/commands/tasks/actions.js.map +1 -0
  179. package/dist/commands/tasks/render.js +253 -0
  180. package/dist/commands/tasks/render.js.map +1 -0
  181. package/dist/commands/tasks/tasks.js +119 -0
  182. package/dist/commands/tasks/tasks.js.map +1 -0
  183. package/dist/commands/unarchive/manifest.js +42 -26
  184. package/dist/commands/unarchive/manifest.js.map +1 -1
  185. package/dist/commands/unarchive/restore.js +83 -33
  186. package/dist/commands/unarchive/restore.js.map +1 -1
  187. package/dist/commands/unarchive/unarchive.js +22 -30
  188. package/dist/commands/unarchive/unarchive.js.map +1 -1
  189. package/dist/commands/validate/arch-coverage.js +78 -27
  190. package/dist/commands/validate/arch-coverage.js.map +1 -1
  191. package/dist/commands/validate/checks/fleet-shape.js +34 -126
  192. package/dist/commands/validate/checks/fleet-shape.js.map +1 -1
  193. package/dist/commands/validate/checks/health-deps.js +9 -6
  194. package/dist/commands/validate/checks/health-deps.js.map +1 -1
  195. package/dist/commands/validate/checks/introduced.js +102 -0
  196. package/dist/commands/validate/checks/introduced.js.map +1 -0
  197. package/dist/commands/validate/checks/requirements.js +18 -8
  198. package/dist/commands/validate/checks/requirements.js.map +1 -1
  199. package/dist/commands/validate/checks/sources.js +11 -2
  200. package/dist/commands/validate/checks/sources.js.map +1 -1
  201. package/dist/commands/validate/coverage/covers-after.js +105 -0
  202. package/dist/commands/validate/coverage/covers-after.js.map +1 -0
  203. package/dist/commands/validate/feature.js +26 -20
  204. package/dist/commands/validate/feature.js.map +1 -1
  205. package/dist/commands/validate/fleet/census.js +37 -13
  206. package/dist/commands/validate/fleet/census.js.map +1 -1
  207. package/dist/commands/validate/fleet/landscape.js +144 -126
  208. package/dist/commands/validate/fleet/landscape.js.map +1 -1
  209. package/dist/commands/validate/fleet/load.js +66 -0
  210. package/dist/commands/validate/fleet/load.js.map +1 -1
  211. package/dist/commands/validate/fleet/map/attest.js +98 -0
  212. package/dist/commands/validate/fleet/map/attest.js.map +1 -0
  213. package/dist/commands/validate/fleet/map/bindings.js +107 -0
  214. package/dist/commands/validate/fleet/map/bindings.js.map +1 -0
  215. package/dist/commands/validate/fleet/map/consumers.js +244 -0
  216. package/dist/commands/validate/fleet/map/consumers.js.map +1 -0
  217. package/dist/commands/validate/fleet/map/isolation.js +116 -0
  218. package/dist/commands/validate/fleet/map/isolation.js.map +1 -0
  219. package/dist/commands/validate/fleet/map/usecases.js +54 -0
  220. package/dist/commands/validate/fleet/map/usecases.js.map +1 -0
  221. package/dist/commands/validate/fleet/obligations.js +44 -14
  222. package/dist/commands/validate/fleet/obligations.js.map +1 -1
  223. package/dist/commands/validate/fleet/scorecard/print.js +10 -2
  224. package/dist/commands/validate/fleet/scorecard/print.js.map +1 -1
  225. package/dist/commands/validate/fleet/scorecard/scorecard.js +17 -11
  226. package/dist/commands/validate/fleet/scorecard/scorecard.js.map +1 -1
  227. package/dist/commands/validate/fleet/usecases/place.js.map +1 -1
  228. package/dist/commands/validate/fleet/views/fleet-project.js +217 -0
  229. package/dist/commands/validate/fleet/views/fleet-project.js.map +1 -0
  230. package/dist/commands/validate/fleet/views/ids.js +50 -15
  231. package/dist/commands/validate/fleet/views/ids.js.map +1 -1
  232. package/dist/commands/validate/fleet/views/projects.js +278 -0
  233. package/dist/commands/validate/fleet/views/projects.js.map +1 -0
  234. package/dist/commands/validate/fleet/views/root-documents.js +83 -0
  235. package/dist/commands/validate/fleet/views/root-documents.js.map +1 -0
  236. package/dist/commands/validate/fleet/views/stale.js +40 -47
  237. package/dist/commands/validate/fleet/views/stale.js.map +1 -1
  238. package/dist/commands/validate/links/corpus.js +1 -4
  239. package/dist/commands/validate/links/corpus.js.map +1 -1
  240. package/dist/commands/validate/links/glossary.js.map +1 -1
  241. package/dist/commands/validate/render/repeats.js +63 -0
  242. package/dist/commands/validate/render/repeats.js.map +1 -0
  243. package/dist/commands/validate/render/rollups.js +115 -0
  244. package/dist/commands/validate/render/rollups.js.map +1 -0
  245. package/dist/commands/validate/render/text.js +199 -0
  246. package/dist/commands/validate/render/text.js.map +1 -0
  247. package/dist/commands/validate/report.js +36 -160
  248. package/dist/commands/validate/report.js.map +1 -1
  249. package/dist/commands/validate/scope.js +113 -0
  250. package/dist/commands/validate/scope.js.map +1 -0
  251. package/dist/commands/validate/service/api.js +21 -107
  252. package/dist/commands/validate/service/api.js.map +1 -1
  253. package/dist/commands/validate/service/contracts/generated.js +134 -0
  254. package/dist/commands/validate/service/contracts/generated.js.map +1 -0
  255. package/dist/commands/validate/service/events/events.js +36 -14
  256. package/dist/commands/validate/service/events/events.js.map +1 -1
  257. package/dist/commands/validate/service/events/message-producers.js +1 -1
  258. package/dist/commands/validate/service/events/message-producers.js.map +1 -1
  259. package/dist/commands/validate/service/evidence-pins.js +56 -10
  260. package/dist/commands/validate/service/evidence-pins.js.map +1 -1
  261. package/dist/commands/validate/service/model/diverged.js +226 -0
  262. package/dist/commands/validate/service/model/diverged.js.map +1 -0
  263. package/dist/commands/validate/service/model/grade.js +163 -0
  264. package/dist/commands/validate/service/model/grade.js.map +1 -0
  265. package/dist/commands/validate/service/service.js +121 -61
  266. package/dist/commands/validate/service/service.js.map +1 -1
  267. package/dist/commands/validate/service/specs.js +88 -28
  268. package/dist/commands/validate/service/specs.js.map +1 -1
  269. package/dist/commands/validate/service/spine.js +38 -3
  270. package/dist/commands/validate/service/spine.js.map +1 -1
  271. package/dist/commands/validate/service/usecases/tags.js +113 -0
  272. package/dist/commands/validate/service/usecases/tags.js.map +1 -0
  273. package/dist/commands/validate/service/usecases/usecases.js +209 -0
  274. package/dist/commands/validate/service/usecases/usecases.js.map +1 -0
  275. package/dist/commands/validate/validate.js +85 -60
  276. package/dist/commands/validate/validate.js.map +1 -1
  277. package/dist/commands/verify/cross/diff.js +2 -6
  278. package/dist/commands/verify/cross/diff.js.map +1 -1
  279. package/dist/commands/verify/evidence/contract.js +1 -1
  280. package/dist/commands/verify/evidence/contract.js.map +1 -1
  281. package/dist/commands/verify/evidence/read.js +12 -3
  282. package/dist/commands/verify/evidence/read.js.map +1 -1
  283. package/dist/commands/verify/frozen.js +45 -23
  284. package/dist/commands/verify/frozen.js.map +1 -1
  285. package/dist/commands/verify/record.js +69 -17
  286. package/dist/commands/verify/record.js.map +1 -1
  287. package/dist/commands/verify/report.js +27 -44
  288. package/dist/commands/verify/report.js.map +1 -1
  289. package/dist/commands/verify/results.js +112 -30
  290. package/dist/commands/verify/results.js.map +1 -1
  291. package/dist/commands/verify/verify.js +55 -52
  292. package/dist/commands/verify/verify.js.map +1 -1
  293. package/dist/commands/vouch/pack/pack.js +2 -2
  294. package/dist/commands/vouch/pack/pack.js.map +1 -1
  295. package/dist/commands/vouch/pack/print.js +1 -6
  296. package/dist/commands/vouch/pack/print.js.map +1 -1
  297. package/dist/commands/vouch/pack/sections.js +1 -2
  298. package/dist/commands/vouch/pack/sections.js.map +1 -1
  299. package/dist/commands/vouch/run.js +26 -81
  300. package/dist/commands/vouch/run.js.map +1 -1
  301. package/dist/commands/vouch/sample/plan.js +20 -34
  302. package/dist/commands/vouch/sample/plan.js.map +1 -1
  303. package/dist/commands/vouch/vet/verify.js +39 -7
  304. package/dist/commands/vouch/vet/verify.js.map +1 -1
  305. package/dist/commands/vouch/vouch.js +10 -17
  306. package/dist/commands/vouch/vouch.js.map +1 -1
  307. package/dist/core/agent/agents-md/command-map.js +81 -106
  308. package/dist/core/agent/agents-md/command-map.js.map +1 -1
  309. package/dist/core/agent/agents-md/map/explain.js +21 -9
  310. package/dist/core/agent/agents-md/map/explain.js.map +1 -1
  311. package/dist/core/agent/agents-md/map/lenses/context.js +17 -8
  312. package/dist/core/agent/agents-md/map/lenses/context.js.map +1 -1
  313. package/dist/core/agent/agents-md/map/lenses/diff.js +33 -20
  314. package/dist/core/agent/agents-md/map/lenses/diff.js.map +1 -1
  315. package/dist/core/agent/agents-md/map/lenses/gate.js +13 -5
  316. package/dist/core/agent/agents-md/map/lenses/gate.js.map +1 -1
  317. package/dist/core/agent/agents-md/map/mcp.js +10 -7
  318. package/dist/core/agent/agents-md/map/mcp.js.map +1 -1
  319. package/dist/core/agent/agents-md/map/status.js +24 -8
  320. package/dist/core/agent/agents-md/map/status.js.map +1 -1
  321. package/dist/core/agent/agents-md/map/subsystem.js +80 -8
  322. package/dist/core/agent/agents-md/map/subsystem.js.map +1 -1
  323. package/dist/core/agent/agents-md/map/usecases.js +88 -10
  324. package/dist/core/agent/agents-md/map/usecases.js.map +1 -1
  325. package/dist/core/agent/agents-md/refusals.js +49 -22
  326. package/dist/core/agent/agents-md/refusals.js.map +1 -1
  327. package/dist/core/agent/agents-md.js +39 -6
  328. package/dist/core/agent/agents-md.js.map +1 -1
  329. package/dist/core/agent/agents-stamp.js +10 -0
  330. package/dist/core/agent/agents-stamp.js.map +1 -1
  331. package/dist/core/agent/protocol.js +1 -1
  332. package/dist/core/agent/protocol.js.map +1 -1
  333. package/dist/core/agent/scaffold.js +10 -15
  334. package/dist/core/agent/scaffold.js.map +1 -1
  335. package/dist/core/agent/support/report.js +46 -5
  336. package/dist/core/agent/support/report.js.map +1 -1
  337. package/dist/core/agent/tools/dialects.js +1 -0
  338. package/dist/core/agent/tools/dialects.js.map +1 -1
  339. package/dist/core/agent/tools/registry.js +41 -76
  340. package/dist/core/agent/tools/registry.js.map +1 -1
  341. package/dist/core/agent/workflows/adopt.js +158 -11
  342. package/dist/core/agent/workflows/adopt.js.map +1 -1
  343. package/dist/core/agent/workflows/check.js +78 -39
  344. package/dist/core/agent/workflows/check.js.map +1 -1
  345. package/dist/core/agent/workflows/closing.js +88 -27
  346. package/dist/core/agent/workflows/closing.js.map +1 -1
  347. package/dist/core/agent/workflows/feature.js +128 -13
  348. package/dist/core/agent/workflows/feature.js.map +1 -1
  349. package/dist/core/agent/workflows/implement.js +96 -13
  350. package/dist/core/agent/workflows/implement.js.map +1 -1
  351. package/dist/core/agent/workflows/reference/authoring.js +106 -4
  352. package/dist/core/agent/workflows/reference/authoring.js.map +1 -1
  353. package/dist/core/agent/workflows/reference/codes.js +8 -6
  354. package/dist/core/agent/workflows/reference/codes.js.map +1 -1
  355. package/dist/core/agent/workflows/reference/done-check.js +37 -15
  356. package/dist/core/agent/workflows/reference/done-check.js.map +1 -1
  357. package/dist/core/agent/workflows/reference/drawing/drawing.js +253 -0
  358. package/dist/core/agent/workflows/reference/drawing/drawing.js.map +1 -0
  359. package/dist/core/agent/workflows/reference/reference.js +6 -3
  360. package/dist/core/agent/workflows/reference/reference.js.map +1 -1
  361. package/dist/core/agent/workflows/reference/spine.js +68 -27
  362. package/dist/core/agent/workflows/reference/spine.js.map +1 -1
  363. package/dist/core/asyncapi/baseline/plan.js +14 -81
  364. package/dist/core/asyncapi/baseline/plan.js.map +1 -1
  365. package/dist/core/asyncapi/digest.js +30 -25
  366. package/dist/core/asyncapi/digest.js.map +1 -1
  367. package/dist/core/asyncapi/merge/components.js +5 -4
  368. package/dist/core/asyncapi/merge/components.js.map +1 -1
  369. package/dist/core/asyncapi/merge/error.js +7 -2
  370. package/dist/core/asyncapi/merge/error.js.map +1 -1
  371. package/dist/core/asyncapi/merge/markers.js +32 -50
  372. package/dist/core/asyncapi/merge/markers.js.map +1 -1
  373. package/dist/core/asyncapi/merge/merge.js +33 -53
  374. package/dist/core/asyncapi/merge/merge.js.map +1 -1
  375. package/dist/core/asyncapi/merge/pin.js +12 -36
  376. package/dist/core/asyncapi/merge/pin.js.map +1 -1
  377. package/dist/core/asyncapi/model.js.map +1 -1
  378. package/dist/core/asyncapi/read.js +36 -12
  379. package/dist/core/asyncapi/read.js.map +1 -1
  380. package/dist/core/brief/brief.js +96 -36
  381. package/dist/core/brief/brief.js.map +1 -1
  382. package/dist/core/brief/checks.js +138 -3
  383. package/dist/core/brief/checks.js.map +1 -1
  384. package/dist/core/brief/landscape.js +209 -130
  385. package/dist/core/brief/landscape.js.map +1 -1
  386. package/dist/core/brief/map/extend.js +84 -0
  387. package/dist/core/brief/map/extend.js.map +1 -0
  388. package/dist/core/brief/map/owed.js +266 -0
  389. package/dist/core/brief/map/owed.js.map +1 -0
  390. package/dist/core/brief/targets.js +109 -31
  391. package/dist/core/brief/targets.js.map +1 -1
  392. package/dist/core/brief/unchecked.js +14 -3
  393. package/dist/core/brief/unchecked.js.map +1 -1
  394. package/dist/core/c4/arch.js +90 -182
  395. package/dist/core/c4/arch.js.map +1 -1
  396. package/dist/core/c4/direction/direction.js +114 -0
  397. package/dist/core/c4/direction/direction.js.map +1 -0
  398. package/dist/core/c4/likec4.js +169 -14
  399. package/dist/core/c4/likec4.js.map +1 -1
  400. package/dist/core/c4/locate/unlocated.js +150 -0
  401. package/dist/core/c4/locate/unlocated.js.map +1 -0
  402. package/dist/core/c4/parsed/deployment.js +160 -0
  403. package/dist/core/c4/parsed/deployment.js.map +1 -0
  404. package/dist/core/c4/parsed/dynamic-views.js.map +1 -1
  405. package/dist/core/c4/parsed/values.js +54 -1
  406. package/dist/core/c4/parsed/values.js.map +1 -1
  407. package/dist/core/c4/parsed/view-ids.js +39 -1
  408. package/dist/core/c4/parsed/view-ids.js.map +1 -1
  409. package/dist/core/c4/prefetch/fleet.js +134 -0
  410. package/dist/core/c4/prefetch/fleet.js.map +1 -0
  411. package/dist/core/c4/project/architecture.js +123 -7
  412. package/dist/core/c4/project/architecture.js.map +1 -1
  413. package/dist/core/c4/project/batch.js +140 -0
  414. package/dist/core/c4/project/batch.js.map +1 -0
  415. package/dist/core/c4/project/documents.js +43 -12
  416. package/dist/core/c4/project/documents.js.map +1 -1
  417. package/dist/core/c4/project/load.js +79 -43
  418. package/dist/core/c4/project/load.js.map +1 -1
  419. package/dist/core/c4/project/staged.js +277 -0
  420. package/dist/core/c4/project/staged.js.map +1 -0
  421. package/dist/core/c4/resolve/attested.js +0 -0
  422. package/dist/core/c4/resolve/attested.js.map +1 -0
  423. package/dist/core/c4/resolve/external.js +51 -0
  424. package/dist/core/c4/resolve/external.js.map +1 -0
  425. package/dist/core/c4/resolve/service.js +78 -17
  426. package/dist/core/c4/resolve/service.js.map +1 -1
  427. package/dist/core/c4/resolve/steps.js +290 -0
  428. package/dist/core/c4/resolve/steps.js.map +1 -0
  429. package/dist/core/c4/resolve/systems.js +154 -0
  430. package/dist/core/c4/resolve/systems.js.map +1 -0
  431. package/dist/core/c4/root-project/exclude.js +352 -0
  432. package/dist/core/c4/root-project/exclude.js.map +1 -0
  433. package/dist/core/c4/seed/template.js +65 -1
  434. package/dist/core/c4/seed/template.js.map +1 -1
  435. package/dist/core/c4/service-model/created/models.js +96 -0
  436. package/dist/core/c4/service-model/created/models.js.map +1 -0
  437. package/dist/core/c4/service-model/documents.js +47 -0
  438. package/dist/core/c4/service-model/documents.js.map +1 -0
  439. package/dist/core/c4/service-model/fleet/extending.js +82 -0
  440. package/dist/core/c4/service-model/fleet/extending.js.map +1 -0
  441. package/dist/core/c4/service-model/load.js +165 -0
  442. package/dist/core/c4/service-model/load.js.map +1 -0
  443. package/dist/core/c4/service-model/renderer.js +128 -0
  444. package/dist/core/c4/service-model/renderer.js.map +1 -0
  445. package/dist/core/c4/service-model/shape.js +106 -0
  446. package/dist/core/c4/service-model/shape.js.map +1 -0
  447. package/dist/core/c4/service-model/slice.js +188 -0
  448. package/dist/core/c4/service-model/slice.js.map +1 -0
  449. package/dist/core/c4/source-mask.js +297 -10
  450. package/dist/core/c4/source-mask.js.map +1 -1
  451. package/dist/core/c4/source-scan.js +222 -141
  452. package/dist/core/c4/source-scan.js.map +1 -1
  453. package/dist/core/c4/splice/authored-source.js +79 -13
  454. package/dist/core/c4/splice/authored-source.js.map +1 -1
  455. package/dist/core/c4/splice/contract.js +20 -0
  456. package/dist/core/c4/splice/contract.js.map +1 -1
  457. package/dist/core/c4/splice/delta-blocks.js +20 -20
  458. package/dist/core/c4/splice/delta-blocks.js.map +1 -1
  459. package/dist/core/c4/splice/identity/declared.js +87 -0
  460. package/dist/core/c4/splice/identity/declared.js.map +1 -0
  461. package/dist/core/c4/splice/identity/edges.js +37 -0
  462. package/dist/core/c4/splice/identity/edges.js.map +1 -1
  463. package/dist/core/c4/splice/identity/existing.js +80 -0
  464. package/dist/core/c4/splice/identity/existing.js.map +1 -0
  465. package/dist/core/c4/splice/identity/interior.js +80 -0
  466. package/dist/core/c4/splice/identity/interior.js.map +1 -0
  467. package/dist/core/c4/splice/identity/owner.js +50 -0
  468. package/dist/core/c4/splice/identity/owner.js.map +1 -0
  469. package/dist/core/c4/splice/landscape-merge.js +182 -114
  470. package/dist/core/c4/splice/landscape-merge.js.map +1 -1
  471. package/dist/core/c4/splice/model/merge.js +151 -0
  472. package/dist/core/c4/splice/model/merge.js.map +1 -0
  473. package/dist/core/c4/splice/placement.js +160 -56
  474. package/dist/core/c4/splice/placement.js.map +1 -1
  475. package/dist/core/c4/splice/text/spot.js +131 -0
  476. package/dist/core/c4/splice/text/spot.js.map +1 -0
  477. package/dist/core/c4/workspace.js +13 -19
  478. package/dist/core/c4/workspace.js.map +1 -1
  479. package/dist/core/capabilities/capabilities.js +6 -6
  480. package/dist/core/capabilities/capabilities.js.map +1 -1
  481. package/dist/core/capabilities/delta/doc.js +7 -10
  482. package/dist/core/capabilities/delta/doc.js.map +1 -1
  483. package/dist/core/capabilities/delta/uncovered.js +2 -2
  484. package/dist/core/capabilities/delta/uncovered.js.map +1 -1
  485. package/dist/core/capabilities/findings.js +18 -22
  486. package/dist/core/capabilities/findings.js.map +1 -1
  487. package/dist/core/capabilities/realizes/findings.js +12 -19
  488. package/dist/core/capabilities/realizes/findings.js.map +1 -1
  489. package/dist/core/capabilities/realizes/join.js +0 -20
  490. package/dist/core/capabilities/realizes/join.js.map +1 -1
  491. package/dist/core/capabilities/rollup.js +6 -0
  492. package/dist/core/capabilities/rollup.js.map +1 -1
  493. package/dist/core/capabilities/tree.js +6 -28
  494. package/dist/core/capabilities/tree.js.map +1 -1
  495. package/dist/core/capabilities/usecase-join.js +3 -13
  496. package/dist/core/capabilities/usecase-join.js.map +1 -1
  497. package/dist/core/coherence/authoring/scaffold.js +11 -3
  498. package/dist/core/coherence/authoring/scaffold.js.map +1 -1
  499. package/dist/core/coherence/authoring/sentinels.js +2 -1
  500. package/dist/core/coherence/authoring/sentinels.js.map +1 -1
  501. package/dist/core/coherence/calls/called.js +52 -0
  502. package/dist/core/coherence/calls/called.js.map +1 -0
  503. package/dist/core/coherence/coherence.js +103 -22
  504. package/dist/core/coherence/coherence.js.map +1 -1
  505. package/dist/core/coherence/consumed/operations.js +70 -0
  506. package/dist/core/coherence/consumed/operations.js.map +1 -0
  507. package/dist/core/coherence/consumed/refusal.js +38 -0
  508. package/dist/core/coherence/consumed/refusal.js.map +1 -0
  509. package/dist/core/coherence/covers/health.js +85 -0
  510. package/dist/core/coherence/covers/health.js.map +1 -0
  511. package/dist/core/coherence/declared.js +60 -34
  512. package/dist/core/coherence/declared.js.map +1 -1
  513. package/dist/core/coherence/events/declared.js +44 -59
  514. package/dist/core/coherence/events/declared.js.map +1 -1
  515. package/dist/core/coherence/events/events.js +147 -16
  516. package/dist/core/coherence/events/events.js.map +1 -1
  517. package/dist/core/coherence/events/grades.js +31 -8
  518. package/dist/core/coherence/events/grades.js.map +1 -1
  519. package/dist/core/coherence/events/lookups.js +28 -87
  520. package/dist/core/coherence/events/lookups.js.map +1 -1
  521. package/dist/core/coherence/events/produced.js +100 -0
  522. package/dist/core/coherence/events/produced.js.map +1 -0
  523. package/dist/core/coherence/lookups.js +18 -78
  524. package/dist/core/coherence/lookups.js.map +1 -1
  525. package/dist/core/coherence/retired/archived.js +285 -0
  526. package/dist/core/coherence/retired/archived.js.map +1 -0
  527. package/dist/core/coherence/retired/event-pair.js +62 -0
  528. package/dist/core/coherence/retired/event-pair.js.map +1 -0
  529. package/dist/core/coherence/retired/merged.js +79 -0
  530. package/dist/core/coherence/retired/merged.js.map +1 -0
  531. package/dist/core/coherence/retired/retirement.js +49 -0
  532. package/dist/core/coherence/retired/retirement.js.map +1 -0
  533. package/dist/core/coherence/retired/revival/arrivals.js +131 -0
  534. package/dist/core/coherence/retired/revival/arrivals.js.map +1 -0
  535. package/dist/core/coherence/retired/revival/revived.js +297 -0
  536. package/dist/core/coherence/retired/revival/revived.js.map +1 -0
  537. package/dist/core/consumers/after.js +113 -0
  538. package/dist/core/consumers/after.js.map +1 -0
  539. package/dist/core/consumers/consumers.js +296 -0
  540. package/dist/core/consumers/consumers.js.map +1 -0
  541. package/dist/core/consumers/current.js +211 -0
  542. package/dist/core/consumers/current.js.map +1 -0
  543. package/dist/core/consumers/scan.js +46 -0
  544. package/dist/core/consumers/scan.js.map +1 -0
  545. package/dist/core/consumers/state.js +27 -0
  546. package/dist/core/consumers/state.js.map +1 -0
  547. package/dist/core/delta/delta.js +51 -6
  548. package/dist/core/delta/delta.js.map +1 -1
  549. package/dist/core/dependencies/fanin.js +2 -2
  550. package/dist/core/dependencies/fanin.js.map +1 -1
  551. package/dist/core/deployment/delta.js +191 -0
  552. package/dist/core/deployment/delta.js.map +1 -0
  553. package/dist/core/deployment/objects.js +145 -0
  554. package/dist/core/deployment/objects.js.map +1 -0
  555. package/dist/core/diff/base-git.js +94 -12
  556. package/dist/core/diff/base-git.js.map +1 -1
  557. package/dist/core/diff/base-state.js +49 -21
  558. package/dist/core/diff/base-state.js.map +1 -1
  559. package/dist/core/diff/joins.js +136 -0
  560. package/dist/core/diff/joins.js.map +1 -0
  561. package/dist/core/diff/scope/changed-paths.js +22 -6
  562. package/dist/core/diff/scope/changed-paths.js.map +1 -1
  563. package/dist/core/diff/scope/edges.js +82 -0
  564. package/dist/core/diff/scope/edges.js.map +1 -0
  565. package/dist/core/diff/semantic.js +100 -31
  566. package/dist/core/diff/semantic.js.map +1 -1
  567. package/dist/core/docs.js +31 -22
  568. package/dist/core/docs.js.map +1 -1
  569. package/dist/core/doctor/agents.js +34 -18
  570. package/dist/core/doctor/agents.js.map +1 -1
  571. package/dist/core/doctor/config.js +7 -3
  572. package/dist/core/doctor/config.js.map +1 -1
  573. package/dist/core/doctor/doctor.js +91 -11
  574. package/dist/core/doctor/doctor.js.map +1 -1
  575. package/dist/core/doctor/report.js.map +1 -1
  576. package/dist/core/doctor/reports/scan.js +242 -0
  577. package/dist/core/doctor/reports/scan.js.map +1 -0
  578. package/dist/core/document/apply.js +158 -11
  579. package/dist/core/document/apply.js.map +1 -1
  580. package/dist/core/document/frontmatter.js +55 -0
  581. package/dist/core/document/frontmatter.js.map +1 -1
  582. package/dist/core/document/parse.js +29 -6
  583. package/dist/core/document/parse.js.map +1 -1
  584. package/dist/core/document/scenarios.js +17 -0
  585. package/dist/core/document/scenarios.js.map +1 -1
  586. package/dist/core/document/spec.js +4 -11
  587. package/dist/core/document/spec.js.map +1 -1
  588. package/dist/core/envelope/config.js +10 -0
  589. package/dist/core/envelope/config.js.map +1 -1
  590. package/dist/core/envelope/json.js +34 -0
  591. package/dist/core/envelope/json.js.map +1 -1
  592. package/dist/core/explain/families.js +26 -21
  593. package/dist/core/explain/families.js.map +1 -1
  594. package/dist/core/explain/lookup.js +14 -1
  595. package/dist/core/explain/lookup.js.map +1 -1
  596. package/dist/core/explain/refusals.js +5 -5
  597. package/dist/core/explain/refusals.js.map +1 -1
  598. package/dist/core/explain/terms/documents.js +227 -0
  599. package/dist/core/explain/terms/documents.js.map +1 -0
  600. package/dist/core/explain/terms/done-check.js +144 -0
  601. package/dist/core/explain/terms/done-check.js.map +1 -0
  602. package/dist/core/explain/terms/entry.js +14 -0
  603. package/dist/core/explain/terms/entry.js.map +1 -0
  604. package/dist/core/explain/terms/stages.js +71 -0
  605. package/dist/core/explain/terms/stages.js.map +1 -0
  606. package/dist/core/explain/terms/tasks.js +97 -0
  607. package/dist/core/explain/terms/tasks.js.map +1 -0
  608. package/dist/core/explain/terms.js +68 -109
  609. package/dist/core/explain/terms.js.map +1 -1
  610. package/dist/core/explore/explore.js +40 -10
  611. package/dist/core/explore/explore.js.map +1 -1
  612. package/dist/core/fleet-context.js +81 -95
  613. package/dist/core/fleet-context.js.map +1 -1
  614. package/dist/core/gate/checks.js +11 -4
  615. package/dist/core/gate/checks.js.map +1 -1
  616. package/dist/core/gate/partners.js +69 -28
  617. package/dist/core/gate/partners.js.map +1 -1
  618. package/dist/core/gate/report.js.map +1 -1
  619. package/dist/core/gate/verification.js +75 -12
  620. package/dist/core/gate/verification.js.map +1 -1
  621. package/dist/core/gherkin/stale.js +13 -37
  622. package/dist/core/gherkin/stale.js.map +1 -1
  623. package/dist/core/glossary/delta.js +10 -7
  624. package/dist/core/glossary/delta.js.map +1 -1
  625. package/dist/core/glossary/tree.js +6 -19
  626. package/dist/core/glossary/tree.js.map +1 -1
  627. package/dist/core/kernel/concurrency.js +19 -0
  628. package/dist/core/kernel/concurrency.js.map +1 -1
  629. package/dist/core/kernel/ids/fqn/ancestors.js +65 -0
  630. package/dist/core/kernel/ids/fqn/ancestors.js.map +1 -0
  631. package/dist/core/kernel/path-safety.js +38 -0
  632. package/dist/core/kernel/path-safety.js.map +1 -1
  633. package/dist/core/kernel/records.js +11 -0
  634. package/dist/core/kernel/records.js.map +1 -1
  635. package/dist/core/links/backlinks.js +1 -3
  636. package/dist/core/links/backlinks.js.map +1 -1
  637. package/dist/core/links/corpus.js +51 -37
  638. package/dist/core/links/corpus.js.map +1 -1
  639. package/dist/core/links/findings.js.map +1 -1
  640. package/dist/core/links/parse.js +38 -9
  641. package/dist/core/links/parse.js.map +1 -1
  642. package/dist/core/mcp/argv.js +101 -0
  643. package/dist/core/mcp/argv.js.map +1 -1
  644. package/dist/core/mcp/author-tools.js +2 -1
  645. package/dist/core/mcp/author-tools.js.map +1 -1
  646. package/dist/core/mcp/protocol.js +2 -2
  647. package/dist/core/mcp/protocol.js.map +1 -1
  648. package/dist/core/mcp/tools.js +43 -33
  649. package/dist/core/mcp/tools.js.map +1 -1
  650. package/dist/core/openapi/baseline/gate.js +53 -12
  651. package/dist/core/openapi/baseline/gate.js.map +1 -1
  652. package/dist/core/openapi/baseline/plan.js +40 -10
  653. package/dist/core/openapi/baseline/plan.js.map +1 -1
  654. package/dist/core/openapi/baseline/record.js +0 -1
  655. package/dist/core/openapi/baseline/record.js.map +1 -1
  656. package/dist/core/openapi/contract-text.js +33 -0
  657. package/dist/core/openapi/contract-text.js.map +1 -0
  658. package/dist/core/openapi/contract-tree.js +301 -0
  659. package/dist/core/openapi/contract-tree.js.map +1 -0
  660. package/dist/core/openapi/depth.js +38 -24
  661. package/dist/core/openapi/depth.js.map +1 -1
  662. package/dist/core/openapi/digest.js +52 -2
  663. package/dist/core/openapi/digest.js.map +1 -1
  664. package/dist/core/openapi/doc.js +12 -4
  665. package/dist/core/openapi/doc.js.map +1 -1
  666. package/dist/core/openapi/merge/components.js +25 -60
  667. package/dist/core/openapi/merge/components.js.map +1 -1
  668. package/dist/core/openapi/merge/error.js +3 -13
  669. package/dist/core/openapi/merge/error.js.map +1 -1
  670. package/dist/core/openapi/merge/markers.js +26 -30
  671. package/dist/core/openapi/merge/markers.js.map +1 -1
  672. package/dist/core/openapi/merge/merge.js +28 -52
  673. package/dist/core/openapi/merge/merge.js.map +1 -1
  674. package/dist/core/openapi/merge/pin.js +17 -35
  675. package/dist/core/openapi/merge/pin.js.map +1 -1
  676. package/dist/core/openspec/decide/verdict.js.map +1 -1
  677. package/dist/core/openspec/inventory.js +4 -5
  678. package/dist/core/openspec/inventory.js.map +1 -1
  679. package/dist/core/openspec/model/mapping.js +30 -28
  680. package/dist/core/openspec/model/mapping.js.map +1 -1
  681. package/dist/core/openspec/model/model.js +12 -7
  682. package/dist/core/openspec/model/model.js.map +1 -1
  683. package/dist/core/openspec/scan/changes.js +10 -4
  684. package/dist/core/openspec/scan/changes.js.map +1 -1
  685. package/dist/core/openspec/scan/config.js +7 -16
  686. package/dist/core/openspec/scan/config.js.map +1 -1
  687. package/dist/core/openspec/scan/shape.js +63 -19
  688. package/dist/core/openspec/scan/shape.js.map +1 -1
  689. package/dist/core/openspec/scan/walk.js +21 -38
  690. package/dist/core/openspec/scan/walk.js.map +1 -1
  691. package/dist/core/pack/living.js +43 -4
  692. package/dist/core/pack/living.js.map +1 -1
  693. package/dist/core/pack/pack.js +50 -6
  694. package/dist/core/pack/pack.js.map +1 -1
  695. package/dist/core/projection/arch-slice.js +2 -2
  696. package/dist/core/projection/arch-slice.js.map +1 -1
  697. package/dist/core/projection/introduced.js +14 -0
  698. package/dist/core/projection/introduced.js.map +1 -0
  699. package/dist/core/provenance/findings.js +48 -12
  700. package/dist/core/provenance/findings.js.map +1 -1
  701. package/dist/core/provenance/git.js +33 -57
  702. package/dist/core/provenance/git.js.map +1 -1
  703. package/dist/core/provenance/gitq/moves.js +71 -114
  704. package/dist/core/provenance/gitq/moves.js.map +1 -1
  705. package/dist/core/provenance/gitq/vouched-ancestor.js +2 -2
  706. package/dist/core/provenance/gitq/vouched-ancestor.js.map +1 -1
  707. package/dist/core/provenance/sources.js +23 -6
  708. package/dist/core/provenance/sources.js.map +1 -1
  709. package/dist/core/provenance/stamp.js +5 -17
  710. package/dist/core/provenance/stamp.js.map +1 -1
  711. package/dist/core/repo/authored/paths.js +18 -0
  712. package/dist/core/repo/authored/paths.js.map +1 -1
  713. package/dist/core/repo/entries.js.map +1 -1
  714. package/dist/core/repo/paths.js +92 -6
  715. package/dist/core/repo/paths.js.map +1 -1
  716. package/dist/core/repo/repo.js +74 -14
  717. package/dist/core/repo/repo.js.map +1 -1
  718. package/dist/core/repo/tree/find.js +12 -3
  719. package/dist/core/repo/tree/find.js.map +1 -1
  720. package/dist/core/repo/tree/fs.js +27 -1
  721. package/dist/core/repo/tree/fs.js.map +1 -1
  722. package/dist/core/repo/tree/render/body.js +258 -0
  723. package/dist/core/repo/tree/render/body.js.map +1 -0
  724. package/dist/core/repo/tree/render/projects.js +182 -0
  725. package/dist/core/repo/tree/render/projects.js.map +1 -0
  726. package/dist/core/repo/tree/render/service/header.js +125 -0
  727. package/dist/core/repo/tree/render/service/header.js.map +1 -0
  728. package/dist/core/repo/tree/render/service/peers.js +28 -0
  729. package/dist/core/repo/tree/render/service/peers.js.map +1 -0
  730. package/dist/core/repo/tree/render/service/view-id.js +67 -0
  731. package/dist/core/repo/tree/render/service/view-id.js.map +1 -0
  732. package/dist/core/repo/tree/render/service/views.js +78 -0
  733. package/dist/core/repo/tree/render/service/views.js.map +1 -0
  734. package/dist/core/repo/tree/render/stale.js +42 -0
  735. package/dist/core/repo/tree/render/stale.js.map +1 -0
  736. package/dist/core/repo/tree/render/text.js +84 -0
  737. package/dist/core/repo/tree/render/text.js.map +1 -0
  738. package/dist/core/repo/tree/render/views.js +293 -0
  739. package/dist/core/repo/tree/render/views.js.map +1 -0
  740. package/dist/core/repo/tree/walk.js +53 -32
  741. package/dist/core/repo/tree/walk.js.map +1 -1
  742. package/dist/core/results.js +47 -12
  743. package/dist/core/results.js.map +1 -1
  744. package/dist/core/scaffold/landscape.js +121 -13
  745. package/dist/core/scaffold/landscape.js.map +1 -1
  746. package/dist/core/scaffold/legacy.js +271 -0
  747. package/dist/core/scaffold/legacy.js.map +1 -0
  748. package/dist/core/staging/commit.js +26 -15
  749. package/dist/core/staging/commit.js.map +1 -1
  750. package/dist/core/staging/lock.js +74 -12
  751. package/dist/core/staging/lock.js.map +1 -1
  752. package/dist/core/staging/recovery/intent.js +2 -5
  753. package/dist/core/staging/recovery/intent.js.map +1 -1
  754. package/dist/core/staging/recovery/recover.js +84 -6
  755. package/dist/core/staging/recovery/recover.js.map +1 -1
  756. package/dist/core/staging/snapshot/manifest.js +188 -0
  757. package/dist/core/staging/snapshot/manifest.js.map +1 -0
  758. package/dist/core/staging/{snapshot.js → snapshot/snapshot.js} +39 -45
  759. package/dist/core/staging/snapshot/snapshot.js.map +1 -0
  760. package/dist/core/staging/txn/forward.js +24 -14
  761. package/dist/core/staging/txn/forward.js.map +1 -1
  762. package/dist/core/staging/writes.js.map +1 -1
  763. package/dist/core/status/actions/execution.js +11 -0
  764. package/dist/core/status/actions/execution.js.map +1 -1
  765. package/dist/core/status/contracts.js +39 -15
  766. package/dist/core/status/contracts.js.map +1 -1
  767. package/dist/core/status/feature/artifacts.js +33 -8
  768. package/dist/core/status/feature/artifacts.js.map +1 -1
  769. package/dist/core/status/feature/feature.js +24 -17
  770. package/dist/core/status/feature/feature.js.map +1 -1
  771. package/dist/core/status/feature/next.js +20 -7
  772. package/dist/core/status/feature/next.js.map +1 -1
  773. package/dist/core/status/feature/words.js +96 -0
  774. package/dist/core/status/feature/words.js.map +1 -0
  775. package/dist/core/status/fleet/fleet.js +43 -14
  776. package/dist/core/status/fleet/fleet.js.map +1 -1
  777. package/dist/core/status/fleet/next.js +153 -58
  778. package/dist/core/status/fleet/next.js.map +1 -1
  779. package/dist/core/status/report.js.map +1 -1
  780. package/dist/core/status/scan.js.map +1 -1
  781. package/dist/core/status/verification.js +30 -15
  782. package/dist/core/status/verification.js.map +1 -1
  783. package/dist/core/tasks/packet.js +199 -0
  784. package/dist/core/tasks/packet.js.map +1 -0
  785. package/dist/core/tasks/record.js +43 -0
  786. package/dist/core/tasks/record.js.map +1 -0
  787. package/dist/core/tasks/sources.js +181 -0
  788. package/dist/core/tasks/sources.js.map +1 -0
  789. package/dist/core/tasks/stamps.js +76 -0
  790. package/dist/core/tasks/stamps.js.map +1 -0
  791. package/dist/core/tasks/unit.js +0 -0
  792. package/dist/core/tasks/unit.js.map +1 -0
  793. package/dist/core/usecases/capability.js +11 -14
  794. package/dist/core/usecases/capability.js.map +1 -1
  795. package/dist/core/usecases/delta/claims.js +31 -7
  796. package/dist/core/usecases/delta/claims.js.map +1 -1
  797. package/dist/core/usecases/delta/flows.js +5 -7
  798. package/dist/core/usecases/delta/flows.js.map +1 -1
  799. package/dist/core/usecases/delta/modified.js +315 -0
  800. package/dist/core/usecases/delta/modified.js.map +1 -0
  801. package/dist/core/usecases/delta/overlay.js +32 -191
  802. package/dist/core/usecases/delta/overlay.js.map +1 -1
  803. package/dist/core/usecases/fleet.js +195 -36
  804. package/dist/core/usecases/fleet.js.map +1 -1
  805. package/dist/{commands/validate/fleet/usecases → core/usecases/grade}/capability-tag.js +8 -9
  806. package/dist/core/usecases/grade/capability-tag.js.map +1 -0
  807. package/dist/core/usecases/grade/feature.js +88 -0
  808. package/dist/core/usecases/grade/feature.js.map +1 -0
  809. package/dist/{commands/validate/fleet/usecases → core/usecases/grade}/requirement-tag.js +3 -4
  810. package/dist/core/usecases/grade/requirement-tag.js.map +1 -0
  811. package/dist/{commands/validate/fleet/usecases → core/usecases/grade}/steps.js +102 -33
  812. package/dist/core/usecases/grade/steps.js.map +1 -0
  813. package/dist/{commands/validate/fleet/usecases → core/usecases/grade}/usecases.js +23 -10
  814. package/dist/core/usecases/grade/usecases.js.map +1 -0
  815. package/dist/core/usecases/operations.js +26 -14
  816. package/dist/core/usecases/operations.js.map +1 -1
  817. package/dist/core/usecases/place.js.map +1 -1
  818. package/dist/core/usecases/service/exclude.js +119 -0
  819. package/dist/core/usecases/service/exclude.js.map +1 -0
  820. package/dist/core/usecases/service/flows.js +164 -0
  821. package/dist/core/usecases/service/flows.js.map +1 -0
  822. package/dist/core/usecases/suites/participants.js +83 -0
  823. package/dist/core/usecases/suites/participants.js.map +1 -0
  824. package/dist/core/usecases/suites/suites.js +45 -0
  825. package/dist/core/usecases/suites/suites.js.map +1 -0
  826. package/dist/core/verify/answers.js +12 -5
  827. package/dist/core/verify/answers.js.map +1 -1
  828. package/dist/core/verify/build.js +102 -82
  829. package/dist/core/verify/build.js.map +1 -1
  830. package/dist/core/verify/checklist.js +70 -12
  831. package/dist/core/verify/checklist.js.map +1 -1
  832. package/dist/core/verify/location.js +67 -0
  833. package/dist/core/verify/location.js.map +1 -0
  834. package/dist/core/verify/pins/lint.js +3 -2
  835. package/dist/core/verify/pins/lint.js.map +1 -1
  836. package/dist/core/verify/pins/pin.js +1 -1
  837. package/dist/core/verify/pins/pin.js.map +1 -1
  838. package/dist/core/verify/read/file.js +224 -0
  839. package/dist/core/verify/read/file.js.map +1 -0
  840. package/dist/core/verify/{file.js → read/shape.js} +16 -104
  841. package/dist/core/verify/read/shape.js.map +1 -0
  842. package/dist/core/verify/read/union.js +105 -0
  843. package/dist/core/verify/read/union.js.map +1 -0
  844. package/dist/core/verify/record.js +35 -12
  845. package/dist/core/verify/record.js.map +1 -1
  846. package/dist/core/verify/store/commit.js +40 -30
  847. package/dist/core/verify/store/commit.js.map +1 -1
  848. package/dist/core/verify/store/render.js +8 -4
  849. package/dist/core/verify/store/render.js.map +1 -1
  850. package/dist/core/vocabulary/issue.js +4 -0
  851. package/dist/core/vocabulary/issue.js.map +1 -1
  852. package/dist/core/vocabulary/maturity.js +75 -4
  853. package/dist/core/vocabulary/maturity.js.map +1 -1
  854. package/dist/core/vocabulary/report.js +16 -1
  855. package/dist/core/vocabulary/report.js.map +1 -1
  856. package/examples/README.md +54 -11
  857. package/examples/docs/architecture/landscape.likec4 +62 -6
  858. package/examples/docs/architecture/services.likec4 +70 -0
  859. package/examples/docs/architecture/subsystems.likec4 +7 -0
  860. package/examples/docs/architecture/usecases/order-notification.likec4 +16 -7
  861. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-service/asyncapi.yaml +11 -8
  862. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/openapi.yaml +6 -6
  863. package/examples/docs/features/FEAT-112-retire-order-v1/specs/order-service/openapi.yaml +4 -1
  864. package/examples/docs/features/archive/FEAT-088-refunds/specs/payment-service/openapi.yaml +13 -10
  865. package/examples/docs/likec4.config.json +0 -1
  866. package/examples/docs/services/checkout-web/model.likec4 +39 -56
  867. package/examples/docs/services/order-service/arch.spec.md +13 -6
  868. package/examples/docs/services/order-service/asyncapi.yaml +3 -2
  869. package/examples/docs/services/order-service/model.likec4 +58 -70
  870. package/examples/docs/services/payment-service/arch.spec.md +7 -4
  871. package/examples/docs/services/payment-service/model.likec4 +38 -37
  872. package/examples/docs/services/platform/identity-service/arch.spec.md +7 -4
  873. package/examples/docs/services/platform/identity-service/model.likec4 +35 -37
  874. package/examples/docs/services/platform/notification-service/asyncapi.yaml +2 -1
  875. package/examples/docs/services/platform/notification-service/health.yaml +8 -3
  876. package/examples/docs/services/platform/notification-service/model.likec4 +43 -64
  877. package/package.json +1 -1
  878. package/dist/commands/validate/checks/vocabulary.js +0 -31
  879. package/dist/commands/validate/checks/vocabulary.js.map +0 -1
  880. package/dist/commands/validate/fleet/usecases/capability-tag.js.map +0 -1
  881. package/dist/commands/validate/fleet/usecases/requirement-tag.js.map +0 -1
  882. package/dist/commands/validate/fleet/usecases/steps.js.map +0 -1
  883. package/dist/commands/validate/fleet/usecases/usecases.js.map +0 -1
  884. package/dist/core/agent/agents-md/artifacts.js +0 -220
  885. package/dist/core/agent/agents-md/artifacts.js.map +0 -1
  886. package/dist/core/agent/agents-md/cycle.js +0 -165
  887. package/dist/core/agent/agents-md/cycle.js.map +0 -1
  888. package/dist/core/agent/agents-md/shipped/archive-gate.js +0 -98
  889. package/dist/core/agent/agents-md/shipped/archive-gate.js.map +0 -1
  890. package/dist/core/agent/agents-md/spine.js +0 -40
  891. package/dist/core/agent/agents-md/spine.js.map +0 -1
  892. package/dist/core/coherence/events/merged.js +0 -40
  893. package/dist/core/coherence/events/merged.js.map +0 -1
  894. package/dist/core/diff/current-state.js +0 -96
  895. package/dist/core/diff/current-state.js.map +0 -1
  896. package/dist/core/diff/victims.js +0 -247
  897. package/dist/core/diff/victims.js.map +0 -1
  898. package/dist/core/repo/tree/views.js +0 -172
  899. package/dist/core/repo/tree/views.js.map +0 -1
  900. package/dist/core/staging/snapshot.js.map +0 -1
  901. package/dist/core/verify/file.js.map +0 -1
@@ -1,4 +1,18 @@
1
- /** Building one service's slice: the delta brief, generated gherkin, steps, code, verify. */
1
+ /**
2
+ * Building one service's slice: the delta brief, then a unit at a time —
3
+ * generated gherkin, steps, code, verify.
4
+ *
5
+ * Steps 3-5 are a LOOP, not a sequence, and that is why `loam tasks` sits at
6
+ * the head of them. They used to be three things done in order — generate the
7
+ * suite, write the definitions, implement — which is only the right order for a
8
+ * slice whose every requirement already owns a scenario. Where one does not,
9
+ * the next thing owed is a sentence in the docs repo, and the body had no step
10
+ * that could say so; where the suite is half written, nothing here answered
11
+ * which half. `at` answers both: the projection names which of four states the
12
+ * next unit is in, and each state names exactly one action, so the numbering
13
+ * below is a table of destinations rather than an itinerary. An editor adding a
14
+ * step must therefore say which `at` value routes to it, or it is unreachable.
15
+ */
2
16
  export const LOAM_IMPLEMENT = {
3
17
  name: "loam-implement",
4
18
  description: "Implement a loam feature's slice for one service — generated gherkin first, tests from it, then code",
@@ -10,6 +24,7 @@ export const LOAM_IMPLEMENT = {
10
24
  "`loam status` — where this feature actually is, and what is owed before you start",
11
25
  "`loam context` — the briefing: the service's living slice, and every delta in flight over it",
12
26
  "`loam delta` — the task: the intent, every requirement verbatim, the endpoints, and the calls in and out",
27
+ "`loam tasks` — the open units, ordered; `--next` is the single next unit, with the scenario verbatim and the fact that closes it",
13
28
  "`loam gherkin` in the service's repo — the digest-stamped `.feature` files. Never edit them",
14
29
  "write step definitions for the generated scenarios first, outside the generated directory",
15
30
  "implement until the suite passes, running it with a JSON report",
@@ -18,7 +33,8 @@ export const LOAM_IMPLEMENT = {
18
33
  ],
19
34
  body: `Implement one service's part of a feature. Every step runs in the SERVICE'S own
20
35
  repository, which needs its own committed ./loam.json — if there is none,
21
- \`loam init --docs <path-to-docs-repo> --service $2\` then \`loam doctor\` first.
36
+ \`loam init --docs <path-to-docs-repo> --service $2 --agent-profile service\` then
37
+ \`loam doctor\` first.
22
38
 
23
39
  0. \`loam status $1 --json\` — where this feature actually is. Run it before
24
40
  anything else if you joined halfway or lost the session: it says which
@@ -59,12 +75,65 @@ repository, which needs its own committed ./loam.json — if there is none,
59
75
  document before building anything — for the delta, \`loam validate $1 --json\` names
60
76
  the error; the contract delta is not graded by validate, so read the parser message
61
77
  the payload carries.
62
- 3. In the service's repo, \`loam gherkin $1 --json\` — one \`.feature\` file per changed
63
- requirement lands under \`<gherkinDir>/loam/\` (default \`features/loam/\`), scenarios
64
- digest-stamped, arch requirements tagged \`@architecture\`. Those files ARE the
65
- acceptance criteria. Never edit them: regeneration rewrites the directory, and
66
- \`loam validate\` reports the suite stale by digest, not by your intentions.
67
- 4. Write step definitions for the generated scenarios FIRST — outside \`loam/\`.
78
+ 3. \`loam tasks $1 --service $2 --next --json\` — ONE unit of work, and the loop
79
+ every step below runs inside. Step 2 is the whole brief; this is the next thing
80
+ to do in it. It writes nothing: the projection is derived from the verify
81
+ checklist, the delta scans, the feature's verification record and — in this,
82
+ the bound service repo — the digest stamps in the generated \`.feature\` files.
83
+ Drop \`--next\` to see every open unit instead of only the head.
84
+ Each entry of \`units[]\` carries its \`id\` (the same id the verify checklist uses
85
+ for that claim), \`kind\` (\`service.exists\`, \`api.exposes\`, \`event.declares\`,
86
+ \`c4.calls\`, \`scenario.tested\` or \`requirement.described\`), \`subject\`, \`claim\`,
87
+ \`digest\`, \`dependsOn\`, \`source\` — the path, line, requirement and scenario it was
88
+ derived from, with the scenario's own \`lines\` verbatim — and \`done.check\`.
89
+
90
+ \`at\` is the instruction. It says what the unit NEEDS, and each of its four
91
+ values names exactly one action:
92
+ - \`describe\` — the requirement owns no scenarios yet. Write the Given/When/Then
93
+ in the DOCS repo, on the requirement \`source\` names, and nothing else. loam
94
+ does not author, and no amount of code closes a unit sitting here.
95
+ - \`generate\` — no stamped \`.feature\` carries this scenario's digest. The only
96
+ action is \`loam gherkin $1\` in this repo (step 4). Do not write code.
97
+ - \`implement\` — the stamped scenario exists and no recorded run has confirmed
98
+ it. Write step definitions outside \`loam/\`, implement until the suite passes,
99
+ then \`loam verify $1 --service $2 --results report.json\` (step 5).
100
+ - \`attested\` — the claim was closed on somebody's word rather than on a run.
101
+ Run the suite and re-record it so it stops resting on an assertion. An
102
+ agent-attested scenario stays visible at \`attested\` forever, deliberately: it
103
+ is the one state that cannot be made to go away by ignoring it.
104
+
105
+ \`done.check\` is the FACT that closes the unit, and the RUNNER decides whether
106
+ that fact holds — never your own reading of the code you just wrote. Done means
107
+ the unit no longer appears, and it stops appearing only once its claim is
108
+ recorded confirmed in a verification record that is not stale. So re-run
109
+ \`loam tasks $1 --service $2 --json\` after every recording instead of working
110
+ down a list you copied out: \`frontier\` (the first ten open unit ids, in order)
111
+ and \`counts\` (\`open\`, \`done\`, \`attested\`) are recomputed from the documents on
112
+ every run, which is what makes taking the head of it always safe.
113
+ \`checklist\` is the digest of the question set the whole projection derives from.
114
+ If it differs from the one you started against, the question set moved under
115
+ you — re-read the feature before continuing, because what you closed earlier may
116
+ not be what is being asked now.
117
+ \`record\` says whether the answers were found at all (\`absent\`, \`recorded\`,
118
+ \`stale\`, \`unreadable\`) and \`stamps\` whether this repo's generated suite could be
119
+ read (\`read\`, \`unknown\`); an \`unknown\` makes every \`generate\` verdict a guess,
120
+ so fix the binding before acting on one. \`contracts\` restates step 6 as data
121
+ (\`expose[]\` and \`call[]\`), \`size\` the shape of the packet, \`review[]\` what a
122
+ reviewer of it will read, and \`waitingOn\` — whenever the packet is narrowed to one
123
+ service: by \`--service\`, or without it to this repo's own service when the feature
124
+ touches it — what another service still owes before your frontier can move.
125
+ Exit 1 with \`ok: true\` is step 2's rule again: delta.likec4 or one of the
126
+ contract axes did not parse, so the projection is SHORT by everything that
127
+ document would have contributed. Fix the document; do not work the units that
128
+ happened to survive it.
129
+ 4. \`at: "generate"\` — in the service's repo, \`loam gherkin $1 --json\`. One
130
+ \`.feature\` file per changed requirement lands under \`<gherkinDir>/loam/\`
131
+ (default \`features/loam/\`), scenarios digest-stamped, arch requirements tagged
132
+ \`@architecture\`. Those files ARE the acceptance criteria. Never edit them:
133
+ regeneration rewrites the directory, and \`loam validate\` reports the suite stale
134
+ by digest, not by your intentions. Generating is the WHOLE action for a unit at
135
+ \`generate\`: go back to step 3, where the same unit now reads \`implement\`.
136
+ 5. \`at: "implement"\` — step definitions FIRST, outside \`loam/\`, then the code.
68
137
  Do not paraphrase a scenario into something easier to pass; it is the acceptance
69
138
  criterion someone else reviews against.
70
139
  Run \`loam steps --service $2 --json\` before you write any: it collapses every
@@ -75,14 +144,26 @@ repository, which needs its own committed ./loam.json — if there is none,
75
144
  and regenerate, rather than writing the second definition.
76
145
  A step's argument arrives as an argument: a \`"""\` docstring is the payload, an
77
146
  indented table is a DataTable. Assert against them; do not re-parse the step text.
78
- 5. Implement until the suite passes — run it with a JSON report
79
- (\`cucumber-js --format json:report.json\`):
147
+ Then implement until the suite passes — run it with a JSON report
148
+ (\`cucumber-js --format json:report.json\`; cucumber-jvm, behave, Reqnroll,
149
+ pytest-bdd \`--cucumberjson\` and godog write the same cucumber JSON):
80
150
  \`loam verify $1 --service $2 --results report.json\` consumes that report as the
81
- done-check's answer sheet. Record from THIS repo, with \`--service\` — the
151
+ done-check's answer sheet. A runner with no cucumber formatter answers through
152
+ loam's runner-neutral shape instead, keyed by each scenario's \`@loam-digest\`
153
+ tag — adapting the runner's report into it is a build step you own:
154
+ \`{"loamScenarioReport": 1, "results": [{"digest": "<16 hex>", "status": "passed"}]}\`.
155
+ A cucumber run must have run every step of the stamped scenario: a report
156
+ entry whose step count differs is not that scenario's run and stays
157
+ unconfirmed. Record from THIS repo, with \`--service\` — the
82
158
  \`--service\`-less \`--record\` form writes the whole record from one place and is
83
- refused (\`record-federated\`) once another service has attested.
159
+ refused (\`record-federated\`) once another service has attested. Recording is what
160
+ closes the unit, so step 3 is the command AFTER it, not the end of the run.
84
161
  6. Honour the contract: every operation in \`architecture.inbound\` must exist under
85
162
  exactly that operationId, and every one in \`architecture.outbound\` must be called.
163
+ The code you just wrote is evidence about the delta's edges. If an edge the
164
+ feature draws as \`connects\` is in fact a publish, a delivery, a read or a write,
165
+ redraw it in delta.likec4 with that kind (\`loam instructions loam-drawing\`) —
166
+ and step 7 applies, because that is a change to the feature's documents.
86
167
  7. If building made you change the feature's documents at all — a requirement's
87
168
  wording, an operation in its openapi.yaml — **\`loam rebase $1\`** before you
88
169
  validate. Every edit you make in the docs repo while other features are in
@@ -99,7 +180,9 @@ repository, which needs its own committed ./loam.json — if there is none,
99
180
  8. \`loam validate --feature $1 --json\` before handing back.
100
181
 
101
182
  If the requirement is ambiguous, say so and stop — do not invent behaviour and
102
- leave the spec disagreeing with the code.
183
+ leave the spec disagreeing with the code. Write the question under
184
+ \`## Open questions\` in the feature's \`intent.md\`, where loam-feature's analyze
185
+ step put the ones it found, so a person answers it once for every service.
103
186
  `,
104
187
  };
105
188
  //# sourceMappingURL=implement.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"implement.js","sourceRoot":"","sources":["../../../../src/core/agent/workflows/implement.ts"],"names":[],"mappings":"AAEA,6FAA6F;AAC7F,MAAM,CAAC,MAAM,cAAc,GAAmB;IAC5C,IAAI,EAAE,gBAAgB;IACtB,WAAW,EACT,sGAAsG;IACxG,YAAY,EAAE,qBAAqB;IACnC,OAAO,EACL,oMAAoM;IACtM,UAAU,EAAE,wCAAwC;IACpD,YAAY,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC;IACpC,KAAK,EAAE;QACL,mFAAmF;QACnF,8FAA8F;QAC9F,0GAA0G;QAC1G,6FAA6F;QAC7F,2FAA2F;QAC3F,iEAAiE;QACjE,iGAAiG;QACjG,qGAAqG;KACtG;IACD,IAAI,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoFP;CACA,CAAC","sourcesContent":["import type { CommandContent } from \"../contract.js\";\n\n/** Building one service's slice: the delta brief, generated gherkin, steps, code, verify. */\nexport const LOAM_IMPLEMENT: CommandContent = {\n name: \"loam-implement\",\n description:\n \"Implement a loam feature's slice for one service — generated gherkin first, tests from it, then code\",\n argumentHint: \"<FEAT-id> [service]\",\n purpose:\n \"Build one service's part of a feature, in that service's own repository. The generated Gherkin is the acceptance criterion — it comes before the step definitions, and those come before the code.\",\n invocation: \"loam instructions loam-implement $1 $2\",\n placeholders: [\"feature\", \"service\"],\n spine: [\n \"`loam status` — where this feature actually is, and what is owed before you start\",\n \"`loam context` — the briefing: the service's living slice, and every delta in flight over it\",\n \"`loam delta` — the task: the intent, every requirement verbatim, the endpoints, and the calls in and out\",\n \"`loam gherkin` in the service's repo — the digest-stamped `.feature` files. Never edit them\",\n \"write step definitions for the generated scenarios first, outside the generated directory\",\n \"implement until the suite passes, running it with a JSON report\",\n \"honour the contract in both directions: expose every inbound operation, call every outbound one\",\n \"`loam rebase` if building made you change the feature's documents at all, then validate the feature\",\n ],\n body: `Implement one service's part of a feature. Every step runs in the SERVICE'S own\nrepository, which needs its own committed ./loam.json — if there is none,\n\\`loam init --docs <path-to-docs-repo> --service $2\\` then \\`loam doctor\\` first.\n\n0. \\`loam status $1 --json\\` — where this feature actually is. Run it before\n anything else if you joined halfway or lost the session: it says which\n artifacts are still owed, whether another feature has to archive first, and\n what the next step is, each \\`next[]\\` entry carrying the literal command. It\n writes nothing, so it is always safe to re-run.\n1. \\`loam context $2 --feature $1 --json\\` — the briefing to load before touching\n code: the service's living requirements and arch requirements verbatim, its\n operations and messages as they stand today, the permissions and capabilities\n its requirements join to, the fleet edges around it, and this feature's delta\n over it (\\`--feature $1\\` narrows the in-flight section; drop it to see every\n feature working over this service). The delta below is WHAT CHANGES; the pack\n is what it changes INTO — read it first so a MODIFIED requirement lands as an\n edit rather than a rewrite, and an operation you are about to add is caught\n when the living contract already defines it. Exit 1 with \\`ok: true\\` means a\n document behind the pack did not parse; the empty section beside the flag is\n the parse failure, not \"nothing here\".\n2. \\`loam delta $1 --service $2 --json\\` (drop \\`--service\\` to use the service configured\n in ./loam.json). That output IS the task:\n - \\`intent\\` — why this exists\n - \\`requirements[]\\` — what to build, with \\`scenarios[].lines\\` verbatim\n - \\`archRequirements[]\\` — the architectural obligations (outbox, retries, alerts),\n same shape; their scenarios become integration/ops tests, and \\`covers\\` names\n the model objects each exercises\n - \\`architecture\\` — whether this service is new, and the calls in and out of it\n - \\`api\\` — the endpoints this feature adds or retires for this service: path,\n method, operationId and summary, with removals spelled \\`REMOVE <METHOD> <path>\\`\n - \\`openapi\\` — whether that contract could be read at all: \\`unreadable\\`, plus an\n \\`error\\` when the parser gave a message. It rides beside \\`api\\` rather than\n inside it because \\`api\\` stays the operations array it has always been, and it\n is what tells an empty \\`api\\` apart from a contract delta that did not parse\n - \\`services\\` — every service this feature projects onto, so a run without\n \\`--service\\` tells you which ones to ask for rather than guessing\n Exit 1 with \\`ok: true\\` means one of the two authored documents behind this brief\n did not parse: \\`architecture.errors\\` non-empty (delta.likec4), or\n \\`openapi.unreadable\\` true (the feature's openapi.yaml for this service). The empty\n slice is the parse failure itself, not \"nothing changes there\". Stop and fix that\n document before building anything — for the delta, \\`loam validate $1 --json\\` names\n the error; the contract delta is not graded by validate, so read the parser message\n the payload carries.\n3. In the service's repo, \\`loam gherkin $1 --json\\` — one \\`.feature\\` file per changed\n requirement lands under \\`<gherkinDir>/loam/\\` (default \\`features/loam/\\`), scenarios\n digest-stamped, arch requirements tagged \\`@architecture\\`. Those files ARE the\n acceptance criteria. Never edit them: regeneration rewrites the directory, and\n \\`loam validate\\` reports the suite stale by digest, not by your intentions.\n4. Write step definitions for the generated scenarios FIRST — outside \\`loam/\\`.\n Do not paraphrase a scenario into something easier to pass; it is the acceptance\n criterion someone else reviews against.\n Run \\`loam steps --service $2 --json\\` before you write any: it collapses every\n written step onto the phrase a definition actually matches, so you see the size\n of the registry you owe and which phrases already exist. Write ONE definition per\n phrase row. If \\`nearDuplicates\\` is non-empty, two rows differ by an article or a\n trailing \\`because …\\` clause and one definition was meant — fix the SPEC's wording\n and regenerate, rather than writing the second definition.\n A step's argument arrives as an argument: a \\`\"\"\"\\` docstring is the payload, an\n indented table is a DataTable. Assert against them; do not re-parse the step text.\n5. Implement until the suite passes — run it with a JSON report\n (\\`cucumber-js --format json:report.json\\`):\n \\`loam verify $1 --service $2 --results report.json\\` consumes that report as the\n done-check's answer sheet. Record from THIS repo, with \\`--service\\` — the\n \\`--service\\`-less \\`--record\\` form writes the whole record from one place and is\n refused (\\`record-federated\\`) once another service has attested.\n6. Honour the contract: every operation in \\`architecture.inbound\\` must exist under\n exactly that operationId, and every one in \\`architecture.outbound\\` must be called.\n7. If building made you change the feature's documents at all — a requirement's\n wording, an operation in its openapi.yaml — **\\`loam rebase $1\\`** before you\n validate. Every edit you make in the docs repo while other features are in\n flight is written against a living document that may have moved since the\n feature directory was created, and the pins are the only thing that lets the\n merge tell an EDIT from a QUOTE — for operations, path-level keys and\n components alike. \\`delta.baseline-missing\\` and\n \\`openapi.baseline-missing\\` are the warnings that say you skipped it — archive\n refuses on them until you rebase (or a human \\`--approve\\`s the unpinned merge);\n \\`delta.baseline-stale\\` / \\`openapi.baseline-stale\\` are archive refusing because\n somebody landed a change underneath you — re-read theirs, fold in what you\n still mean, then rebase again. Re-pinning without re-reading is how you\n overwrite someone else's requirement with loam's blessing.\n8. \\`loam validate --feature $1 --json\\` before handing back.\n\nIf the requirement is ambiguous, say so and stop — do not invent behaviour and\nleave the spec disagreeing with the code.\n`,\n};\n"]}
1
+ {"version":3,"file":"implement.js","sourceRoot":"","sources":["../../../../src/core/agent/workflows/implement.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,cAAc,GAAmB;IAC5C,IAAI,EAAE,gBAAgB;IACtB,WAAW,EACT,sGAAsG;IACxG,YAAY,EAAE,qBAAqB;IACnC,OAAO,EACL,oMAAoM;IACtM,UAAU,EAAE,wCAAwC;IACpD,YAAY,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC;IACpC,KAAK,EAAE;QACL,mFAAmF;QACnF,8FAA8F;QAC9F,0GAA0G;QAC1G,kIAAkI;QAClI,6FAA6F;QAC7F,2FAA2F;QAC3F,iEAAiE;QACjE,iGAAiG;QACjG,qGAAqG;KACtG;IACD,IAAI,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwJP;CACA,CAAC","sourcesContent":["import type { CommandContent } from \"../contract.js\";\n\n/**\n * Building one service's slice: the delta brief, then a unit at a time —\n * generated gherkin, steps, code, verify.\n *\n * Steps 3-5 are a LOOP, not a sequence, and that is why `loam tasks` sits at\n * the head of them. They used to be three things done in order — generate the\n * suite, write the definitions, implement — which is only the right order for a\n * slice whose every requirement already owns a scenario. Where one does not,\n * the next thing owed is a sentence in the docs repo, and the body had no step\n * that could say so; where the suite is half written, nothing here answered\n * which half. `at` answers both: the projection names which of four states the\n * next unit is in, and each state names exactly one action, so the numbering\n * below is a table of destinations rather than an itinerary. An editor adding a\n * step must therefore say which `at` value routes to it, or it is unreachable.\n */\nexport const LOAM_IMPLEMENT: CommandContent = {\n name: \"loam-implement\",\n description:\n \"Implement a loam feature's slice for one service — generated gherkin first, tests from it, then code\",\n argumentHint: \"<FEAT-id> [service]\",\n purpose:\n \"Build one service's part of a feature, in that service's own repository. The generated Gherkin is the acceptance criterion — it comes before the step definitions, and those come before the code.\",\n invocation: \"loam instructions loam-implement $1 $2\",\n placeholders: [\"feature\", \"service\"],\n spine: [\n \"`loam status` — where this feature actually is, and what is owed before you start\",\n \"`loam context` — the briefing: the service's living slice, and every delta in flight over it\",\n \"`loam delta` — the task: the intent, every requirement verbatim, the endpoints, and the calls in and out\",\n \"`loam tasks` — the open units, ordered; `--next` is the single next unit, with the scenario verbatim and the fact that closes it\",\n \"`loam gherkin` in the service's repo — the digest-stamped `.feature` files. Never edit them\",\n \"write step definitions for the generated scenarios first, outside the generated directory\",\n \"implement until the suite passes, running it with a JSON report\",\n \"honour the contract in both directions: expose every inbound operation, call every outbound one\",\n \"`loam rebase` if building made you change the feature's documents at all, then validate the feature\",\n ],\n body: `Implement one service's part of a feature. Every step runs in the SERVICE'S own\nrepository, which needs its own committed ./loam.json — if there is none,\n\\`loam init --docs <path-to-docs-repo> --service $2 --agent-profile service\\` then\n\\`loam doctor\\` first.\n\n0. \\`loam status $1 --json\\` — where this feature actually is. Run it before\n anything else if you joined halfway or lost the session: it says which\n artifacts are still owed, whether another feature has to archive first, and\n what the next step is, each \\`next[]\\` entry carrying the literal command. It\n writes nothing, so it is always safe to re-run.\n1. \\`loam context $2 --feature $1 --json\\` — the briefing to load before touching\n code: the service's living requirements and arch requirements verbatim, its\n operations and messages as they stand today, the permissions and capabilities\n its requirements join to, the fleet edges around it, and this feature's delta\n over it (\\`--feature $1\\` narrows the in-flight section; drop it to see every\n feature working over this service). The delta below is WHAT CHANGES; the pack\n is what it changes INTO — read it first so a MODIFIED requirement lands as an\n edit rather than a rewrite, and an operation you are about to add is caught\n when the living contract already defines it. Exit 1 with \\`ok: true\\` means a\n document behind the pack did not parse; the empty section beside the flag is\n the parse failure, not \"nothing here\".\n2. \\`loam delta $1 --service $2 --json\\` (drop \\`--service\\` to use the service configured\n in ./loam.json). That output IS the task:\n - \\`intent\\` — why this exists\n - \\`requirements[]\\` — what to build, with \\`scenarios[].lines\\` verbatim\n - \\`archRequirements[]\\` — the architectural obligations (outbox, retries, alerts),\n same shape; their scenarios become integration/ops tests, and \\`covers\\` names\n the model objects each exercises\n - \\`architecture\\` — whether this service is new, and the calls in and out of it\n - \\`api\\` — the endpoints this feature adds or retires for this service: path,\n method, operationId and summary, with removals spelled \\`REMOVE <METHOD> <path>\\`\n - \\`openapi\\` — whether that contract could be read at all: \\`unreadable\\`, plus an\n \\`error\\` when the parser gave a message. It rides beside \\`api\\` rather than\n inside it because \\`api\\` stays the operations array it has always been, and it\n is what tells an empty \\`api\\` apart from a contract delta that did not parse\n - \\`services\\` — every service this feature projects onto, so a run without\n \\`--service\\` tells you which ones to ask for rather than guessing\n Exit 1 with \\`ok: true\\` means one of the two authored documents behind this brief\n did not parse: \\`architecture.errors\\` non-empty (delta.likec4), or\n \\`openapi.unreadable\\` true (the feature's openapi.yaml for this service). The empty\n slice is the parse failure itself, not \"nothing changes there\". Stop and fix that\n document before building anything — for the delta, \\`loam validate $1 --json\\` names\n the error; the contract delta is not graded by validate, so read the parser message\n the payload carries.\n3. \\`loam tasks $1 --service $2 --next --json\\` — ONE unit of work, and the loop\n every step below runs inside. Step 2 is the whole brief; this is the next thing\n to do in it. It writes nothing: the projection is derived from the verify\n checklist, the delta scans, the feature's verification record and — in this,\n the bound service repo — the digest stamps in the generated \\`.feature\\` files.\n Drop \\`--next\\` to see every open unit instead of only the head.\n Each entry of \\`units[]\\` carries its \\`id\\` (the same id the verify checklist uses\n for that claim), \\`kind\\` (\\`service.exists\\`, \\`api.exposes\\`, \\`event.declares\\`,\n \\`c4.calls\\`, \\`scenario.tested\\` or \\`requirement.described\\`), \\`subject\\`, \\`claim\\`,\n \\`digest\\`, \\`dependsOn\\`, \\`source\\` — the path, line, requirement and scenario it was\n derived from, with the scenario's own \\`lines\\` verbatim — and \\`done.check\\`.\n\n \\`at\\` is the instruction. It says what the unit NEEDS, and each of its four\n values names exactly one action:\n - \\`describe\\` — the requirement owns no scenarios yet. Write the Given/When/Then\n in the DOCS repo, on the requirement \\`source\\` names, and nothing else. loam\n does not author, and no amount of code closes a unit sitting here.\n - \\`generate\\` — no stamped \\`.feature\\` carries this scenario's digest. The only\n action is \\`loam gherkin $1\\` in this repo (step 4). Do not write code.\n - \\`implement\\` — the stamped scenario exists and no recorded run has confirmed\n it. Write step definitions outside \\`loam/\\`, implement until the suite passes,\n then \\`loam verify $1 --service $2 --results report.json\\` (step 5).\n - \\`attested\\` — the claim was closed on somebody's word rather than on a run.\n Run the suite and re-record it so it stops resting on an assertion. An\n agent-attested scenario stays visible at \\`attested\\` forever, deliberately: it\n is the one state that cannot be made to go away by ignoring it.\n\n \\`done.check\\` is the FACT that closes the unit, and the RUNNER decides whether\n that fact holds — never your own reading of the code you just wrote. Done means\n the unit no longer appears, and it stops appearing only once its claim is\n recorded confirmed in a verification record that is not stale. So re-run\n \\`loam tasks $1 --service $2 --json\\` after every recording instead of working\n down a list you copied out: \\`frontier\\` (the first ten open unit ids, in order)\n and \\`counts\\` (\\`open\\`, \\`done\\`, \\`attested\\`) are recomputed from the documents on\n every run, which is what makes taking the head of it always safe.\n \\`checklist\\` is the digest of the question set the whole projection derives from.\n If it differs from the one you started against, the question set moved under\n you — re-read the feature before continuing, because what you closed earlier may\n not be what is being asked now.\n \\`record\\` says whether the answers were found at all (\\`absent\\`, \\`recorded\\`,\n \\`stale\\`, \\`unreadable\\`) and \\`stamps\\` whether this repo's generated suite could be\n read (\\`read\\`, \\`unknown\\`); an \\`unknown\\` makes every \\`generate\\` verdict a guess,\n so fix the binding before acting on one. \\`contracts\\` restates step 6 as data\n (\\`expose[]\\` and \\`call[]\\`), \\`size\\` the shape of the packet, \\`review[]\\` what a\n reviewer of it will read, and \\`waitingOn\\` — whenever the packet is narrowed to one\n service: by \\`--service\\`, or without it to this repo's own service when the feature\n touches it — what another service still owes before your frontier can move.\n Exit 1 with \\`ok: true\\` is step 2's rule again: delta.likec4 or one of the\n contract axes did not parse, so the projection is SHORT by everything that\n document would have contributed. Fix the document; do not work the units that\n happened to survive it.\n4. \\`at: \"generate\"\\` — in the service's repo, \\`loam gherkin $1 --json\\`. One\n \\`.feature\\` file per changed requirement lands under \\`<gherkinDir>/loam/\\`\n (default \\`features/loam/\\`), scenarios digest-stamped, arch requirements tagged\n \\`@architecture\\`. Those files ARE the acceptance criteria. Never edit them:\n regeneration rewrites the directory, and \\`loam validate\\` reports the suite stale\n by digest, not by your intentions. Generating is the WHOLE action for a unit at\n \\`generate\\`: go back to step 3, where the same unit now reads \\`implement\\`.\n5. \\`at: \"implement\"\\` — step definitions FIRST, outside \\`loam/\\`, then the code.\n Do not paraphrase a scenario into something easier to pass; it is the acceptance\n criterion someone else reviews against.\n Run \\`loam steps --service $2 --json\\` before you write any: it collapses every\n written step onto the phrase a definition actually matches, so you see the size\n of the registry you owe and which phrases already exist. Write ONE definition per\n phrase row. If \\`nearDuplicates\\` is non-empty, two rows differ by an article or a\n trailing \\`because …\\` clause and one definition was meant — fix the SPEC's wording\n and regenerate, rather than writing the second definition.\n A step's argument arrives as an argument: a \\`\"\"\"\\` docstring is the payload, an\n indented table is a DataTable. Assert against them; do not re-parse the step text.\n Then implement until the suite passes — run it with a JSON report\n (\\`cucumber-js --format json:report.json\\`; cucumber-jvm, behave, Reqnroll,\n pytest-bdd \\`--cucumberjson\\` and godog write the same cucumber JSON):\n \\`loam verify $1 --service $2 --results report.json\\` consumes that report as the\n done-check's answer sheet. A runner with no cucumber formatter answers through\n loam's runner-neutral shape instead, keyed by each scenario's \\`@loam-digest\\`\n tag — adapting the runner's report into it is a build step you own:\n \\`{\"loamScenarioReport\": 1, \"results\": [{\"digest\": \"<16 hex>\", \"status\": \"passed\"}]}\\`.\n A cucumber run must have run every step of the stamped scenario: a report\n entry whose step count differs is not that scenario's run and stays\n unconfirmed. Record from THIS repo, with \\`--service\\` — the\n \\`--service\\`-less \\`--record\\` form writes the whole record from one place and is\n refused (\\`record-federated\\`) once another service has attested. Recording is what\n closes the unit, so step 3 is the command AFTER it, not the end of the run.\n6. Honour the contract: every operation in \\`architecture.inbound\\` must exist under\n exactly that operationId, and every one in \\`architecture.outbound\\` must be called.\n The code you just wrote is evidence about the delta's edges. If an edge the\n feature draws as \\`connects\\` is in fact a publish, a delivery, a read or a write,\n redraw it in delta.likec4 with that kind (\\`loam instructions loam-drawing\\`) —\n and step 7 applies, because that is a change to the feature's documents.\n7. If building made you change the feature's documents at all — a requirement's\n wording, an operation in its openapi.yaml — **\\`loam rebase $1\\`** before you\n validate. Every edit you make in the docs repo while other features are in\n flight is written against a living document that may have moved since the\n feature directory was created, and the pins are the only thing that lets the\n merge tell an EDIT from a QUOTE — for operations, path-level keys and\n components alike. \\`delta.baseline-missing\\` and\n \\`openapi.baseline-missing\\` are the warnings that say you skipped it — archive\n refuses on them until you rebase (or a human \\`--approve\\`s the unpinned merge);\n \\`delta.baseline-stale\\` / \\`openapi.baseline-stale\\` are archive refusing because\n somebody landed a change underneath you — re-read theirs, fold in what you\n still mean, then rebase again. Re-pinning without re-reading is how you\n overwrite someone else's requirement with loam's blessing.\n8. \\`loam validate --feature $1 --json\\` before handing back.\n\nIf the requirement is ambiguous, say so and stop — do not invent behaviour and\nleave the spec disagreeing with the code. Write the question under\n\\`## Open questions\\` in the feature's \\`intent.md\\`, where loam-feature's analyze\nstep put the ones it found, so a person answers it once for every service.\n`,\n};\n"]}
@@ -1,18 +1,19 @@
1
1
  export const LOAM_AUTHORING = {
2
2
  name: "loam-authoring",
3
- description: "Reference: the grammars you author against — arch.spec.md, the generated Gherkin suite, frontmatter",
3
+ description: "Reference: the grammars you author against — arch.spec.md, the generated Gherkin suite, frontmatter, and writing a feature a person can follow",
4
4
  // No arguments: one document, printed whole. See ./spine.ts for why the hint
5
5
  // is empty rather than a spelled-out "<none>".
6
6
  argumentHint: "",
7
- purpose: "What each document you author by hand must contain: the architecture requirements axis and its `Covers:` line, how scenarios become an executable suite, and the frontmatter fields `loam vouch` stamps.",
7
+ purpose: "What each document you author by hand must contain: the architecture requirements axis and its `Covers:` line, how scenarios become an executable suite, the frontmatter fields `loam vouch` stamps, and how to write a feature's documents so a reviewer can follow them.",
8
8
  invocation: "loam instructions loam-authoring",
9
9
  placeholders: [],
10
10
  spine: [
11
11
  "The architecture spec axis",
12
12
  "The generated Gherkin suite",
13
13
  "Frontmatter — who vouched for this, and from what",
14
+ "Writing for a person",
14
15
  ],
15
- body: `The grammars you author against: the architecture spec axis, the generated Gherkin suite, and frontmatter.
16
+ body: `The grammars you author against: the architecture spec axis, the generated Gherkin suite, frontmatter, and writing a feature a person can follow.
16
17
 
17
18
  ## The architecture spec axis
18
19
 
@@ -161,7 +162,9 @@ the forgery — editing a spec after it was vouched used to leave \`status: veri
161
162
  standing over words nobody read. \`loam validate\` recomputes it wherever it can
162
163
  read the doc (no service repo needed, so it fires from the docs repo too) and
163
164
  reports \`content.stale\` (warn): only a person can say whether verified still
164
- holds of the new words.
165
+ holds of the new words. The fleet readouts say the same: \`loam list\` shows
166
+ \`vouched (stale)\` and owes the row a re-vouch, and \`loam status\` emits
167
+ \`next.revouch\` — a step for a person, never for you.
165
168
 
166
169
  \`vouch_scope\` appears only when the person vouched after reading a SAMPLE of the
167
170
  document — \`loam vouch --sample <n>\`, whose whole purpose is that a partial read
@@ -204,6 +207,105 @@ exists for a person's own scripted run; typing it on someone's behalf is
204
207
  writing their name. The generated command and skill files pre-approve loam's
205
208
  read-only and authoring verbs one by one and deliberately not this one: when
206
209
  the work is done, hand back and say a vouch is owed.
210
+
211
+ ## Writing for a person
212
+
213
+ A feature is read by a reviewer before anyone builds it, and its requirements
214
+ are read for years after \`loam archive\` copies them into the living docs. loam
215
+ grades the joins and never the prose, so nothing in this section is checked: a
216
+ delta can validate clean and still be one nobody can follow.
217
+
218
+ **intent.md** opens with the problem in business terms — \`## Why\` and
219
+ \`## Scope\`, the two sections the archive gate reads — and then carries the three
220
+ things a reviewer looks for first:
221
+
222
+ - \`## How to read this feature\`: two or three sentences saying which services
223
+ change, which document to open first, and which picture shows the change (the
224
+ delta's own view, or a flow under the feature's \`usecases/\`).
225
+ - a business-requirement coverage table, one row per business requirement the
226
+ feature was asked to meet, naming what keeps it:
227
+
228
+ | Business requirement | Kept by | Where |
229
+ |---|---|---|
230
+ | A customer can split one payment between two cards | PAY-SPLIT-1 | payment-split-service spec.md |
231
+ | Every payee gets a receipt | uc_split_receipt | usecases/split-receipt.likec4 |
232
+
233
+ - \`## Open questions\` (the scaffold already writes the heading) as a table, so
234
+ that a person can answer each question and a reader can see what each blocks:
235
+
236
+ | ID | Question | Blocks | Owner | Current default |
237
+ |---|---|---|---|---|
238
+ | Q1 | Is a split refunded per card or as a whole? | PAY-SPLIT-3 | payments-team | per card |
239
+
240
+ The current default is what gets built if nobody answers, so write one for
241
+ every question.
242
+
243
+ **Each spec delta opens with a plain-language \`## Purpose\`**: what the service
244
+ does in this change, written for someone who has never opened its code. Where
245
+ the delta CREATES the living document — a new service's spec.md, a first
246
+ arch.spec.md, a new capability — \`loam archive\` copies that section into the
247
+ new document as its narrative. Where the living document already exists, the
248
+ section stays with the archived delta, and the archive plan says so on that
249
+ file's line; if the service's own narrative should change, edit the living
250
+ document in the same change.
251
+
252
+ **Write a long requirement body as a lead and bullets.** A new requirement
253
+ states one behaviour. A requirement carried over from another source often
254
+ arrives as one paragraph of SHALL sentences. Keep every sentence, but open with
255
+ one line that says what the requirement is for, and give each SHALL sentence a
256
+ bullet of its own:
257
+
258
+ ### Requirement: Split a payment
259
+ Requirement-ID: PAY-SPLIT-1
260
+
261
+ A payment can be divided between several payees.
262
+
263
+ - The service SHALL accept between two and five payees per split.
264
+ - The service SHALL reject a split whose shares do not add up to the authorized amount.
265
+
266
+ **Expand every abbreviation the first time a document uses it**, in words a new
267
+ reader knows: "service-level objective (SLO)", then "SLO".
268
+
269
+ **Keep review-time wording out of what the archive copies.** "This delta", "this
270
+ feature", "the new endpoint" and "we now" read correctly in review. But
271
+ \`loam archive\` copies requirement bodies, scenarios and contract descriptions
272
+ into living documents, where "this feature" points at a pull request that merged
273
+ long ago. Write what the service does, not what the change does. Prose about the
274
+ change belongs in \`intent.md\`, which stays with the feature.
275
+
276
+ **A feature's vocabulary, decisions and flows travel with it.**
277
+
278
+ - A word the feature brings is \`features/<FEAT>/glossary/<term>.md\`, which the
279
+ archive copies into \`glossary/\`. A term the living glossary already defines is
280
+ edited there instead, because the copy never overwrites
281
+ (\`glossary.term-exists\`).
282
+ - A decision is \`features/<FEAT>/adrs/NNNN-<slug>.md\`. It stays with the
283
+ feature under \`features/archive/\`, and the living documents that link to it go
284
+ on resolving. A decision meant to outlive the change belongs in
285
+ \`architecture/adrs/\` or the service's own \`adrs/\` instead.
286
+ - A flow that keeps a promise across services is
287
+ \`features/<FEAT>/usecases/<name>.likec4\`: a \`dynamic view\` tagged
288
+ \`#cap-<capability>\`, naming a capability the fleet declares, and
289
+ \`#req-<Requirement-ID>\`, naming the promise it keeps. A promise the feature's
290
+ own capability delta adds resolves too. \`usecase.capability-unresolved\` and
291
+ \`usecase.requirement-unresolved\` grade both tags before the archive.
292
+
293
+ Link to all three from the deltas, written relative to the file you write in:
294
+ \`loam archive\` re-points every link into the feature for the move.
295
+
296
+ **Write a \`Covers:\` edge by service name**:
297
+ \`Covers: order-service -> payment-service\`. An edge spelled by its endpoints'
298
+ service names resolves the same before and after the archive. A delta's own
299
+ element id may not, and \`covers.unknown\` at feature scope says when it would not.
300
+ A kinded spelling such as \`order-service -[calls]-> payment-service\` is accepted,
301
+ but the kind is read past rather than compared: it covers every edge from the
302
+ first service to the second, whatever its kind. So write the plain arrow.
303
+
304
+ **Draw a producer outside the fleet as an \`#external\` element**, with the edge
305
+ it publishes on carrying \`metadata { publishes }\`, so that the consumer's
306
+ \`Consumes:\` line has a producer to join to. \`loam instructions loam-spine\`
307
+ ("A message produced outside the fleet") has the join, and
308
+ \`loam instructions loam-drawing\` has the drawing.
207
309
  `,
208
310
  };
209
311
  //# sourceMappingURL=authoring.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"authoring.js","sourceRoot":"","sources":["../../../../../src/core/agent/workflows/reference/authoring.ts"],"names":[],"mappings":"AAgBA,MAAM,CAAC,MAAM,cAAc,GAAmB;IAC5C,IAAI,EAAE,gBAAgB;IACtB,WAAW,EACT,qGAAqG;IACvG,6EAA6E;IAC7E,+CAA+C;IAC/C,YAAY,EAAE,EAAE;IAChB,OAAO,EACL,0MAA0M;IAC5M,UAAU,EAAE,kCAAkC;IAC9C,YAAY,EAAE,EAAE;IAChB,KAAK,EAAE;QACL,4BAA4B;QAC5B,6BAA6B;QAC7B,mDAAmD;KACpD;IACD,IAAI,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgMP;CACA,CAAC","sourcesContent":["/**\n * The `loam-authoring` reference page: the grammars of the documents you write.\n *\n * The architecture spec axis (`arch.spec.md` and its `Covers:` line), the\n * generated Gherkin suite, and the frontmatter/vouch chain that ties a\n * document to the code it was written from.\n *\n * All three are consulted at a moment you can name — while authoring one file\n * — and none of them is needed to form the question. That is the split this\n * page exists to make; ./reference.ts records why it had to be made at all.\n *\n * The text is the three AGENTS.md sections verbatim, in their original order,\n * so a cross-reference elsewhere in the corpus still names the same headings.\n */\nimport type { CommandContent } from \"../../contract.js\";\n\nexport const LOAM_AUTHORING: CommandContent = {\n name: \"loam-authoring\",\n description:\n \"Reference: the grammars you author against — arch.spec.md, the generated Gherkin suite, frontmatter\",\n // No arguments: one document, printed whole. See ./spine.ts for why the hint\n // is empty rather than a spelled-out \"<none>\".\n argumentHint: \"\",\n purpose:\n \"What each document you author by hand must contain: the architecture requirements axis and its `Covers:` line, how scenarios become an executable suite, and the frontmatter fields `loam vouch` stamps.\",\n invocation: \"loam instructions loam-authoring\",\n placeholders: [],\n spine: [\n \"The architecture spec axis\",\n \"The generated Gherkin suite\",\n \"Frontmatter — who vouched for this, and from what\",\n ],\n body: `The grammars you author against: the architecture spec axis, the generated Gherkin suite, and frontmatter.\n\n## The architecture spec axis\n\nThe business spec will never mention the transactional outbox — that is\narchitecture. Retries, idempotency, metrics, alerts: real obligations no business\nscenario states, and exactly where generated code cuts corners unless the\nobligations are derived mechanically. They live in \\`arch.spec.md\\` — living and\ndelta, same grammar, same delta algebra, merged by \\`loam archive\\` through the\nsame code path (the two files are separate requirement namespaces).\n\nWhere a business requirement carries \\`Operations:\\`, an arch requirement carries\n\\`Covers:\\` — the model objects its scenarios exercise, comma-separated:\n\n\\`\\`\\`\nCovers: paymentService.db, paymentService -> kafka, alert:payment_5xx, sli:availability\n\\`\\`\\`\n\na C4 element (id, or the service a bound element stands for), an edge\n(\\`source -> target\\`), or a health signal the service's health.yaml declares.\nEvery entry must resolve — \\`covers.unknown\\` (warn) is the typo guard, because a\nmistyped entry silently costs the coverage it was written for.\n\nCoverage is then derived, never trusted, as two warnings: a feature's NEW tagged\nelements and edges want a covering requirement in its arch.spec.md deltas\n(\\`c4.uncovered\\`), and every alert/SLI health.yaml declares wants one in the\nliving arch spec (\\`health.uncovered\\`). None of this gates \\`loam archive\\`;\n\\`--strict\\` is the CI escalation. An absent arch.spec.md is not a finding —\npartial adoption is supported — but write one for any service with real\narchitecture, or its obligations ship unchecked.\n\n**Effective configuration and dependency semantics live here too, by\nconvention.** Facts about the service that no artifact structurally holds —\nthe value a deploy chart actually sets, the retry budget a client library\nhardcodes (\"retries: -1 is unbounded\"), the delivery or idempotency guarantee\na driver decides — are ARCH REQUIREMENTS: prose with a \\`Covers:\\` line naming\nthe element or edge whose behaviour the fact decides. loam will never verify\nthe values; naming the home is the point. A service whose timeout comes from\nan env var in a chart in another repository is otherwise described by no file\nin this repo, and two adoptions will file the same fact two different ways.\n\n**Test levels, mapped once.** A business scenario is an acceptance test. An arch\nscenario is an integration/ops test — the outbox relay under a dead broker, the\nretry that stays idempotent, the alert rule that actually fires. \\`api.exposes\\`\nis a contract test. Unit tests sit below spec granularity and are your TDD\nconcern, not the specs'.\n\n## The generated Gherkin suite\n\nScenarios are the acceptance criteria, and \\`loam gherkin\\` makes them\nexecutable: real \\`.feature\\` files, written into the SERVICE'S repo — the one\nloam command that writes there, because tests live with the code they gate.\nOutput lands in \\`<gherkinDir>/loam/\\` (\\`gherkinDir\\` is an optional loam.json\nfact, default \\`features\\`), and that \\`loam/\\` subdirectory is loam's own\nderived space — and a committed one: an emission lands through the same lock\nand journal the docs repo's writers use, as \\`loam/.loam-lock\\` and\n\\`loam/.loam-commit\\` dotfiles that exist only while a run is in flight (or\nafter a kill, where the journal is what lets the next run finish the job).\nRegeneration rewrites its scope and deletes its orphans, so\nnever hand-edit inside it — step definitions and hand-written features belong\noutside it, and loam never touches a byte outside \\`loam/\\`.\n\n- \\`loam gherkin FEAT-101\\` — the feature's ADDED/MODIFIED requirements for this\n service, both spec axes. Files carry \\`@FEAT-101\\`; arch-axis files add\n \\`@architecture\\` and are named \\`arch--<slug>.feature\\` — their scenarios are\n integration/ops tests, not acceptance tests.\n- \\`loam gherkin --service <id>\\` (no feature) — the full living suite from\n spec.md + arch.spec.md: the regression skeleton a legacy service gets at\n adoption.\n\nOne file per requirement (\\`Feature:\\` is the requirement name). Bullet lines\nopening with Given/When/Then/And/But — the \\`- **WHEN** ...\\` convention\nincluded — become steps; every other body line is kept as scenario\ndescription. A valid Markdown table AT THE MARGIN becomes the \\`Examples:\\` of\na \\`Scenario Outline\\`; a malformed table stays in the description and is\nreported, because it will run once rather than once per row.\n\nA step takes an ARGUMENT by carrying it INDENTED underneath: an indented table\nbecomes that step's data table (the rows an outbox or a DB table must hold after\nthe pass), a fenced block becomes its docstring, indentation intact (the request\npayload). Indented under a step means this step's rows; at the margin means the\nscenario's cases. A block no step precedes stays description and is reported as\n\\`strandedBlocks\\` — the document reads, and the TEST lost its argument. Each scenario is\ntagged \\`@loam-digest-<16hex>\\`: the same body\nhash \\`loam verify\\` folds into its claim ids, riding into cucumber's JSON\nreport as a tag, so the suite, the claim and the report cannot quietly\ndisagree about what a scenario says. \\`loam validate\n--service <id>\\`, run in the service repo, grades the suite by those digests\n(\\`gherkin.missing\\` / \\`gherkin.stale\\` / \\`gherkin.orphaned\\`, all warn) — the\nfix is always regeneration, never editing a generated file.\n\nThe flow, closed end to end: \\`loam gherkin FEAT-101\\` → \\`loam steps --service\n<id>\\` (the phrase inventory: how many step definitions this suite needs, one\nper phrase row, and which phrases differ only by an article or a trailing\nclause) → write step definitions (outside \\`loam/\\`) → run the suite with a JSON report\n(\\`cucumber-js --format json:report.json\\`) → implement until green →\n\\`loam verify FEAT-101 --service <id> --results report.json [--contract-results contract.json] [--record rest.json]\\`,\nrun in that same service repo. The digest\ntags ride through the runner into the report, so the \\`scenario.tested\\` claims\nare answered mechanically from the passing report rather than anybody's word.\nThis proves which digest-matched report bytes loam accepted; it does not prove\nthe report was produced by executing the attested commit. See\n\\`loam instructions loam-done-check\\` for what \\`--record\\` still covers.\n\n## Frontmatter — who vouched for this, and from what\n\nEvery markdown artifact opens with a YAML block:\n\n\\`\\`\\`yaml\n---\nservice: payment-service # or feature: FEAT-101\nstatus: verified # services: draft -> verified\n # features: proposed -> in_progress -> built -> done\nowner: payments-team\nlast_verified: 2026-07-31 # written by \\`loam vouch\\` — do not hand-edit\nsources: # files/directories in the SERVICE'S repo this was written from — no globs\n - src/main/java/com/shop/payment/\nsources_digest: 6f1c0a… # written by \\`loam vouch\\` — do not hand-edit\ncontent_digest: 9b2f41… # written by \\`loam vouch\\` — do not hand-edit\nsources_files: | # written by \\`loam vouch\\` — do not hand-edit\n 9b2f41… src/main/java/com/shop/payment/Api.java\nvouch_scope: sampled 2/9 seed=1a2b3c4d5e6f7089 # only when the vouch read a SAMPLE\n---\n\\`\\`\\`\n\n\\`sources\\` matters more than it looks. Everything else loam checks is internal\nconsistency — and a corpus can agree with itself perfectly while describing nothing\nthat exists. \\`sources\\` is the one thing tying a document to code: \\`loam validate\\`,\nrun inside that service's repository, checks every listed path is still there.\nEntries are literal files and directories only — a directory covers everything\nbeneath it. Glob patterns are refused loudly (\\`loam vouch\\` will not stamp them,\n\\`loam validate\\` errors on them): a pattern dialect nobody can be sure of digests\na different file set than intended, corrupting the staleness signal silently.\n\n\\`sources_digest\\` is what makes that tie say something over time: a hash of the\nCONTENT of those files, taken when a human last vouched for the document. Every\nlater \\`loam validate\\` re-computes it, so it can tell a document nobody has checked\n(\\`sources.unvouched\\`) from one that still matches the code (\\`sources.current\\`) from\none the code has moved out from under (\\`sources.stale\\`). On \\`sources.stale\\` or\n\\`content.stale\\`, \\`loam vouch --pack --service <id>\\` (read-only, stamps nothing)\nprints exactly what to re-read before the human re-vouches — the body's diff since\nthe last vouch, the source files that moved, and the sections already covered.\n\n\\`content_digest\\` is the same promise about the document itself: a hash of the\nbody below the frontmatter, stamped by the same vouch. It closes the other half of\nthe forgery — editing a spec after it was vouched used to leave \\`status: verified\\`\nstanding over words nobody read. \\`loam validate\\` recomputes it wherever it can\nread the doc (no service repo needed, so it fires from the docs repo too) and\nreports \\`content.stale\\` (warn): only a person can say whether verified still\nholds of the new words.\n\n\\`vouch_scope\\` appears only when the person vouched after reading a SAMPLE of the\ndocument — \\`loam vouch --sample <n>\\`, whose whole purpose is that a partial read\nis recorded as a partial read. Its value is one flat string,\n\\`sampled <k>/<n> seed=<16 hex>\\`: k sections read of n, and the seed those k were\nchosen with. The seed is \\`sha256(<service> NUL <content_digest> NUL <sources_digest>)\\`\ntruncated to 16 hex characters, and the sections are ranked by\n\\`sha256(<seed> NUL <index> NUL <heading>)\\` with the lowest k taken, over every H2\nand H3 heading of the body outside code fences — so anybody holding the document\ncan recompute exactly which sections that person was shown, and an agent cannot\nsteer the pick without rewriting the document (which changes the seed and voids the\nstamp). \\`status\\` stays \\`verified\\` and the maturity rung stays \\`vouched\\`: the scope\nqualifies that claim, it is not a fourth status. \\`loam validate\\` reports\n\\`sources.sampled-vouch\\` (warn) while it is there, \\`loam list\\` shows\n\\`vouched (sampled)\\`, and a later FULL \\`loam vouch\\` deletes the field. Never write\nor delete it by hand: removing it turns a partial read into a full one on every\nsurface at once, which is the one forgery this field exists to make impossible.\n\nWrite \\`sources\\` for anything you author from reading code, and leave \\`status: draft\\`\nuntil a human has read it. Promoting draft to verified is their call, not yours, and\nit has its own command — \\`loam vouch --service <id>\\`, run inside that service's repo,\nwhich stamps the status, the date, the identity (\\`vouched_by\\`, from git), both digests\nand the per-file index\n(\\`sources_files\\`, which is what lets a later \\`sources.stale\\` name the paths that\nmoved) together — into the living spec.md\nand, when the service has one, arch.spec.md, in one all-or-nothing run: a file whose\nsources cannot be verified refuses the whole vouch. Never write those six fields by\nhand: a status with no digest behind it is a claim with nothing behind it. If the\ndocument changed under vouch between the read and the write, it refuses with\n\\`vouch-raced\\` and stamps nothing — re-read and re-run.\n\n**\\`loam vouch\\` is not yours to run**, and it is built so that it cannot be. It is\nthe one command whose output is a claim about a HUMAN act — everything else loam\nchecks is internal consistency, which fluent prose satisfies on its own — so it\nrefuses \\`vouch-unattended\\` when stdin is not a terminal (and in \\`--json\\` mode,\nwhere a question cannot be asked), answers \\`vouch-declined\\` when the person says\nno, and refuses \\`vouch-unattributable\\` when git can name nobody, because a stamp\nwith no \\`vouched_by\\` behind it records only that the word was written. \\`--yes\\`\nexists for a person's own scripted run; typing it on someone's behalf is\nwriting their name. The generated command and skill files pre-approve loam's\nread-only and authoring verbs one by one and deliberately not this one: when\nthe work is done, hand back and say a vouch is owed.\n`,\n};\n"]}
1
+ {"version":3,"file":"authoring.js","sourceRoot":"","sources":["../../../../../src/core/agent/workflows/reference/authoring.ts"],"names":[],"mappings":"AAuBA,MAAM,CAAC,MAAM,cAAc,GAAmB;IAC5C,IAAI,EAAE,gBAAgB;IACtB,WAAW,EACT,gJAAgJ;IAClJ,6EAA6E;IAC7E,+CAA+C;IAC/C,YAAY,EAAE,EAAE;IAChB,OAAO,EACL,4QAA4Q;IAC9Q,UAAU,EAAE,kCAAkC;IAC9C,YAAY,EAAE,EAAE;IAChB,KAAK,EAAE;QACL,4BAA4B;QAC5B,6BAA6B;QAC7B,mDAAmD;QACnD,sBAAsB;KACvB;IACD,IAAI,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqSP;CACA,CAAC","sourcesContent":["/**\n * The `loam-authoring` reference page: the grammars of the documents you write.\n *\n * The architecture spec axis (`arch.spec.md` and its `Covers:` line), the\n * generated Gherkin suite, and the frontmatter/vouch chain that ties a\n * document to the code it was written from.\n *\n * All three are consulted at a moment you can name — while authoring one file\n * — and none of them is needed to form the question. That is the split this\n * page exists to make; ./reference.ts records why it had to be made at all.\n *\n * The first three sections are the three AGENTS.md sections verbatim, in their\n * original order, so a cross-reference elsewhere in the corpus still names the\n * same headings. The fourth, \"Writing for a person\", was written for this page\n * and never stood in AGENTS.md. A large real fleet was migrated into one feature\n * whose every delta validated, and its reviewers still could not follow it: no\n * purpose said what a service did, requirement bodies were a source document\n * pasted whole, and \"this delta\" was copied into the living docs by the\n * archive. No check reads prose, so this is where that lesson lives. Its\n * examples are neutral; nothing from that fleet may enter this repository.\n */\nimport type { CommandContent } from \"../../contract.js\";\n\nexport const LOAM_AUTHORING: CommandContent = {\n name: \"loam-authoring\",\n description:\n \"Reference: the grammars you author against — arch.spec.md, the generated Gherkin suite, frontmatter, and writing a feature a person can follow\",\n // No arguments: one document, printed whole. See ./spine.ts for why the hint\n // is empty rather than a spelled-out \"<none>\".\n argumentHint: \"\",\n purpose:\n \"What each document you author by hand must contain: the architecture requirements axis and its `Covers:` line, how scenarios become an executable suite, the frontmatter fields `loam vouch` stamps, and how to write a feature's documents so a reviewer can follow them.\",\n invocation: \"loam instructions loam-authoring\",\n placeholders: [],\n spine: [\n \"The architecture spec axis\",\n \"The generated Gherkin suite\",\n \"Frontmatter — who vouched for this, and from what\",\n \"Writing for a person\",\n ],\n body: `The grammars you author against: the architecture spec axis, the generated Gherkin suite, frontmatter, and writing a feature a person can follow.\n\n## The architecture spec axis\n\nThe business spec will never mention the transactional outbox — that is\narchitecture. Retries, idempotency, metrics, alerts: real obligations no business\nscenario states, and exactly where generated code cuts corners unless the\nobligations are derived mechanically. They live in \\`arch.spec.md\\` — living and\ndelta, same grammar, same delta algebra, merged by \\`loam archive\\` through the\nsame code path (the two files are separate requirement namespaces).\n\nWhere a business requirement carries \\`Operations:\\`, an arch requirement carries\n\\`Covers:\\` — the model objects its scenarios exercise, comma-separated:\n\n\\`\\`\\`\nCovers: paymentService.db, paymentService -> kafka, alert:payment_5xx, sli:availability\n\\`\\`\\`\n\na C4 element (id, or the service a bound element stands for), an edge\n(\\`source -> target\\`), or a health signal the service's health.yaml declares.\nEvery entry must resolve — \\`covers.unknown\\` (warn) is the typo guard, because a\nmistyped entry silently costs the coverage it was written for.\n\nCoverage is then derived, never trusted, as two warnings: a feature's NEW tagged\nelements and edges want a covering requirement in its arch.spec.md deltas\n(\\`c4.uncovered\\`), and every alert/SLI health.yaml declares wants one in the\nliving arch spec (\\`health.uncovered\\`). None of this gates \\`loam archive\\`;\n\\`--strict\\` is the CI escalation. An absent arch.spec.md is not a finding —\npartial adoption is supported — but write one for any service with real\narchitecture, or its obligations ship unchecked.\n\n**Effective configuration and dependency semantics live here too, by\nconvention.** Facts about the service that no artifact structurally holds —\nthe value a deploy chart actually sets, the retry budget a client library\nhardcodes (\"retries: -1 is unbounded\"), the delivery or idempotency guarantee\na driver decides — are ARCH REQUIREMENTS: prose with a \\`Covers:\\` line naming\nthe element or edge whose behaviour the fact decides. loam will never verify\nthe values; naming the home is the point. A service whose timeout comes from\nan env var in a chart in another repository is otherwise described by no file\nin this repo, and two adoptions will file the same fact two different ways.\n\n**Test levels, mapped once.** A business scenario is an acceptance test. An arch\nscenario is an integration/ops test — the outbox relay under a dead broker, the\nretry that stays idempotent, the alert rule that actually fires. \\`api.exposes\\`\nis a contract test. Unit tests sit below spec granularity and are your TDD\nconcern, not the specs'.\n\n## The generated Gherkin suite\n\nScenarios are the acceptance criteria, and \\`loam gherkin\\` makes them\nexecutable: real \\`.feature\\` files, written into the SERVICE'S repo — the one\nloam command that writes there, because tests live with the code they gate.\nOutput lands in \\`<gherkinDir>/loam/\\` (\\`gherkinDir\\` is an optional loam.json\nfact, default \\`features\\`), and that \\`loam/\\` subdirectory is loam's own\nderived space — and a committed one: an emission lands through the same lock\nand journal the docs repo's writers use, as \\`loam/.loam-lock\\` and\n\\`loam/.loam-commit\\` dotfiles that exist only while a run is in flight (or\nafter a kill, where the journal is what lets the next run finish the job).\nRegeneration rewrites its scope and deletes its orphans, so\nnever hand-edit inside it — step definitions and hand-written features belong\noutside it, and loam never touches a byte outside \\`loam/\\`.\n\n- \\`loam gherkin FEAT-101\\` — the feature's ADDED/MODIFIED requirements for this\n service, both spec axes. Files carry \\`@FEAT-101\\`; arch-axis files add\n \\`@architecture\\` and are named \\`arch--<slug>.feature\\` — their scenarios are\n integration/ops tests, not acceptance tests.\n- \\`loam gherkin --service <id>\\` (no feature) — the full living suite from\n spec.md + arch.spec.md: the regression skeleton a legacy service gets at\n adoption.\n\nOne file per requirement (\\`Feature:\\` is the requirement name). Bullet lines\nopening with Given/When/Then/And/But — the \\`- **WHEN** ...\\` convention\nincluded — become steps; every other body line is kept as scenario\ndescription. A valid Markdown table AT THE MARGIN becomes the \\`Examples:\\` of\na \\`Scenario Outline\\`; a malformed table stays in the description and is\nreported, because it will run once rather than once per row.\n\nA step takes an ARGUMENT by carrying it INDENTED underneath: an indented table\nbecomes that step's data table (the rows an outbox or a DB table must hold after\nthe pass), a fenced block becomes its docstring, indentation intact (the request\npayload). Indented under a step means this step's rows; at the margin means the\nscenario's cases. A block no step precedes stays description and is reported as\n\\`strandedBlocks\\` — the document reads, and the TEST lost its argument. Each scenario is\ntagged \\`@loam-digest-<16hex>\\`: the same body\nhash \\`loam verify\\` folds into its claim ids, riding into cucumber's JSON\nreport as a tag, so the suite, the claim and the report cannot quietly\ndisagree about what a scenario says. \\`loam validate\n--service <id>\\`, run in the service repo, grades the suite by those digests\n(\\`gherkin.missing\\` / \\`gherkin.stale\\` / \\`gherkin.orphaned\\`, all warn) — the\nfix is always regeneration, never editing a generated file.\n\nThe flow, closed end to end: \\`loam gherkin FEAT-101\\` → \\`loam steps --service\n<id>\\` (the phrase inventory: how many step definitions this suite needs, one\nper phrase row, and which phrases differ only by an article or a trailing\nclause) → write step definitions (outside \\`loam/\\`) → run the suite with a JSON report\n(\\`cucumber-js --format json:report.json\\`) → implement until green →\n\\`loam verify FEAT-101 --service <id> --results report.json [--contract-results contract.json] [--record rest.json]\\`,\nrun in that same service repo. The digest\ntags ride through the runner into the report, so the \\`scenario.tested\\` claims\nare answered mechanically from the passing report rather than anybody's word.\nThis proves which digest-matched report bytes loam accepted; it does not prove\nthe report was produced by executing the attested commit. See\n\\`loam instructions loam-done-check\\` for what \\`--record\\` still covers.\n\n## Frontmatter — who vouched for this, and from what\n\nEvery markdown artifact opens with a YAML block:\n\n\\`\\`\\`yaml\n---\nservice: payment-service # or feature: FEAT-101\nstatus: verified # services: draft -> verified\n # features: proposed -> in_progress -> built -> done\nowner: payments-team\nlast_verified: 2026-07-31 # written by \\`loam vouch\\` — do not hand-edit\nsources: # files/directories in the SERVICE'S repo this was written from — no globs\n - src/main/java/com/shop/payment/\nsources_digest: 6f1c0a… # written by \\`loam vouch\\` — do not hand-edit\ncontent_digest: 9b2f41… # written by \\`loam vouch\\` — do not hand-edit\nsources_files: | # written by \\`loam vouch\\` — do not hand-edit\n 9b2f41… src/main/java/com/shop/payment/Api.java\nvouch_scope: sampled 2/9 seed=1a2b3c4d5e6f7089 # only when the vouch read a SAMPLE\n---\n\\`\\`\\`\n\n\\`sources\\` matters more than it looks. Everything else loam checks is internal\nconsistency — and a corpus can agree with itself perfectly while describing nothing\nthat exists. \\`sources\\` is the one thing tying a document to code: \\`loam validate\\`,\nrun inside that service's repository, checks every listed path is still there.\nEntries are literal files and directories only — a directory covers everything\nbeneath it. Glob patterns are refused loudly (\\`loam vouch\\` will not stamp them,\n\\`loam validate\\` errors on them): a pattern dialect nobody can be sure of digests\na different file set than intended, corrupting the staleness signal silently.\n\n\\`sources_digest\\` is what makes that tie say something over time: a hash of the\nCONTENT of those files, taken when a human last vouched for the document. Every\nlater \\`loam validate\\` re-computes it, so it can tell a document nobody has checked\n(\\`sources.unvouched\\`) from one that still matches the code (\\`sources.current\\`) from\none the code has moved out from under (\\`sources.stale\\`). On \\`sources.stale\\` or\n\\`content.stale\\`, \\`loam vouch --pack --service <id>\\` (read-only, stamps nothing)\nprints exactly what to re-read before the human re-vouches — the body's diff since\nthe last vouch, the source files that moved, and the sections already covered.\n\n\\`content_digest\\` is the same promise about the document itself: a hash of the\nbody below the frontmatter, stamped by the same vouch. It closes the other half of\nthe forgery — editing a spec after it was vouched used to leave \\`status: verified\\`\nstanding over words nobody read. \\`loam validate\\` recomputes it wherever it can\nread the doc (no service repo needed, so it fires from the docs repo too) and\nreports \\`content.stale\\` (warn): only a person can say whether verified still\nholds of the new words. The fleet readouts say the same: \\`loam list\\` shows\n\\`vouched (stale)\\` and owes the row a re-vouch, and \\`loam status\\` emits\n\\`next.revouch\\` — a step for a person, never for you.\n\n\\`vouch_scope\\` appears only when the person vouched after reading a SAMPLE of the\ndocument — \\`loam vouch --sample <n>\\`, whose whole purpose is that a partial read\nis recorded as a partial read. Its value is one flat string,\n\\`sampled <k>/<n> seed=<16 hex>\\`: k sections read of n, and the seed those k were\nchosen with. The seed is \\`sha256(<service> NUL <content_digest> NUL <sources_digest>)\\`\ntruncated to 16 hex characters, and the sections are ranked by\n\\`sha256(<seed> NUL <index> NUL <heading>)\\` with the lowest k taken, over every H2\nand H3 heading of the body outside code fences — so anybody holding the document\ncan recompute exactly which sections that person was shown, and an agent cannot\nsteer the pick without rewriting the document (which changes the seed and voids the\nstamp). \\`status\\` stays \\`verified\\` and the maturity rung stays \\`vouched\\`: the scope\nqualifies that claim, it is not a fourth status. \\`loam validate\\` reports\n\\`sources.sampled-vouch\\` (warn) while it is there, \\`loam list\\` shows\n\\`vouched (sampled)\\`, and a later FULL \\`loam vouch\\` deletes the field. Never write\nor delete it by hand: removing it turns a partial read into a full one on every\nsurface at once, which is the one forgery this field exists to make impossible.\n\nWrite \\`sources\\` for anything you author from reading code, and leave \\`status: draft\\`\nuntil a human has read it. Promoting draft to verified is their call, not yours, and\nit has its own command — \\`loam vouch --service <id>\\`, run inside that service's repo,\nwhich stamps the status, the date, the identity (\\`vouched_by\\`, from git), both digests\nand the per-file index\n(\\`sources_files\\`, which is what lets a later \\`sources.stale\\` name the paths that\nmoved) together — into the living spec.md\nand, when the service has one, arch.spec.md, in one all-or-nothing run: a file whose\nsources cannot be verified refuses the whole vouch. Never write those six fields by\nhand: a status with no digest behind it is a claim with nothing behind it. If the\ndocument changed under vouch between the read and the write, it refuses with\n\\`vouch-raced\\` and stamps nothing — re-read and re-run.\n\n**\\`loam vouch\\` is not yours to run**, and it is built so that it cannot be. It is\nthe one command whose output is a claim about a HUMAN act — everything else loam\nchecks is internal consistency, which fluent prose satisfies on its own — so it\nrefuses \\`vouch-unattended\\` when stdin is not a terminal (and in \\`--json\\` mode,\nwhere a question cannot be asked), answers \\`vouch-declined\\` when the person says\nno, and refuses \\`vouch-unattributable\\` when git can name nobody, because a stamp\nwith no \\`vouched_by\\` behind it records only that the word was written. \\`--yes\\`\nexists for a person's own scripted run; typing it on someone's behalf is\nwriting their name. The generated command and skill files pre-approve loam's\nread-only and authoring verbs one by one and deliberately not this one: when\nthe work is done, hand back and say a vouch is owed.\n\n## Writing for a person\n\nA feature is read by a reviewer before anyone builds it, and its requirements\nare read for years after \\`loam archive\\` copies them into the living docs. loam\ngrades the joins and never the prose, so nothing in this section is checked: a\ndelta can validate clean and still be one nobody can follow.\n\n**intent.md** opens with the problem in business terms — \\`## Why\\` and\n\\`## Scope\\`, the two sections the archive gate reads — and then carries the three\nthings a reviewer looks for first:\n\n- \\`## How to read this feature\\`: two or three sentences saying which services\n change, which document to open first, and which picture shows the change (the\n delta's own view, or a flow under the feature's \\`usecases/\\`).\n- a business-requirement coverage table, one row per business requirement the\n feature was asked to meet, naming what keeps it:\n\n | Business requirement | Kept by | Where |\n |---|---|---|\n | A customer can split one payment between two cards | PAY-SPLIT-1 | payment-split-service spec.md |\n | Every payee gets a receipt | uc_split_receipt | usecases/split-receipt.likec4 |\n\n- \\`## Open questions\\` (the scaffold already writes the heading) as a table, so\n that a person can answer each question and a reader can see what each blocks:\n\n | ID | Question | Blocks | Owner | Current default |\n |---|---|---|---|---|\n | Q1 | Is a split refunded per card or as a whole? | PAY-SPLIT-3 | payments-team | per card |\n\n The current default is what gets built if nobody answers, so write one for\n every question.\n\n**Each spec delta opens with a plain-language \\`## Purpose\\`**: what the service\ndoes in this change, written for someone who has never opened its code. Where\nthe delta CREATES the living document — a new service's spec.md, a first\narch.spec.md, a new capability — \\`loam archive\\` copies that section into the\nnew document as its narrative. Where the living document already exists, the\nsection stays with the archived delta, and the archive plan says so on that\nfile's line; if the service's own narrative should change, edit the living\ndocument in the same change.\n\n**Write a long requirement body as a lead and bullets.** A new requirement\nstates one behaviour. A requirement carried over from another source often\narrives as one paragraph of SHALL sentences. Keep every sentence, but open with\none line that says what the requirement is for, and give each SHALL sentence a\nbullet of its own:\n\n ### Requirement: Split a payment\n Requirement-ID: PAY-SPLIT-1\n\n A payment can be divided between several payees.\n\n - The service SHALL accept between two and five payees per split.\n - The service SHALL reject a split whose shares do not add up to the authorized amount.\n\n**Expand every abbreviation the first time a document uses it**, in words a new\nreader knows: \"service-level objective (SLO)\", then \"SLO\".\n\n**Keep review-time wording out of what the archive copies.** \"This delta\", \"this\nfeature\", \"the new endpoint\" and \"we now\" read correctly in review. But\n\\`loam archive\\` copies requirement bodies, scenarios and contract descriptions\ninto living documents, where \"this feature\" points at a pull request that merged\nlong ago. Write what the service does, not what the change does. Prose about the\nchange belongs in \\`intent.md\\`, which stays with the feature.\n\n**A feature's vocabulary, decisions and flows travel with it.**\n\n- A word the feature brings is \\`features/<FEAT>/glossary/<term>.md\\`, which the\n archive copies into \\`glossary/\\`. A term the living glossary already defines is\n edited there instead, because the copy never overwrites\n (\\`glossary.term-exists\\`).\n- A decision is \\`features/<FEAT>/adrs/NNNN-<slug>.md\\`. It stays with the\n feature under \\`features/archive/\\`, and the living documents that link to it go\n on resolving. A decision meant to outlive the change belongs in\n \\`architecture/adrs/\\` or the service's own \\`adrs/\\` instead.\n- A flow that keeps a promise across services is\n \\`features/<FEAT>/usecases/<name>.likec4\\`: a \\`dynamic view\\` tagged\n \\`#cap-<capability>\\`, naming a capability the fleet declares, and\n \\`#req-<Requirement-ID>\\`, naming the promise it keeps. A promise the feature's\n own capability delta adds resolves too. \\`usecase.capability-unresolved\\` and\n \\`usecase.requirement-unresolved\\` grade both tags before the archive.\n\nLink to all three from the deltas, written relative to the file you write in:\n\\`loam archive\\` re-points every link into the feature for the move.\n\n**Write a \\`Covers:\\` edge by service name**:\n\\`Covers: order-service -> payment-service\\`. An edge spelled by its endpoints'\nservice names resolves the same before and after the archive. A delta's own\nelement id may not, and \\`covers.unknown\\` at feature scope says when it would not.\nA kinded spelling such as \\`order-service -[calls]-> payment-service\\` is accepted,\nbut the kind is read past rather than compared: it covers every edge from the\nfirst service to the second, whatever its kind. So write the plain arrow.\n\n**Draw a producer outside the fleet as an \\`#external\\` element**, with the edge\nit publishes on carrying \\`metadata { publishes }\\`, so that the consumer's\n\\`Consumes:\\` line has a producer to join to. \\`loam instructions loam-spine\\`\n(\"A message produced outside the fleet\") has the join, and\n\\`loam instructions loam-drawing\\` has the drawing.\n`,\n};\n"]}
@@ -14,14 +14,16 @@
14
14
  * written — every byte comes from ../../agents-md/, which is where the sections
15
15
  * already lived and where they stayed. The parts still carry their own trailing
16
16
  * newlines and are joined with no separator, so the printed page is the old
17
- * section byte for byte.
17
+ * section byte for byte. That is the assembly contract every part's header
18
+ * points back at: each starts at the first character of its opening line and
19
+ * ends with the newline that closes its last one, or two parts glue onto one
20
+ * line on the printed page.
18
21
  *
19
22
  * WHAT IS AND IS NOT DUPLICATED. `## Reading loam's output` still exists in
20
- * AGENTS.md (../../agents-md/command-map.ts's READING_OUTPUT), and it is a
21
- * different three facts, not a summary of these: that every command speaks
22
- * JSON, that the envelope survives a bad invocation, and that codes are the
23
- * contract, plus the two places the detail went. The per-invocation inventory
24
- * below appears in exactly one place.
23
+ * AGENTS.md (../../agents-md.ts's ORIENTATION), and it is orientation, not a
24
+ * summary of this page: the envelope's keys, branching on codes rather than
25
+ * prose, severity versus gating, and a pointer here. The per-invocation
26
+ * inventory below appears in exactly one place.
25
27
  */
26
28
  import { CODE_MAP } from "../../agents-md/command-map.js";
27
29
  import { CONTEXT_COMMAND } from "../../agents-md/map/lenses/context.js";
@@ -1 +1 @@
1
- {"version":3,"file":"codes.js","sourceRoot":"","sources":["../../../../../src/core/agent/workflows/reference/codes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,gCAAgC,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,uCAAuC,CAAC;AACxE,OAAO,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AAClE,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AACtE,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAChE,OAAO,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AAGvD,MAAM,CAAC,MAAM,UAAU,GAAmB;IACxC,IAAI,EAAE,YAAY;IAClB,WAAW,EAAE,sEAAsE;IACnF,6EAA6E;IAC7E,+CAA+C;IAC/C,YAAY,EAAE,EAAE;IAChB,OAAO,EACL,iRAAiR;IACnR,UAAU,EAAE,8BAA8B;IAC1C,YAAY,EAAE,EAAE;IAChB,2EAA2E;IAC3E,4EAA4E;IAC5E,+CAA+C;IAC/C,KAAK,EAAE;QACL,wCAAwC;QACxC,qDAAqD;QACrD,8DAA8D;QAC9D,6DAA6D;KAC9D;IACD,0EAA0E;IAC1E,gDAAgD;IAChD,IAAI,EACF,QAAQ;QACR,eAAe;QACf,YAAY;QACZ,kBAAkB;QAClB,aAAa;QACb,YAAY;QACZ,eAAe;QACf,WAAW;QACX,QAAQ;CACX,CAAC","sourcesContent":["/**\n * The `loam-codes` reference page: which codes each INVOCATION can raise.\n *\n * The largest of the four pages and the one this migration is mostly about. As\n * a section of AGENTS.md it was 44,433 bytes — 41% of a 109,399-byte file that\n * Codex truncates at 32,768 and Windsurf at 12,000 characters, both silently.\n * It is also the half a reader consults at a moment it can NAME (a run reported\n * something) rather than the half it needs to form a question at all, which is\n * what decided which side of the split it went. ./reference.ts carries the rest\n * of that argument.\n *\n * This module does one thing: it CONCATENATES, in the order ../../agents-md.ts\n * used to. Nothing here reformats a part on the way past, and nothing here is\n * written — every byte comes from ../../agents-md/, which is where the sections\n * already lived and where they stayed. The parts still carry their own trailing\n * newlines and are joined with no separator, so the printed page is the old\n * section byte for byte.\n *\n * WHAT IS AND IS NOT DUPLICATED. `## Reading loam's output` still exists in\n * AGENTS.md (../../agents-md/command-map.ts's READING_OUTPUT), and it is a\n * different three facts, not a summary of these: that every command speaks\n * JSON, that the envelope survives a bad invocation, and that codes are the\n * contract, plus the two places the detail went. The per-invocation inventory\n * below appears in exactly one place.\n */\nimport { CODE_MAP } from \"../../agents-md/command-map.js\";\nimport { CONTEXT_COMMAND } from \"../../agents-md/map/lenses/context.js\";\nimport { DIFF_COMMAND } from \"../../agents-md/map/lenses/diff.js\";\nimport { GATE_COMMAND } from \"../../agents-md/map/lenses/gate.js\";\nimport { EXPLAIN_COMMAND } from \"../../agents-md/map/explain.js\";\nimport { MCP_COMMAND } from \"../../agents-md/map/mcp.js\";\nimport { SUBSYSTEM_COMMANDS } from \"../../agents-md/map/subsystem.js\";\nimport { USECASE_VIEWS } from \"../../agents-md/map/usecases.js\";\nimport { REFUSALS } from \"../../agents-md/refusals.js\";\nimport type { CommandContent } from \"../../contract.js\";\n\nexport const LOAM_CODES: CommandContent = {\n name: \"loam-codes\",\n description: \"Reference: which codes each invocation can raise, command by command\",\n // No arguments: one document, printed whole. See ./spine.ts for why the hint\n // is empty rather than a spelled-out \"<none>\".\n argumentHint: \"\",\n purpose:\n \"The per-invocation inventory: which findings `validate --service` / `--feature` / `--all`, `status`, `doctor`, `gate`, `context`, `diff`, `explore`, `dependencies`, `rebase`, `seed`, `subsystem` and `mcp` can report, and the refusals the containment surface answers with.\",\n invocation: \"loam instructions loam-codes\",\n placeholders: [],\n // The page carries no `## ` headings — it is one list, and the bullets are\n // the structure. The spine names the invocations it walks instead, which is\n // what a reader is actually looking one of up.\n spine: [\n \"validate --service / --feature / --all\",\n \"status, doctor, rebase, dependencies, explore, seed\",\n \"context, gate, subsystem, use-case views, diff, explain, mcp\",\n \"the containment refusals and the OpenSpec migration surface\",\n ],\n // CODE_MAP already opens with the page's own \"**What this page is.**\" and\n // leads with `status`, the orientation command.\n body:\n CODE_MAP +\n CONTEXT_COMMAND +\n GATE_COMMAND +\n SUBSYSTEM_COMMANDS +\n USECASE_VIEWS +\n DIFF_COMMAND +\n EXPLAIN_COMMAND +\n MCP_COMMAND +\n REFUSALS,\n};\n"]}
1
+ {"version":3,"file":"codes.js","sourceRoot":"","sources":["../../../../../src/core/agent/workflows/reference/codes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,gCAAgC,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,uCAAuC,CAAC;AACxE,OAAO,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AAClE,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AACtE,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAChE,OAAO,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AAGvD,MAAM,CAAC,MAAM,UAAU,GAAmB;IACxC,IAAI,EAAE,YAAY;IAClB,WAAW,EAAE,sEAAsE;IACnF,6EAA6E;IAC7E,+CAA+C;IAC/C,YAAY,EAAE,EAAE;IAChB,OAAO,EACL,iRAAiR;IACnR,UAAU,EAAE,8BAA8B;IAC1C,YAAY,EAAE,EAAE;IAChB,2EAA2E;IAC3E,4EAA4E;IAC5E,+CAA+C;IAC/C,KAAK,EAAE;QACL,wCAAwC;QACxC,qDAAqD;QACrD,8DAA8D;QAC9D,6DAA6D;KAC9D;IACD,0EAA0E;IAC1E,gDAAgD;IAChD,IAAI,EACF,QAAQ;QACR,eAAe;QACf,YAAY;QACZ,kBAAkB;QAClB,aAAa;QACb,YAAY;QACZ,eAAe;QACf,WAAW;QACX,QAAQ;CACX,CAAC","sourcesContent":["/**\n * The `loam-codes` reference page: which codes each INVOCATION can raise.\n *\n * The largest of the four pages and the one this migration is mostly about. As\n * a section of AGENTS.md it was 44,433 bytes — 41% of a 109,399-byte file that\n * Codex truncates at 32,768 and Windsurf at 12,000 characters, both silently.\n * It is also the half a reader consults at a moment it can NAME (a run reported\n * something) rather than the half it needs to form a question at all, which is\n * what decided which side of the split it went. ./reference.ts carries the rest\n * of that argument.\n *\n * This module does one thing: it CONCATENATES, in the order ../../agents-md.ts\n * used to. Nothing here reformats a part on the way past, and nothing here is\n * written — every byte comes from ../../agents-md/, which is where the sections\n * already lived and where they stayed. The parts still carry their own trailing\n * newlines and are joined with no separator, so the printed page is the old\n * section byte for byte. That is the assembly contract every part's header\n * points back at: each starts at the first character of its opening line and\n * ends with the newline that closes its last one, or two parts glue onto one\n * line on the printed page.\n *\n * WHAT IS AND IS NOT DUPLICATED. `## Reading loam's output` still exists in\n * AGENTS.md (../../agents-md.ts's ORIENTATION), and it is orientation, not a\n * summary of this page: the envelope's keys, branching on codes rather than\n * prose, severity versus gating, and a pointer here. The per-invocation\n * inventory below appears in exactly one place.\n */\nimport { CODE_MAP } from \"../../agents-md/command-map.js\";\nimport { CONTEXT_COMMAND } from \"../../agents-md/map/lenses/context.js\";\nimport { DIFF_COMMAND } from \"../../agents-md/map/lenses/diff.js\";\nimport { GATE_COMMAND } from \"../../agents-md/map/lenses/gate.js\";\nimport { EXPLAIN_COMMAND } from \"../../agents-md/map/explain.js\";\nimport { MCP_COMMAND } from \"../../agents-md/map/mcp.js\";\nimport { SUBSYSTEM_COMMANDS } from \"../../agents-md/map/subsystem.js\";\nimport { USECASE_VIEWS } from \"../../agents-md/map/usecases.js\";\nimport { REFUSALS } from \"../../agents-md/refusals.js\";\nimport type { CommandContent } from \"../../contract.js\";\n\nexport const LOAM_CODES: CommandContent = {\n name: \"loam-codes\",\n description: \"Reference: which codes each invocation can raise, command by command\",\n // No arguments: one document, printed whole. See ./spine.ts for why the hint\n // is empty rather than a spelled-out \"<none>\".\n argumentHint: \"\",\n purpose:\n \"The per-invocation inventory: which findings `validate --service` / `--feature` / `--all`, `status`, `doctor`, `gate`, `context`, `diff`, `explore`, `dependencies`, `rebase`, `seed`, `subsystem` and `mcp` can report, and the refusals the containment surface answers with.\",\n invocation: \"loam instructions loam-codes\",\n placeholders: [],\n // The page carries no `## ` headings — it is one list, and the bullets are\n // the structure. The spine names the invocations it walks instead, which is\n // what a reader is actually looking one of up.\n spine: [\n \"validate --service / --feature / --all\",\n \"status, doctor, rebase, dependencies, explore, seed\",\n \"context, gate, subsystem, use-case views, diff, explain, mcp\",\n \"the containment refusals and the OpenSpec migration surface\",\n ],\n // CODE_MAP already opens with the page's own \"**What this page is.**\" and\n // leads with `status`, the orientation command.\n body:\n CODE_MAP +\n CONTEXT_COMMAND +\n GATE_COMMAND +\n SUBSYSTEM_COMMANDS +\n USECASE_VIEWS +\n DIFF_COMMAND +\n EXPLAIN_COMMAND +\n MCP_COMMAND +\n REFUSALS,\n};\n"]}
@@ -30,9 +30,12 @@ so a JUnit or pytest fleet is not held at \`attested\` by a file format —
30
30
  \`loam verify <FEAT> --results report.json\`. A claim is confirmed only when a
31
31
  report scenario carrying its \`@loam-digest-<16hex>\` tag ran at least one step
32
32
  and every step passed — every occurrence, when the report holds a re-run, and
33
- every before/after hook with it. A failed, undefined, pending or skipped step,
34
- a failed hook, or no matching scenario at all, is \`unconfirmed\` with the
35
- reason. The digest is the only identity: a reworded spec scenario matches
33
+ every before/after hook with it — and, in a cucumber report, ran exactly as
34
+ many steps as the stamped scenario has: a hand-tagged stub is not that
35
+ scenario's run. A failed, undefined, pending or skipped step, a failed hook, a
36
+ step count that differs, or no matching scenario at all, is \`unconfirmed\` with
37
+ the reason. A report that is not JSON (a JUnit XML file) is refused
38
+ \`answers-unreadable\`, naming both shapes. The digest is the only identity: a reworded spec scenario matches
36
39
  nothing until the suite is regenerated and re-run. When a report exists,
37
40
  ALWAYS pass \`--results\` — under it the runner owns every scenario claim, and
38
41
  an answers-file entry for one is refused.
@@ -92,9 +95,12 @@ re-checks the pins and reports drift under the \`evidence.*\` findings; nothing
92
95
  there moves a verdict either.
93
96
 
94
97
  Two more codes belong to the record itself. \`verify.record-miscounted\` (error):
95
- a \`verification.yaml\` whose \`summary\` block contradicts its own \`claims[]\` — the
96
- record is refused as unreadable rather than believed in either half, and
97
- re-recording is the repair, never editing the counts. \`verify.digest-contested\`
98
+ a record file whose \`summary\` block contradicts its own \`claims[]\` — the
99
+ record is refused as unreadable rather than believed in either half, and the
100
+ repair is never editing the counts: a service's own \`verification/<id>.yaml\`
101
+ is deleted and recorded again by that service, and the one-file
102
+ \`verification.yaml\` is restored from version control and then recorded over.
103
+ \`verify.digest-contested\`
98
104
  (warn): two or more services word a scenario identically, so they share one
99
105
  \`@loam-digest-…\` tag and no single cucumber report can say whose suite ran it —
100
106
  those scenario claims are left unconfirmed, and each service records its own
@@ -113,7 +119,10 @@ services that all answered a since-rewritten delta agree with each other and are
113
119
  every one of them stale. Differing \`docsCommit\` values are NOT a finding:
114
120
  recording a week apart is normal for a feature in flight.
115
121
  Normal mid-rollout and it gates nothing; re-record the services on the older
116
- version from their own repositories, or accept the split knowingly.
122
+ version from their own repositories. In a record kept as per-service files the
123
+ answers of the services it names do not count until they do: the record
124
+ answers the newest version its files answered, and an answer filed against an
125
+ older one could otherwise fill the slot of the question that replaced it.
117
126
  Attestations written before the field existed carry no \`checklist\` and are not
118
127
  counted as a third version — silence is not disagreement.
119
128
 
@@ -126,8 +135,9 @@ commit. It does not prove the file came from executing that commit; no digest
126
135
  can.
127
136
 
128
137
  Everything else you answer from the code, and \`--record answers.json\` takes
129
- those back, writing \`features/<FEAT>/verification.yaml\` — it travels into the
130
- archive with the feature and reads without loam. Alongside the mechanical
138
+ those back — into \`features/<FEAT>/verification/<svc>.yaml\` with \`--service\`,
139
+ into the one file \`features/<FEAT>/verification.yaml\` without — and either
140
+ travels into the archive with the feature and reads without loam. Alongside the mechanical
131
141
  flags, the answers file must answer exactly the claims no report owns: an
132
142
  entry for a report-owned claim is refused (\`answers-mismatch\`), and a
133
143
  mechanical flag alone is refused while claims outside its kind are
@@ -147,9 +157,16 @@ loam verify FEAT-101 --service payment-service --results report.json --contract-
147
157
  \`\`\`
148
158
 
149
159
  \`--service <id>\` narrows the checklist to that service's claims and binds the
150
- answers to this repository's commit, producing one **attestation** per service
151
- inside a single \`schema: 2\` \`verification.yaml\`. Re-running it in the next
152
- repo adds that repo's attestation and leaves the others standing. Omitting
160
+ answers to this repository's commit, producing that service's **attestation**
161
+ as a file of its own, \`features/<FEAT>/verification/<id>.yaml\`. The directory
162
+ is the record: loam adds the files up when it reads, and the verdict and
163
+ counts are computed from them, never stored. Re-running it in the next repo
164
+ writes that repo's file and touches no other — which is why two teams'
165
+ attestations on two docs-repo branches merge cleanly, where one shared file
166
+ conflicted every time. A one-file federated \`verification.yaml\` written
167
+ before the directory is still read; a service that records again supersedes
168
+ its share of it, and the file goes once every service it names has its own.
169
+ Omitting
153
170
  \`--service\` in a repo whose \`loam.json\` declares one substitutes it, so the
154
171
  short form is safe there; a \`--service\` naming a service this repo does not
155
172
  declare is refused (\`service-mismatch\`), and \`--service\` from a repo that
@@ -161,9 +178,14 @@ no \`--service\` writes the whole record from one place.** Over a record that
161
178
  already carries other services' attestations it is refused outright
162
179
  (\`record-federated\`, naming the attestors) rather than merged or migrated — the
163
180
  alternative was one repo silently erasing nine others' evidence. Use it only for
164
- a single-service feature that has never been recorded federated. A
165
- \`verification.yaml\` that exists but cannot be read is \`record-unreadable\`: it is
166
- never overwritten and never reported as "no record".
181
+ a single-service feature that has never been recorded federated. A record file
182
+ that exists but cannot be read — broken YAML, git conflict markers, a miscount
183
+ — is \`record-unreadable\`: it is never overwritten and never reported as "no
184
+ record", and the message names the file and the repair that is safe for it. A
185
+ service's own \`verification/<id>.yaml\` holds only that service's word, so that
186
+ service may delete it and record again; the one-file \`verification.yaml\` may
187
+ hold other services' attestations, so it is restored from version control
188
+ (after a merge, the copy on the branch you merged into) and never deleted.
167
189
 
168
190
  Reading is not writing: \`loam verify <FEAT> --service <id>\` **without**
169
191
  \`--record\` is a pure lens on the checklist. A read-only verify checklist needs no