@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,177 @@
1
+ /**
2
+ * The evidence-pin re-check as validate findings: every ACTIVE feature record
3
+ * this service has attested, its pins graded against THIS working tree.
4
+ *
5
+ * Service-repo-scoped like `sources.*` and the gherkin chain — the citations
6
+ * resolve only inside the service's own repository. From the docs repo this
7
+ * TARGET is silent by design: every pin would grade `unresolved` there, which
8
+ * would be a lie about the code rather than about the record, and
9
+ * `sources.unverifiable-from-here` already names the blind spot once per
10
+ * service. One code of the family is not about the code at all —
11
+ * `evidence.record-unreadable` is about the record, which lives in the docs
12
+ * repo — so the FEATURE target (`../feature.ts`) raises it too, from anywhere,
13
+ * through `featureRecordFindings` below:
14
+ * with only this target raising it, `validate --all` in the docs repo stayed
15
+ * green over a conflict-marked record that `verify` refused and `status`,
16
+ * `gate` and `tasks` all reported. In a service repo's `--all` the same file
17
+ * is therefore named twice, once per target: here as this service's pins
18
+ * going unchecked, there as the feature's record itself.
19
+ *
20
+ * ARCHIVED records are deliberately not linted (a v1 non-goal, recorded here):
21
+ * a frozen record is history, post-ship code drift is normal evolution, and
22
+ * grading it would turn every service's CI permanently yellow the week after
23
+ * every ship. If audit-time re-checks of shipped records are ever wanted, the
24
+ * same `lintEvidencePins` call over `listFeatures` include-archived is the
25
+ * whole change — behind an explicit flag, so the default stays quiet.
26
+ *
27
+ * Everything here demotes reviewer confidence only: warns never flip `valid`,
28
+ * `--strict` may gate on them as it gates on any warning, and no grade ever
29
+ * moves a verdict — `attested` never silently becomes `verified` and a drifted
30
+ * pin never un-confirms a claim.
31
+ */
32
+ import { repoPath } from "../../../core/envelope/json.js";
33
+ import { inOrder } from "../../../core/kernel/concurrency.js";
34
+ import {} from "../../../core/kernel/ids/service.js";
35
+ import {} from "../../../core/repo/entries.js";
36
+ import { listFeatures } from "../../../core/repo/repo.js";
37
+ import { readVerificationState } from "../../../core/verify/read/file.js";
38
+ import { lintEvidencePins } from "../../../core/verify/pins/lint.js";
39
+ import {} from "../../../core/vocabulary/report.js";
40
+ export async function evidencePinFindings(docsDir, service, repoDir, fleet) {
41
+ if (repoDir === undefined)
42
+ return [];
43
+ // Membership questions cross the provenance line through plain strings by
44
+ // design (kernel/ids/service.ts) — record subjects are document text.
45
+ const me = service;
46
+ // ACTIVE features only — see the header for why archived records stay frozen.
47
+ const features = await listFeatures(docsDir, {}, fleet);
48
+ const lints = await inOrder(features, async (feature) => {
49
+ // Three states, graded apart on purpose. ABSENT is a feature nobody has
50
+ // verified — legitimate silence. UNREADABLE is somebody's record this run
51
+ // could not use, and it must be a finding here rather than a skip: the
52
+ // damage that most plausibly breaks a record in a service repo's CI is a
53
+ // hand edit to the very pins this family grades, and a lint that went
54
+ // silent over it would turn "someone broke the record" into a green run —
55
+ // `verify` names the same file `record-unreadable`, but this CI job never
56
+ // runs verify. An unreadable record also cannot say whether it attests
57
+ // this service, so the finding fires regardless of attestation.
58
+ const read = await readVerificationState(feature.dir);
59
+ if (read.state === "unreadable") {
60
+ return { feature: feature.id, path: repoPath(docsDir, read.path), unreadable: read.reason, advice: read.advice };
61
+ }
62
+ if (read.state === "absent" || read.verification.schema !== 2)
63
+ return null;
64
+ if (!(read.verification.attestations ?? []).some((a) => a.service === me))
65
+ return null;
66
+ return { feature: feature.id, lint: await lintEvidencePins(read.verification.claims, me, repoDir) };
67
+ });
68
+ const findings = [];
69
+ let checked = 0;
70
+ let pinnedRecords = 0;
71
+ let drifted = false;
72
+ for (const entry of lints) {
73
+ if (entry === null)
74
+ continue;
75
+ if ("unreadable" in entry) {
76
+ findings.push({
77
+ severity: "warn",
78
+ code: "evidence.record-unreadable",
79
+ subject: service,
80
+ message: recordUnreadableMessage(`${me}: ${entry.feature}`, entry),
81
+ });
82
+ continue;
83
+ }
84
+ const { feature, lint } = entry;
85
+ if (lint.checked > 0 || lint.drifts.length > 0)
86
+ pinnedRecords += 1;
87
+ checked += lint.checked;
88
+ // The code is spelled as a literal at each call below, and the grade rides
89
+ // beside it rather than being sliced back out of the code string — the
90
+ // codes-drift collector resolves the `code` slot, and a derivation would
91
+ // be a second definition of the pairing free to drift from the first.
92
+ const drift = (grade, code, sentence) => {
93
+ const drifts = lint.drifts.filter((d) => d.grade === grade);
94
+ if (drifts.length === 0)
95
+ return;
96
+ drifted = true;
97
+ findings.push({
98
+ severity: "warn",
99
+ code,
100
+ subject: service,
101
+ message: `${me}: ${feature}: ${drifts.length} recorded evidence pin(s) ${sentence} — ` +
102
+ "a reading priority for the reviewer, never a verdict change; re-answer and re-record " +
103
+ `(\`loam verify ${feature} --service ${me} --record answers.json\`) once the evidence is re-read`,
104
+ details: drifts.map(detailLine),
105
+ });
106
+ };
107
+ drift("unresolved", "evidence.unresolved", "cannot be re-checked in this working tree: the cited file is gone, unreadable, not a regular file, or the cited line is past its end");
108
+ drift("moved", "evidence.moved", "cite a file that changed since the record, though each cited line survives");
109
+ drift("line-changed", "evidence.line-changed", "cite line(s) that no longer say what was recorded");
110
+ drift("token-missing", "evidence.token-missing", "cite file(s) that no longer contain the literal string the claim asserts");
111
+ if (lint.unpinned > 0) {
112
+ findings.push({
113
+ severity: "ok",
114
+ // The pre-content_digest-vouch precedent: a record from before the
115
+ // capability existed is not wrong, it is unfindable-by-this-check.
116
+ code: "evidence.unpinned",
117
+ subject: service,
118
+ message: `${me}: ${feature}: ${lint.unpinned} agent-confirmed citation(s) carry no evidence pin — ` +
119
+ `recorded before pins existed; the next \`loam verify ${feature} --service ${me} --record\` makes them drift-checkable`,
120
+ });
121
+ }
122
+ }
123
+ if (checked > 0 && !drifted) {
124
+ findings.push({
125
+ severity: "ok",
126
+ code: "evidence.checked",
127
+ subject: service,
128
+ message: `${me}: ${checked} evidence pin(s) across ${pinnedRecords} feature record(s) re-checked against this working tree`,
129
+ });
130
+ }
131
+ return findings;
132
+ }
133
+ /**
134
+ * `evidence.record-unreadable` on the FEATURE target (`../feature.ts`), from
135
+ * anywhere — the docs repo included, which is where the record lives. Kept
136
+ * here, beside the service target's emission, so one module owns the code and
137
+ * its words: the record read is the same `readVerificationState`, the path is
138
+ * made docs-relative the same way, and the message is the same sentence.
139
+ * Readability only — an `ok` record contributes nothing here, its verdict is
140
+ * `verify`'s and `status`'s to state — and a warn for the reasons the header
141
+ * gives: `valid` and `loam archive` are untouched, `--strict` is the lever.
142
+ */
143
+ export async function featureRecordFindings(docsDir, feature) {
144
+ const read = await readVerificationState(feature.dir);
145
+ if (read.state !== "unreadable")
146
+ return [];
147
+ const path = repoPath(docsDir, read.path);
148
+ return [
149
+ {
150
+ severity: "warn",
151
+ code: "evidence.record-unreadable",
152
+ message: recordUnreadableMessage(feature.id, { path, unreadable: read.reason, advice: read.advice }),
153
+ locations: [{ path, role: "primary" }],
154
+ },
155
+ ];
156
+ }
157
+ /**
158
+ * The sentence `evidence.record-unreadable` carries, for both targets that
159
+ * raise it. Each emission spells the code literally (the codes-drift
160
+ * collector resolves the `code` slot, as `drift` above says); only the words
161
+ * are shared, so the two cannot drift into two descriptions of one file.
162
+ *
163
+ * The reader's own recipe for the one file that failed, never a fixed one:
164
+ * "re-record" alone sent this finding's reader into `--record`'s refusal of
165
+ * the very same file, and the safe repair differs between a service's own
166
+ * attestation file and the one-file record other services' evidence may sit
167
+ * in. `path` is docs-relative.
168
+ */
169
+ function recordUnreadableMessage(label, file) {
170
+ return (`${label}: ${file.path} exists but cannot be read as a verification record (${file.unreadable}) — ` +
171
+ `none of its evidence was checked. ${file.advice} loam never overwrites a record it could not read`);
172
+ }
173
+ /** One drift as a detail line: which claim, which citation, what changed. */
174
+ function detailLine(d) {
175
+ return `${d.claim} ${d.evidence} — ${d.what}`;
176
+ }
177
+ //# sourceMappingURL=evidence-pins.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evidence-pins.js","sourceRoot":"","sources":["../../../../src/commands/validate/service/evidence-pins.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The evidence-pin re-check as validate findings: every ACTIVE feature record\n * this service has attested, its pins graded against THIS working tree.\n *\n * Service-repo-scoped like `sources.*` and the gherkin chain — the citations\n * resolve only inside the service's own repository. From the docs repo this\n * TARGET is silent by design: every pin would grade `unresolved` there, which\n * would be a lie about the code rather than about the record, and\n * `sources.unverifiable-from-here` already names the blind spot once per\n * service. One code of the family is not about the code at all —\n * `evidence.record-unreadable` is about the record, which lives in the docs\n * repo — so the FEATURE target (`../feature.ts`) raises it too, from anywhere,\n * through `featureRecordFindings` below:\n * with only this target raising it, `validate --all` in the docs repo stayed\n * green over a conflict-marked record that `verify` refused and `status`,\n * `gate` and `tasks` all reported. In a service repo's `--all` the same file\n * is therefore named twice, once per target: here as this service's pins\n * going unchecked, there as the feature's record itself.\n *\n * ARCHIVED records are deliberately not linted (a v1 non-goal, recorded here):\n * a frozen record is history, post-ship code drift is normal evolution, and\n * grading it would turn every service's CI permanently yellow the week after\n * every ship. If audit-time re-checks of shipped records are ever wanted, the\n * same `lintEvidencePins` call over `listFeatures` include-archived is the\n * whole change — behind an explicit flag, so the default stays quiet.\n *\n * Everything here demotes reviewer confidence only: warns never flip `valid`,\n * `--strict` may gate on them as it gates on any warning, and no grade ever\n * moves a verdict — `attested` never silently becomes `verified` and a drifted\n * pin never un-confirms a claim.\n */\nimport { repoPath } from \"../../../core/envelope/json.js\";\nimport { inOrder } from \"../../../core/kernel/concurrency.js\";\nimport { type PathableService } from \"../../../core/kernel/ids/service.js\";\nimport { type FeatureEntry } from \"../../../core/repo/entries.js\";\nimport { listFeatures } from \"../../../core/repo/repo.js\";\nimport { readVerificationState } from \"../../../core/verify/read/file.js\";\nimport { lintEvidencePins, type PinDrift, type PinLint } from \"../../../core/verify/pins/lint.js\";\nimport { type Finding } from \"../../../core/vocabulary/report.js\";\nimport type { FleetContext } from \"../../../core/fleet-context.js\";\nimport type { DocsDir } from \"../../../core/kernel/ids/dirs.js\";\n\nexport async function evidencePinFindings(\n docsDir: DocsDir,\n service: PathableService,\n repoDir: string | undefined,\n fleet: FleetContext,\n): Promise<Finding[]> {\n if (repoDir === undefined) return [];\n // Membership questions cross the provenance line through plain strings by\n // design (kernel/ids/service.ts) — record subjects are document text.\n const me: string = service;\n // ACTIVE features only — see the header for why archived records stay frozen.\n const features = await listFeatures(docsDir, {}, fleet);\n type Linted =\n | null\n | { feature: string; path: string; unreadable: string; advice: string }\n | { feature: string; lint: PinLint };\n const lints = await inOrder(features, async (feature): Promise<Linted> => {\n // Three states, graded apart on purpose. ABSENT is a feature nobody has\n // verified — legitimate silence. UNREADABLE is somebody's record this run\n // could not use, and it must be a finding here rather than a skip: the\n // damage that most plausibly breaks a record in a service repo's CI is a\n // hand edit to the very pins this family grades, and a lint that went\n // silent over it would turn \"someone broke the record\" into a green run —\n // `verify` names the same file `record-unreadable`, but this CI job never\n // runs verify. An unreadable record also cannot say whether it attests\n // this service, so the finding fires regardless of attestation.\n const read = await readVerificationState(feature.dir);\n if (read.state === \"unreadable\") {\n return { feature: feature.id, path: repoPath(docsDir, read.path), unreadable: read.reason, advice: read.advice };\n }\n if (read.state === \"absent\" || read.verification.schema !== 2) return null;\n if (!(read.verification.attestations ?? []).some((a) => a.service === me)) return null;\n return { feature: feature.id, lint: await lintEvidencePins(read.verification.claims, me, repoDir) };\n });\n\n const findings: Finding[] = [];\n let checked = 0;\n let pinnedRecords = 0;\n let drifted = false;\n for (const entry of lints) {\n if (entry === null) continue;\n if (\"unreadable\" in entry) {\n findings.push({\n severity: \"warn\",\n code: \"evidence.record-unreadable\",\n subject: service,\n message: recordUnreadableMessage(`${me}: ${entry.feature}`, entry),\n });\n continue;\n }\n const { feature, lint } = entry;\n if (lint.checked > 0 || lint.drifts.length > 0) pinnedRecords += 1;\n checked += lint.checked;\n // The code is spelled as a literal at each call below, and the grade rides\n // beside it rather than being sliced back out of the code string — the\n // codes-drift collector resolves the `code` slot, and a derivation would\n // be a second definition of the pairing free to drift from the first.\n const drift = (grade: PinDrift[\"grade\"], code: string, sentence: string): void => {\n const drifts = lint.drifts.filter((d) => d.grade === grade);\n if (drifts.length === 0) return;\n drifted = true;\n findings.push({\n severity: \"warn\",\n code,\n subject: service,\n message:\n `${me}: ${feature}: ${drifts.length} recorded evidence pin(s) ${sentence} — ` +\n \"a reading priority for the reviewer, never a verdict change; re-answer and re-record \" +\n `(\\`loam verify ${feature} --service ${me} --record answers.json\\`) once the evidence is re-read`,\n details: drifts.map(detailLine),\n });\n };\n drift(\n \"unresolved\",\n \"evidence.unresolved\",\n \"cannot be re-checked in this working tree: the cited file is gone, unreadable, not a regular file, or the cited line is past its end\",\n );\n drift(\"moved\", \"evidence.moved\", \"cite a file that changed since the record, though each cited line survives\");\n drift(\"line-changed\", \"evidence.line-changed\", \"cite line(s) that no longer say what was recorded\");\n drift(\n \"token-missing\",\n \"evidence.token-missing\",\n \"cite file(s) that no longer contain the literal string the claim asserts\",\n );\n if (lint.unpinned > 0) {\n findings.push({\n severity: \"ok\",\n // The pre-content_digest-vouch precedent: a record from before the\n // capability existed is not wrong, it is unfindable-by-this-check.\n code: \"evidence.unpinned\",\n subject: service,\n message:\n `${me}: ${feature}: ${lint.unpinned} agent-confirmed citation(s) carry no evidence pin — ` +\n `recorded before pins existed; the next \\`loam verify ${feature} --service ${me} --record\\` makes them drift-checkable`,\n });\n }\n }\n if (checked > 0 && !drifted) {\n findings.push({\n severity: \"ok\",\n code: \"evidence.checked\",\n subject: service,\n message: `${me}: ${checked} evidence pin(s) across ${pinnedRecords} feature record(s) re-checked against this working tree`,\n });\n }\n return findings;\n}\n\n/**\n * `evidence.record-unreadable` on the FEATURE target (`../feature.ts`), from\n * anywhere — the docs repo included, which is where the record lives. Kept\n * here, beside the service target's emission, so one module owns the code and\n * its words: the record read is the same `readVerificationState`, the path is\n * made docs-relative the same way, and the message is the same sentence.\n * Readability only — an `ok` record contributes nothing here, its verdict is\n * `verify`'s and `status`'s to state — and a warn for the reasons the header\n * gives: `valid` and `loam archive` are untouched, `--strict` is the lever.\n */\nexport async function featureRecordFindings(docsDir: DocsDir, feature: FeatureEntry): Promise<Finding[]> {\n const read = await readVerificationState(feature.dir);\n if (read.state !== \"unreadable\") return [];\n const path = repoPath(docsDir, read.path);\n return [\n {\n severity: \"warn\",\n code: \"evidence.record-unreadable\",\n message: recordUnreadableMessage(feature.id, { path, unreadable: read.reason, advice: read.advice }),\n locations: [{ path, role: \"primary\" }],\n },\n ];\n}\n\n/**\n * The sentence `evidence.record-unreadable` carries, for both targets that\n * raise it. Each emission spells the code literally (the codes-drift\n * collector resolves the `code` slot, as `drift` above says); only the words\n * are shared, so the two cannot drift into two descriptions of one file.\n *\n * The reader's own recipe for the one file that failed, never a fixed one:\n * \"re-record\" alone sent this finding's reader into `--record`'s refusal of\n * the very same file, and the safe repair differs between a service's own\n * attestation file and the one-file record other services' evidence may sit\n * in. `path` is docs-relative.\n */\nfunction recordUnreadableMessage(\n label: string,\n file: { path: string; unreadable: string; advice: string },\n): string {\n return (\n `${label}: ${file.path} exists but cannot be read as a verification record (${file.unreadable}) — ` +\n `none of its evidence was checked. ${file.advice} loam never overwrites a record it could not read`\n );\n}\n\n/** One drift as a detail line: which claim, which citation, what changed. */\nfunction detailLine(d: PinDrift): string {\n return `${d.claim} ${d.evidence} — ${d.what}`;\n}\n"]}
@@ -0,0 +1,226 @@
1
+ import { ARTIFACT_FILES } from "../../../../core/repo/paths.js";
2
+ import { serviceLevelElements } from "../../fleet/census.js";
3
+ /**
4
+ * How the OTHER declaration is named.
5
+ *
6
+ * The document, not the file: `Elem` carries no source path, and the map is a
7
+ * PROJECT — `architecture/landscape.likec4` plus every other `.likec4` under
8
+ * `architecture/` — so naming the landscape file was a guess that sent an author
9
+ * to a document that does not declare the element at all.
10
+ */
11
+ const MAP = "the fleet map (architecture/)";
12
+ export function divergedFindings(check) {
13
+ const { service, model, architecture, known } = check;
14
+ // An extending model declares each of these elements exactly once by
15
+ // construction — there is no copy to diverge — and the shapes' other grade
16
+ // (`c4.element-unowned`) is what asks its question.
17
+ if (model.shape !== "standalone")
18
+ return [];
19
+ if (model.doc.errors.length > 0)
20
+ return [];
21
+ if (architecture === null || architecture.errors.length > 0)
22
+ return [];
23
+ const index = joinIndex(architecture.elements, known);
24
+ const findings = [];
25
+ for (const mine of model.doc.elements) {
26
+ const theirs = counterpart(index, mine);
27
+ if (theirs === undefined)
28
+ continue;
29
+ const fields = differing(mine, theirs);
30
+ if (fields.length === 0)
31
+ continue;
32
+ // Where "copy the map's declaration verbatim" is a no-op: the tag sets are
33
+ // all that differ (so the two kinds are equal, and the block to open can be
34
+ // named) and copying the map's literal tags across would leave them still
35
+ // differing. `fields` is checked first because copying DOES fix a title or a
36
+ // binding, so the verbatim remedy stays right whenever one of those differs.
37
+ const specs = { mine: model.doc.specification, theirs: architecture.specification };
38
+ const inherited = fields.length === 1 && fields[0] === "tags" && copyIsNoOp(mine, theirs, specs)
39
+ ? declaringSide(mine.kind, specs)
40
+ : null;
41
+ findings.push({
42
+ severity: "warn",
43
+ code: "c4.declaration-diverged",
44
+ subject: service,
45
+ message: `${service}: ${ARTIFACT_FILES.model} declares '${mine.id}' as ${describe(mine)} and ` +
46
+ `${MAP} declares ${theirs.id === mine.id ? "it" : `'${theirs.id}'`} as ${describe(theirs)} — ` +
47
+ remedy(fields, mine.kind, inherited),
48
+ });
49
+ }
50
+ return findings;
51
+ }
52
+ /**
53
+ * What the message says after the two declarations: which fields differ, and
54
+ * what to do about it. `inherited` is null when copying the map's declaration
55
+ * fixes this, and otherwise the clause naming which document's `specification`
56
+ * puts the tags on the kind — the side an author has to open.
57
+ */
58
+ function remedy(fields, kind, inherited) {
59
+ // "the kind differs" / "the title differs" / "the tags differ": the verb
60
+ // agrees with the last field named, and `tags` is the one plural noun in the
61
+ // set. It shipped as "the kind differ", and a sentence a reader trips over is
62
+ // one they stop reading.
63
+ const plural = fields.length > 1 || fields[fields.length - 1] === "tags";
64
+ const named = `the ${fields.join(", ")} differ${plural ? "" : "s"}`;
65
+ // The two kinds are equal whenever `tags` is the only differing field, so the
66
+ // block to open can be named exactly.
67
+ if (inherited !== null) {
68
+ return (`${named}, and copying the map's declaration would not clear it: the sets come apart on ` +
69
+ `\`specification { element ${kind} { … } }\`, ${inherited}. Either match the two specification ` +
70
+ 'blocks on that kind, or migrate the model to extend the map (SCHEMA.md, "Two shapes of a service ' +
71
+ 'model") so there is one specification and one declaration');
72
+ }
73
+ return (`${named}, so two documents are two authorities on one element. Copy the map's declaration verbatim, or ` +
74
+ 'migrate the model to extend the map (SCHEMA.md, "Two shapes of a service model") so it is declared once');
75
+ }
76
+ function joinIndex(elements, known) {
77
+ // Which map elements are the fleet's own boxes rather than somebody's
78
+ // interior, by the ONE predicate every other fleet check asks it with
79
+ // (`fleet/census.ts`): a binding or a title naming a real services/<id>/ makes
80
+ // an element a service at any depth, and what sits inside one is that
81
+ // service's container. Everything else is fleet-level — a top-level element,
82
+ // or a box the map draws inside a plain grouping element — see the header.
83
+ const fleetLevel = new Set(serviceLevelElements([...elements], known).map((e) => e.id));
84
+ return {
85
+ byId: unique(elements, (e) => [e.id]),
86
+ byBinding: unique(elements, (e) => (e.service === undefined ? [] : [e.service])),
87
+ // Every DOTTED tail of the id, so a model's `paymentService.api` reaches the
88
+ // map's `marketplace.paymentService.api`: a tail carrying a dot names the
89
+ // owner as well as the leaf, so the two documents are talking about one
90
+ // element.
91
+ //
92
+ // The bare LAST segment names only the leaf, and it is emitted for
93
+ // FLEET-LEVEL boxes alone. This shipped unconditional, and the comment
94
+ // here claimed it was not: a standalone model's own `db`, `api` or `agent`
95
+ // joined whatever `<something>.<that name>` the map happened to hold — one
96
+ // service's private cache told to copy another service's store, verbatim.
97
+ // loam's own meta/docs hit it (`agent` ↔ `loam.core.agent`, a container of
98
+ // src/core/agent/), which is the case that made the rung wrong rather than
99
+ // merely risky (verification 2026-09-04).
100
+ //
101
+ // A box the map draws inside a plain GROUP still emits its bare segment,
102
+ // and deliberately: `infra.cache` is the fleet's cache, so a model's own
103
+ // top-level `cache` is a second meaning for one name and worth the warning.
104
+ // Grouping is a drawing convenience, not ownership — only a SERVICE owns an
105
+ // interior — so the guard is "no ancestor stands for a service" and not
106
+ // "the id carries no dot".
107
+ bySuffix: unique(elements, (e) => {
108
+ const segments = e.id.split(".");
109
+ const tails = segments.map((_, i) => segments.slice(i).join("."));
110
+ return fleetLevel.has(e.id) ? tails : tails.slice(0, -1);
111
+ }),
112
+ };
113
+ }
114
+ /** An index holding only the keys exactly ONE element answers to — a shared key joins nothing. */
115
+ function unique(elements, keys) {
116
+ const claims = new Map();
117
+ for (const element of elements) {
118
+ for (const key of keys(element)) {
119
+ const held = claims.get(key);
120
+ if (held === undefined)
121
+ claims.set(key, [element]);
122
+ else
123
+ held.push(element);
124
+ }
125
+ }
126
+ const index = new Map();
127
+ for (const [key, held] of claims)
128
+ if (held.length === 1)
129
+ index.set(key, held[0]);
130
+ return index;
131
+ }
132
+ /** The map's declaration of the element this model declares, or undefined when nothing joins. */
133
+ function counterpart(index, mine) {
134
+ const byId = index.byId.get(mine.id);
135
+ if (byId !== undefined)
136
+ return byId;
137
+ // The binding is the strongest evidence after the id: both documents wrote
138
+ // `metadata { service '<id>' }`, so both mean the same directory.
139
+ const bound = mine.service === undefined ? undefined : index.byBinding.get(mine.service);
140
+ if (bound !== undefined)
141
+ return bound;
142
+ return index.bySuffix.get(mine.id);
143
+ }
144
+ /** Which of the four compared fields disagree, in a fixed order so two runs read alike. */
145
+ function differing(mine, theirs) {
146
+ const fields = [];
147
+ if (mine.kind !== theirs.kind)
148
+ fields.push("kind");
149
+ if (mine.title !== theirs.title)
150
+ fields.push("title");
151
+ // A SET, sorted: tag order is authoring order and means nothing, and a model
152
+ // that lists the map's two tags the other way round is the same declaration.
153
+ if (tagList(mine) !== tagList(theirs))
154
+ fields.push("tags");
155
+ if (mine.service !== theirs.service)
156
+ fields.push("service binding");
157
+ return fields;
158
+ }
159
+ function tagList(e) {
160
+ return [...new Set(e.tags)].sort().join(" ");
161
+ }
162
+ /**
163
+ * Would "copy the map's declaration verbatim" leave the tag sets still
164
+ * differing? Answered by SIMULATING the copy, which is the only way to be right
165
+ * about it in both directions.
166
+ *
167
+ * `Elem.tags` is what LikeC4 hands over, and since 1.59.0 that includes every
168
+ * tag the element's kind declares (`core/c4/parsed/specification.ts` says why
169
+ * loam reads the block at all). Copying the map's DECLARATION copies its literal
170
+ * tags into the model and nothing else — the model keeps its own specification —
171
+ * so the model's element would come back carrying `mine's kind defaults ∪ the
172
+ * map's literal tags`, against the map's `its kind defaults ∪ the same literal
173
+ * tags`. Those differ exactly when the two kind defaults differ outside the
174
+ * copied literals, and then the remedy is a no-op.
175
+ *
176
+ * The first version compared the two LITERAL tag lists and switched arms only
177
+ * when they were equal, which caught one direction of the same case and missed
178
+ * its mirror: a model writing `#external` on an element whose map twin inherits
179
+ * `#external #platform` from `element topic { … }` was told to copy the map's
180
+ * bare line, and doing exactly that produced the OTHER arm of this same message
181
+ * (verification 2026-09-04, second pass, examples/docs order-service).
182
+ */
183
+ function copyIsNoOp(mine, theirs, specs) {
184
+ const copied = literalTags(theirs, specs.theirs);
185
+ const after = union(kindTags(mine.kind, specs.mine), copied);
186
+ const before = union(kindTags(theirs.kind, specs.theirs), copied);
187
+ return after !== before;
188
+ }
189
+ /**
190
+ * Which document's `specification` puts the tags on the kind — the half of the
191
+ * message that tells an author which file to open. "Both, differently" is a real
192
+ * state (each block declares its own tag on the same kind) and gets its own
193
+ * words rather than a guess at one side.
194
+ */
195
+ function declaringSide(kind, specs) {
196
+ const mine = kindTags(kind, specs.mine);
197
+ const theirs = kindTags(kind, specs.theirs);
198
+ if (mine.length > 0 && theirs.length > 0)
199
+ return "which the two documents declare different tags on";
200
+ if (theirs.length > 0)
201
+ return `which ${MAP} declares tags on and ${ARTIFACT_FILES.model} does not`;
202
+ if (mine.length > 0)
203
+ return `which ${ARTIFACT_FILES.model} declares tags on and ${MAP} does not`;
204
+ // No kind declares anything and the copy still fails: not reachable from the
205
+ // predicate above (with equal kinds and no defaults the copy always clears
206
+ // it), and a sentence that names no file beats one that names the wrong file.
207
+ return "which the two documents' blocks disagree on";
208
+ }
209
+ /** The tags `spec` puts on every element of `kind`, sorted — the defaults an element cannot see. */
210
+ function kindTags(kind, spec) {
211
+ return [...new Set(spec?.elementKindTags[kind] ?? [])].sort();
212
+ }
213
+ /** A tag SET as one comparable string; see `tagList` for why order is dropped. */
214
+ function union(a, b) {
215
+ return [...new Set([...a, ...b])].sort().join(" ");
216
+ }
217
+ function literalTags(e, spec) {
218
+ const inherited = new Set(kindTags(e.kind, spec));
219
+ return [...new Set(e.tags)].filter((tag) => !inherited.has(tag)).sort();
220
+ }
221
+ /** One element as the message names it — every compared field, in the order `differing` reports them. */
222
+ function describe(e) {
223
+ const tags = tagList(e);
224
+ return `${e.kind} '${e.title}' [${tags === "" ? "no tags" : tags}, bound to ${e.service ?? "unbound"}]`;
225
+ }
226
+ //# sourceMappingURL=diverged.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diverged.js","sourceRoot":"","sources":["../../../../../src/commands/validate/service/model/diverged.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `c4.declaration-diverged` — the check the \"every shared element is declared\n * once per document\" report asked for.\n *\n * A STANDALONE model has to re-declare every element it talks about: it is\n * parsed alone, so `kafka`, `uaa` and each peer service appear a second time,\n * with a second kind, a second title, a second tag list and a second binding.\n * Nothing compared the copies. Measured on the fleet that filed the report: 78\n * double declarations across 56 services, and the copies had already drifted —\n * `#platform` was on the map's elements and missing from the models'.\n *\n * WHAT IS COMPARED, and why exactly these four. `kind`, `title`, the tag SET and\n * the `metadata { service }` binding each change what loam concludes or what a\n * view shows: the kind decides which specification rule applies and which\n * exemptions (`ACTOR_KINDS`, `#external`) fire, the title is a resolver fallback\n * when nothing is bound, a tag is graded (`#external`, `#obl-…`), and the\n * binding decides which directory an edge is filed under. `description` is\n * deliberately NOT compared: it is prose, nothing joins on it, and reporting two\n * differently-worded sentences as a divergence would train a reader to ignore\n * the code.\n *\n * WHICH TWO DECLARATIONS ARE ONE ELEMENT is `counterpart` below, and it is the\n * half the first release got wrong: it joined on the literal id, so in a GROUPED\n * map — one that nests its services under `marketplace`, as loam's own example\n * does — a model's `paymentService` never met the map's\n * `marketplace.paymentService` and the check was silent on every fleet that\n * groups (verification 2026-09-04, W3). The three rungs are ordered by how much\n * they assume: the id, then the `metadata { service }` binding both sides wrote,\n * then a unique dotted TAIL of the map's id. Ambiguity is never resolved by\n * picking one — a key two map elements answer to joins nothing, because a\n * divergence reported against the wrong peer is worse than the silence. And the\n * BARE last segment is a tail only when the map element it names is a\n * FLEET-LEVEL box: see `joinIndex`, where the first release of the tail rung\n * joined one service's `db` to another service's.\n *\n * WHAT \"FLEET-LEVEL\" MEANS, spelled once here because three pages spelled it\n * differently and all three were wrong (verification 2026-09-04, second pass):\n * a map element NO ANCESTOR of which stands for a service — `serviceLevelElements`,\n * the one predicate every fleet check asks this question with. That is a\n * top-level element, and equally a child of a plain grouping element: a map\n * that draws `infra = group 'Infra' { cache = database … }` is drawing the\n * fleet's cache, at fleet level, and a standalone model that declares its own\n * top-level `cache` IS shadowing that box — the two documents give one name two\n * meanings, which is the thing this code exists to report. What the rung must\n * never reach is an element drawn INSIDE a service's own element: that is\n * somebody's interior, it belongs to that service, and a model's private `db`\n * being told to copy another service's `db` verbatim is the wrong-join class\n * the tail rung was restricted for in the first place.\n *\n * SILENT WHEN THE MAP DOES NOT PARSE, and when the model does not: a diff\n * against half a document is invention, and both states already have a finding\n * of their own.\n *\n * The repair has two forms on purpose. Copying the map's declaration verbatim\n * keeps the standalone shape, which is legal forever; migrating the model to\n * extend the map removes the copy altogether, which is the only fix that cannot\n * drift again. Except where the first repair is a no-op, and `copyIsNoOp`\n * decides that by SIMULATING it rather than by pattern-matching one shape of it:\n * a tag difference that survives the copy comes off the two documents'\n * `specification` blocks, so the message names the block instead.\n */\nimport type { Elem, LoadedDoc } from \"../../../../core/c4/likec4.js\";\nimport type { DocSpecification } from \"../../../../core/c4/parsed/specification.js\";\nimport type { ServiceModel } from \"../../../../core/c4/service-model/load.js\";\nimport type { PathableService } from \"../../../../core/kernel/ids/service.js\";\nimport { ARTIFACT_FILES } from \"../../../../core/repo/paths.js\";\nimport type { Finding } from \"../../../../core/vocabulary/report.js\";\nimport { serviceLevelElements } from \"../../fleet/census.js\";\n\n/**\n * How the OTHER declaration is named.\n *\n * The document, not the file: `Elem` carries no source path, and the map is a\n * PROJECT — `architecture/landscape.likec4` plus every other `.likec4` under\n * `architecture/` — so naming the landscape file was a guess that sent an author\n * to a document that does not declare the element at all.\n */\nconst MAP = \"the fleet map (architecture/)\";\n\nexport interface DivergenceCheck {\n service: PathableService;\n model: ServiceModel;\n /** The `architecture/` project — the map as every other fleet check reads it. Null when the repo has none. */\n architecture: LoadedDoc | null;\n /**\n * Every `services/<id>/` that exists — the census's positive evidence, which\n * is what tells a map's fleet-level box from a container drawn inside a\n * service. Only the bare-last-segment tail join reads it; see `joinIndex`.\n */\n known: ReadonlySet<string>;\n}\n\nexport function divergedFindings(check: DivergenceCheck): Finding[] {\n const { service, model, architecture, known } = check;\n // An extending model declares each of these elements exactly once by\n // construction — there is no copy to diverge — and the shapes' other grade\n // (`c4.element-unowned`) is what asks its question.\n if (model.shape !== \"standalone\") return [];\n if (model.doc.errors.length > 0) return [];\n if (architecture === null || architecture.errors.length > 0) return [];\n\n const index = joinIndex(architecture.elements, known);\n const findings: Finding[] = [];\n for (const mine of model.doc.elements) {\n const theirs = counterpart(index, mine);\n if (theirs === undefined) continue;\n const fields = differing(mine, theirs);\n if (fields.length === 0) continue;\n // Where \"copy the map's declaration verbatim\" is a no-op: the tag sets are\n // all that differ (so the two kinds are equal, and the block to open can be\n // named) and copying the map's literal tags across would leave them still\n // differing. `fields` is checked first because copying DOES fix a title or a\n // binding, so the verbatim remedy stays right whenever one of those differs.\n const specs = { mine: model.doc.specification, theirs: architecture.specification };\n const inherited =\n fields.length === 1 && fields[0] === \"tags\" && copyIsNoOp(mine, theirs, specs)\n ? declaringSide(mine.kind, specs)\n : null;\n findings.push({\n severity: \"warn\",\n code: \"c4.declaration-diverged\",\n subject: service,\n message:\n `${service}: ${ARTIFACT_FILES.model} declares '${mine.id}' as ${describe(mine)} and ` +\n `${MAP} declares ${theirs.id === mine.id ? \"it\" : `'${theirs.id}'`} as ${describe(theirs)} — ` +\n remedy(fields, mine.kind, inherited),\n });\n }\n return findings;\n}\n\n/**\n * What the message says after the two declarations: which fields differ, and\n * what to do about it. `inherited` is null when copying the map's declaration\n * fixes this, and otherwise the clause naming which document's `specification`\n * puts the tags on the kind — the side an author has to open.\n */\nfunction remedy(fields: string[], kind: string, inherited: string | null): string {\n // \"the kind differs\" / \"the title differs\" / \"the tags differ\": the verb\n // agrees with the last field named, and `tags` is the one plural noun in the\n // set. It shipped as \"the kind differ\", and a sentence a reader trips over is\n // one they stop reading.\n const plural = fields.length > 1 || fields[fields.length - 1] === \"tags\";\n const named = `the ${fields.join(\", \")} differ${plural ? \"\" : \"s\"}`;\n // The two kinds are equal whenever `tags` is the only differing field, so the\n // block to open can be named exactly.\n if (inherited !== null) {\n return (\n `${named}, and copying the map's declaration would not clear it: the sets come apart on ` +\n `\\`specification { element ${kind} { … } }\\`, ${inherited}. Either match the two specification ` +\n 'blocks on that kind, or migrate the model to extend the map (SCHEMA.md, \"Two shapes of a service ' +\n 'model\") so there is one specification and one declaration'\n );\n }\n return (\n `${named}, so two documents are two authorities on one element. Copy the map's declaration verbatim, or ` +\n 'migrate the model to extend the map (SCHEMA.md, \"Two shapes of a service model\") so it is declared once'\n );\n}\n\n/** The map's elements, indexed by each key `counterpart` may join on — ambiguous keys dropped. */\ninterface JoinIndex {\n byId: Map<string, Elem>;\n byBinding: Map<string, Elem>;\n bySuffix: Map<string, Elem>;\n}\n\nfunction joinIndex(elements: readonly Elem[], known: ReadonlySet<string>): JoinIndex {\n // Which map elements are the fleet's own boxes rather than somebody's\n // interior, by the ONE predicate every other fleet check asks it with\n // (`fleet/census.ts`): a binding or a title naming a real services/<id>/ makes\n // an element a service at any depth, and what sits inside one is that\n // service's container. Everything else is fleet-level — a top-level element,\n // or a box the map draws inside a plain grouping element — see the header.\n const fleetLevel = new Set(serviceLevelElements([...elements], known).map((e) => e.id));\n return {\n byId: unique(elements, (e) => [e.id]),\n byBinding: unique(elements, (e) => (e.service === undefined ? [] : [e.service as string])),\n // Every DOTTED tail of the id, so a model's `paymentService.api` reaches the\n // map's `marketplace.paymentService.api`: a tail carrying a dot names the\n // owner as well as the leaf, so the two documents are talking about one\n // element.\n //\n // The bare LAST segment names only the leaf, and it is emitted for\n // FLEET-LEVEL boxes alone. This shipped unconditional, and the comment\n // here claimed it was not: a standalone model's own `db`, `api` or `agent`\n // joined whatever `<something>.<that name>` the map happened to hold — one\n // service's private cache told to copy another service's store, verbatim.\n // loam's own meta/docs hit it (`agent` ↔ `loam.core.agent`, a container of\n // src/core/agent/), which is the case that made the rung wrong rather than\n // merely risky (verification 2026-09-04).\n //\n // A box the map draws inside a plain GROUP still emits its bare segment,\n // and deliberately: `infra.cache` is the fleet's cache, so a model's own\n // top-level `cache` is a second meaning for one name and worth the warning.\n // Grouping is a drawing convenience, not ownership — only a SERVICE owns an\n // interior — so the guard is \"no ancestor stands for a service\" and not\n // \"the id carries no dot\".\n bySuffix: unique(elements, (e) => {\n const segments = e.id.split(\".\");\n const tails = segments.map((_, i) => segments.slice(i).join(\".\"));\n return fleetLevel.has(e.id) ? tails : tails.slice(0, -1);\n }),\n };\n}\n\n/** An index holding only the keys exactly ONE element answers to — a shared key joins nothing. */\nfunction unique(elements: readonly Elem[], keys: (e: Elem) => string[]): Map<string, Elem> {\n const claims = new Map<string, Elem[]>();\n for (const element of elements) {\n for (const key of keys(element)) {\n const held = claims.get(key);\n if (held === undefined) claims.set(key, [element]);\n else held.push(element);\n }\n }\n const index = new Map<string, Elem>();\n for (const [key, held] of claims) if (held.length === 1) index.set(key, held[0]!);\n return index;\n}\n\n/** The map's declaration of the element this model declares, or undefined when nothing joins. */\nfunction counterpart(index: JoinIndex, mine: Elem): Elem | undefined {\n const byId = index.byId.get(mine.id);\n if (byId !== undefined) return byId;\n // The binding is the strongest evidence after the id: both documents wrote\n // `metadata { service '<id>' }`, so both mean the same directory.\n const bound = mine.service === undefined ? undefined : index.byBinding.get(mine.service as string);\n if (bound !== undefined) return bound;\n return index.bySuffix.get(mine.id);\n}\n\n/** Which of the four compared fields disagree, in a fixed order so two runs read alike. */\nfunction differing(mine: Elem, theirs: Elem): string[] {\n const fields: string[] = [];\n if (mine.kind !== theirs.kind) fields.push(\"kind\");\n if (mine.title !== theirs.title) fields.push(\"title\");\n // A SET, sorted: tag order is authoring order and means nothing, and a model\n // that lists the map's two tags the other way round is the same declaration.\n if (tagList(mine) !== tagList(theirs)) fields.push(\"tags\");\n if (mine.service !== theirs.service) fields.push(\"service binding\");\n return fields;\n}\n\nfunction tagList(e: Elem): string {\n return [...new Set(e.tags)].sort().join(\" \");\n}\n\n/** The two documents' `specification` blocks, as `copyIsNoOp` and `declaringSide` read them. */\ninterface SpecPair {\n mine: DocSpecification | undefined;\n theirs: DocSpecification | undefined;\n}\n\n/**\n * Would \"copy the map's declaration verbatim\" leave the tag sets still\n * differing? Answered by SIMULATING the copy, which is the only way to be right\n * about it in both directions.\n *\n * `Elem.tags` is what LikeC4 hands over, and since 1.59.0 that includes every\n * tag the element's kind declares (`core/c4/parsed/specification.ts` says why\n * loam reads the block at all). Copying the map's DECLARATION copies its literal\n * tags into the model and nothing else — the model keeps its own specification —\n * so the model's element would come back carrying `mine's kind defaults ∪ the\n * map's literal tags`, against the map's `its kind defaults ∪ the same literal\n * tags`. Those differ exactly when the two kind defaults differ outside the\n * copied literals, and then the remedy is a no-op.\n *\n * The first version compared the two LITERAL tag lists and switched arms only\n * when they were equal, which caught one direction of the same case and missed\n * its mirror: a model writing `#external` on an element whose map twin inherits\n * `#external #platform` from `element topic { … }` was told to copy the map's\n * bare line, and doing exactly that produced the OTHER arm of this same message\n * (verification 2026-09-04, second pass, examples/docs order-service).\n */\nfunction copyIsNoOp(mine: Elem, theirs: Elem, specs: SpecPair): boolean {\n const copied = literalTags(theirs, specs.theirs);\n const after = union(kindTags(mine.kind, specs.mine), copied);\n const before = union(kindTags(theirs.kind, specs.theirs), copied);\n return after !== before;\n}\n\n/**\n * Which document's `specification` puts the tags on the kind — the half of the\n * message that tells an author which file to open. \"Both, differently\" is a real\n * state (each block declares its own tag on the same kind) and gets its own\n * words rather than a guess at one side.\n */\nfunction declaringSide(kind: string, specs: SpecPair): string {\n const mine = kindTags(kind, specs.mine);\n const theirs = kindTags(kind, specs.theirs);\n if (mine.length > 0 && theirs.length > 0) return \"which the two documents declare different tags on\";\n if (theirs.length > 0) return `which ${MAP} declares tags on and ${ARTIFACT_FILES.model} does not`;\n if (mine.length > 0) return `which ${ARTIFACT_FILES.model} declares tags on and ${MAP} does not`;\n // No kind declares anything and the copy still fails: not reachable from the\n // predicate above (with equal kinds and no defaults the copy always clears\n // it), and a sentence that names no file beats one that names the wrong file.\n return \"which the two documents' blocks disagree on\";\n}\n\n/** The tags `spec` puts on every element of `kind`, sorted — the defaults an element cannot see. */\nfunction kindTags(kind: string, spec: DocSpecification | undefined): string[] {\n return [...new Set(spec?.elementKindTags[kind] ?? [])].sort();\n}\n\n/** A tag SET as one comparable string; see `tagList` for why order is dropped. */\nfunction union(a: readonly string[], b: readonly string[]): string {\n return [...new Set([...a, ...b])].sort().join(\" \");\n}\n\nfunction literalTags(e: Elem, spec: DocSpecification | undefined): string[] {\n const inherited = new Set(kindTags(e.kind, spec));\n return [...new Set(e.tags)].filter((tag) => !inherited.has(tag)).sort();\n}\n\n/** One element as the message names it — every compared field, in the order `differing` reports them. */\nfunction describe(e: Elem): string {\n const tags = tagList(e);\n return `${e.kind} '${e.title}' [${tags === \"\" ? \"no tags\" : tags}, bound to ${e.service ?? \"unbound\"}]`;\n}\n"]}