codebaseiq 0.1.0 → 0.2.0

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 (422) hide show
  1. package/CHANGELOG.md +47 -0
  2. package/dist/augment-vue-worker.js +1 -1
  3. package/dist/{chunk-DQMDCD24.js → chunk-27PHVDKL.js} +2 -2
  4. package/dist/{chunk-ZMI2JSX2.js → chunk-2DMVFAY7.js} +2 -2
  5. package/dist/{chunk-5PUWMSDU.js → chunk-2E6BTWER.js} +2 -2
  6. package/dist/{chunk-YESXMKX3.js → chunk-2F5ERMNI.js} +2 -2
  7. package/dist/chunk-2VKB5CMA.js +60 -0
  8. package/dist/{chunk-NNJ2KZZG.js → chunk-327YK6TB.js} +4 -4
  9. package/dist/chunk-347TXATM.js +2 -0
  10. package/dist/{chunk-VEXUL62T.js → chunk-35YYZD3D.js} +2 -2
  11. package/dist/chunk-36WRYYTE.js +3 -0
  12. package/dist/chunk-37TKC6MB.js +2 -0
  13. package/dist/{chunk-FAJQ7LWY.js → chunk-3AC56WAR.js} +2 -2
  14. package/dist/{chunk-JE3WZ6II.js → chunk-3NUZVLR7.js} +2 -2
  15. package/dist/{chunk-UZGZB3VB.js → chunk-3XFJUWJE.js} +2 -2
  16. package/dist/{chunk-OVTS4DKB.js → chunk-4AOOSCZ7.js} +2 -2
  17. package/dist/{chunk-LU3BMVH2.js → chunk-4IFISPQW.js} +2 -2
  18. package/dist/chunk-4NHWNAWQ.js +11 -0
  19. package/dist/chunk-4O52YNKL.js +5 -0
  20. package/dist/{chunk-HPJRBHVT.js → chunk-54K6556S.js} +2 -2
  21. package/dist/{chunk-HRWGYWRJ.js → chunk-57GCCPLS.js} +2 -2
  22. package/dist/{chunk-J77SU6VA.js → chunk-57KEZDPT.js} +2 -2
  23. package/dist/{chunk-OFBE4NGP.js → chunk-57KFVPVZ.js} +2 -2
  24. package/dist/{chunk-WOQBZPIF.js → chunk-5BDK6QC3.js} +2 -2
  25. package/dist/{chunk-7MGU3HPH.js → chunk-5IO2APSS.js} +2 -2
  26. package/dist/chunk-5NJPH3QZ.js +61 -0
  27. package/dist/{chunk-GW6Z3WGY.js → chunk-5WXOEJ4G.js} +2 -2
  28. package/dist/chunk-5XEVXVTK.js +3 -0
  29. package/dist/{chunk-RR7SX44N.js → chunk-6OVNYYY4.js} +2 -2
  30. package/dist/{chunk-ZV3JV5G5.js → chunk-6SDEQTVY.js} +2 -2
  31. package/dist/{chunk-EF2R3WNQ.js → chunk-6URCE5QY.js} +2 -2
  32. package/dist/{chunk-UCD3H3UZ.js → chunk-6ZV5EDUT.js} +2 -2
  33. package/dist/{chunk-C6SBF2WH.js → chunk-77GHPR2R.js} +2 -2
  34. package/dist/{chunk-YVCIMIOC.js → chunk-7R64XY4Y.js} +2 -2
  35. package/dist/{chunk-VXYS3FZD.js → chunk-7Z7HCZ7J.js} +2 -2
  36. package/dist/{chunk-CO5R3UNA.js → chunk-A67HT5FR.js} +2 -2
  37. package/dist/{chunk-UDS562V4.js → chunk-A7XQT7MH.js} +2 -2
  38. package/dist/{chunk-RDBI2RXU.js → chunk-ACZDU5GK.js} +2 -2
  39. package/dist/{chunk-FETNQCFO.js → chunk-AM5SUGHF.js} +2 -2
  40. package/dist/{chunk-NNOKTMZT.js → chunk-B2E3HZ2A.js} +2 -2
  41. package/dist/{chunk-CVYSU6BX.js → chunk-BH5CE4LN.js} +2 -2
  42. package/dist/chunk-BLKYYQ7C.js +543 -0
  43. package/dist/{chunk-4WKDMDEW.js → chunk-BX2U3QQV.js} +2 -2
  44. package/dist/{chunk-ZKX2FRS6.js → chunk-CANBLFVQ.js} +2 -2
  45. package/dist/{chunk-SMRBZ6EC.js → chunk-CCRZLRWJ.js} +2 -2
  46. package/dist/chunk-CDWSLAPN.js +21 -0
  47. package/dist/chunk-CIVYHK7U.js +22 -0
  48. package/dist/{chunk-L57ZKWVG.js → chunk-CMXW7MFV.js} +2 -2
  49. package/dist/{chunk-T3DGWPXM.js → chunk-CSZOQ7YO.js} +2 -2
  50. package/dist/{chunk-ZZXSWSN6.js → chunk-CWMHWD56.js} +2 -2
  51. package/dist/{chunk-6NW7MU72.js → chunk-CZEIHYMP.js} +2 -2
  52. package/dist/{chunk-DO6WQD2T.js → chunk-D62CTZX6.js} +2 -2
  53. package/dist/{chunk-XWUOUWYI.js → chunk-DFPAZXLU.js} +2 -2
  54. package/dist/{chunk-MOVBWNIP.js → chunk-DKJXK3HA.js} +2 -2
  55. package/dist/{chunk-XMQ23E27.js → chunk-DLC6JDN7.js} +2 -2
  56. package/dist/chunk-DUKHVPU5.js +4 -0
  57. package/dist/{chunk-ID63777H.js → chunk-DVYG3JTA.js} +2 -2
  58. package/dist/{chunk-NE6IU5ZD.js → chunk-EFFMFK7C.js} +2 -2
  59. package/dist/{chunk-I2T2LLK2.js → chunk-EM5UHLAM.js} +2 -2
  60. package/dist/chunk-EN4AHLL3.js +3 -0
  61. package/dist/chunk-EXMVF3JR.js +3 -0
  62. package/dist/{chunk-SWHMHUKF.js → chunk-FEBLLMTL.js} +2 -2
  63. package/dist/chunk-FIXYHQ3W.js +3 -0
  64. package/dist/{chunk-RKEJ6VTF.js → chunk-FLLXYUOL.js} +2 -2
  65. package/dist/{chunk-KWVHSKHK.js → chunk-FPDL2TUB.js} +2 -2
  66. package/dist/chunk-FQA3KIFX.js +17 -0
  67. package/dist/chunk-FWY2PRIF.js +3 -0
  68. package/dist/chunk-FY5V4V4F.js +2 -0
  69. package/dist/chunk-G2XUZCF2.js +88 -0
  70. package/dist/{chunk-QHRNXP3C.js → chunk-GXVDTHFC.js} +2 -2
  71. package/dist/{chunk-6MUIJMVL.js → chunk-H3CKAL6P.js} +2 -2
  72. package/dist/chunk-H5QXP63L.js +2 -0
  73. package/dist/{chunk-VUIYB2V3.js → chunk-HBQGKMM3.js} +2 -2
  74. package/dist/{chunk-PYAB5SM6.js → chunk-HBXZAGY6.js} +2 -2
  75. package/dist/{chunk-NNO6A2PO.js → chunk-HCMQZPEO.js} +2 -2
  76. package/dist/{chunk-Q65CQ4XL.js → chunk-HHBBGWES.js} +2 -2
  77. package/dist/{chunk-GTXSJDCO.js → chunk-HIEXRDJF.js} +2 -2
  78. package/dist/{chunk-4FC325IF.js → chunk-HYKSLTAR.js} +2 -2
  79. package/dist/{chunk-XLQ3GLWZ.js → chunk-I2KP4AGR.js} +2 -2
  80. package/dist/chunk-I5FCDTK2.js +2 -0
  81. package/dist/{chunk-QKPLA6IC.js → chunk-I645ZF75.js} +2 -2
  82. package/dist/{chunk-FDGD5AB5.js → chunk-IBM3F2BJ.js} +2 -2
  83. package/dist/{chunk-Q72QSKXC.js → chunk-IEL6Q5W3.js} +38 -38
  84. package/dist/{chunk-NCZUNH3E.js → chunk-IGQQUENU.js} +12 -12
  85. package/dist/chunk-IGYAZPRX.js +4 -0
  86. package/dist/chunk-IOVPAZWP.js +3 -0
  87. package/dist/{chunk-OL6KJP3N.js → chunk-IVJJNVSX.js} +2 -2
  88. package/dist/{chunk-AKB7V7TV.js → chunk-IWAMYGPN.js} +2 -2
  89. package/dist/chunk-IYBIBMPF.js +90 -0
  90. package/dist/{chunk-IOP6FWIM.js → chunk-J24VICI5.js} +2 -2
  91. package/dist/{chunk-C7QOQX32.js → chunk-JN5LIBT3.js} +2 -2
  92. package/dist/{chunk-O6QTXQPJ.js → chunk-JOALNFY3.js} +2 -2
  93. package/dist/{chunk-GCHRX4YW.js → chunk-JUO3Z644.js} +2 -2
  94. package/dist/{chunk-BJ6SQAEN.js → chunk-JXHLB7TP.js} +2 -2
  95. package/dist/{chunk-IJ4HMYBE.js → chunk-JYX5UZSZ.js} +2 -2
  96. package/dist/chunk-K2O7SBAU.js +2 -0
  97. package/dist/{chunk-OLF4MA5W.js → chunk-K5G7SPAG.js} +2 -2
  98. package/dist/{chunk-YSNONTJ2.js → chunk-KDYQQJ6X.js} +2 -2
  99. package/dist/{chunk-7NVGT435.js → chunk-KM4QRWI5.js} +2 -2
  100. package/dist/{chunk-HKQUXIFO.js → chunk-KNV5VFDV.js} +2 -2
  101. package/dist/chunk-L3YSDLNB.js +2 -0
  102. package/dist/{chunk-EZNMUY67.js → chunk-LAGDJXFY.js} +2 -2
  103. package/dist/{chunk-ENCCHKM6.js → chunk-LY2NB5XR.js} +4 -4
  104. package/dist/chunk-M4EVGA5S.js +14 -0
  105. package/dist/chunk-M7LAIM77.js +127 -0
  106. package/dist/{chunk-BVAJLC5A.js → chunk-MRGTCMDK.js} +2 -2
  107. package/dist/{chunk-OZYRSMSH.js → chunk-MT5W4DUG.js} +2 -2
  108. package/dist/{chunk-VE5AVNMP.js → chunk-MTMF4N7F.js} +2 -2
  109. package/dist/chunk-N3Q3AWGW.js +545 -0
  110. package/dist/{chunk-TXXOEMZJ.js → chunk-NDGTJHQN.js} +2 -2
  111. package/dist/chunk-NIO346UL.js +2 -0
  112. package/dist/chunk-NJA4MMBD.js +2 -0
  113. package/dist/{chunk-7FND7D7N.js → chunk-NK76RSB6.js} +2 -2
  114. package/dist/{chunk-H3LGFZVK.js → chunk-NTRW52UR.js} +2 -2
  115. package/dist/{chunk-JOIRNPPY.js → chunk-OJFLPVBP.js} +2 -2
  116. package/dist/{chunk-KMITESMT.js → chunk-OMBRP7BB.js} +2 -2
  117. package/dist/{chunk-UP3BUZR5.js → chunk-OVKZM2XI.js} +2 -2
  118. package/dist/{chunk-MVB3DAEY.js → chunk-PARCKE3Q.js} +2 -2
  119. package/dist/{chunk-CAUCPUOF.js → chunk-PFPHS4NO.js} +2 -2
  120. package/dist/chunk-PHPQ24UG.js +22 -0
  121. package/dist/chunk-PLZXWZHY.js +77 -0
  122. package/dist/{chunk-34WBMAYK.js → chunk-PNVZIJ57.js} +2 -2
  123. package/dist/{chunk-SYDJMPES.js → chunk-QKVTWODE.js} +2 -2
  124. package/dist/{chunk-FW53T7EB.js → chunk-QLTFXVUI.js} +2 -2
  125. package/dist/{chunk-PBI2LFKH.js → chunk-QMGWSEPL.js} +2 -2
  126. package/dist/{chunk-CQP3THUZ.js → chunk-QVHZB75Z.js} +2 -2
  127. package/dist/{chunk-6BQ3DSPK.js → chunk-QVWDQTMG.js} +2 -2
  128. package/dist/{chunk-ST7V3SKN.js → chunk-RCPZOPV6.js} +2 -2
  129. package/dist/chunk-RJWAB4VR.js +345 -0
  130. package/dist/chunk-RRPK327J.js +20 -0
  131. package/dist/chunk-RVYLJDXC.js +21 -0
  132. package/dist/chunk-RWKEXCHU.js +3 -0
  133. package/dist/{chunk-L4NRUAGJ.js → chunk-S5SKXCND.js} +2 -2
  134. package/dist/{chunk-RBAS5ZHI.js → chunk-S64NCE2Z.js} +2 -2
  135. package/dist/{chunk-WMPRTGH2.js → chunk-SF34QLK2.js} +2 -2
  136. package/dist/{chunk-ANFVSJWQ.js → chunk-SJZQ2PTZ.js} +2 -2
  137. package/dist/{chunk-4XTAUQFD.js → chunk-SRY26ITJ.js} +2 -2
  138. package/dist/chunk-SV2LEFVM.js +2 -0
  139. package/dist/{chunk-7XAN6GKB.js → chunk-T3YFIJ5P.js} +2 -2
  140. package/dist/chunk-T55YPJGB.js +3 -0
  141. package/dist/chunk-TAJ6UGCO.js +21 -0
  142. package/dist/{chunk-PIOMTC27.js → chunk-TUTSO7UZ.js} +2 -2
  143. package/dist/{chunk-FQKZWM4L.js → chunk-U24M5RQM.js} +5 -5
  144. package/dist/{chunk-XME3HPXZ.js → chunk-U2XX3BT4.js} +2 -2
  145. package/dist/{chunk-SZD2KF7Q.js → chunk-UWB5WMC2.js} +2 -2
  146. package/dist/{chunk-6CS3UQTN.js → chunk-VCL7FK3E.js} +2 -2
  147. package/dist/{chunk-N3IQCBCF.js → chunk-VCWAJPXQ.js} +2 -2
  148. package/dist/{chunk-LZYFLFEH.js → chunk-VG55NFXF.js} +2 -2
  149. package/dist/{chunk-PTAWHLVJ.js → chunk-VLTUX4IF.js} +2 -2
  150. package/dist/{chunk-JEJLSICM.js → chunk-VVCBMH5O.js} +2 -2
  151. package/dist/{chunk-JSOYNVWH.js → chunk-VYZQZ4ZN.js} +2 -2
  152. package/dist/chunk-W3FK73MD.js +8 -0
  153. package/dist/{chunk-UNBY47BC.js → chunk-W6C6QTXJ.js} +2 -2
  154. package/dist/chunk-WH5SYOMD.js +2 -0
  155. package/dist/chunk-WJOQC4P7.js +7 -0
  156. package/dist/chunk-WO47BIPY.js +3 -0
  157. package/dist/chunk-WOOTEWQT.js +239 -0
  158. package/dist/{chunk-UBGWN7I4.js → chunk-X5I2BQGX.js} +2 -2
  159. package/dist/{chunk-PX4RYAAK.js → chunk-XNUWRTYM.js} +2 -2
  160. package/dist/{chunk-ICFDQHAM.js → chunk-XUJM6474.js} +2 -2
  161. package/dist/chunk-XYLV727H.js +21 -0
  162. package/dist/{chunk-TRRC4ZJ7.js → chunk-YFQPWKHR.js} +2 -2
  163. package/dist/{chunk-NEDP5RFQ.js → chunk-YIOQJ45A.js} +2 -2
  164. package/dist/{chunk-Y6KHROC3.js → chunk-YXJ4IAHH.js} +2 -2
  165. package/dist/chunk-YYFV32WR.js +3 -0
  166. package/dist/{chunk-BH5F2Q4O.js → chunk-ZB3V5QM7.js} +2 -2
  167. package/dist/chunk-ZJZQ7Q2Q.js +3 -0
  168. package/dist/{chunk-EMNIHCRB.js → chunk-ZNQCR656.js} +2 -2
  169. package/dist/{chunk-TIIC3ZE7.js → chunk-ZOEDRCR4.js} +2 -2
  170. package/dist/cli-context-TSADTXLB.js +2 -0
  171. package/dist/cli-context-XEPPF4RX.js +3 -0
  172. package/dist/cli-program-KJGQEM72.js +7 -0
  173. package/dist/cli.js +1 -1
  174. package/dist/{code-DlqpBDd0.d.ts → code-CDe-mIjx.d.ts} +1 -1
  175. package/dist/code-viewer-YGDON6SY.js +12 -0
  176. package/dist/code-viewer-ZCTHXQ5C.js +11 -0
  177. package/dist/command-descriptors-5VAB2MZX.js +335 -0
  178. package/dist/command-descriptors-EAHKIRAG.js +337 -0
  179. package/dist/{config-types-BNoC96J3.d.ts → config-types-D6X5S68_.d.ts} +50 -0
  180. package/dist/{db-D7sauVFH.d.ts → db-DmRNdCtm.d.ts} +1 -1
  181. package/dist/direct-navigation-B3SGOOBW.js +2 -0
  182. package/dist/direct-navigation-ZL362KXF.js +3 -0
  183. package/dist/{graph-evidence-BIFqyisO.d.ts → graph-evidence-Bs54NWws.d.ts} +1 -1
  184. package/dist/{health-DJaZXg8I.d.ts → health-BnzbSLCE.d.ts} +1 -1
  185. package/dist/index.d.ts +2 -2
  186. package/dist/index.js +1 -1
  187. package/dist/invocation-command-descriptors-CSUGUHTT.js +2 -0
  188. package/dist/invocation-command-descriptors-PPVZOIE5.js +3 -0
  189. package/dist/output-continuation-command-FTVVBVSN.js +2 -0
  190. package/dist/output-continuation-command-ITPRC3YV.js +3 -0
  191. package/dist/project-reindex-7HZSLLLY.js +3 -0
  192. package/dist/project-reindex-NGM3DYBN.js +2 -0
  193. package/dist/queries/affected.d.ts +2 -2
  194. package/dist/queries/affected.js +1 -1
  195. package/dist/queries/anchors.d.ts +2 -2
  196. package/dist/queries/anchors.js +1 -1
  197. package/dist/queries/architecture.d.ts +2 -2
  198. package/dist/queries/architecture.js +1 -1
  199. package/dist/queries/bottlenecks.d.ts +2 -2
  200. package/dist/queries/bottlenecks.js +1 -1
  201. package/dist/queries/by-kind.d.ts +2 -2
  202. package/dist/queries/by-kind.js +1 -1
  203. package/dist/queries/call-graph.d.ts +2 -2
  204. package/dist/queries/call-graph.js +1 -1
  205. package/dist/queries/change-surface.d.ts +2 -2
  206. package/dist/queries/change-surface.js +1 -1
  207. package/dist/queries/cleanup-plan.d.ts +2 -2
  208. package/dist/queries/cleanup-plan.js +1 -1
  209. package/dist/queries/co-change.d.ts +2 -2
  210. package/dist/queries/co-change.js +1 -1
  211. package/dist/queries/code.d.ts +3 -3
  212. package/dist/queries/code.js +1 -1
  213. package/dist/queries/complexity-hotspots.d.ts +2 -2
  214. package/dist/queries/complexity-hotspots.js +1 -1
  215. package/dist/queries/complexity.d.ts +2 -2
  216. package/dist/queries/complexity.js +1 -1
  217. package/dist/queries/context.d.ts +2 -2
  218. package/dist/queries/context.js +1 -1
  219. package/dist/queries/convergence.d.ts +2 -2
  220. package/dist/queries/convergence.js +1 -1
  221. package/dist/queries/coupling.d.ts +2 -2
  222. package/dist/queries/coupling.js +1 -1
  223. package/dist/queries/cycles.d.ts +2 -2
  224. package/dist/queries/cycles.js +1 -1
  225. package/dist/queries/dataflow.d.ts +2 -2
  226. package/dist/queries/dataflow.js +1 -1
  227. package/dist/queries/dead.d.ts +2 -2
  228. package/dist/queries/dead.js +1 -1
  229. package/dist/queries/decorative-checkers.d.ts +2 -2
  230. package/dist/queries/decorative-checkers.js +1 -1
  231. package/dist/queries/deep-chains.d.ts +2 -2
  232. package/dist/queries/deep-chains.js +1 -1
  233. package/dist/queries/dependence-slice.d.ts +3 -3
  234. package/dist/queries/dependence-slice.js +1 -1
  235. package/dist/queries/dependency-depth.d.ts +2 -2
  236. package/dist/queries/dependency-depth.js +1 -1
  237. package/dist/queries/deps.d.ts +2 -2
  238. package/dist/queries/deps.js +1 -1
  239. package/dist/queries/diff-impact.d.ts +2 -2
  240. package/dist/queries/diff-impact.js +1 -1
  241. package/dist/queries/doc-drift.d.ts +2 -2
  242. package/dist/queries/doc-drift.js +1 -1
  243. package/dist/queries/drift.d.ts +2 -2
  244. package/dist/queries/drift.js +1 -1
  245. package/dist/queries/duplicate-bodies.d.ts +2 -2
  246. package/dist/queries/duplicate-bodies.js +1 -1
  247. package/dist/queries/entry-map.d.ts +2 -2
  248. package/dist/queries/entry-map.js +1 -1
  249. package/dist/queries/evidence.d.ts +3 -3
  250. package/dist/queries/evidence.js +1 -1
  251. package/dist/queries/extract-candidates.d.ts +2 -2
  252. package/dist/queries/extract-candidates.js +1 -1
  253. package/dist/queries/fan.d.ts +2 -2
  254. package/dist/queries/fan.js +1 -1
  255. package/dist/queries/files.d.ts +2 -2
  256. package/dist/queries/files.js +1 -1
  257. package/dist/queries/health.d.ts +3 -3
  258. package/dist/queries/health.js +1 -1
  259. package/dist/queries/hierarchy.d.ts +2 -2
  260. package/dist/queries/hierarchy.js +1 -1
  261. package/dist/queries/hotspots.d.ts +2 -2
  262. package/dist/queries/hotspots.js +1 -1
  263. package/dist/queries/imports.d.ts +2 -2
  264. package/dist/queries/imports.js +1 -1
  265. package/dist/queries/incomplete-migration.d.ts +2 -2
  266. package/dist/queries/incomplete-migration.js +1 -1
  267. package/dist/queries/index.d.ts +5 -5
  268. package/dist/queries/index.js +1 -1
  269. package/dist/queries/isolated.d.ts +2 -2
  270. package/dist/queries/isolated.js +1 -1
  271. package/dist/queries/locality-candidates.d.ts +2 -2
  272. package/dist/queries/locality-candidates.js +1 -1
  273. package/dist/queries/members.d.ts +2 -2
  274. package/dist/queries/members.js +1 -1
  275. package/dist/queries/methods.d.ts +2 -2
  276. package/dist/queries/methods.js +1 -1
  277. package/dist/queries/not-implemented.d.ts +2 -2
  278. package/dist/queries/not-implemented.js +1 -1
  279. package/dist/queries/outline.d.ts +2 -2
  280. package/dist/queries/outline.js +1 -1
  281. package/dist/queries/passthrough-candidates.d.ts +2 -2
  282. package/dist/queries/passthrough-candidates.js +1 -1
  283. package/dist/queries/plan-context.d.ts +2 -2
  284. package/dist/queries/plan-context.js +1 -1
  285. package/dist/queries/react-component-duplicates.d.ts +2 -2
  286. package/dist/queries/react-component-duplicates.js +1 -1
  287. package/dist/queries/react-hook-candidates.d.ts +2 -2
  288. package/dist/queries/react-hook-candidates.js +1 -1
  289. package/dist/queries/react-large-component-pressure.d.ts +2 -2
  290. package/dist/queries/react-large-component-pressure.js +1 -1
  291. package/dist/queries/recent-duplicates.d.ts +2 -2
  292. package/dist/queries/recent-duplicates.js +1 -1
  293. package/dist/queries/redundant-reexports.d.ts +2 -2
  294. package/dist/queries/redundant-reexports.js +1 -1
  295. package/dist/queries/reference-neighborhood.d.ts +2 -2
  296. package/dist/queries/reference-neighborhood.js +1 -1
  297. package/dist/queries/reference-reachability.d.ts +2 -2
  298. package/dist/queries/reference-reachability.js +1 -1
  299. package/dist/queries/refs.d.ts +2 -2
  300. package/dist/queries/refs.js +1 -1
  301. package/dist/queries/self-audit.d.ts +2 -2
  302. package/dist/queries/self-audit.js +1 -1
  303. package/dist/queries/similar-chains.d.ts +2 -2
  304. package/dist/queries/similar-chains.js +1 -1
  305. package/dist/queries/similar-files.d.ts +2 -2
  306. package/dist/queries/similar-files.js +1 -1
  307. package/dist/queries/similar-signatures.d.ts +2 -2
  308. package/dist/queries/similar-signatures.js +1 -1
  309. package/dist/queries/similar.d.ts +2 -2
  310. package/dist/queries/similar.js +1 -1
  311. package/dist/queries/slice.d.ts +2 -2
  312. package/dist/queries/slice.js +1 -1
  313. package/dist/queries/source-inspection.d.ts +4 -4
  314. package/dist/queries/source-inspection.js +1 -1
  315. package/dist/queries/source-search.d.ts +2 -2
  316. package/dist/queries/source-search.js +1 -1
  317. package/dist/queries/stale-abstractions.d.ts +2 -2
  318. package/dist/queries/stale-abstractions.js +1 -1
  319. package/dist/queries/stats.d.ts +2 -2
  320. package/dist/queries/surface.d.ts +2 -2
  321. package/dist/queries/surface.js +1 -1
  322. package/dist/queries/symbols.d.ts +2 -2
  323. package/dist/queries/symbols.js +1 -1
  324. package/dist/queries/system-map.d.ts +2 -2
  325. package/dist/queries/system-map.js +1 -1
  326. package/dist/queries/system.d.ts +2 -2
  327. package/dist/queries/system.js +1 -1
  328. package/dist/queries/test-quality.d.ts +2 -2
  329. package/dist/queries/test-quality.js +1 -1
  330. package/dist/queries/trace.d.ts +2 -2
  331. package/dist/queries/trace.js +1 -1
  332. package/dist/queries/twin-ab.d.ts +2 -2
  333. package/dist/queries/twin-ab.js +1 -1
  334. package/dist/queries/twin-drift.d.ts +2 -2
  335. package/dist/queries/twin-drift.js +1 -1
  336. package/dist/queries/unused-imports.d.ts +2 -2
  337. package/dist/queries/unused-imports.js +1 -1
  338. package/dist/queries/unused-params.d.ts +2 -2
  339. package/dist/queries/unused-params.js +1 -1
  340. package/dist/queries/value-flow.d.ts +3 -3
  341. package/dist/queries/value-flow.js +1 -1
  342. package/dist/queries/vue-component-duplicates.d.ts +2 -2
  343. package/dist/queries/vue-component-duplicates.js +1 -1
  344. package/dist/queries/vue-composable-candidates.d.ts +2 -2
  345. package/dist/queries/vue-composable-candidates.js +1 -1
  346. package/dist/queries/vue-large-view-pressure.d.ts +2 -2
  347. package/dist/queries/vue-large-view-pressure.js +1 -1
  348. package/dist/queries/wrapper-candidates.d.ts +2 -2
  349. package/dist/queries/wrapper-candidates.js +1 -1
  350. package/dist/reindex-worker.js +1 -1
  351. package/dist/reindex.d.ts +3 -3
  352. package/dist/reindex.js +31 -31
  353. package/dist/runtime.d.ts +24 -4
  354. package/dist/runtime.js +3 -3
  355. package/dist/rust-semantic-session-server.js +1 -1
  356. package/dist/rust-semantic-session-worker.js +1 -1
  357. package/dist/rust-semantic-worker.js +1 -1
  358. package/dist/{scip-cli-B7N3haxa.d.ts → scip-cli-BRFKkHQn.d.ts} +1 -1
  359. package/dist/sentinel-ensure-command-KYYULCFU.js +2 -0
  360. package/dist/sentinel-ensure-command-RIZA3RY7.js +3 -0
  361. package/dist/sentinel-hook.js +39 -0
  362. package/dist/sentinel-worker.js +16 -0
  363. package/dist/typescript-mailbox-worker.js +1 -1
  364. package/dist/watch-server.js +6 -6
  365. package/docs/COMMAND_REFERENCE.md +5 -3
  366. package/docs/schemas/project-config.schema.json +159 -0
  367. package/package.json +9 -5
  368. package/skills/codebaseiq/SKILL.md +1 -1
  369. package/skills/concrete-plan/SKILL.md +1 -1
  370. package/ui/view/api.js +450 -0
  371. package/ui/view/app.js +394 -0
  372. package/ui/view/builder.js +323 -0
  373. package/ui/view/file-panel.js +170 -0
  374. package/ui/view/focus.js +379 -0
  375. package/ui/view/index.html +54 -0
  376. package/ui/view/map.js +424 -0
  377. package/ui/view/styles.css +1125 -0
  378. package/dist/chunk-2X7V4HS4.js +0 -88
  379. package/dist/chunk-3IER7Q6H.js +0 -12
  380. package/dist/chunk-3JSXXYTZ.js +0 -345
  381. package/dist/chunk-476NR5B7.js +0 -2
  382. package/dist/chunk-5VKBFZZU.js +0 -3
  383. package/dist/chunk-ADTBPVUZ.js +0 -21
  384. package/dist/chunk-BFFZDZQV.js +0 -2
  385. package/dist/chunk-BMYOV5GP.js +0 -77
  386. package/dist/chunk-C74PPYLA.js +0 -3
  387. package/dist/chunk-CWONGW6P.js +0 -3
  388. package/dist/chunk-DDZ7VHWV.js +0 -20
  389. package/dist/chunk-DR2LURYU.js +0 -3
  390. package/dist/chunk-ECQBG7PW.js +0 -564
  391. package/dist/chunk-FM5BPL4V.js +0 -60
  392. package/dist/chunk-G6XFR4ZL.js +0 -4
  393. package/dist/chunk-GTIYTDRE.js +0 -562
  394. package/dist/chunk-HOA5YGOH.js +0 -3
  395. package/dist/chunk-KUW32IRO.js +0 -2
  396. package/dist/chunk-LTA3BRZX.js +0 -2
  397. package/dist/chunk-NAUD7LCA.js +0 -2
  398. package/dist/chunk-OGTFJ3XD.js +0 -2
  399. package/dist/chunk-Q5ELPRKQ.js +0 -2
  400. package/dist/chunk-QCN62RTF.js +0 -3
  401. package/dist/chunk-QW7EP6WI.js +0 -21
  402. package/dist/chunk-RU65DDUP.js +0 -215
  403. package/dist/chunk-SELM5MER.js +0 -2
  404. package/dist/chunk-SNNWPCN7.js +0 -4
  405. package/dist/chunk-TFZB6XTM.js +0 -239
  406. package/dist/chunk-UXM43C7T.js +0 -3
  407. package/dist/chunk-VFY6Y2H6.js +0 -61
  408. package/dist/chunk-WE5RZHZ7.js +0 -5
  409. package/dist/chunk-Z54RD7VL.js +0 -3
  410. package/dist/cli-context-3SNLDYBM.js +0 -3
  411. package/dist/cli-context-T3B7W6GG.js +0 -2
  412. package/dist/cli-program-YNOXO72B.js +0 -7
  413. package/dist/command-descriptors-6AOUKWW7.js +0 -346
  414. package/dist/command-descriptors-ZFKJSRUP.js +0 -344
  415. package/dist/direct-navigation-DP4LVMRX.js +0 -3
  416. package/dist/direct-navigation-FLUS3BT6.js +0 -2
  417. package/dist/invocation-command-descriptors-QT2JMY5J.js +0 -3
  418. package/dist/invocation-command-descriptors-YN4QJEAX.js +0 -2
  419. package/dist/output-continuation-command-2V2SL4TD.js +0 -2
  420. package/dist/output-continuation-command-65J5IP3O.js +0 -3
  421. package/dist/project-reindex-5JOKXAXT.js +0 -2
  422. package/dist/project-reindex-UQBIKO4M.js +0 -3
