@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,75 @@
1
+ /**
2
+ * `glossary.unlinked` — a defined term that no document outside the glossary
3
+ * cites.
4
+ *
5
+ * The mirror of `permissions.unenforced` and `capability.unrealized`, and it
6
+ * earns its place for their reason: a vocabulary is worth what cites it. A term
7
+ * nobody links to is either a word the fleet never adopted or a definition left
8
+ * behind by a rename — both are drift, and neither is visible from inside the
9
+ * file. WARN, because the honest answer is often "not written up yet", and
10
+ * because a glossary must be safe to start: a fleet that defines twenty terms
11
+ * on a Monday and cites four of them is adopting the axis, not failing it.
12
+ *
13
+ * A TERM CITED ONLY BY OTHER TERMS IS STILL UNLINKED, and this is the judgement
14
+ * that keeps the warning worth anything. A glossary is a network of definitions,
15
+ * so `order-line` linking to `order` is normal and correct — and it proves
16
+ * nothing about whether the FLEET uses either word. The same reasoning
17
+ * `capability.requirement-inert-join` applies one axis over: a join written
18
+ * inside the tree is not evidence about the world outside it. The intra-glossary
19
+ * citations are listed in `details` rather than hidden, because they are the
20
+ * first thing a reader will otherwise go looking for.
21
+ *
22
+ * ONE FINDING FOR THE WHOLE GLOSSARY when nothing cites anything, and one per
23
+ * term otherwise. A fleet that has just created `glossary/` and written its
24
+ * first eight definitions would otherwise get eight identical warnings saying
25
+ * the same thing about the same afternoon's work.
26
+ */
27
+ import { backlinkIndex } from "../../../core/links/backlinks.js";
28
+ import { readGlossary } from "../../../core/glossary/tree.js";
29
+ import { glossaryDir } from "../../../core/repo/authored/paths.js";
30
+ import { repoPath } from "../../../core/envelope/json.js";
31
+ import { FleetContext } from "../../../core/fleet-context.js";
32
+ import {} from "../../../core/vocabulary/report.js";
33
+ export async function glossaryFindings(docsDir, fleet) {
34
+ const root = glossaryDir(docsDir);
35
+ const glossary = await readGlossary(root);
36
+ // The directory's existence is the axis's opt-in, exactly as
37
+ // `architecture/capabilities.yaml` and `capabilities/` are the business
38
+ // axis's. A fleet without one pays a single `existsSync` and hears nothing —
39
+ // and the whole fleet-wide link walk below is never built.
40
+ if (!glossary.present || glossary.terms.length === 0)
41
+ return [];
42
+ const index = await backlinkIndex(docsDir, fleet);
43
+ const inGlossary = (source) => source.startsWith(`${repoPath(docsDir, root)}/`);
44
+ const unlinked = glossary.terms
45
+ .map((term) => ({ term, cited: index.linkersOf(term.path) }))
46
+ .map(({ term, cited }) => ({ term, outside: cited.filter((s) => !inGlossary(s)), within: cited.filter(inGlossary) }))
47
+ .filter(({ outside }) => outside.length === 0);
48
+ if (unlinked.length === 0)
49
+ return [];
50
+ // The whole vocabulary uncited is one fact about one afternoon, not N facts.
51
+ if (unlinked.length === glossary.terms.length && glossary.terms.length > 1) {
52
+ return [
53
+ {
54
+ severity: "warn",
55
+ code: "glossary.unlinked",
56
+ message: `glossary: none of the ${glossary.terms.length} defined term(s) is linked from any document outside glossary/. ` +
57
+ "A term becomes checkable when a requirement, capability or intent cites it — " +
58
+ "`[Order](../../glossary/order.md)` — and until then the definitions are a document nothing joins to.",
59
+ details: unlinked.map(({ term }) => term.id),
60
+ },
61
+ ];
62
+ }
63
+ return unlinked.map(({ term, within }) => ({
64
+ severity: "warn",
65
+ code: "glossary.unlinked",
66
+ subject: term.id,
67
+ message: `glossary/${term.id}.md is linked from no document outside glossary/` +
68
+ (within.length === 0
69
+ ? " — either a word the fleet has not adopted, or a definition left behind by a rename."
70
+ : ", only from other terms — which says the glossary is consistent, not that the fleet uses the word.") +
71
+ ` Cite it as \`[${term.id}](<relative>/glossary/${term.id}.md)\` from the requirement or capability that uses it, or delete the definition.`,
72
+ ...(within.length === 0 ? {} : { details: within }),
73
+ }));
74
+ }
75
+ //# sourceMappingURL=glossary.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"glossary.js","sourceRoot":"","sources":["../../../../src/commands/validate/links/glossary.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `glossary.unlinked` — a defined term that no document outside the glossary\n * cites.\n *\n * The mirror of `permissions.unenforced` and `capability.unrealized`, and it\n * earns its place for their reason: a vocabulary is worth what cites it. A term\n * nobody links to is either a word the fleet never adopted or a definition left\n * behind by a rename — both are drift, and neither is visible from inside the\n * file. WARN, because the honest answer is often \"not written up yet\", and\n * because a glossary must be safe to start: a fleet that defines twenty terms\n * on a Monday and cites four of them is adopting the axis, not failing it.\n *\n * A TERM CITED ONLY BY OTHER TERMS IS STILL UNLINKED, and this is the judgement\n * that keeps the warning worth anything. A glossary is a network of definitions,\n * so `order-line` linking to `order` is normal and correct — and it proves\n * nothing about whether the FLEET uses either word. The same reasoning\n * `capability.requirement-inert-join` applies one axis over: a join written\n * inside the tree is not evidence about the world outside it. The intra-glossary\n * citations are listed in `details` rather than hidden, because they are the\n * first thing a reader will otherwise go looking for.\n *\n * ONE FINDING FOR THE WHOLE GLOSSARY when nothing cites anything, and one per\n * term otherwise. A fleet that has just created `glossary/` and written its\n * first eight definitions would otherwise get eight identical warnings saying\n * the same thing about the same afternoon's work.\n */\nimport { backlinkIndex } from \"../../../core/links/backlinks.js\";\nimport { readGlossary } from \"../../../core/glossary/tree.js\";\nimport { glossaryDir } from \"../../../core/repo/authored/paths.js\";\nimport { repoPath } from \"../../../core/envelope/json.js\";\nimport { FleetContext } from \"../../../core/fleet-context.js\";\nimport { type Finding } from \"../../../core/vocabulary/report.js\";\nimport type { DocsDir } from \"../../../core/kernel/ids/dirs.js\";\n\nexport async function glossaryFindings(docsDir: DocsDir, fleet?: FleetContext): Promise<Finding[]> {\n const root = glossaryDir(docsDir);\n const glossary = await readGlossary(root);\n // The directory's existence is the axis's opt-in, exactly as\n // `architecture/capabilities.yaml` and `capabilities/` are the business\n // axis's. A fleet without one pays a single `existsSync` and hears nothing —\n // and the whole fleet-wide link walk below is never built.\n if (!glossary.present || glossary.terms.length === 0) return [];\n\n const index = await backlinkIndex(docsDir, fleet);\n const inGlossary = (source: string): boolean => source.startsWith(`${repoPath(docsDir, root)}/`);\n const unlinked = glossary.terms\n .map((term) => ({ term, cited: index.linkersOf(term.path) }))\n .map(({ term, cited }) => ({ term, outside: cited.filter((s) => !inGlossary(s)), within: cited.filter(inGlossary) }))\n .filter(({ outside }) => outside.length === 0);\n if (unlinked.length === 0) return [];\n\n // The whole vocabulary uncited is one fact about one afternoon, not N facts.\n if (unlinked.length === glossary.terms.length && glossary.terms.length > 1) {\n return [\n {\n severity: \"warn\",\n code: \"glossary.unlinked\",\n message:\n `glossary: none of the ${glossary.terms.length} defined term(s) is linked from any document outside glossary/. ` +\n \"A term becomes checkable when a requirement, capability or intent cites it — \" +\n \"`[Order](../../glossary/order.md)` — and until then the definitions are a document nothing joins to.\",\n details: unlinked.map(({ term }) => term.id),\n },\n ];\n }\n return unlinked.map(({ term, within }) => ({\n severity: \"warn\" as const,\n code: \"glossary.unlinked\",\n subject: term.id,\n message:\n `glossary/${term.id}.md is linked from no document outside glossary/` +\n (within.length === 0\n ? \" — either a word the fleet has not adopted, or a definition left behind by a rename.\"\n : \", only from other terms — which says the glossary is consistent, not that the fleet uses the word.\") +\n ` Cite it as \\`[${term.id}](<relative>/glossary/${term.id}.md)\\` from the requirement or capability that uses it, or delete the definition.`,\n ...(within.length === 0 ? {} : { details: within }),\n }));\n}\n"]}
@@ -0,0 +1,269 @@
1
+ /**
2
+ * Everything that happens to a `TargetReport` around the checks themselves:
3
+ * how one is built when a target could not be read at all, how a finding's
4
+ * evidence is capped, how the set is summed, and how it prints.
5
+ *
6
+ * A module rather than the tail of validate.ts because the rollup and the
7
+ * renderer have to agree. The `--all` footer and the `--json` summary are the
8
+ * same `summary()`, and the cap reaches both payloads from one place; a second
9
+ * copy of either is how a footer starts printing a number its own findings
10
+ * contradict.
11
+ */
12
+ import { DocsRepoUnavailableError } from "../../core/repo/state.js";
13
+ import { listCodes } from "../../core/explain/lookup.js";
14
+ import { countSeverity, subjectsWith, SEVERITY_MARK, } from "../../core/vocabulary/report.js";
15
+ import { EXPLAIN_FOOTER, plural } from "../policy/format.js";
16
+ import { ADOPTION_AXES, groupedWarnCodes, } from "./fleet/scorecard/adoption.js";
17
+ export function summary(targets) {
18
+ return {
19
+ services: targets.filter((t) => t.kind === "service").length,
20
+ features: targets.filter((t) => t.kind === "feature").length,
21
+ errors: countSeverity(targets, "error"),
22
+ warnings: countSeverity(targets, "warn"),
23
+ };
24
+ }
25
+ /**
26
+ * How many services this run could not check, for the rollup line and the
27
+ * `--json` payload.
28
+ *
29
+ * Counted off the findings rather than alongside them, so the rollup line
30
+ * and the per-service findings can never disagree about how many services
31
+ * this run could not check. The by-SUBJECT rule (a service whose spec.md and
32
+ * arch.spec.md both name `sources` raises two findings and is one service) is
33
+ * `subjectsWith`'s, spelled once for every findings-derived rollup — the
34
+ * fleet scorecard counts through the same function on the same code, so its
35
+ * number and this one are structurally the same number. The code is a LITERAL
36
+ * rather than checks/vocabulary.ts's UNVERIFIABLE constant because the
37
+ * stable-code collector reads counting sites too, and it refuses a slot it
38
+ * cannot read — the collector is also what convicts a typo here.
39
+ */
40
+ export function unverifiableSubjects(targets) {
41
+ return subjectsWith(targets, "sources.unverifiable-from-here");
42
+ }
43
+ /**
44
+ * How many `details` lines any one finding may print before the rest are
45
+ * summarised away.
46
+ *
47
+ * A finding's details are evidence, not a log: LikeC4 reports one syntax error
48
+ * as dozens of cascading diagnostics, and a fleet-sized repo multiplies that by
49
+ * every target that mentions the file. The report is read by a person scrolling
50
+ * a CI log and by an agent with a context window, and neither of them is helped
51
+ * by the four-hundredth copy. The cap is applied to the JSON payload too, on
52
+ * purpose: `--json` is the interface an agent pipes, and an unbounded array is
53
+ * the same denial-of-attention there, just machine-readable.
54
+ */
55
+ const DETAIL_LIMIT = 10;
56
+ /** Truncate every finding's details, marking what was dropped so nothing looks complete when it is not. */
57
+ export function capDetails(t) {
58
+ return {
59
+ ...t,
60
+ findings: t.findings.map((f) => {
61
+ const details = f.details ?? [];
62
+ if (details.length <= DETAIL_LIMIT)
63
+ return f;
64
+ return {
65
+ ...f,
66
+ details: [...details.slice(0, DETAIL_LIMIT), `… (+${details.length - DETAIL_LIMIT} more)`],
67
+ };
68
+ }),
69
+ };
70
+ }
71
+ /**
72
+ * One target's checks, with an IO exception turned into a finding ON that
73
+ * target instead of aborting the run.
74
+ *
75
+ * A fleet gate that dies on the first unreadable file reports nothing about the
76
+ * other ninety-nine services — one bad permission bit, one file that is a
77
+ * dangling symlink, and CI's answer to "how is the fleet" becomes a stack
78
+ * trace. The failure is real and it is an error, so the run still exits 1; what
79
+ * changes is that everything else is still graded, and the finding names the
80
+ * service and the path instead of arriving as the `internal` catch-all.
81
+ */
82
+ export async function guarded(target, run) {
83
+ try {
84
+ return await run();
85
+ }
86
+ catch (err) {
87
+ // A docs repo that vanished mid-run is not one target's problem — it is the
88
+ // whole run's, and the action's own catch reports it.
89
+ if (err instanceof DocsRepoUnavailableError)
90
+ throw err;
91
+ const path = err.path;
92
+ const reason = err instanceof Error ? err.message : String(err);
93
+ return {
94
+ kind: target.kind,
95
+ id: target.id,
96
+ findings: [
97
+ {
98
+ severity: "error",
99
+ code: target.kind === "service" ? "service.unreadable" : "feature.unreadable",
100
+ subject: target.id,
101
+ message: `${target.id}: ${path === undefined ? "an artifact" : path} could not be read — ` +
102
+ `nothing about this ${target.kind} was checked. ${reason}`,
103
+ },
104
+ ],
105
+ };
106
+ }
107
+ }
108
+ /**
109
+ * `target.ambiguous` — the positional named a service AND a feature. The tie is
110
+ * still broken the way it always was (the feature wins), because changing which
111
+ * one is picked would silently re-target every script that relies on it; what
112
+ * is new is that the run says which reading it took and how to force the other.
113
+ */
114
+ export function ambiguousTarget(arg, chosen) {
115
+ const other = chosen === "feature" ? "service" : "feature";
116
+ return {
117
+ severity: "warn",
118
+ code: "target.ambiguous",
119
+ subject: arg,
120
+ message: `'${arg}' names both a service and a feature — validated as the ${chosen}. ` +
121
+ `Pass --${other} ${arg} for the other reading.`,
122
+ };
123
+ }
124
+ /**
125
+ * `--errors-only` is a RENDERING lever, the way `--strict` is an exit-code
126
+ * lever: neither changes the report, and the `--json` payload is unaffected by
127
+ * both. On a fleet of a hundred services the clean run prints several hundred
128
+ * `ok` confirmations, and the two warnings that matter are somewhere inside it;
129
+ * anyone reading a CI log wants the exceptions, and anyone auditing wants all
130
+ * of it. Both are available, from the same run, and neither is the default.
131
+ *
132
+ * Axis grouping is the same kind of lever, one notch further: warnings whose
133
+ * SOLE cause is a fleet-wide not-started axis (the mechanical, fail-closed
134
+ * rule in fleet/scorecard/adoption.ts — warn severity, listed code, axis at
135
+ * zero) are dropped from the per-target listing and re-stated as one banner
136
+ * per axis after the footer. The report, the footer's counts, `--json` and
137
+ * `--strict` are all computed from the UNFILTERED findings, so nothing a
138
+ * machine or an exit code reads moves by a single bit.
139
+ */
140
+ export function renderText(targets, opts) {
141
+ const { all, errorsOnly, unverifiable } = opts;
142
+ // When the fleet-wide "not started" claim is measurable at all — each guard
143
+ // fails closed to ungrouped rendering. `!all` is structural, not just the
144
+ // call site's promise: the banners print after the footer that only `--all`
145
+ // reaches, so grouping outside `--all` would DROP warnings instead of
146
+ // moving them — the one thing this lever must never do. `services === 0`
147
+ // is the vacuous fleet: with no services every axis is 0 "fleet-wide", and
148
+ // a banner over "0 of 0 services" would hide the fleet-level warnings of a
149
+ // repo that merely has no fleet yet. And an unreadable service proves
150
+ // nothing about what it started: its all-false participation (contracts.ts)
151
+ // could MANUFACTURE the very N=0 that licenses suppression — beside an
152
+ // error saying that service could not be checked — so one
153
+ // `service.unreadable` subject disables grouping for the whole run.
154
+ const card = !all ||
155
+ opts.scorecard === null ||
156
+ opts.scorecard.services === 0 ||
157
+ subjectsWith(targets, "service.unreadable") > 0
158
+ ? null
159
+ : opts.scorecard;
160
+ const grouped = card === null ? new Map() : groupedWarnCodes(card.adoption);
161
+ const isGrouped = (f) => f.severity === "warn" && grouped.has(f.code);
162
+ // The explain pointer follows any report that printed work — a non-ok
163
+ // finding, listed or folded under an axis banner. Gated on the UNFILTERED
164
+ // findings like every other rollup, so `--errors-only` and grouping cannot
165
+ // print codes the pointer then fails to follow. It is computed HERE rather
166
+ // than beside the two places it prints because the code column below asks
167
+ // the same question and must not walk the findings a second time to answer
168
+ // it differently.
169
+ const pointer = targets.some((t) => t.findings.some((f) => f.severity !== "ok"));
170
+ // The lookup key on the line itself.
171
+ //
172
+ // Until now a text report printed messages and no codes, so the footer under
173
+ // it could only say codes were somewhere else — in `--json`, which a reader
174
+ // would have to re-run the whole command to see. The code is what `loam
175
+ // explain` takes, what a CI branch tests and what a bug report quotes, and
176
+ // withholding it from the one surface a person actually reads made the
177
+ // footer's own offer unreachable.
178
+ //
179
+ // Only where a code is genuinely answerable, and that guard is not
180
+ // decoration: a handful of emitted finding codes still have no fix-table row
181
+ // (test/explain.test.ts names them), and printing one beside a footer
182
+ // promising an explanation would send the reader to a refusal. The set is
183
+ // built ONCE per render, and only when something non-ok will be printed:
184
+ // `explainSubject` walks the shipped workflow bodies per code (the cost
185
+ // `fixesFor` measured from the other side, where a handful of lookups is the
186
+ // cheaper shape), while `listCodes()` walks them once for the whole
187
+ // vocabulary — and a fleet report has far more finding lines than the fleet
188
+ // has distinct codes. Measured: 2.7 ms for all 273 codes, once per report.
189
+ const explainable = pointer ? new Set(listCodes().map((listing) => listing.code)) : new Set();
190
+ for (const t of targets) {
191
+ const shown = t.findings.filter((f) => !isGrouped(f) && (!errorsOnly || f.severity !== "ok"));
192
+ if (shown.length === 0)
193
+ continue;
194
+ // A feature announces itself; a service's findings already carry its name.
195
+ if (t.kind === "feature")
196
+ console.log(t.id);
197
+ let header;
198
+ for (const f of shown) {
199
+ const hint = f.text ?? {};
200
+ if (hint.header && hint.header !== header) {
201
+ header = hint.header;
202
+ console.log(` ${header}`);
203
+ }
204
+ // The whole report goes to stdout, in document order. Splitting errors
205
+ // onto stderr meant a piped stdout silently lost them from the middle of
206
+ // the report and 2>&1 could reorder it; the exit code carries failure,
207
+ // and stderr stays reserved for refusals (the fail() path).
208
+ const marker = hint.marker === false ? "" : `${SEVERITY_MARK[f.severity]} `;
209
+ // `ok` confirmations stay clean, deliberately. A clean fleet run is
210
+ // several hundred ✓ lines and two warnings, and a code appended to every
211
+ // one of them would cost exactly the signal the exceptions carry — there
212
+ // is nothing to look up about a check that passed.
213
+ const code = f.severity !== "ok" && explainable.has(f.code) ? ` (${f.code})` : "";
214
+ console.log(`${" ".repeat(hint.indent ?? 0)}${marker}${f.message}${code}`);
215
+ for (const d of f.details ?? [])
216
+ console.log(` ${hint.detailPrefix ?? ""}${d}`);
217
+ }
218
+ }
219
+ if (!all) {
220
+ // Without the --all footer there would be nothing at all to print for a
221
+ // clean single target under --errors-only — and silence is the one output
222
+ // that must never mean "checked, fine".
223
+ if (errorsOnly && targets.every((t) => t.findings.every((f) => f.severity === "ok"))) {
224
+ console.log(`${targets.map((t) => t.id).join(", ")}: no errors or warnings`);
225
+ }
226
+ if (pointer)
227
+ console.log(`\n${EXPLAIN_FOOTER}`);
228
+ return;
229
+ }
230
+ const s = summary(targets);
231
+ console.log(`\n${plural(s.services, "service")}, ${plural(s.features, "feature")} — ` +
232
+ `${plural(s.errors, "error")}, ${plural(s.warnings, "warning")}`);
233
+ // One line for the whole fleet, never one per service: honest about the blind
234
+ // spot without drowning the report in a hundred copies of it.
235
+ if (unverifiable > 0) {
236
+ const whose = unverifiable === 1 ? "1 service's" : `${unverifiable} services'`;
237
+ console.log(`⚠ sources.unverifiable-from-here: ${whose} sources can only be checked from their own repos`);
238
+ }
239
+ // The axis banners — one per not-started axis that actually grouped a
240
+ // warning, in the axes' fixed order, each naming its dropped codes with
241
+ // counts. Tallied off the UNFILTERED findings (the same walk the footer
242
+ // counts), and printed under --errors-only too: like the footer and the
243
+ // unverifiable line this is a rollup, not a finding.
244
+ if (card !== null && grouped.size > 0) {
245
+ const tally = new Map();
246
+ for (const t of targets) {
247
+ for (const f of t.findings) {
248
+ if (isGrouped(f))
249
+ tally.set(f.code, (tally.get(f.code) ?? 0) + 1);
250
+ }
251
+ }
252
+ for (const axis of ADOPTION_AXES) {
253
+ // Insertion order of `grouped` is the table's order, so the pairs render
254
+ // deterministically across runs and machines.
255
+ const pairs = [...grouped]
256
+ .filter(([code, a]) => a === axis && (tally.get(code) ?? 0) > 0)
257
+ .map(([code]) => [code, tally.get(code) ?? 0]);
258
+ if (pairs.length === 0)
259
+ continue;
260
+ const total = pairs.reduce((n, [, k]) => n + k, 0);
261
+ console.log(`⚠ ${axis} axis not started fleet-wide (0 of ${plural(card.services, "service")}), ` +
262
+ `expected during staged adoption — ${total} warning(s) grouped: ` +
263
+ `${pairs.map(([code, k]) => `${code}×${k}`).join(", ")}; every finding is unchanged in --json`);
264
+ }
265
+ }
266
+ if (pointer)
267
+ console.log(`\n${EXPLAIN_FOOTER}`);
268
+ }
269
+ //# sourceMappingURL=report.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.js","sourceRoot":"","sources":["../../../src/commands/validate/report.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Everything that happens to a `TargetReport` around the checks themselves:\n * how one is built when a target could not be read at all, how a finding's\n * evidence is capped, how the set is summed, and how it prints.\n *\n * A module rather than the tail of validate.ts because the rollup and the\n * renderer have to agree. The `--all` footer and the `--json` summary are the\n * same `summary()`, and the cap reaches both payloads from one place; a second\n * copy of either is how a footer starts printing a number its own findings\n * contradict.\n */\nimport { DocsRepoUnavailableError } from \"../../core/repo/state.js\";\nimport { listCodes } from \"../../core/explain/lookup.js\";\nimport {\n countSeverity,\n subjectsWith,\n SEVERITY_MARK,\n type Finding,\n type TargetReport,\n} from \"../../core/vocabulary/report.js\";\nimport { EXPLAIN_FOOTER, plural } from \"../policy/format.js\";\nimport {\n ADOPTION_AXES,\n groupedWarnCodes,\n type Adoption,\n type AdoptionAxis,\n} from \"./fleet/scorecard/adoption.js\";\n\n/**\n * The rollup `--json` carries and the `--all` footer prints.\n *\n * Four named fields rather than a `Record<string, number>`: the keys ARE the\n * contract, and under an index signature every read of them was an assertion\n * (`s.errors!`) that tsc could not check — rename one and the compiler stayed\n * quiet while the footer printed `undefined errors`.\n */\nexport interface ValidateSummary {\n services: number;\n features: number;\n errors: number;\n warnings: number;\n}\n\nexport function summary(targets: TargetReport[]): ValidateSummary {\n return {\n services: targets.filter((t) => t.kind === \"service\").length,\n features: targets.filter((t) => t.kind === \"feature\").length,\n errors: countSeverity(targets, \"error\"),\n warnings: countSeverity(targets, \"warn\"),\n };\n}\n\n/**\n * How many services this run could not check, for the rollup line and the\n * `--json` payload.\n *\n * Counted off the findings rather than alongside them, so the rollup line\n * and the per-service findings can never disagree about how many services\n * this run could not check. The by-SUBJECT rule (a service whose spec.md and\n * arch.spec.md both name `sources` raises two findings and is one service) is\n * `subjectsWith`'s, spelled once for every findings-derived rollup — the\n * fleet scorecard counts through the same function on the same code, so its\n * number and this one are structurally the same number. The code is a LITERAL\n * rather than checks/vocabulary.ts's UNVERIFIABLE constant because the\n * stable-code collector reads counting sites too, and it refuses a slot it\n * cannot read — the collector is also what convicts a typo here.\n */\nexport function unverifiableSubjects(targets: TargetReport[]): number {\n return subjectsWith(targets, \"sources.unverifiable-from-here\");\n}\n\n/**\n * How many `details` lines any one finding may print before the rest are\n * summarised away.\n *\n * A finding's details are evidence, not a log: LikeC4 reports one syntax error\n * as dozens of cascading diagnostics, and a fleet-sized repo multiplies that by\n * every target that mentions the file. The report is read by a person scrolling\n * a CI log and by an agent with a context window, and neither of them is helped\n * by the four-hundredth copy. The cap is applied to the JSON payload too, on\n * purpose: `--json` is the interface an agent pipes, and an unbounded array is\n * the same denial-of-attention there, just machine-readable.\n */\nconst DETAIL_LIMIT = 10;\n\n/** Truncate every finding's details, marking what was dropped so nothing looks complete when it is not. */\nexport function capDetails(t: TargetReport): TargetReport {\n return {\n ...t,\n findings: t.findings.map((f) => {\n const details = f.details ?? [];\n if (details.length <= DETAIL_LIMIT) return f;\n return {\n ...f,\n details: [...details.slice(0, DETAIL_LIMIT), `… (+${details.length - DETAIL_LIMIT} more)`],\n };\n }),\n };\n}\n\n/**\n * One target's checks, with an IO exception turned into a finding ON that\n * target instead of aborting the run.\n *\n * A fleet gate that dies on the first unreadable file reports nothing about the\n * other ninety-nine services — one bad permission bit, one file that is a\n * dangling symlink, and CI's answer to \"how is the fleet\" becomes a stack\n * trace. The failure is real and it is an error, so the run still exits 1; what\n * changes is that everything else is still graded, and the finding names the\n * service and the path instead of arriving as the `internal` catch-all.\n */\nexport async function guarded(\n target: { kind: \"service\" | \"feature\"; id: string },\n run: () => Promise<TargetReport>,\n): Promise<TargetReport> {\n try {\n return await run();\n } catch (err) {\n // A docs repo that vanished mid-run is not one target's problem — it is the\n // whole run's, and the action's own catch reports it.\n if (err instanceof DocsRepoUnavailableError) throw err;\n const path = (err as NodeJS.ErrnoException).path;\n const reason = err instanceof Error ? err.message : String(err);\n return {\n kind: target.kind,\n id: target.id,\n findings: [\n {\n severity: \"error\",\n code: target.kind === \"service\" ? \"service.unreadable\" : \"feature.unreadable\",\n subject: target.id,\n message:\n `${target.id}: ${path === undefined ? \"an artifact\" : path} could not be read — ` +\n `nothing about this ${target.kind} was checked. ${reason}`,\n },\n ],\n };\n }\n}\n\n/**\n * `target.ambiguous` — the positional named a service AND a feature. The tie is\n * still broken the way it always was (the feature wins), because changing which\n * one is picked would silently re-target every script that relies on it; what\n * is new is that the run says which reading it took and how to force the other.\n */\nexport function ambiguousTarget(arg: string, chosen: \"service\" | \"feature\"): Finding {\n const other = chosen === \"feature\" ? \"service\" : \"feature\";\n return {\n severity: \"warn\",\n code: \"target.ambiguous\",\n subject: arg,\n message:\n `'${arg}' names both a service and a feature — validated as the ${chosen}. ` +\n `Pass --${other} ${arg} for the other reading.`,\n };\n}\n\n/* ------------------------------------------------------------------ */\n/* Text renderer */\n/* ------------------------------------------------------------------ */\n\n/** What `renderText` needs of the run beyond the graded targets themselves. */\nexport interface RenderOptions {\n all: boolean;\n errorsOnly: boolean;\n /** The fleet's unverifiable-sources subject count, for the one-line rollup. */\n unverifiable: number;\n /**\n * The run's scorecard facts the renderer reads — ONE field, not a nullable\n * adoption beside a defaulted denominator, so \"adoption without its real\n * denominator\" is not constructible. Null on every single-target run and on\n * an `--all` run whose card failed closed, and null renders exactly as\n * before grouping existed: fail-open to today's behaviour, every warning\n * printed individually.\n */\n scorecard: { readonly adoption: Adoption; readonly services: number } | null;\n}\n\n/**\n * `--errors-only` is a RENDERING lever, the way `--strict` is an exit-code\n * lever: neither changes the report, and the `--json` payload is unaffected by\n * both. On a fleet of a hundred services the clean run prints several hundred\n * `ok` confirmations, and the two warnings that matter are somewhere inside it;\n * anyone reading a CI log wants the exceptions, and anyone auditing wants all\n * of it. Both are available, from the same run, and neither is the default.\n *\n * Axis grouping is the same kind of lever, one notch further: warnings whose\n * SOLE cause is a fleet-wide not-started axis (the mechanical, fail-closed\n * rule in fleet/scorecard/adoption.ts — warn severity, listed code, axis at\n * zero) are dropped from the per-target listing and re-stated as one banner\n * per axis after the footer. The report, the footer's counts, `--json` and\n * `--strict` are all computed from the UNFILTERED findings, so nothing a\n * machine or an exit code reads moves by a single bit.\n */\nexport function renderText(targets: TargetReport[], opts: RenderOptions): void {\n const { all, errorsOnly, unverifiable } = opts;\n // When the fleet-wide \"not started\" claim is measurable at all — each guard\n // fails closed to ungrouped rendering. `!all` is structural, not just the\n // call site's promise: the banners print after the footer that only `--all`\n // reaches, so grouping outside `--all` would DROP warnings instead of\n // moving them — the one thing this lever must never do. `services === 0`\n // is the vacuous fleet: with no services every axis is 0 \"fleet-wide\", and\n // a banner over \"0 of 0 services\" would hide the fleet-level warnings of a\n // repo that merely has no fleet yet. And an unreadable service proves\n // nothing about what it started: its all-false participation (contracts.ts)\n // could MANUFACTURE the very N=0 that licenses suppression — beside an\n // error saying that service could not be checked — so one\n // `service.unreadable` subject disables grouping for the whole run.\n const card =\n !all ||\n opts.scorecard === null ||\n opts.scorecard.services === 0 ||\n subjectsWith(targets, \"service.unreadable\") > 0\n ? null\n : opts.scorecard;\n const grouped = card === null ? new Map<string, AdoptionAxis>() : groupedWarnCodes(card.adoption);\n const isGrouped = (f: Finding): boolean => f.severity === \"warn\" && grouped.has(f.code);\n\n // The explain pointer follows any report that printed work — a non-ok\n // finding, listed or folded under an axis banner. Gated on the UNFILTERED\n // findings like every other rollup, so `--errors-only` and grouping cannot\n // print codes the pointer then fails to follow. It is computed HERE rather\n // than beside the two places it prints because the code column below asks\n // the same question and must not walk the findings a second time to answer\n // it differently.\n const pointer = targets.some((t) => t.findings.some((f) => f.severity !== \"ok\"));\n // The lookup key on the line itself.\n //\n // Until now a text report printed messages and no codes, so the footer under\n // it could only say codes were somewhere else — in `--json`, which a reader\n // would have to re-run the whole command to see. The code is what `loam\n // explain` takes, what a CI branch tests and what a bug report quotes, and\n // withholding it from the one surface a person actually reads made the\n // footer's own offer unreachable.\n //\n // Only where a code is genuinely answerable, and that guard is not\n // decoration: a handful of emitted finding codes still have no fix-table row\n // (test/explain.test.ts names them), and printing one beside a footer\n // promising an explanation would send the reader to a refusal. The set is\n // built ONCE per render, and only when something non-ok will be printed:\n // `explainSubject` walks the shipped workflow bodies per code (the cost\n // `fixesFor` measured from the other side, where a handful of lookups is the\n // cheaper shape), while `listCodes()` walks them once for the whole\n // vocabulary — and a fleet report has far more finding lines than the fleet\n // has distinct codes. Measured: 2.7 ms for all 273 codes, once per report.\n const explainable = pointer ? new Set(listCodes().map((listing) => listing.code)) : new Set<string>();\n for (const t of targets) {\n const shown = t.findings.filter(\n (f) => !isGrouped(f) && (!errorsOnly || f.severity !== \"ok\"),\n );\n if (shown.length === 0) continue;\n // A feature announces itself; a service's findings already carry its name.\n if (t.kind === \"feature\") console.log(t.id);\n let header: string | undefined;\n for (const f of shown) {\n const hint = f.text ?? {};\n if (hint.header && hint.header !== header) {\n header = hint.header;\n console.log(` ${header}`);\n }\n // The whole report goes to stdout, in document order. Splitting errors\n // onto stderr meant a piped stdout silently lost them from the middle of\n // the report and 2>&1 could reorder it; the exit code carries failure,\n // and stderr stays reserved for refusals (the fail() path).\n const marker = hint.marker === false ? \"\" : `${SEVERITY_MARK[f.severity]} `;\n // `ok` confirmations stay clean, deliberately. A clean fleet run is\n // several hundred ✓ lines and two warnings, and a code appended to every\n // one of them would cost exactly the signal the exceptions carry — there\n // is nothing to look up about a check that passed.\n const code = f.severity !== \"ok\" && explainable.has(f.code) ? ` (${f.code})` : \"\";\n console.log(`${\" \".repeat(hint.indent ?? 0)}${marker}${f.message}${code}`);\n for (const d of f.details ?? []) console.log(` ${hint.detailPrefix ?? \"\"}${d}`);\n }\n }\n\n if (!all) {\n // Without the --all footer there would be nothing at all to print for a\n // clean single target under --errors-only — and silence is the one output\n // that must never mean \"checked, fine\".\n if (errorsOnly && targets.every((t) => t.findings.every((f) => f.severity === \"ok\"))) {\n console.log(`${targets.map((t) => t.id).join(\", \")}: no errors or warnings`);\n }\n if (pointer) console.log(`\\n${EXPLAIN_FOOTER}`);\n return;\n }\n const s = summary(targets);\n console.log(\n `\\n${plural(s.services, \"service\")}, ${plural(s.features, \"feature\")} — ` +\n `${plural(s.errors, \"error\")}, ${plural(s.warnings, \"warning\")}`,\n );\n // One line for the whole fleet, never one per service: honest about the blind\n // spot without drowning the report in a hundred copies of it.\n if (unverifiable > 0) {\n const whose = unverifiable === 1 ? \"1 service's\" : `${unverifiable} services'`;\n console.log(\n `⚠ sources.unverifiable-from-here: ${whose} sources can only be checked from their own repos`,\n );\n }\n // The axis banners — one per not-started axis that actually grouped a\n // warning, in the axes' fixed order, each naming its dropped codes with\n // counts. Tallied off the UNFILTERED findings (the same walk the footer\n // counts), and printed under --errors-only too: like the footer and the\n // unverifiable line this is a rollup, not a finding.\n if (card !== null && grouped.size > 0) {\n const tally = new Map<string, number>();\n for (const t of targets) {\n for (const f of t.findings) {\n if (isGrouped(f)) tally.set(f.code, (tally.get(f.code) ?? 0) + 1);\n }\n }\n for (const axis of ADOPTION_AXES) {\n // Insertion order of `grouped` is the table's order, so the pairs render\n // deterministically across runs and machines.\n const pairs = [...grouped]\n .filter(([code, a]) => a === axis && (tally.get(code) ?? 0) > 0)\n .map(([code]) => [code, tally.get(code) ?? 0] as const);\n if (pairs.length === 0) continue;\n const total = pairs.reduce((n, [, k]) => n + k, 0);\n console.log(\n `⚠ ${axis} axis not started fleet-wide (0 of ${plural(card.services, \"service\")}), ` +\n `expected during staged adoption — ${total} warning(s) grouped: ` +\n `${pairs.map(([code, k]) => `${code}×${k}`).join(\", \")}; every finding is unchanged in --json`,\n );\n }\n }\n if (pointer) console.log(`\\n${EXPLAIN_FOOTER}`);\n}\n"]}