@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,139 @@
1
+ /**
2
+ * The subsystem surface's git questions, beside the provenance ones
3
+ * (`../git.ts`) whose `gitText` — one spawn, its timeout and its capped
4
+ * stdout reader — they ask through. A package of their own because `git.ts`
5
+ * sat against the then 300-line limit and these three are one subject: what a
6
+ * `subsystem move` must know before renaming (`gitDirtyPaths`), what
7
+ * `subsystem history` asks after (`gitRenameHops`), and the ONE write the
8
+ * roadmap blesses (`gitStageRenames` — "move stages renames without
9
+ * committing"). The doctrine is unchanged: every way git can decline reads as
10
+ * "git will not say", never as an error a caller must handle.
11
+ */
12
+ import { gitText } from "../git.js";
13
+ /**
14
+ * Which of these repo-relative paths carry UNCOMMITTED work — anything
15
+ * `git status --porcelain` reports beneath them, untracked files included: an
16
+ * untracked file is exactly a change no commit records. Null for every way
17
+ * git declines (not a repository, not installed, a timeout, a non-zero exit),
18
+ * and the one caller — `subsystem move`'s only refusal — treats null as
19
+ * "proceed": a refusal needs positive evidence, and a fleet that does not use
20
+ * git must not be refused a move over it.
21
+ *
22
+ * `-z` for the same reason `gitTrackedFiles` uses it: line output QUOTES
23
+ * paths with spaces or non-ASCII bytes. A rename entry (`R ` when something
24
+ * is already staged) carries a second NUL-separated path; both belong in the
25
+ * answer.
26
+ */
27
+ export async function gitDirtyPaths(repoDir, rels) {
28
+ if (rels.length === 0)
29
+ return [];
30
+ const a = await gitText(repoDir, ["status", "--porcelain", "-z", "--", ...rels]);
31
+ if (a.code !== 0 || a.overflowed)
32
+ return null;
33
+ const tokens = a.out.split("\0").filter((t) => t !== "");
34
+ const paths = [];
35
+ for (let i = 0; i < tokens.length; i += 1) {
36
+ const entry = tokens[i];
37
+ // "XY <path>" — two status letters and a space. A rename/copy entry's
38
+ // ORIGINAL path follows as its own NUL token; take it too.
39
+ paths.push(entry.slice(3));
40
+ if (entry.startsWith("R") || entry.startsWith("C")) {
41
+ i += 1;
42
+ if (tokens[i] !== undefined)
43
+ paths.push(tokens[i]);
44
+ }
45
+ }
46
+ return paths;
47
+ }
48
+ /**
49
+ * How this file moved over time, OLDEST hop first — or null when git will not
50
+ * say. The question follows one FILE deliberately: `git log --follow` is
51
+ * defined for a single file and prints NOTHING for a directory path, so
52
+ * `subsystem history` follows a representative file inside the directory it
53
+ * is asked about (a service's spec.md, a subsystem's marker) and reads each
54
+ * hop's directories off the file's own rename record. An empty array is git
55
+ * ANSWERING "never renamed"; null is git declining — the caller renders the
56
+ * two differently and exits 0 for both, per the doctrine above.
57
+ *
58
+ * Output shape under `-z --format=%H`: `<hash>\0\nR<score>\0<old>\0<new>\0…`,
59
+ * newest commit first — the token walk below is anchored on the two shapes a
60
+ * token can have (a 40-hex hash, an R-status) so an unexpected shape yields
61
+ * fewer hops, never a wrong pairing.
62
+ */
63
+ export async function gitRenameHops(repoDir, rel) {
64
+ const a = await gitText(repoDir, ["log", "--follow", "--diff-filter=R", "--name-status", "-z", "--format=%H", "--", rel]);
65
+ if (a.code !== 0 || a.overflowed)
66
+ return null;
67
+ const tokens = a.out.split("\0").map((t) => (t.startsWith("\n") ? t.slice(1) : t));
68
+ const hops = [];
69
+ let commit = "";
70
+ for (let i = 0; i < tokens.length; i += 1) {
71
+ const token = tokens[i];
72
+ if (/^[0-9a-f]{40}$/.test(token))
73
+ commit = token;
74
+ else if (/^R\d*$/.test(token) && tokens[i + 1] !== undefined && tokens[i + 2] !== undefined) {
75
+ hops.push({ commit, from: tokens[i + 1], to: tokens[i + 2] });
76
+ i += 2;
77
+ }
78
+ }
79
+ return hops.reverse();
80
+ }
81
+ /**
82
+ * Was the rename record that produced a hop into `dest` at `commit` a GUESS?
83
+ * `git log --follow` pairs old and new paths by CONTENT similarity, and two
84
+ * identical files moved (or one moved while its twin is created or deleted)
85
+ * in the same commit give it a coin to flip — subsystem markers are routinely
86
+ * byte-identical (often empty), so a multi-directory move can report a hop
87
+ * from a directory the followed file never occupied. The cross-check asks the
88
+ * commit itself: if two or more of its diff entries carry the same blob as
89
+ * the one `dest` received, the pairing chose between equals and the hop is
90
+ * not evidence. `false` = unambiguous; `true` = a guess; null = git will not
91
+ * say — and the caller must treat BOTH non-false answers as "will not say",
92
+ * because repeating a maybe-phantom hop is worse than answering nothing.
93
+ */
94
+ export async function gitRenamePairingAmbiguous(repoDir, commit, dest) {
95
+ const a = await gitText(repoDir, ["diff-tree", "-r", "-M", "-z", commit]);
96
+ if (a.code !== 0 || a.overflowed)
97
+ return null;
98
+ // `-z` raw form: `:<mode> <mode> <sha> <sha> <status>` NUL, then one
99
+ // path token — two for a rename/copy. The leading token is the commit.
100
+ const tokens = a.out.split("\0").filter((t) => t !== "");
101
+ const entries = [];
102
+ for (let i = 0; i < tokens.length; i += 1) {
103
+ const token = tokens[i];
104
+ if (!token.startsWith(":"))
105
+ continue;
106
+ const fields = token.slice(1).split(" ");
107
+ const status = fields[4] ?? "";
108
+ const paths = status.startsWith("R") || status.startsWith("C") ? [tokens[i + 1], tokens[i + 2]] : [tokens[i + 1]];
109
+ entries.push({
110
+ srcSha: fields[2] ?? "",
111
+ dstSha: fields[3] ?? "",
112
+ status,
113
+ paths: paths.filter((p) => p !== undefined),
114
+ });
115
+ i += paths.length;
116
+ }
117
+ const own = entries.find((e) => e.status.startsWith("R") && e.paths[1] === dest);
118
+ // The hop's own rename is not in the commit's record — an answer this
119
+ // check cannot ground is an answer git will not give.
120
+ if (own === undefined)
121
+ return null;
122
+ const twins = entries.filter((e) => e.srcSha === own.dstSha || e.dstSha === own.dstSha);
123
+ return twins.length > 1;
124
+ }
125
+ /**
126
+ * Best-effort `git add -A` over these repo-relative paths — the ONE write
127
+ * (module banner): after a `subsystem move` lands its renames, staging the
128
+ * delete-side and add-side together is what lets git record the pair as a
129
+ * rename, which is what keeps `subsystem history` answerable after the user
130
+ * commits. Failure-silent in every direction: a fleet without git, an index
131
+ * lock, a timeout — the move already succeeded, and nothing here may turn it
132
+ * into an error.
133
+ */
134
+ export async function gitStageRenames(repoDir, rels) {
135
+ if (rels.length === 0)
136
+ return;
137
+ await gitText(repoDir, ["add", "-A", "--", ...rels]);
138
+ }
139
+ //# sourceMappingURL=moves.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"moves.js","sourceRoot":"","sources":["../../../../src/core/provenance/gitq/moves.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The subsystem surface's git questions, beside the provenance ones\n * (`../git.ts`) whose `gitText` — one spawn, its timeout and its capped\n * stdout reader — they ask through. A package of their own because `git.ts`\n * sat against the then 300-line limit and these three are one subject: what a\n * `subsystem move` must know before renaming (`gitDirtyPaths`), what\n * `subsystem history` asks after (`gitRenameHops`), and the ONE write the\n * roadmap blesses (`gitStageRenames` — \"move stages renames without\n * committing\"). The doctrine is unchanged: every way git can decline reads as\n * \"git will not say\", never as an error a caller must handle.\n */\nimport { gitText } from \"../git.js\";\n\n/**\n * Which of these repo-relative paths carry UNCOMMITTED work — anything\n * `git status --porcelain` reports beneath them, untracked files included: an\n * untracked file is exactly a change no commit records. Null for every way\n * git declines (not a repository, not installed, a timeout, a non-zero exit),\n * and the one caller — `subsystem move`'s only refusal — treats null as\n * \"proceed\": a refusal needs positive evidence, and a fleet that does not use\n * git must not be refused a move over it.\n *\n * `-z` for the same reason `gitTrackedFiles` uses it: line output QUOTES\n * paths with spaces or non-ASCII bytes. A rename entry (`R ` when something\n * is already staged) carries a second NUL-separated path; both belong in the\n * answer.\n */\nexport async function gitDirtyPaths(repoDir: string, rels: string[]): Promise<string[] | null> {\n if (rels.length === 0) return [];\n const a = await gitText(repoDir, [\"status\", \"--porcelain\", \"-z\", \"--\", ...rels]);\n if (a.code !== 0 || a.overflowed) return null;\n const tokens = a.out.split(\"\\0\").filter((t) => t !== \"\");\n const paths: string[] = [];\n for (let i = 0; i < tokens.length; i += 1) {\n const entry = tokens[i]!;\n // \"XY <path>\" — two status letters and a space. A rename/copy entry's\n // ORIGINAL path follows as its own NUL token; take it too.\n paths.push(entry.slice(3));\n if (entry.startsWith(\"R\") || entry.startsWith(\"C\")) {\n i += 1;\n if (tokens[i] !== undefined) paths.push(tokens[i]!);\n }\n }\n return paths;\n}\n\n/** One hop of a path's rename history: the commit, and the path either side of it. */\nexport interface RenameHop {\n commit: string;\n from: string;\n to: string;\n}\n\n/**\n * How this file moved over time, OLDEST hop first — or null when git will not\n * say. The question follows one FILE deliberately: `git log --follow` is\n * defined for a single file and prints NOTHING for a directory path, so\n * `subsystem history` follows a representative file inside the directory it\n * is asked about (a service's spec.md, a subsystem's marker) and reads each\n * hop's directories off the file's own rename record. An empty array is git\n * ANSWERING \"never renamed\"; null is git declining — the caller renders the\n * two differently and exits 0 for both, per the doctrine above.\n *\n * Output shape under `-z --format=%H`: `<hash>\\0\\nR<score>\\0<old>\\0<new>\\0…`,\n * newest commit first — the token walk below is anchored on the two shapes a\n * token can have (a 40-hex hash, an R-status) so an unexpected shape yields\n * fewer hops, never a wrong pairing.\n */\nexport async function gitRenameHops(repoDir: string, rel: string): Promise<RenameHop[] | null> {\n const a = await gitText(repoDir, [\"log\", \"--follow\", \"--diff-filter=R\", \"--name-status\", \"-z\", \"--format=%H\", \"--\", rel]);\n if (a.code !== 0 || a.overflowed) return null;\n const tokens = a.out.split(\"\\0\").map((t) => (t.startsWith(\"\\n\") ? t.slice(1) : t));\n const hops: RenameHop[] = [];\n let commit = \"\";\n for (let i = 0; i < tokens.length; i += 1) {\n const token = tokens[i]!;\n if (/^[0-9a-f]{40}$/.test(token)) commit = token;\n else if (/^R\\d*$/.test(token) && tokens[i + 1] !== undefined && tokens[i + 2] !== undefined) {\n hops.push({ commit, from: tokens[i + 1]!, to: tokens[i + 2]! });\n i += 2;\n }\n }\n return hops.reverse();\n}\n\n/**\n * Was the rename record that produced a hop into `dest` at `commit` a GUESS?\n * `git log --follow` pairs old and new paths by CONTENT similarity, and two\n * identical files moved (or one moved while its twin is created or deleted)\n * in the same commit give it a coin to flip — subsystem markers are routinely\n * byte-identical (often empty), so a multi-directory move can report a hop\n * from a directory the followed file never occupied. The cross-check asks the\n * commit itself: if two or more of its diff entries carry the same blob as\n * the one `dest` received, the pairing chose between equals and the hop is\n * not evidence. `false` = unambiguous; `true` = a guess; null = git will not\n * say — and the caller must treat BOTH non-false answers as \"will not say\",\n * because repeating a maybe-phantom hop is worse than answering nothing.\n */\nexport async function gitRenamePairingAmbiguous(\n repoDir: string,\n commit: string,\n dest: string,\n): Promise<boolean | null> {\n const a = await gitText(repoDir, [\"diff-tree\", \"-r\", \"-M\", \"-z\", commit]);\n if (a.code !== 0 || a.overflowed) return null;\n // `-z` raw form: `:<mode> <mode> <sha> <sha> <status>` NUL, then one\n // path token — two for a rename/copy. The leading token is the commit.\n const tokens = a.out.split(\"\\0\").filter((t) => t !== \"\");\n const entries: { srcSha: string; dstSha: string; status: string; paths: string[] }[] = [];\n for (let i = 0; i < tokens.length; i += 1) {\n const token = tokens[i]!;\n if (!token.startsWith(\":\")) continue;\n const fields = token.slice(1).split(\" \");\n const status = fields[4] ?? \"\";\n const paths = status.startsWith(\"R\") || status.startsWith(\"C\") ? [tokens[i + 1], tokens[i + 2]] : [tokens[i + 1]];\n entries.push({\n srcSha: fields[2] ?? \"\",\n dstSha: fields[3] ?? \"\",\n status,\n paths: paths.filter((p): p is string => p !== undefined),\n });\n i += paths.length;\n }\n const own = entries.find((e) => e.status.startsWith(\"R\") && e.paths[1] === dest);\n // The hop's own rename is not in the commit's record — an answer this\n // check cannot ground is an answer git will not give.\n if (own === undefined) return null;\n const twins = entries.filter((e) => e.srcSha === own.dstSha || e.dstSha === own.dstSha);\n return twins.length > 1;\n}\n\n/**\n * Best-effort `git add -A` over these repo-relative paths — the ONE write\n * (module banner): after a `subsystem move` lands its renames, staging the\n * delete-side and add-side together is what lets git record the pair as a\n * rename, which is what keeps `subsystem history` answerable after the user\n * commits. Failure-silent in every direction: a fleet without git, an index\n * lock, a timeout — the move already succeeded, and nothing here may turn it\n * into an error.\n */\nexport async function gitStageRenames(repoDir: string, rels: string[]): Promise<void> {\n if (rels.length === 0) return;\n await gitText(repoDir, [\"add\", \"-A\", \"--\", ...rels]);\n}\n"]}
@@ -0,0 +1,179 @@
1
+ /**
2
+ * Doc-body ancestry in the DOCS repo — the two git questions behind
3
+ * `loam vouch --pack`'s body delta: which commit last held the body a person
4
+ * vouched for (`findVouchedAncestor`), and what the file's diff from that
5
+ * commit to the working tree says (`bodyDiffText`). Read-only throughout:
6
+ * `rev-parse`/`log`/`show`/`diff`, no checkout, no temp writes.
7
+ *
8
+ * The mechanics are `core/diff/base-git.ts`'s to the letter — literally so:
9
+ * both import the one `gitText`/`GitAnswer`/`declineDetail` set from
10
+ * `../git.js`, so a hardening lands in both or in neither — but the doctrine
11
+ * is deliberately the OPPOSITE consequence. `loam diff` REFUSES when git
12
+ * cannot answer, because a silently empty base would report the whole fleet
13
+ * as added — a lie with a green exit code. The pack DEGRADES to "full read"
14
+ * instead: its output is a reading list, and for a reading list the
15
+ * conservative direction — read more, never less — is always honest, the same
16
+ * direction as provenance's existing hash-everything fallback. The shared
17
+ * helpers carry no verdict, so neither module can borrow the other's
18
+ * consequence by accident; each spells its own at its own call sites.
19
+ *
20
+ * The walk is BOUNDED at `ANCESTOR_WALK_CAP` commits. A vouched commit pushed
21
+ * past the cap by a very active docs repo degrades a legitimate incremental
22
+ * read to a full read — safe direction, and the `none` reason names the cap
23
+ * so the human understands why. Within the walk, one commit whose version of
24
+ * the file is absent (git answering "not here") is skipped; a git that stops
25
+ * answering mid-walk (spawn error, kill, timeout, output cap) aborts the whole
26
+ * search as `no-git` rather than letting 200 futile spawns each wait out the
27
+ * timeout.
28
+ */
29
+ import { declineDetail, gitText } from "../git.js";
30
+ import { contentDigest } from "../../document/frontmatter.js";
31
+ /**
32
+ * How many commits touching the file the ancestor search will read before
33
+ * declaring the vouched state unreachable. Past it the answer is `none` — a
34
+ * full read — with a reason that names the cap.
35
+ */
36
+ const ANCESTOR_WALK_CAP = 200;
37
+ /**
38
+ * How much diff text the pack will print. A body diff past this is not a
39
+ * reading list any more — the honest answer is "read the file", as `failed`.
40
+ */
41
+ const MAX_DIFF_TEXT_CHARS = 1024 * 1024;
42
+ /**
43
+ * The shared `gitText` (`../git.js`) with colour forced off. base-git's three
44
+ * questions (`rev-parse`/`ls-tree`/`show`) never colour, but this module runs
45
+ * `log` and `diff`, and a user's `color.ui = always` forces SGR escape
46
+ * sequences into their output even on a pipe — which would put terminal codes
47
+ * inside the `--json` payload's diff text and make the 40-hex-anchored log
48
+ * walk silently match nothing on exactly that machine. The flag lives here,
49
+ * not in the shared helper, because it is this module's need, not a property
50
+ * of asking git a question.
51
+ */
52
+ async function gitPlain(docsDir, args) {
53
+ return gitText(docsDir, ["-c", "color.ui=false", ...args]);
54
+ }
55
+ /**
56
+ * The bytes this commit's blob would carry on a CRLF checkout. The stamped
57
+ * `content_digest` is byte-exact over the WORKING-TREE file (document/frontmatter.ts), while
58
+ * `git show` hands back the BLOB — and on a Windows checkout with
59
+ * `core.autocrlf=true` the blob is LF where every working-tree byte is CRLF,
60
+ * so the exact digest of the blob would never equal a stamp taken over the
61
+ * same content and every vouched ancestor would be invisible on exactly those
62
+ * machines. Same hazard, same direction as `core/verify/pins/pin.ts`'s
63
+ * `pinnedDigest`, resolved the inverse way because the stamp's recipe is
64
+ * published and cannot be re-normalized after the fact: instead of
65
+ * normalizing both sides, the search hashes each candidate twice — as the
66
+ * blob is, and as its CRLF checkout rendering — and a match on either is a
67
+ * match. Only lone LFs are rewritten, so a blob that already carries CRLFs
68
+ * (committed without the clean filter, hence byte-identical on disk) is
69
+ * covered by the exact hash.
70
+ */
71
+ function checkoutRendering(text) {
72
+ return text.replace(/(?<!\r)\n/g, "\r\n");
73
+ }
74
+ /**
75
+ * The last commit in the docs repo's history whose version of `rel` (a
76
+ * docs-relative, `/`-separated path) has a body hashing to the stamped
77
+ * `content_digest` — newest first, because the reading list wants the
78
+ * SHORTEST honest diff, and any older commit holding the same bytes yields
79
+ * the same one.
80
+ */
81
+ export async function findVouchedAncestor(docsDir, rel, stampedDigest) {
82
+ // Belt to the callers' braces: `rel` is derived from loam's own path
83
+ // spelling, never argv, but every spelled pathspec below rides an argv, so
84
+ // an option-shaped or empty value is refused here rather than parsed by
85
+ // git as a flag. Same reason base-git.ts refuses option-shaped refs.
86
+ if (rel.trim() === "" || rel.startsWith("-")) {
87
+ return { kind: "no-git", detail: `'${rel}' is not a path git can be asked about.` };
88
+ }
89
+ // `--show-prefix` first, and not decoration (base-git.ts proved this): a
90
+ // docs repo checked out as a subdirectory of a larger repository answers
91
+ // `show` only under that prefix, and a walk whose paths all miss would
92
+ // report "no vouched ancestor" about a history that holds one.
93
+ const where = await gitPlain(docsDir, ["rev-parse", "--show-prefix"]);
94
+ if (where.spawnError !== undefined || where.code !== 0) {
95
+ return { kind: "no-git", detail: declineDetail(where) };
96
+ }
97
+ const prefix = where.out.trim();
98
+ // The pathspec is cwd-relative (no prefix — `log` resolves it against the
99
+ // cwd, unlike `show`'s repo-root spelling below). `-n` is the walk's bound.
100
+ const log = await gitPlain(docsDir, [
101
+ "log", "-n", String(ANCESTOR_WALK_CAP), "--format=%H", "--", rel,
102
+ ]);
103
+ if (log.spawnError !== undefined || log.code !== 0 || log.overflowed) {
104
+ return { kind: "no-git", detail: declineDetail(log) };
105
+ }
106
+ // Only shas shaped like shas walk on — an unexpected line yields a shorter
107
+ // walk, never a malformed argv (the gitq/moves.ts token-anchoring rule).
108
+ const commits = log.out.split("\n").map((l) => l.trim()).filter((l) => /^[0-9a-f]{40}$/.test(l));
109
+ // Sequential on purpose: newest-first order is the answer's definition, and
110
+ // the walk stops at the first match — a fan-out would read history it does
111
+ // not need and could answer with an older commit than the newest match.
112
+ for (const commit of commits) {
113
+ const shown = await gitPlain(docsDir, ["show", `${commit}:${prefix}${rel}`]);
114
+ if (shown.spawnError !== undefined || shown.code === null) {
115
+ // Git stopped answering (not installed mid-walk, killed, timed out, or
116
+ // the output cap fired on a monstrous version). Abort rather than walk
117
+ // on: each further spawn could wait out the whole timeout, and a "none"
118
+ // built over commits nobody read would claim the history was searched.
119
+ return {
120
+ kind: "no-git",
121
+ detail: shown.overflowed
122
+ ? `the file at ${commit.slice(0, 12)} exceeds the git output cap.`
123
+ : declineDetail(shown),
124
+ };
125
+ }
126
+ // A real non-zero exit is git ANSWERING — the file is absent at this
127
+ // commit (renamed since, or the commit only deleted it). Skip it.
128
+ if (shown.code !== 0)
129
+ continue;
130
+ if (contentDigest(shown.out) === stampedDigest ||
131
+ contentDigest(checkoutRendering(shown.out)) === stampedDigest) {
132
+ return { kind: "found", commit, text: shown.out };
133
+ }
134
+ }
135
+ return {
136
+ kind: "none",
137
+ reason: commits.length < ANCESTOR_WALK_CAP
138
+ ? "body has no vouched ancestor in history"
139
+ : `body has no vouched ancestor in history — only the last ${ANCESTOR_WALK_CAP} commits touching the file were walked, and the vouched state may lie beyond them`,
140
+ };
141
+ }
142
+ /**
143
+ * The file's diff from its last vouched state: `git diff <commit> -- <rel>`,
144
+ * commit-to-working-tree, in the docs repo. The output is git's own — when a
145
+ * hand edit touched the frontmatter after the vouch, its hunks ride along,
146
+ * which is why the pack's prose says "the file's diff", never "the body's".
147
+ */
148
+ export async function bodyDiffText(docsDir, commit, rel) {
149
+ // The commit came out of `findVouchedAncestor`'s own regex-vetted walk, but
150
+ // this function is exported API: re-vet, so no future caller can place an
151
+ // option-shaped string in the one argv slot that is not behind `--`.
152
+ if (!/^[0-9a-f]{40}$/.test(commit)) {
153
+ return { kind: "failed", reason: `'${commit}' is not a commit this diff can be asked about.` };
154
+ }
155
+ if (rel.trim() === "" || rel.startsWith("-")) {
156
+ return { kind: "failed", reason: `'${rel}' is not a path git can be asked about.` };
157
+ }
158
+ // `--no-optional-locks`: a commit-to-worktree diff may opportunistically
159
+ // refresh `.git/index`'s stat cache, which is a WRITE — small, benign, and
160
+ // exactly what a command documented as "writes nothing" must not do. The
161
+ // global flag tells git to skip any operation that would take a lock it
162
+ // does not strictly need. `--no-ext-diff --no-textconv` close the rest of
163
+ // the config surface: `diff.external` / a `.gitattributes` diff driver make
164
+ // `git diff` EXECUTE a user-configured program instead of printing a diff —
165
+ // an arbitrary write hazard on a read-only path, and output no machine
166
+ // consumer of `body.diff` could parse. The pack's diff is a machine
167
+ // artifact, not a terminal rendering; git's own plumbing flags say so.
168
+ const answer = await gitPlain(docsDir, [
169
+ "--no-optional-locks", "diff", "--no-ext-diff", "--no-textconv", commit, "--", rel,
170
+ ]);
171
+ if (answer.spawnError !== undefined || answer.code !== 0 || answer.overflowed) {
172
+ return { kind: "failed", reason: declineDetail(answer) };
173
+ }
174
+ if (answer.out.length > MAX_DIFF_TEXT_CHARS) {
175
+ return { kind: "failed", reason: "the body diff exceeds the pack's print cap — read the file" };
176
+ }
177
+ return { kind: "ok", diff: answer.out };
178
+ }
179
+ //# sourceMappingURL=vouched-ancestor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vouched-ancestor.js","sourceRoot":"","sources":["../../../../src/core/provenance/gitq/vouched-ancestor.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Doc-body ancestry in the DOCS repo — the two git questions behind\n * `loam vouch --pack`'s body delta: which commit last held the body a person\n * vouched for (`findVouchedAncestor`), and what the file's diff from that\n * commit to the working tree says (`bodyDiffText`). Read-only throughout:\n * `rev-parse`/`log`/`show`/`diff`, no checkout, no temp writes.\n *\n * The mechanics are `core/diff/base-git.ts`'s to the letter — literally so:\n * both import the one `gitText`/`GitAnswer`/`declineDetail` set from\n * `../git.js`, so a hardening lands in both or in neither — but the doctrine\n * is deliberately the OPPOSITE consequence. `loam diff` REFUSES when git\n * cannot answer, because a silently empty base would report the whole fleet\n * as added — a lie with a green exit code. The pack DEGRADES to \"full read\"\n * instead: its output is a reading list, and for a reading list the\n * conservative direction — read more, never less — is always honest, the same\n * direction as provenance's existing hash-everything fallback. The shared\n * helpers carry no verdict, so neither module can borrow the other's\n * consequence by accident; each spells its own at its own call sites.\n *\n * The walk is BOUNDED at `ANCESTOR_WALK_CAP` commits. A vouched commit pushed\n * past the cap by a very active docs repo degrades a legitimate incremental\n * read to a full read — safe direction, and the `none` reason names the cap\n * so the human understands why. Within the walk, one commit whose version of\n * the file is absent (git answering \"not here\") is skipped; a git that stops\n * answering mid-walk (spawn error, kill, timeout, output cap) aborts the whole\n * search as `no-git` rather than letting 200 futile spawns each wait out the\n * timeout.\n */\nimport { declineDetail, gitText, type GitAnswer } from \"../git.js\";\nimport { contentDigest } from \"../../document/frontmatter.js\";\n\n/**\n * How many commits touching the file the ancestor search will read before\n * declaring the vouched state unreachable. Past it the answer is `none` — a\n * full read — with a reason that names the cap.\n */\nconst ANCESTOR_WALK_CAP = 200;\n\n/**\n * How much diff text the pack will print. A body diff past this is not a\n * reading list any more — the honest answer is \"read the file\", as `failed`.\n */\nconst MAX_DIFF_TEXT_CHARS = 1024 * 1024;\n\n/**\n * The shared `gitText` (`../git.js`) with colour forced off. base-git's three\n * questions (`rev-parse`/`ls-tree`/`show`) never colour, but this module runs\n * `log` and `diff`, and a user's `color.ui = always` forces SGR escape\n * sequences into their output even on a pipe — which would put terminal codes\n * inside the `--json` payload's diff text and make the 40-hex-anchored log\n * walk silently match nothing on exactly that machine. The flag lives here,\n * not in the shared helper, because it is this module's need, not a property\n * of asking git a question.\n */\nasync function gitPlain(docsDir: string, args: string[]): Promise<GitAnswer> {\n return gitText(docsDir, [\"-c\", \"color.ui=false\", ...args]);\n}\n\n/**\n * The bytes this commit's blob would carry on a CRLF checkout. The stamped\n * `content_digest` is byte-exact over the WORKING-TREE file (document/frontmatter.ts), while\n * `git show` hands back the BLOB — and on a Windows checkout with\n * `core.autocrlf=true` the blob is LF where every working-tree byte is CRLF,\n * so the exact digest of the blob would never equal a stamp taken over the\n * same content and every vouched ancestor would be invisible on exactly those\n * machines. Same hazard, same direction as `core/verify/pins/pin.ts`'s\n * `pinnedDigest`, resolved the inverse way because the stamp's recipe is\n * published and cannot be re-normalized after the fact: instead of\n * normalizing both sides, the search hashes each candidate twice — as the\n * blob is, and as its CRLF checkout rendering — and a match on either is a\n * match. Only lone LFs are rewritten, so a blob that already carries CRLFs\n * (committed without the clean filter, hence byte-identical on disk) is\n * covered by the exact hash.\n */\nfunction checkoutRendering(text: string): string {\n return text.replace(/(?<!\\r)\\n/g, \"\\r\\n\");\n}\n\nexport type AncestorSearch =\n | {\n kind: \"found\";\n commit: string;\n /** The file exactly as that commit holds it — what the section delta reads. */\n text: string;\n }\n /** The walk completed and nothing matched — the honest verdict is a full read. */\n | { kind: \"none\"; reason: string }\n /** Git declined somewhere the walk could not continue past — also a full read. */\n | { kind: \"no-git\"; detail: string };\n\n/**\n * The last commit in the docs repo's history whose version of `rel` (a\n * docs-relative, `/`-separated path) has a body hashing to the stamped\n * `content_digest` — newest first, because the reading list wants the\n * SHORTEST honest diff, and any older commit holding the same bytes yields\n * the same one.\n */\nexport async function findVouchedAncestor(\n docsDir: string,\n rel: string,\n stampedDigest: string,\n): Promise<AncestorSearch> {\n // Belt to the callers' braces: `rel` is derived from loam's own path\n // spelling, never argv, but every spelled pathspec below rides an argv, so\n // an option-shaped or empty value is refused here rather than parsed by\n // git as a flag. Same reason base-git.ts refuses option-shaped refs.\n if (rel.trim() === \"\" || rel.startsWith(\"-\")) {\n return { kind: \"no-git\", detail: `'${rel}' is not a path git can be asked about.` };\n }\n // `--show-prefix` first, and not decoration (base-git.ts proved this): a\n // docs repo checked out as a subdirectory of a larger repository answers\n // `show` only under that prefix, and a walk whose paths all miss would\n // report \"no vouched ancestor\" about a history that holds one.\n const where = await gitPlain(docsDir, [\"rev-parse\", \"--show-prefix\"]);\n if (where.spawnError !== undefined || where.code !== 0) {\n return { kind: \"no-git\", detail: declineDetail(where) };\n }\n const prefix = where.out.trim();\n\n // The pathspec is cwd-relative (no prefix — `log` resolves it against the\n // cwd, unlike `show`'s repo-root spelling below). `-n` is the walk's bound.\n const log = await gitPlain(docsDir, [\n \"log\", \"-n\", String(ANCESTOR_WALK_CAP), \"--format=%H\", \"--\", rel,\n ]);\n if (log.spawnError !== undefined || log.code !== 0 || log.overflowed) {\n return { kind: \"no-git\", detail: declineDetail(log) };\n }\n // Only shas shaped like shas walk on — an unexpected line yields a shorter\n // walk, never a malformed argv (the gitq/moves.ts token-anchoring rule).\n const commits = log.out.split(\"\\n\").map((l) => l.trim()).filter((l) => /^[0-9a-f]{40}$/.test(l));\n // Sequential on purpose: newest-first order is the answer's definition, and\n // the walk stops at the first match — a fan-out would read history it does\n // not need and could answer with an older commit than the newest match.\n for (const commit of commits) {\n const shown = await gitPlain(docsDir, [\"show\", `${commit}:${prefix}${rel}`]);\n if (shown.spawnError !== undefined || shown.code === null) {\n // Git stopped answering (not installed mid-walk, killed, timed out, or\n // the output cap fired on a monstrous version). Abort rather than walk\n // on: each further spawn could wait out the whole timeout, and a \"none\"\n // built over commits nobody read would claim the history was searched.\n return {\n kind: \"no-git\",\n detail: shown.overflowed\n ? `the file at ${commit.slice(0, 12)} exceeds the git output cap.`\n : declineDetail(shown),\n };\n }\n // A real non-zero exit is git ANSWERING — the file is absent at this\n // commit (renamed since, or the commit only deleted it). Skip it.\n if (shown.code !== 0) continue;\n if (\n contentDigest(shown.out) === stampedDigest ||\n contentDigest(checkoutRendering(shown.out)) === stampedDigest\n ) {\n return { kind: \"found\", commit, text: shown.out };\n }\n }\n return {\n kind: \"none\",\n reason:\n commits.length < ANCESTOR_WALK_CAP\n ? \"body has no vouched ancestor in history\"\n : `body has no vouched ancestor in history — only the last ${ANCESTOR_WALK_CAP} commits touching the file were walked, and the vouched state may lie beyond them`,\n };\n}\n\nexport type BodyDiff =\n | { kind: \"ok\"; diff: string }\n /** No diff to print — the honest degrade is a full read, with this reason. */\n | { kind: \"failed\"; reason: string };\n\n/**\n * The file's diff from its last vouched state: `git diff <commit> -- <rel>`,\n * commit-to-working-tree, in the docs repo. The output is git's own — when a\n * hand edit touched the frontmatter after the vouch, its hunks ride along,\n * which is why the pack's prose says \"the file's diff\", never \"the body's\".\n */\nexport async function bodyDiffText(docsDir: string, commit: string, rel: string): Promise<BodyDiff> {\n // The commit came out of `findVouchedAncestor`'s own regex-vetted walk, but\n // this function is exported API: re-vet, so no future caller can place an\n // option-shaped string in the one argv slot that is not behind `--`.\n if (!/^[0-9a-f]{40}$/.test(commit)) {\n return { kind: \"failed\", reason: `'${commit}' is not a commit this diff can be asked about.` };\n }\n if (rel.trim() === \"\" || rel.startsWith(\"-\")) {\n return { kind: \"failed\", reason: `'${rel}' is not a path git can be asked about.` };\n }\n // `--no-optional-locks`: a commit-to-worktree diff may opportunistically\n // refresh `.git/index`'s stat cache, which is a WRITE — small, benign, and\n // exactly what a command documented as \"writes nothing\" must not do. The\n // global flag tells git to skip any operation that would take a lock it\n // does not strictly need. `--no-ext-diff --no-textconv` close the rest of\n // the config surface: `diff.external` / a `.gitattributes` diff driver make\n // `git diff` EXECUTE a user-configured program instead of printing a diff —\n // an arbitrary write hazard on a read-only path, and output no machine\n // consumer of `body.diff` could parse. The pack's diff is a machine\n // artifact, not a terminal rendering; git's own plumbing flags say so.\n const answer = await gitPlain(docsDir, [\n \"--no-optional-locks\", \"diff\", \"--no-ext-diff\", \"--no-textconv\", commit, \"--\", rel,\n ]);\n if (answer.spawnError !== undefined || answer.code !== 0 || answer.overflowed) {\n return { kind: \"failed\", reason: declineDetail(answer) };\n }\n if (answer.out.length > MAX_DIFF_TEXT_CHARS) {\n return { kind: \"failed\", reason: \"the body diff exceeds the pack's print cap — read the file\" };\n }\n return { kind: \"ok\", diff: answer.out };\n}\n"]}
@@ -0,0 +1,238 @@
1
+ /**
2
+ * What a SAMPLED vouch claims, how its sample is chosen, and how the claim is
3
+ * written into the document beside `vouched_by`.
4
+ *
5
+ * `loam vouch --sample <n>` exists because the alternative to a partial read
6
+ * is usually not a full read — it is no vouch at all, and a fleet of
7
+ * unvouched drafts. So this deliberately REDUCES the assurance a stamp
8
+ * carries, and every line here exists to make sure the reduction is visible:
9
+ * the scope rides beside `status: verified` (never as a new status — that
10
+ * string is frozen), it says k of n in the document itself, and it carries
11
+ * the seed so anyone can recompute exactly which sections the person was
12
+ * shown. A sampled vouch that could be mistaken for a full one would be worse
13
+ * than no vouch, because it would spend the one signal loam has.
14
+ *
15
+ * The seed is derived from the document's OWN content and the digest of its
16
+ * sources — never from the clock, a counter or a random number — for three
17
+ * reasons, in order of how much they matter:
18
+ *
19
+ * 1. **Anyone can audit it.** The stamp records the seed, k and n; the
20
+ * document records `content_digest` and `sources_digest`. A reviewer
21
+ * recomputes `sampleSeed` from those three values and `pickSample` over
22
+ * the body, and gets back the exact list the voucher was shown.
23
+ * 2. **The pick cannot be re-rolled in place.** A random seed would let an
24
+ * agent run the vouch — or `--pack --sample` — until the section it wrote
25
+ * carelessly fell outside the sample, leaving no trace anywhere. Content
26
+ * derivation makes every re-roll an EDIT to the document: recorded in the
27
+ * docs repo's history, and moving `content_digest` under any stamp
28
+ * already standing over it.
29
+ * 3. **The same recipe answers before and after.** The pre-vouch reading
30
+ * list, the prompt and `loam vouch --pack --sample` all call `planSample`
31
+ * with the digests the stamp is about to carry, so the pack cannot
32
+ * prescribe one sample while the stamp records another.
33
+ *
34
+ * Reproducibility rests on one property of the writer:
35
+ * `withFrontmatterFields` leaves the body byte-identical, and `contentDigest`
36
+ * hashes only the body — so `contentDigest(raw)` computed BEFORE the stamp
37
+ * equals the `content_digest` the stamp writes. That is what lets the sample
38
+ * be chosen (and shown to a person) before the value it is keyed to exists on
39
+ * disk.
40
+ *
41
+ * What this does NOT do — and the difference is worth stating plainly, since
42
+ * an overstated claim is worse than none — is make the sample UNPREDICTABLE.
43
+ * The recipe is published (SCHEMA.md), so anybody holding the document can
44
+ * compute the pick before anybody vouches: that IS reason 1, and the two
45
+ * properties are in direct tension. An agent that wants a particular section
46
+ * left out of the read can append a space and recompute until it is, at the
47
+ * cost of one cosmetic edit per attempt in a version-controlled file,
48
+ * immediately before asking a person to vouch. Auditability was chosen over
49
+ * unpredictability deliberately — hiding the recipe needs a secret loam has
50
+ * nowhere to keep, and a sample nobody can check is not evidence of anything.
51
+ * What the design buys is that steering is neither free nor invisible: the
52
+ * same bargain `sources_digest` strikes, which is a change detector and not a
53
+ * seal.
54
+ *
55
+ * It also does not weight the sample. See `pickSample`.
56
+ */
57
+ import { createHash } from "node:crypto";
58
+ import { stringField } from "../../document/frontmatter.js";
59
+ import { splitSections } from "./sections.js";
60
+ /**
61
+ * Hex characters kept from a sha256 — `provenance/stamp.ts`'s DIGEST_LENGTH,
62
+ * respelled rather than imported because this is a seed and not a digest: the
63
+ * two would be free to diverge, and importing would tie a sampling decision to
64
+ * a change-detection budget. 64 bits is not a seal here either; an adversary
65
+ * who wants a collision can have one, and the audit trail is the git history
66
+ * of the docs repo, not this number.
67
+ */
68
+ const SEED_LENGTH = 16;
69
+ /**
70
+ * The seed for one spec-axis FILE: `sha256(service \0 content_digest \0
71
+ * sources_digest)`, first 16 hex characters.
72
+ *
73
+ * Per file, not per service, because the two inputs are per-file stamps —
74
+ * spec.md and arch.spec.md carry their own digests, so one `--sample 3` run
75
+ * picks three sections of each from two different seeds. The service id is in
76
+ * the hash so two services whose specs happen to be byte-identical (a
77
+ * scaffold, a copy) do not get the same reading list.
78
+ *
79
+ * NUL separators, `sourcesDigest`'s own recipe: without them
80
+ * `("ab", "c")` and `("a", "bc")` hash alike, and a service id may contain
81
+ * dots and dashes.
82
+ */
83
+ export function sampleSeed(service, contentDigest, sourcesDigest) {
84
+ return createHash("sha256")
85
+ .update(`${service}\0${contentDigest}\0${sourcesDigest}`)
86
+ .digest("hex")
87
+ .slice(0, SEED_LENGTH);
88
+ }
89
+ /**
90
+ * Pick `n` sections deterministically from `sections`, returned in DOCUMENT
91
+ * order.
92
+ *
93
+ * Rank each section by `sha256(seed \0 index \0 heading)` and take the `n`
94
+ * lowest ranks. Hash-ranking rather than a seeded PRNG: there is no PRNG in
95
+ * the standard library, adding a dependency for one is a product decision this
96
+ * repo has already made against, and a hash rank is recomputable one section
97
+ * at a time by anybody with a shell. The index is in the rank so two sections
98
+ * with identical heading text (a document with two `## Notes`) still rank
99
+ * apart, and the index tiebreak below keeps the sort total.
100
+ *
101
+ * Document order on the way out, not rank order: the person is going to read
102
+ * the file top to bottom, and a list that jumps around is a list they lose
103
+ * their place in.
104
+ *
105
+ * **Uniform — the sample is NOT weighted by fan-in**, and that is a decision
106
+ * rather than an omission. `core/dependencies/fanin.ts` counts how many
107
+ * services depend on a SERVICE; nothing in loam says which consumer depends on
108
+ * which SECTION, and the join that would (section -> `Operations:`/`Publishes:`
109
+ * -> landscape edge -> caller) has three defects at this stakes. It is
110
+ * derivable only for `### Requirement:` sections that carry those lines, so
111
+ * every narrative section — `## Overview`, `## Interfaces`, the prose most
112
+ * likely to be quietly false — would weight to zero and effectively stop being
113
+ * sampled. It needs the fleet map and every sibling's contract, so a vouch in
114
+ * a service repo would depend on documents it cannot see, and an unparseable
115
+ * landscape would silently flatten the weights back to uniform without saying
116
+ * so. And decisively: those inputs are documents an agent can edit, and they
117
+ * are not covered by either digest in the seed — so weighting would hand back
118
+ * exactly the steering that content-derived seeding exists to take away. The
119
+ * parameter list has room for weights if a later version can answer those;
120
+ * v1's answer is that an unweighted sample nobody can aim is worth more than a
121
+ * weighted one somebody can.
122
+ */
123
+ export function pickSample(sections, n, seed) {
124
+ return sections
125
+ .map((section, index) => ({
126
+ index,
127
+ section,
128
+ rank: createHash("sha256").update(`${seed}\0${index}\0${section.heading}`).digest("hex"),
129
+ }))
130
+ // Rank first, index second: sha256 makes a tie astronomically unlikely,
131
+ // but "unlikely" is not "total", and an unstable sort over equal ranks
132
+ // would make the pick depend on the engine's sort implementation — which
133
+ // is exactly the reproducibility this whole module promises.
134
+ .sort((a, b) => (a.rank < b.rank ? -1 : a.rank > b.rank ? 1 : a.index - b.index))
135
+ .slice(0, n)
136
+ .sort((a, b) => a.index - b.index)
137
+ .map((ranked) => ranked.section);
138
+ }
139
+ /**
140
+ * The whole per-file derivation in one call, so that the reading list, the
141
+ * prompt, `--pack --sample` and the stamp cannot drift into prescribing
142
+ * different samples of the same file. Every caller goes through here.
143
+ *
144
+ * A file with `of <= n` comes back with every section picked: the sample
145
+ * covers the document, so the run is an ordinary full vouch and stamps no
146
+ * scope at all. That case is decided by comparing `picked.length` with `of`,
147
+ * one derivation rather than a boolean somebody has to keep true.
148
+ */
149
+ export function planSample(req) {
150
+ const sections = splitSections(req.body);
151
+ const seed = sampleSeed(req.service, req.contentDigest, req.sourcesDigest);
152
+ return { seed, of: sections.length, picked: pickSample(sections, req.n, seed) };
153
+ }
154
+ /**
155
+ * The `vouch_scope` value: `sampled 4/17 seed=1a2b3c4d5e6f7089`.
156
+ *
157
+ * One flat string rather than a nested YAML mapping, following the
158
+ * `sources_files` precedent: `withFrontmatterFields` takes string values and
159
+ * promises a byte-identical body, and a mapping value would put the writer in
160
+ * the business of composing YAML structure inside somebody's header. It also
161
+ * reads: a reviewer scanning a diff sees the whole claim on one line.
162
+ */
163
+ export function encodeVouchScope(scope) {
164
+ return `sampled ${scope.sections}/${scope.of} seed=${scope.seed}`;
165
+ }
166
+ /** Exactly what `encodeVouchScope` writes, and nothing else. */
167
+ const SCOPE_RE = new RegExp(String.raw `^sampled (\d+)\/(\d+) seed=([0-9a-f]{${SEED_LENGTH}})$`);
168
+ /**
169
+ * Read a stamped `vouch_scope` back, or null when it is not one this loam
170
+ * wrote.
171
+ *
172
+ * Null means "cannot be read", NEVER "is not sampled" — the two are different
173
+ * facts and every caller must keep them apart, which is what `isSampled`
174
+ * below is for. A verified document carrying an unreadable scope is graded as
175
+ * SAMPLED by `sources.sampled-vouch`, `loam list` and `loam show`: fail
176
+ * closed, because the alternative is that mangling one field promotes a
177
+ * partial read to a full one.
178
+ */
179
+ export function decodeVouchScope(stamped) {
180
+ if (stamped === undefined)
181
+ return null;
182
+ const m = SCOPE_RE.exec(stamped.trim());
183
+ if (m === null)
184
+ return null;
185
+ const scope = { sections: Number(m[1]), of: Number(m[2]), seed: m[3] };
186
+ // A claim that reads as covering everything is not a sample, and neither is
187
+ // one that read nothing: both are shapes this writer never produces, so
188
+ // treating them as decodable would let a hand-edited `sampled 17/17` grade
189
+ // as a legible partial claim instead of an unreadable one.
190
+ return scope.sections >= 1 && scope.sections < scope.of ? scope : null;
191
+ }
192
+ export function readVouchScope(fm) {
193
+ if (!Object.hasOwn(fm.data, "vouch_scope"))
194
+ return { kind: "none" };
195
+ const text = stringField(fm, "vouch_scope");
196
+ if (text === undefined)
197
+ return { kind: "unreadable", text: null };
198
+ const scope = decodeVouchScope(text);
199
+ return scope === null ? { kind: "unreadable", text } : { kind: "sampled", scope, text };
200
+ }
201
+ /**
202
+ * The scope as a surface shows it: the stamped text, or — for a value that is
203
+ * not even text — one fixed sentence, because what a reader must not be shown
204
+ * for a present scope is nothing at all. Null means the key is absent, which
205
+ * is the only state that reads as a full vouch.
206
+ *
207
+ * One spelling of the unreadable case, because `loam show` and the context
208
+ * pack have to say the same thing about the same document.
209
+ */
210
+ export function scopeText(fm) {
211
+ const stamp = readVouchScope(fm);
212
+ if (stamp.kind === "none")
213
+ return null;
214
+ if (stamp.kind === "sampled")
215
+ return stamp.text;
216
+ return stamp.text ?? "present, but its value is not text — graded sampled";
217
+ }
218
+ /**
219
+ * Which sections a recorded scope actually covered, recomputed from its own
220
+ * seed over the body it was taken over.
221
+ *
222
+ * This is the audit property in code: hand it the stamped scope and the body
223
+ * that was vouched, get back the list the voucher was shown. The re-vouch
224
+ * pack uses it to say which sections a previous sampled vouch READ, so the
225
+ * ones it did not can be named as never-read rather than quietly counted as
226
+ * covered.
227
+ *
228
+ * Null when the body no longer has the section count the scope names — the
229
+ * body has changed, so the pick cannot be reproduced and no claim about what
230
+ * was read is safe. Fail closed: an unreproducible sample licenses nothing.
231
+ */
232
+ export function sampledSections(body, scope) {
233
+ const sections = splitSections(body);
234
+ if (sections.length !== scope.of)
235
+ return null;
236
+ return pickSample(sections, scope.sections, scope.seed);
237
+ }
238
+ //# sourceMappingURL=scope.js.map