@ybotok/loam 0.1.0-beta.3 → 0.2.0-alpha.1

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 (1026) hide show
  1. package/CHANGELOG.md +2548 -86
  2. package/COMPARISON.md +80 -63
  3. package/CONTRIBUTING.md +84 -0
  4. package/MIGRATING-from-OpenSpec.md +213 -54
  5. package/QUICKSTART.md +125 -0
  6. package/README.md +450 -150
  7. package/ROADMAP.md +494 -0
  8. package/SCHEMA.md +2355 -256
  9. package/SECURITY.md +21 -3
  10. package/WORKFLOW.md +701 -0
  11. package/dist/cli.js +113 -19
  12. package/dist/cli.js.map +1 -1
  13. package/dist/commands/adopt/adopt.js +209 -0
  14. package/dist/commands/adopt/adopt.js.map +1 -0
  15. package/dist/commands/adopt/render.js +268 -0
  16. package/dist/commands/adopt/render.js.map +1 -0
  17. package/dist/commands/archive/archive.js +77 -0
  18. package/dist/commands/archive/archive.js.map +1 -0
  19. package/dist/commands/archive/plan/contracts/asyncapi.js +178 -0
  20. package/dist/commands/archive/plan/contracts/asyncapi.js.map +1 -0
  21. package/dist/commands/archive/plan/contracts/openapi.js +159 -0
  22. package/dist/commands/archive/plan/contracts/openapi.js.map +1 -0
  23. package/dist/commands/archive/plan/gate.js +317 -0
  24. package/dist/commands/archive/plan/gate.js.map +1 -0
  25. package/dist/commands/archive/plan/landscape.js +161 -0
  26. package/dist/commands/archive/plan/landscape.js.map +1 -0
  27. package/dist/commands/archive/plan/refusal.js +111 -0
  28. package/dist/commands/archive/plan/refusal.js.map +1 -0
  29. package/dist/commands/archive/plan/specs.js +237 -0
  30. package/dist/commands/archive/plan/specs.js.map +1 -0
  31. package/dist/commands/archive/plan/state.js +27 -0
  32. package/dist/commands/archive/plan/state.js.map +1 -0
  33. package/dist/commands/archive/run.js +251 -0
  34. package/dist/commands/archive/run.js.map +1 -0
  35. package/dist/commands/context/context.js +99 -0
  36. package/dist/commands/context/context.js.map +1 -0
  37. package/dist/commands/context/print.js +283 -0
  38. package/dist/commands/context/print.js.map +1 -0
  39. package/dist/commands/delta/delta.js +279 -0
  40. package/dist/commands/delta/delta.js.map +1 -0
  41. package/dist/commands/delta/print.js +205 -0
  42. package/dist/commands/delta/print.js.map +1 -0
  43. package/dist/commands/dependencies.js +9 -7
  44. package/dist/commands/dependencies.js.map +1 -1
  45. package/dist/commands/diff/diff.js +93 -0
  46. package/dist/commands/diff/diff.js.map +1 -0
  47. package/dist/commands/diff/print.js +38 -0
  48. package/dist/commands/diff/print.js.map +1 -0
  49. package/dist/commands/doctor.js +5 -4
  50. package/dist/commands/doctor.js.map +1 -1
  51. package/dist/commands/explain/explain.js +151 -0
  52. package/dist/commands/explain/explain.js.map +1 -0
  53. package/dist/commands/explore.js +29 -24
  54. package/dist/commands/explore.js.map +1 -1
  55. package/dist/commands/gate/gate.js +115 -0
  56. package/dist/commands/gate/gate.js.map +1 -0
  57. package/dist/commands/gate/print.js +54 -0
  58. package/dist/commands/gate/print.js.map +1 -0
  59. package/dist/commands/gherkin/commit.js +146 -0
  60. package/dist/commands/gherkin/commit.js.map +1 -0
  61. package/dist/commands/gherkin/gherkin.js +246 -0
  62. package/dist/commands/gherkin/gherkin.js.map +1 -0
  63. package/dist/commands/gherkin/reconcile.js +149 -0
  64. package/dist/commands/gherkin/reconcile.js.map +1 -0
  65. package/dist/commands/gherkin/render.js +77 -0
  66. package/dist/commands/gherkin/render.js.map +1 -0
  67. package/dist/commands/init/example.js +204 -0
  68. package/dist/commands/init/example.js.map +1 -0
  69. package/dist/commands/init/first-hour.js +28 -0
  70. package/dist/commands/init/first-hour.js.map +1 -0
  71. package/dist/commands/{init.js → init/init.js} +146 -71
  72. package/dist/commands/init/init.js.map +1 -0
  73. package/dist/commands/init/mcp.js +131 -0
  74. package/dist/commands/init/mcp.js.map +1 -0
  75. package/dist/commands/init/options.js +78 -0
  76. package/dist/commands/init/options.js.map +1 -0
  77. package/dist/commands/instructions.js +72 -14
  78. package/dist/commands/instructions.js.map +1 -1
  79. package/dist/commands/list/campaign/campaign.js +65 -0
  80. package/dist/commands/list/campaign/campaign.js.map +1 -0
  81. package/dist/commands/list/campaign/owners.js +65 -0
  82. package/dist/commands/list/campaign/owners.js.map +1 -0
  83. package/dist/commands/list/json.js +157 -0
  84. package/dist/commands/list/json.js.map +1 -0
  85. package/dist/commands/list/list.js +343 -0
  86. package/dist/commands/list/list.js.map +1 -0
  87. package/dist/commands/list/print.js +301 -0
  88. package/dist/commands/list/print.js.map +1 -0
  89. package/dist/commands/list/review.js +120 -0
  90. package/dist/commands/list/review.js.map +1 -0
  91. package/dist/commands/list/views.js +105 -0
  92. package/dist/commands/list/views.js.map +1 -0
  93. package/dist/commands/mcp/dispatch.js +183 -0
  94. package/dist/commands/mcp/dispatch.js.map +1 -0
  95. package/dist/commands/mcp/mcp.js +34 -0
  96. package/dist/commands/mcp/mcp.js.map +1 -0
  97. package/dist/commands/mcp/serve.js +55 -0
  98. package/dist/commands/mcp/serve.js.map +1 -0
  99. package/dist/commands/migrate-openspec/materialize/active.js +170 -0
  100. package/dist/commands/migrate-openspec/materialize/active.js.map +1 -0
  101. package/dist/commands/migrate-openspec/materialize/feature.js +41 -0
  102. package/dist/commands/migrate-openspec/materialize/feature.js.map +1 -0
  103. package/dist/commands/migrate-openspec/materialize/living.js +62 -0
  104. package/dist/commands/migrate-openspec/materialize/living.js.map +1 -0
  105. package/dist/commands/migrate-openspec/materialize/stage.js +142 -0
  106. package/dist/commands/migrate-openspec/materialize/stage.js.map +1 -0
  107. package/dist/commands/migrate-openspec/materialize/target.js +219 -0
  108. package/dist/commands/migrate-openspec/materialize/target.js.map +1 -0
  109. package/dist/commands/migrate-openspec/migrate-openspec.js +142 -0
  110. package/dist/commands/migrate-openspec/migrate-openspec.js.map +1 -0
  111. package/dist/commands/migrate-openspec/openspec/decisions.js +91 -0
  112. package/dist/commands/migrate-openspec/openspec/decisions.js.map +1 -0
  113. package/dist/commands/migrate-openspec/openspec/error.js +19 -0
  114. package/dist/commands/migrate-openspec/openspec/error.js.map +1 -0
  115. package/dist/commands/migrate-openspec/openspec/mapping.js +170 -0
  116. package/dist/commands/migrate-openspec/openspec/mapping.js.map +1 -0
  117. package/dist/commands/migrate-openspec/openspec/paths.js +43 -0
  118. package/dist/commands/migrate-openspec/openspec/paths.js.map +1 -0
  119. package/dist/commands/migrate-openspec/openspec/read.js +49 -0
  120. package/dist/commands/migrate-openspec/openspec/read.js.map +1 -0
  121. package/dist/commands/migrate-openspec/print.js +89 -0
  122. package/dist/commands/migrate-openspec/print.js.map +1 -0
  123. package/dist/commands/new/commit.js +76 -0
  124. package/dist/commands/new/commit.js.map +1 -0
  125. package/dist/commands/new/new.js +283 -0
  126. package/dist/commands/new/new.js.map +1 -0
  127. package/dist/commands/new/templates.js +355 -0
  128. package/dist/commands/new/templates.js.map +1 -0
  129. package/dist/commands/open.js +203 -0
  130. package/dist/commands/open.js.map +1 -0
  131. package/dist/commands/policy/format.js +152 -0
  132. package/dist/commands/policy/format.js.map +1 -0
  133. package/dist/commands/{docs-repo-gate.js → policy/gate.js} +11 -11
  134. package/dist/commands/policy/gate.js.map +1 -0
  135. package/dist/commands/rebase/edit.js +106 -0
  136. package/dist/commands/rebase/edit.js.map +1 -0
  137. package/dist/commands/rebase/living.js +185 -0
  138. package/dist/commands/rebase/living.js.map +1 -0
  139. package/dist/commands/rebase/plan.js +245 -0
  140. package/dist/commands/rebase/plan.js.map +1 -0
  141. package/dist/commands/rebase/rebase.js +275 -0
  142. package/dist/commands/rebase/rebase.js.map +1 -0
  143. package/dist/commands/seed/commit.js +192 -0
  144. package/dist/commands/seed/commit.js.map +1 -0
  145. package/dist/commands/seed/plan.js +133 -0
  146. package/dist/commands/seed/plan.js.map +1 -0
  147. package/dist/commands/seed/seed.js +172 -0
  148. package/dist/commands/seed/seed.js.map +1 -0
  149. package/dist/commands/show/feature.js +178 -0
  150. package/dist/commands/show/feature.js.map +1 -0
  151. package/dist/commands/show/marks.js +24 -0
  152. package/dist/commands/show/marks.js.map +1 -0
  153. package/dist/commands/{show.js → show/service.js} +63 -152
  154. package/dist/commands/show/service.js.map +1 -0
  155. package/dist/commands/show/show.js +77 -0
  156. package/dist/commands/show/show.js.map +1 -0
  157. package/dist/commands/status/json.js +45 -0
  158. package/dist/commands/status/json.js.map +1 -0
  159. package/dist/commands/status/print.js +157 -0
  160. package/dist/commands/status/print.js.map +1 -0
  161. package/dist/commands/status/status.js +119 -0
  162. package/dist/commands/status/status.js.map +1 -0
  163. package/dist/commands/steps/steps.js +189 -0
  164. package/dist/commands/steps/steps.js.map +1 -0
  165. package/dist/commands/subsystem/edit.js +192 -0
  166. package/dist/commands/subsystem/edit.js.map +1 -0
  167. package/dist/commands/subsystem/move.js +265 -0
  168. package/dist/commands/subsystem/move.js.map +1 -0
  169. package/dist/commands/subsystem/query.js +115 -0
  170. package/dist/commands/subsystem/query.js.map +1 -0
  171. package/dist/commands/subsystem/subsystem.js +101 -0
  172. package/dist/commands/subsystem/subsystem.js.map +1 -0
  173. package/dist/commands/subsystem/sync.js +103 -0
  174. package/dist/commands/subsystem/sync.js.map +1 -0
  175. package/dist/commands/subsystem/txn/txn.js +94 -0
  176. package/dist/commands/subsystem/txn/txn.js.map +1 -0
  177. package/dist/commands/subsystem/txn/views.js +70 -0
  178. package/dist/commands/subsystem/txn/views.js.map +1 -0
  179. package/dist/commands/unarchive/manifest.js +160 -0
  180. package/dist/commands/unarchive/manifest.js.map +1 -0
  181. package/dist/commands/{unarchive.js → unarchive/restore.js} +47 -160
  182. package/dist/commands/unarchive/restore.js.map +1 -0
  183. package/dist/commands/unarchive/unarchive.js +67 -0
  184. package/dist/commands/unarchive/unarchive.js.map +1 -0
  185. package/dist/commands/validate/arch-coverage.js +194 -0
  186. package/dist/commands/validate/arch-coverage.js.map +1 -0
  187. package/dist/commands/validate/checks/fleet-shape.js +296 -0
  188. package/dist/commands/validate/checks/fleet-shape.js.map +1 -0
  189. package/dist/commands/validate/checks/health-deps.js +55 -0
  190. package/dist/commands/validate/checks/health-deps.js.map +1 -0
  191. package/dist/commands/validate/checks/requirements.js +254 -0
  192. package/dist/commands/validate/checks/requirements.js.map +1 -0
  193. package/dist/commands/validate/checks/sources.js +76 -0
  194. package/dist/commands/validate/checks/sources.js.map +1 -0
  195. package/dist/commands/validate/checks/vocabulary.js +31 -0
  196. package/dist/commands/validate/checks/vocabulary.js.map +1 -0
  197. package/dist/commands/validate/feature.js +216 -0
  198. package/dist/commands/validate/feature.js.map +1 -0
  199. package/dist/commands/validate/fleet/census.js +69 -0
  200. package/dist/commands/validate/fleet/census.js.map +1 -0
  201. package/dist/commands/validate/fleet/kind-tags.js +39 -0
  202. package/dist/commands/validate/fleet/kind-tags.js.map +1 -0
  203. package/dist/commands/validate/fleet/landscape.js +353 -0
  204. package/dist/commands/validate/fleet/landscape.js.map +1 -0
  205. package/dist/commands/validate/fleet/load.js +52 -0
  206. package/dist/commands/validate/fleet/load.js.map +1 -0
  207. package/dist/commands/validate/fleet/obligations.js +236 -0
  208. package/dist/commands/validate/fleet/obligations.js.map +1 -0
  209. package/dist/commands/validate/fleet/scorecard/adoption.js +102 -0
  210. package/dist/commands/validate/fleet/scorecard/adoption.js.map +1 -0
  211. package/dist/commands/validate/fleet/scorecard/contracts.js +98 -0
  212. package/dist/commands/validate/fleet/scorecard/contracts.js.map +1 -0
  213. package/dist/commands/validate/fleet/scorecard/print.js +63 -0
  214. package/dist/commands/validate/fleet/scorecard/print.js.map +1 -0
  215. package/dist/commands/validate/fleet/scorecard/scorecard.js +156 -0
  216. package/dist/commands/validate/fleet/scorecard/scorecard.js.map +1 -0
  217. package/dist/commands/validate/fleet/usecases/capability-tag.js +94 -0
  218. package/dist/commands/validate/fleet/usecases/capability-tag.js.map +1 -0
  219. package/dist/commands/validate/fleet/usecases/place.js +13 -0
  220. package/dist/commands/validate/fleet/usecases/place.js.map +1 -0
  221. package/dist/commands/validate/fleet/usecases/requirement-tag.js +95 -0
  222. package/dist/commands/validate/fleet/usecases/requirement-tag.js.map +1 -0
  223. package/dist/commands/validate/fleet/usecases/steps.js +197 -0
  224. package/dist/commands/validate/fleet/usecases/steps.js.map +1 -0
  225. package/dist/commands/validate/fleet/usecases/usecases.js +99 -0
  226. package/dist/commands/validate/fleet/usecases/usecases.js.map +1 -0
  227. package/dist/commands/validate/fleet/views/ids.js +40 -0
  228. package/dist/commands/validate/fleet/views/ids.js.map +1 -0
  229. package/dist/commands/validate/fleet/views/stale.js +59 -0
  230. package/dist/commands/validate/fleet/views/stale.js.map +1 -0
  231. package/dist/commands/validate/links/corpus.js +92 -0
  232. package/dist/commands/validate/links/corpus.js.map +1 -0
  233. package/dist/commands/validate/links/glossary.js +75 -0
  234. package/dist/commands/validate/links/glossary.js.map +1 -0
  235. package/dist/commands/validate/report.js +269 -0
  236. package/dist/commands/validate/report.js.map +1 -0
  237. package/dist/commands/validate/service/api.js +338 -0
  238. package/dist/commands/validate/service/api.js.map +1 -0
  239. package/dist/commands/validate/service/events/events.js +219 -0
  240. package/dist/commands/validate/service/events/events.js.map +1 -0
  241. package/dist/commands/validate/service/events/message-producers.js +77 -0
  242. package/dist/commands/validate/service/events/message-producers.js.map +1 -0
  243. package/dist/commands/validate/service/evidence-pins.js +131 -0
  244. package/dist/commands/validate/service/evidence-pins.js.map +1 -0
  245. package/dist/commands/validate/service/service.js +250 -0
  246. package/dist/commands/validate/service/service.js.map +1 -0
  247. package/dist/commands/validate/service/specs.js +219 -0
  248. package/dist/commands/validate/service/specs.js.map +1 -0
  249. package/dist/commands/validate/service/spine.js +113 -0
  250. package/dist/commands/validate/service/spine.js.map +1 -0
  251. package/dist/commands/validate/validate.js +338 -0
  252. package/dist/commands/validate/validate.js.map +1 -0
  253. package/dist/commands/verify/cross/diff.js +182 -0
  254. package/dist/commands/verify/cross/diff.js.map +1 -0
  255. package/dist/commands/verify/evidence/contract.js +32 -0
  256. package/dist/commands/verify/evidence/contract.js.map +1 -0
  257. package/dist/commands/verify/evidence/pins.js +52 -0
  258. package/dist/commands/verify/evidence/pins.js.map +1 -0
  259. package/dist/commands/verify/evidence/read.js +72 -0
  260. package/dist/commands/verify/evidence/read.js.map +1 -0
  261. package/dist/commands/verify/frozen.js +241 -0
  262. package/dist/commands/verify/frozen.js.map +1 -0
  263. package/dist/commands/verify/record.js +226 -0
  264. package/dist/commands/verify/record.js.map +1 -0
  265. package/dist/commands/verify/report.js +223 -0
  266. package/dist/commands/verify/report.js.map +1 -0
  267. package/dist/commands/verify/results.js +246 -0
  268. package/dist/commands/verify/results.js.map +1 -0
  269. package/dist/commands/verify/verify.js +217 -0
  270. package/dist/commands/verify/verify.js.map +1 -0
  271. package/dist/commands/vouch/contract.js +11 -0
  272. package/dist/commands/vouch/contract.js.map +1 -0
  273. package/dist/commands/vouch/pack/contract.js +2 -0
  274. package/dist/commands/vouch/pack/contract.js.map +1 -0
  275. package/dist/commands/vouch/pack/pack.js +266 -0
  276. package/dist/commands/vouch/pack/pack.js.map +1 -0
  277. package/dist/commands/vouch/pack/print.js +271 -0
  278. package/dist/commands/vouch/pack/print.js.map +1 -0
  279. package/dist/commands/vouch/pack/sections.js +142 -0
  280. package/dist/commands/vouch/pack/sections.js.map +1 -0
  281. package/dist/commands/vouch/prompt/confirm.js +46 -0
  282. package/dist/commands/vouch/prompt/confirm.js.map +1 -0
  283. package/dist/commands/vouch/report.js +101 -0
  284. package/dist/commands/vouch/report.js.map +1 -0
  285. package/dist/commands/vouch/run.js +285 -0
  286. package/dist/commands/vouch/run.js.map +1 -0
  287. package/dist/commands/vouch/sample/plan.js +125 -0
  288. package/dist/commands/vouch/sample/plan.js.map +1 -0
  289. package/dist/commands/vouch/sample/print.js +109 -0
  290. package/dist/commands/vouch/sample/print.js.map +1 -0
  291. package/dist/commands/vouch/vet/verify.js +123 -0
  292. package/dist/commands/vouch/vet/verify.js.map +1 -0
  293. package/dist/commands/vouch/vouch.js +176 -0
  294. package/dist/commands/vouch/vouch.js.map +1 -0
  295. package/dist/core/agent/agents-md/artifacts.js +220 -0
  296. package/dist/core/agent/agents-md/artifacts.js.map +1 -0
  297. package/dist/core/agent/agents-md/command-map.js +324 -0
  298. package/dist/core/agent/agents-md/command-map.js.map +1 -0
  299. package/dist/core/agent/agents-md/cycle.js +165 -0
  300. package/dist/core/agent/agents-md/cycle.js.map +1 -0
  301. package/dist/core/agent/agents-md/map/explain.js +34 -0
  302. package/dist/core/agent/agents-md/map/explain.js.map +1 -0
  303. package/dist/core/agent/agents-md/map/lenses/context.js +41 -0
  304. package/dist/core/agent/agents-md/map/lenses/context.js.map +1 -0
  305. package/dist/core/agent/agents-md/map/lenses/diff.js +46 -0
  306. package/dist/core/agent/agents-md/map/lenses/diff.js.map +1 -0
  307. package/dist/core/agent/agents-md/map/lenses/gate.js +57 -0
  308. package/dist/core/agent/agents-md/map/lenses/gate.js.map +1 -0
  309. package/dist/core/agent/agents-md/map/mcp.js +41 -0
  310. package/dist/core/agent/agents-md/map/mcp.js.map +1 -0
  311. package/dist/core/agent/agents-md/map/status.js +62 -0
  312. package/dist/core/agent/agents-md/map/status.js.map +1 -0
  313. package/dist/core/agent/agents-md/map/subsystem.js +32 -0
  314. package/dist/core/agent/agents-md/map/subsystem.js.map +1 -0
  315. package/dist/core/agent/agents-md/map/usecases.js +60 -0
  316. package/dist/core/agent/agents-md/map/usecases.js.map +1 -0
  317. package/dist/core/agent/agents-md/refusals.js +246 -0
  318. package/dist/core/agent/agents-md/refusals.js.map +1 -0
  319. package/dist/core/agent/agents-md/shipped/archive-gate.js +98 -0
  320. package/dist/core/agent/agents-md/shipped/archive-gate.js.map +1 -0
  321. package/dist/core/agent/agents-md/spine.js +40 -0
  322. package/dist/core/agent/agents-md/spine.js.map +1 -0
  323. package/dist/core/agent/agents-md.js +170 -0
  324. package/dist/core/agent/agents-md.js.map +1 -0
  325. package/dist/core/{agents-stamp.js → agent/agents-stamp.js} +50 -0
  326. package/dist/core/agent/agents-stamp.js.map +1 -0
  327. package/dist/core/agent/contract.js +2 -0
  328. package/dist/core/agent/contract.js.map +1 -0
  329. package/dist/core/agent/protocol.js +193 -0
  330. package/dist/core/agent/protocol.js.map +1 -0
  331. package/dist/core/agent/scaffold.js +259 -0
  332. package/dist/core/agent/scaffold.js.map +1 -0
  333. package/dist/core/agent/support/report.js +103 -0
  334. package/dist/core/agent/support/report.js.map +1 -0
  335. package/dist/core/agent/tools/dialects.js +150 -0
  336. package/dist/core/agent/tools/dialects.js.map +1 -0
  337. package/dist/core/agent/tools/registry.js +228 -0
  338. package/dist/core/agent/tools/registry.js.map +1 -0
  339. package/dist/core/agent/workflows/adopt.js +133 -0
  340. package/dist/core/agent/workflows/adopt.js.map +1 -0
  341. package/dist/core/agent/workflows/check.js +334 -0
  342. package/dist/core/agent/workflows/check.js.map +1 -0
  343. package/dist/core/agent/workflows/closing.js +262 -0
  344. package/dist/core/agent/workflows/closing.js.map +1 -0
  345. package/dist/core/agent/workflows/feature.js +105 -0
  346. package/dist/core/agent/workflows/feature.js.map +1 -0
  347. package/dist/core/agent/workflows/implement.js +105 -0
  348. package/dist/core/agent/workflows/implement.js.map +1 -0
  349. package/dist/core/agent/workflows/reference/authoring.js +209 -0
  350. package/dist/core/agent/workflows/reference/authoring.js.map +1 -0
  351. package/dist/core/agent/workflows/reference/codes.js +65 -0
  352. package/dist/core/agent/workflows/reference/codes.js.map +1 -0
  353. package/dist/core/agent/workflows/reference/done-check.js +188 -0
  354. package/dist/core/agent/workflows/reference/done-check.js.map +1 -0
  355. package/dist/core/agent/workflows/reference/reference.js +16 -0
  356. package/dist/core/agent/workflows/reference/reference.js.map +1 -0
  357. package/dist/core/agent/workflows/reference/spine.js +297 -0
  358. package/dist/core/agent/workflows/reference/spine.js.map +1 -0
  359. package/dist/core/asyncapi/baseline/plan.js +110 -0
  360. package/dist/core/asyncapi/baseline/plan.js.map +1 -0
  361. package/dist/core/asyncapi/baseline/surfaces.js +54 -0
  362. package/dist/core/asyncapi/baseline/surfaces.js.map +1 -0
  363. package/dist/core/asyncapi/depth.js +164 -0
  364. package/dist/core/asyncapi/depth.js.map +1 -0
  365. package/dist/core/asyncapi/digest.js +141 -0
  366. package/dist/core/asyncapi/digest.js.map +1 -0
  367. package/dist/core/asyncapi/merge/components.js +91 -0
  368. package/dist/core/asyncapi/merge/components.js.map +1 -0
  369. package/dist/core/asyncapi/merge/error.js +33 -0
  370. package/dist/core/asyncapi/merge/error.js.map +1 -0
  371. package/dist/core/asyncapi/merge/markers.js +308 -0
  372. package/dist/core/asyncapi/merge/markers.js.map +1 -0
  373. package/dist/core/asyncapi/merge/merge.js +215 -0
  374. package/dist/core/asyncapi/merge/merge.js.map +1 -0
  375. package/dist/core/asyncapi/merge/pin.js +107 -0
  376. package/dist/core/asyncapi/merge/pin.js.map +1 -0
  377. package/dist/core/asyncapi/model.js +11 -0
  378. package/dist/core/asyncapi/model.js.map +1 -0
  379. package/dist/core/asyncapi/producers.js +50 -0
  380. package/dist/core/asyncapi/producers.js.map +1 -0
  381. package/dist/core/{asyncapi.js → asyncapi/read.js} +95 -109
  382. package/dist/core/asyncapi/read.js.map +1 -0
  383. package/dist/core/brief/brief.js +225 -0
  384. package/dist/core/brief/brief.js.map +1 -0
  385. package/dist/core/brief/checks.js +250 -0
  386. package/dist/core/brief/checks.js.map +1 -0
  387. package/dist/core/brief/landscape.js +194 -0
  388. package/dist/core/brief/landscape.js.map +1 -0
  389. package/dist/core/brief/targets.js +226 -0
  390. package/dist/core/brief/targets.js.map +1 -0
  391. package/dist/core/brief/unchecked.js +47 -0
  392. package/dist/core/brief/unchecked.js.map +1 -0
  393. package/dist/core/c4/arch.js +282 -0
  394. package/dist/core/c4/arch.js.map +1 -0
  395. package/dist/core/c4/likec4.js +88 -0
  396. package/dist/core/c4/likec4.js.map +1 -0
  397. package/dist/core/c4/parsed/dynamic-views.js +132 -0
  398. package/dist/core/c4/parsed/dynamic-views.js.map +1 -0
  399. package/dist/core/c4/parsed/specification.js +78 -0
  400. package/dist/core/c4/parsed/specification.js.map +1 -0
  401. package/dist/core/c4/parsed/values.js +57 -0
  402. package/dist/core/c4/parsed/values.js.map +1 -0
  403. package/dist/core/c4/parsed/view-ids.js +75 -0
  404. package/dist/core/c4/parsed/view-ids.js.map +1 -0
  405. package/dist/core/c4/project/architecture.js +45 -0
  406. package/dist/core/c4/project/architecture.js.map +1 -0
  407. package/dist/core/c4/project/documents.js +58 -0
  408. package/dist/core/c4/project/documents.js.map +1 -0
  409. package/dist/core/c4/project/load.js +183 -0
  410. package/dist/core/c4/project/load.js.map +1 -0
  411. package/dist/core/c4/resolve/service.js +113 -0
  412. package/dist/core/c4/resolve/service.js.map +1 -0
  413. package/dist/core/c4/seed/fleet-file.js +201 -0
  414. package/dist/core/c4/seed/fleet-file.js.map +1 -0
  415. package/dist/core/c4/seed/items.js +91 -0
  416. package/dist/core/c4/seed/items.js.map +1 -0
  417. package/dist/core/c4/seed/stamp.js +48 -0
  418. package/dist/core/c4/seed/stamp.js.map +1 -0
  419. package/dist/core/c4/seed/template.js +109 -0
  420. package/dist/core/c4/seed/template.js.map +1 -0
  421. package/dist/core/c4/source-mask.js +82 -0
  422. package/dist/core/c4/source-mask.js.map +1 -0
  423. package/dist/core/c4/source-scan.js +227 -0
  424. package/dist/core/c4/source-scan.js.map +1 -0
  425. package/dist/core/c4/splice/authored-source.js +101 -0
  426. package/dist/core/c4/splice/authored-source.js.map +1 -0
  427. package/dist/core/c4/splice/contract.js +10 -0
  428. package/dist/core/c4/splice/contract.js.map +1 -0
  429. package/dist/core/c4/splice/delta-blocks.js +126 -0
  430. package/dist/core/c4/splice/delta-blocks.js.map +1 -0
  431. package/dist/core/c4/splice/identity/edges.js +36 -0
  432. package/dist/core/c4/splice/identity/edges.js.map +1 -0
  433. package/dist/core/c4/splice/landscape-merge.js +269 -0
  434. package/dist/core/c4/splice/landscape-merge.js.map +1 -0
  435. package/dist/core/c4/splice/placement.js +194 -0
  436. package/dist/core/c4/splice/placement.js.map +1 -0
  437. package/dist/core/c4/workspace.js +172 -0
  438. package/dist/core/c4/workspace.js.map +1 -0
  439. package/dist/core/capabilities/authoring/notes.js +141 -0
  440. package/dist/core/capabilities/authoring/notes.js.map +1 -0
  441. package/dist/core/capabilities/capabilities.js +124 -0
  442. package/dist/core/capabilities/capabilities.js.map +1 -0
  443. package/dist/core/capabilities/delta/doc.js +50 -0
  444. package/dist/core/capabilities/delta/doc.js.map +1 -0
  445. package/dist/core/capabilities/delta/overlay.js +129 -0
  446. package/dist/core/capabilities/delta/overlay.js.map +1 -0
  447. package/dist/core/capabilities/delta/summary.js +57 -0
  448. package/dist/core/capabilities/delta/summary.js.map +1 -0
  449. package/dist/core/capabilities/delta/tree.js +43 -0
  450. package/dist/core/capabilities/delta/tree.js.map +1 -0
  451. package/dist/core/capabilities/delta/uncovered.js +222 -0
  452. package/dist/core/capabilities/delta/uncovered.js.map +1 -0
  453. package/dist/core/capabilities/findings.js +342 -0
  454. package/dist/core/capabilities/findings.js.map +1 -0
  455. package/dist/core/capabilities/realizes/findings.js +181 -0
  456. package/dist/core/capabilities/realizes/findings.js.map +1 -0
  457. package/dist/core/capabilities/realizes/join.js +143 -0
  458. package/dist/core/capabilities/realizes/join.js.map +1 -0
  459. package/dist/core/capabilities/rollup.js +199 -0
  460. package/dist/core/capabilities/rollup.js.map +1 -0
  461. package/dist/core/capabilities/tree.js +126 -0
  462. package/dist/core/capabilities/tree.js.map +1 -0
  463. package/dist/core/capabilities/usecase-join.js +277 -0
  464. package/dist/core/capabilities/usecase-join.js.map +1 -0
  465. package/dist/core/coherence/authoring/scaffold.js +177 -0
  466. package/dist/core/coherence/authoring/scaffold.js.map +1 -0
  467. package/dist/core/coherence/authoring/sentinels.js +74 -0
  468. package/dist/core/coherence/authoring/sentinels.js.map +1 -0
  469. package/dist/core/coherence/coherence.js +251 -0
  470. package/dist/core/coherence/coherence.js.map +1 -0
  471. package/dist/core/coherence/declared.js +269 -0
  472. package/dist/core/coherence/declared.js.map +1 -0
  473. package/dist/core/coherence/events/declared.js +206 -0
  474. package/dist/core/coherence/events/declared.js.map +1 -0
  475. package/dist/core/coherence/events/events.js +204 -0
  476. package/dist/core/coherence/events/events.js.map +1 -0
  477. package/dist/core/coherence/events/grades.js +166 -0
  478. package/dist/core/coherence/events/grades.js.map +1 -0
  479. package/dist/core/coherence/events/lookups.js +122 -0
  480. package/dist/core/coherence/events/lookups.js.map +1 -0
  481. package/dist/core/coherence/events/merged.js +40 -0
  482. package/dist/core/coherence/events/merged.js.map +1 -0
  483. package/dist/core/coherence/living.js +198 -0
  484. package/dist/core/coherence/living.js.map +1 -0
  485. package/dist/core/coherence/lookups.js +155 -0
  486. package/dist/core/coherence/lookups.js.map +1 -0
  487. package/dist/core/coherence/pending.js +39 -0
  488. package/dist/core/coherence/pending.js.map +1 -0
  489. package/dist/core/conflict-markers.js +60 -0
  490. package/dist/core/conflict-markers.js.map +1 -0
  491. package/dist/core/delta/claims.js +73 -0
  492. package/dist/core/delta/claims.js.map +1 -0
  493. package/dist/core/delta/delta.js +296 -0
  494. package/dist/core/delta/delta.js.map +1 -0
  495. package/dist/core/delta/document.js +177 -0
  496. package/dist/core/delta/document.js.map +1 -0
  497. package/dist/core/delta/scope.js +48 -0
  498. package/dist/core/delta/scope.js.map +1 -0
  499. package/dist/core/delta/select.js +237 -0
  500. package/dist/core/delta/select.js.map +1 -0
  501. package/dist/core/dependencies/dependencies.js +141 -0
  502. package/dist/core/dependencies/dependencies.js.map +1 -0
  503. package/dist/core/dependencies/facts.js +165 -0
  504. package/dist/core/dependencies/facts.js.map +1 -0
  505. package/dist/core/dependencies/fanin.js +88 -0
  506. package/dist/core/dependencies/fanin.js.map +1 -0
  507. package/dist/core/dependencies/graph.js +106 -0
  508. package/dist/core/dependencies/graph.js.map +1 -0
  509. package/dist/core/diff/base-git.js +148 -0
  510. package/dist/core/diff/base-git.js.map +1 -0
  511. package/dist/core/diff/base-state.js +209 -0
  512. package/dist/core/diff/base-state.js.map +1 -0
  513. package/dist/core/diff/current-state.js +96 -0
  514. package/dist/core/diff/current-state.js.map +1 -0
  515. package/dist/core/diff/scope/changed-paths.js +188 -0
  516. package/dist/core/diff/scope/changed-paths.js.map +1 -0
  517. package/dist/core/diff/semantic.js +243 -0
  518. package/dist/core/diff/semantic.js.map +1 -0
  519. package/dist/core/diff/victims.js +247 -0
  520. package/dist/core/diff/victims.js.map +1 -0
  521. package/dist/core/docs.js +7 -64
  522. package/dist/core/docs.js.map +1 -1
  523. package/dist/core/doctor/agents.js +222 -0
  524. package/dist/core/doctor/agents.js.map +1 -0
  525. package/dist/core/doctor/config.js +135 -0
  526. package/dist/core/doctor/config.js.map +1 -0
  527. package/dist/core/doctor/doctor.js +275 -0
  528. package/dist/core/doctor/doctor.js.map +1 -0
  529. package/dist/core/doctor/report.js +13 -0
  530. package/dist/core/doctor/report.js.map +1 -0
  531. package/dist/core/doctor/residue.js +110 -0
  532. package/dist/core/doctor/residue.js.map +1 -0
  533. package/dist/core/document/apply.js +77 -0
  534. package/dist/core/document/apply.js.map +1 -0
  535. package/dist/core/{frontmatter.js → document/frontmatter.js} +48 -2
  536. package/dist/core/document/frontmatter.js.map +1 -0
  537. package/dist/core/document/grammar/directives.js +143 -0
  538. package/dist/core/document/grammar/directives.js.map +1 -0
  539. package/dist/core/document/parse.js +263 -0
  540. package/dist/core/document/parse.js.map +1 -0
  541. package/dist/core/document/scenarios.js +221 -0
  542. package/dist/core/document/scenarios.js.map +1 -0
  543. package/dist/core/document/spec.js +241 -0
  544. package/dist/core/document/spec.js.map +1 -0
  545. package/dist/core/{config.js → envelope/config.js} +79 -18
  546. package/dist/core/envelope/config.js.map +1 -0
  547. package/dist/core/envelope/json.js +175 -0
  548. package/dist/core/envelope/json.js.map +1 -0
  549. package/dist/core/{version.js → envelope/version.js} +3 -3
  550. package/dist/core/envelope/version.js.map +1 -0
  551. package/dist/core/explain/families.js +175 -0
  552. package/dist/core/explain/families.js.map +1 -0
  553. package/dist/core/explain/fix-tables.js +178 -0
  554. package/dist/core/explain/fix-tables.js.map +1 -0
  555. package/dist/core/explain/lookup.js +181 -0
  556. package/dist/core/explain/lookup.js.map +1 -0
  557. package/dist/core/explain/refusals.js +49 -0
  558. package/dist/core/explain/refusals.js.map +1 -0
  559. package/dist/core/explain/terms.js +144 -0
  560. package/dist/core/explain/terms.js.map +1 -0
  561. package/dist/core/explore/describe.js +105 -0
  562. package/dist/core/explore/describe.js.map +1 -0
  563. package/dist/core/{explore.js → explore/explore.js} +50 -101
  564. package/dist/core/explore/explore.js.map +1 -0
  565. package/dist/core/fleet-context.js +120 -78
  566. package/dist/core/fleet-context.js.map +1 -1
  567. package/dist/core/gate/checks.js +201 -0
  568. package/dist/core/gate/checks.js.map +1 -0
  569. package/dist/core/gate/partners.js +205 -0
  570. package/dist/core/gate/partners.js.map +1 -0
  571. package/dist/core/gate/report.js +47 -0
  572. package/dist/core/gate/report.js.map +1 -0
  573. package/dist/core/gate/verification.js +113 -0
  574. package/dist/core/gate/verification.js.map +1 -0
  575. package/dist/core/gherkin/digest.js +60 -0
  576. package/dist/core/gherkin/digest.js.map +1 -0
  577. package/dist/core/gherkin/emit.js +177 -0
  578. package/dist/core/gherkin/emit.js.map +1 -0
  579. package/dist/core/gherkin/read.js +76 -0
  580. package/dist/core/gherkin/read.js.map +1 -0
  581. package/dist/core/gherkin/stale.js +234 -0
  582. package/dist/core/gherkin/stale.js.map +1 -0
  583. package/dist/core/gherkin/stamp.js +77 -0
  584. package/dist/core/gherkin/stamp.js.map +1 -0
  585. package/dist/core/gherkin/steps/catalogue.js +154 -0
  586. package/dist/core/gherkin/steps/catalogue.js.map +1 -0
  587. package/dist/core/gherkin/steps/inventory.js +98 -0
  588. package/dist/core/gherkin/steps/inventory.js.map +1 -0
  589. package/dist/core/gherkin/steps/phrase.js +72 -0
  590. package/dist/core/gherkin/steps/phrase.js.map +1 -0
  591. package/dist/core/glossary/delta.js +106 -0
  592. package/dist/core/glossary/delta.js.map +1 -0
  593. package/dist/core/glossary/tree.js +86 -0
  594. package/dist/core/glossary/tree.js.map +1 -0
  595. package/dist/core/kernel/concurrency.js.map +1 -0
  596. package/dist/core/{document-bytes.js → kernel/document-bytes.js} +1 -1
  597. package/dist/core/kernel/document-bytes.js.map +1 -0
  598. package/dist/core/kernel/fences.js +42 -0
  599. package/dist/core/kernel/fences.js.map +1 -0
  600. package/dist/core/kernel/ids/capability.js +72 -0
  601. package/dist/core/kernel/ids/capability.js.map +1 -0
  602. package/dist/core/kernel/ids/dirs.js +33 -0
  603. package/dist/core/kernel/ids/dirs.js.map +1 -0
  604. package/dist/core/kernel/ids/feature.js +75 -0
  605. package/dist/core/kernel/ids/feature.js.map +1 -0
  606. package/dist/core/kernel/ids/service.js +156 -0
  607. package/dist/core/kernel/ids/service.js.map +1 -0
  608. package/dist/core/kernel/ids/subsystem.js +63 -0
  609. package/dist/core/kernel/ids/subsystem.js.map +1 -0
  610. package/dist/core/{path-safety.js → kernel/path-safety.js} +18 -4
  611. package/dist/core/kernel/path-safety.js.map +1 -0
  612. package/dist/core/kernel/records.js.map +1 -0
  613. package/dist/core/links/backlinks.js +68 -0
  614. package/dist/core/links/backlinks.js.map +1 -0
  615. package/dist/core/links/case.js +74 -0
  616. package/dist/core/links/case.js.map +1 -0
  617. package/dist/core/links/corpus.js +104 -0
  618. package/dist/core/links/corpus.js.map +1 -0
  619. package/dist/core/links/findings.js +110 -0
  620. package/dist/core/links/findings.js.map +1 -0
  621. package/dist/core/links/parse.js +236 -0
  622. package/dist/core/links/parse.js.map +1 -0
  623. package/dist/core/mcp/argv.js +111 -0
  624. package/dist/core/mcp/argv.js.map +1 -0
  625. package/dist/core/mcp/author-tools.js +72 -0
  626. package/dist/core/mcp/author-tools.js.map +1 -0
  627. package/dist/core/mcp/framing.js +46 -0
  628. package/dist/core/mcp/framing.js.map +1 -0
  629. package/dist/core/mcp/protocol.js +280 -0
  630. package/dist/core/mcp/protocol.js.map +1 -0
  631. package/dist/core/mcp/tools.js +314 -0
  632. package/dist/core/mcp/tools.js.map +1 -0
  633. package/dist/core/obligations/obligations.js +106 -0
  634. package/dist/core/obligations/obligations.js.map +1 -0
  635. package/dist/core/openapi/baseline/gate.js +166 -0
  636. package/dist/core/openapi/baseline/gate.js.map +1 -0
  637. package/dist/core/openapi/baseline/plan.js +112 -0
  638. package/dist/core/openapi/baseline/plan.js.map +1 -0
  639. package/dist/core/openapi/baseline/record.js +175 -0
  640. package/dist/core/openapi/baseline/record.js.map +1 -0
  641. package/dist/core/openapi/depth.js +122 -0
  642. package/dist/core/openapi/depth.js.map +1 -0
  643. package/dist/core/openapi/digest.js +189 -0
  644. package/dist/core/openapi/digest.js.map +1 -0
  645. package/dist/core/{openapi.js → openapi/doc.js} +44 -106
  646. package/dist/core/openapi/doc.js.map +1 -0
  647. package/dist/core/openapi/merge/components.js +234 -0
  648. package/dist/core/openapi/merge/components.js.map +1 -0
  649. package/dist/core/openapi/merge/error.js +26 -0
  650. package/dist/core/openapi/merge/error.js.map +1 -0
  651. package/dist/core/openapi/merge/markers.js +208 -0
  652. package/dist/core/openapi/merge/markers.js.map +1 -0
  653. package/dist/core/openapi/merge/merge.js +256 -0
  654. package/dist/core/openapi/merge/merge.js.map +1 -0
  655. package/dist/core/openapi/merge/pin.js +128 -0
  656. package/dist/core/openapi/merge/pin.js.map +1 -0
  657. package/dist/core/openspec/decide/capabilities.js +244 -0
  658. package/dist/core/openspec/decide/capabilities.js.map +1 -0
  659. package/dist/core/openspec/decide/dispositions.js +63 -0
  660. package/dist/core/openspec/decide/dispositions.js.map +1 -0
  661. package/dist/core/openspec/decide/renames.js +179 -0
  662. package/dist/core/openspec/decide/renames.js.map +1 -0
  663. package/dist/core/openspec/decide/verdict.js +84 -0
  664. package/dist/core/openspec/decide/verdict.js.map +1 -0
  665. package/dist/core/openspec/inventory.js +221 -0
  666. package/dist/core/openspec/inventory.js.map +1 -0
  667. package/dist/core/openspec/model/mapping.js +76 -0
  668. package/dist/core/openspec/model/mapping.js.map +1 -0
  669. package/dist/core/openspec/model/model.js +65 -0
  670. package/dist/core/openspec/model/model.js.map +1 -0
  671. package/dist/core/openspec/scan/changes.js +235 -0
  672. package/dist/core/openspec/scan/changes.js.map +1 -0
  673. package/dist/core/openspec/scan/config.js +200 -0
  674. package/dist/core/openspec/scan/config.js.map +1 -0
  675. package/dist/core/openspec/scan/shape.js +260 -0
  676. package/dist/core/openspec/scan/shape.js.map +1 -0
  677. package/dist/core/openspec/scan/walk.js +133 -0
  678. package/dist/core/openspec/scan/walk.js.map +1 -0
  679. package/dist/core/openspec/scan/workspace.js +71 -0
  680. package/dist/core/openspec/scan/workspace.js.map +1 -0
  681. package/dist/core/owners/codeowners.js +141 -0
  682. package/dist/core/owners/codeowners.js.map +1 -0
  683. package/dist/core/pack/features.js +120 -0
  684. package/dist/core/pack/features.js.map +1 -0
  685. package/dist/core/pack/joins.js +112 -0
  686. package/dist/core/pack/joins.js.map +1 -0
  687. package/dist/core/pack/living.js +118 -0
  688. package/dist/core/pack/living.js.map +1 -0
  689. package/dist/core/pack/pack.js +76 -0
  690. package/dist/core/pack/pack.js.map +1 -0
  691. package/dist/core/permissions/permissions.js +87 -0
  692. package/dist/core/permissions/permissions.js.map +1 -0
  693. package/dist/core/projection/api.js +84 -0
  694. package/dist/core/projection/api.js.map +1 -0
  695. package/dist/core/projection/arch-slice.js +63 -0
  696. package/dist/core/projection/arch-slice.js.map +1 -0
  697. package/dist/core/projection/events.js +34 -0
  698. package/dist/core/projection/events.js.map +1 -0
  699. package/dist/core/provenance/findings.js +208 -0
  700. package/dist/core/provenance/findings.js.map +1 -0
  701. package/dist/core/provenance/git.js +225 -0
  702. package/dist/core/provenance/git.js.map +1 -0
  703. package/dist/core/provenance/gitq/moves.js +182 -0
  704. package/dist/core/provenance/gitq/moves.js.map +1 -0
  705. package/dist/core/provenance/gitq/vouched-ancestor.js +179 -0
  706. package/dist/core/provenance/gitq/vouched-ancestor.js.map +1 -0
  707. package/dist/core/provenance/sample/scope.js +238 -0
  708. package/dist/core/provenance/sample/scope.js.map +1 -0
  709. package/dist/core/provenance/sample/sections.js +61 -0
  710. package/dist/core/provenance/sample/sections.js.map +1 -0
  711. package/dist/core/provenance/sources.js +263 -0
  712. package/dist/core/provenance/sources.js.map +1 -0
  713. package/dist/core/provenance/stamp.js +232 -0
  714. package/dist/core/provenance/stamp.js.map +1 -0
  715. package/dist/core/provenance/walk.js +157 -0
  716. package/dist/core/provenance/walk.js.map +1 -0
  717. package/dist/core/repo/authored/paths.js +192 -0
  718. package/dist/core/repo/authored/paths.js.map +1 -0
  719. package/dist/core/repo/entries.js +126 -0
  720. package/dist/core/repo/entries.js.map +1 -0
  721. package/dist/core/repo/paths.js +236 -0
  722. package/dist/core/repo/paths.js.map +1 -0
  723. package/dist/core/repo/repo.js +248 -0
  724. package/dist/core/repo/repo.js.map +1 -0
  725. package/dist/core/repo/service-target.js +153 -0
  726. package/dist/core/repo/service-target.js.map +1 -0
  727. package/dist/core/repo/state.js +58 -0
  728. package/dist/core/repo/state.js.map +1 -0
  729. package/dist/core/repo/tree/find.js +52 -0
  730. package/dist/core/repo/tree/find.js.map +1 -0
  731. package/dist/core/repo/tree/fs.js +64 -0
  732. package/dist/core/repo/tree/fs.js.map +1 -0
  733. package/dist/core/repo/tree/marker.js +61 -0
  734. package/dist/core/repo/tree/marker.js.map +1 -0
  735. package/dist/core/repo/tree/views.js +172 -0
  736. package/dist/core/repo/tree/views.js.map +1 -0
  737. package/dist/core/repo/tree/walk.js +234 -0
  738. package/dist/core/repo/tree/walk.js.map +1 -0
  739. package/dist/core/results.js +99 -2
  740. package/dist/core/results.js.map +1 -1
  741. package/dist/core/scaffold/landscape.js +131 -0
  742. package/dist/core/scaffold/landscape.js.map +1 -0
  743. package/dist/core/scaffold/readme.js +84 -0
  744. package/dist/core/scaffold/readme.js.map +1 -0
  745. package/dist/core/staging/commit.js +241 -0
  746. package/dist/core/staging/commit.js.map +1 -0
  747. package/dist/core/staging/interrupted.js +96 -0
  748. package/dist/core/staging/interrupted.js.map +1 -0
  749. package/dist/core/staging/lock.js +206 -0
  750. package/dist/core/staging/lock.js.map +1 -0
  751. package/dist/core/staging/recovery/finding.js +35 -0
  752. package/dist/core/staging/recovery/finding.js.map +1 -0
  753. package/dist/core/staging/recovery/intent.js +98 -0
  754. package/dist/core/staging/recovery/intent.js.map +1 -0
  755. package/dist/core/staging/recovery/recover.js +126 -0
  756. package/dist/core/staging/recovery/recover.js.map +1 -0
  757. package/dist/core/staging/recovery/residue.js +62 -0
  758. package/dist/core/staging/recovery/residue.js.map +1 -0
  759. package/dist/core/staging/snapshot.js +202 -0
  760. package/dist/core/staging/snapshot.js.map +1 -0
  761. package/dist/core/staging/txn/forward.js +171 -0
  762. package/dist/core/staging/txn/forward.js.map +1 -0
  763. package/dist/core/staging/txn/journal.js +139 -0
  764. package/dist/core/staging/txn/journal.js.map +1 -0
  765. package/dist/core/staging/txn/transaction.js +75 -0
  766. package/dist/core/staging/txn/transaction.js.map +1 -0
  767. package/dist/core/staging/writes.js +113 -0
  768. package/dist/core/staging/writes.js.map +1 -0
  769. package/dist/core/status/actions/execution.js +49 -0
  770. package/dist/core/status/actions/execution.js.map +1 -0
  771. package/dist/core/status/contracts.js +102 -0
  772. package/dist/core/status/contracts.js.map +1 -0
  773. package/dist/core/status/feature/artifacts.js +171 -0
  774. package/dist/core/status/feature/artifacts.js.map +1 -0
  775. package/dist/core/status/feature/feature.js +207 -0
  776. package/dist/core/status/feature/feature.js.map +1 -0
  777. package/dist/core/status/feature/next.js +150 -0
  778. package/dist/core/status/feature/next.js.map +1 -0
  779. package/dist/core/status/feature/state.js +21 -0
  780. package/dist/core/status/feature/state.js.map +1 -0
  781. package/dist/core/status/fleet/fleet.js +187 -0
  782. package/dist/core/status/fleet/fleet.js.map +1 -0
  783. package/dist/core/status/fleet/next.js +207 -0
  784. package/dist/core/status/fleet/next.js.map +1 -0
  785. package/dist/core/status/interrupted.js +97 -0
  786. package/dist/core/status/interrupted.js.map +1 -0
  787. package/dist/core/status/report.js +31 -0
  788. package/dist/core/status/report.js.map +1 -0
  789. package/dist/core/status/scan.js +41 -0
  790. package/dist/core/status/scan.js.map +1 -0
  791. package/dist/core/status/verification.js +201 -0
  792. package/dist/core/status/verification.js.map +1 -0
  793. package/dist/core/usecases/capability.js +169 -0
  794. package/dist/core/usecases/capability.js.map +1 -0
  795. package/dist/core/usecases/delta/claims.js +116 -0
  796. package/dist/core/usecases/delta/claims.js.map +1 -0
  797. package/dist/core/usecases/delta/flows.js +103 -0
  798. package/dist/core/usecases/delta/flows.js.map +1 -0
  799. package/dist/core/usecases/delta/overlay.js +235 -0
  800. package/dist/core/usecases/delta/overlay.js.map +1 -0
  801. package/dist/core/usecases/fleet.js +137 -0
  802. package/dist/core/usecases/fleet.js.map +1 -0
  803. package/dist/core/usecases/operations.js +111 -0
  804. package/dist/core/usecases/operations.js.map +1 -0
  805. package/dist/core/usecases/place.js +44 -0
  806. package/dist/core/usecases/place.js.map +1 -0
  807. package/dist/core/usecases/touch.js +101 -0
  808. package/dist/core/usecases/touch.js.map +1 -0
  809. package/dist/core/verify/answers.js +173 -0
  810. package/dist/core/verify/answers.js.map +1 -0
  811. package/dist/core/verify/build.js +150 -0
  812. package/dist/core/verify/build.js.map +1 -0
  813. package/dist/core/verify/checklist.js +201 -0
  814. package/dist/core/verify/checklist.js.map +1 -0
  815. package/dist/core/verify/claims/identity.js +61 -0
  816. package/dist/core/verify/claims/identity.js.map +1 -0
  817. package/dist/core/verify/cross/diff.js +97 -0
  818. package/dist/core/verify/cross/diff.js.map +1 -0
  819. package/dist/core/verify/evidence/contract.js +169 -0
  820. package/dist/core/verify/evidence/contract.js.map +1 -0
  821. package/dist/core/verify/file.js +257 -0
  822. package/dist/core/verify/file.js.map +1 -0
  823. package/dist/core/verify/pins/lint.js +157 -0
  824. package/dist/core/verify/pins/lint.js.map +1 -0
  825. package/dist/core/verify/pins/pin.js +95 -0
  826. package/dist/core/verify/pins/pin.js.map +1 -0
  827. package/dist/core/verify/record.js +142 -0
  828. package/dist/core/verify/record.js.map +1 -0
  829. package/dist/core/verify/store/commit.js +89 -0
  830. package/dist/core/verify/store/commit.js.map +1 -0
  831. package/dist/core/verify/store/render.js +57 -0
  832. package/dist/core/verify/store/render.js.map +1 -0
  833. package/dist/core/vocabulary/health.js +91 -0
  834. package/dist/core/vocabulary/health.js.map +1 -0
  835. package/dist/core/vocabulary/issue.js +55 -0
  836. package/dist/core/vocabulary/issue.js.map +1 -0
  837. package/dist/core/vocabulary/maturity.js +145 -0
  838. package/dist/core/vocabulary/maturity.js.map +1 -0
  839. package/dist/core/{report.js → vocabulary/report.js} +30 -2
  840. package/dist/core/vocabulary/report.js.map +1 -0
  841. package/dist/core/vocabulary/steps.js +266 -0
  842. package/dist/core/vocabulary/steps.js.map +1 -0
  843. package/dist/core/workspace/discover.js +239 -0
  844. package/dist/core/workspace/discover.js.map +1 -0
  845. package/dist/core/workspace/render.js +52 -0
  846. package/dist/core/workspace/render.js.map +1 -0
  847. package/examples/README.md +189 -0
  848. package/examples/docs/architecture/adrs/0001-transactional-outbox.md +33 -0
  849. package/examples/docs/architecture/capabilities.yaml +31 -0
  850. package/examples/docs/architecture/landscape.likec4 +280 -0
  851. package/examples/docs/architecture/obligations.yaml +23 -0
  852. package/examples/docs/architecture/permissions.yaml +50 -0
  853. package/examples/docs/architecture/subsystems.likec4 +11 -0
  854. package/examples/docs/architecture/usecases/order-notification.likec4 +65 -0
  855. package/examples/docs/capabilities/checkout/spec.md +55 -0
  856. package/examples/docs/capabilities/identity/tokens/spec.md +42 -0
  857. package/examples/docs/capabilities/order-notifications/spec.md +43 -0
  858. package/examples/docs/features/FEAT-101-payment-splitting/adrs/0001-dedicated-split-service.md +18 -0
  859. package/examples/docs/features/FEAT-101-payment-splitting/delta.likec4 +94 -0
  860. package/examples/docs/features/FEAT-101-payment-splitting/intent.md +44 -0
  861. package/examples/docs/features/FEAT-101-payment-splitting/specs/checkout-web/spec.md +21 -0
  862. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-service/asyncapi.yaml +129 -0
  863. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-service/spec.md +36 -0
  864. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/arch.spec.md +40 -0
  865. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/openapi.yaml +116 -0
  866. package/examples/docs/features/FEAT-101-payment-splitting/specs/payment-split-service/spec.md +55 -0
  867. package/examples/docs/features/FEAT-112-retire-order-v1/intent.md +35 -0
  868. package/examples/docs/features/FEAT-112-retire-order-v1/specs/order-service/openapi.yaml +28 -0
  869. package/examples/docs/features/FEAT-112-retire-order-v1/specs/order-service/spec.md +17 -0
  870. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/architecture/landscape.likec4 +253 -0
  871. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/services/order-service/spec.md +121 -0
  872. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/services/payment-service/openapi.yaml +111 -0
  873. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/files/services/payment-service/spec.md +58 -0
  874. package/examples/docs/features/archive/FEAT-088-refunds/.loam-before/manifest.json +32 -0
  875. package/examples/docs/features/archive/FEAT-088-refunds/adrs/0001-refunds-stay-in-payment-service.md +26 -0
  876. package/examples/docs/features/archive/FEAT-088-refunds/delta.likec4 +28 -0
  877. package/examples/docs/features/archive/FEAT-088-refunds/intent.md +26 -0
  878. package/examples/docs/features/archive/FEAT-088-refunds/specs/order-service/spec.md +37 -0
  879. package/examples/docs/features/archive/FEAT-088-refunds/specs/payment-service/openapi.yaml +70 -0
  880. package/examples/docs/features/archive/FEAT-088-refunds/specs/payment-service/spec.md +23 -0
  881. package/examples/docs/features/archive/FEAT-088-refunds/verification.yaml +76 -0
  882. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/architecture/landscape.likec4 +275 -0
  883. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/payment-service/asyncapi.yaml +96 -0
  884. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/payment-service/spec.md +82 -0
  885. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/platform/notification-service/asyncapi.yaml +164 -0
  886. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/files/services/platform/notification-service/spec.md +91 -0
  887. package/examples/docs/features/archive/FEAT-120-refund-notification/.loam-before/manifest.json +46 -0
  888. package/examples/docs/features/archive/FEAT-120-refund-notification/delta.likec4 +36 -0
  889. package/examples/docs/features/archive/FEAT-120-refund-notification/intent.md +22 -0
  890. package/examples/docs/features/archive/FEAT-120-refund-notification/scenario-report.json +10 -0
  891. package/examples/docs/features/archive/FEAT-120-refund-notification/specs/notification-service/asyncapi.yaml +208 -0
  892. package/examples/docs/features/archive/FEAT-120-refund-notification/specs/notification-service/spec.md +24 -0
  893. package/examples/docs/features/archive/FEAT-120-refund-notification/specs/payment-service/asyncapi.yaml +137 -0
  894. package/examples/docs/features/archive/FEAT-120-refund-notification/specs/payment-service/spec.md +31 -0
  895. package/examples/docs/features/archive/FEAT-120-refund-notification/verification.yaml +84 -0
  896. package/examples/docs/glossary/order.md +15 -0
  897. package/examples/docs/glossary/payments/authorization.md +14 -0
  898. package/examples/docs/likec4.config.json +9 -0
  899. package/examples/docs/loam.json +3 -0
  900. package/examples/docs/services/checkout-web/model.likec4 +109 -0
  901. package/examples/docs/services/checkout-web/spec.md +91 -0
  902. package/examples/docs/services/checkout-web/ui/pages/checkout.page.yaml +40 -0
  903. package/examples/docs/services/checkout-web/ui/pages/order-status.page.yaml +24 -0
  904. package/examples/docs/services/checkout-web/ui/pages/split-payment.page.yaml +26 -0
  905. package/examples/docs/services/order-service/adrs/0001-orchestrated-order-lifecycle.md +52 -0
  906. package/examples/docs/services/order-service/arch.spec.md +127 -0
  907. package/examples/docs/services/order-service/asyncapi.yaml +108 -0
  908. package/examples/docs/services/order-service/health.yaml +57 -0
  909. package/examples/docs/services/order-service/model.likec4 +138 -0
  910. package/examples/docs/services/order-service/openapi.yaml +257 -0
  911. package/examples/docs/services/order-service/runbook.md +62 -0
  912. package/examples/docs/services/order-service/spec.md +134 -0
  913. package/examples/docs/services/payment-service/adrs/0001-payments-outbox.md +18 -0
  914. package/examples/docs/services/payment-service/adrs/0002-idempotency-keys-on-authorization.md +27 -0
  915. package/examples/docs/services/payment-service/arch.spec.md +73 -0
  916. package/examples/docs/services/payment-service/asyncapi.yaml +130 -0
  917. package/examples/docs/services/payment-service/health.yaml +39 -0
  918. package/examples/docs/services/payment-service/model.likec4 +67 -0
  919. package/examples/docs/services/payment-service/openapi.yaml +151 -0
  920. package/examples/docs/services/payment-service/runbook.md +37 -0
  921. package/examples/docs/services/payment-service/spec.md +88 -0
  922. package/examples/docs/services/platform/identity-service/adrs/0001-token-introspection-over-local-validation.md +60 -0
  923. package/examples/docs/services/platform/identity-service/arch.spec.md +117 -0
  924. package/examples/docs/services/platform/identity-service/health.yaml +70 -0
  925. package/examples/docs/services/platform/identity-service/model.likec4 +83 -0
  926. package/examples/docs/services/platform/identity-service/openapi.yaml +197 -0
  927. package/examples/docs/services/platform/identity-service/runbook.md +95 -0
  928. package/examples/docs/services/platform/identity-service/spec.md +119 -0
  929. package/examples/docs/services/platform/notification-service/asyncapi.yaml +199 -0
  930. package/examples/docs/services/platform/notification-service/health.yaml +35 -0
  931. package/examples/docs/services/platform/notification-service/model.likec4 +118 -0
  932. package/examples/docs/services/platform/notification-service/runbook.md +48 -0
  933. package/examples/docs/services/platform/notification-service/spec.md +112 -0
  934. package/examples/docs/services/platform/subsystem.yaml +2 -0
  935. package/examples/fleet.yaml +57 -0
  936. package/package.json +19 -6
  937. package/dist/commands/adopt.js +0 -240
  938. package/dist/commands/adopt.js.map +0 -1
  939. package/dist/commands/archive.js +0 -1313
  940. package/dist/commands/archive.js.map +0 -1
  941. package/dist/commands/delta.js +0 -388
  942. package/dist/commands/delta.js.map +0 -1
  943. package/dist/commands/docs-repo-gate.js.map +0 -1
  944. package/dist/commands/format.js +0 -17
  945. package/dist/commands/format.js.map +0 -1
  946. package/dist/commands/gherkin.js +0 -309
  947. package/dist/commands/gherkin.js.map +0 -1
  948. package/dist/commands/init.js.map +0 -1
  949. package/dist/commands/list.js +0 -295
  950. package/dist/commands/list.js.map +0 -1
  951. package/dist/commands/migrate-openspec.js +0 -950
  952. package/dist/commands/migrate-openspec.js.map +0 -1
  953. package/dist/commands/new.js +0 -413
  954. package/dist/commands/new.js.map +0 -1
  955. package/dist/commands/rebase.js +0 -356
  956. package/dist/commands/rebase.js.map +0 -1
  957. package/dist/commands/show.js.map +0 -1
  958. package/dist/commands/status.js +0 -262
  959. package/dist/commands/status.js.map +0 -1
  960. package/dist/commands/unarchive.js.map +0 -1
  961. package/dist/commands/validate.js +0 -1773
  962. package/dist/commands/validate.js.map +0 -1
  963. package/dist/commands/verify.js +0 -775
  964. package/dist/commands/verify.js.map +0 -1
  965. package/dist/commands/vouch.js +0 -421
  966. package/dist/commands/vouch.js.map +0 -1
  967. package/dist/core/agent.js +0 -2173
  968. package/dist/core/agent.js.map +0 -1
  969. package/dist/core/agents-stamp.js.map +0 -1
  970. package/dist/core/arch.js +0 -130
  971. package/dist/core/arch.js.map +0 -1
  972. package/dist/core/asyncapi.js.map +0 -1
  973. package/dist/core/brief.js +0 -755
  974. package/dist/core/brief.js.map +0 -1
  975. package/dist/core/coherence.js +0 -577
  976. package/dist/core/coherence.js.map +0 -1
  977. package/dist/core/concurrency.js.map +0 -1
  978. package/dist/core/config.js.map +0 -1
  979. package/dist/core/delta.js +0 -476
  980. package/dist/core/delta.js.map +0 -1
  981. package/dist/core/dependencies.js +0 -356
  982. package/dist/core/dependencies.js.map +0 -1
  983. package/dist/core/doctor.js +0 -596
  984. package/dist/core/doctor.js.map +0 -1
  985. package/dist/core/document-bytes.js.map +0 -1
  986. package/dist/core/explore.js.map +0 -1
  987. package/dist/core/frontmatter.js.map +0 -1
  988. package/dist/core/gherkin.js +0 -463
  989. package/dist/core/gherkin.js.map +0 -1
  990. package/dist/core/health.js +0 -67
  991. package/dist/core/health.js.map +0 -1
  992. package/dist/core/ids.js +0 -122
  993. package/dist/core/ids.js.map +0 -1
  994. package/dist/core/issue.js +0 -9
  995. package/dist/core/issue.js.map +0 -1
  996. package/dist/core/json.js +0 -74
  997. package/dist/core/json.js.map +0 -1
  998. package/dist/core/likec4.js +0 -489
  999. package/dist/core/likec4.js.map +0 -1
  1000. package/dist/core/maturity.js +0 -66
  1001. package/dist/core/maturity.js.map +0 -1
  1002. package/dist/core/openapi-merge.js +0 -552
  1003. package/dist/core/openapi-merge.js.map +0 -1
  1004. package/dist/core/openapi.js.map +0 -1
  1005. package/dist/core/openspec-inventory.js +0 -1440
  1006. package/dist/core/openspec-inventory.js.map +0 -1
  1007. package/dist/core/path-safety.js.map +0 -1
  1008. package/dist/core/provenance.js +0 -787
  1009. package/dist/core/provenance.js.map +0 -1
  1010. package/dist/core/records.js.map +0 -1
  1011. package/dist/core/repo.js +0 -438
  1012. package/dist/core/repo.js.map +0 -1
  1013. package/dist/core/report.js.map +0 -1
  1014. package/dist/core/spec.js +0 -505
  1015. package/dist/core/spec.js.map +0 -1
  1016. package/dist/core/staging.js +0 -890
  1017. package/dist/core/staging.js.map +0 -1
  1018. package/dist/core/status.js +0 -1132
  1019. package/dist/core/status.js.map +0 -1
  1020. package/dist/core/steps.js +0 -72
  1021. package/dist/core/steps.js.map +0 -1
  1022. package/dist/core/verify.js +0 -807
  1023. package/dist/core/verify.js.map +0 -1
  1024. package/dist/core/version.js.map +0 -1
  1025. /package/dist/core/{concurrency.js → kernel/concurrency.js} +0 -0
  1026. /package/dist/core/{records.js → kernel/records.js} +0 -0
