@ybotok/loam 0.1.0-beta.3 → 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 (1256) hide show
  1. package/CHANGELOG.md +5992 -82
  2. package/COMPARISON.md +168 -63
  3. package/CONTRIBUTING.md +121 -0
  4. package/MIGRATING-from-OpenSpec.md +238 -55
  5. package/QUICKSTART.md +302 -0
  6. package/README.md +653 -144
  7. package/ROADMAP.md +1035 -0
  8. package/SCHEMA.md +3916 -263
  9. package/SECURITY.md +21 -3
  10. package/WORKFLOW.md +927 -0
  11. package/dist/cli.js +133 -21
  12. package/dist/cli.js.map +1 -1
  13. package/dist/commands/adopt/adopt.js +204 -0
  14. package/dist/commands/adopt/adopt.js.map +1 -0
  15. package/dist/commands/adopt/render.js +309 -0
  16. package/dist/commands/adopt/render.js.map +1 -0
  17. package/dist/commands/archive/archive.js +74 -0
  18. package/dist/commands/archive/archive.js.map +1 -0
  19. package/dist/commands/archive/closing.js +42 -0
  20. package/dist/commands/archive/closing.js.map +1 -0
  21. package/dist/commands/archive/plan/contracts/asyncapi.js +172 -0
  22. package/dist/commands/archive/plan/contracts/asyncapi.js.map +1 -0
  23. package/dist/commands/archive/plan/contracts/consumers.js +56 -0
  24. package/dist/commands/archive/plan/contracts/consumers.js.map +1 -0
  25. package/dist/commands/archive/plan/contracts/openapi.js +193 -0
  26. package/dist/commands/archive/plan/contracts/openapi.js.map +1 -0
  27. package/dist/commands/archive/plan/contracts/verdict-lines.js +103 -0
  28. package/dist/commands/archive/plan/contracts/verdict-lines.js.map +1 -0
  29. package/dist/commands/archive/plan/document/head.js +151 -0
  30. package/dist/commands/archive/plan/document/head.js.map +1 -0
  31. package/dist/commands/archive/plan/document/links.js +284 -0
  32. package/dist/commands/archive/plan/document/links.js.map +1 -0
  33. package/dist/commands/archive/plan/document/run.js +136 -0
  34. package/dist/commands/archive/plan/document/run.js.map +1 -0
  35. package/dist/commands/archive/plan/gate.js +319 -0
  36. package/dist/commands/archive/plan/gate.js.map +1 -0
  37. package/dist/commands/archive/plan/landscape.js +298 -0
  38. package/dist/commands/archive/plan/landscape.js.map +1 -0
  39. package/dist/commands/archive/plan/model/extending.js +85 -0
  40. package/dist/commands/archive/plan/model/extending.js.map +1 -0
  41. package/dist/commands/archive/plan/refusal.js +106 -0
  42. package/dist/commands/archive/plan/refusal.js.map +1 -0
  43. package/dist/commands/archive/plan/specs.js +318 -0
  44. package/dist/commands/archive/plan/specs.js.map +1 -0
  45. package/dist/commands/archive/plan/state.js +30 -0
  46. package/dist/commands/archive/plan/state.js.map +1 -0
  47. package/dist/commands/archive/run.js +355 -0
  48. package/dist/commands/archive/run.js.map +1 -0
  49. package/dist/commands/archive/shipped.js +49 -0
  50. package/dist/commands/archive/shipped.js.map +1 -0
  51. package/dist/commands/context/context.js +166 -0
  52. package/dist/commands/context/context.js.map +1 -0
  53. package/dist/commands/context/print.js +305 -0
  54. package/dist/commands/context/print.js.map +1 -0
  55. package/dist/commands/delta/delta.js +367 -0
  56. package/dist/commands/delta/delta.js.map +1 -0
  57. package/dist/commands/delta/print.js +221 -0
  58. package/dist/commands/delta/print.js.map +1 -0
  59. package/dist/commands/dependencies.js +6 -8
  60. package/dist/commands/dependencies.js.map +1 -1
  61. package/dist/commands/diff/diff.js +86 -0
  62. package/dist/commands/diff/diff.js.map +1 -0
  63. package/dist/commands/diff/print.js +38 -0
  64. package/dist/commands/diff/print.js.map +1 -0
  65. package/dist/commands/doctor.js +65 -5
  66. package/dist/commands/doctor.js.map +1 -1
  67. package/dist/commands/explain/explain.js +227 -0
  68. package/dist/commands/explain/explain.js.map +1 -0
  69. package/dist/commands/explore.js +39 -28
  70. package/dist/commands/explore.js.map +1 -1
  71. package/dist/commands/gate/gate.js +152 -0
  72. package/dist/commands/gate/gate.js.map +1 -0
  73. package/dist/commands/gate/print.js +66 -0
  74. package/dist/commands/gate/print.js.map +1 -0
  75. package/dist/commands/gherkin/commit.js +105 -0
  76. package/dist/commands/gherkin/commit.js.map +1 -0
  77. package/dist/commands/gherkin/gherkin.js +262 -0
  78. package/dist/commands/gherkin/gherkin.js.map +1 -0
  79. package/dist/commands/gherkin/reconcile.js +146 -0
  80. package/dist/commands/gherkin/reconcile.js.map +1 -0
  81. package/dist/commands/gherkin/render.js +77 -0
  82. package/dist/commands/gherkin/render.js.map +1 -0
  83. package/dist/commands/init/example.js +204 -0
  84. package/dist/commands/init/example.js.map +1 -0
  85. package/dist/commands/init/first-hour.js +72 -0
  86. package/dist/commands/init/first-hour.js.map +1 -0
  87. package/dist/commands/{init.js → init/init.js} +142 -71
  88. package/dist/commands/init/init.js.map +1 -0
  89. package/dist/commands/init/mcp.js +131 -0
  90. package/dist/commands/init/mcp.js.map +1 -0
  91. package/dist/commands/init/options.js +78 -0
  92. package/dist/commands/init/options.js.map +1 -0
  93. package/dist/commands/instructions.js +72 -14
  94. package/dist/commands/instructions.js.map +1 -1
  95. package/dist/commands/list/campaign/campaign.js +63 -0
  96. package/dist/commands/list/campaign/campaign.js.map +1 -0
  97. package/dist/commands/list/campaign/owners.js +65 -0
  98. package/dist/commands/list/campaign/owners.js.map +1 -0
  99. package/dist/commands/list/json.js +155 -0
  100. package/dist/commands/list/json.js.map +1 -0
  101. package/dist/commands/list/list.js +358 -0
  102. package/dist/commands/list/list.js.map +1 -0
  103. package/dist/commands/list/print.js +344 -0
  104. package/dist/commands/list/print.js.map +1 -0
  105. package/dist/commands/list/review.js +120 -0
  106. package/dist/commands/list/review.js.map +1 -0
  107. package/dist/commands/list/suites/suites.js +140 -0
  108. package/dist/commands/list/suites/suites.js.map +1 -0
  109. package/dist/commands/list/views.js +108 -0
  110. package/dist/commands/list/views.js.map +1 -0
  111. package/dist/commands/mcp/dispatch.js +238 -0
  112. package/dist/commands/mcp/dispatch.js.map +1 -0
  113. package/dist/commands/mcp/mcp.js +75 -0
  114. package/dist/commands/mcp/mcp.js.map +1 -0
  115. package/dist/commands/mcp/serve.js +55 -0
  116. package/dist/commands/mcp/serve.js.map +1 -0
  117. package/dist/commands/migrate-openspec/materialize/active.js +175 -0
  118. package/dist/commands/migrate-openspec/materialize/active.js.map +1 -0
  119. package/dist/commands/migrate-openspec/materialize/feature.js +41 -0
  120. package/dist/commands/migrate-openspec/materialize/feature.js.map +1 -0
  121. package/dist/commands/migrate-openspec/materialize/living.js +62 -0
  122. package/dist/commands/migrate-openspec/materialize/living.js.map +1 -0
  123. package/dist/commands/migrate-openspec/materialize/stage.js +143 -0
  124. package/dist/commands/migrate-openspec/materialize/stage.js.map +1 -0
  125. package/dist/commands/migrate-openspec/materialize/target.js +219 -0
  126. package/dist/commands/migrate-openspec/materialize/target.js.map +1 -0
  127. package/dist/commands/migrate-openspec/migrate-openspec.js +142 -0
  128. package/dist/commands/migrate-openspec/migrate-openspec.js.map +1 -0
  129. package/dist/commands/migrate-openspec/openspec/decisions.js +86 -0
  130. package/dist/commands/migrate-openspec/openspec/decisions.js.map +1 -0
  131. package/dist/commands/migrate-openspec/openspec/error.js +18 -0
  132. package/dist/commands/migrate-openspec/openspec/error.js.map +1 -0
  133. package/dist/commands/migrate-openspec/openspec/mapping.js +162 -0
  134. package/dist/commands/migrate-openspec/openspec/mapping.js.map +1 -0
  135. package/dist/commands/migrate-openspec/openspec/paths.js +40 -0
  136. package/dist/commands/migrate-openspec/openspec/paths.js.map +1 -0
  137. package/dist/commands/migrate-openspec/openspec/read.js +49 -0
  138. package/dist/commands/migrate-openspec/openspec/read.js.map +1 -0
  139. package/dist/commands/migrate-openspec/print.js +89 -0
  140. package/dist/commands/migrate-openspec/print.js.map +1 -0
  141. package/dist/commands/new/capability-template.js +118 -0
  142. package/dist/commands/new/capability-template.js.map +1 -0
  143. package/dist/commands/new/commit.js +62 -0
  144. package/dist/commands/new/commit.js.map +1 -0
  145. package/dist/commands/new/modifies.js +206 -0
  146. package/dist/commands/new/modifies.js.map +1 -0
  147. package/dist/commands/new/new.js +328 -0
  148. package/dist/commands/new/new.js.map +1 -0
  149. package/dist/commands/new/templates.js +279 -0
  150. package/dist/commands/new/templates.js.map +1 -0
  151. package/dist/commands/open.js +199 -0
  152. package/dist/commands/open.js.map +1 -0
  153. package/dist/commands/policy/format.js +152 -0
  154. package/dist/commands/policy/format.js.map +1 -0
  155. package/dist/commands/{docs-repo-gate.js → policy/gate.js} +38 -11
  156. package/dist/commands/policy/gate.js.map +1 -0
  157. package/dist/commands/rebase/edit.js +106 -0
  158. package/dist/commands/rebase/edit.js.map +1 -0
  159. package/dist/commands/rebase/living.js +185 -0
  160. package/dist/commands/rebase/living.js.map +1 -0
  161. package/dist/commands/rebase/plan.js +245 -0
  162. package/dist/commands/rebase/plan.js.map +1 -0
  163. package/dist/commands/rebase/rebase.js +300 -0
  164. package/dist/commands/rebase/rebase.js.map +1 -0
  165. package/dist/commands/seed/commit.js +221 -0
  166. package/dist/commands/seed/commit.js.map +1 -0
  167. package/dist/commands/seed/plan.js +278 -0
  168. package/dist/commands/seed/plan.js.map +1 -0
  169. package/dist/commands/seed/seed.js +174 -0
  170. package/dist/commands/seed/seed.js.map +1 -0
  171. package/dist/commands/show/feature.js +182 -0
  172. package/dist/commands/show/feature.js.map +1 -0
  173. package/dist/commands/show/introduced.js +157 -0
  174. package/dist/commands/show/introduced.js.map +1 -0
  175. package/dist/commands/show/marks.js +53 -0
  176. package/dist/commands/show/marks.js.map +1 -0
  177. package/dist/commands/show/service.js +239 -0
  178. package/dist/commands/show/service.js.map +1 -0
  179. package/dist/commands/show/show.js +87 -0
  180. package/dist/commands/show/show.js.map +1 -0
  181. package/dist/commands/status/fleet-next.js +90 -0
  182. package/dist/commands/status/fleet-next.js.map +1 -0
  183. package/dist/commands/status/json.js +47 -0
  184. package/dist/commands/status/json.js.map +1 -0
  185. package/dist/commands/status/print.js +209 -0
  186. package/dist/commands/status/print.js.map +1 -0
  187. package/dist/commands/status/status.js +115 -0
  188. package/dist/commands/status/status.js.map +1 -0
  189. package/dist/commands/steps/steps.js +269 -0
  190. package/dist/commands/steps/steps.js.map +1 -0
  191. package/dist/commands/subsystem/edit.js +192 -0
  192. package/dist/commands/subsystem/edit.js.map +1 -0
  193. package/dist/commands/subsystem/move.js +325 -0
  194. package/dist/commands/subsystem/move.js.map +1 -0
  195. package/dist/commands/subsystem/query.js +113 -0
  196. package/dist/commands/subsystem/query.js.map +1 -0
  197. package/dist/commands/subsystem/subsystem.js +98 -0
  198. package/dist/commands/subsystem/subsystem.js.map +1 -0
  199. package/dist/commands/subsystem/sync.js +318 -0
  200. package/dist/commands/subsystem/sync.js.map +1 -0
  201. package/dist/commands/subsystem/txn/exclude.js +132 -0
  202. package/dist/commands/subsystem/txn/exclude.js.map +1 -0
  203. package/dist/commands/subsystem/txn/links.js +128 -0
  204. package/dist/commands/subsystem/txn/links.js.map +1 -0
  205. package/dist/commands/subsystem/txn/report.js +174 -0
  206. package/dist/commands/subsystem/txn/report.js.map +1 -0
  207. package/dist/commands/subsystem/txn/txn.js +196 -0
  208. package/dist/commands/subsystem/txn/txn.js.map +1 -0
  209. package/dist/commands/subsystem/txn/views.js +249 -0
  210. package/dist/commands/subsystem/txn/views.js.map +1 -0
  211. package/dist/commands/tasks/actions.js +107 -0
  212. package/dist/commands/tasks/actions.js.map +1 -0
  213. package/dist/commands/tasks/render.js +253 -0
  214. package/dist/commands/tasks/render.js.map +1 -0
  215. package/dist/commands/tasks/tasks.js +119 -0
  216. package/dist/commands/tasks/tasks.js.map +1 -0
  217. package/dist/commands/unarchive/manifest.js +176 -0
  218. package/dist/commands/unarchive/manifest.js.map +1 -0
  219. package/dist/commands/unarchive/restore.js +254 -0
  220. package/dist/commands/unarchive/restore.js.map +1 -0
  221. package/dist/commands/unarchive/unarchive.js +59 -0
  222. package/dist/commands/unarchive/unarchive.js.map +1 -0
  223. package/dist/commands/validate/arch-coverage.js +245 -0
  224. package/dist/commands/validate/arch-coverage.js.map +1 -0
  225. package/dist/commands/validate/checks/fleet-shape.js +204 -0
  226. package/dist/commands/validate/checks/fleet-shape.js.map +1 -0
  227. package/dist/commands/validate/checks/health-deps.js +58 -0
  228. package/dist/commands/validate/checks/health-deps.js.map +1 -0
  229. package/dist/commands/validate/checks/introduced.js +102 -0
  230. package/dist/commands/validate/checks/introduced.js.map +1 -0
  231. package/dist/commands/validate/checks/requirements.js +264 -0
  232. package/dist/commands/validate/checks/requirements.js.map +1 -0
  233. package/dist/commands/validate/checks/sources.js +85 -0
  234. package/dist/commands/validate/checks/sources.js.map +1 -0
  235. package/dist/commands/validate/coverage/covers-after.js +105 -0
  236. package/dist/commands/validate/coverage/covers-after.js.map +1 -0
  237. package/dist/commands/validate/feature.js +222 -0
  238. package/dist/commands/validate/feature.js.map +1 -0
  239. package/dist/commands/validate/fleet/census.js +93 -0
  240. package/dist/commands/validate/fleet/census.js.map +1 -0
  241. package/dist/commands/validate/fleet/kind-tags.js +39 -0
  242. package/dist/commands/validate/fleet/kind-tags.js.map +1 -0
  243. package/dist/commands/validate/fleet/landscape.js +371 -0
  244. package/dist/commands/validate/fleet/landscape.js.map +1 -0
  245. package/dist/commands/validate/fleet/load.js +118 -0
  246. package/dist/commands/validate/fleet/load.js.map +1 -0
  247. package/dist/commands/validate/fleet/map/attest.js +98 -0
  248. package/dist/commands/validate/fleet/map/attest.js.map +1 -0
  249. package/dist/commands/validate/fleet/map/bindings.js +107 -0
  250. package/dist/commands/validate/fleet/map/bindings.js.map +1 -0
  251. package/dist/commands/validate/fleet/map/consumers.js +244 -0
  252. package/dist/commands/validate/fleet/map/consumers.js.map +1 -0
  253. package/dist/commands/validate/fleet/map/isolation.js +116 -0
  254. package/dist/commands/validate/fleet/map/isolation.js.map +1 -0
  255. package/dist/commands/validate/fleet/map/usecases.js +54 -0
  256. package/dist/commands/validate/fleet/map/usecases.js.map +1 -0
  257. package/dist/commands/validate/fleet/obligations.js +266 -0
  258. package/dist/commands/validate/fleet/obligations.js.map +1 -0
  259. package/dist/commands/validate/fleet/scorecard/adoption.js +102 -0
  260. package/dist/commands/validate/fleet/scorecard/adoption.js.map +1 -0
  261. package/dist/commands/validate/fleet/scorecard/contracts.js +98 -0
  262. package/dist/commands/validate/fleet/scorecard/contracts.js.map +1 -0
  263. package/dist/commands/validate/fleet/scorecard/print.js +71 -0
  264. package/dist/commands/validate/fleet/scorecard/print.js.map +1 -0
  265. package/dist/commands/validate/fleet/scorecard/scorecard.js +162 -0
  266. package/dist/commands/validate/fleet/scorecard/scorecard.js.map +1 -0
  267. package/dist/commands/validate/fleet/usecases/place.js +13 -0
  268. package/dist/commands/validate/fleet/usecases/place.js.map +1 -0
  269. package/dist/commands/validate/fleet/views/fleet-project.js +217 -0
  270. package/dist/commands/validate/fleet/views/fleet-project.js.map +1 -0
  271. package/dist/commands/validate/fleet/views/ids.js +75 -0
  272. package/dist/commands/validate/fleet/views/ids.js.map +1 -0
  273. package/dist/commands/validate/fleet/views/projects.js +278 -0
  274. package/dist/commands/validate/fleet/views/projects.js.map +1 -0
  275. package/dist/commands/validate/fleet/views/root-documents.js +83 -0
  276. package/dist/commands/validate/fleet/views/root-documents.js.map +1 -0
  277. package/dist/commands/validate/fleet/views/stale.js +52 -0
  278. package/dist/commands/validate/fleet/views/stale.js.map +1 -0
  279. package/dist/commands/validate/links/corpus.js +89 -0
  280. package/dist/commands/validate/links/corpus.js.map +1 -0
  281. package/dist/commands/validate/links/glossary.js +75 -0
  282. package/dist/commands/validate/links/glossary.js.map +1 -0
  283. package/dist/commands/validate/render/repeats.js +63 -0
  284. package/dist/commands/validate/render/repeats.js.map +1 -0
  285. package/dist/commands/validate/render/rollups.js +115 -0
  286. package/dist/commands/validate/render/rollups.js.map +1 -0
  287. package/dist/commands/validate/render/text.js +199 -0
  288. package/dist/commands/validate/render/text.js.map +1 -0
  289. package/dist/commands/validate/report.js +145 -0
  290. package/dist/commands/validate/report.js.map +1 -0
  291. package/dist/commands/validate/scope.js +113 -0
  292. package/dist/commands/validate/scope.js.map +1 -0
  293. package/dist/commands/validate/service/api.js +252 -0
  294. package/dist/commands/validate/service/api.js.map +1 -0
  295. package/dist/commands/validate/service/contracts/generated.js +134 -0
  296. package/dist/commands/validate/service/contracts/generated.js.map +1 -0
  297. package/dist/commands/validate/service/events/events.js +241 -0
  298. package/dist/commands/validate/service/events/events.js.map +1 -0
  299. package/dist/commands/validate/service/events/message-producers.js +77 -0
  300. package/dist/commands/validate/service/events/message-producers.js.map +1 -0
  301. package/dist/commands/validate/service/evidence-pins.js +177 -0
  302. package/dist/commands/validate/service/evidence-pins.js.map +1 -0
  303. package/dist/commands/validate/service/model/diverged.js +226 -0
  304. package/dist/commands/validate/service/model/diverged.js.map +1 -0
  305. package/dist/commands/validate/service/model/grade.js +163 -0
  306. package/dist/commands/validate/service/model/grade.js.map +1 -0
  307. package/dist/commands/validate/service/service.js +310 -0
  308. package/dist/commands/validate/service/service.js.map +1 -0
  309. package/dist/commands/validate/service/specs.js +279 -0
  310. package/dist/commands/validate/service/specs.js.map +1 -0
  311. package/dist/commands/validate/service/spine.js +148 -0
  312. package/dist/commands/validate/service/spine.js.map +1 -0
  313. package/dist/commands/validate/service/usecases/tags.js +113 -0
  314. package/dist/commands/validate/service/usecases/tags.js.map +1 -0
  315. package/dist/commands/validate/service/usecases/usecases.js +209 -0
  316. package/dist/commands/validate/service/usecases/usecases.js.map +1 -0
  317. package/dist/commands/validate/validate.js +363 -0
  318. package/dist/commands/validate/validate.js.map +1 -0
  319. package/dist/commands/verify/cross/diff.js +178 -0
  320. package/dist/commands/verify/cross/diff.js.map +1 -0
  321. package/dist/commands/verify/evidence/contract.js +32 -0
  322. package/dist/commands/verify/evidence/contract.js.map +1 -0
  323. package/dist/commands/verify/evidence/pins.js +52 -0
  324. package/dist/commands/verify/evidence/pins.js.map +1 -0
  325. package/dist/commands/verify/evidence/read.js +81 -0
  326. package/dist/commands/verify/evidence/read.js.map +1 -0
  327. package/dist/commands/verify/frozen.js +263 -0
  328. package/dist/commands/verify/frozen.js.map +1 -0
  329. package/dist/commands/verify/record.js +278 -0
  330. package/dist/commands/verify/record.js.map +1 -0
  331. package/dist/commands/verify/report.js +206 -0
  332. package/dist/commands/verify/report.js.map +1 -0
  333. package/dist/commands/verify/results.js +328 -0
  334. package/dist/commands/verify/results.js.map +1 -0
  335. package/dist/commands/verify/verify.js +220 -0
  336. package/dist/commands/verify/verify.js.map +1 -0
  337. package/dist/commands/vouch/contract.js +11 -0
  338. package/dist/commands/vouch/contract.js.map +1 -0
  339. package/dist/commands/vouch/pack/contract.js +2 -0
  340. package/dist/commands/vouch/pack/contract.js.map +1 -0
  341. package/dist/commands/vouch/pack/pack.js +266 -0
  342. package/dist/commands/vouch/pack/pack.js.map +1 -0
  343. package/dist/commands/vouch/pack/print.js +266 -0
  344. package/dist/commands/vouch/pack/print.js.map +1 -0
  345. package/dist/commands/vouch/pack/sections.js +141 -0
  346. package/dist/commands/vouch/pack/sections.js.map +1 -0
  347. package/dist/commands/vouch/prompt/confirm.js +46 -0
  348. package/dist/commands/vouch/prompt/confirm.js.map +1 -0
  349. package/dist/commands/vouch/report.js +101 -0
  350. package/dist/commands/vouch/report.js.map +1 -0
  351. package/dist/commands/vouch/run.js +230 -0
  352. package/dist/commands/vouch/run.js.map +1 -0
  353. package/dist/commands/vouch/sample/plan.js +111 -0
  354. package/dist/commands/vouch/sample/plan.js.map +1 -0
  355. package/dist/commands/vouch/sample/print.js +109 -0
  356. package/dist/commands/vouch/sample/print.js.map +1 -0
  357. package/dist/commands/vouch/vet/verify.js +155 -0
  358. package/dist/commands/vouch/vet/verify.js.map +1 -0
  359. package/dist/commands/vouch/vouch.js +169 -0
  360. package/dist/commands/vouch/vouch.js.map +1 -0
  361. package/dist/core/agent/agents-md/command-map.js +299 -0
  362. package/dist/core/agent/agents-md/command-map.js.map +1 -0
  363. package/dist/core/agent/agents-md/map/explain.js +46 -0
  364. package/dist/core/agent/agents-md/map/explain.js.map +1 -0
  365. package/dist/core/agent/agents-md/map/lenses/context.js +50 -0
  366. package/dist/core/agent/agents-md/map/lenses/context.js.map +1 -0
  367. package/dist/core/agent/agents-md/map/lenses/diff.js +59 -0
  368. package/dist/core/agent/agents-md/map/lenses/diff.js.map +1 -0
  369. package/dist/core/agent/agents-md/map/lenses/gate.js +65 -0
  370. package/dist/core/agent/agents-md/map/lenses/gate.js.map +1 -0
  371. package/dist/core/agent/agents-md/map/mcp.js +44 -0
  372. package/dist/core/agent/agents-md/map/mcp.js.map +1 -0
  373. package/dist/core/agent/agents-md/map/status.js +78 -0
  374. package/dist/core/agent/agents-md/map/status.js.map +1 -0
  375. package/dist/core/agent/agents-md/map/subsystem.js +104 -0
  376. package/dist/core/agent/agents-md/map/subsystem.js.map +1 -0
  377. package/dist/core/agent/agents-md/map/usecases.js +138 -0
  378. package/dist/core/agent/agents-md/map/usecases.js.map +1 -0
  379. package/dist/core/agent/agents-md/refusals.js +273 -0
  380. package/dist/core/agent/agents-md/refusals.js.map +1 -0
  381. package/dist/core/agent/agents-md.js +203 -0
  382. package/dist/core/agent/agents-md.js.map +1 -0
  383. package/dist/core/{agents-stamp.js → agent/agents-stamp.js} +60 -0
  384. package/dist/core/agent/agents-stamp.js.map +1 -0
  385. package/dist/core/agent/contract.js +2 -0
  386. package/dist/core/agent/contract.js.map +1 -0
  387. package/dist/core/agent/protocol.js +193 -0
  388. package/dist/core/agent/protocol.js.map +1 -0
  389. package/dist/core/agent/scaffold.js +254 -0
  390. package/dist/core/agent/scaffold.js.map +1 -0
  391. package/dist/core/agent/support/report.js +144 -0
  392. package/dist/core/agent/support/report.js.map +1 -0
  393. package/dist/core/agent/tools/dialects.js +151 -0
  394. package/dist/core/agent/tools/dialects.js.map +1 -0
  395. package/dist/core/agent/tools/registry.js +193 -0
  396. package/dist/core/agent/tools/registry.js.map +1 -0
  397. package/dist/core/agent/workflows/adopt.js +280 -0
  398. package/dist/core/agent/workflows/adopt.js.map +1 -0
  399. package/dist/core/agent/workflows/check.js +373 -0
  400. package/dist/core/agent/workflows/check.js.map +1 -0
  401. package/dist/core/agent/workflows/closing.js +323 -0
  402. package/dist/core/agent/workflows/closing.js.map +1 -0
  403. package/dist/core/agent/workflows/feature.js +220 -0
  404. package/dist/core/agent/workflows/feature.js.map +1 -0
  405. package/dist/core/agent/workflows/implement.js +188 -0
  406. package/dist/core/agent/workflows/implement.js.map +1 -0
  407. package/dist/core/agent/workflows/reference/authoring.js +311 -0
  408. package/dist/core/agent/workflows/reference/authoring.js.map +1 -0
  409. package/dist/core/agent/workflows/reference/codes.js +67 -0
  410. package/dist/core/agent/workflows/reference/codes.js.map +1 -0
  411. package/dist/core/agent/workflows/reference/done-check.js +210 -0
  412. package/dist/core/agent/workflows/reference/done-check.js.map +1 -0
  413. package/dist/core/agent/workflows/reference/drawing/drawing.js +253 -0
  414. package/dist/core/agent/workflows/reference/drawing/drawing.js.map +1 -0
  415. package/dist/core/agent/workflows/reference/reference.js +19 -0
  416. package/dist/core/agent/workflows/reference/reference.js.map +1 -0
  417. package/dist/core/agent/workflows/reference/spine.js +338 -0
  418. package/dist/core/agent/workflows/reference/spine.js.map +1 -0
  419. package/dist/core/asyncapi/baseline/plan.js +43 -0
  420. package/dist/core/asyncapi/baseline/plan.js.map +1 -0
  421. package/dist/core/asyncapi/baseline/surfaces.js +54 -0
  422. package/dist/core/asyncapi/baseline/surfaces.js.map +1 -0
  423. package/dist/core/asyncapi/depth.js +164 -0
  424. package/dist/core/asyncapi/depth.js.map +1 -0
  425. package/dist/core/asyncapi/digest.js +146 -0
  426. package/dist/core/asyncapi/digest.js.map +1 -0
  427. package/dist/core/asyncapi/merge/components.js +92 -0
  428. package/dist/core/asyncapi/merge/components.js.map +1 -0
  429. package/dist/core/asyncapi/merge/error.js +38 -0
  430. package/dist/core/asyncapi/merge/error.js.map +1 -0
  431. package/dist/core/asyncapi/merge/markers.js +290 -0
  432. package/dist/core/asyncapi/merge/markers.js.map +1 -0
  433. package/dist/core/asyncapi/merge/merge.js +195 -0
  434. package/dist/core/asyncapi/merge/merge.js.map +1 -0
  435. package/dist/core/asyncapi/merge/pin.js +83 -0
  436. package/dist/core/asyncapi/merge/pin.js.map +1 -0
  437. package/dist/core/asyncapi/model.js +11 -0
  438. package/dist/core/asyncapi/model.js.map +1 -0
  439. package/dist/core/asyncapi/producers.js +50 -0
  440. package/dist/core/asyncapi/producers.js.map +1 -0
  441. package/dist/core/asyncapi/read.js +263 -0
  442. package/dist/core/asyncapi/read.js.map +1 -0
  443. package/dist/core/brief/brief.js +285 -0
  444. package/dist/core/brief/brief.js.map +1 -0
  445. package/dist/core/brief/checks.js +385 -0
  446. package/dist/core/brief/checks.js.map +1 -0
  447. package/dist/core/brief/landscape.js +273 -0
  448. package/dist/core/brief/landscape.js.map +1 -0
  449. package/dist/core/brief/map/extend.js +84 -0
  450. package/dist/core/brief/map/extend.js.map +1 -0
  451. package/dist/core/brief/map/owed.js +266 -0
  452. package/dist/core/brief/map/owed.js.map +1 -0
  453. package/dist/core/brief/targets.js +304 -0
  454. package/dist/core/brief/targets.js.map +1 -0
  455. package/dist/core/brief/unchecked.js +58 -0
  456. package/dist/core/brief/unchecked.js.map +1 -0
  457. package/dist/core/c4/arch.js +190 -0
  458. package/dist/core/c4/arch.js.map +1 -0
  459. package/dist/core/c4/direction/direction.js +114 -0
  460. package/dist/core/c4/direction/direction.js.map +1 -0
  461. package/dist/core/c4/likec4.js +243 -0
  462. package/dist/core/c4/likec4.js.map +1 -0
  463. package/dist/core/c4/locate/unlocated.js +150 -0
  464. package/dist/core/c4/locate/unlocated.js.map +1 -0
  465. package/dist/core/c4/parsed/deployment.js +160 -0
  466. package/dist/core/c4/parsed/deployment.js.map +1 -0
  467. package/dist/core/c4/parsed/dynamic-views.js +132 -0
  468. package/dist/core/c4/parsed/dynamic-views.js.map +1 -0
  469. package/dist/core/c4/parsed/specification.js +78 -0
  470. package/dist/core/c4/parsed/specification.js.map +1 -0
  471. package/dist/core/c4/parsed/values.js +110 -0
  472. package/dist/core/c4/parsed/values.js.map +1 -0
  473. package/dist/core/c4/parsed/view-ids.js +113 -0
  474. package/dist/core/c4/parsed/view-ids.js.map +1 -0
  475. package/dist/core/c4/prefetch/fleet.js +134 -0
  476. package/dist/core/c4/prefetch/fleet.js.map +1 -0
  477. package/dist/core/c4/project/architecture.js +161 -0
  478. package/dist/core/c4/project/architecture.js.map +1 -0
  479. package/dist/core/c4/project/batch.js +140 -0
  480. package/dist/core/c4/project/batch.js.map +1 -0
  481. package/dist/core/c4/project/documents.js +89 -0
  482. package/dist/core/c4/project/documents.js.map +1 -0
  483. package/dist/core/c4/project/load.js +219 -0
  484. package/dist/core/c4/project/load.js.map +1 -0
  485. package/dist/core/c4/project/staged.js +277 -0
  486. package/dist/core/c4/project/staged.js.map +1 -0
  487. package/dist/core/c4/resolve/attested.js +0 -0
  488. package/dist/core/c4/resolve/attested.js.map +1 -0
  489. package/dist/core/c4/resolve/external.js +51 -0
  490. package/dist/core/c4/resolve/external.js.map +1 -0
  491. package/dist/core/c4/resolve/service.js +174 -0
  492. package/dist/core/c4/resolve/service.js.map +1 -0
  493. package/dist/core/c4/resolve/steps.js +290 -0
  494. package/dist/core/c4/resolve/steps.js.map +1 -0
  495. package/dist/core/c4/resolve/systems.js +154 -0
  496. package/dist/core/c4/resolve/systems.js.map +1 -0
  497. package/dist/core/c4/root-project/exclude.js +352 -0
  498. package/dist/core/c4/root-project/exclude.js.map +1 -0
  499. package/dist/core/c4/seed/fleet-file.js +201 -0
  500. package/dist/core/c4/seed/fleet-file.js.map +1 -0
  501. package/dist/core/c4/seed/items.js +91 -0
  502. package/dist/core/c4/seed/items.js.map +1 -0
  503. package/dist/core/c4/seed/stamp.js +48 -0
  504. package/dist/core/c4/seed/stamp.js.map +1 -0
  505. package/dist/core/c4/seed/template.js +173 -0
  506. package/dist/core/c4/seed/template.js.map +1 -0
  507. package/dist/core/c4/service-model/created/models.js +96 -0
  508. package/dist/core/c4/service-model/created/models.js.map +1 -0
  509. package/dist/core/c4/service-model/documents.js +47 -0
  510. package/dist/core/c4/service-model/documents.js.map +1 -0
  511. package/dist/core/c4/service-model/fleet/extending.js +82 -0
  512. package/dist/core/c4/service-model/fleet/extending.js.map +1 -0
  513. package/dist/core/c4/service-model/load.js +165 -0
  514. package/dist/core/c4/service-model/load.js.map +1 -0
  515. package/dist/core/c4/service-model/renderer.js +128 -0
  516. package/dist/core/c4/service-model/renderer.js.map +1 -0
  517. package/dist/core/c4/service-model/shape.js +106 -0
  518. package/dist/core/c4/service-model/shape.js.map +1 -0
  519. package/dist/core/c4/service-model/slice.js +188 -0
  520. package/dist/core/c4/service-model/slice.js.map +1 -0
  521. package/dist/core/c4/source-mask.js +369 -0
  522. package/dist/core/c4/source-mask.js.map +1 -0
  523. package/dist/core/c4/source-scan.js +308 -0
  524. package/dist/core/c4/source-scan.js.map +1 -0
  525. package/dist/core/c4/splice/authored-source.js +167 -0
  526. package/dist/core/c4/splice/authored-source.js.map +1 -0
  527. package/dist/core/c4/splice/contract.js +30 -0
  528. package/dist/core/c4/splice/contract.js.map +1 -0
  529. package/dist/core/c4/splice/delta-blocks.js +126 -0
  530. package/dist/core/c4/splice/delta-blocks.js.map +1 -0
  531. package/dist/core/c4/splice/identity/declared.js +87 -0
  532. package/dist/core/c4/splice/identity/declared.js.map +1 -0
  533. package/dist/core/c4/splice/identity/edges.js +73 -0
  534. package/dist/core/c4/splice/identity/edges.js.map +1 -0
  535. package/dist/core/c4/splice/identity/existing.js +80 -0
  536. package/dist/core/c4/splice/identity/existing.js.map +1 -0
  537. package/dist/core/c4/splice/identity/interior.js +80 -0
  538. package/dist/core/c4/splice/identity/interior.js.map +1 -0
  539. package/dist/core/c4/splice/identity/owner.js +50 -0
  540. package/dist/core/c4/splice/identity/owner.js.map +1 -0
  541. package/dist/core/c4/splice/landscape-merge.js +337 -0
  542. package/dist/core/c4/splice/landscape-merge.js.map +1 -0
  543. package/dist/core/c4/splice/model/merge.js +151 -0
  544. package/dist/core/c4/splice/model/merge.js.map +1 -0
  545. package/dist/core/c4/splice/placement.js +298 -0
  546. package/dist/core/c4/splice/placement.js.map +1 -0
  547. package/dist/core/c4/splice/text/spot.js +131 -0
  548. package/dist/core/c4/splice/text/spot.js.map +1 -0
  549. package/dist/core/c4/workspace.js +166 -0
  550. package/dist/core/c4/workspace.js.map +1 -0
  551. package/dist/core/capabilities/authoring/notes.js +141 -0
  552. package/dist/core/capabilities/authoring/notes.js.map +1 -0
  553. package/dist/core/capabilities/capabilities.js +124 -0
  554. package/dist/core/capabilities/capabilities.js.map +1 -0
  555. package/dist/core/capabilities/delta/doc.js +47 -0
  556. package/dist/core/capabilities/delta/doc.js.map +1 -0
  557. package/dist/core/capabilities/delta/overlay.js +129 -0
  558. package/dist/core/capabilities/delta/overlay.js.map +1 -0
  559. package/dist/core/capabilities/delta/summary.js +57 -0
  560. package/dist/core/capabilities/delta/summary.js.map +1 -0
  561. package/dist/core/capabilities/delta/tree.js +43 -0
  562. package/dist/core/capabilities/delta/tree.js.map +1 -0
  563. package/dist/core/capabilities/delta/uncovered.js +222 -0
  564. package/dist/core/capabilities/delta/uncovered.js.map +1 -0
  565. package/dist/core/capabilities/findings.js +338 -0
  566. package/dist/core/capabilities/findings.js.map +1 -0
  567. package/dist/core/capabilities/realizes/findings.js +174 -0
  568. package/dist/core/capabilities/realizes/findings.js.map +1 -0
  569. package/dist/core/capabilities/realizes/join.js +123 -0
  570. package/dist/core/capabilities/realizes/join.js.map +1 -0
  571. package/dist/core/capabilities/rollup.js +205 -0
  572. package/dist/core/capabilities/rollup.js.map +1 -0
  573. package/dist/core/capabilities/tree.js +104 -0
  574. package/dist/core/capabilities/tree.js.map +1 -0
  575. package/dist/core/capabilities/usecase-join.js +267 -0
  576. package/dist/core/capabilities/usecase-join.js.map +1 -0
  577. package/dist/core/coherence/authoring/scaffold.js +185 -0
  578. package/dist/core/coherence/authoring/scaffold.js.map +1 -0
  579. package/dist/core/coherence/authoring/sentinels.js +75 -0
  580. package/dist/core/coherence/authoring/sentinels.js.map +1 -0
  581. package/dist/core/coherence/calls/called.js +52 -0
  582. package/dist/core/coherence/calls/called.js.map +1 -0
  583. package/dist/core/coherence/coherence.js +332 -0
  584. package/dist/core/coherence/coherence.js.map +1 -0
  585. package/dist/core/coherence/consumed/operations.js +70 -0
  586. package/dist/core/coherence/consumed/operations.js.map +1 -0
  587. package/dist/core/coherence/consumed/refusal.js +38 -0
  588. package/dist/core/coherence/consumed/refusal.js.map +1 -0
  589. package/dist/core/coherence/covers/health.js +85 -0
  590. package/dist/core/coherence/covers/health.js.map +1 -0
  591. package/dist/core/coherence/declared.js +295 -0
  592. package/dist/core/coherence/declared.js.map +1 -0
  593. package/dist/core/coherence/events/declared.js +191 -0
  594. package/dist/core/coherence/events/declared.js.map +1 -0
  595. package/dist/core/coherence/events/events.js +335 -0
  596. package/dist/core/coherence/events/events.js.map +1 -0
  597. package/dist/core/coherence/events/grades.js +189 -0
  598. package/dist/core/coherence/events/grades.js.map +1 -0
  599. package/dist/core/coherence/events/lookups.js +63 -0
  600. package/dist/core/coherence/events/lookups.js.map +1 -0
  601. package/dist/core/coherence/events/produced.js +100 -0
  602. package/dist/core/coherence/events/produced.js.map +1 -0
  603. package/dist/core/coherence/living.js +198 -0
  604. package/dist/core/coherence/living.js.map +1 -0
  605. package/dist/core/coherence/lookups.js +95 -0
  606. package/dist/core/coherence/lookups.js.map +1 -0
  607. package/dist/core/coherence/pending.js +39 -0
  608. package/dist/core/coherence/pending.js.map +1 -0
  609. package/dist/core/coherence/retired/archived.js +285 -0
  610. package/dist/core/coherence/retired/archived.js.map +1 -0
  611. package/dist/core/coherence/retired/event-pair.js +62 -0
  612. package/dist/core/coherence/retired/event-pair.js.map +1 -0
  613. package/dist/core/coherence/retired/merged.js +79 -0
  614. package/dist/core/coherence/retired/merged.js.map +1 -0
  615. package/dist/core/coherence/retired/retirement.js +49 -0
  616. package/dist/core/coherence/retired/retirement.js.map +1 -0
  617. package/dist/core/coherence/retired/revival/arrivals.js +131 -0
  618. package/dist/core/coherence/retired/revival/arrivals.js.map +1 -0
  619. package/dist/core/coherence/retired/revival/revived.js +297 -0
  620. package/dist/core/coherence/retired/revival/revived.js.map +1 -0
  621. package/dist/core/conflict-markers.js +60 -0
  622. package/dist/core/conflict-markers.js.map +1 -0
  623. package/dist/core/consumers/after.js +113 -0
  624. package/dist/core/consumers/after.js.map +1 -0
  625. package/dist/core/consumers/consumers.js +296 -0
  626. package/dist/core/consumers/consumers.js.map +1 -0
  627. package/dist/core/consumers/current.js +211 -0
  628. package/dist/core/consumers/current.js.map +1 -0
  629. package/dist/core/consumers/scan.js +46 -0
  630. package/dist/core/consumers/scan.js.map +1 -0
  631. package/dist/core/consumers/state.js +27 -0
  632. package/dist/core/consumers/state.js.map +1 -0
  633. package/dist/core/delta/claims.js +73 -0
  634. package/dist/core/delta/claims.js.map +1 -0
  635. package/dist/core/delta/delta.js +341 -0
  636. package/dist/core/delta/delta.js.map +1 -0
  637. package/dist/core/delta/document.js +177 -0
  638. package/dist/core/delta/document.js.map +1 -0
  639. package/dist/core/delta/scope.js +48 -0
  640. package/dist/core/delta/scope.js.map +1 -0
  641. package/dist/core/delta/select.js +237 -0
  642. package/dist/core/delta/select.js.map +1 -0
  643. package/dist/core/dependencies/dependencies.js +141 -0
  644. package/dist/core/dependencies/dependencies.js.map +1 -0
  645. package/dist/core/dependencies/facts.js +165 -0
  646. package/dist/core/dependencies/facts.js.map +1 -0
  647. package/dist/core/dependencies/fanin.js +88 -0
  648. package/dist/core/dependencies/fanin.js.map +1 -0
  649. package/dist/core/dependencies/graph.js +106 -0
  650. package/dist/core/dependencies/graph.js.map +1 -0
  651. package/dist/core/deployment/delta.js +191 -0
  652. package/dist/core/deployment/delta.js.map +1 -0
  653. package/dist/core/deployment/objects.js +145 -0
  654. package/dist/core/deployment/objects.js.map +1 -0
  655. package/dist/core/diff/base-git.js +230 -0
  656. package/dist/core/diff/base-git.js.map +1 -0
  657. package/dist/core/diff/base-state.js +237 -0
  658. package/dist/core/diff/base-state.js.map +1 -0
  659. package/dist/core/diff/joins.js +136 -0
  660. package/dist/core/diff/joins.js.map +1 -0
  661. package/dist/core/diff/scope/changed-paths.js +204 -0
  662. package/dist/core/diff/scope/changed-paths.js.map +1 -0
  663. package/dist/core/diff/scope/edges.js +82 -0
  664. package/dist/core/diff/scope/edges.js.map +1 -0
  665. package/dist/core/diff/semantic.js +312 -0
  666. package/dist/core/diff/semantic.js.map +1 -0
  667. package/dist/core/docs.js +37 -85
  668. package/dist/core/docs.js.map +1 -1
  669. package/dist/core/doctor/agents.js +238 -0
  670. package/dist/core/doctor/agents.js.map +1 -0
  671. package/dist/core/doctor/config.js +139 -0
  672. package/dist/core/doctor/config.js.map +1 -0
  673. package/dist/core/doctor/doctor.js +355 -0
  674. package/dist/core/doctor/doctor.js.map +1 -0
  675. package/dist/core/doctor/report.js +13 -0
  676. package/dist/core/doctor/report.js.map +1 -0
  677. package/dist/core/doctor/reports/scan.js +242 -0
  678. package/dist/core/doctor/reports/scan.js.map +1 -0
  679. package/dist/core/doctor/residue.js +110 -0
  680. package/dist/core/doctor/residue.js.map +1 -0
  681. package/dist/core/document/apply.js +224 -0
  682. package/dist/core/document/apply.js.map +1 -0
  683. package/dist/core/{frontmatter.js → document/frontmatter.js} +103 -2
  684. package/dist/core/document/frontmatter.js.map +1 -0
  685. package/dist/core/document/grammar/directives.js +143 -0
  686. package/dist/core/document/grammar/directives.js.map +1 -0
  687. package/dist/core/document/parse.js +286 -0
  688. package/dist/core/document/parse.js.map +1 -0
  689. package/dist/core/document/scenarios.js +238 -0
  690. package/dist/core/document/scenarios.js.map +1 -0
  691. package/dist/core/document/spec.js +234 -0
  692. package/dist/core/document/spec.js.map +1 -0
  693. package/dist/core/{config.js → envelope/config.js} +89 -18
  694. package/dist/core/envelope/config.js.map +1 -0
  695. package/dist/core/envelope/json.js +209 -0
  696. package/dist/core/envelope/json.js.map +1 -0
  697. package/dist/core/{version.js → envelope/version.js} +3 -3
  698. package/dist/core/envelope/version.js.map +1 -0
  699. package/dist/core/explain/families.js +180 -0
  700. package/dist/core/explain/families.js.map +1 -0
  701. package/dist/core/explain/fix-tables.js +178 -0
  702. package/dist/core/explain/fix-tables.js.map +1 -0
  703. package/dist/core/explain/lookup.js +194 -0
  704. package/dist/core/explain/lookup.js.map +1 -0
  705. package/dist/core/explain/refusals.js +49 -0
  706. package/dist/core/explain/refusals.js.map +1 -0
  707. package/dist/core/explain/terms/documents.js +227 -0
  708. package/dist/core/explain/terms/documents.js.map +1 -0
  709. package/dist/core/explain/terms/done-check.js +144 -0
  710. package/dist/core/explain/terms/done-check.js.map +1 -0
  711. package/dist/core/explain/terms/entry.js +14 -0
  712. package/dist/core/explain/terms/entry.js.map +1 -0
  713. package/dist/core/explain/terms/stages.js +71 -0
  714. package/dist/core/explain/terms/stages.js.map +1 -0
  715. package/dist/core/explain/terms/tasks.js +97 -0
  716. package/dist/core/explain/terms/tasks.js.map +1 -0
  717. package/dist/core/explain/terms.js +103 -0
  718. package/dist/core/explain/terms.js.map +1 -0
  719. package/dist/core/explore/describe.js +105 -0
  720. package/dist/core/explore/describe.js.map +1 -0
  721. package/dist/core/explore/explore.js +204 -0
  722. package/dist/core/explore/explore.js.map +1 -0
  723. package/dist/core/fleet-context.js +174 -146
  724. package/dist/core/fleet-context.js.map +1 -1
  725. package/dist/core/gate/checks.js +208 -0
  726. package/dist/core/gate/checks.js.map +1 -0
  727. package/dist/core/gate/partners.js +246 -0
  728. package/dist/core/gate/partners.js.map +1 -0
  729. package/dist/core/gate/report.js +47 -0
  730. package/dist/core/gate/report.js.map +1 -0
  731. package/dist/core/gate/verification.js +176 -0
  732. package/dist/core/gate/verification.js.map +1 -0
  733. package/dist/core/gherkin/digest.js +60 -0
  734. package/dist/core/gherkin/digest.js.map +1 -0
  735. package/dist/core/gherkin/emit.js +177 -0
  736. package/dist/core/gherkin/emit.js.map +1 -0
  737. package/dist/core/gherkin/read.js +76 -0
  738. package/dist/core/gherkin/read.js.map +1 -0
  739. package/dist/core/gherkin/stale.js +210 -0
  740. package/dist/core/gherkin/stale.js.map +1 -0
  741. package/dist/core/gherkin/stamp.js +77 -0
  742. package/dist/core/gherkin/stamp.js.map +1 -0
  743. package/dist/core/gherkin/steps/catalogue.js +154 -0
  744. package/dist/core/gherkin/steps/catalogue.js.map +1 -0
  745. package/dist/core/gherkin/steps/inventory.js +98 -0
  746. package/dist/core/gherkin/steps/inventory.js.map +1 -0
  747. package/dist/core/gherkin/steps/phrase.js +72 -0
  748. package/dist/core/gherkin/steps/phrase.js.map +1 -0
  749. package/dist/core/glossary/delta.js +109 -0
  750. package/dist/core/glossary/delta.js.map +1 -0
  751. package/dist/core/glossary/tree.js +73 -0
  752. package/dist/core/glossary/tree.js.map +1 -0
  753. package/dist/core/{concurrency.js → kernel/concurrency.js} +19 -0
  754. package/dist/core/kernel/concurrency.js.map +1 -0
  755. package/dist/core/{document-bytes.js → kernel/document-bytes.js} +1 -1
  756. package/dist/core/kernel/document-bytes.js.map +1 -0
  757. package/dist/core/kernel/fences.js +42 -0
  758. package/dist/core/kernel/fences.js.map +1 -0
  759. package/dist/core/kernel/ids/capability.js +72 -0
  760. package/dist/core/kernel/ids/capability.js.map +1 -0
  761. package/dist/core/kernel/ids/dirs.js +33 -0
  762. package/dist/core/kernel/ids/dirs.js.map +1 -0
  763. package/dist/core/kernel/ids/feature.js +75 -0
  764. package/dist/core/kernel/ids/feature.js.map +1 -0
  765. package/dist/core/kernel/ids/fqn/ancestors.js +65 -0
  766. package/dist/core/kernel/ids/fqn/ancestors.js.map +1 -0
  767. package/dist/core/kernel/ids/service.js +156 -0
  768. package/dist/core/kernel/ids/service.js.map +1 -0
  769. package/dist/core/kernel/ids/subsystem.js +63 -0
  770. package/dist/core/kernel/ids/subsystem.js.map +1 -0
  771. package/dist/core/{path-safety.js → kernel/path-safety.js} +56 -4
  772. package/dist/core/kernel/path-safety.js.map +1 -0
  773. package/dist/core/{records.js → kernel/records.js} +11 -0
  774. package/dist/core/kernel/records.js.map +1 -0
  775. package/dist/core/links/backlinks.js +66 -0
  776. package/dist/core/links/backlinks.js.map +1 -0
  777. package/dist/core/links/case.js +74 -0
  778. package/dist/core/links/case.js.map +1 -0
  779. package/dist/core/links/corpus.js +118 -0
  780. package/dist/core/links/corpus.js.map +1 -0
  781. package/dist/core/links/findings.js +110 -0
  782. package/dist/core/links/findings.js.map +1 -0
  783. package/dist/core/links/parse.js +265 -0
  784. package/dist/core/links/parse.js.map +1 -0
  785. package/dist/core/mcp/argv.js +212 -0
  786. package/dist/core/mcp/argv.js.map +1 -0
  787. package/dist/core/mcp/author-tools.js +73 -0
  788. package/dist/core/mcp/author-tools.js.map +1 -0
  789. package/dist/core/mcp/framing.js +46 -0
  790. package/dist/core/mcp/framing.js.map +1 -0
  791. package/dist/core/mcp/protocol.js +280 -0
  792. package/dist/core/mcp/protocol.js.map +1 -0
  793. package/dist/core/mcp/tools.js +324 -0
  794. package/dist/core/mcp/tools.js.map +1 -0
  795. package/dist/core/obligations/obligations.js +106 -0
  796. package/dist/core/obligations/obligations.js.map +1 -0
  797. package/dist/core/openapi/baseline/gate.js +207 -0
  798. package/dist/core/openapi/baseline/gate.js.map +1 -0
  799. package/dist/core/openapi/baseline/plan.js +142 -0
  800. package/dist/core/openapi/baseline/plan.js.map +1 -0
  801. package/dist/core/openapi/baseline/record.js +174 -0
  802. package/dist/core/openapi/baseline/record.js.map +1 -0
  803. package/dist/core/openapi/contract-text.js +33 -0
  804. package/dist/core/openapi/contract-text.js.map +1 -0
  805. package/dist/core/openapi/contract-tree.js +301 -0
  806. package/dist/core/openapi/contract-tree.js.map +1 -0
  807. package/dist/core/openapi/depth.js +136 -0
  808. package/dist/core/openapi/depth.js.map +1 -0
  809. package/dist/core/openapi/digest.js +239 -0
  810. package/dist/core/openapi/digest.js.map +1 -0
  811. package/dist/core/{openapi.js → openapi/doc.js} +54 -108
  812. package/dist/core/openapi/doc.js.map +1 -0
  813. package/dist/core/openapi/merge/components.js +199 -0
  814. package/dist/core/openapi/merge/components.js.map +1 -0
  815. package/dist/core/openapi/merge/error.js +16 -0
  816. package/dist/core/openapi/merge/error.js.map +1 -0
  817. package/dist/core/openapi/merge/markers.js +204 -0
  818. package/dist/core/openapi/merge/markers.js.map +1 -0
  819. package/dist/core/openapi/merge/merge.js +232 -0
  820. package/dist/core/openapi/merge/merge.js.map +1 -0
  821. package/dist/core/openapi/merge/pin.js +110 -0
  822. package/dist/core/openapi/merge/pin.js.map +1 -0
  823. package/dist/core/openspec/decide/capabilities.js +244 -0
  824. package/dist/core/openspec/decide/capabilities.js.map +1 -0
  825. package/dist/core/openspec/decide/dispositions.js +63 -0
  826. package/dist/core/openspec/decide/dispositions.js.map +1 -0
  827. package/dist/core/openspec/decide/renames.js +179 -0
  828. package/dist/core/openspec/decide/renames.js.map +1 -0
  829. package/dist/core/openspec/decide/verdict.js +84 -0
  830. package/dist/core/openspec/decide/verdict.js.map +1 -0
  831. package/dist/core/openspec/inventory.js +220 -0
  832. package/dist/core/openspec/inventory.js.map +1 -0
  833. package/dist/core/openspec/model/mapping.js +78 -0
  834. package/dist/core/openspec/model/mapping.js.map +1 -0
  835. package/dist/core/openspec/model/model.js +70 -0
  836. package/dist/core/openspec/model/model.js.map +1 -0
  837. package/dist/core/openspec/scan/changes.js +241 -0
  838. package/dist/core/openspec/scan/changes.js.map +1 -0
  839. package/dist/core/openspec/scan/config.js +191 -0
  840. package/dist/core/openspec/scan/config.js.map +1 -0
  841. package/dist/core/openspec/scan/shape.js +304 -0
  842. package/dist/core/openspec/scan/shape.js.map +1 -0
  843. package/dist/core/openspec/scan/walk.js +116 -0
  844. package/dist/core/openspec/scan/walk.js.map +1 -0
  845. package/dist/core/openspec/scan/workspace.js +71 -0
  846. package/dist/core/openspec/scan/workspace.js.map +1 -0
  847. package/dist/core/owners/codeowners.js +141 -0
  848. package/dist/core/owners/codeowners.js.map +1 -0
  849. package/dist/core/pack/features.js +120 -0
  850. package/dist/core/pack/features.js.map +1 -0
  851. package/dist/core/pack/joins.js +112 -0
  852. package/dist/core/pack/joins.js.map +1 -0
  853. package/dist/core/pack/living.js +157 -0
  854. package/dist/core/pack/living.js.map +1 -0
  855. package/dist/core/pack/pack.js +120 -0
  856. package/dist/core/pack/pack.js.map +1 -0
  857. package/dist/core/permissions/permissions.js +87 -0
  858. package/dist/core/permissions/permissions.js.map +1 -0
  859. package/dist/core/projection/api.js +84 -0
  860. package/dist/core/projection/api.js.map +1 -0
  861. package/dist/core/projection/arch-slice.js +63 -0
  862. package/dist/core/projection/arch-slice.js.map +1 -0
  863. package/dist/core/projection/events.js +34 -0
  864. package/dist/core/projection/events.js.map +1 -0
  865. package/dist/core/projection/introduced.js +14 -0
  866. package/dist/core/projection/introduced.js.map +1 -0
  867. package/dist/core/provenance/findings.js +244 -0
  868. package/dist/core/provenance/findings.js.map +1 -0
  869. package/dist/core/provenance/git.js +201 -0
  870. package/dist/core/provenance/git.js.map +1 -0
  871. package/dist/core/provenance/gitq/moves.js +139 -0
  872. package/dist/core/provenance/gitq/moves.js.map +1 -0
  873. package/dist/core/provenance/gitq/vouched-ancestor.js +179 -0
  874. package/dist/core/provenance/gitq/vouched-ancestor.js.map +1 -0
  875. package/dist/core/provenance/sample/scope.js +238 -0
  876. package/dist/core/provenance/sample/scope.js.map +1 -0
  877. package/dist/core/provenance/sample/sections.js +61 -0
  878. package/dist/core/provenance/sample/sections.js.map +1 -0
  879. package/dist/core/provenance/sources.js +280 -0
  880. package/dist/core/provenance/sources.js.map +1 -0
  881. package/dist/core/provenance/stamp.js +220 -0
  882. package/dist/core/provenance/stamp.js.map +1 -0
  883. package/dist/core/provenance/walk.js +157 -0
  884. package/dist/core/provenance/walk.js.map +1 -0
  885. package/dist/core/repo/authored/paths.js +210 -0
  886. package/dist/core/repo/authored/paths.js.map +1 -0
  887. package/dist/core/repo/entries.js +126 -0
  888. package/dist/core/repo/entries.js.map +1 -0
  889. package/dist/core/repo/paths.js +322 -0
  890. package/dist/core/repo/paths.js.map +1 -0
  891. package/dist/core/repo/repo.js +308 -0
  892. package/dist/core/repo/repo.js.map +1 -0
  893. package/dist/core/repo/service-target.js +153 -0
  894. package/dist/core/repo/service-target.js.map +1 -0
  895. package/dist/core/repo/state.js +58 -0
  896. package/dist/core/repo/state.js.map +1 -0
  897. package/dist/core/repo/tree/find.js +61 -0
  898. package/dist/core/repo/tree/find.js.map +1 -0
  899. package/dist/core/repo/tree/fs.js +90 -0
  900. package/dist/core/repo/tree/fs.js.map +1 -0
  901. package/dist/core/repo/tree/marker.js +61 -0
  902. package/dist/core/repo/tree/marker.js.map +1 -0
  903. package/dist/core/repo/tree/render/body.js +258 -0
  904. package/dist/core/repo/tree/render/body.js.map +1 -0
  905. package/dist/core/repo/tree/render/projects.js +182 -0
  906. package/dist/core/repo/tree/render/projects.js.map +1 -0
  907. package/dist/core/repo/tree/render/service/header.js +125 -0
  908. package/dist/core/repo/tree/render/service/header.js.map +1 -0
  909. package/dist/core/repo/tree/render/service/peers.js +28 -0
  910. package/dist/core/repo/tree/render/service/peers.js.map +1 -0
  911. package/dist/core/repo/tree/render/service/view-id.js +67 -0
  912. package/dist/core/repo/tree/render/service/view-id.js.map +1 -0
  913. package/dist/core/repo/tree/render/service/views.js +78 -0
  914. package/dist/core/repo/tree/render/service/views.js.map +1 -0
  915. package/dist/core/repo/tree/render/stale.js +42 -0
  916. package/dist/core/repo/tree/render/stale.js.map +1 -0
  917. package/dist/core/repo/tree/render/text.js +84 -0
  918. package/dist/core/repo/tree/render/text.js.map +1 -0
  919. package/dist/core/repo/tree/render/views.js +293 -0
  920. package/dist/core/repo/tree/render/views.js.map +1 -0
  921. package/dist/core/repo/tree/walk.js +255 -0
  922. package/dist/core/repo/tree/walk.js.map +1 -0
  923. package/dist/core/results.js +146 -14
  924. package/dist/core/results.js.map +1 -1
  925. package/dist/core/scaffold/landscape.js +239 -0
  926. package/dist/core/scaffold/landscape.js.map +1 -0
  927. package/dist/core/scaffold/legacy.js +271 -0
  928. package/dist/core/scaffold/legacy.js.map +1 -0
  929. package/dist/core/scaffold/readme.js +84 -0
  930. package/dist/core/scaffold/readme.js.map +1 -0
  931. package/dist/core/staging/commit.js +252 -0
  932. package/dist/core/staging/commit.js.map +1 -0
  933. package/dist/core/staging/interrupted.js +96 -0
  934. package/dist/core/staging/interrupted.js.map +1 -0
  935. package/dist/core/staging/lock.js +268 -0
  936. package/dist/core/staging/lock.js.map +1 -0
  937. package/dist/core/staging/recovery/finding.js +35 -0
  938. package/dist/core/staging/recovery/finding.js.map +1 -0
  939. package/dist/core/staging/recovery/intent.js +95 -0
  940. package/dist/core/staging/recovery/intent.js.map +1 -0
  941. package/dist/core/staging/recovery/recover.js +204 -0
  942. package/dist/core/staging/recovery/recover.js.map +1 -0
  943. package/dist/core/staging/recovery/residue.js +62 -0
  944. package/dist/core/staging/recovery/residue.js.map +1 -0
  945. package/dist/core/staging/snapshot/manifest.js +188 -0
  946. package/dist/core/staging/snapshot/manifest.js.map +1 -0
  947. package/dist/core/staging/snapshot/snapshot.js +196 -0
  948. package/dist/core/staging/snapshot/snapshot.js.map +1 -0
  949. package/dist/core/staging/txn/forward.js +181 -0
  950. package/dist/core/staging/txn/forward.js.map +1 -0
  951. package/dist/core/staging/txn/journal.js +139 -0
  952. package/dist/core/staging/txn/journal.js.map +1 -0
  953. package/dist/core/staging/txn/transaction.js +75 -0
  954. package/dist/core/staging/txn/transaction.js.map +1 -0
  955. package/dist/core/staging/writes.js +113 -0
  956. package/dist/core/staging/writes.js.map +1 -0
  957. package/dist/core/status/actions/execution.js +60 -0
  958. package/dist/core/status/actions/execution.js.map +1 -0
  959. package/dist/core/status/contracts.js +126 -0
  960. package/dist/core/status/contracts.js.map +1 -0
  961. package/dist/core/status/feature/artifacts.js +196 -0
  962. package/dist/core/status/feature/artifacts.js.map +1 -0
  963. package/dist/core/status/feature/feature.js +214 -0
  964. package/dist/core/status/feature/feature.js.map +1 -0
  965. package/dist/core/status/feature/next.js +163 -0
  966. package/dist/core/status/feature/next.js.map +1 -0
  967. package/dist/core/status/feature/state.js +21 -0
  968. package/dist/core/status/feature/state.js.map +1 -0
  969. package/dist/core/status/feature/words.js +96 -0
  970. package/dist/core/status/feature/words.js.map +1 -0
  971. package/dist/core/status/fleet/fleet.js +216 -0
  972. package/dist/core/status/fleet/fleet.js.map +1 -0
  973. package/dist/core/status/fleet/next.js +302 -0
  974. package/dist/core/status/fleet/next.js.map +1 -0
  975. package/dist/core/status/interrupted.js +97 -0
  976. package/dist/core/status/interrupted.js.map +1 -0
  977. package/dist/core/status/report.js +31 -0
  978. package/dist/core/status/report.js.map +1 -0
  979. package/dist/core/status/scan.js +41 -0
  980. package/dist/core/status/scan.js.map +1 -0
  981. package/dist/core/status/verification.js +216 -0
  982. package/dist/core/status/verification.js.map +1 -0
  983. package/dist/core/tasks/packet.js +199 -0
  984. package/dist/core/tasks/packet.js.map +1 -0
  985. package/dist/core/tasks/record.js +43 -0
  986. package/dist/core/tasks/record.js.map +1 -0
  987. package/dist/core/tasks/sources.js +181 -0
  988. package/dist/core/tasks/sources.js.map +1 -0
  989. package/dist/core/tasks/stamps.js +76 -0
  990. package/dist/core/tasks/stamps.js.map +1 -0
  991. package/dist/core/tasks/unit.js +0 -0
  992. package/dist/core/tasks/unit.js.map +1 -0
  993. package/dist/core/usecases/capability.js +166 -0
  994. package/dist/core/usecases/capability.js.map +1 -0
  995. package/dist/core/usecases/delta/claims.js +140 -0
  996. package/dist/core/usecases/delta/claims.js.map +1 -0
  997. package/dist/core/usecases/delta/flows.js +101 -0
  998. package/dist/core/usecases/delta/flows.js.map +1 -0
  999. package/dist/core/usecases/delta/modified.js +315 -0
  1000. package/dist/core/usecases/delta/modified.js.map +1 -0
  1001. package/dist/core/usecases/delta/overlay.js +76 -0
  1002. package/dist/core/usecases/delta/overlay.js.map +1 -0
  1003. package/dist/core/usecases/fleet.js +296 -0
  1004. package/dist/core/usecases/fleet.js.map +1 -0
  1005. package/dist/core/usecases/grade/capability-tag.js +93 -0
  1006. package/dist/core/usecases/grade/capability-tag.js.map +1 -0
  1007. package/dist/core/usecases/grade/feature.js +88 -0
  1008. package/dist/core/usecases/grade/feature.js.map +1 -0
  1009. package/dist/core/usecases/grade/requirement-tag.js +94 -0
  1010. package/dist/core/usecases/grade/requirement-tag.js.map +1 -0
  1011. package/dist/core/usecases/grade/steps.js +266 -0
  1012. package/dist/core/usecases/grade/steps.js.map +1 -0
  1013. package/dist/core/usecases/grade/usecases.js +112 -0
  1014. package/dist/core/usecases/grade/usecases.js.map +1 -0
  1015. package/dist/core/usecases/operations.js +123 -0
  1016. package/dist/core/usecases/operations.js.map +1 -0
  1017. package/dist/core/usecases/place.js +44 -0
  1018. package/dist/core/usecases/place.js.map +1 -0
  1019. package/dist/core/usecases/service/exclude.js +119 -0
  1020. package/dist/core/usecases/service/exclude.js.map +1 -0
  1021. package/dist/core/usecases/service/flows.js +164 -0
  1022. package/dist/core/usecases/service/flows.js.map +1 -0
  1023. package/dist/core/usecases/suites/participants.js +83 -0
  1024. package/dist/core/usecases/suites/participants.js.map +1 -0
  1025. package/dist/core/usecases/suites/suites.js +45 -0
  1026. package/dist/core/usecases/suites/suites.js.map +1 -0
  1027. package/dist/core/usecases/touch.js +101 -0
  1028. package/dist/core/usecases/touch.js.map +1 -0
  1029. package/dist/core/verify/answers.js +180 -0
  1030. package/dist/core/verify/answers.js.map +1 -0
  1031. package/dist/core/verify/build.js +170 -0
  1032. package/dist/core/verify/build.js.map +1 -0
  1033. package/dist/core/verify/checklist.js +259 -0
  1034. package/dist/core/verify/checklist.js.map +1 -0
  1035. package/dist/core/verify/claims/identity.js +61 -0
  1036. package/dist/core/verify/claims/identity.js.map +1 -0
  1037. package/dist/core/verify/cross/diff.js +97 -0
  1038. package/dist/core/verify/cross/diff.js.map +1 -0
  1039. package/dist/core/verify/evidence/contract.js +169 -0
  1040. package/dist/core/verify/evidence/contract.js.map +1 -0
  1041. package/dist/core/verify/location.js +67 -0
  1042. package/dist/core/verify/location.js.map +1 -0
  1043. package/dist/core/verify/pins/lint.js +158 -0
  1044. package/dist/core/verify/pins/lint.js.map +1 -0
  1045. package/dist/core/verify/pins/pin.js +95 -0
  1046. package/dist/core/verify/pins/pin.js.map +1 -0
  1047. package/dist/core/verify/read/file.js +224 -0
  1048. package/dist/core/verify/read/file.js.map +1 -0
  1049. package/dist/core/verify/read/shape.js +169 -0
  1050. package/dist/core/verify/read/shape.js.map +1 -0
  1051. package/dist/core/verify/read/union.js +105 -0
  1052. package/dist/core/verify/read/union.js.map +1 -0
  1053. package/dist/core/verify/record.js +165 -0
  1054. package/dist/core/verify/record.js.map +1 -0
  1055. package/dist/core/verify/store/commit.js +99 -0
  1056. package/dist/core/verify/store/commit.js.map +1 -0
  1057. package/dist/core/verify/store/render.js +61 -0
  1058. package/dist/core/verify/store/render.js.map +1 -0
  1059. package/dist/core/vocabulary/health.js +91 -0
  1060. package/dist/core/vocabulary/health.js.map +1 -0
  1061. package/dist/core/vocabulary/issue.js +59 -0
  1062. package/dist/core/vocabulary/issue.js.map +1 -0
  1063. package/dist/core/vocabulary/maturity.js +216 -0
  1064. package/dist/core/vocabulary/maturity.js.map +1 -0
  1065. package/dist/core/vocabulary/report.js +90 -0
  1066. package/dist/core/vocabulary/report.js.map +1 -0
  1067. package/dist/core/vocabulary/steps.js +266 -0
  1068. package/dist/core/vocabulary/steps.js.map +1 -0
  1069. package/dist/core/workspace/discover.js +239 -0
  1070. package/dist/core/workspace/discover.js.map +1 -0
  1071. package/dist/core/workspace/render.js +52 -0
  1072. package/dist/core/workspace/render.js.map +1 -0
  1073. package/examples/README.md +232 -0
  1074. package/examples/docs/architecture/adrs/0001-transactional-outbox.md +33 -0
  1075. package/examples/docs/architecture/capabilities.yaml +31 -0
  1076. package/examples/docs/architecture/landscape.likec4 +336 -0
  1077. package/examples/docs/architecture/obligations.yaml +23 -0
  1078. package/examples/docs/architecture/permissions.yaml +50 -0
  1079. package/examples/docs/architecture/services.likec4 +70 -0
  1080. package/examples/docs/architecture/subsystems.likec4 +18 -0
  1081. package/examples/docs/architecture/usecases/order-notification.likec4 +74 -0
  1082. package/examples/docs/capabilities/checkout/spec.md +55 -0
  1083. package/examples/docs/capabilities/identity/tokens/spec.md +42 -0
  1084. package/examples/docs/capabilities/order-notifications/spec.md +43 -0
  1085. package/examples/docs/features/FEAT-101-payment-splitting/adrs/0001-dedicated-split-service.md +18 -0
  1086. package/examples/docs/features/FEAT-101-payment-splitting/delta.likec4 +94 -0
  1087. package/examples/docs/features/FEAT-101-payment-splitting/intent.md +44 -0
  1088. package/examples/docs/features/FEAT-101-payment-splitting/specs/checkout-web/spec.md +21 -0
  1089. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-service/asyncapi.yaml +132 -0
  1090. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-service/spec.md +36 -0
  1091. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/arch.spec.md +40 -0
  1092. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/openapi.yaml +116 -0
  1093. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/spec.md +55 -0
  1094. package/examples/docs/features/FEAT-112-retire-order-v1/intent.md +35 -0
  1095. package/examples/docs/features/FEAT-112-retire-order-v1/specs/order-service/openapi.yaml +31 -0
  1096. package/examples/docs/features/FEAT-112-retire-order-v1/specs/order-service/spec.md +17 -0
  1097. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/architecture/landscape.likec4 +253 -0
  1098. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/services/order-service/spec.md +121 -0
  1099. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/services/payment-service/openapi.yaml +111 -0
  1100. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/services/payment-service/spec.md +58 -0
  1101. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/manifest.json +32 -0
  1102. package/examples/docs/features/archive/FEAT-088-refunds/adrs/0001-refunds-stay-in-payment-service.md +26 -0
  1103. package/examples/docs/features/archive/FEAT-088-refunds/delta.likec4 +28 -0
  1104. package/examples/docs/features/archive/FEAT-088-refunds/intent.md +26 -0
  1105. package/examples/docs/features/archive/FEAT-088-refunds/specs/order-service/spec.md +37 -0
  1106. package/examples/docs/features/archive/FEAT-088-refunds/specs/payment-service/openapi.yaml +73 -0
  1107. package/examples/docs/features/archive/FEAT-088-refunds/specs/payment-service/spec.md +23 -0
  1108. package/examples/docs/features/archive/FEAT-088-refunds/verification.yaml +76 -0
  1109. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/architecture/landscape.likec4 +275 -0
  1110. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/payment-service/asyncapi.yaml +96 -0
  1111. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/payment-service/spec.md +82 -0
  1112. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/platform/notification-service/asyncapi.yaml +164 -0
  1113. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/platform/notification-service/spec.md +91 -0
  1114. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/manifest.json +46 -0
  1115. package/examples/docs/features/archive/FEAT-120-refund-notification/delta.likec4 +36 -0
  1116. package/examples/docs/features/archive/FEAT-120-refund-notification/intent.md +22 -0
  1117. package/examples/docs/features/archive/FEAT-120-refund-notification/scenario-report.json +10 -0
  1118. package/examples/docs/features/archive/FEAT-120-refund-notification/specs/notification-service/asyncapi.yaml +208 -0
  1119. package/examples/docs/features/archive/FEAT-120-refund-notification/specs/notification-service/spec.md +24 -0
  1120. package/examples/docs/features/archive/FEAT-120-refund-notification/specs/payment-service/asyncapi.yaml +137 -0
  1121. package/examples/docs/features/archive/FEAT-120-refund-notification/specs/payment-service/spec.md +31 -0
  1122. package/examples/docs/features/archive/FEAT-120-refund-notification/verification.yaml +84 -0
  1123. package/examples/docs/glossary/order.md +15 -0
  1124. package/examples/docs/glossary/payments/authorization.md +14 -0
  1125. package/examples/docs/likec4.config.json +8 -0
  1126. package/examples/docs/loam.json +3 -0
  1127. package/examples/docs/services/checkout-web/model.likec4 +92 -0
  1128. package/examples/docs/services/checkout-web/spec.md +91 -0
  1129. package/examples/docs/services/checkout-web/ui/pages/checkout.page.yaml +40 -0
  1130. package/examples/docs/services/checkout-web/ui/pages/order-status.page.yaml +24 -0
  1131. package/examples/docs/services/checkout-web/ui/pages/split-payment.page.yaml +26 -0
  1132. package/examples/docs/services/order-service/adrs/0001-orchestrated-order-lifecycle.md +52 -0
  1133. package/examples/docs/services/order-service/arch.spec.md +134 -0
  1134. package/examples/docs/services/order-service/asyncapi.yaml +109 -0
  1135. package/examples/docs/services/order-service/health.yaml +57 -0
  1136. package/examples/docs/services/order-service/model.likec4 +126 -0
  1137. package/examples/docs/services/order-service/openapi.yaml +257 -0
  1138. package/examples/docs/services/order-service/runbook.md +62 -0
  1139. package/examples/docs/services/order-service/spec.md +134 -0
  1140. package/examples/docs/services/payment-service/adrs/0001-payments-outbox.md +18 -0
  1141. package/examples/docs/services/payment-service/adrs/0002-idempotency-keys-on-authorization.md +27 -0
  1142. package/examples/docs/services/payment-service/arch.spec.md +76 -0
  1143. package/examples/docs/services/payment-service/asyncapi.yaml +130 -0
  1144. package/examples/docs/services/payment-service/health.yaml +39 -0
  1145. package/examples/docs/services/payment-service/model.likec4 +68 -0
  1146. package/examples/docs/services/payment-service/openapi.yaml +151 -0
  1147. package/examples/docs/services/payment-service/runbook.md +37 -0
  1148. package/examples/docs/services/payment-service/spec.md +88 -0
  1149. package/examples/docs/services/platform/identity-service/adrs/0001-token-introspection-over-local-validation.md +60 -0
  1150. package/examples/docs/services/platform/identity-service/arch.spec.md +120 -0
  1151. package/examples/docs/services/platform/identity-service/health.yaml +70 -0
  1152. package/examples/docs/services/platform/identity-service/model.likec4 +81 -0
  1153. package/examples/docs/services/platform/identity-service/openapi.yaml +197 -0
  1154. package/examples/docs/services/platform/identity-service/runbook.md +95 -0
  1155. package/examples/docs/services/platform/identity-service/spec.md +119 -0
  1156. package/examples/docs/services/platform/notification-service/asyncapi.yaml +200 -0
  1157. package/examples/docs/services/platform/notification-service/health.yaml +40 -0
  1158. package/examples/docs/services/platform/notification-service/model.likec4 +97 -0
  1159. package/examples/docs/services/platform/notification-service/runbook.md +48 -0
  1160. package/examples/docs/services/platform/notification-service/spec.md +112 -0
  1161. package/examples/docs/services/platform/subsystem.yaml +2 -0
  1162. package/examples/fleet.yaml +57 -0
  1163. package/package.json +19 -6
  1164. package/dist/commands/adopt.js +0 -240
  1165. package/dist/commands/adopt.js.map +0 -1
  1166. package/dist/commands/archive.js +0 -1313
  1167. package/dist/commands/archive.js.map +0 -1
  1168. package/dist/commands/delta.js +0 -388
  1169. package/dist/commands/delta.js.map +0 -1
  1170. package/dist/commands/docs-repo-gate.js.map +0 -1
  1171. package/dist/commands/format.js +0 -17
  1172. package/dist/commands/format.js.map +0 -1
  1173. package/dist/commands/gherkin.js +0 -309
  1174. package/dist/commands/gherkin.js.map +0 -1
  1175. package/dist/commands/init.js.map +0 -1
  1176. package/dist/commands/list.js +0 -295
  1177. package/dist/commands/list.js.map +0 -1
  1178. package/dist/commands/migrate-openspec.js +0 -950
  1179. package/dist/commands/migrate-openspec.js.map +0 -1
  1180. package/dist/commands/new.js +0 -413
  1181. package/dist/commands/new.js.map +0 -1
  1182. package/dist/commands/rebase.js +0 -356
  1183. package/dist/commands/rebase.js.map +0 -1
  1184. package/dist/commands/show.js +0 -320
  1185. package/dist/commands/show.js.map +0 -1
  1186. package/dist/commands/status.js +0 -262
  1187. package/dist/commands/status.js.map +0 -1
  1188. package/dist/commands/unarchive.js +0 -317
  1189. package/dist/commands/unarchive.js.map +0 -1
  1190. package/dist/commands/validate.js +0 -1773
  1191. package/dist/commands/validate.js.map +0 -1
  1192. package/dist/commands/verify.js +0 -775
  1193. package/dist/commands/verify.js.map +0 -1
  1194. package/dist/commands/vouch.js +0 -421
  1195. package/dist/commands/vouch.js.map +0 -1
  1196. package/dist/core/agent.js +0 -2173
  1197. package/dist/core/agent.js.map +0 -1
  1198. package/dist/core/agents-stamp.js.map +0 -1
  1199. package/dist/core/arch.js +0 -130
  1200. package/dist/core/arch.js.map +0 -1
  1201. package/dist/core/asyncapi.js +0 -253
  1202. package/dist/core/asyncapi.js.map +0 -1
  1203. package/dist/core/brief.js +0 -755
  1204. package/dist/core/brief.js.map +0 -1
  1205. package/dist/core/coherence.js +0 -577
  1206. package/dist/core/coherence.js.map +0 -1
  1207. package/dist/core/concurrency.js.map +0 -1
  1208. package/dist/core/config.js.map +0 -1
  1209. package/dist/core/delta.js +0 -476
  1210. package/dist/core/delta.js.map +0 -1
  1211. package/dist/core/dependencies.js +0 -356
  1212. package/dist/core/dependencies.js.map +0 -1
  1213. package/dist/core/doctor.js +0 -596
  1214. package/dist/core/doctor.js.map +0 -1
  1215. package/dist/core/document-bytes.js.map +0 -1
  1216. package/dist/core/explore.js +0 -225
  1217. package/dist/core/explore.js.map +0 -1
  1218. package/dist/core/frontmatter.js.map +0 -1
  1219. package/dist/core/gherkin.js +0 -463
  1220. package/dist/core/gherkin.js.map +0 -1
  1221. package/dist/core/health.js +0 -67
  1222. package/dist/core/health.js.map +0 -1
  1223. package/dist/core/ids.js +0 -122
  1224. package/dist/core/ids.js.map +0 -1
  1225. package/dist/core/issue.js +0 -9
  1226. package/dist/core/issue.js.map +0 -1
  1227. package/dist/core/json.js +0 -74
  1228. package/dist/core/json.js.map +0 -1
  1229. package/dist/core/likec4.js +0 -489
  1230. package/dist/core/likec4.js.map +0 -1
  1231. package/dist/core/maturity.js +0 -66
  1232. package/dist/core/maturity.js.map +0 -1
  1233. package/dist/core/openapi-merge.js +0 -552
  1234. package/dist/core/openapi-merge.js.map +0 -1
  1235. package/dist/core/openapi.js.map +0 -1
  1236. package/dist/core/openspec-inventory.js +0 -1440
  1237. package/dist/core/openspec-inventory.js.map +0 -1
  1238. package/dist/core/path-safety.js.map +0 -1
  1239. package/dist/core/provenance.js +0 -787
  1240. package/dist/core/provenance.js.map +0 -1
  1241. package/dist/core/records.js.map +0 -1
  1242. package/dist/core/repo.js +0 -438
  1243. package/dist/core/repo.js.map +0 -1
  1244. package/dist/core/report.js +0 -47
  1245. package/dist/core/report.js.map +0 -1
  1246. package/dist/core/spec.js +0 -505
  1247. package/dist/core/spec.js.map +0 -1
  1248. package/dist/core/staging.js +0 -890
  1249. package/dist/core/staging.js.map +0 -1
  1250. package/dist/core/status.js +0 -1132
  1251. package/dist/core/status.js.map +0 -1
  1252. package/dist/core/steps.js +0 -72
  1253. package/dist/core/steps.js.map +0 -1
  1254. package/dist/core/verify.js +0 -807
  1255. package/dist/core/verify.js.map +0 -1
  1256. package/dist/core/version.js.map +0 -1