package/ui/view/api.js ADDED
@@ -0,0 +1,450 @@
1
+ // Shared client foundation: fetch wrappers for the viewer API, the DOM builders
2
+ // every view uses (text only, never markup), route helpers, and adapters that
3
+ // tolerate optional or renamed fields in server payloads.
4
+
5
+ const TOKEN_META = 'codebaseiq-token';
6
+ const EDITOR_PREFIX = 'vscode://file/';
7
+ const SAFE_HREF = /^(?:\?|\/(?!\/)|vscode:\/\/file\/)/;
8
+ const REFERENCES = 'references';
9
+ const IMPORTS = 'imports';
10
+ const HEALTHY_WATCHER_STATES = new Set(['idle', 'waiting', 'indexing', 'cooldown', 'ready', 'watching']);
11
+ const STALE_MESSAGE = 'File changed since the index was built — lines may be off.';
12
+
13
+ export class ApiError extends Error {
14
+ constructor(message, status, payload) {
15
+ super(message);
16
+ this.name = 'ApiError';
17
+ this.status = status;
18
+ this.payload = payload;
19
+ }
20
+ }
21
+
22
+ export function isAbort(error) {
23
+ return error?.name === 'AbortError';
24
+ }
25
+
26
+ function describeFailure(response, payload) {
27
+ if (payload && typeof payload.error === 'string' && payload.error) return payload.error;
28
+ const detail = response.statusText ? ` ${response.statusText}` : '';
29
+ return `Request failed (${response.status}${detail}).`;
30
+ }
31
+
32
+ async function request(path, { method = 'GET', params, body, headers, signal } = {}) {
33
+ const query = new URLSearchParams();
34
+ for (const [key, value] of Object.entries(params ?? {})) {
35
+ if (value !== undefined && value !== null) query.set(key, String(value));
36
+ }
37
+ const queryText = query.toString();
38
+ const target = queryText ? `${path}?${queryText}` : path;
39
+ let response;
40
+ try {
41
+ response = await fetch(target, { method, headers, body, signal, credentials: 'same-origin', cache: 'no-store' });
42
+ } catch (error) {
43
+ if (isAbort(error)) throw error;
44
+ throw new ApiError('Cannot reach the codebaseiq server. Is `codebaseiq view` still running?', 0, null);
45
+ }
46
+ const text = await response.text();
47
+ let payload = null;
48
+ if (text) {
49
+ try {
50
+ payload = JSON.parse(text);
51
+ } catch {
52
+ payload = null;
53
+ }
54
+ }
55
+ if (!response.ok) throw new ApiError(describeFailure(response, payload), response.status, payload);
56
+ if (payload === null) throw new ApiError('The server returned an unreadable response.', response.status, null);
57
+ return payload;
58
+ }
59
+
60
+ function sessionToken() {
61
+ return document.querySelector(`meta[name="${TOKEN_META}"]`)?.getAttribute('content') ?? '';
62
+ }
63
+
64
+ export function getMeta(options) {
65
+ return request('/api/meta', options);
66
+ }
67
+
68
+ export function getScope(path, basis, options) {
69
+ return request('/api/scope', { ...options, params: { path, basis } });
70
+ }
71
+
72
+ export function getFile(path, basis, options) {
73
+ return request('/api/file', { ...options, params: { path, basis } });
74
+ }
75
+
76
+ export function getSymbol({ symbol, focus, statements }, options) {
77
+ return request('/api/symbol', {
78
+ ...options,
79
+ params: { symbol, focus, statements: statements ? '1' : undefined },
80
+ });
81
+ }
82
+
83
+ export function getSource({ file, start, end }, options) {
84
+ return request('/api/source', { ...options, params: { file, start, end } });
85
+ }
86
+
87
+ export function postBuilder(payload, options) {
88
+ return request('/api/builder', {
89
+ ...options,
90
+ method: 'POST',
91
+ headers: { 'Content-Type': 'application/json', 'X-CodeBaseIQ-Token': sessionToken() },
92
+ body: JSON.stringify(payload),
93
+ });
94
+ }
95
+
96
+ // ── Routes ────────────────────────────────────────────────
97
+
98
+ /** Exactly one target wins: symbol, then focus, then file, then scope; the default is the project root. */
99
+ export function parseRoute(search) {
100
+ const params = new URLSearchParams(search);
101
+ const route = { basis: params.get('basis') === IMPORTS ? IMPORTS : REFERENCES };
102
+ const symbol = params.get('symbol');
103
+ const focus = params.get('focus');
104
+ const file = params.get('file');
105
+ const scope = params.get('scope');
106
+ if (symbol) route.symbol = symbol;
107
+ else if (focus) route.focus = focus;
108
+ else if (file) route.file = file;
109
+ else if (scope) route.scope = scope;
110
+ return route;
111
+ }
112
+
113
+ export function routeToSearch(route) {
114
+ const params = new URLSearchParams();
115
+ if (route.symbol) params.set('symbol', route.symbol);
116
+ else if (route.focus) params.set('focus', route.focus);
117
+ else if (route.file) params.set('file', route.file);
118
+ else if (route.scope) params.set('scope', route.scope);
119
+ if (route.basis === IMPORTS) params.set('basis', IMPORTS);
120
+ const text = params.toString();
121
+ return text ? `?${text}` : '';
122
+ }
123
+
124
+ /** An anchor that navigates in place on a plain click and keeps native behavior for new-tab clicks. */
125
+ export function routeLink(nav, route, children, props = {}, onActivate) {
126
+ return el(
127
+ 'a',
128
+ {
129
+ ...props,
130
+ href: nav.href(route),
131
+ on: {
132
+ click: (event) => {
133
+ if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey) return;
134
+ event.preventDefault();
135
+ onActivate?.();
136
+ nav.go(route);
137
+ },
138
+ },
139
+ },
140
+ children,
141
+ );
142
+ }
143
+
144
+ // ── Paths and text ────────────────────────────────────────
145
+
146
+ export function dirname(path) {
147
+ const index = path.lastIndexOf('/');
148
+ return index < 0 ? '' : path.slice(0, index);
149
+ }
150
+
151
+ export function basename(path) {
152
+ return path.slice(path.lastIndexOf('/') + 1);
153
+ }
154
+
155
+ /** A path as a dimmed directory part and a bold file name. */
156
+ export function pathLabel(path) {
157
+ const folder = dirname(path);
158
+ return [
159
+ folder ? el('span', { class: 'path-dir' }, `${folder}/`) : null,
160
+ el('span', { class: 'path-base' }, basename(path)),
161
+ ];
162
+ }
163
+
164
+ /** Cumulative directories of a path: `a/b/c` gives `a`, `a/b`, `a/b/c`. */
165
+ export function pathPrefixes(path) {
166
+ const parts = path.split('/').filter(Boolean);
167
+ return parts.map((part, index) => ({ name: part, path: parts.slice(0, index + 1).join('/') }));
168
+ }
169
+
170
+ export function plural(count, noun) {
171
+ return `${count} ${noun}${count === 1 ? '' : 's'}`;
172
+ }
173
+
174
+ export function formatLocation(file, line) {
175
+ if (!file) return '';
176
+ return line ? `${file}:${line}` : file;
177
+ }
178
+
179
+ function safeEditorUri(uri) {
180
+ return typeof uri === 'string' && uri.startsWith(EDITOR_PREFIX) ? uri : null;
181
+ }
182
+
183
+ export function titleCase(text) {
184
+ return text ? text[0].toUpperCase() + text.slice(1) : text;
185
+ }
186
+
187
+ // ── DOM builders ──────────────────────────────────────────
188
+
189
+ /**
190
+ * Build an element. Values are always set as text or as attributes; markup
191
+ * strings are never parsed. `false`, `null`, and `undefined` props are skipped,
192
+ * so ARIA states are passed as the strings 'true' and 'false'.
193
+ */
194
+ export function el(tag, props, ...children) {
195
+ const node = document.createElement(tag);
196
+ for (const [name, value] of Object.entries(props ?? {})) applyProp(node, name, value);
197
+ appendChildren(node, children);
198
+ return node;
199
+ }
200
+
201
+ function applyProp(node, name, value) {
202
+ if (value === undefined || value === null || value === false) return;
203
+ if (name === 'class') node.className = value;
204
+ else if (name === 'text') node.textContent = value;
205
+ else if (name === 'on') {
206
+ for (const [type, handler] of Object.entries(value)) node.addEventListener(type, handler);
207
+ } else if (name === 'data') {
208
+ for (const [key, item] of Object.entries(value)) {
209
+ if (item !== undefined && item !== null) node.dataset[key] = String(item);
210
+ }
211
+ } else if (/^on/i.test(name) || name === 'style' || name === 'srcdoc') return;
212
+ else if (name === 'href' && !SAFE_HREF.test(value)) return;
213
+ else node.setAttribute(name, value === true ? '' : String(value));
214
+ }
215
+
216
+ function appendChildren(parent, children) {
217
+ for (const child of children) {
218
+ if (child === null || child === undefined || child === false) continue;
219
+ if (Array.isArray(child)) appendChildren(parent, child);
220
+ else parent.append(typeof child === 'object' ? child : document.createTextNode(String(child)));
221
+ }
222
+ }
223
+
224
+ /** Replace a node's children; unlike `replaceChildren`, nested arrays flatten and null children are skipped. */
225
+ export function fill(node, ...children) {
226
+ node.replaceChildren();
227
+ appendChildren(node, children);
228
+ return node;
229
+ }
230
+
231
+ export function chip(text, className = '') {
232
+ return el('span', { class: `chip ${className}`.trim() }, text);
233
+ }
234
+
235
+ export function editorLink(uri, label, className = 'editor-link') {
236
+ const href = safeEditorUri(uri);
237
+ return href ? el('a', { class: className, href }, label) : null;
238
+ }
239
+
240
+ export function notice(kind, ...children) {
241
+ return el('div', { class: `notice ${kind}`, role: kind === 'error' ? 'alert' : 'status' }, ...children);
242
+ }
243
+
244
+ export function staleNotice() {
245
+ return notice('warn', STALE_MESSAGE);
246
+ }
247
+
248
+ /** Only a live watcher doing normal work (including debounce and cooldown waits) is healthy; every other state warns. */
249
+ export function watcherTone(state) {
250
+ return HEALTHY_WATCHER_STATES.has(String(state).toLowerCase()) ? 'ok' : 'warn';
251
+ }
252
+
253
+ /** A list that renders `limit` rows and reveals the rest on request. */
254
+ export function expandableList(items, renderItem, { limit = 30, className = 'plain-list' } = {}) {
255
+ const list = el('ul', { class: className });
256
+ const append = (from, to) => {
257
+ for (const item of items.slice(from, to)) list.append(renderItem(item));
258
+ };
259
+ append(0, limit);
260
+ if (items.length > limit) {
261
+ const row = el('li', { class: 'more-row' });
262
+ const reveal = () => {
263
+ row.remove();
264
+ append(limit, items.length);
265
+ list.children[limit]?.querySelector('a, button')?.focus();
266
+ };
267
+ row.append(
268
+ el(
269
+ 'button',
270
+ { type: 'button', class: 'link-button', on: { click: reveal } },
271
+ `Show ${items.length - limit} more`,
272
+ ),
273
+ );
274
+ list.append(row);
275
+ }
276
+ return list;
277
+ }
278
+
279
+ // ── Payload adapters ──────────────────────────────────────
280
+
281
+ export function asArray(value) {
282
+ return Array.isArray(value) ? value : [];
283
+ }
284
+
285
+ function str(value) {
286
+ return typeof value === 'string' ? value : '';
287
+ }
288
+
289
+ function count(value) {
290
+ return typeof value === 'number' && Number.isFinite(value) ? value : null;
291
+ }
292
+
293
+ function sampleOf(sample) {
294
+ return sample && typeof sample.from === 'string' && typeof sample.to === 'string'
295
+ ? { from: sample.from, to: sample.to }
296
+ : null;
297
+ }
298
+
299
+ /**
300
+ * Reduce a scope payload to what the viewer draws. Nodes are directories,
301
+ * files, and external nodes (the payload's separate `external` list); each
302
+ * external node records whether it stands for one file or a directory so a
303
+ * click can open the right view. Edges to unknown nodes are dropped.
304
+ */
305
+ export function normalizeScope(raw, requestedPath = '') {
306
+ const nodes = [];
307
+ const ids = new Set();
308
+ const add = (item, forcedKind) => {
309
+ const path = str(item?.path) || str(item?.id);
310
+ const id = str(item?.id) || path;
311
+ if (!id || ids.has(id)) return;
312
+ ids.add(id);
313
+ const kind = forcedKind ?? (item.kind === 'dir' || item.kind === 'directory' ? 'directory' : 'file');
314
+ nodes.push({
315
+ id,
316
+ kind,
317
+ path,
318
+ name: forcedKind === 'external' ? path : str(item.name) || basename(path) || id,
319
+ fileCount: kind === 'directory' ? count(item.files) : null,
320
+ internalEdges: count(item.internalEdges) ?? 0,
321
+ cycle: count(item.cycle),
322
+ isFile: false,
323
+ });
324
+ };
325
+ for (const item of asArray(raw?.nodes)) add(item);
326
+ for (const item of asArray(raw?.external)) add(item, 'external');
327
+
328
+ const edges = [];
329
+ for (const item of asArray(raw?.edges)) {
330
+ const source = str(item?.from);
331
+ const target = str(item?.to);
332
+ if (!ids.has(source) || !ids.has(target)) continue;
333
+ edges.push({
334
+ id: `edge-${edges.length}`,
335
+ source,
336
+ target,
337
+ count: count(item.count) || 1,
338
+ cycle: item.cycle === true,
339
+ samples: asArray(item.samples).map(sampleOf).filter(Boolean),
340
+ });
341
+ }
342
+ const byId = new Map(nodes.map((node) => [node.id, node]));
343
+ for (const edge of edges) {
344
+ for (const node of [byId.get(edge.source), byId.get(edge.target)]) {
345
+ if (node.kind === 'external' && edge.samples.some((pair) => pair.from === node.path || pair.to === node.path)) {
346
+ node.isFile = true;
347
+ }
348
+ }
349
+ }
350
+ return {
351
+ path: str(raw?.scope) || requestedPath,
352
+ basis: raw?.basis === IMPORTS ? IMPORTS : REFERENCES,
353
+ nodes,
354
+ edges,
355
+ totals: { files: count(raw?.totals?.files), edges: count(raw?.totals?.edges) },
356
+ };
357
+ }
358
+
359
+ /** Region labels arrive as `root:<path>`; show the directory the way the map does. */
360
+ function regionLabel(label) {
361
+ const path = label.replace(/^root(?::|$)/, '').replace(/\/+$/, '');
362
+ return path ? `${path}/` : 'project root';
363
+ }
364
+
365
+ function laneLabel(kind, label, file, line) {
366
+ if (kind === 'region' && label) return regionLabel(label);
367
+ if (kind === 'location' && file) return formatLocation(file, line);
368
+ if (kind === 'symbol' && file) return symbolDisplayName(label);
369
+ return label;
370
+ }
371
+
372
+ /**
373
+ * A symbol label is its shortened identity (`src:queries:graph:value-flow:valueFlow()`); the file is
374
+ * already shown beside it, so only the member path after the module segment is kept (`valueFlow()`).
375
+ */
376
+ function symbolDisplayName(label) {
377
+ const parts = label.split(':');
378
+ return parts.length > 1 ? parts[parts.length - 1] : label;
379
+ }
380
+
381
+ /** One lane entry; `symbol`, the location, and `strength` may each be absent. */
382
+ export function normalizeLaneItem(item) {
383
+ const kind = str(item?.kind) || null;
384
+ const file = str(item?.file) || null;
385
+ const line = count(item?.line);
386
+ return {
387
+ kind,
388
+ label: laneLabel(kind, str(item?.label), file, line) || str(item?.symbol) || file || '(unnamed)',
389
+ symbol: str(item?.symbol) || null,
390
+ file,
391
+ line,
392
+ reference: item?.reference === true,
393
+ local: item?.local === true,
394
+ editorUri: safeEditorUri(item?.editorUri),
395
+ subtypes: asArray(item?.subtypes).filter((subtype) => typeof subtype === 'string' && subtype),
396
+ count: count(item?.count),
397
+ strength: str(item?.strength) || null,
398
+ };
399
+ }
400
+
401
+ function statementEndpoint(node) {
402
+ const location = node?.location;
403
+ return {
404
+ label: str(node?.label) || str(node?.symbol) || str(node?.id),
405
+ symbol: str(node?.symbol) || null,
406
+ place: location && typeof location.file === 'string' ? formatLocation(location.file, count(location.line)) : '',
407
+ };
408
+ }
409
+
410
+ /**
411
+ * The statements payload is an inventory of relationship counts plus the
412
+ * relationship edges; edges are grouped by family for display.
413
+ */
414
+ export function normalizeStatements(statements) {
415
+ const groups = new Map();
416
+ for (const edge of asArray(statements?.edges)) {
417
+ const family = str(edge?.family) || 'other';
418
+ if (!groups.has(family)) groups.set(family, []);
419
+ groups.get(family).push({
420
+ subtype: str(edge?.subtype),
421
+ from: statementEndpoint(edge?.from),
422
+ to: statementEndpoint(edge?.to),
423
+ strength: str(edge?.strength),
424
+ });
425
+ }
426
+ return {
427
+ inventory: asArray(statements?.inventory).map((row) => ({
428
+ family: str(row?.family),
429
+ subtype: str(row?.subtype),
430
+ incoming: count(row?.incoming) ?? 0,
431
+ outgoing: count(row?.outgoing) ?? 0,
432
+ both: count(row?.both) ?? 0,
433
+ })),
434
+ groups: [...groups].map(([name, rows]) => ({ name, rows })),
435
+ };
436
+ }
437
+
438
+ /** One line for a focus coverage object (`status`, `omittedEdges`); anything but `accounted` is flagged. */
439
+ export function describeCoverage(coverage) {
440
+ const status = str(coverage?.status);
441
+ if (!status) return null;
442
+ const omitted = count(coverage.omittedEdges) ?? 0;
443
+ return [
444
+ status,
445
+ omitted > 0 ? `${plural(omitted, 'edge')} omitted` : null,
446
+ status === 'accounted' ? null : 'an empty lane is not proof of absence',
447
+ ]
448
+ .filter(Boolean)
449
+ .join(' · ');
450
+ }