@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 @@
1
+ {"version":3,"file":"diff.js","sourceRoot":"","sources":["../../../../src/commands/verify/cross/diff.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `loam verify <FEAT> --diff-answers a.json b.json` — the command surface of\n * the cross-examination lens.\n *\n * A third read form beside the report and frozen views: it takes no lock,\n * needs no service binding, and writes nothing. The payload deliberately\n * carries NO `verified`, `verdict` or `attested` key — their absence is the\n * doctrine made structural (`core/verify/cross/diff.ts` holds the\n * reasoning): this surface ranks review, it grades nothing.\n *\n * Both files validate through the same `checkAnswers` the record path uses,\n * against the same scoped checklist, with `runnerOwned` unset: under a diff\n * both agents answer everything in scope, `scenario.tested` included — that\n * is the attested channel, and this command records nothing. If a future\n * wave ever makes scenario claims runner-only even without `--results`,\n * blind agents can no longer answer them and this command starts refusing;\n * `checkAnswers`' own `runnerOwned` note carries the same warning where that\n * editor will see it.\n */\nimport { createHash } from \"node:crypto\";\nimport { readFile } from \"node:fs/promises\";\nimport { resolve } from \"node:path\";\nimport { emitJson, fail, repoPath } from \"../../../core/envelope/json.js\";\nimport { isRecord } from \"../../../core/kernel/records.js\";\nimport { answerEntries, checkAnswers, type Answer, type AnswerRefusal } from \"../../../core/verify/answers.js\";\nimport { type Checklist, type Claim } from \"../../../core/verify/checklist.js\";\nimport { crossExamine, disjointNotice, type CrossAnswer } from \"../../../core/verify/cross/diff.js\";\nimport { plural } from \"../../policy/format.js\";\nimport { type VerifyTarget } from \"../report.js\";\n\n/**\n * The two files, named for the order they were given: `a` is the first and\n * every refusal about it says \"first answer set\". One record rather than two\n * loose strings because they are never asked about separately, and because a\n * transposed pair is exactly the mistake a positional form invites.\n */\nexport interface AnswerFiles {\n a: string;\n b: string;\n}\n\ntype SideRead =\n | { ok: true; answers: Answer[]; digest: string }\n | { ok: false; code: AnswerRefusal; message: string };\n\n/**\n * Everything a side is validated against: the lens-scoped claims, the whole\n * checklist behind them (what the honest off-lens diagnosis is written from),\n * and the lens itself. One record because the three are never asked about\n * separately — a scoped array without its checklist is how the false \"not on\n * the checklist\" diagnosis happened.\n */\ninterface DiffScope {\n scoped: Claim[];\n checklist: Checklist;\n lens?: string;\n}\n\n/**\n * The honest half of a lens-narrowed mismatch. `checkAnswers` is handed only\n * the scoped claims, so an answer naming another service's claim — which IS\n * on the feature's checklist — would otherwise be called \"not on the\n * checklist\": the same false diagnosis `runnerOwned` exists to prevent on the\n * recording path. When the stray ids are real claims the lens filtered out,\n * say that, and say what the lens narrowed.\n */\nfunction offLensNote(scope: DiffScope, raw: unknown): string {\n if (scope.lens === undefined) return \"\";\n const entries = answerEntries(raw) ?? [];\n const scoped = new Set(scope.scoped.map((c) => c.id));\n const onChecklist = new Set(scope.checklist.claims.map((c) => c.id));\n const foreign = [\n ...new Set(\n entries\n .filter(isRecord)\n .map((entry) => entry[\"id\"])\n .filter((id): id is string => typeof id === \"string\" && onChecklist.has(id) && !scoped.has(id)),\n ),\n ];\n if (foreign.length === 0) return \"\";\n return (\n ` (${foreign.join(\", \")}: on the ${scope.checklist.feature} checklist but owned by another service — ` +\n `--service ${scope.lens} narrowed the comparison to ${scope.scoped.length} of ${scope.checklist.claims.length} claims)`\n );\n}\n\n/**\n * Read, digest and validate ONE answer set. Fail-closed on purpose at every\n * step: an unreadable or malformed file is a refusal naming which file and\n * why — never a silently empty side, which would grade as \"no disagreement\"\n * about claims nobody compared.\n */\nasync function readSide(scope: DiffScope, file: string, side: \"first\" | \"second\"): Promise<SideRead> {\n const label = `${side} answer set (${file})`;\n let bytes: Buffer;\n try {\n // cwd-relative deliberately — record.ts's reason for the same choice: the\n // answer sets are the caller's hand-offs, not repository artifacts, and\n // nothing on any record will ever point at them.\n bytes = await readFile(resolve(process.cwd(), file));\n } catch (err) {\n return {\n ok: false,\n code: \"answers-unreadable\",\n message: `${label}: cannot read: ${err instanceof Error ? err.message : String(err)}`,\n };\n }\n let raw: unknown;\n try {\n raw = JSON.parse(bytes.toString(\"utf8\"));\n } catch (err) {\n return {\n ok: false,\n code: \"answers-unreadable\",\n message: `${label}: not JSON: ${err instanceof Error ? err.message : String(err)}`,\n };\n }\n const context = { feature: scope.checklist.feature, ...(scope.lens === undefined ? {} : { service: scope.lens }) };\n const checked = checkAnswers(scope.scoped, raw, undefined, context);\n if (!checked.ok) {\n return { ok: false, code: checked.code, message: `${label}: ${checked.message}${offLensNote(scope, raw)}` };\n }\n // The digest is over the exact bytes read — the same reviewer-checkable\n // promise `reportLine` makes for consumed reports: `shasum -a 256 <file>`\n // answers whether the diff in hand read the file in hand.\n return { ok: true, answers: checked.answers, digest: createHash(\"sha256\").update(bytes).digest(\"hex\") };\n}\n\nfunction sideLine(answer: CrossAnswer): string {\n if (answer.verdict === \"confirmed\") return `confirmed (${answer.evidence.join(\", \")})`;\n return `unconfirmed${answer.note === undefined ? \"\" : ` — ${answer.note}`}`;\n}\n\nexport async function diffAnswers(\n target: VerifyTarget,\n checklist: Checklist,\n files: AnswerFiles,\n scope: { lens?: string },\n): Promise<void> {\n const { docsDir, featureDir, json } = target;\n const lens = scope.lens;\n // The same lens the read view applies (report.ts): the claims that\n // service's code answers, no repository binding asked for — a diff writes\n // nothing, so there is nothing to bind.\n const scoped = lens === undefined ? checklist.claims : checklist.claims.filter((c) => c.subject === lens);\n // record.ts's refusal, mirrored: a lens that owns nothing here is almost\n // always a typo'd service id, and validating two files against an empty\n // claim set would call every honest answer off-checklist instead of naming\n // the real mistake.\n if (lens !== undefined && scoped.length === 0) {\n return fail(\n json,\n \"unknown-service\",\n `The current ${checklist.feature} checklist has no claims owned by service '${lens}'.`,\n );\n }\n const diffScope: DiffScope = { scoped, checklist, ...(lens === undefined ? {} : { lens }) };\n\n // Sequential on purpose — a short-circuit, not a race: readSide never\n // rejects, but when the first file refuses, the second is never read or\n // parsed, so the refusal a caller sees always names the earliest problem\n // and no work is spent on a file whose sibling already failed the run.\n const a = await readSide(diffScope, files.a, \"first\");\n if (!a.ok) return fail(json, a.code, a.message);\n const b = await readSide(diffScope, files.b, \"second\");\n if (!b.ok) return fail(json, b.code, b.message);\n\n const cross = crossExamine(scoped, a.answers, b.answers);\n const notice = disjointNotice(cross.rows);\n\n if (json) {\n emitJson({\n command: \"verify\",\n feature: checklist.feature,\n path: repoPath(docsDir, featureDir),\n digest: checklist.digest,\n // Named only when narrowed — report.ts's rule: a consumer must never\n // mistake one service's cross-examination for the feature's.\n ...(lens === undefined ? {} : { service: lens, checklistClaims: checklist.claims.length }),\n files: {\n a: { path: files.a, digest: a.digest },\n b: { path: files.b, digest: b.digest },\n },\n summary: cross.summary,\n claims: cross.rows,\n disagreements: cross.disagreements,\n ...(notice === null ? {} : { notices: [notice] }),\n });\n return;\n }\n\n const scopeNote =\n lens === undefined ? \"\" : ` owned by ${lens} (of ${plural(checklist.claims.length, \"claim\")} on the checklist)`;\n console.log(\n `${checklist.feature} — cross-examination over ${plural(cross.rows.length, \"claim\")}${scopeNote} (${files.a} vs ${files.b})\\n`,\n );\n if (cross.rows.length === 0) {\n // Only the whole-checklist form can get here: a lens that owns nothing\n // refused `unknown-service` above.\n console.log(\" Nothing to cross-examine: this feature's delta, specs and openapi promise nothing yet.\");\n return;\n }\n for (const row of cross.rows) {\n if (row.code === \"cross.disagree\") {\n console.log(` ✗ cross.disagree ${row.id} [${row.subject}] ${row.claim}`);\n console.log(` a: ${sideLine(row.a)}`);\n console.log(` b: ${sideLine(row.b)}`);\n } else if (row.code === \"cross.agree-unconfirmed\") {\n console.log(` = ${row.id} [${row.subject}] ${row.claim} (both unconfirmed)`);\n } else {\n console.log(` = ${row.id} [${row.subject}] ${row.claim}${row.evidenceDisjoint === true ? \" (disjoint evidence)\" : \"\"}`);\n }\n }\n console.log(\"\");\n if (notice !== null) console.log(` ⚠ ${notice.code}: ${notice.message}`);\n console.log(\n ` ${cross.summary.agreeConfirmed} agree-confirmed, ${cross.summary.agreeUnconfirmed} agree-unconfirmed, ${cross.summary.disagree} disagree.`,\n );\n console.log(\"\\n Agreement is not verification — nothing was written and no verdict changed.\");\n console.log(\" Read the disagreements first, then the disjoint-evidence agreements.\");\n}\n"]}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * `--contract-results` consumed: the file read and pinned through the shared
3
+ * plumbing in `./read.ts`, then graded by the format reader in
4
+ * `core/verify/evidence/contract.ts`. Mirrors what `../results.ts` is for the
5
+ * cucumber report — the command-side half that touches the filesystem, kept
6
+ * apart from the core half that only ever judges a parsed document.
7
+ */
8
+ import { readContractReport } from "../../../core/verify/evidence/contract.js";
9
+ import {} from "../../../core/verify/record.js";
10
+ import { readReportArtifact } from "./read.js";
11
+ export async function readContractResults(spelled, repoDir) {
12
+ const artifact = await readReportArtifact(spelled, repoDir, "contract-test report", 'It reads loam\'s generic contract-results JSON — {"loamContractReport": 1, "results": [{"operationId": "…", "status": "passed"}]} — which any contract suite can be adapted into.');
13
+ if (!artifact.ok)
14
+ return artifact;
15
+ const parsed = readContractReport(artifact.doc, spelled);
16
+ if (!parsed.ok)
17
+ return { ok: false, code: "answers-unreadable", message: parsed.message };
18
+ return {
19
+ ok: true,
20
+ runs: parsed.runs,
21
+ report: {
22
+ path: artifact.spelled,
23
+ digest: artifact.digest,
24
+ mtime: artifact.mtime,
25
+ // Distinct operationIds, not entries: the pin says how much of an API
26
+ // the file speaks about, and a re-run is not a second operation.
27
+ operations: new Set(parsed.runs.map((r) => r.operationId)).size,
28
+ format: "generic",
29
+ },
30
+ };
31
+ }
32
+ //# sourceMappingURL=contract.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contract.js","sourceRoot":"","sources":["../../../../src/commands/verify/evidence/contract.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,kBAAkB,EAAoB,MAAM,2CAA2C,CAAC;AACjG,OAAO,EAA+B,MAAM,gCAAgC,CAAC;AAC7E,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAM/C,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,OAAe,EACf,OAA2B;IAE3B,MAAM,QAAQ,GAAG,MAAM,kBAAkB,CACvC,OAAO,EACP,OAAO,EACP,sBAAsB,EACtB,mLAAmL,CACpL,CAAC;IACF,IAAI,CAAC,QAAQ,CAAC,EAAE;QAAE,OAAO,QAAQ,CAAC;IAClC,MAAM,MAAM,GAAG,kBAAkB,CAAC,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IACzD,IAAI,CAAC,MAAM,CAAC,EAAE;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,oBAAoB,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC;IAC1F,OAAO;QACL,EAAE,EAAE,IAAI;QACR,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,MAAM,EAAE;YACN,IAAI,EAAE,QAAQ,CAAC,OAAO;YACtB,MAAM,EAAE,QAAQ,CAAC,MAAM;YACvB,KAAK,EAAE,QAAQ,CAAC,KAAK;YACrB,sEAAsE;YACtE,iEAAiE;YACjE,UAAU,EAAE,IAAI,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI;YAC/D,MAAM,EAAE,SAAS;SAClB;KACF,CAAC;AACJ,CAAC","sourcesContent":["/**\n * `--contract-results` consumed: the file read and pinned through the shared\n * plumbing in `./read.ts`, then graded by the format reader in\n * `core/verify/evidence/contract.ts`. Mirrors what `../results.ts` is for the\n * cucumber report — the command-side half that touches the filesystem, kept\n * apart from the core half that only ever judges a parsed document.\n */\nimport { readContractReport, type ContractRun } from \"../../../core/verify/evidence/contract.js\";\nimport { type ConsumedContractReport } from \"../../../core/verify/record.js\";\nimport { readReportArtifact } from \"./read.js\";\n\nexport type ContractResultsRead =\n | { ok: true; report: ConsumedContractReport; runs: ContractRun[] }\n | { ok: false; code: \"answers-unreadable\"; message: string };\n\nexport async function readContractResults(\n spelled: string,\n repoDir: string | undefined,\n): Promise<ContractResultsRead> {\n const artifact = await readReportArtifact(\n spelled,\n repoDir,\n \"contract-test report\",\n 'It reads loam\\'s generic contract-results JSON — {\"loamContractReport\": 1, \"results\": [{\"operationId\": \"…\", \"status\": \"passed\"}]} — which any contract suite can be adapted into.',\n );\n if (!artifact.ok) return artifact;\n const parsed = readContractReport(artifact.doc, spelled);\n if (!parsed.ok) return { ok: false, code: \"answers-unreadable\", message: parsed.message };\n return {\n ok: true,\n runs: parsed.runs,\n report: {\n path: artifact.spelled,\n digest: artifact.digest,\n mtime: artifact.mtime,\n // Distinct operationIds, not entries: the pin says how much of an API\n // the file speaks about, and a re-run is not a second operation.\n operations: new Set(parsed.runs.map((r) => r.operationId)).size,\n format: \"generic\",\n },\n };\n}\n"]}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * The record path's half of evidence pins: attaching what the evidence
3
+ * validation computed onto the answers being recorded, and saying — once,
4
+ * while the agent is still in the loop — when a cited blob does not contain
5
+ * the string its claim asserts.
6
+ *
7
+ * It lives in `evidence/` beside the report readers because it is the same
8
+ * subject (what a federated confirmation rests on), and because `record.ts`
9
+ * sits against the line limit: the notice's wording and the attach loop are a
10
+ * seam of their own, not lines seventeen-through-forty of the record flow.
11
+ */
12
+ import {} from "../../../core/verify/answers.js";
13
+ import {} from "../../../core/verify/checklist.js";
14
+ import {} from "../../../core/verify/pins/pin.js";
15
+ import {} from "../../../core/verify/record.js";
16
+ import { plural } from "../../policy/format.js";
17
+ /** Claim id → the literal the claim asserts, for the kinds that assert one. */
18
+ export function claimTokens(claims) {
19
+ return new Map(claims.flatMap((c) => (c.token === undefined ? [] : [[c.id, c.token]])));
20
+ }
21
+ /**
22
+ * Stamp the computed pins onto the answers they were computed from, and build
23
+ * the one record-time notice. The notice is verdict-neutral and gates nothing
24
+ * — verify has never gated — but it fires HERE rather than only at the next
25
+ * `loam validate` because record time is the anti-fabrication moment: the
26
+ * agent whose evidence does not spell the claim is still in the loop to
27
+ * re-read it. The validate-side `evidence.token-missing` finding describes the
28
+ * same fact later and continuously, in a different repository's run; neither
29
+ * surface is derivable from the other's.
30
+ */
31
+ export function pinAnswers(answers, evidence, commit) {
32
+ const pinned = answers.map((answer) => {
33
+ const pins = evidence.pins.get(answer.id);
34
+ return pins === undefined ? answer : { ...answer, evidence_pins: pins };
35
+ });
36
+ if (evidence.tokenMisses.length === 0)
37
+ return { answers: pinned, notice: null };
38
+ const cited = evidence.tokenMisses.map((m) => `${m.id} ${m.evidence} (token '${m.token}')`);
39
+ return {
40
+ answers: pinned,
41
+ notice: {
42
+ code: "verify.evidence-token-missing",
43
+ severity: "warn",
44
+ message: `${plural(evidence.tokenMisses.length, "confirmed citation")} whose file at ${commit.slice(0, 12)} does not contain ` +
45
+ `the literal string the claim asserts: ${cited.join("; ")}. ` +
46
+ "Read that evidence before trusting it — a pin records what was cited, not that the claim is true. " +
47
+ "The answer stands as given; nothing gates on this.",
48
+ claims: [...new Set(evidence.tokenMisses.map((m) => m.id))],
49
+ },
50
+ };
51
+ }
52
+ //# sourceMappingURL=pins.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pins.js","sourceRoot":"","sources":["../../../../src/commands/verify/evidence/pins.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAe,MAAM,iCAAiC,CAAC;AAC9D,OAAO,EAAc,MAAM,mCAAmC,CAAC;AAC/D,OAAO,EAAoB,MAAM,kCAAkC,CAAC;AACpE,OAAO,EAAqB,MAAM,gCAAgC,CAAC;AACnE,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAgBhD,+EAA+E;AAC/E,MAAM,UAAU,WAAW,CAAC,MAAwB;IAClD,OAAO,IAAI,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,CAAU,CAAC,CAAC,CAAC,CAAC,CAAC;AACnG,CAAC;AAeD;;;;;;;;;GASG;AACH,MAAM,UAAU,UAAU,CAAC,OAAiB,EAAE,QAAsB,EAAE,MAAc;IAClF,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE;QACpC,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAC1C,OAAO,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,MAAM,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;IAC1E,CAAC,CAAC,CAAC;IACH,IAAI,QAAQ,CAAC,WAAW,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IAChF,MAAM,KAAK,GAAG,QAAQ,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,QAAQ,YAAY,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC;IAC5F,OAAO;QACL,OAAO,EAAE,MAAM;QACf,MAAM,EAAE;YACN,IAAI,EAAE,+BAA+B;YACrC,QAAQ,EAAE,MAAM;YAChB,OAAO,EACL,GAAG,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC,MAAM,EAAE,oBAAoB,CAAC,kBAAkB,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,oBAAoB;gBACrH,yCAAyC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI;gBAC7D,oGAAoG;gBACpG,oDAAoD;YACtD,MAAM,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;SAC5D;KACF,CAAC;AACJ,CAAC","sourcesContent":["/**\n * The record path's half of evidence pins: attaching what the evidence\n * validation computed onto the answers being recorded, and saying — once,\n * while the agent is still in the loop — when a cited blob does not contain\n * the string its claim asserts.\n *\n * It lives in `evidence/` beside the report readers because it is the same\n * subject (what a federated confirmation rests on), and because `record.ts`\n * sits against the line limit: the notice's wording and the attach loop are a\n * seam of their own, not lines seventeen-through-forty of the record flow.\n */\nimport { type Answer } from \"../../../core/verify/answers.js\";\nimport { type Claim } from \"../../../core/verify/checklist.js\";\nimport { type EvidencePin } from \"../../../core/verify/pins/pin.js\";\nimport { type VerifyNotice } from \"../../../core/verify/record.js\";\nimport { plural } from \"../../policy/format.js\";\n\n/**\n * One citation whose committed blob does not contain the claim's token —\n * collected by `validateServiceEvidence` in the same pass that builds the pin,\n * where the blob is already in hand. The type lives here rather than in\n * `../results.ts` so this package never imports its parent back (the package\n * graph's acyclicity is a checked obligation, not a taste).\n */\nexport interface TokenMiss {\n id: string;\n /** The `path:line` citation whose blob was scanned. */\n evidence: string;\n token: string;\n}\n\n/** Claim id → the literal the claim asserts, for the kinds that assert one. */\nexport function claimTokens(claims: readonly Claim[]): ReadonlyMap<string, string> {\n return new Map(claims.flatMap((c) => (c.token === undefined ? [] : [[c.id, c.token] as const])));\n}\n\n/** The validation's pin and token-miss halves together — they come from one pass. */\nexport interface EvidencePins {\n /** Claim id → one pin per file:line citation, in evidence order. */\n pins: ReadonlyMap<string, EvidencePin[]>;\n tokenMisses: TokenMiss[];\n}\n\nexport interface PinnedAnswers {\n answers: Answer[];\n /** The record-time token warning, or null when every scanned blob held its token. */\n notice: VerifyNotice | null;\n}\n\n/**\n * Stamp the computed pins onto the answers they were computed from, and build\n * the one record-time notice. The notice is verdict-neutral and gates nothing\n * — verify has never gated — but it fires HERE rather than only at the next\n * `loam validate` because record time is the anti-fabrication moment: the\n * agent whose evidence does not spell the claim is still in the loop to\n * re-read it. The validate-side `evidence.token-missing` finding describes the\n * same fact later and continuously, in a different repository's run; neither\n * surface is derivable from the other's.\n */\nexport function pinAnswers(answers: Answer[], evidence: EvidencePins, commit: string): PinnedAnswers {\n const pinned = answers.map((answer) => {\n const pins = evidence.pins.get(answer.id);\n return pins === undefined ? answer : { ...answer, evidence_pins: pins };\n });\n if (evidence.tokenMisses.length === 0) return { answers: pinned, notice: null };\n const cited = evidence.tokenMisses.map((m) => `${m.id} ${m.evidence} (token '${m.token}')`);\n return {\n answers: pinned,\n notice: {\n code: \"verify.evidence-token-missing\",\n severity: \"warn\",\n message:\n `${plural(evidence.tokenMisses.length, \"confirmed citation\")} whose file at ${commit.slice(0, 12)} does not contain ` +\n `the literal string the claim asserts: ${cited.join(\"; \")}. ` +\n \"Read that evidence before trusting it — a pin records what was cited, not that the claim is true. \" +\n \"The answer stands as given; nothing gates on this.\",\n claims: [...new Set(evidence.tokenMisses.map((m) => m.id))],\n },\n };\n}\n"]}
@@ -0,0 +1,81 @@
1
+ /**
2
+ * A report file as an artifact: resolved, read, digested, parsed — the
3
+ * plumbing `--results` and `--contract-results` share, extracted from
4
+ * `../results.ts` when the contract path became its second consumer. One
5
+ * spelling on purpose: the two flags must agree byte-for-byte about what "the
6
+ * file loam read" means, because both pins end up on the same record making
7
+ * the same promise.
8
+ *
9
+ * `repoDir` is set in federated mode, and there the report must be a file
10
+ * INSIDE the repository being attested, resolved by the same rules as evidence
11
+ * (`portablePathOf` then `resolveInside`): an attestation says "at this
12
+ * commit, in this repository", and a report living somewhere else answers for
13
+ * a run nobody standing here can find. The legacy all-at-once form binds to no
14
+ * repository at all, so it takes the path as spelled — its looser contract,
15
+ * unchanged.
16
+ *
17
+ * Every refusal is `answers-unreadable` with the failing fact named — a path
18
+ * that is a directory arrives here as the read's own EISDIR, a file that is
19
+ * not UTF-8 is refused by name rather than parsed through U+FFFD substitution
20
+ * (JSON.parse's "unexpected token" over bytes nobody wrote is a message that
21
+ * sends the caller hunting a typo that is not there), and broken JSON carries
22
+ * the parser's message. Never `internal`: the file is the caller's, so the
23
+ * refusal must name the file.
24
+ */
25
+ import { isUtf8 } from "node:buffer";
26
+ import { createHash } from "node:crypto";
27
+ import { readFile, stat } from "node:fs/promises";
28
+ import { resolve } from "node:path";
29
+ import { resolvePortableFileInside } from "../../../core/kernel/path-safety.js";
30
+ /**
31
+ * `shapes` is the sentence naming what the flag accepts, appended when the file
32
+ * is not JSON at all. A JUnit XML report handed to `--results` used to die
33
+ * with the parser's own "Unexpected token '<' … is not valid JSON" — true, and
34
+ * no help to somebody whose runner speaks XML: the refusal has to say which
35
+ * shapes ARE read, because one of them exists precisely for that runner.
36
+ */
37
+ export async function readReportArtifact(spelled, repoDir, label, shapes) {
38
+ const refuse = (message) => ({ ok: false, code: "answers-unreadable", message });
39
+ let path;
40
+ if (repoDir === undefined) {
41
+ path = resolve(process.cwd(), spelled);
42
+ }
43
+ else {
44
+ try {
45
+ path = resolvePortableFileInside(repoDir, spelled, label);
46
+ }
47
+ catch (err) {
48
+ return refuse(`Cannot answer from ${spelled}: ${err instanceof Error ? err.message : String(err)}. ` +
49
+ "A federated attestation rests on a report inside the repository it attests — give the path relative to the repo root.");
50
+ }
51
+ }
52
+ let bytes;
53
+ let mtime;
54
+ try {
55
+ bytes = await readFile(path);
56
+ mtime = (await stat(path)).mtime;
57
+ }
58
+ catch (err) {
59
+ return refuse(`Cannot read ${spelled} as a ${label}: ${err instanceof Error ? err.message : String(err)}`);
60
+ }
61
+ if (!isUtf8(bytes)) {
62
+ return refuse(`Cannot read ${spelled} as a ${label}: the file is not valid UTF-8`);
63
+ }
64
+ let doc;
65
+ const text = bytes.toString("utf8");
66
+ try {
67
+ doc = JSON.parse(text);
68
+ }
69
+ catch (err) {
70
+ const what = text.trimStart().startsWith("<") ? "it is XML (a JUnit report?), not JSON" : "it is not JSON";
71
+ return refuse(`Cannot read ${spelled} as a ${label}: ${what} (${err instanceof Error ? err.message : String(err)}). ${shapes}`);
72
+ }
73
+ return {
74
+ ok: true,
75
+ spelled,
76
+ digest: createHash("sha256").update(bytes).digest("hex"),
77
+ mtime: mtime.toISOString(),
78
+ doc,
79
+ };
80
+ }
81
+ //# sourceMappingURL=read.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read.js","sourceRoot":"","sources":["../../../../src/commands/verify/evidence/read.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * A report file as an artifact: resolved, read, digested, parsed — the\n * plumbing `--results` and `--contract-results` share, extracted from\n * `../results.ts` when the contract path became its second consumer. One\n * spelling on purpose: the two flags must agree byte-for-byte about what \"the\n * file loam read\" means, because both pins end up on the same record making\n * the same promise.\n *\n * `repoDir` is set in federated mode, and there the report must be a file\n * INSIDE the repository being attested, resolved by the same rules as evidence\n * (`portablePathOf` then `resolveInside`): an attestation says \"at this\n * commit, in this repository\", and a report living somewhere else answers for\n * a run nobody standing here can find. The legacy all-at-once form binds to no\n * repository at all, so it takes the path as spelled — its looser contract,\n * unchanged.\n *\n * Every refusal is `answers-unreadable` with the failing fact named — a path\n * that is a directory arrives here as the read's own EISDIR, a file that is\n * not UTF-8 is refused by name rather than parsed through U+FFFD substitution\n * (JSON.parse's \"unexpected token\" over bytes nobody wrote is a message that\n * sends the caller hunting a typo that is not there), and broken JSON carries\n * the parser's message. Never `internal`: the file is the caller's, so the\n * refusal must name the file.\n */\nimport { isUtf8 } from \"node:buffer\";\nimport { createHash } from \"node:crypto\";\nimport { readFile, stat } from \"node:fs/promises\";\nimport { resolve } from \"node:path\";\nimport { resolvePortableFileInside } from \"../../../core/kernel/path-safety.js\";\n\nexport type ReportArtifactRead =\n | {\n ok: true;\n /** The path as the caller spelled it — what goes on the record. */\n spelled: string;\n /** Full sha256 of the exact bytes read. */\n digest: string;\n /** ISO-8601 mtime of the report file. */\n mtime: string;\n /** The parsed JSON document, for the format reader to grade. */\n doc: unknown;\n }\n | { ok: false; code: \"answers-unreadable\"; message: string };\n\n/**\n * `shapes` is the sentence naming what the flag accepts, appended when the file\n * is not JSON at all. A JUnit XML report handed to `--results` used to die\n * with the parser's own \"Unexpected token '<' … is not valid JSON\" — true, and\n * no help to somebody whose runner speaks XML: the refusal has to say which\n * shapes ARE read, because one of them exists precisely for that runner.\n */\nexport async function readReportArtifact(\n spelled: string,\n repoDir: string | undefined,\n label: string,\n shapes: string,\n): Promise<ReportArtifactRead> {\n const refuse = (message: string): ReportArtifactRead => ({ ok: false, code: \"answers-unreadable\", message });\n let path: string;\n if (repoDir === undefined) {\n path = resolve(process.cwd(), spelled);\n } else {\n try {\n path = resolvePortableFileInside(repoDir, spelled, label);\n } catch (err) {\n return refuse(\n `Cannot answer from ${spelled}: ${err instanceof Error ? err.message : String(err)}. ` +\n \"A federated attestation rests on a report inside the repository it attests — give the path relative to the repo root.\",\n );\n }\n }\n\n let bytes: Buffer;\n let mtime: Date;\n try {\n bytes = await readFile(path);\n mtime = (await stat(path)).mtime;\n } catch (err) {\n return refuse(`Cannot read ${spelled} as a ${label}: ${err instanceof Error ? err.message : String(err)}`);\n }\n if (!isUtf8(bytes)) {\n return refuse(`Cannot read ${spelled} as a ${label}: the file is not valid UTF-8`);\n }\n let doc: unknown;\n const text = bytes.toString(\"utf8\");\n try {\n doc = JSON.parse(text);\n } catch (err) {\n const what = text.trimStart().startsWith(\"<\") ? \"it is XML (a JUnit report?), not JSON\" : \"it is not JSON\";\n return refuse(\n `Cannot read ${spelled} as a ${label}: ${what} (${err instanceof Error ? err.message : String(err)}). ${shapes}`,\n );\n }\n return {\n ok: true,\n spelled,\n digest: createHash(\"sha256\").update(bytes).digest(\"hex\"),\n mtime: mtime.toISOString(),\n doc,\n };\n}\n"]}
@@ -0,0 +1,263 @@
1
+ /**
2
+ * An archived feature's record, read back and never recomputed.
3
+ *
4
+ * A frozen record is history: the checklist it answered no longer exists in
5
+ * `features/`, so there is nothing to re-derive it from and re-deriving it would
6
+ * be an opinion about a feature nobody can change. Everything here reads the
7
+ * recorded claims, which is also why the shared marks (`answeredMark`), the
8
+ * contested-claim notices and the report-pin lines live beside it: the read
9
+ * and record views print the same facts about the same claims, in one voice.
10
+ */
11
+ import { emitJson, repoPath } from "../../core/envelope/json.js";
12
+ import { contestedDigests } from "../../core/results.js";
13
+ import {} from "../../core/verify/checklist.js";
14
+ import { contestedOperations } from "../../core/verify/evidence/contract.js";
15
+ import { attestedNotice, openClaimsNotice, tallyRecord, verificationVerdict, } from "../../core/verify/record.js";
16
+ import { recordLocation } from "../../core/verify/location.js";
17
+ import { plural } from "../policy/format.js";
18
+ import {} from "./report.js";
19
+ /**
20
+ * The frozen view: an archived feature's record, verbatim. No checklist is
21
+ * derived and no staleness is judged — there is nothing current to judge
22
+ * against, and pretending otherwise is how a true record reads as a lie.
23
+ * `frozen` is the marker a consumer branches on.
24
+ *
25
+ * The verdict is recounted from `claims[]`, never taken from `summary`: this is
26
+ * the post-ship verdict on a feature nobody can re-derive a checklist for, so a
27
+ * record whose counts had drifted from its own answers reported a shipped
28
+ * feature as fully confirmed. (A record that contradicts itself never reaches
29
+ * here — `readVerificationState` refuses it — so the recount and the summary
30
+ * agree; the recount is what says WHY.) No record at all is reported as exactly
31
+ * that, with `summary: null`, not zero claims, which would falsely say the
32
+ * feature promised nothing.
33
+ */
34
+ export function reportFrozen(target, featureId, v) {
35
+ const { docsDir, featureDir, json } = target;
36
+ const tally = v === null ? null : tallyRecord(v);
37
+ const verdict = tally === null ? "unverified" : verificationVerdict(tally);
38
+ // The open-claims line rides into the frozen view too: a feature archived on
39
+ // a partial record must keep saying so after it ships, not only before. No
40
+ // record stays bare — the prose already says nothing was recorded.
41
+ const open = tally === null ? null : openClaimsNotice(tally, featureId);
42
+ const notices = [...(v === null ? [] : noticesFor(v.claims, featureId)), ...(open === null ? [] : [open])];
43
+ if (json) {
44
+ emitJson({
45
+ command: "verify",
46
+ feature: featureId,
47
+ path: repoPath(docsDir, featureDir),
48
+ frozen: true,
49
+ verified: verdict === "verified",
50
+ verdict,
51
+ attested: tally?.attested ?? 0,
52
+ summary: v === null ? null : v.summary,
53
+ recorded: v === null ? null : recordedPayload(target, v),
54
+ claims: v === null ? [] : v.claims,
55
+ ...(notices.length === 0 ? {} : { notices }),
56
+ });
57
+ return;
58
+ }
59
+ if (v === null) {
60
+ console.log(`${featureId} is archived and has no verification record — nothing was recorded before it shipped.`);
61
+ return;
62
+ }
63
+ console.log(`${featureId} — verification recorded ${v.recorded}, frozen at archive (${repoPath(docsDir, featureDir)})\n`);
64
+ for (const c of v.claims) {
65
+ // `subject` is absent in records written before schema 2 — an old record
66
+ // must read as itself, not gain a service it never named.
67
+ const subject = c.subject === undefined ? "" : ` [${c.subject}]`;
68
+ console.log(` ${MARK[c.verdict]} ${c.id}${subject} ${c.claim}${answeredMark(c)}`);
69
+ for (const e of c.evidence)
70
+ console.log(` ${e}`);
71
+ if (c.note !== undefined)
72
+ console.log(` note: ${c.note}`);
73
+ }
74
+ const counts = tallyRecord(v);
75
+ console.log(`\n Recorded ${v.recorded} — ${counts.confirmed} confirmed, ${counts.unconfirmed} unconfirmed.`);
76
+ console.log(" This checklist is frozen at record time: the feature is archived and its claims are not re-derived.");
77
+ for (const attestation of v.attestations ?? []) {
78
+ console.log(` Attested by ${attestation.service} at ${attestation.commit.slice(0, 12)} (${attestation.recorded}).`);
79
+ if (attestation.report !== undefined)
80
+ console.log(` from ${reportLine(attestation.report)}`);
81
+ if (attestation.contractReport !== undefined) {
82
+ console.log(` from ${contractReportLine(attestation.contractReport)}`);
83
+ }
84
+ }
85
+ if (v.report !== undefined)
86
+ console.log(` Answered from ${reportLine(v.report)}.`);
87
+ if (v.contractReport !== undefined)
88
+ console.log(` Contract report read: ${contractReportLine(v.contractReport)}.`);
89
+ for (const notice of notices)
90
+ console.log(` ⚠ ${notice.code}: ${notice.message}`);
91
+ }
92
+ export const MARK = { confirmed: "✓", unconfirmed: "✗", unanswered: "?" };
93
+ /**
94
+ * The `recorded` block both views emit: where the record is, when it was
95
+ * written, which checklist it answered, and the evidence provenance it carries.
96
+ * `extra` lands right after `checklist` — the read view's `stale` — so each
97
+ * payload keeps the key order it has always had.
98
+ */
99
+ export function recordedPayload(target, v, extra = {}) {
100
+ return {
101
+ path: repoPath(target.docsDir, recordLocation(target.featureDir)),
102
+ recorded: v.recorded,
103
+ checklist: v.checklist,
104
+ ...extra,
105
+ ...(v.attestations === undefined ? {} : { attestations: v.attestations }),
106
+ ...(v.report === undefined ? {} : { report: v.report }),
107
+ ...(v.contractReport === undefined ? {} : { contractReport: v.contractReport }),
108
+ };
109
+ }
110
+ /**
111
+ * Who answered, where that changes what the verdict means. `[runner]` is a
112
+ * digest-matched green run; `[contract]` is an operationId-matched green
113
+ * contract-test run — mechanical too, and marked so the record's provenance is
114
+ * readable per line, not only in `contractReport:`; `[attested]` is a scenario
115
+ * claim confirmed on somebody's word — the same ✓, a weaker fact, and it must
116
+ * be visible on the line itself and not only in the summary. The attested test
117
+ * runs FIRST and uses `attestedClaims`' own predicate (a confirmed scenario
118
+ * claim not answered by the runner), so the mark can never disagree with the
119
+ * tally: a scenario claim carrying `answered_by: external-runner` — a hand
120
+ * edit, or a future loam; the reader accepts any string on purpose — COUNTS as
121
+ * attested, and printing `[contract]` two lines above a notice saying "an
122
+ * agent's word" would be the mark calling the tally a liar. Everything else is
123
+ * unmarked: an agent's answer about a service existing or an operation being
124
+ * exposed is exactly what the checklist asks for.
125
+ */
126
+ export function answeredMark(c) {
127
+ if (c.answered_by === "runner")
128
+ return " [runner]";
129
+ if (c.kind === "scenario.tested") {
130
+ return c.verdict === "confirmed" ? " [attested]" : "";
131
+ }
132
+ return c.answered_by === "external-runner" ? " [contract]" : "";
133
+ }
134
+ /** Everything a verify surface has to say about a set of answers beyond the counts. */
135
+ export function noticesFor(claims, feature) {
136
+ const attested = attestedNotice(claims, feature);
137
+ return attested === null ? [] : [attested];
138
+ }
139
+ /**
140
+ * `verify.checklist-forked` — two services answered DIFFERENT versions of this
141
+ * feature{@link ServiceAttestation}'s question set.
142
+ *
143
+ * The record carries one top-level `checklist` digest, so before attestations
144
+ * carried their own the file could not represent this at all: a service that
145
+ * attested last week against a delta since rewritten wrote the same digest as
146
+ * one that attested this morning, and the record-level staleness check flagged
147
+ * both or neither. It could never say WHICH answers went stale, which is the
148
+ * only question a reader has.
149
+ *
150
+ * A warn, and only ever a warn: a fork is normal mid-rollout — services attest
151
+ * as they finish, and a feature legitimately changes between the first and the
152
+ * last. What it must not do is stay invisible. Attestations with no `checklist`
153
+ * field are excluded rather than counted as a third version: they make no claim
154
+ * about what they answered, and reading silence as disagreement would fire this
155
+ * on every record written before the field existed.
156
+ *
157
+ * In a record kept as per-service files the fork also decides what counts:
158
+ * the union counts only the files that answered its newest version
159
+ * (`core/verify/read/union.ts` says why), so the services named here are the
160
+ * ones whose answers are left out until they record again. In a one-file
161
+ * record the last writer had already pruned their stale answers, and the rest
162
+ * still count — which is why the sentence below says only what is true of
163
+ * both.
164
+ */
165
+ export function forkedChecklistNotices(recorded, current) {
166
+ const stated = (recorded?.attestations ?? []).filter((a) => a.checklist !== undefined);
167
+ // Measured against the CURRENT checklist, not pairwise between attestations.
168
+ // The pairwise reading answers the wrong question: three services that all
169
+ // attested against a since-rewritten delta agree with each other perfectly
170
+ // and are all stale, which pairwise calls clean. What a reader needs is
171
+ // WHICH services answered something other than what is being asked now.
172
+ const behind = stated.filter((a) => a.checklist !== current);
173
+ if (behind.length === 0)
174
+ return [];
175
+ const byVersion = [...new Set(behind.map((a) => a.checklist))]
176
+ .sort()
177
+ .map((v) => `${v} (${behind.filter((a) => a.checklist === v).map((a) => a.service).sort().join(", ")})`);
178
+ return [
179
+ {
180
+ code: "verify.checklist-forked",
181
+ severity: "warn",
182
+ message: `${plural(behind.length, "service")} answered a different version of this feature's question set ` +
183
+ `than the one it now asks (${current}): ${byVersion.join("; ")}. ` +
184
+ "The feature changed after they recorded, so their answers are not about the questions being asked now. " +
185
+ "Re-record them from their own repositories (`loam verify <FEAT> --service <id> --record`) — " +
186
+ "nothing gates on it, but until they do, the record does not answer what the feature asks.",
187
+ },
188
+ ];
189
+ }
190
+ /**
191
+ * The claims one report could not attribute: a scenario digest — and therefore
192
+ * an `@loam-digest-…` tag — that more than one service claims.
193
+ *
194
+ * This is now a GUARD rather than a diagnosis of ordinary authoring. Until the
195
+ * digest was salted by service, two services wording a scenario identically
196
+ * really did share one tag, and this is what stopped one repository's green run
197
+ * from confirming the other's claim. `scenarioBodyHash` folds the owning
198
+ * service into the hash, so a claim's digest is computed from the same service
199
+ * the claim is filed under and two subjects cannot share one short of a
200
+ * truncated-sha256 collision. It stays because the invariant is worth asserting
201
+ * where it is relied on: if this ever fires, a digest is answering for two
202
+ * services and no report can say which, so nothing here may confirm.
203
+ *
204
+ * Derived from claims rather than from a report, so the read view raises it too
205
+ * — the collision exists the moment the checklist does, and learning about it
206
+ * from a `--results` run that already happened is learning too late.
207
+ */
208
+ export function contestedNotices(claims) {
209
+ const contested = contestedDigests(claims);
210
+ if (contested.size === 0)
211
+ return [];
212
+ const shared = [...contested].map(([digest, services]) => `${digest} (${services.join(", ")})`);
213
+ return [
214
+ {
215
+ code: "verify.digest-contested",
216
+ severity: "warn",
217
+ message: `${plural(contested.size, "scenario digest")} claimed by more than one service: ${shared.join("; ")}. ` +
218
+ "The digest is salted by service, so this is a hash collision, not shared wording — but one report still " +
219
+ "cannot say whose suite ran them, so a shared --results run leaves them unconfirmed. " +
220
+ "Record each service's claims from its own repository with --service.",
221
+ claims: claims.filter((c) => c.digest !== undefined && contested.has(c.digest)).map((c) => c.id),
222
+ },
223
+ ];
224
+ }
225
+ /**
226
+ * The digest-contested rule's twin on the contract axis: operationIds that
227
+ * more than one service on this checklist exposes, which one report can
228
+ * therefore never attribute (`contestedOperations`, the module that also
229
+ * leaves those claims unconfirmed). Raised where the contract report is
230
+ * consumed, so the record path says WHY the claims came back unconfirmed
231
+ * instead of leaving two bare ✗ lines to be misread as failures.
232
+ */
233
+ export function contestedOperationNotices(claims) {
234
+ const contested = contestedOperations(claims);
235
+ if (contested.size === 0)
236
+ return [];
237
+ const shared = [...contested].map(([operation, services]) => `${operation} (${services.join(", ")})`);
238
+ return [
239
+ {
240
+ code: "verify.operation-contested",
241
+ severity: "warn",
242
+ message: `${plural(contested.size, "operationId")} exposed by more than one service on this checklist: ${shared.join("; ")}. ` +
243
+ "A contract report entry names no service, so a shared --contract-results run cannot say whose suite exercised them and leaves them unconfirmed. " +
244
+ "Record each service's claims from its own repository with --service.",
245
+ claims: claims.filter((c) => c.operation !== undefined && contested.has(c.operation)).map((c) => c.id),
246
+ },
247
+ ];
248
+ }
249
+ /** The report a `--results` run consumed, as one line a reviewer can check by hand. */
250
+ export function reportLine(r) {
251
+ return `${r.path} (sha256 ${r.digest.slice(0, 12)}…, ${plural(r.scenarios, "tagged scenario")}, written ${r.mtime})`;
252
+ }
253
+ /**
254
+ * The contract report a `--contract-results` run consumed — the same line for
255
+ * the same promise, counting operations where the cucumber one counts tagged
256
+ * scenarios. A separate function rather than a parameter on `reportLine`
257
+ * because the two pins are different shapes, and a merged formatter would need
258
+ * exactly the switching flag that near-duplicates are kept apart to avoid.
259
+ */
260
+ export function contractReportLine(r) {
261
+ return `${r.path} (sha256 ${r.digest.slice(0, 12)}…, ${plural(r.operations, "operation")}, written ${r.mtime})`;
262
+ }
263
+ //# sourceMappingURL=frozen.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frozen.js","sourceRoot":"","sources":["../../../src/commands/verify/frozen.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * An archived feature's record, read back and never recomputed.\n *\n * A frozen record is history: the checklist it answered no longer exists in\n * `features/`, so there is nothing to re-derive it from and re-deriving it would\n * be an opinion about a feature nobody can change. Everything here reads the\n * recorded claims, which is also why the shared marks (`answeredMark`), the\n * contested-claim notices and the report-pin lines live beside it: the read\n * and record views print the same facts about the same claims, in one voice.\n */\nimport { emitJson, repoPath } from \"../../core/envelope/json.js\";\nimport { contestedDigests } from \"../../core/results.js\";\nimport { type Claim } from \"../../core/verify/checklist.js\";\nimport { contestedOperations } from \"../../core/verify/evidence/contract.js\";\nimport {\n attestedNotice,\n openClaimsNotice,\n tallyRecord,\n type AnsweredClaim,\n type ConsumedContractReport,\n type ConsumedReport,\n type Verification,\n type VerifyNotice,\n verificationVerdict,\n} from \"../../core/verify/record.js\";\nimport { recordLocation } from \"../../core/verify/location.js\";\nimport { plural } from \"../policy/format.js\";\nimport { type VerifyTarget } from \"./report.js\";\n\n/**\n * The frozen view: an archived feature's record, verbatim. No checklist is\n * derived and no staleness is judged — there is nothing current to judge\n * against, and pretending otherwise is how a true record reads as a lie.\n * `frozen` is the marker a consumer branches on.\n *\n * The verdict is recounted from `claims[]`, never taken from `summary`: this is\n * the post-ship verdict on a feature nobody can re-derive a checklist for, so a\n * record whose counts had drifted from its own answers reported a shipped\n * feature as fully confirmed. (A record that contradicts itself never reaches\n * here — `readVerificationState` refuses it — so the recount and the summary\n * agree; the recount is what says WHY.) No record at all is reported as exactly\n * that, with `summary: null`, not zero claims, which would falsely say the\n * feature promised nothing.\n */\nexport function reportFrozen(\n target: VerifyTarget,\n featureId: string,\n v: Verification | null,\n): void {\n const { docsDir, featureDir, json } = target;\n const tally = v === null ? null : tallyRecord(v);\n const verdict = tally === null ? \"unverified\" : verificationVerdict(tally);\n // The open-claims line rides into the frozen view too: a feature archived on\n // a partial record must keep saying so after it ships, not only before. No\n // record stays bare — the prose already says nothing was recorded.\n const open = tally === null ? null : openClaimsNotice(tally, featureId);\n const notices = [...(v === null ? [] : noticesFor(v.claims, featureId)), ...(open === null ? [] : [open])];\n\n if (json) {\n emitJson({\n command: \"verify\",\n feature: featureId,\n path: repoPath(docsDir, featureDir),\n frozen: true,\n verified: verdict === \"verified\",\n verdict,\n attested: tally?.attested ?? 0,\n summary: v === null ? null : v.summary,\n recorded: v === null ? null : recordedPayload(target, v),\n claims: v === null ? [] : v.claims,\n ...(notices.length === 0 ? {} : { notices }),\n });\n return;\n }\n\n if (v === null) {\n console.log(\n `${featureId} is archived and has no verification record — nothing was recorded before it shipped.`,\n );\n return;\n }\n\n console.log(\n `${featureId} — verification recorded ${v.recorded}, frozen at archive (${repoPath(docsDir, featureDir)})\\n`,\n );\n for (const c of v.claims) {\n // `subject` is absent in records written before schema 2 — an old record\n // must read as itself, not gain a service it never named.\n const subject = c.subject === undefined ? \"\" : ` [${c.subject}]`;\n console.log(` ${MARK[c.verdict]} ${c.id}${subject} ${c.claim}${answeredMark(c)}`);\n for (const e of c.evidence) console.log(` ${e}`);\n if (c.note !== undefined) console.log(` note: ${c.note}`);\n }\n const counts = tallyRecord(v);\n console.log(`\\n Recorded ${v.recorded} — ${counts.confirmed} confirmed, ${counts.unconfirmed} unconfirmed.`);\n console.log(\n \" This checklist is frozen at record time: the feature is archived and its claims are not re-derived.\",\n );\n for (const attestation of v.attestations ?? []) {\n console.log(\n ` Attested by ${attestation.service} at ${attestation.commit.slice(0, 12)} (${attestation.recorded}).`,\n );\n if (attestation.report !== undefined) console.log(` from ${reportLine(attestation.report)}`);\n if (attestation.contractReport !== undefined) {\n console.log(` from ${contractReportLine(attestation.contractReport)}`);\n }\n }\n if (v.report !== undefined) console.log(` Answered from ${reportLine(v.report)}.`);\n if (v.contractReport !== undefined) console.log(` Contract report read: ${contractReportLine(v.contractReport)}.`);\n for (const notice of notices) console.log(` ⚠ ${notice.code}: ${notice.message}`);\n}\n\nexport const MARK: Record<string, string> = { confirmed: \"✓\", unconfirmed: \"✗\", unanswered: \"?\" };\n\n/**\n * The `recorded` block both views emit: where the record is, when it was\n * written, which checklist it answered, and the evidence provenance it carries.\n * `extra` lands right after `checklist` — the read view's `stale` — so each\n * payload keeps the key order it has always had.\n */\nexport function recordedPayload(\n target: VerifyTarget,\n v: Verification,\n extra: { stale?: boolean } = {},\n): Record<string, unknown> {\n return {\n path: repoPath(target.docsDir, recordLocation(target.featureDir)),\n recorded: v.recorded,\n checklist: v.checklist,\n ...extra,\n ...(v.attestations === undefined ? {} : { attestations: v.attestations }),\n ...(v.report === undefined ? {} : { report: v.report }),\n ...(v.contractReport === undefined ? {} : { contractReport: v.contractReport }),\n };\n}\n\n/**\n * Who answered, where that changes what the verdict means. `[runner]` is a\n * digest-matched green run; `[contract]` is an operationId-matched green\n * contract-test run — mechanical too, and marked so the record's provenance is\n * readable per line, not only in `contractReport:`; `[attested]` is a scenario\n * claim confirmed on somebody's word — the same ✓, a weaker fact, and it must\n * be visible on the line itself and not only in the summary. The attested test\n * runs FIRST and uses `attestedClaims`' own predicate (a confirmed scenario\n * claim not answered by the runner), so the mark can never disagree with the\n * tally: a scenario claim carrying `answered_by: external-runner` — a hand\n * edit, or a future loam; the reader accepts any string on purpose — COUNTS as\n * attested, and printing `[contract]` two lines above a notice saying \"an\n * agent's word\" would be the mark calling the tally a liar. Everything else is\n * unmarked: an agent's answer about a service existing or an operation being\n * exposed is exactly what the checklist asks for.\n */\nexport function answeredMark(c: AnsweredClaim): string {\n if (c.answered_by === \"runner\") return \" [runner]\";\n if (c.kind === \"scenario.tested\") {\n return c.verdict === \"confirmed\" ? \" [attested]\" : \"\";\n }\n return c.answered_by === \"external-runner\" ? \" [contract]\" : \"\";\n}\n\n/** Everything a verify surface has to say about a set of answers beyond the counts. */\nexport function noticesFor(claims: readonly AnsweredClaim[], feature: string): VerifyNotice[] {\n const attested = attestedNotice(claims, feature);\n return attested === null ? [] : [attested];\n}\n\n/**\n * `verify.checklist-forked` — two services answered DIFFERENT versions of this\n * feature{@link ServiceAttestation}'s question set.\n *\n * The record carries one top-level `checklist` digest, so before attestations\n * carried their own the file could not represent this at all: a service that\n * attested last week against a delta since rewritten wrote the same digest as\n * one that attested this morning, and the record-level staleness check flagged\n * both or neither. It could never say WHICH answers went stale, which is the\n * only question a reader has.\n *\n * A warn, and only ever a warn: a fork is normal mid-rollout — services attest\n * as they finish, and a feature legitimately changes between the first and the\n * last. What it must not do is stay invisible. Attestations with no `checklist`\n * field are excluded rather than counted as a third version: they make no claim\n * about what they answered, and reading silence as disagreement would fire this\n * on every record written before the field existed.\n *\n * In a record kept as per-service files the fork also decides what counts:\n * the union counts only the files that answered its newest version\n * (`core/verify/read/union.ts` says why), so the services named here are the\n * ones whose answers are left out until they record again. In a one-file\n * record the last writer had already pruned their stale answers, and the rest\n * still count — which is why the sentence below says only what is true of\n * both.\n */\nexport function forkedChecklistNotices(\n recorded: Verification | null,\n current: string,\n): VerifyNotice[] {\n const stated = (recorded?.attestations ?? []).filter((a) => a.checklist !== undefined);\n // Measured against the CURRENT checklist, not pairwise between attestations.\n // The pairwise reading answers the wrong question: three services that all\n // attested against a since-rewritten delta agree with each other perfectly\n // and are all stale, which pairwise calls clean. What a reader needs is\n // WHICH services answered something other than what is being asked now.\n const behind = stated.filter((a) => a.checklist !== current);\n if (behind.length === 0) return [];\n const byVersion = [...new Set(behind.map((a) => a.checklist!))]\n .sort()\n .map((v) => `${v} (${behind.filter((a) => a.checklist === v).map((a) => a.service).sort().join(\", \")})`);\n return [\n {\n code: \"verify.checklist-forked\",\n severity: \"warn\",\n message:\n `${plural(behind.length, \"service\")} answered a different version of this feature's question set ` +\n `than the one it now asks (${current}): ${byVersion.join(\"; \")}. ` +\n \"The feature changed after they recorded, so their answers are not about the questions being asked now. \" +\n \"Re-record them from their own repositories (`loam verify <FEAT> --service <id> --record`) — \" +\n \"nothing gates on it, but until they do, the record does not answer what the feature asks.\",\n },\n ];\n}\n\n/**\n * The claims one report could not attribute: a scenario digest — and therefore\n * an `@loam-digest-…` tag — that more than one service claims.\n *\n * This is now a GUARD rather than a diagnosis of ordinary authoring. Until the\n * digest was salted by service, two services wording a scenario identically\n * really did share one tag, and this is what stopped one repository's green run\n * from confirming the other's claim. `scenarioBodyHash` folds the owning\n * service into the hash, so a claim's digest is computed from the same service\n * the claim is filed under and two subjects cannot share one short of a\n * truncated-sha256 collision. It stays because the invariant is worth asserting\n * where it is relied on: if this ever fires, a digest is answering for two\n * services and no report can say which, so nothing here may confirm.\n *\n * Derived from claims rather than from a report, so the read view raises it too\n * — the collision exists the moment the checklist does, and learning about it\n * from a `--results` run that already happened is learning too late.\n */\nexport function contestedNotices(claims: readonly Claim[]): VerifyNotice[] {\n const contested = contestedDigests(claims);\n if (contested.size === 0) return [];\n const shared = [...contested].map(([digest, services]) => `${digest} (${services.join(\", \")})`);\n return [\n {\n code: \"verify.digest-contested\",\n severity: \"warn\",\n message:\n `${plural(contested.size, \"scenario digest\")} claimed by more than one service: ${shared.join(\"; \")}. ` +\n \"The digest is salted by service, so this is a hash collision, not shared wording — but one report still \" +\n \"cannot say whose suite ran them, so a shared --results run leaves them unconfirmed. \" +\n \"Record each service's claims from its own repository with --service.\",\n claims: claims.filter((c) => c.digest !== undefined && contested.has(c.digest)).map((c) => c.id),\n },\n ];\n}\n\n/**\n * The digest-contested rule's twin on the contract axis: operationIds that\n * more than one service on this checklist exposes, which one report can\n * therefore never attribute (`contestedOperations`, the module that also\n * leaves those claims unconfirmed). Raised where the contract report is\n * consumed, so the record path says WHY the claims came back unconfirmed\n * instead of leaving two bare ✗ lines to be misread as failures.\n */\nexport function contestedOperationNotices(claims: readonly Claim[]): VerifyNotice[] {\n const contested = contestedOperations(claims);\n if (contested.size === 0) return [];\n const shared = [...contested].map(([operation, services]) => `${operation} (${services.join(\", \")})`);\n return [\n {\n code: \"verify.operation-contested\",\n severity: \"warn\",\n message:\n `${plural(contested.size, \"operationId\")} exposed by more than one service on this checklist: ${shared.join(\"; \")}. ` +\n \"A contract report entry names no service, so a shared --contract-results run cannot say whose suite exercised them and leaves them unconfirmed. \" +\n \"Record each service's claims from its own repository with --service.\",\n claims: claims.filter((c) => c.operation !== undefined && contested.has(c.operation)).map((c) => c.id),\n },\n ];\n}\n\n/** The report a `--results` run consumed, as one line a reviewer can check by hand. */\nexport function reportLine(r: ConsumedReport): string {\n return `${r.path} (sha256 ${r.digest.slice(0, 12)}…, ${plural(r.scenarios, \"tagged scenario\")}, written ${r.mtime})`;\n}\n\n/**\n * The contract report a `--contract-results` run consumed — the same line for\n * the same promise, counting operations where the cucumber one counts tagged\n * scenarios. A separate function rather than a parameter on `reportLine`\n * because the two pins are different shapes, and a merged formatter would need\n * exactly the switching flag that near-duplicates are kept apart to avoid.\n */\nexport function contractReportLine(r: ConsumedContractReport): string {\n return `${r.path} (sha256 ${r.digest.slice(0, 12)}…, ${plural(r.operations, \"operation\")}, written ${r.mtime})`;\n}\n"]}