@@ -0,0 +1,302 @@
1
+ import { serviceTreePath } from "../../kernel/ids/dirs.js";
2
+ import { compareIds } from "../../repo/entries.js";
3
+ import { recoverStep } from "../interrupted.js";
4
+ import { featureLabel, fleetStageWords } from "../feature/words.js";
5
+ import { undocumented, vouched, } from "../report.js";
6
+ /** How urgent a stage is at fleet level. See {@link fleetNext}. */
7
+ const STAGE_RANK = {
8
+ done: 0,
9
+ ready: 1,
10
+ draft: 2,
11
+ missing: 3,
12
+ blocked: 4,
13
+ };
14
+ /**
15
+ * How many per-service and per-feature steps the fleet form will print before
16
+ * it stops and says how many it left out. A fleet mid-adoption produced 135
17
+ * entries under the heading "the next thing to do" — a list nobody reads is a
18
+ * list that is not navigation, and the first ten are the ten that matter
19
+ * because the ordering below is already most-unblocking-first.
20
+ *
21
+ * Exported so the test asserts the cap through the constant: a literal 10 in a
22
+ * fixture is a second declaration of the limit, free to disagree the day this
23
+ * one moves.
24
+ */
25
+ export const FLEET_NEXT_LIMIT = 10;
26
+ export function fleetNext(fleet, binding) {
27
+ const { services, features, graph, interrupted, teaching } = fleet;
28
+ const steps = [];
29
+ // The two arms of the binding, each named for the question it answers. The
30
+ // first reproduces the old parameter exactly, so everything reading it below
31
+ // is unchanged; the second is the fact that used to be thrown away.
32
+ const unadoptedBinding = binding !== null && !binding.adopted ? binding.id : null;
33
+ const adoptedBinding = binding !== null && binding.adopted ? binding.id : null;
34
+ // The features that bring the bound service into being, when any in flight
35
+ // do. Their steps lead and the feature loop below skips them, so a feature
36
+ // this repository exists for is named once, first — EVERY one of them, since
37
+ // whichever archives first is the one that makes the service living.
38
+ const introducing = unadoptedBinding === null ? [] : features.filter((f) => binding.introducedBy.includes(f.id));
39
+ // The repository this command is standing in names a service the fleet has no
40
+ // directory for. First, ahead of every other service's partial adoption,
41
+ // because it is the only step that is about HERE.
42
+ //
43
+ // This form used to count the fleet and ignore the binding entirely, so in a
44
+ // service repo bound to an unadopted service — a freshly wired one, the most
45
+ // common repo there is — an empty fleet made "every service is written down"
46
+ // vacuously true and `next.fleet-clean` came out top. `loam doctor` had the
47
+ // right answer (`doctor.service-unknown`) at the same moment, and the
48
+ // documented agent loop reads `status`: an agent following it was sent to
49
+ // start a feature instead of adopting the service under its feet.
50
+ //
51
+ // Unless a feature in flight INTRODUCES the service. Then there is no code
52
+ // yet for `loam adopt` to read — the feature's own specs/ ARE its documents
53
+ // until it archives — and telling its first developer to adopt it sent them
54
+ // to describe an empty repository. The step is the feature's, under the code
55
+ // the feature loop already emits, so nothing new needs branching on.
56
+ for (const f of introducing) {
57
+ const others = introducing.filter((o) => o !== f).map((o) => o.id);
58
+ steps.push({
59
+ code: "next.feature",
60
+ statement: `This repository's loam.json says it is '${unadoptedBinding}', which ${f.id} introduces` +
61
+ (others.length > 0 ? ` (so does ${others.join(", ")})` : "") +
62
+ ` — it is not in the living docs until ${others.length > 0 ? "one of them" : f.id} archives, so there is ` +
63
+ `nothing to adopt; ${f.id}'s own status says what this repository owes it.`,
64
+ command: `loam status ${f.id} --json`,
65
+ });
66
+ }
67
+ if (unadoptedBinding !== null && introducing.length === 0) {
68
+ steps.push({
69
+ code: "next.adopt-bound",
70
+ statement: `This repository's loam.json says it is '${unadoptedBinding}', and the fleet has no ` +
71
+ `services/${unadoptedBinding}/ — nothing about the service you are standing in is written down yet.`,
72
+ command: `loam adopt --service ${unadoptedBinding} --json`,
73
+ service: unadoptedBinding,
74
+ });
75
+ }
76
+ // The first hour of a docs repo, in order. Zero services and zero features
77
+ // used to fall through every loop below into `next.fleet-clean` — the header
78
+ // says why that answer was vacuous — so the emptiest repository loam serves
79
+ // got the least from the command whose whole purpose is "what do I do next".
80
+ // These are ordinary steps on purpose: the gate entry still closes the list,
81
+ // and the tail ternary is untouched. The bind/adopt rungs are suppressed when
82
+ // `next.adopt-bound` above already names the exact adopt to run, and the
83
+ // whole ladder is withheld on narrowed runs (`teaching === null`).
84
+ if (teaching !== null && services.length === 0 && features.length === 0) {
85
+ if (teaching.landscape !== "authored") {
86
+ steps.push({
87
+ code: "next.author-landscape",
88
+ statement: teaching.landscape === "missing"
89
+ ? "architecture/landscape.likec4 does not exist — the fleet map is the one artifact every " +
90
+ "cross-service check reads. Run `loam init --create` to scaffold it, then draw the first service."
91
+ : "architecture/landscape.likec4 is still the scaffold's untouched map — no service is drawn. " +
92
+ "State the facts in a fleet.yaml (service ids, `a -> b` calls) and run " +
93
+ "`loam seed --from fleet.yaml` to template the map mechanically — or open the file " +
94
+ "and follow its own comments. Either way loam never guesses who calls whom.",
95
+ // The command each arm's own prose already names, and for a while it
96
+ // was neither: both arms carried the gate. WORKFLOW.md documents the
97
+ // agent loop as "read next[0], run the command it names, repeat" and
98
+ // every generated skill says to branch on the code rather than the
99
+ // prose — so an agent on the first rung of the first hour ran
100
+ // `validate --all` against a repository with no services in it, which
101
+ // answers ok:true with `landscape.matched` and changes nothing, and
102
+ // came back to the identical next[0] forever. A livelock on day zero,
103
+ // on the one command built to answer "what now". The gate is still
104
+ // named: `next.fleet-gate` closes this same list.
105
+ command: teaching.landscape === "missing" ? "loam init --create" : "loam seed --from fleet.yaml",
106
+ path: "architecture/landscape.likec4",
107
+ });
108
+ }
109
+ if (unadoptedBinding === null) {
110
+ steps.push({
111
+ code: "next.bind-service",
112
+ statement: "No service repository is bound to this fleet yet. From a service's own repo, point --docs " +
113
+ "here and --service at its canonical id with the service agent profile, then commit the " +
114
+ "loam.json it writes.",
115
+ // `--agent-profile service`, because the default is `full`, and `full`
116
+ // writes loam-feature and loam-ship into the service checkout — the two
117
+ // workflows this docs repo keeps, which README tells every service
118
+ // repo to leave out. An agent runs this literal, not the README.
119
+ command: "loam init --docs <path-to-this-docs-repo> --service <service-id> --agent-profile service",
120
+ });
121
+ steps.push({
122
+ code: "next.adopt-first",
123
+ statement: "services/ is empty — nothing about any service is written down yet. Adopt the first one: " +
124
+ "the brief walks an agent through writing its baseline docs as draft.",
125
+ command: "loam adopt --service <service-id> --json",
126
+ });
127
+ }
128
+ }
129
+ // Features BEFORE the per-service rungs. The rungs used to lead, on the
130
+ // reading that an adoption gap blocks grading — and on a fleet mid-adoption
131
+ // that put a page of `next.adopt` lines ahead of the one feature anybody was
132
+ // working on, and the cap below elided that feature as "more step(s) of the
133
+ // same kinds": the only change in flight, invisible under the heading
134
+ // "next". A feature is work somebody started; an undocumented service is
135
+ // backlog. The rungs still follow, and still in full where it matters —
136
+ // `serviceSteps` beside this list carries every one of them uncapped.
137
+ const ordered = [...features].sort((a, b) => STAGE_RANK[a.stage] - STAGE_RANK[b.stage] ||
138
+ graph.order.indexOf(a.id) - graph.order.indexOf(b.id) ||
139
+ compareIds(a.id, b.id));
140
+ for (const f of ordered) {
141
+ if (introducing.includes(f))
142
+ continue;
143
+ const label = featureLabel(f);
144
+ if (f.stage === "done") {
145
+ steps.push({
146
+ code: "next.archive",
147
+ statement: `${label} is authored and verified — archive it to fold its deltas into the living docs, and everything waiting on it is released.`,
148
+ command: `loam archive ${f.id} --dry-run --json`,
149
+ });
150
+ continue;
151
+ }
152
+ steps.push({
153
+ code: "next.feature",
154
+ statement:
155
+ // The list, not the stage, is what this sentence names. `blocked` has
156
+ // two causes now — another feature in flight, and an interrupted commit
157
+ // that stalls the whole repository — and the second one names no
158
+ // feature, so keying off the stage alone printed "FEAT-1 is waiting
159
+ // on ." The recover step above already says what the repository is
160
+ // waiting on.
161
+ //
162
+ // And never the bare stage word: "FEAT-1 is at 'ready'" over a feature
163
+ // with nothing built read as ready to ship. `stageWords` is the one
164
+ // place the human sentence for a stage lives (../feature/words.ts).
165
+ f.stage === "blocked" && interrupted === null && f.blockedBy.length > 0
166
+ ? `${label} is waiting on ${f.blockedBy.join(", ")}.`
167
+ : `${label}: ${fleetStageWords(f, interrupted !== null)}.`,
168
+ command: `loam status ${f.id} --json`,
169
+ });
170
+ }
171
+ steps.push(...perServiceSteps(services, adoptedBinding));
172
+ const left = steps.slice(FLEET_NEXT_LIMIT);
173
+ // Outside the cap, not merely first inside it: the one step that must never
174
+ // be the one this list left out.
175
+ const out = [...(interrupted === null ? [] : [recoverStep(interrupted)]), ...steps.slice(0, FLEET_NEXT_LIMIT)];
176
+ if (left.length > 0) {
177
+ // Which kinds, counted: "of the same kinds" told a reader nothing about
178
+ // whether the feature they came for was among the missing.
179
+ const kinds = [...new Set(left.map((s) => s.code))].map((code) => `${left.filter((s) => s.code === code).length} ${code}`);
180
+ out.push({
181
+ code: "next.elided",
182
+ statement: `${left.length} more step(s) were left out (${kinds.join(", ")}) — this list is ordered most-unblocking first, so work down it and run status again.`,
183
+ command: "loam list --json",
184
+ });
185
+ }
186
+ out.push(steps.length === 0
187
+ ? {
188
+ code: "next.fleet-clean",
189
+ statement: "Nothing is in flight and every service is written down — keep the fleet green, then start the next feature.",
190
+ command: "loam validate --all --json",
191
+ }
192
+ : {
193
+ code: "next.fleet-gate",
194
+ // `loam validate --all` inside the backticks, not the bare
195
+ // `validate --all` this sentence carried for a year: a span without
196
+ // the binary name is invisible to every check that reads a
197
+ // backticked `loam <verb>` as an instruction — the parse check in
198
+ // test/agent-commands-runnable.test.ts, and the statement/command
199
+ // invariant in test/status.test.ts. A prefix is cheaper than an
200
+ // exemption, and the exemption is what lets a wrong command through.
201
+ statement: `${features.length} feature(s) in flight over ${services.length} service(s) — ` +
202
+ "status grades none of them; `loam validate --all` is the gate this repository has to pass, and it is what CI runs.",
203
+ command: "loam validate --all --json",
204
+ });
205
+ return out;
206
+ }
207
+ /**
208
+ * Every per-service rung, in the order the list prints them: the bound
209
+ * service's own first, then the rest alphabetically. Exported because the
210
+ * same list, uncapped and grouped (`groupServiceSteps`), rides beside `next[]`
211
+ * as `serviceSteps` — one derivation, so the two can never disagree about
212
+ * what a service owes.
213
+ */
214
+ export function perServiceSteps(services, adoptedBinding) {
215
+ // The per-service rungs are collected as one list because the partition
216
+ // below acts on them as a group — and only on them. Where the list goes is
217
+ // the caller's: `fleetNext` puts it after every feature, and nothing here may
218
+ // float above `next.adopt-bound` or the first-hour ladder, both of which are
219
+ // about the repository rather than about any one service in the fleet.
220
+ const perService = [];
221
+ // `adoption: partial` is one feature's slice archived into a service never
222
+ // adopted (SCHEMA.md); the file's presence used to discharge this rung.
223
+ for (const s of services.filter((x) => undocumented(x) || x.adoption !== null)) {
224
+ perService.push({
225
+ code: "next.adopt",
226
+ statement: undocumented(s)
227
+ ? `${serviceTreePath(s)}/ has no spec.md — nothing about ${s.id} is written down, so no feature can be graded against it.`
228
+ : `${serviceTreePath(s)}/spec.md is adoption: partial — it holds what an archived feature added, nothing of what ${s.id} already did.`,
229
+ command: `loam adopt --service ${s.id} --json`,
230
+ service: s.id,
231
+ });
232
+ }
233
+ // Adoption does not end at spec.md. A service with a living spec and no
234
+ // model.likec4 is the state archive itself warns about (`service.no-model`)
235
+ // and the fleet gate reports — invisible here until now, because this form
236
+ // looked at exactly one bit of each service's artifact set.
237
+ for (const s of services.filter((x) => !undocumented(x) && x.adoption === null && !x.has.model)) {
238
+ perService.push({
239
+ code: "next.complete-service",
240
+ statement: `${serviceTreePath(s)}/ has a spec.md but no model.likec4 — the fleet gate reports the service incomplete until something models it.`,
241
+ command: `loam validate --service ${s.id} --json`,
242
+ service: s.id,
243
+ });
244
+ }
245
+ // A vouch the document has moved out from under. `content.stale` needs
246
+ // nothing but the document, so unlike `sources.stale` this form CAN see it —
247
+ // and before it looked, a fleet whose specs were edited after the person read
248
+ // them got `next.fleet-clean`: "nothing is owed" over words nobody had
249
+ // re-read, while `loam validate` warned about each one. The re-vouch is a
250
+ // person's act from that service's own repository (`loam vouch` restamps the
251
+ // code side too), so the step names the documents and that repository, and
252
+ // its execution contract is a human review rather than a command to run.
253
+ for (const s of services.filter((x) => vouched(x) && x.contentStale.length > 0)) {
254
+ const files = s.contentStale.map((file) => `${serviceTreePath(s)}/${file}`);
255
+ perService.push({
256
+ code: "next.revouch",
257
+ statement: `${files.join(" and ")} changed since ${s.id} was vouched — \`status: verified\` stands over words nobody has re-read (content.stale). ` +
258
+ `A person re-reads what moved (\`loam vouch --pack --service ${s.id}\` lists it) and re-vouches from ${s.id}'s own repository.`,
259
+ command: `loam vouch --service ${s.id}`,
260
+ service: s.id,
261
+ });
262
+ }
263
+ // The boundary this repository IS comes first among the boundaries it merely
264
+ // shares a fleet with. A stable PARTITION and deliberately not a sort: the
265
+ // bound service's rungs move to the front and every other service keeps the
266
+ // alphabetical order it already had, so the list an unbound reader sees — a
267
+ // docs repo, CI, `loam validate --all`'s scorecard — is byte-for-byte the one
268
+ // it saw before.
269
+ //
270
+ // The cap is why this is ordering and not cosmetics. Ten steps print, and in
271
+ // the ten-repo case WORKFLOW.md describes every developer's `loam status`
272
+ // listed nine other services' adoption work ahead of their own; past ten
273
+ // services the one rung this developer can actually act on was elided
274
+ // entirely, leaving a list of nothing but other people's boundaries under
275
+ // the heading "next". No new code is emitted for any of this — `next[]` has
276
+ // always been documented as most-unblocking first, and this is the line that
277
+ // makes the claim true from where the reader is standing.
278
+ return adoptedBinding === null
279
+ ? perService
280
+ : [
281
+ ...perService.filter((s) => s.service === adoptedBinding),
282
+ ...perService.filter((s) => s.service !== adoptedBinding),
283
+ ];
284
+ }
285
+ /**
286
+ * `perServiceSteps` grouped by code, in first-appearance order — the
287
+ * `serviceSteps` payload. `command` is the FIRST service's step command, so a
288
+ * reader folding forty rungs into one line still gets a literal to run rather
289
+ * than a second spelling of it.
290
+ */
291
+ export function groupServiceSteps(steps) {
292
+ const groups = new Map();
293
+ for (const step of steps) {
294
+ if (step.service === undefined)
295
+ continue;
296
+ const group = groups.get(step.code) ?? { code: step.code, services: [], command: step.command };
297
+ group.services.push(step.service);
298
+ groups.set(step.code, group);
299
+ }
300
+ return [...groups.values()];
301
+ }
302
+ //# sourceMappingURL=next.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"next.js","sourceRoot":"","sources":["../../../../src/core/status/fleet/next.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `next[]` — the whole repository: the steps about the repository itself\n * first, then every feature in flight, then each service's adoption gaps,\n * most-unblocking first, capped so the list stays navigation rather than\n * inventory.\n */\nimport type { DependencyGraph } from \"../../dependencies/facts.js\";\nimport { serviceTreePath } from \"../../kernel/ids/dirs.js\";\nimport { compareIds, type ServiceEntry } from \"../../repo/entries.js\";\nimport { recoverStep } from \"../interrupted.js\";\nimport { featureLabel, fleetStageWords } from \"../feature/words.js\";\nimport {\n undocumented,\n vouched,\n type ArtifactStatus,\n type FleetFeatureState,\n type InterruptedCommit,\n type NextStep,\n} from \"../report.js\";\n\n/** How urgent a stage is at fleet level. See {@link fleetNext}. */\nconst STAGE_RANK: Record<ArtifactStatus, number> = {\n done: 0,\n ready: 1,\n draft: 2,\n missing: 3,\n blocked: 4,\n};\n\n/**\n * How many per-service and per-feature steps the fleet form will print before\n * it stops and says how many it left out. A fleet mid-adoption produced 135\n * entries under the heading \"the next thing to do\" — a list nobody reads is a\n * list that is not navigation, and the first ten are the ten that matter\n * because the ordering below is already most-unblocking-first.\n *\n * Exported so the test asserts the cap through the constant: a literal 10 in a\n * fixture is a second declaration of the limit, free to disagree the day this\n * one moves.\n */\nexport const FLEET_NEXT_LIMIT = 10;\n\n/**\n * Fleet-level steps, most-unblocking first. A verified feature, ready to\n * archive, comes before one that still needs authoring, because archiving it\n * is what releases\n * everything queued behind it; a blocked feature comes last, because there is\n * nothing to do about it from here — its prerequisite is already higher up the\n * list under its own entry.\n *\n * The gate is the LAST entry and it is always there. `next.fleet-clean` used to\n * be the only route to `loam validate --all`, and it was emitted only when\n * nothing was in flight — so a repository that FAILS the fleet gate, which is\n * every repository with work in it, was handed a green-looking list that never\n * once named the command CI runs. This form grades nothing; the least it can do\n * is say where grading happens. `next.fleet-clean` is also no longer the\n * empty-repo answer: over zero services, \"every service is written down\" is\n * vacuously true, and the first hour of a docs repo used to get that green\n * sentence instead of its first three steps. The teaching ladder below owns\n * that case now, and the clean entry survives only for its truthful one —\n * services exist, and nothing is owed.\n */\n/** The whole fleet as the next-step walk reads it. */\nexport interface Fleet {\n services: ServiceEntry[];\n features: FleetFeatureState[];\n graph: DependencyGraph;\n interrupted: InterruptedCommit | null;\n /**\n * The ladder's fact, present exactly when the ladder can apply — an\n * unnarrowed run over an empty fleet. `null` otherwise: on a narrowed run\n * (withheld for the reason fleet.ts records beside the binding) and on any\n * fleet with services or features, where fleet.ts skips the read entirely.\n */\n teaching: { landscape: \"missing\" | \"stub\" | \"authored\" } | null;\n}\n\n/**\n * What this repository says it IS, as the walk needs it — and it needs BOTH\n * facts, which is why this is a record and not the bare id it used to be.\n *\n * `adopted: false` is the case the walk always handled: the fleet has no\n * `services/<id>/`, and `next.adopt-bound` leads. `adopted: true` was invisible\n * — the parameter was `string | null` and went null exactly when the directory\n * existed — so a repository bound to a service the fleet DOES know got the\n * whole system's worklist in alphabetical order, with its own boundary\n * somewhere in the middle of it or, past ten services, not on the list at all.\n */\nexport interface Binding {\n id: string;\n /** Whether the fleet has a `services/<id>/` for it. */\n adopted: boolean;\n /**\n * The active features whose `specs/` introduce it (`introducingFeatures`) —\n * empty unless `adopted` is false. A service a feature in flight introduces\n * has no code to adopt yet: the work in its repository IS that feature.\n */\n introducedBy: string[];\n}\n\nexport function fleetNext(fleet: Fleet, binding: Binding | null): NextStep[] {\n const { services, features, graph, interrupted, teaching } = fleet;\n const steps: NextStep[] = [];\n // The two arms of the binding, each named for the question it answers. The\n // first reproduces the old parameter exactly, so everything reading it below\n // is unchanged; the second is the fact that used to be thrown away.\n const unadoptedBinding = binding !== null && !binding.adopted ? binding.id : null;\n const adoptedBinding = binding !== null && binding.adopted ? binding.id : null;\n // The features that bring the bound service into being, when any in flight\n // do. Their steps lead and the feature loop below skips them, so a feature\n // this repository exists for is named once, first — EVERY one of them, since\n // whichever archives first is the one that makes the service living.\n const introducing = unadoptedBinding === null ? [] : features.filter((f) => binding!.introducedBy.includes(f.id));\n\n // The repository this command is standing in names a service the fleet has no\n // directory for. First, ahead of every other service's partial adoption,\n // because it is the only step that is about HERE.\n //\n // This form used to count the fleet and ignore the binding entirely, so in a\n // service repo bound to an unadopted service — a freshly wired one, the most\n // common repo there is — an empty fleet made \"every service is written down\"\n // vacuously true and `next.fleet-clean` came out top. `loam doctor` had the\n // right answer (`doctor.service-unknown`) at the same moment, and the\n // documented agent loop reads `status`: an agent following it was sent to\n // start a feature instead of adopting the service under its feet.\n //\n // Unless a feature in flight INTRODUCES the service. Then there is no code\n // yet for `loam adopt` to read — the feature's own specs/ ARE its documents\n // until it archives — and telling its first developer to adopt it sent them\n // to describe an empty repository. The step is the feature's, under the code\n // the feature loop already emits, so nothing new needs branching on.\n for (const f of introducing) {\n const others = introducing.filter((o) => o !== f).map((o) => o.id);\n steps.push({\n code: \"next.feature\",\n statement:\n `This repository's loam.json says it is '${unadoptedBinding}', which ${f.id} introduces` +\n (others.length > 0 ? ` (so does ${others.join(\", \")})` : \"\") +\n ` — it is not in the living docs until ${others.length > 0 ? \"one of them\" : f.id} archives, so there is ` +\n `nothing to adopt; ${f.id}'s own status says what this repository owes it.`,\n command: `loam status ${f.id} --json`,\n });\n }\n if (unadoptedBinding !== null && introducing.length === 0) {\n steps.push({\n code: \"next.adopt-bound\",\n statement:\n `This repository's loam.json says it is '${unadoptedBinding}', and the fleet has no ` +\n `services/${unadoptedBinding}/ — nothing about the service you are standing in is written down yet.`,\n command: `loam adopt --service ${unadoptedBinding} --json`,\n service: unadoptedBinding,\n });\n }\n\n // The first hour of a docs repo, in order. Zero services and zero features\n // used to fall through every loop below into `next.fleet-clean` — the header\n // says why that answer was vacuous — so the emptiest repository loam serves\n // got the least from the command whose whole purpose is \"what do I do next\".\n // These are ordinary steps on purpose: the gate entry still closes the list,\n // and the tail ternary is untouched. The bind/adopt rungs are suppressed when\n // `next.adopt-bound` above already names the exact adopt to run, and the\n // whole ladder is withheld on narrowed runs (`teaching === null`).\n if (teaching !== null && services.length === 0 && features.length === 0) {\n if (teaching.landscape !== \"authored\") {\n steps.push({\n code: \"next.author-landscape\",\n statement:\n teaching.landscape === \"missing\"\n ? \"architecture/landscape.likec4 does not exist — the fleet map is the one artifact every \" +\n \"cross-service check reads. Run `loam init --create` to scaffold it, then draw the first service.\"\n : \"architecture/landscape.likec4 is still the scaffold's untouched map — no service is drawn. \" +\n \"State the facts in a fleet.yaml (service ids, `a -> b` calls) and run \" +\n \"`loam seed --from fleet.yaml` to template the map mechanically — or open the file \" +\n \"and follow its own comments. Either way loam never guesses who calls whom.\",\n // The command each arm's own prose already names, and for a while it\n // was neither: both arms carried the gate. WORKFLOW.md documents the\n // agent loop as \"read next[0], run the command it names, repeat\" and\n // every generated skill says to branch on the code rather than the\n // prose — so an agent on the first rung of the first hour ran\n // `validate --all` against a repository with no services in it, which\n // answers ok:true with `landscape.matched` and changes nothing, and\n // came back to the identical next[0] forever. A livelock on day zero,\n // on the one command built to answer \"what now\". The gate is still\n // named: `next.fleet-gate` closes this same list.\n command: teaching.landscape === \"missing\" ? \"loam init --create\" : \"loam seed --from fleet.yaml\",\n path: \"architecture/landscape.likec4\",\n });\n }\n if (unadoptedBinding === null) {\n steps.push({\n code: \"next.bind-service\",\n statement:\n \"No service repository is bound to this fleet yet. From a service's own repo, point --docs \" +\n \"here and --service at its canonical id with the service agent profile, then commit the \" +\n \"loam.json it writes.\",\n // `--agent-profile service`, because the default is `full`, and `full`\n // writes loam-feature and loam-ship into the service checkout — the two\n // workflows this docs repo keeps, which README tells every service\n // repo to leave out. An agent runs this literal, not the README.\n command: \"loam init --docs <path-to-this-docs-repo> --service <service-id> --agent-profile service\",\n });\n steps.push({\n code: \"next.adopt-first\",\n statement:\n \"services/ is empty — nothing about any service is written down yet. Adopt the first one: \" +\n \"the brief walks an agent through writing its baseline docs as draft.\",\n command: \"loam adopt --service <service-id> --json\",\n });\n }\n }\n\n // Features BEFORE the per-service rungs. The rungs used to lead, on the\n // reading that an adoption gap blocks grading — and on a fleet mid-adoption\n // that put a page of `next.adopt` lines ahead of the one feature anybody was\n // working on, and the cap below elided that feature as \"more step(s) of the\n // same kinds\": the only change in flight, invisible under the heading\n // \"next\". A feature is work somebody started; an undocumented service is\n // backlog. The rungs still follow, and still in full where it matters —\n // `serviceSteps` beside this list carries every one of them uncapped.\n const ordered = [...features].sort(\n (a, b) =>\n STAGE_RANK[a.stage] - STAGE_RANK[b.stage] ||\n graph.order.indexOf(a.id) - graph.order.indexOf(b.id) ||\n compareIds(a.id, b.id),\n );\n for (const f of ordered) {\n if (introducing.includes(f)) continue;\n const label = featureLabel(f);\n if (f.stage === \"done\") {\n steps.push({\n code: \"next.archive\",\n statement: `${label} is authored and verified — archive it to fold its deltas into the living docs, and everything waiting on it is released.`,\n command: `loam archive ${f.id} --dry-run --json`,\n });\n continue;\n }\n steps.push({\n code: \"next.feature\",\n statement:\n // The list, not the stage, is what this sentence names. `blocked` has\n // two causes now — another feature in flight, and an interrupted commit\n // that stalls the whole repository — and the second one names no\n // feature, so keying off the stage alone printed \"FEAT-1 is waiting\n // on .\" The recover step above already says what the repository is\n // waiting on.\n //\n // And never the bare stage word: \"FEAT-1 is at 'ready'\" over a feature\n // with nothing built read as ready to ship. `stageWords` is the one\n // place the human sentence for a stage lives (../feature/words.ts).\n f.stage === \"blocked\" && interrupted === null && f.blockedBy.length > 0\n ? `${label} is waiting on ${f.blockedBy.join(\", \")}.`\n : `${label}: ${fleetStageWords(f, interrupted !== null)}.`,\n command: `loam status ${f.id} --json`,\n });\n }\n\n steps.push(...perServiceSteps(services, adoptedBinding));\n\n const left = steps.slice(FLEET_NEXT_LIMIT);\n // Outside the cap, not merely first inside it: the one step that must never\n // be the one this list left out.\n const out = [...(interrupted === null ? [] : [recoverStep(interrupted)]), ...steps.slice(0, FLEET_NEXT_LIMIT)];\n if (left.length > 0) {\n // Which kinds, counted: \"of the same kinds\" told a reader nothing about\n // whether the feature they came for was among the missing.\n const kinds = [...new Set(left.map((s) => s.code))].map((code) => `${left.filter((s) => s.code === code).length} ${code}`);\n out.push({\n code: \"next.elided\",\n statement: `${left.length} more step(s) were left out (${kinds.join(\", \")}) — this list is ordered most-unblocking first, so work down it and run status again.`,\n command: \"loam list --json\",\n });\n }\n\n out.push(\n steps.length === 0\n ? {\n code: \"next.fleet-clean\",\n statement:\n \"Nothing is in flight and every service is written down — keep the fleet green, then start the next feature.\",\n command: \"loam validate --all --json\",\n }\n : {\n code: \"next.fleet-gate\",\n // `loam validate --all` inside the backticks, not the bare\n // `validate --all` this sentence carried for a year: a span without\n // the binary name is invisible to every check that reads a\n // backticked `loam <verb>` as an instruction — the parse check in\n // test/agent-commands-runnable.test.ts, and the statement/command\n // invariant in test/status.test.ts. A prefix is cheaper than an\n // exemption, and the exemption is what lets a wrong command through.\n statement:\n `${features.length} feature(s) in flight over ${services.length} service(s) — ` +\n \"status grades none of them; `loam validate --all` is the gate this repository has to pass, and it is what CI runs.\",\n command: \"loam validate --all --json\",\n },\n );\n return out;\n}\n\n/**\n * Every per-service rung, in the order the list prints them: the bound\n * service's own first, then the rest alphabetically. Exported because the\n * same list, uncapped and grouped (`groupServiceSteps`), rides beside `next[]`\n * as `serviceSteps` — one derivation, so the two can never disagree about\n * what a service owes.\n */\nexport function perServiceSteps(services: ServiceEntry[], adoptedBinding: string | null): NextStep[] {\n // The per-service rungs are collected as one list because the partition\n // below acts on them as a group — and only on them. Where the list goes is\n // the caller's: `fleetNext` puts it after every feature, and nothing here may\n // float above `next.adopt-bound` or the first-hour ladder, both of which are\n // about the repository rather than about any one service in the fleet.\n const perService: NextStep[] = [];\n // `adoption: partial` is one feature's slice archived into a service never\n // adopted (SCHEMA.md); the file's presence used to discharge this rung.\n for (const s of services.filter((x) => undocumented(x) || x.adoption !== null)) {\n perService.push({\n code: \"next.adopt\",\n statement: undocumented(s)\n ? `${serviceTreePath(s)}/ has no spec.md — nothing about ${s.id} is written down, so no feature can be graded against it.`\n : `${serviceTreePath(s)}/spec.md is adoption: partial — it holds what an archived feature added, nothing of what ${s.id} already did.`,\n command: `loam adopt --service ${s.id} --json`,\n service: s.id,\n });\n }\n\n // Adoption does not end at spec.md. A service with a living spec and no\n // model.likec4 is the state archive itself warns about (`service.no-model`)\n // and the fleet gate reports — invisible here until now, because this form\n // looked at exactly one bit of each service's artifact set.\n for (const s of services.filter((x) => !undocumented(x) && x.adoption === null && !x.has.model)) {\n perService.push({\n code: \"next.complete-service\",\n statement: `${serviceTreePath(s)}/ has a spec.md but no model.likec4 — the fleet gate reports the service incomplete until something models it.`,\n command: `loam validate --service ${s.id} --json`,\n service: s.id,\n });\n }\n\n // A vouch the document has moved out from under. `content.stale` needs\n // nothing but the document, so unlike `sources.stale` this form CAN see it —\n // and before it looked, a fleet whose specs were edited after the person read\n // them got `next.fleet-clean`: \"nothing is owed\" over words nobody had\n // re-read, while `loam validate` warned about each one. The re-vouch is a\n // person's act from that service's own repository (`loam vouch` restamps the\n // code side too), so the step names the documents and that repository, and\n // its execution contract is a human review rather than a command to run.\n for (const s of services.filter((x) => vouched(x) && x.contentStale.length > 0)) {\n const files = s.contentStale.map((file) => `${serviceTreePath(s)}/${file}`);\n perService.push({\n code: \"next.revouch\",\n statement:\n `${files.join(\" and \")} changed since ${s.id} was vouched — \\`status: verified\\` stands over words nobody has re-read (content.stale). ` +\n `A person re-reads what moved (\\`loam vouch --pack --service ${s.id}\\` lists it) and re-vouches from ${s.id}'s own repository.`,\n command: `loam vouch --service ${s.id}`,\n service: s.id,\n });\n }\n\n // The boundary this repository IS comes first among the boundaries it merely\n // shares a fleet with. A stable PARTITION and deliberately not a sort: the\n // bound service's rungs move to the front and every other service keeps the\n // alphabetical order it already had, so the list an unbound reader sees — a\n // docs repo, CI, `loam validate --all`'s scorecard — is byte-for-byte the one\n // it saw before.\n //\n // The cap is why this is ordering and not cosmetics. Ten steps print, and in\n // the ten-repo case WORKFLOW.md describes every developer's `loam status`\n // listed nine other services' adoption work ahead of their own; past ten\n // services the one rung this developer can actually act on was elided\n // entirely, leaving a list of nothing but other people's boundaries under\n // the heading \"next\". No new code is emitted for any of this — `next[]` has\n // always been documented as most-unblocking first, and this is the line that\n // makes the claim true from where the reader is standing.\n return adoptedBinding === null\n ? perService\n : [\n ...perService.filter((s) => s.service === adoptedBinding),\n ...perService.filter((s) => s.service !== adoptedBinding),\n ];\n}\n\n/**\n * `perServiceSteps` grouped by code, in first-appearance order — the\n * `serviceSteps` payload. `command` is the FIRST service's step command, so a\n * reader folding forty rungs into one line still gets a literal to run rather\n * than a second spelling of it.\n */\nexport function groupServiceSteps(steps: NextStep[]): Array<{ code: string; services: string[]; command: string }> {\n const groups = new Map<string, { code: string; services: string[]; command: string }>();\n for (const step of steps) {\n if (step.service === undefined) continue;\n const group = groups.get(step.code) ?? { code: step.code, services: [], command: step.command };\n group.services.push(step.service);\n groups.set(step.code, group);\n }\n return [...groups.values()];\n}\n"]}
@@ -0,0 +1,97 @@
1
+ /**
2
+ * The one state that outranks everything else: a journaled writer — archive,
3
+ * unarchive, rebase, vouch, new, or a record — killed mid-commit, read off
4
+ * the intent journal `.loam-commit` leaves in the docs repo. The shape both report forms carry it in is `InterruptedCommit`
5
+ * (report.ts); this module is the cheap read behind it, and the recovery step
6
+ * that leads every `next[]` while the journal exists.
7
+ */
8
+ import { existsSync } from "node:fs";
9
+ import { join } from "node:path";
10
+ import { COMMIT_INTENT } from "../staging/interrupted.js";
11
+ import { readCommitIntent } from "../staging/recovery/intent.js";
12
+ import { readTxnIntent } from "../staging/txn/journal.js";
13
+ /**
14
+ * The intent journal, if a commit left one behind. Null on every healthy repo,
15
+ * which is every repo except one whose last write was killed.
16
+ *
17
+ * Cheap on purpose: an `existsSync` and, at most, one small JSON read. `doctor`
18
+ * pays for the whole `scanWritePathResidue` walk because it is a diagnosis;
19
+ * `status` is run before every step of the loop and asks the one question whose
20
+ * answer invalidates all its others.
21
+ */
22
+ export async function readInterruptedCommit(docsDir) {
23
+ const intent = await readCommitIntent(docsDir);
24
+ if (intent === null) {
25
+ if (!existsSync(join(docsDir, COMMIT_INTENT)))
26
+ return null;
27
+ // Version 2 — the smaller journaled transaction. Its `rerun` field IS the
28
+ // recovering command: recovery runs at the start of that command's next
29
+ // invocation, exactly as archive's does under its own lock.
30
+ const txn = await readTxnIntent(docsDir);
31
+ if (txn !== null) {
32
+ return {
33
+ command: txn.command,
34
+ feature: txn.target,
35
+ host: txn.host,
36
+ pid: txn.pid,
37
+ at: txn.at,
38
+ files: txn.files.map((f) => f.path),
39
+ unreadable: false,
40
+ recover: txn.rerun,
41
+ };
42
+ }
43
+ return {
44
+ command: null,
45
+ feature: null,
46
+ host: null,
47
+ pid: null,
48
+ at: null,
49
+ files: [],
50
+ unreadable: true,
51
+ recover: null,
52
+ };
53
+ }
54
+ return {
55
+ command: intent.command,
56
+ feature: intent.feature,
57
+ // Coerced here rather than trusted. `readCommitIntent` validates exactly the
58
+ // fields a REPAIR needs — the version, the command, the restore direction,
59
+ // the feature, the two move paths and the file digests — so `host`, `pid`
60
+ // and `at` arrive as whatever the journal happened to hold, `undefined`
61
+ // included. That is worse than null in both renderings: `JSON.stringify`
62
+ // drops an undefined value's key entirely, so `--json` loses the field
63
+ // instead of reporting it empty, and the two human lines print
64
+ // "(undefined, pid undefined, undefined)". These three are the label a
65
+ // person places the crash against and nothing branches on them, so the
66
+ // coercion belongs at this boundary — widening the validator would change
67
+ // which journals `archive` and `unarchive` agree to repair, which is a
68
+ // decision about somebody's half-written docs, not about a label.
69
+ host: typeof intent.host === "string" ? intent.host : null,
70
+ pid: typeof intent.pid === "number" ? intent.pid : null,
71
+ at: typeof intent.at === "string" ? intent.at : null,
72
+ files: intent.files.map((f) => f.path),
73
+ unreadable: false,
74
+ // The recovering command is the interrupted one re-run: it repairs first,
75
+ // under the lock, from the snapshot it took before the commit. Spelled per
76
+ // branch rather than interpolated, like doctor's own repair line, so
77
+ // test/agent-commands-runnable.test.ts can parse it against the real program.
78
+ recover: intent.command === "archive" ? `loam archive ${intent.feature}` : `loam unarchive ${intent.feature}`,
79
+ };
80
+ }
81
+ /**
82
+ * The step that has to come before every other one. Always first, and never
83
+ * elided by the fleet form's cap: nothing else in the list can be done until
84
+ * somebody knows whether the living docs are the docs.
85
+ */
86
+ export function recoverStep(i) {
87
+ return {
88
+ code: "next.recover-commit",
89
+ statement: i.unreadable
90
+ ? `${COMMIT_INTENT} in this docs repo cannot be read — a commit was interrupted and the one record of which files it had already written is unreadable. Nothing below can be trusted until a human compares the living docs against version control.`
91
+ : `A \`${i.recover}\` was killed mid-commit (${i.host}, pid ${i.pid}, ${i.at}) — ${i.files.length} file(s) may be half-written: ${i.files.join(", ")}. Everything below is derived from those files.`,
92
+ // No command loam offers repairs an unreadable journal — saying otherwise
93
+ // would send an agent to run something that refuses.
94
+ command: i.recover ?? "loam doctor --json",
95
+ };
96
+ }
97
+ //# sourceMappingURL=interrupted.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interrupted.js","sourceRoot":"","sources":["../../../src/core/status/interrupted.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The one state that outranks everything else: a journaled writer — archive,\n * unarchive, rebase, vouch, new, or a record — killed mid-commit, read off\n * the intent journal `.loam-commit` leaves in the docs repo. The shape both report forms carry it in is `InterruptedCommit`\n * (report.ts); this module is the cheap read behind it, and the recovery step\n * that leads every `next[]` while the journal exists.\n */\nimport { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { COMMIT_INTENT } from \"../staging/interrupted.js\";\nimport { readCommitIntent } from \"../staging/recovery/intent.js\";\nimport { readTxnIntent } from \"../staging/txn/journal.js\";\nimport type { InterruptedCommit, NextStep } from \"./report.js\";\n\n/**\n * The intent journal, if a commit left one behind. Null on every healthy repo,\n * which is every repo except one whose last write was killed.\n *\n * Cheap on purpose: an `existsSync` and, at most, one small JSON read. `doctor`\n * pays for the whole `scanWritePathResidue` walk because it is a diagnosis;\n * `status` is run before every step of the loop and asks the one question whose\n * answer invalidates all its others.\n */\nexport async function readInterruptedCommit(docsDir: string): Promise<InterruptedCommit | null> {\n const intent = await readCommitIntent(docsDir);\n if (intent === null) {\n if (!existsSync(join(docsDir, COMMIT_INTENT))) return null;\n // Version 2 — the smaller journaled transaction. Its `rerun` field IS the\n // recovering command: recovery runs at the start of that command's next\n // invocation, exactly as archive's does under its own lock.\n const txn = await readTxnIntent(docsDir);\n if (txn !== null) {\n return {\n command: txn.command,\n feature: txn.target,\n host: txn.host,\n pid: txn.pid,\n at: txn.at,\n files: txn.files.map((f) => f.path),\n unreadable: false,\n recover: txn.rerun,\n };\n }\n return {\n command: null,\n feature: null,\n host: null,\n pid: null,\n at: null,\n files: [],\n unreadable: true,\n recover: null,\n };\n }\n return {\n command: intent.command,\n feature: intent.feature,\n // Coerced here rather than trusted. `readCommitIntent` validates exactly the\n // fields a REPAIR needs — the version, the command, the restore direction,\n // the feature, the two move paths and the file digests — so `host`, `pid`\n // and `at` arrive as whatever the journal happened to hold, `undefined`\n // included. That is worse than null in both renderings: `JSON.stringify`\n // drops an undefined value's key entirely, so `--json` loses the field\n // instead of reporting it empty, and the two human lines print\n // \"(undefined, pid undefined, undefined)\". These three are the label a\n // person places the crash against and nothing branches on them, so the\n // coercion belongs at this boundary — widening the validator would change\n // which journals `archive` and `unarchive` agree to repair, which is a\n // decision about somebody's half-written docs, not about a label.\n host: typeof intent.host === \"string\" ? intent.host : null,\n pid: typeof intent.pid === \"number\" ? intent.pid : null,\n at: typeof intent.at === \"string\" ? intent.at : null,\n files: intent.files.map((f) => f.path),\n unreadable: false,\n // The recovering command is the interrupted one re-run: it repairs first,\n // under the lock, from the snapshot it took before the commit. Spelled per\n // branch rather than interpolated, like doctor's own repair line, so\n // test/agent-commands-runnable.test.ts can parse it against the real program.\n recover: intent.command === \"archive\" ? `loam archive ${intent.feature}` : `loam unarchive ${intent.feature}`,\n };\n}\n\n/**\n * The step that has to come before every other one. Always first, and never\n * elided by the fleet form's cap: nothing else in the list can be done until\n * somebody knows whether the living docs are the docs.\n */\nexport function recoverStep(i: InterruptedCommit): NextStep {\n return {\n code: \"next.recover-commit\",\n statement: i.unreadable\n ? `${COMMIT_INTENT} in this docs repo cannot be read — a commit was interrupted and the one record of which files it had already written is unreadable. Nothing below can be trusted until a human compares the living docs against version control.`\n : `A \\`${i.recover}\\` was killed mid-commit (${i.host}, pid ${i.pid}, ${i.at}) — ${i.files.length} file(s) may be half-written: ${i.files.join(\", \")}. Everything below is derived from those files.`,\n // No command loam offers repairs an unreadable journal — saying otherwise\n // would send an agent to run something that refuses.\n command: i.recover ?? \"loam doctor --json\",\n };\n}\n"]}
@@ -0,0 +1,31 @@
1
+ /** The closed set. The module header says what each value instructs. */
2
+ export const ARTIFACT_STATUSES = ["missing", "blocked", "draft", "ready", "done"];
3
+ /**
4
+ * The artifact kinds a feature can owe, in the order the cycle authors them.
5
+ * `spec`, `arch-spec`, `openapi` and `asyncapi` are per-service and repeat
6
+ * once per service the feature touches; `capabilities` repeats once per
7
+ * capability document the feature's delta carries; the rest are feature-wide.
8
+ *
9
+ * `capabilities` sits where an analyst writes it — the business promise comes
10
+ * before the services that keep it, and a capability-only feature is a real and
11
+ * ordinary first commit.
12
+ */
13
+ export const ARTIFACT_IDS = [
14
+ "intent",
15
+ "delta",
16
+ "capabilities",
17
+ "spec",
18
+ "arch-spec",
19
+ "openapi",
20
+ "asyncapi",
21
+ "verification",
22
+ ];
23
+ /** Nothing is written down: no living spec at all. Every other absence is partial adoption. */
24
+ export function undocumented(s) {
25
+ return !s.has.spec;
26
+ }
27
+ /** A person stamped it — `loam vouch`'s exact postcondition, read back off the frontmatter. */
28
+ export function vouched(s) {
29
+ return s.status === "verified" && s.sources.stamped;
30
+ }
31
+ //# sourceMappingURL=report.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.js","sourceRoot":"","sources":["../../../src/core/status/report.ts"],"names":[],"mappings":"AAqFA,wEAAwE;AACxE,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,CAAU,CAAC;AAG3F;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,QAAQ;IACR,OAAO;IACP,cAAc;IACd,MAAM;IACN,WAAW;IACX,SAAS;IACT,UAAU;IACV,cAAc;CACN,CAAC;AA0RX,+FAA+F;AAC/F,MAAM,UAAU,YAAY,CAAC,CAAe;IAC1C,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC;AACrB,CAAC;AAED,+FAA+F;AAC/F,MAAM,UAAU,OAAO,CAAC,CAAe;IACrC,OAAO,CAAC,CAAC,MAAM,KAAK,UAAU,IAAI,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC;AACtD,CAAC","sourcesContent":["/**\n * Where does this work stand, and what is the next thing to do?\n *\n * Every other command answers a question you already know how to ask: validate\n * grades a target you name, delta briefs a service you name, verify checks a\n * feature you name. The one thing loam could not answer was the question an\n * agent asks FIRST — the one it has when it joins a repository halfway, or\n * comes back after losing its session. That knowledge existed, but only as\n * prose inside the slash commands (\"1. scaffold, 2. author, 3. validate\"),\n * which is to say it existed for whoever had read them recently and for nobody\n * else.\n *\n * The obvious implementation is a state file — a `.loam/state.json` recording\n * which step each feature reached. It is rejected here for the reason core/verify/\n * refuses a second mutable database: the moment a second record of the truth\n * exists, an author who edits a file by hand, a merge, a rebase or a\n * `git checkout` desynchronises it, and the state file's answer is confidently\n * wrong exactly when somebody trusts it. So `status` stores nothing and caches\n * nothing. It is a projection: every invocation re-derives the whole answer\n * from the files, and a file edited in another window is visible on the next\n * run with no invalidation step for anyone to forget.\n *\n * It also grades nothing itself. Every verdict here is somebody else's\n * function: `featureCoherence` (what `loam archive` refuses on) plus\n * `featureProvenance` and `requirementsMissingScenarios` (`loam validate\n * --feature`'s other error sources, as far as they exist as shared functions),\n * and `readVerificationState` + `featureChecklist`, the pair `loam verify`\n * uses. A second opinion about whether a feature holds together would be a\n * second answer to grade a pull request against, and the one a reader consults\n * is never the one the gate obeys (doctor.ts learnt this with its own config\n * validator). A check that lives inline inside `validate` cannot be inherited\n * at all, which is why `stage` never rests on `checks.coherent` alone.\n *\n * Which is why the rule this module is held to is one-directional: **status may\n * be more pessimistic than the gates, never greener.** `validate` and `archive`\n * answer two different questions — is the DOCUMENT valid, is the MERGE safe\n * (issue.ts) — and a projection that reported only one of them told an author\n * \"ship it\" about a feature the other one refuses. So `stage` and `next[]` take\n * the UNION: an error `validate` grades and a warning `archive` gates on both\n * make a feature `draft`, and test/status-agrees-with-gate.test.ts holds the\n * direction on a matrix of deliberately-damaged trees.\n *\n * ## The status vocabulary\n *\n * Five values, closed, and an agent is expected to branch on them:\n *\n * `missing` the artifact is owed and is not on disk; nothing stands in the\n * way of writing it now.\n * `blocked` the work is stalled on something that is NOT this artifact — an\n * artifact it is derived from is absent, or another feature in\n * flight has to archive first.\n * `draft` it is on disk and the shared checks report an error against it:\n * what exists is wrong.\n * `ready` it is on disk and clean, but its obligation is not discharged —\n * something outside the documents (code, a test run, a recording)\n * still has to answer it.\n * `done` nothing is owed here — and for an ARCHIVED feature, only that:\n * archive checks documents, never code or evidence, so whether\n * it was verified is `verification`'s answer, not this one.\n *\n * These are branching values, not sentences: the human view prints them in\n * words with the counts beside them (`feature/words.ts`), because a bare\n * `ready` over a feature with nothing built read as \"ready to ship\".\n *\n * The two pairs that look alike are the point of the set. `missing` and\n * `blocked` both mean \"not written\", and they are different instructions: one\n * says write it now, the other says you cannot yet and names what comes first —\n * an agent that cannot tell them apart authors a verification record against a\n * checklist that does not exist. `draft` and `ready` both mean \"on disk\", and\n * they are different instructions too: `draft` says the document is wrong and\n * the fix is in this repository, `ready` says the document is right and the\n * world has not caught up — the code is not built, or the claims are not\n * answered. Collapsing those two would send an agent to re-edit a spec that is\n * already correct.\n *\n * A value unreachable in a scope is simply never emitted there, deliberately:\n * the fleet form never says `draft`, because grading is a per-feature cost it\n * refuses to pay.\n */\nimport type { ServiceEntry } from \"../repo/entries.js\";\nimport type { UseCaseBlastRadius } from \"../usecases/touch.js\";\nimport type { AnsweredBy } from \"../verify/answers.js\";\nimport type { VerificationVerdict } from \"../verify/record.js\";\nimport type { Finding } from \"../vocabulary/report.js\";\n\n/** The closed set. The module header says what each value instructs. */\nexport const ARTIFACT_STATUSES = [\"missing\", \"blocked\", \"draft\", \"ready\", \"done\"] as const;\nexport type ArtifactStatus = (typeof ARTIFACT_STATUSES)[number];\n\n/**\n * The artifact kinds a feature can owe, in the order the cycle authors them.\n * `spec`, `arch-spec`, `openapi` and `asyncapi` are per-service and repeat\n * once per service the feature touches; `capabilities` repeats once per\n * capability document the feature's delta carries; the rest are feature-wide.\n *\n * `capabilities` sits where an analyst writes it — the business promise comes\n * before the services that keep it, and a capability-only feature is a real and\n * ordinary first commit.\n */\nexport const ARTIFACT_IDS = [\n \"intent\",\n \"delta\",\n \"capabilities\",\n \"spec\",\n \"arch-spec\",\n \"openapi\",\n \"asyncapi\",\n \"verification\",\n] as const;\nexport type ArtifactId = (typeof ARTIFACT_IDS)[number];\n\nexport interface ArtifactState {\n id: ArtifactId;\n /** The service this artifact belongs to, or null for the feature-wide ones. */\n service: string | null;\n /**\n * The capability this artifact belongs to, on `capabilities` rows only.\n *\n * A field of its own rather than a capability id put in `service`: the two\n * are different namespaces — a fleet may hold a service and a capability of\n * one name — and bending a published field to carry the other kind is how a\n * consumer grouping by service silently acquires a row that is not one. Absent\n * on every other row, so nothing that reads `service` today changes.\n */\n capability?: string;\n /** Repo-relative with forward slashes — diffable across machines, like every path in the contract. */\n path: string;\n exists: boolean;\n /**\n * Whether ABSENCE is a defect. False for the artifacts a feature may\n * legitimately not have: `delta.likec4` (a requirements-only change deletes\n * it), `arch.spec.md` and `asyncapi.yaml` (optional everywhere), and\n * `openapi.yaml` for a service\n * the living docs already carry. An absent optional artifact is `done` —\n * nothing is owed — and `exists: false` beside it is how a reader tells that\n * from a file that is present and fine.\n */\n required: boolean;\n status: ArtifactStatus;\n /** Artifact ids that must come first. Non-empty only when `status` is `blocked`. */\n blockedBy: string[];\n}\n\nexport interface NextStep {\n /** Stable — prose may change, this may not. */\n code: string;\n /** One sentence, actionable without reading any other field. */\n statement: string;\n /** The literal command to run. */\n command: string;\n artifact?: ArtifactId;\n service?: string;\n /** The repo-relative file the step is about, when it names one. */\n path?: string;\n}\n\nexport type NextActionKind = \"command\" | \"edit\" | \"external-repo\" | \"human-review\";\nexport type NextActionCwd = \"configured-repo\" | \"docs-repo\" | \"service-repo\";\n\n/**\n * The machine contract beside the legacy `NextStep.command` string.\n *\n * `command` exists only when every argument is concrete. An edit names the\n * file and puts the old command in `after`, because that command grades the\n * authored work rather than performing it. `needs` is data the caller must\n * obtain; it is never smuggled into a shell-looking placeholder.\n */\nexport interface NextExecution {\n kind: NextActionKind;\n runnable: boolean;\n cwd: NextActionCwd;\n command?: string;\n after?: string;\n needs?: string[];\n}\n\nexport type ExecutableNextStep = NextStep & { execution: NextExecution };\n\n/**\n * What the record beside the feature says, without asking whether anyone should\n * believe the code. `stale` is its own state and not merely \"recorded\": the\n * feature moved after the answers were written, so the record answers questions\n * that are no longer the ones being asked — which is exactly why `loam verify\n * --record` refuses to merge into it.\n */\nexport interface VerificationState {\n state: \"absent\" | \"unreadable\" | \"stale\" | \"recorded\";\n /** The day the record was written, when there is a readable one. */\n recorded: string | null;\n /**\n * `verify --json`'s own three-valued verdict, through `verificationVerdict` —\n * not a fourth opinion computed here. `attested` is the one that matters to a\n * reader of this command: complete, and resting on somebody's word about a\n * test rather than on a run.\n */\n verdict: VerificationVerdict;\n /** Every count below is `tallyRecord` — the record's `claims:` array, never its `summary:` block. */\n claims: number;\n confirmed: number;\n unconfirmed: number;\n /** Federated records only: claims nobody has answered yet. */\n unanswered: number;\n /** Of the confirmed, the scenario claims on an agent's word (`attestedClaims`). */\n attested: number;\n /**\n * Of the confirmed, one count per `answered_by` value (`confirmedProvenance`),\n * every key present — `list --json`'s `answered`, under the same name. A\n * different question from `attested`: that one asks only about the scenario\n * claims the verdict turns on, this one who answered EVERY kind, so a record\n * `verified` on its scenarios can still say six of its answers were an\n * agent's word about a permission or an edge.\n */\n answered: Record<AnsweredBy, number>;\n}\n\n/**\n * A `loam archive`/`unarchive` that was killed mid-commit, read off the intent\n * journal `.loam-commit` leaves in the docs repo.\n *\n * It belongs in a projection that grades nothing because it is not a grade: it\n * is the one repository state where every OTHER answer this command gives is\n * about files that may be half-written. `doctor` blocks on it; `status` is what\n * an agent runs first, and it reported `done` over a half-merged repo — so it\n * says so too, from the same journal, and leads its steps with the repair.\n *\n * Read, never repaired: recovery happens under the docs lock inside `archive`\n * and `unarchive`, and `status` writes nothing and takes no lock.\n */\nexport interface InterruptedCommit {\n /**\n * Which command was committing, or null when the journal cannot be read at\n * all. A sentence for a human, never a branch: version-2 journals carry any\n * writer's name (rebase, vouch, new, gherkin), so an enum here would be a\n * list this type has to chase.\n */\n command: string | null;\n feature: string | null;\n /** Who and when, so a human can place it against their own shell history. */\n host: string | null;\n pid: number | null;\n at: string | null;\n /** Docs-repo-relative paths that may hold half-written bytes. */\n files: string[];\n /** `.loam-commit` exists but does not parse — the worst case, because nothing can grade it. */\n unreadable: boolean;\n /** The command that recovers, or null when only a human can. */\n recover: string | null;\n}\n\nexport interface FeatureStatusReport {\n /**\n * A killed commit in this docs repo, or null. Present on both forms: it is a\n * fact about the repository, and every artifact row below it is a fact about\n * files that repository may have half-written.\n */\n interrupted: InterruptedCommit | null;\n feature: {\n id: string;\n /** intent.md's title, for a person (`featureTitle`); null when it names none. Additive. */\n title: string | null;\n dirName: string;\n path: string;\n archived: boolean;\n /** The feature's own rollup, from the same vocabulary as its artifacts. */\n stage: ArtifactStatus;\n /** Every service the feature touches, whatever `--service` narrowed the view to. */\n services: string[];\n /** Active features that must archive before this one, from the dependency index. */\n blockedBy: string[];\n };\n /** The `--service` narrowing, or null when the whole feature is in view. */\n service: string | null;\n artifacts: ArtifactState[];\n /**\n * The grade, from the same calls the two gates make: `featureCoherence`\n * (archive), plus `featureProvenance` and the scenario-coverage check — the\n * error sources `validate --feature` shares as functions. `ran` is false for\n * an archived feature: its delta is already merged into the living docs, so\n * re-grading it would compare a change against a world that has absorbed it.\n */\n checks: {\n ran: boolean;\n /**\n * No error among the findings above — `loam validate --feature`'s verdict\n * for every error source that is a shared function. It is not on its own\n * what makes a feature shippable: `stage` and `next[]` take the union with\n * archive's gating set, because a warning that gates is a warning this\n * field reports as coherent.\n */\n coherent: boolean;\n errors: number;\n warnings: number;\n /**\n * Findings carrying `gates: true` — archive's judgement calls, which `--approve` overrides. Not\n * every refusal: its pre-plan ones (unknown service, bad specs/ name, conflict markers) are errors.\n */\n gating: number;\n /**\n * Findings, not Issues: the set is wider than coherence now, and `gates` is\n * resolved on every coherence finding so a consumer never re-implements the\n * severity default. One breach reported by `validate` and by `status` has\n * to arrive in one shape.\n */\n issues: Finding[];\n };\n verification: VerificationState;\n /**\n * How many claims the feature's checklist asks NOW, or null for an archived\n * feature (frozen history: nothing is re-derived). Additive. With no record\n * every count in `verification` is zero, and \"0 of 0\" is not what an\n * unverified feature with nineteen promises is.\n */\n checklist: { claims: number } | null;\n /**\n * The declared business flows the services IN VIEW are hops of — blast\n * radius, and the only field here that is a fact about the fleet rather than\n * about the feature.\n *\n * It narrows with `--service` exactly as `artifacts` and `next` do, because\n * `--service` is a lens on what the reader is being asked to do next. What it\n * must never do is go silently empty: `unreadable` is how it says that\n * `architecture/` could not be read, which is a different fact from a fleet\n * that draws no use cases and produces the identical empty list.\n *\n * The FLEET form has no equivalent, deliberately. That form grades nothing and\n * is coarse by design, and a per-feature flow join over every feature in flight\n * is exactly the per-feature cost it refuses to pay.\n */\n useCases: UseCaseBlastRadius;\n next: NextStep[];\n}\n\nexport interface FleetFeatureState {\n id: string;\n /** See {@link FeatureStatusReport.feature}'s `title`. */\n title: string | null;\n dirName: string;\n path: string;\n stage: ArtifactStatus;\n services: string[];\n blockedBy: string[];\n /** Artifacts the feature owes and has not written. Presence only — the fleet form grades nothing. */\n missing: string[];\n verification: VerificationState;\n}\n\nexport interface FleetStatusReport {\n /** See {@link FeatureStatusReport.interrupted}. */\n interrupted: InterruptedCommit | null;\n /**\n * Three disjoint buckets over `services/`, summing to `total`. Deliberately\n * coarser than `list`'s maturity ladder, and deliberately not the same words:\n * that ladder grades an adoption campaign rung by rung, this asks only\n * whether there is anything here to build a feature on.\n */\n services: {\n total: number;\n /** No `spec.md` — nothing about this service is written down. */\n undocumented: number;\n /** Documented, with no vouch stamp behind it. */\n draft: number;\n /** `status: verified` with a `sources_digest` — a person stood behind it. */\n vouched: number;\n /**\n * Of `vouched`, the ones read from a recorded SAMPLE rather than in full\n * (`vouch_scope`, either axis) — a SUBSET: the three above still sum to `total`.\n */\n sampledVouched: number;\n /**\n * Of `vouched`, the ones with a stamped document whose words moved after\n * the vouch (`content.stale`, either axis) — a SUBSET like\n * `sampledVouched`, and each one is a `next.revouch` step below.\n */\n contentStale: number;\n };\n features: FleetFeatureState[];\n /** Dependencies before consumers — which feature has to archive first. */\n order: string[];\n service: string | null;\n next: NextStep[];\n /**\n * Every per-service rung (`next.adopt`, `next.complete-service`,\n * `next.revouch`), UNCAPPED and grouped by code, services in `next[]` order.\n * Additive. `next[]` stops at ten, so mid-adoption it cannot say how much\n * adoption work there is; this can, and the human view folds it into one\n * counted line under the features.\n */\n serviceSteps: Array<{ code: string; services: string[]; command: string }>;\n}\n\n/** Nothing is written down: no living spec at all. Every other absence is partial adoption. */\nexport function undocumented(s: ServiceEntry): boolean {\n return !s.has.spec;\n}\n\n/** A person stamped it — `loam vouch`'s exact postcondition, read back off the frontmatter. */\nexport function vouched(s: ServiceEntry): boolean {\n return s.status === \"verified\" && s.sources.stamped;\n}\n"]}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Reading a feature's per-service deltas without grading them. Both status
3
+ * forms draw on this one scan: it is how the artifact table and the fleet form
4
+ * decide which services owe a contract, and where the scenario steps come from.
5
+ */
6
+ import { existsSync } from "node:fs";
7
+ import { requirementsMissingScenarios } from "../document/scenarios.js";
8
+ import {} from "../document/spec.js";
9
+ import { repoPath } from "../envelope/json.js";
10
+ import { featureSpecPaths, SPEC_AXES } from "../repo/paths.js";
11
+ export async function scanDeltas(docsDir, feature, services, context) {
12
+ const out = [];
13
+ for (const svc of services) {
14
+ const p = featureSpecPaths(feature.dir, svc);
15
+ // SPEC_AXES already carries the prose name of each axis — "requirements"
16
+ // and "arch requirements" are its `label`s verbatim — so the pair is read
17
+ // from there rather than spelled again, and a service's status can never
18
+ // walk a different set of spec files than its validation does.
19
+ for (const [file, label] of SPEC_AXES.map((axis) => [p[axis.key], `${svc}: ${axis.label}`])) {
20
+ if (!existsSync(file))
21
+ continue;
22
+ const reqs = await context.readRequirements(file);
23
+ out.push({
24
+ service: svc,
25
+ path: repoPath(docsDir, file),
26
+ label,
27
+ bare: requirementsMissingScenarios(reqs),
28
+ scenarios: reqs.reduce((n, r) => n + r.scenarios.length, 0),
29
+ operations: file === p.spec
30
+ ? reqs.filter((r) => r.kind !== "REMOVED").reduce((n, r) => n + r.operations.length, 0)
31
+ : 0,
32
+ });
33
+ }
34
+ }
35
+ return out;
36
+ }
37
+ /** Services this feature sends at least one operation to — see contracts.ts's `owesContract`. */
38
+ export function governedServices(scans) {
39
+ return new Set(scans.filter((s) => s.operations > 0).map((s) => s.service));
40
+ }
41
+ //# sourceMappingURL=scan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scan.js","sourceRoot":"","sources":["../../../src/core/status/scan.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,4BAA4B,EAAE,MAAM,0BAA0B,CAAC;AACxE,OAAO,EAAoB,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAG/C,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAyB/D,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,OAAgB,EAChB,OAAqB,EACrB,QAA2B,EAC3B,OAAqB;IAErB,MAAM,GAAG,GAAgB,EAAE,CAAC;IAC5B,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;QAC3B,MAAM,CAAC,GAAG,gBAAgB,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QAC7C,yEAAyE;QACzE,0EAA0E;QAC1E,yEAAyE;QACzE,+DAA+D;QAC/D,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,SAAS,CAAC,GAAG,CACvC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,GAAG,GAAG,KAAK,IAAI,CAAC,KAAK,EAAE,CAAU,CAC1D,EAAE,CAAC;YACF,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;gBAAE,SAAS;YAChC,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;YAClD,GAAG,CAAC,IAAI,CAAC;gBACP,OAAO,EAAE,GAAG;gBACZ,IAAI,EAAE,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC;gBAC7B,KAAK;gBACL,IAAI,EAAE,4BAA4B,CAAC,IAAI,CAAC;gBACxC,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC;gBAC3D,UAAU,EACR,IAAI,KAAK,CAAC,CAAC,IAAI;oBACb,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC;oBACvF,CAAC,CAAC,CAAC;aACR,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,iGAAiG;AACjG,MAAM,UAAU,gBAAgB,CAAC,KAA2B;IAC1D,OAAO,IAAI,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;AAC9E,CAAC","sourcesContent":["/**\n * Reading a feature's per-service deltas without grading them. Both status\n * forms draw on this one scan: it is how the artifact table and the fleet form\n * decide which services owe a contract, and where the scenario steps come from.\n */\nimport { existsSync } from \"node:fs\";\nimport { requirementsMissingScenarios } from \"../document/scenarios.js\";\nimport { type Requirement } from \"../document/spec.js\";\nimport { repoPath } from \"../envelope/json.js\";\nimport type { FleetContext } from \"../fleet-context.js\";\nimport type { FeatureEntry } from \"../repo/entries.js\";\nimport { featureSpecPaths, SPEC_AXES } from \"../repo/paths.js\";\nimport type { DocsDir } from \"../kernel/ids/dirs.js\";\nimport type { PathableService } from \"../kernel/ids/service.js\";\n\n/**\n * One read of each per-service delta, answering the three questions the two\n * status forms ask of it: which requirements carry no scenario (via the same\n * `requirementsMissingScenarios` every coverage check calls — REMOVED\n * requirements are exempt there and stay exempt here, content on its way out\n * owes no acceptance criteria), how many scenarios there are to generate a\n * suite from, and whether the delta governs any operation at all — which is\n * what decides whether the service is owed a contract.\n */\nexport interface DeltaScan {\n service: string;\n /** Repo-relative, and the file the steps point at. */\n path: string;\n /** validate's own label for this axis: `<svc>: requirements` / `<svc>: arch requirements`. */\n label: string;\n bare: Requirement[];\n scenarios: number;\n /** Operations the non-REMOVED requirements govern. `spec.md` only, like coherence's own `reqOps`. */\n operations: number;\n}\n\nexport async function scanDeltas(\n docsDir: DocsDir,\n feature: FeatureEntry,\n services: PathableService[],\n context: FleetContext,\n): Promise<DeltaScan[]> {\n const out: DeltaScan[] = [];\n for (const svc of services) {\n const p = featureSpecPaths(feature.dir, svc);\n // SPEC_AXES already carries the prose name of each axis — \"requirements\"\n // and \"arch requirements\" are its `label`s verbatim — so the pair is read\n // from there rather than spelled again, and a service's status can never\n // walk a different set of spec files than its validation does.\n for (const [file, label] of SPEC_AXES.map(\n (axis) => [p[axis.key], `${svc}: ${axis.label}`] as const,\n )) {\n if (!existsSync(file)) continue;\n const reqs = await context.readRequirements(file);\n out.push({\n service: svc,\n path: repoPath(docsDir, file),\n label,\n bare: requirementsMissingScenarios(reqs),\n scenarios: reqs.reduce((n, r) => n + r.scenarios.length, 0),\n operations:\n file === p.spec\n ? reqs.filter((r) => r.kind !== \"REMOVED\").reduce((n, r) => n + r.operations.length, 0)\n : 0,\n });\n }\n }\n return out;\n}\n\n/** Services this feature sends at least one operation to — see contracts.ts's `owesContract`. */\nexport function governedServices(scans: readonly DeltaScan[]): ReadonlySet<string> {\n return new Set(scans.filter((s) => s.operations > 0).map((s) => s.service));\n}\n"]}