@@ -0,0 +1,216 @@
1
+ /**
2
+ * The feature target: a delta graded on its own, before anything merges.
3
+ *
4
+ * Everything here reads the feature directory — delta.likec4, the per-service
5
+ * spec.md/arch.spec.md deltas, the provenance stamp — and grades the documents
6
+ * a merge is about to fold into living ones. A delta is held to the same
7
+ * document rules as the file it becomes (`./checks/requirements.js`), because
8
+ * grading it more leniently is how a defect acquires a signature saying it was
9
+ * reviewed.
10
+ *
11
+ * The one question that needs the LIVING fleet — what in this delta is actually
12
+ * new architecture — is `./arch-coverage.js`.
13
+ */
14
+ import { existsSync } from "node:fs";
15
+ import { readFile } from "node:fs/promises";
16
+ import { loadFile } from "../../core/c4/likec4.js";
17
+ import { elementService } from "../../core/c4/resolve/service.js";
18
+ import {} from "../../core/kernel/ids/service.js";
19
+ import {} from "../../core/repo/entries.js";
20
+ import { featurePaths, featureSpecPaths } from "../../core/repo/paths.js";
21
+ import { enumeratedServiceIds } from "../../core/repo/service-target.js";
22
+ import { docsRepoState } from "../../core/repo/state.js";
23
+ import { featureSpecServices, listServices } from "../../core/repo/repo.js";
24
+ import {} from "../../core/vocabulary/report.js";
25
+ import { parseRequirements } from "../../core/document/parse.js";
26
+ import { assertionlessFindings, examplesFindings, steplessFindings, } from "../../core/document/scenarios.js";
27
+ import {} from "../../core/document/spec.js";
28
+ import { featureCoherence } from "../../core/coherence/coherence.js";
29
+ import { deltaServiceUnknownFinding, invalidSpecServiceFindings, } from "../../core/coherence/living.js";
30
+ import { issueFinding } from "../../core/vocabulary/issue.js";
31
+ import { featureProvenance } from "../../core/provenance/findings.js";
32
+ import { documentConflictFinding } from "../../core/conflict-markers.js";
33
+ import { featureCapabilityDeltas } from "../../core/capabilities/delta/tree.js";
34
+ import { docMissingFindings } from "../../core/capabilities/findings.js";
35
+ import { FleetContext } from "../../core/fleet-context.js";
36
+ import { errorText } from "./checks/vocabulary.js";
37
+ import { coverageFinding, repeatedListLineFindings } from "./checks/requirements.js";
38
+ import { deltaArchCoverage } from "./arch-coverage.js";
39
+ import { featureLinkFindings } from "./links/corpus.js";
40
+ export async function validateFeature(docsDir, feature, preloadedLand, fleet) {
41
+ const findings = [];
42
+ const featureDir = feature.dir;
43
+ const featureId = feature.id;
44
+ // delta.likec4 parse + collect tagged edges. The loaded doc is kept and
45
+ // handed to featureCoherence below — loading it is a Langium workspace spin,
46
+ // and paying it twice per feature was the dominant cost of `validate --all`.
47
+ let taggedEls = [];
48
+ let taggedRels = [];
49
+ let elements = [];
50
+ let deltaRels = [];
51
+ let deltaDoc;
52
+ const deltaPath = featurePaths(featureDir).delta;
53
+ if (existsSync(deltaPath)) {
54
+ const res = fleet === undefined ? await loadFile(deltaPath) : await fleet.loadLikeC4(deltaPath);
55
+ deltaDoc = res;
56
+ if (res.errors.length > 0) {
57
+ findings.push({
58
+ severity: "error",
59
+ code: "delta.invalid",
60
+ message: `delta.likec4 has ${res.errors.length} error(s)`,
61
+ details: res.errors.map(errorText),
62
+ });
63
+ }
64
+ else {
65
+ elements = res.elements;
66
+ deltaRels = res.relationships;
67
+ taggedEls = res.elements.filter((e) => e.tags.includes(featureId));
68
+ taggedRels = res.relationships.filter((r) => r.tags.includes(featureId));
69
+ findings.push({
70
+ severity: "ok",
71
+ code: "delta.valid",
72
+ message: `delta.likec4 valid (${res.elements.length} elements · ${res.relationships.length} relationships)`,
73
+ });
74
+ }
75
+ }
76
+ findings.push(...(await featureProvenance(featureDir, featureId)));
77
+ // Who this feature is allowed to address. `specs/<svc>/` is what the archive
78
+ // materialises `services/<svc>/` from, and nothing used to ask whether that
79
+ // name means anything: one wrong character in `--touches` passed
80
+ // `validate --all` with zero errors, and archive then created the phantom
81
+ // directory. A delta may legitimately name a service that does not exist yet
82
+ // — but only one it INTRODUCES itself, in its own tagged C4. A delta that did
83
+ // not parse proves neither (`delta.invalid` is that finding), so the question
84
+ // is suspended there rather than answered by guessing.
85
+ //
86
+ // Existence is enumeration MEMBERSHIP through the no-services-tolerant
87
+ // spelling, never `existsSync(services/<svc>/)` at the root: a service filed
88
+ // into a subsystem exists wherever the tree walk found it, and the root
89
+ // probe graded every filed service `delta.service-unknown`. The tolerance
90
+ // carries the old carve-out forward — `validate --feature` is allowed to run
91
+ // in a docs repo with no services/ at all, where enumerating is a refusal;
92
+ // `enumeratedServiceIds` swallows exactly that refusal to an empty list, in
93
+ // which every service is honestly absent.
94
+ const featureServices = await featureSpecServices(featureDir, fleet);
95
+ const introduces = new Set(taggedEls.map(elementService));
96
+ const deltaReadable = deltaDoc === undefined || deltaDoc.errors.length === 0;
97
+ const enumerated = new Set(await enumeratedServiceIds(docsDir, fleet));
98
+ const unknownServices = deltaReadable
99
+ ? featureServices.filter((svc) => !enumerated.has(svc) && !introduces.has(svc))
100
+ : [];
101
+ // The near-miss hint, on the same rule `service.unknown` uses — a typo is
102
+ // only diagnosable against the ids that DO exist.
103
+ const closeTo = unknownServices.length > 0 && docsRepoState(docsDir).kind === "ok"
104
+ ? (await listServices(docsDir, fleet)).map((s) => s.id)
105
+ : [];
106
+ // The finding is coherence/living.ts's — the same words archive refuses with,
107
+ // because it is the same conclusion about the same directory.
108
+ for (const svc of unknownServices)
109
+ findings.push(deltaServiceUnknownFinding(svc, closeTo));
110
+ // The grammar half of the same guarantee. `delta.service-unknown` asks whether
111
+ // the directory names a service anyone knows; this asks whether the NAME could
112
+ // ever be one. The two are independent on purpose: a tagged element whose
113
+ // title matches the directory answers the first question, which is exactly how
114
+ // `specs/Payment Service/` used to validate green and archive into a directory
115
+ // no loam command can address. Not suspended on an unreadable delta either —
116
+ // no reading of the architecture axis can make the name legal.
117
+ findings.push(...(await invalidSpecServiceFindings(featureDir, fleet)));
118
+ // Requirement coverage across every per-service delta — the business spec and
119
+ // the arch spec through the same check — and collect scenario text.
120
+ let scenarioText = "";
121
+ const archDeltas = [];
122
+ for (const svc of featureServices) {
123
+ const p = featureSpecPaths(featureDir, svc);
124
+ if (existsSync(p.spec)) {
125
+ const raw = fleet === undefined ? await readFile(p.spec, "utf8") : await fleet.readText(p.spec);
126
+ scenarioText += "\n" + raw.toLowerCase();
127
+ const reqs = fleet === undefined ? parseRequirements(raw) : await fleet.readRequirements(p.spec);
128
+ // Both document-level breaches carry into the living spec through the
129
+ // merge, so a delta is graded for them exactly as a living document is:
130
+ // conflict markers merge as prose under someone's requirement, and a
131
+ // stepless scenario merges as a requirement the coverage rule calls
132
+ // covered forever after.
133
+ const conflict = documentConflictFinding(`${svc}: spec.md`, svc, raw);
134
+ if (conflict !== null)
135
+ findings.push(conflict);
136
+ findings.push({ ...coverageFinding(`${svc}: requirements`, reqs), subject: svc });
137
+ findings.push(...steplessFindings(`${svc}: requirements`, svc, reqs));
138
+ findings.push(...assertionlessFindings(`${svc}: requirements`, svc, reqs));
139
+ findings.push(...examplesFindings(`${svc}: requirements`, svc, reqs));
140
+ // The keep-last quirk loses lines in a delta exactly as in a living spec
141
+ // — and a delta's lost Operations: line then merges into the living one.
142
+ findings.push(...repeatedListLineFindings(reqs, `${svc}: spec.md`, svc));
143
+ }
144
+ if (existsSync(p.archSpec)) {
145
+ const raw = fleet === undefined ? await readFile(p.archSpec, "utf8") : await fleet.readText(p.archSpec);
146
+ scenarioText += "\n" + raw.toLowerCase();
147
+ const reqs = fleet === undefined ? parseRequirements(raw) : await fleet.readRequirements(p.archSpec);
148
+ archDeltas.push({ service: svc, reqs });
149
+ const conflict = documentConflictFinding(`${svc}: arch.spec.md`, svc, raw);
150
+ if (conflict !== null)
151
+ findings.push(conflict);
152
+ findings.push({ ...coverageFinding(`${svc}: arch requirements`, reqs), subject: svc });
153
+ findings.push(...steplessFindings(`${svc}: arch requirements`, svc, reqs));
154
+ findings.push(...assertionlessFindings(`${svc}: arch requirements`, svc, reqs));
155
+ findings.push(...examplesFindings(`${svc}: arch requirements`, svc, reqs));
156
+ findings.push(...repeatedListLineFindings(reqs, `${svc}: arch.spec.md`, svc));
157
+ }
158
+ }
159
+ // The BUSINESS corpus's delta documents, graded for the same document-level
160
+ // breach as the service ones and for the same reason: a conflicted delta
161
+ // parses as prose, so every other check reads it as a valid document, and
162
+ // `loam archive` then re-serializes both sides of somebody's merge into the
163
+ // LIVING capability document. It is worse there than one tree over — once the
164
+ // feature is archived, nothing walks the delta again, and the living
165
+ // capability documents are only conflict-scanned while some feature still
166
+ // carries a delta for them.
167
+ const capabilityDeltas = fleet === undefined ? await featureCapabilityDeltas(featureDir) : await fleet.featureCapabilityDeltas(featureDir);
168
+ // The half-created directory, on the FEATURE side. The living tree has warned
169
+ // about `capabilities/<id>/` with no document since the axis landed; the same
170
+ // `mkdir` inside `features/<FEAT>/capabilities/` earned nothing, and it is the
171
+ // quieter of the two — an empty directory is not a delta, so the walk finds
172
+ // no document, the merge carries nothing, and the business change ships as
173
+ // zero at exit 0. Same code, feature-scoped message (`../../core/capabilities/findings.ts`).
174
+ // `dirName`, not the id: the directory is `features/FEAT-1-split/`, and a
175
+ // message spelling `features/FEAT-1/` names a path nobody can open.
176
+ findings.push(...docMissingFindings(capabilityDeltas, feature.dirName));
177
+ for (const doc of capabilityDeltas.docs) {
178
+ const raw = fleet === undefined ? await readFile(doc.spec, "utf8") : await fleet.readText(doc.spec);
179
+ const conflict = documentConflictFinding(`capability ${doc.id}: spec.md`, doc.id, raw);
180
+ if (conflict !== null)
181
+ findings.push(conflict);
182
+ }
183
+ // The links this feature's own documents write — the intent, each service's
184
+ // two spec deltas, its ADRs and its capability deltas. Same place in the
185
+ // order as the service target's: after every join loam defined a line for.
186
+ findings.push(...(await featureLinkFindings({ docsDir, subject: featureId, fleet }, featureDir)));
187
+ findings.push(...(await deltaArchCoverage({
188
+ docsDir,
189
+ elements,
190
+ relationships: deltaRels,
191
+ taggedEls,
192
+ taggedRels,
193
+ archDeltas,
194
+ featureServices,
195
+ scenarioText,
196
+ preloadedLand,
197
+ fleet,
198
+ })));
199
+ // Coherence — cross-axis consistency (C4 ↔ requirements ↔ OpenAPI).
200
+ const issues = await featureCoherence({ docsDir, featureDir, featureId, preloadedDelta: deltaDoc, context: fleet });
201
+ if (issues.length === 0) {
202
+ findings.push({
203
+ severity: "ok",
204
+ code: "coherence.ok",
205
+ message: "coherence: ✓ C4 · requirements · OpenAPI agree",
206
+ text: { indent: 2, marker: false },
207
+ });
208
+ }
209
+ else {
210
+ for (const i of issues) {
211
+ findings.push({ ...issueFinding(i), text: { indent: 4, header: "coherence:" } });
212
+ }
213
+ }
214
+ return { kind: "feature", id: featureId, path: `features/${feature.dirName}`, findings };
215
+ }
216
+ //# sourceMappingURL=feature.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"feature.js","sourceRoot":"","sources":["../../../src/commands/validate/feature.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAuC,MAAM,yBAAyB,CAAC;AACxF,OAAO,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAClE,OAAO,EAAwB,MAAM,kCAAkC,CAAC;AACxE,OAAO,EAAqB,MAAM,4BAA4B,CAAC;AAC/D,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC1E,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AACzE,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC5E,OAAO,EAAmC,MAAM,iCAAiC,CAAC;AAClF,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,EACL,qBAAqB,EACrB,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EAAoB,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AACrE,OAAO,EACL,0BAA0B,EAC1B,0BAA0B,GAC3B,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AACtE,OAAO,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;AACzE,OAAO,EAAE,uBAAuB,EAAE,MAAM,uCAAuC,CAAC;AAChF,OAAO,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AACzE,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AACrF,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAGxD,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,OAAgB,EAChB,OAAqB,EACrB,aAAgC,EAChC,KAAoB;IAEpB,MAAM,QAAQ,GAAc,EAAE,CAAC;IAC/B,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC;IAC/B,MAAM,SAAS,GAAG,OAAO,CAAC,EAAE,CAAC;IAE7B,wEAAwE;IACxE,6EAA6E;IAC7E,6EAA6E;IAC7E,IAAI,SAAS,GAAW,EAAE,CAAC;IAC3B,IAAI,UAAU,GAAU,EAAE,CAAC;IAC3B,IAAI,QAAQ,GAAW,EAAE,CAAC;IAC1B,IAAI,SAAS,GAAU,EAAE,CAAC;IAC1B,IAAI,QAA+B,CAAC;IACpC,MAAM,SAAS,GAAG,YAAY,CAAC,UAAU,CAAC,CAAC,KAAK,CAAC;IACjD,IAAI,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC1B,MAAM,GAAG,GAAG,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;QAChG,QAAQ,GAAG,GAAG,CAAC;QACf,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC1B,QAAQ,CAAC,IAAI,CAAC;gBACZ,QAAQ,EAAE,OAAO;gBACjB,IAAI,EAAE,eAAe;gBACrB,OAAO,EAAE,oBAAoB,GAAG,CAAC,MAAM,CAAC,MAAM,WAAW;gBACzD,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC;aACnC,CAAC,CAAC;QACL,CAAC;aAAM,CAAC;YACN,QAAQ,GAAG,GAAG,CAAC,QAAQ,CAAC;YACxB,SAAS,GAAG,GAAG,CAAC,aAAa,CAAC;YAC9B,SAAS,GAAG,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;YACnE,UAAU,GAAG,GAAG,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;YACzE,QAAQ,CAAC,IAAI,CAAC;gBACZ,QAAQ,EAAE,IAAI;gBACd,IAAI,EAAE,aAAa;gBACnB,OAAO,EAAE,uBAAuB,GAAG,CAAC,QAAQ,CAAC,MAAM,eAAe,GAAG,CAAC,aAAa,CAAC,MAAM,iBAAiB;aAC5G,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,iBAAiB,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC;IAEnE,6EAA6E;IAC7E,4EAA4E;IAC5E,iEAAiE;IACjE,0EAA0E;IAC1E,6EAA6E;IAC7E,8EAA8E;IAC9E,8EAA8E;IAC9E,uDAAuD;IACvD,EAAE;IACF,uEAAuE;IACvE,6EAA6E;IAC7E,wEAAwE;IACxE,0EAA0E;IAC1E,6EAA6E;IAC7E,2EAA2E;IAC3E,4EAA4E;IAC5E,0CAA0C;IAC1C,MAAM,eAAe,GAAG,MAAM,mBAAmB,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;IACrE,MAAM,UAAU,GAAwB,IAAI,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,CAAC;IAC/E,MAAM,aAAa,GAAG,QAAQ,KAAK,SAAS,IAAI,QAAQ,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC;IAC7E,MAAM,UAAU,GAAG,IAAI,GAAG,CAAS,MAAM,oBAAoB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC;IAC/E,MAAM,eAAe,GAAG,aAAa;QACnC,CAAC,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC/E,CAAC,CAAC,EAAE,CAAC;IACP,0EAA0E;IAC1E,kDAAkD;IAClD,MAAM,OAAO,GACX,eAAe,CAAC,MAAM,GAAG,CAAC,IAAI,aAAa,CAAC,OAAO,CAAC,CAAC,IAAI,KAAK,IAAI;QAChE,CAAC,CAAC,CAAC,MAAM,YAAY,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACvD,CAAC,CAAC,EAAE,CAAC;IACT,8EAA8E;IAC9E,8DAA8D;IAC9D,KAAK,MAAM,GAAG,IAAI,eAAe;QAAE,QAAQ,CAAC,IAAI,CAAC,0BAA0B,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC;IAE3F,+EAA+E;IAC/E,+EAA+E;IAC/E,0EAA0E;IAC1E,+EAA+E;IAC/E,+EAA+E;IAC/E,6EAA6E;IAC7E,+DAA+D;IAC/D,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,0BAA0B,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;IAExE,8EAA8E;IAC9E,oEAAoE;IACpE,IAAI,YAAY,GAAG,EAAE,CAAC;IACtB,MAAM,UAAU,GAA6D,EAAE,CAAC;IAChF,KAAK,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;QAClC,MAAM,CAAC,GAAG,gBAAgB,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;QAC5C,IAAI,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;YACvB,MAAM,GAAG,GAAG,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,QAAQ,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YAChG,YAAY,IAAI,IAAI,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC;YACzC,MAAM,IAAI,GAAG,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YACjG,sEAAsE;YACtE,wEAAwE;YACxE,qEAAqE;YACrE,oEAAoE;YACpE,yBAAyB;YACzB,MAAM,QAAQ,GAAG,uBAAuB,CAAC,GAAG,GAAG,WAAW,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;YACtE,IAAI,QAAQ,KAAK,IAAI;gBAAE,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAC/C,QAAQ,CAAC,IAAI,CAAC,EAAE,GAAG,eAAe,CAAC,GAAG,GAAG,gBAAgB,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC;YAClF,QAAQ,CAAC,IAAI,CAAC,GAAG,gBAAgB,CAAC,GAAG,GAAG,gBAAgB,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC;YACtE,QAAQ,CAAC,IAAI,CAAC,GAAG,qBAAqB,CAAC,GAAG,GAAG,gBAAgB,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC;YAC3E,QAAQ,CAAC,IAAI,CAAC,GAAG,gBAAgB,CAAC,GAAG,GAAG,gBAAgB,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC;YACtE,yEAAyE;YACzE,yEAAyE;YACzE,QAAQ,CAAC,IAAI,CAAC,GAAG,wBAAwB,CAAC,IAAI,EAAE,GAAG,GAAG,WAAW,EAAE,GAAG,CAAC,CAAC,CAAC;QAC3E,CAAC;QACD,IAAI,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC3B,MAAM,GAAG,GAAG,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,QAAQ,CAAC,CAAC,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;YACxG,YAAY,IAAI,IAAI,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC;YACzC,MAAM,IAAI,GAAG,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;YACrG,UAAU,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC;YACxC,MAAM,QAAQ,GAAG,uBAAuB,CAAC,GAAG,GAAG,gBAAgB,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;YAC3E,IAAI,QAAQ,KAAK,IAAI;gBAAE,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAC/C,QAAQ,CAAC,IAAI,CAAC,EAAE,GAAG,eAAe,CAAC,GAAG,GAAG,qBAAqB,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC;YACvF,QAAQ,CAAC,IAAI,CAAC,GAAG,gBAAgB,CAAC,GAAG,GAAG,qBAAqB,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC;YAC3E,QAAQ,CAAC,IAAI,CAAC,GAAG,qBAAqB,CAAC,GAAG,GAAG,qBAAqB,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC;YAChF,QAAQ,CAAC,IAAI,CAAC,GAAG,gBAAgB,CAAC,GAAG,GAAG,qBAAqB,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC;YAC3E,QAAQ,CAAC,IAAI,CAAC,GAAG,wBAAwB,CAAC,IAAI,EAAE,GAAG,GAAG,gBAAgB,EAAE,GAAG,CAAC,CAAC,CAAC;QAChF,CAAC;IACH,CAAC;IAED,4EAA4E;IAC5E,yEAAyE;IACzE,0EAA0E;IAC1E,4EAA4E;IAC5E,8EAA8E;IAC9E,qEAAqE;IACrE,0EAA0E;IAC1E,4BAA4B;IAC5B,MAAM,gBAAgB,GACpB,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,uBAAuB,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,uBAAuB,CAAC,UAAU,CAAC,CAAC;IACpH,8EAA8E;IAC9E,8EAA8E;IAC9E,+EAA+E;IAC/E,4EAA4E;IAC5E,2EAA2E;IAC3E,6FAA6F;IAC7F,0EAA0E;IAC1E,oEAAoE;IACpE,QAAQ,CAAC,IAAI,CAAC,GAAG,kBAAkB,CAAC,gBAAgB,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;IACxE,KAAK,MAAM,GAAG,IAAI,gBAAgB,CAAC,IAAI,EAAE,CAAC;QACxC,MAAM,GAAG,GAAG,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACpG,MAAM,QAAQ,GAAG,uBAAuB,CAAC,cAAc,GAAG,CAAC,EAAE,WAAW,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;QACvF,IAAI,QAAQ,KAAK,IAAI;YAAE,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACjD,CAAC;IAED,4EAA4E;IAC5E,yEAAyE;IACzE,2EAA2E;IAC3E,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,mBAAmB,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC;IAElG,QAAQ,CAAC,IAAI,CACX,GAAG,CAAC,MAAM,iBAAiB,CAAC;QAC1B,OAAO;QACP,QAAQ;QACR,aAAa,EAAE,SAAS;QACxB,SAAS;QACT,UAAU;QACV,UAAU;QACV,eAAe;QACf,YAAY;QACZ,aAAa;QACb,KAAK;KACN,CAAC,CAAC,CACJ,CAAC;IAGF,oEAAoE;IACpE,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,cAAc,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;IACpH,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,QAAQ,CAAC,IAAI,CAAC;YACZ,QAAQ,EAAE,IAAI;YACd,IAAI,EAAE,cAAc;YACpB,OAAO,EAAE,gDAAgD;YACzD,IAAI,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE;SACnC,CAAC,CAAC;IACL,CAAC;SAAM,CAAC;QACN,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;YACvB,QAAQ,CAAC,IAAI,CAAC,EAAE,GAAG,YAAY,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,EAAE,CAAC,CAAC;QACnF,CAAC;IACH,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,YAAY,OAAO,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,CAAC;AAC3F,CAAC","sourcesContent":["/**\n * The feature target: a delta graded on its own, before anything merges.\n *\n * Everything here reads the feature directory — delta.likec4, the per-service\n * spec.md/arch.spec.md deltas, the provenance stamp — and grades the documents\n * a merge is about to fold into living ones. A delta is held to the same\n * document rules as the file it becomes (`./checks/requirements.js`), because\n * grading it more leniently is how a defect acquires a signature saying it was\n * reviewed.\n *\n * The one question that needs the LIVING fleet — what in this delta is actually\n * new architecture — is `./arch-coverage.js`.\n */\nimport { existsSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport { loadFile, type Elem, type LoadedDoc, type Rel } from \"../../core/c4/likec4.js\";\nimport { elementService } from \"../../core/c4/resolve/service.js\";\nimport { type PathableService } from \"../../core/kernel/ids/service.js\";\nimport { type FeatureEntry } from \"../../core/repo/entries.js\";\nimport { featurePaths, featureSpecPaths } from \"../../core/repo/paths.js\";\nimport { enumeratedServiceIds } from \"../../core/repo/service-target.js\";\nimport { docsRepoState } from \"../../core/repo/state.js\";\nimport { featureSpecServices, listServices } from \"../../core/repo/repo.js\";\nimport { type Finding, type TargetReport } from \"../../core/vocabulary/report.js\";\nimport { parseRequirements } from \"../../core/document/parse.js\";\nimport {\n assertionlessFindings,\n examplesFindings,\n steplessFindings,\n} from \"../../core/document/scenarios.js\";\nimport { type Requirement } from \"../../core/document/spec.js\";\nimport { featureCoherence } from \"../../core/coherence/coherence.js\";\nimport {\n deltaServiceUnknownFinding,\n invalidSpecServiceFindings,\n} from \"../../core/coherence/living.js\";\nimport { issueFinding } from \"../../core/vocabulary/issue.js\";\nimport { featureProvenance } from \"../../core/provenance/findings.js\";\nimport { documentConflictFinding } from \"../../core/conflict-markers.js\";\nimport { featureCapabilityDeltas } from \"../../core/capabilities/delta/tree.js\";\nimport { docMissingFindings } from \"../../core/capabilities/findings.js\";\nimport { FleetContext } from \"../../core/fleet-context.js\";\nimport { errorText } from \"./checks/vocabulary.js\";\nimport { coverageFinding, repeatedListLineFindings } from \"./checks/requirements.js\";\nimport { deltaArchCoverage } from \"./arch-coverage.js\";\nimport { featureLinkFindings } from \"./links/corpus.js\";\nimport type { DocsDir } from \"../../core/kernel/ids/dirs.js\";\n\nexport async function validateFeature(\n docsDir: DocsDir,\n feature: FeatureEntry,\n preloadedLand?: LoadedDoc | null,\n fleet?: FleetContext,\n): Promise<TargetReport> {\n const findings: Finding[] = [];\n const featureDir = feature.dir;\n const featureId = feature.id;\n\n // delta.likec4 parse + collect tagged edges. The loaded doc is kept and\n // handed to featureCoherence below — loading it is a Langium workspace spin,\n // and paying it twice per feature was the dominant cost of `validate --all`.\n let taggedEls: Elem[] = [];\n let taggedRels: Rel[] = [];\n let elements: Elem[] = [];\n let deltaRels: Rel[] = [];\n let deltaDoc: LoadedDoc | undefined;\n const deltaPath = featurePaths(featureDir).delta;\n if (existsSync(deltaPath)) {\n const res = fleet === undefined ? await loadFile(deltaPath) : await fleet.loadLikeC4(deltaPath);\n deltaDoc = res;\n if (res.errors.length > 0) {\n findings.push({\n severity: \"error\",\n code: \"delta.invalid\",\n message: `delta.likec4 has ${res.errors.length} error(s)`,\n details: res.errors.map(errorText),\n });\n } else {\n elements = res.elements;\n deltaRels = res.relationships;\n taggedEls = res.elements.filter((e) => e.tags.includes(featureId));\n taggedRels = res.relationships.filter((r) => r.tags.includes(featureId));\n findings.push({\n severity: \"ok\",\n code: \"delta.valid\",\n message: `delta.likec4 valid (${res.elements.length} elements · ${res.relationships.length} relationships)`,\n });\n }\n }\n\n findings.push(...(await featureProvenance(featureDir, featureId)));\n\n // Who this feature is allowed to address. `specs/<svc>/` is what the archive\n // materialises `services/<svc>/` from, and nothing used to ask whether that\n // name means anything: one wrong character in `--touches` passed\n // `validate --all` with zero errors, and archive then created the phantom\n // directory. A delta may legitimately name a service that does not exist yet\n // — but only one it INTRODUCES itself, in its own tagged C4. A delta that did\n // not parse proves neither (`delta.invalid` is that finding), so the question\n // is suspended there rather than answered by guessing.\n //\n // Existence is enumeration MEMBERSHIP through the no-services-tolerant\n // spelling, never `existsSync(services/<svc>/)` at the root: a service filed\n // into a subsystem exists wherever the tree walk found it, and the root\n // probe graded every filed service `delta.service-unknown`. The tolerance\n // carries the old carve-out forward — `validate --feature` is allowed to run\n // in a docs repo with no services/ at all, where enumerating is a refusal;\n // `enumeratedServiceIds` swallows exactly that refusal to an empty list, in\n // which every service is honestly absent.\n const featureServices = await featureSpecServices(featureDir, fleet);\n const introduces: ReadonlySet<string> = new Set(taggedEls.map(elementService));\n const deltaReadable = deltaDoc === undefined || deltaDoc.errors.length === 0;\n const enumerated = new Set<string>(await enumeratedServiceIds(docsDir, fleet));\n const unknownServices = deltaReadable\n ? featureServices.filter((svc) => !enumerated.has(svc) && !introduces.has(svc))\n : [];\n // The near-miss hint, on the same rule `service.unknown` uses — a typo is\n // only diagnosable against the ids that DO exist.\n const closeTo =\n unknownServices.length > 0 && docsRepoState(docsDir).kind === \"ok\"\n ? (await listServices(docsDir, fleet)).map((s) => s.id)\n : [];\n // The finding is coherence/living.ts's — the same words archive refuses with,\n // because it is the same conclusion about the same directory.\n for (const svc of unknownServices) findings.push(deltaServiceUnknownFinding(svc, closeTo));\n\n // The grammar half of the same guarantee. `delta.service-unknown` asks whether\n // the directory names a service anyone knows; this asks whether the NAME could\n // ever be one. The two are independent on purpose: a tagged element whose\n // title matches the directory answers the first question, which is exactly how\n // `specs/Payment Service/` used to validate green and archive into a directory\n // no loam command can address. Not suspended on an unreadable delta either —\n // no reading of the architecture axis can make the name legal.\n findings.push(...(await invalidSpecServiceFindings(featureDir, fleet)));\n\n // Requirement coverage across every per-service delta — the business spec and\n // the arch spec through the same check — and collect scenario text.\n let scenarioText = \"\";\n const archDeltas: Array<{ service: PathableService; reqs: Requirement[] }> = [];\n for (const svc of featureServices) {\n const p = featureSpecPaths(featureDir, svc);\n if (existsSync(p.spec)) {\n const raw = fleet === undefined ? await readFile(p.spec, \"utf8\") : await fleet.readText(p.spec);\n scenarioText += \"\\n\" + raw.toLowerCase();\n const reqs = fleet === undefined ? parseRequirements(raw) : await fleet.readRequirements(p.spec);\n // Both document-level breaches carry into the living spec through the\n // merge, so a delta is graded for them exactly as a living document is:\n // conflict markers merge as prose under someone's requirement, and a\n // stepless scenario merges as a requirement the coverage rule calls\n // covered forever after.\n const conflict = documentConflictFinding(`${svc}: spec.md`, svc, raw);\n if (conflict !== null) findings.push(conflict);\n findings.push({ ...coverageFinding(`${svc}: requirements`, reqs), subject: svc });\n findings.push(...steplessFindings(`${svc}: requirements`, svc, reqs));\n findings.push(...assertionlessFindings(`${svc}: requirements`, svc, reqs));\n findings.push(...examplesFindings(`${svc}: requirements`, svc, reqs));\n // The keep-last quirk loses lines in a delta exactly as in a living spec\n // — and a delta's lost Operations: line then merges into the living one.\n findings.push(...repeatedListLineFindings(reqs, `${svc}: spec.md`, svc));\n }\n if (existsSync(p.archSpec)) {\n const raw = fleet === undefined ? await readFile(p.archSpec, \"utf8\") : await fleet.readText(p.archSpec);\n scenarioText += \"\\n\" + raw.toLowerCase();\n const reqs = fleet === undefined ? parseRequirements(raw) : await fleet.readRequirements(p.archSpec);\n archDeltas.push({ service: svc, reqs });\n const conflict = documentConflictFinding(`${svc}: arch.spec.md`, svc, raw);\n if (conflict !== null) findings.push(conflict);\n findings.push({ ...coverageFinding(`${svc}: arch requirements`, reqs), subject: svc });\n findings.push(...steplessFindings(`${svc}: arch requirements`, svc, reqs));\n findings.push(...assertionlessFindings(`${svc}: arch requirements`, svc, reqs));\n findings.push(...examplesFindings(`${svc}: arch requirements`, svc, reqs));\n findings.push(...repeatedListLineFindings(reqs, `${svc}: arch.spec.md`, svc));\n }\n }\n\n // The BUSINESS corpus's delta documents, graded for the same document-level\n // breach as the service ones and for the same reason: a conflicted delta\n // parses as prose, so every other check reads it as a valid document, and\n // `loam archive` then re-serializes both sides of somebody's merge into the\n // LIVING capability document. It is worse there than one tree over — once the\n // feature is archived, nothing walks the delta again, and the living\n // capability documents are only conflict-scanned while some feature still\n // carries a delta for them.\n const capabilityDeltas =\n fleet === undefined ? await featureCapabilityDeltas(featureDir) : await fleet.featureCapabilityDeltas(featureDir);\n // The half-created directory, on the FEATURE side. The living tree has warned\n // about `capabilities/<id>/` with no document since the axis landed; the same\n // `mkdir` inside `features/<FEAT>/capabilities/` earned nothing, and it is the\n // quieter of the two — an empty directory is not a delta, so the walk finds\n // no document, the merge carries nothing, and the business change ships as\n // zero at exit 0. Same code, feature-scoped message (`../../core/capabilities/findings.ts`).\n // `dirName`, not the id: the directory is `features/FEAT-1-split/`, and a\n // message spelling `features/FEAT-1/` names a path nobody can open.\n findings.push(...docMissingFindings(capabilityDeltas, feature.dirName));\n for (const doc of capabilityDeltas.docs) {\n const raw = fleet === undefined ? await readFile(doc.spec, \"utf8\") : await fleet.readText(doc.spec);\n const conflict = documentConflictFinding(`capability ${doc.id}: spec.md`, doc.id, raw);\n if (conflict !== null) findings.push(conflict);\n }\n\n // The links this feature's own documents write — the intent, each service's\n // two spec deltas, its ADRs and its capability deltas. Same place in the\n // order as the service target's: after every join loam defined a line for.\n findings.push(...(await featureLinkFindings({ docsDir, subject: featureId, fleet }, featureDir)));\n\n findings.push(\n ...(await deltaArchCoverage({\n docsDir,\n elements,\n relationships: deltaRels,\n taggedEls,\n taggedRels,\n archDeltas,\n featureServices,\n scenarioText,\n preloadedLand,\n fleet,\n })),\n );\n\n\n // Coherence — cross-axis consistency (C4 ↔ requirements ↔ OpenAPI).\n const issues = await featureCoherence({ docsDir, featureDir, featureId, preloadedDelta: deltaDoc, context: fleet });\n if (issues.length === 0) {\n findings.push({\n severity: \"ok\",\n code: \"coherence.ok\",\n message: \"coherence: ✓ C4 · requirements · OpenAPI agree\",\n text: { indent: 2, marker: false },\n });\n } else {\n for (const i of issues) {\n findings.push({ ...issueFinding(i), text: { indent: 4, header: \"coherence:\" } });\n }\n }\n\n return { kind: \"feature\", id: featureId, path: `features/${feature.dirName}`, findings };\n}\n"]}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * The fleet map's census: which drawn elements answer for a `services/<id>/`.
3
+ *
4
+ * Three predicates, in one place because every exemption in the fleet target,
5
+ * the scorecard's `c4.elements` count and the kind-tag check all have to answer
6
+ * the same question the same way — a second spelling of "is this element a
7
+ * service" is how a map and a rollup start disagreeing about the same fleet.
8
+ * They lived in `./landscape.ts` beside their first reader until that file hit
9
+ * its line limit; the seam was already there, since nothing here reads a file,
10
+ * emits a finding, or knows what a target is.
11
+ */
12
+ import {} from "../../../core/c4/likec4.js";
13
+ import { ACTOR_KINDS, EXTERNAL_TAG } from "../../../core/vocabulary/maturity.js";
14
+ /**
15
+ * Does this element stand for a `services/<id>/` directory — an explicit
16
+ * `metadata { service }` binding, or a title naming a real one? The question
17
+ * every exemption in `./landscape.ts`, the scorecard's census and
18
+ * `./kind-tags.ts` all ask, exported so they cannot answer it differently.
19
+ */
20
+ export function standsForService(e, services) {
21
+ return e.service !== undefined || services.has(e.title);
22
+ }
23
+ /**
24
+ * Service-LEVEL elements: everything not drawn inside something that is
25
+ * already a service.
26
+ *
27
+ * Depth is not a fact about a service. This used to keep only top-level
28
+ * elements (`!e.id.includes(".")`), which ordinary C4 breaks the moment it
29
+ * groups services under a parent: every nested element was thrown away, so a
30
+ * bound service read as unmodelled — an ERROR, on every service in the fleet
31
+ * — and a binding written one level down was never checked at all. The tree
32
+ * is walked instead, the way `serviceResolver` walks it for edges: a binding
33
+ * wins at any depth, then a title naming a real services/<id>/, and what sits
34
+ * INSIDE one of those is that service's container, not a service of its own.
35
+ */
36
+ export function serviceLevelElements(elements, services) {
37
+ const byId = new Map(elements.map((e) => [e.id, e]));
38
+ /** Declared ancestors of an element, nearest first. */
39
+ const ancestorsOf = (e) => {
40
+ const out = [];
41
+ for (let dot = e.id.lastIndexOf("."); dot !== -1; dot = e.id.lastIndexOf(".", dot - 1)) {
42
+ const parent = byId.get(e.id.slice(0, dot));
43
+ if (parent !== undefined)
44
+ out.push(parent);
45
+ }
46
+ return out;
47
+ };
48
+ return elements.filter((e) => !ancestorsOf(e).some((p) => standsForService(p, services)));
49
+ }
50
+ /**
51
+ * The drawn SYSTEMS: service-level elements minus everything the map itself
52
+ * says is not a service. Actor kinds model people; `#external` is somebody
53
+ * else's system; and an element that CONTAINS a service is a grouping — a
54
+ * domain, a boundary, an enterprise — not a service nobody adopted. There is
55
+ * nothing to bind on a grouping and nothing to tag #external, so asking for
56
+ * either would be a warning with no correct fix; the services under it answer
57
+ * for themselves. `validateLandscape`'s undocumented pass walks this set, and
58
+ * the scorecard's `c4.elements` census counts it — one predicate, two readers,
59
+ * zero drift.
60
+ *
61
+ * The `#external` skip here is exactly what `./kind-tags.ts` guards: read off a
62
+ * tag a KIND declared, it can empty this census for a whole fleet at once.
63
+ */
64
+ export function drawnSystems(elements, services) {
65
+ return serviceLevelElements(elements, services).filter((e) => !e.tags.includes(EXTERNAL_TAG) &&
66
+ !ACTOR_KINDS.has(e.kind.toLowerCase()) &&
67
+ !elements.some((c) => c.id.startsWith(`${e.id}.`) && standsForService(c, services)));
68
+ }
69
+ //# sourceMappingURL=census.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"census.js","sourceRoot":"","sources":["../../../../src/commands/validate/fleet/census.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAa,MAAM,4BAA4B,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,sCAAsC,CAAC;AAEjF;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAAC,CAAO,EAAE,QAA6B;IACrE,OAAO,CAAC,CAAC,OAAO,KAAK,SAAS,IAAI,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;AAC1D,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,oBAAoB,CAAC,QAAgB,EAAE,QAA6B;IAClF,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IACrD,uDAAuD;IACvD,MAAM,WAAW,GAAG,CAAC,CAAO,EAAU,EAAE;QACtC,MAAM,GAAG,GAAW,EAAE,CAAC;QACvB,KAAK,IAAI,GAAG,GAAG,CAAC,CAAC,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,GAAG,KAAK,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,CAAC,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,GAAG,CAAC,CAAC,EAAE,CAAC;YACvF,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;YAC5C,IAAI,MAAM,KAAK,SAAS;gBAAE,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC7C,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC,CAAC;IACF,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,gBAAgB,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC;AAC5F,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,YAAY,CAAC,QAAgB,EAAE,QAA6B;IAC1E,OAAO,oBAAoB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,MAAM,CACpD,CAAC,CAAC,EAAE,EAAE,CACJ,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC;QAC9B,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;QACtC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,gBAAgB,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CACtF,CAAC;AACJ,CAAC","sourcesContent":["/**\n * The fleet map's census: which drawn elements answer for a `services/<id>/`.\n *\n * Three predicates, in one place because every exemption in the fleet target,\n * the scorecard's `c4.elements` count and the kind-tag check all have to answer\n * the same question the same way — a second spelling of \"is this element a\n * service\" is how a map and a rollup start disagreeing about the same fleet.\n * They lived in `./landscape.ts` beside their first reader until that file hit\n * its line limit; the seam was already there, since nothing here reads a file,\n * emits a finding, or knows what a target is.\n */\nimport { type Elem } from \"../../../core/c4/likec4.js\";\nimport { ACTOR_KINDS, EXTERNAL_TAG } from \"../../../core/vocabulary/maturity.js\";\n\n/**\n * Does this element stand for a `services/<id>/` directory — an explicit\n * `metadata { service }` binding, or a title naming a real one? The question\n * every exemption in `./landscape.ts`, the scorecard's census and\n * `./kind-tags.ts` all ask, exported so they cannot answer it differently.\n */\nexport function standsForService(e: Elem, services: ReadonlySet<string>): boolean {\n return e.service !== undefined || services.has(e.title);\n}\n\n/**\n * Service-LEVEL elements: everything not drawn inside something that is\n * already a service.\n *\n * Depth is not a fact about a service. This used to keep only top-level\n * elements (`!e.id.includes(\".\")`), which ordinary C4 breaks the moment it\n * groups services under a parent: every nested element was thrown away, so a\n * bound service read as unmodelled — an ERROR, on every service in the fleet\n * — and a binding written one level down was never checked at all. The tree\n * is walked instead, the way `serviceResolver` walks it for edges: a binding\n * wins at any depth, then a title naming a real services/<id>/, and what sits\n * INSIDE one of those is that service's container, not a service of its own.\n */\nexport function serviceLevelElements(elements: Elem[], services: ReadonlySet<string>): Elem[] {\n const byId = new Map(elements.map((e) => [e.id, e]));\n /** Declared ancestors of an element, nearest first. */\n const ancestorsOf = (e: Elem): Elem[] => {\n const out: Elem[] = [];\n for (let dot = e.id.lastIndexOf(\".\"); dot !== -1; dot = e.id.lastIndexOf(\".\", dot - 1)) {\n const parent = byId.get(e.id.slice(0, dot));\n if (parent !== undefined) out.push(parent);\n }\n return out;\n };\n return elements.filter((e) => !ancestorsOf(e).some((p) => standsForService(p, services)));\n}\n\n/**\n * The drawn SYSTEMS: service-level elements minus everything the map itself\n * says is not a service. Actor kinds model people; `#external` is somebody\n * else's system; and an element that CONTAINS a service is a grouping — a\n * domain, a boundary, an enterprise — not a service nobody adopted. There is\n * nothing to bind on a grouping and nothing to tag #external, so asking for\n * either would be a warning with no correct fix; the services under it answer\n * for themselves. `validateLandscape`'s undocumented pass walks this set, and\n * the scorecard's `c4.elements` census counts it — one predicate, two readers,\n * zero drift.\n *\n * The `#external` skip here is exactly what `./kind-tags.ts` guards: read off a\n * tag a KIND declared, it can empty this census for a whole fleet at once.\n */\nexport function drawnSystems(elements: Elem[], services: ReadonlySet<string>): Elem[] {\n return serviceLevelElements(elements, services).filter(\n (e) =>\n !e.tags.includes(EXTERNAL_TAG) &&\n !ACTOR_KINDS.has(e.kind.toLowerCase()) &&\n !elements.some((c) => c.id.startsWith(`${e.id}.`) && standsForService(c, services)),\n );\n}\n"]}
@@ -0,0 +1,39 @@
1
+ import { GRADED_TAGS } from "../../../core/vocabulary/maturity.js";
2
+ import {} from "../../../core/vocabulary/report.js";
3
+ import { standsForService } from "./census.js";
4
+ /**
5
+ * One finding per (kind, graded tag) whose elements include something that
6
+ * stands for a real service directory. An ERROR, not a warning: the whole point
7
+ * is that the run must not be able to end green, and a warning leaves exit code
8
+ * 0 for every caller not passing `--strict`.
9
+ */
10
+ export function kindTagFindings(input) {
11
+ const { specification, elements, services } = input;
12
+ if (specification === undefined)
13
+ return [];
14
+ const findings = [];
15
+ for (const [kind, tags] of Object.entries(specification.elementKindTags)) {
16
+ const graded = tags.filter((t) => GRADED_TAGS.includes(t));
17
+ if (graded.length === 0)
18
+ continue;
19
+ const ours = elements.filter((e) => e.kind === kind && standsForService(e, services));
20
+ if (ours.length === 0)
21
+ continue;
22
+ const named = ours.slice(0, 3).map((e) => `'${e.title}'`).join(", ");
23
+ for (const tag of graded) {
24
+ findings.push({
25
+ severity: "error",
26
+ code: "landscape.kind-tag-graded",
27
+ subject: kind,
28
+ message: `landscape: the specification declares '#${tag}' on element kind '${kind}', so every '${kind}' ` +
29
+ `inherits it — including ${ours.length} that stand(s) for a services/ directory of ours ` +
30
+ `(${named}${ours.length > 3 ? ", …" : ""}). loam reads '#${tag}' as "not ours, stop grading", so the ` +
31
+ `landscape↔services checks are silenced for exactly the elements they exist for. Remove '#${tag}' from ` +
32
+ `the kind and write it on the individual elements that really are foreign — or, if every '${kind}' is ` +
33
+ `foreign, stop drawing our services as one.`,
34
+ });
35
+ }
36
+ }
37
+ return findings;
38
+ }
39
+ //# sourceMappingURL=kind-tags.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kind-tags.js","sourceRoot":"","sources":["../../../../src/commands/validate/fleet/kind-tags.ts"],"names":[],"mappings":"AA8DA,OAAO,EAAE,WAAW,EAAE,MAAM,sCAAsC,CAAC;AACnE,OAAO,EAAgB,MAAM,oCAAoC,CAAC;AAClE,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAW/C;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,KAAmB;IACjD,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAC;IACpD,IAAI,aAAa,KAAK,SAAS;QAAE,OAAO,EAAE,CAAC;IAC3C,MAAM,QAAQ,GAAc,EAAE,CAAC;IAC/B,KAAK,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,eAAe,CAAC,EAAE,CAAC;QACzE,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3D,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS;QAClC,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,IAAI,gBAAgB,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC;QACtF,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS;QAChC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrE,KAAK,MAAM,GAAG,IAAI,MAAM,EAAE,CAAC;YACzB,QAAQ,CAAC,IAAI,CAAC;gBACZ,QAAQ,EAAE,OAAO;gBACjB,IAAI,EAAE,2BAA2B;gBACjC,OAAO,EAAE,IAAI;gBACb,OAAO,EACL,2CAA2C,GAAG,sBAAsB,IAAI,gBAAgB,IAAI,IAAI;oBAChG,2BAA2B,IAAI,CAAC,MAAM,mDAAmD;oBACzF,IAAI,KAAK,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,mBAAmB,GAAG,wCAAwC;oBACtG,4FAA4F,GAAG,SAAS;oBACxG,4FAA4F,IAAI,OAAO;oBACvG,4CAA4C;aAC/C,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC","sourcesContent":["/**\n * The fleet gate's guard against a tag loam grades on exempting a service.\n *\n * LikeC4 1.59.0 added tags in the specification block, and 1.59.2 applies them\n * before loam sees anything: `specification { element softwareSystem {\n * #external } }` makes EVERY softwareSystem in the document carry `#external`,\n * on `Elem.tags`, indistinguishable from a tag somebody wrote on the element.\n *\n * loam reads `#external` as \"deliberately not ours — stop grading it\". So those\n * six words switched the landscape↔services reconciliation off for the whole\n * fleet, and the gate then printed `landscape.matched` — \"N service(s) modelled\n * … and services/ agree\" — over a map it had stopped checking. That is the worst\n * failure this product has: not a wrong answer, but a green one.\n *\n * ## Why this is not simply \"refuse a graded tag on a kind\"\n *\n * Because a graded tag on a kind is a pattern loam DOCUMENTS and the shipped\n * example depends on. `examples/docs/architecture/landscape.likec4` declares\n *\n * element topic { #external #platform style { shape queue } }\n *\n * so that the Kafka topics nested inside an external broker do not each demand a\n * `services/payment.events/` nobody owes. Every `topic` is foreign by\n * construction; saying so once on the kind is the spelling that scales, and\n * test/landscape.test.ts has pinned it since long before kind tags existed.\n * Refusing that would be loam breaking its own published fleet map.\n *\n * The line is therefore not WHERE the tag is written but WHAT it exempts:\n *\n * - a kind whose elements stand for nothing in `services/` — `topic`,\n * `externalSystem`, `saasVendor` — is the legitimate idiom, and silent here;\n * - a kind whose elements stand for a REAL `services/<id>/` directory, by an\n * explicit `metadata { service }` binding or by a title naming one, is the\n * fail-open. That element is provably ours and provably exempted, and loam\n * has just been told to stop grading the thing it exists to grade.\n *\n * The second case is also exactly where the suppression reaches ERROR severity:\n * `landscape.binding-unknown` — a binding naming a directory that does not exist\n * — is skipped for `#external` elements, and only a bound element can raise it.\n *\n * Two further limits, both deliberate:\n *\n * - Only the tags in `GRADED_TAGS`. A kind declaring `#tier1` or `#legacy` is\n * ordinary LikeC4 that loam does not read, and refusing it would be loam\n * inventing a rule about somebody else's vocabulary.\n * - Relationship kinds are not graded. loam reads no relationship tag on the\n * landscape — `#external` and `#platform` are asked of elements only — so a\n * relationship kind declaring one changes no conclusion. The relationship\n * half of the same defect bites on the FEATURE tag at archive time, and is\n * refused there (`commands/archive/plan/landscape.ts`), where it costs\n * something.\n *\n * A residual is accepted knowingly: a kind-wide graded tag over elements that\n * stand for no directory still silences `landscape.service-undocumented` for\n * them. That is the `topic` idiom's whole purpose, and it cannot be told from\n * abuse without loam guessing which foreign systems somebody meant to adopt.\n * `landscape.service-unmodelled` — the ERROR that a `services/<id>/` is undrawn\n * — reads no tags at all, so the fleet's own directories are never exempted by\n * any of this.\n */\nimport type { Elem } from \"../../../core/c4/likec4.js\";\nimport type { DocSpecification } from \"../../../core/c4/parsed/specification.js\";\nimport { GRADED_TAGS } from \"../../../core/vocabulary/maturity.js\";\nimport { type Finding } from \"../../../core/vocabulary/report.js\";\nimport { standsForService } from \"./census.js\";\n\nexport interface KindTagInput {\n /** The landscape's own specification block; absent for a document that did not parse. */\n specification: DocSpecification | undefined;\n /** Every element the landscape declares, at any depth. */\n elements: Elem[];\n /** The `services/<id>/` directories that exist — what \"ours\" is measured against. */\n services: ReadonlySet<string>;\n}\n\n/**\n * One finding per (kind, graded tag) whose elements include something that\n * stands for a real service directory. An ERROR, not a warning: the whole point\n * is that the run must not be able to end green, and a warning leaves exit code\n * 0 for every caller not passing `--strict`.\n */\nexport function kindTagFindings(input: KindTagInput): Finding[] {\n const { specification, elements, services } = input;\n if (specification === undefined) return [];\n const findings: Finding[] = [];\n for (const [kind, tags] of Object.entries(specification.elementKindTags)) {\n const graded = tags.filter((t) => GRADED_TAGS.includes(t));\n if (graded.length === 0) continue;\n const ours = elements.filter((e) => e.kind === kind && standsForService(e, services));\n if (ours.length === 0) continue;\n const named = ours.slice(0, 3).map((e) => `'${e.title}'`).join(\", \");\n for (const tag of graded) {\n findings.push({\n severity: \"error\",\n code: \"landscape.kind-tag-graded\",\n subject: kind,\n message:\n `landscape: the specification declares '#${tag}' on element kind '${kind}', so every '${kind}' ` +\n `inherits it — including ${ours.length} that stand(s) for a services/ directory of ours ` +\n `(${named}${ours.length > 3 ? \", …\" : \"\"}). loam reads '#${tag}' as \"not ours, stop grading\", so the ` +\n `landscape↔services checks are silenced for exactly the elements they exist for. Remove '#${tag}' from ` +\n `the kind and write it on the individual elements that really are foreign — or, if every '${kind}' is ` +\n `foreign, stop drawing our services as one.`,\n });\n }\n }\n return findings;\n}\n"]}