@plebeiantech/lat.md 0.12.3-fork.13 → 0.12.3-fork.15

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 (278) hide show
  1. package/README.md +24 -0
  2. package/dist/src/cli/check-context.d.ts +56 -0
  3. package/dist/src/cli/check-context.js +215 -0
  4. package/dist/src/cli/check-coverage.js +9 -5
  5. package/dist/src/cli/check-frontmatter.js +1 -1
  6. package/dist/src/cli/check-mode.js +1 -1
  7. package/dist/src/cli/check-status.js +1 -1
  8. package/dist/src/cli/check.d.ts +19 -12
  9. package/dist/src/cli/check.js +259 -206
  10. package/dist/src/cli/context.js +1 -1
  11. package/dist/src/cli/expand.d.ts +1 -2
  12. package/dist/src/cli/expand.js +52 -5
  13. package/dist/src/cli/external.d.ts +11 -0
  14. package/dist/src/cli/external.js +185 -0
  15. package/dist/src/cli/fork-instructions.d.ts +1 -0
  16. package/dist/src/cli/fork-instructions.js +3 -2
  17. package/dist/src/cli/hook.d.ts +26 -0
  18. package/dist/src/cli/hook.js +112 -40
  19. package/dist/src/cli/index.js +55 -3
  20. package/dist/src/cli/init.d.ts +1 -0
  21. package/dist/src/cli/init.js +40 -2
  22. package/dist/src/cli/locate.js +4 -3
  23. package/dist/src/cli/refs.d.ts +2 -1
  24. package/dist/src/cli/refs.js +88 -43
  25. package/dist/src/cli/reindex.js +2 -1
  26. package/dist/src/cli/search.d.ts +12 -3
  27. package/dist/src/cli/search.js +45 -49
  28. package/dist/src/cli/section.d.ts +3 -1
  29. package/dist/src/cli/section.js +114 -38
  30. package/dist/src/code-refs.d.ts +17 -5
  31. package/dist/src/code-refs.js +246 -65
  32. package/dist/src/context.d.ts +3 -0
  33. package/dist/src/document-formats.d.ts +7 -0
  34. package/dist/src/document-formats.js +39 -0
  35. package/dist/src/extensions/alert-marker.d.ts +25 -0
  36. package/dist/src/extensions/alert-marker.js +55 -0
  37. package/dist/src/external-documents.d.ts +56 -0
  38. package/dist/src/external-documents.js +404 -0
  39. package/dist/src/external-sources.d.ts +136 -0
  40. package/dist/src/external-sources.js +1098 -0
  41. package/dist/src/fork/antigravity-hook.d.ts +47 -0
  42. package/dist/src/fork/antigravity-hook.js +424 -0
  43. package/dist/src/fork/antigravity-init.d.ts +17 -0
  44. package/dist/src/fork/antigravity-init.js +124 -0
  45. package/dist/src/fork/frontmatter-fields.d.ts +36 -0
  46. package/dist/src/fork/frontmatter-fields.js +23 -0
  47. package/dist/src/format.d.ts +5 -2
  48. package/dist/src/format.js +8 -3
  49. package/dist/src/graph-export.js +1 -1
  50. package/dist/src/lattice-model.d.ts +77 -0
  51. package/dist/src/lattice-model.js +464 -0
  52. package/dist/src/lattice.d.ts +9 -104
  53. package/dist/src/lattice.js +69 -516
  54. package/dist/src/markdown-analysis-cache.d.ts +20 -0
  55. package/dist/src/markdown-analysis-cache.js +139 -0
  56. package/dist/src/markdown-analysis-worker.d.ts +16 -0
  57. package/dist/src/markdown-analysis-worker.js +33 -0
  58. package/dist/src/markdown-analysis.d.ts +50 -0
  59. package/dist/src/markdown-analysis.js +139 -0
  60. package/dist/src/markdown-analyzer-loader.d.ts +4 -0
  61. package/dist/src/markdown-analyzer-loader.js +13 -0
  62. package/dist/src/markdown-validation.d.ts +25 -0
  63. package/dist/src/markdown-validation.js +104 -0
  64. package/dist/src/mcp/server.js +27 -11
  65. package/dist/src/parser-cache.d.ts +17 -0
  66. package/dist/src/parser-cache.js +65 -0
  67. package/dist/src/parser-import.d.ts +8 -0
  68. package/dist/src/parser-import.js +1 -0
  69. package/dist/src/parser.js +80 -5
  70. package/dist/src/path.d.ts +2 -0
  71. package/dist/src/path.js +4 -0
  72. package/dist/src/profiler.d.ts +16 -0
  73. package/dist/src/profiler.js +81 -0
  74. package/dist/src/project-analysis.d.ts +59 -0
  75. package/dist/src/project-analysis.js +233 -0
  76. package/dist/src/project-discovery.d.ts +6 -0
  77. package/dist/src/project-discovery.js +30 -0
  78. package/dist/src/repository-path.d.ts +11 -0
  79. package/dist/src/repository-path.js +52 -0
  80. package/dist/src/search/db.d.ts +1 -1
  81. package/dist/src/search/db.js +2 -2
  82. package/dist/src/search/embedder.d.ts +2 -1
  83. package/dist/src/search/embedder.js +6 -5
  84. package/dist/src/search/index.d.ts +2 -1
  85. package/dist/src/search/index.js +10 -8
  86. package/dist/src/search/query.d.ts +20 -0
  87. package/dist/src/search/query.js +67 -0
  88. package/dist/src/search/search.d.ts +3 -1
  89. package/dist/src/search/search.js +5 -2
  90. package/dist/src/source-formats.d.ts +7 -0
  91. package/dist/src/source-formats.js +26 -0
  92. package/dist/src/source-parser.d.ts +44 -4
  93. package/dist/src/source-parser.js +494 -57
  94. package/dist/src/view/client/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
  95. package/dist/src/view/client/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
  96. package/dist/src/view/client/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
  97. package/dist/src/view/client/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
  98. package/dist/src/view/client/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
  99. package/dist/src/view/client/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
  100. package/dist/src/view/client/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
  101. package/dist/src/view/client/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
  102. package/dist/src/view/client/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
  103. package/dist/src/view/client/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
  104. package/dist/src/view/client/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
  105. package/dist/src/view/client/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
  106. package/dist/src/view/client/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
  107. package/dist/src/view/client/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
  108. package/dist/src/view/client/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
  109. package/dist/src/view/client/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
  110. package/dist/src/view/client/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
  111. package/dist/src/view/client/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
  112. package/dist/src/view/client/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
  113. package/dist/src/view/client/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
  114. package/dist/src/view/client/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
  115. package/dist/src/view/client/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
  116. package/dist/src/view/client/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
  117. package/dist/src/view/client/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
  118. package/dist/src/view/client/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
  119. package/dist/src/view/client/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
  120. package/dist/src/view/client/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
  121. package/dist/src/view/client/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
  122. package/dist/src/view/client/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
  123. package/dist/src/view/client/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
  124. package/dist/src/view/client/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
  125. package/dist/src/view/client/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
  126. package/dist/src/view/client/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
  127. package/dist/src/view/client/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
  128. package/dist/src/view/client/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
  129. package/dist/src/view/client/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
  130. package/dist/src/view/client/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
  131. package/dist/src/view/client/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
  132. package/dist/src/view/client/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
  133. package/dist/src/view/client/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
  134. package/dist/src/view/client/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
  135. package/dist/src/view/client/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
  136. package/dist/src/view/client/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
  137. package/dist/src/view/client/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
  138. package/dist/src/view/client/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
  139. package/dist/src/view/client/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
  140. package/dist/src/view/client/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
  141. package/dist/src/view/client/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
  142. package/dist/src/view/client/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
  143. package/dist/src/view/client/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
  144. package/dist/src/view/client/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
  145. package/dist/src/view/client/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
  146. package/dist/src/view/client/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
  147. package/dist/src/view/client/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
  148. package/dist/src/view/client/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
  149. package/dist/src/view/client/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
  150. package/dist/src/view/client/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
  151. package/dist/src/view/client/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
  152. package/dist/src/view/client/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
  153. package/dist/src/view/client/assets/MarkdownEditor-B7quqPb8.js +28 -0
  154. package/dist/src/view/client/assets/OrbitControls-DwcpQNja.js +1 -0
  155. package/dist/src/view/client/assets/STLLoader-CLWTKt5i.js +1 -0
  156. package/dist/src/view/client/assets/abnfDiagram-VCTEODGH-V7-T6qsl.js +1 -0
  157. package/dist/src/view/client/assets/arc-BnwR8Bu7.js +1 -0
  158. package/dist/src/view/client/assets/architectureDiagram-5GKGNRK7-u97vDna9.js +36 -0
  159. package/dist/src/view/client/assets/blockDiagram-I7D4REHJ-DETl8e_H.js +129 -0
  160. package/dist/src/view/client/assets/c4Diagram-7LVT6UL2-DJRAT1Ve.js +38 -0
  161. package/dist/src/view/client/assets/channel-BwQbnWCN.js +1 -0
  162. package/dist/src/view/client/assets/chunk-2Q5K7J3B-C0TmOC1Q.js +1 -0
  163. package/dist/src/view/client/assets/chunk-5VM5RSS4-dfBOrYE6.js +15 -0
  164. package/dist/src/view/client/assets/chunk-F27PBJKO-DAnks99K.js +1 -0
  165. package/dist/src/view/client/assets/chunk-IMKFNOWR-CPjB07if.js +231 -0
  166. package/dist/src/view/client/assets/chunk-JWPE2WC7-VvU_gZI6.js +1 -0
  167. package/dist/src/view/client/assets/chunk-POPQ4Y6H-DDUbVF55.js +1 -0
  168. package/dist/src/view/client/assets/chunk-SVP7TREG-BHROkr6D.js +88 -0
  169. package/dist/src/view/client/assets/chunk-TICWLB2K-95PzGIOg.js +206 -0
  170. package/dist/src/view/client/assets/chunk-XXDRQBXY-MdmuLhIs.js +1 -0
  171. package/dist/src/view/client/assets/classDiagram-ZZMXUADV-HvQKkIS-.js +1 -0
  172. package/dist/src/view/client/assets/classDiagram-v2-VYDZK3BY-HvQKkIS-.js +1 -0
  173. package/dist/src/view/client/assets/cose-bilkent-JH36ORCC-CauUf_rN.js +1 -0
  174. package/dist/src/view/client/assets/cynefin-OW5HDTMX-CeA8IKWo.js +166 -0
  175. package/dist/src/view/client/assets/cynefinDiagram-5FMLGOSQ-L1rtcT8l.js +62 -0
  176. package/dist/src/view/client/assets/cytoscape.esm-DzSz-X2X.js +321 -0
  177. package/dist/src/view/client/assets/dagre-GXQ25YYZ-DLQwTa3H.js +4 -0
  178. package/dist/src/view/client/assets/defaultLocale-DX6XiGOO.js +1 -0
  179. package/dist/src/view/client/assets/diagram-S7CK7UJ4-kbKdIyXG.js +30 -0
  180. package/dist/src/view/client/assets/diagram-UQ7AKVKN-kmzp92RC.js +41 -0
  181. package/dist/src/view/client/assets/diagram-VSXAHHWV-EXJTU8qq.js +3 -0
  182. package/dist/src/view/client/assets/diagram-VX7I27RA-DAiIyMCG.js +24 -0
  183. package/dist/src/view/client/assets/diagram-Z3DM3KII-G9wz50ZV.js +24 -0
  184. package/dist/src/view/client/assets/ebnfDiagram-PWID7BFC-D2tVRCNA.js +1 -0
  185. package/dist/src/view/client/assets/erDiagram-RLTQ6QDP-C925J5A3.js +99 -0
  186. package/dist/src/view/client/assets/flowDiagram-HODETNUW-DzoCa-Nq.js +168 -0
  187. package/dist/src/view/client/assets/ganttDiagram-EL5Y4UJY-D2ebbg4p.js +292 -0
  188. package/dist/src/view/client/assets/gitGraphDiagram-WWUBYQGX-B4QratYy.js +106 -0
  189. package/dist/src/view/client/assets/index-BnENo9bV.js +1 -0
  190. package/dist/src/view/client/assets/index-D0ajr_Ja.css +1 -0
  191. package/dist/src/view/client/assets/index-KZcnpXJH.js +321 -0
  192. package/dist/src/view/client/assets/infoDiagram-27XIBGKW-DL4mtHkt.js +2 -0
  193. package/dist/src/view/client/assets/init-Gi6I4Gst.js +1 -0
  194. package/dist/src/view/client/assets/ishikawaDiagram-5VMMS53U-CW4mto2d.js +70 -0
  195. package/dist/src/view/client/assets/journeyDiagram-3NMN7TZE-8R4eacFW.js +139 -0
  196. package/dist/src/view/client/assets/kanban-definition-UXKFOSKX-Cy9ioXEJ.js +89 -0
  197. package/dist/src/view/client/assets/katex-HP8lGamR.js +257 -0
  198. package/dist/src/view/client/assets/layout-C0MFuhth.js +1 -0
  199. package/dist/src/view/client/assets/linear-Dv3N4dQR.js +1 -0
  200. package/dist/src/view/client/assets/logo-small-RR_KBOAT.svg +149 -0
  201. package/dist/src/view/client/assets/maplibre-gl-DnqZgfUS.js +800 -0
  202. package/dist/src/view/client/assets/mermaid.core-bds9A7e2.js +310 -0
  203. package/dist/src/view/client/assets/mindmap-definition-YA3MSWOX-DjmGW355.js +96 -0
  204. package/dist/src/view/client/assets/ordinal-Cboi1Yqb.js +1 -0
  205. package/dist/src/view/client/assets/pegDiagram-XKGWAZYB-BWsZp0ab.js +1 -0
  206. package/dist/src/view/client/assets/pieDiagram-E7YTZNPT-CCH2gGR-.js +39 -0
  207. package/dist/src/view/client/assets/quadrantDiagram-AXDQQJYC-CjocPJFz.js +7 -0
  208. package/dist/src/view/client/assets/railroadDiagram-O6MQD6OU-BjLeb2KF.js +1 -0
  209. package/dist/src/view/client/assets/requirementDiagram-BXWQKSXE-Ct6AoXRr.js +84 -0
  210. package/dist/src/view/client/assets/sankeyDiagram-P5KCCOFB-CIpgGN_w.js +40 -0
  211. package/dist/src/view/client/assets/sequenceDiagram-WJ2MYXX4-DrmLFj6w.js +162 -0
  212. package/dist/src/view/client/assets/sizeCapture-INFHLROL-BdFMe2Lr.js +1 -0
  213. package/dist/src/view/client/assets/stateDiagram-D77RDMKH-Zd9F1goW.js +1 -0
  214. package/dist/src/view/client/assets/stateDiagram-v2-MP3YSRHH-ByIKCftl.js +1 -0
  215. package/dist/src/view/client/assets/swimlanes-42K2YHIH-a7VFwi00.js +1 -0
  216. package/dist/src/view/client/assets/swimlanesDiagram-VR7AAH4N-CzxaUHB-.js +8 -0
  217. package/dist/src/view/client/assets/three.module-PDSP0dbZ.js +4108 -0
  218. package/dist/src/view/client/assets/timeline-definition-24CTP7MA-BExPu6X5.js +120 -0
  219. package/dist/src/view/client/assets/vennDiagram-4TSXK5OY-PC1MU3si.js +34 -0
  220. package/dist/src/view/client/assets/wardleyDiagram-VM6X3IG4-DNWqU3fa.js +78 -0
  221. package/dist/src/view/client/assets/xychartDiagram-S5SC5T6Z-E1uA28_D.js +7 -0
  222. package/dist/src/view/client/index.html +2 -2
  223. package/dist/src/view/client-shell.d.ts +2 -0
  224. package/dist/src/view/client-shell.js +5 -0
  225. package/dist/src/view/diagnostics.d.ts +3 -2
  226. package/dist/src/view/diagnostics.js +49 -58
  227. package/dist/src/view/document-edit.d.ts +8 -0
  228. package/dist/src/view/document-edit.js +25 -0
  229. package/dist/src/view/document-route.d.ts +12 -0
  230. package/dist/src/view/document-route.js +93 -0
  231. package/dist/src/view/document-tree.d.ts +18 -0
  232. package/dist/src/view/document-tree.js +139 -0
  233. package/dist/src/view/external-document-tree.d.ts +3 -0
  234. package/dist/src/view/external-document-tree.js +674 -0
  235. package/dist/src/view/git-diff.js +187 -0
  236. package/dist/src/view/git.js +1 -1
  237. package/dist/src/view/graph.d.ts +3 -2
  238. package/dist/src/view/graph.js +94 -7
  239. package/dist/src/view/highlight.d.ts +10 -2
  240. package/dist/src/view/highlight.js +4540 -1360
  241. package/dist/src/view/markdown.d.ts +3 -2
  242. package/dist/src/view/markdown.js +214 -53
  243. package/dist/src/view/protocol.d.ts +59 -6
  244. package/dist/src/view/references.d.ts +10 -25
  245. package/dist/src/view/references.js +117 -107
  246. package/dist/src/view/repository.d.ts +13 -3
  247. package/dist/src/view/repository.js +234 -15
  248. package/dist/src/view/search.d.ts +1 -1
  249. package/dist/src/view/search.js +3 -7
  250. package/dist/src/view/server.d.ts +11 -2
  251. package/dist/src/view/server.js +212 -70
  252. package/dist/src/view/source-target.js +5 -8
  253. package/dist/src/view/static-build.d.ts +1 -0
  254. package/dist/src/view/static-build.js +245 -42
  255. package/dist/src/view/static-protocol.d.ts +19 -2
  256. package/dist/src/view/store.d.ts +16 -3
  257. package/dist/src/view/store.js +228 -36
  258. package/dist/src/view/table-of-contents.d.ts +2 -2
  259. package/dist/src/view/table-of-contents.js +2 -22
  260. package/dist/src/walk.d.ts +5 -3
  261. package/dist/src/walk.js +102 -8
  262. package/dist/vendor/lat.md-server/cli.d.ts +2 -0
  263. package/dist/vendor/lat.md-server/cli.js +12 -0
  264. package/dist/vendor/lat.md-server/index.d.ts +38 -0
  265. package/dist/vendor/lat.md-server/index.js +128 -0
  266. package/package.json +52 -12
  267. package/plugins/lat-md/README.md +61 -0
  268. package/plugins/lat-md/hooks.json +38 -0
  269. package/plugins/lat-md/plugin.json +9 -0
  270. package/plugins/lat-md/rules/AGENTS.md +118 -0
  271. package/plugins/lat-md/skills/lat-md/SKILL.md +178 -0
  272. package/plugins/lat-md/skills/lat-md-conventions/SKILL.md +182 -0
  273. package/templates/AGENTS.md +15 -3
  274. package/templates/cursor-rules.md +12 -3
  275. package/templates/skill/SKILL.md +22 -1
  276. package/dist/src/view/client/assets/index-C3iaZyYT.css +0 -1
  277. package/dist/src/view/client/assets/index-KWi67IMz.js +0 -334
  278. package/dist/src/view/client/assets/logo-CNF8zs47.svg +0 -182
@@ -1,7 +1,10 @@
1
- import { readFileSync } from 'node:fs';
1
+ import { readFile } from 'node:fs/promises';
2
2
  import { dirname, join } from 'node:path';
3
3
  import { createRequire } from 'node:module';
4
+ import { performance } from 'node:perf_hooks';
5
+ import { PARSER_CACHE_VERSION, hashParserContent, parsedCachePath, parserCacheIdentity, readParsedCache, writeParsedCache, } from './parser-cache.js';
4
6
  import { Parser, Language, } from 'web-tree-sitter';
7
+ import { sourceFileExtension, } from './source-formats.js';
5
8
  // Lazy singleton for the parser
6
9
  let parserReady = null;
7
10
  let parserInstance = null;
@@ -21,25 +24,22 @@ async function ensureParser() {
21
24
  }
22
25
  return parserInstance;
23
26
  }
24
- /** Extension → tree-sitter WASM grammar mapping. This is the single source of
25
- * truth for which source file extensions lat supports. */
27
+ /** Every supported source extension must declare a tree-sitter grammar. */
26
28
  const grammarMap = {
27
- '.ts': 'tree-sitter-typescript.wasm',
28
- '.tsx': 'tree-sitter-tsx.wasm',
29
+ '.c': 'tree-sitter-c.wasm',
30
+ '.dart': 'tree-sitter-dart.wasm',
31
+ '.go': 'tree-sitter-go.wasm',
32
+ '.h': 'tree-sitter-c.wasm',
33
+ '.java': 'tree-sitter-java.wasm',
29
34
  '.js': 'tree-sitter-javascript.wasm',
30
35
  '.jsx': 'tree-sitter-javascript.wasm',
31
36
  '.py': 'tree-sitter-python.wasm',
32
37
  '.rs': 'tree-sitter-rust.wasm',
33
- '.go': 'tree-sitter-go.wasm',
34
- '.c': 'tree-sitter-c.wasm',
35
- '.h': 'tree-sitter-c.wasm',
38
+ '.ts': 'tree-sitter-typescript.wasm',
39
+ '.tsx': 'tree-sitter-tsx.wasm',
36
40
  };
37
- /** All source file extensions that lat can parse (derived from grammarMap). */
38
- export const SOURCE_EXTENSIONS = new Set(Object.keys(grammarMap));
39
41
  async function getLanguage(ext) {
40
42
  const wasmFile = grammarMap[ext];
41
- if (!wasmFile)
42
- return null;
43
43
  // Ensure WASM runtime is initialized before loading languages
44
44
  await ensureParser();
45
45
  if (!languages.has(wasmFile)) {
@@ -246,6 +246,314 @@ function extractPySymbols(tree) {
246
246
  }
247
247
  return symbols;
248
248
  }
249
+ function dartDirectChild(node, type) {
250
+ return node.namedChildren.find((child) => child.type === type) ?? null;
251
+ }
252
+ function dartDefinitionName(node) {
253
+ const fieldName = extractName(node);
254
+ if (fieldName)
255
+ return fieldName;
256
+ if (node.type === 'class_definition') {
257
+ const alias = dartDirectChild(node, 'mixin_application_class');
258
+ return alias ? (dartDirectChild(alias, 'identifier')?.text ?? null) : null;
259
+ }
260
+ if (node.type === 'type_alias') {
261
+ return dartDirectChild(node, 'type_identifier')?.text ?? null;
262
+ }
263
+ return dartDirectChild(node, 'identifier')?.text ?? null;
264
+ }
265
+ function dartCallableNode(node) {
266
+ if (node.type !== 'method_signature' && node.type !== 'declaration') {
267
+ return node;
268
+ }
269
+ return (node.namedChildren.find((child) => [
270
+ 'constructor_signature',
271
+ 'factory_constructor_signature',
272
+ 'function_signature',
273
+ 'getter_signature',
274
+ 'operator_signature',
275
+ 'redirecting_factory_constructor_signature',
276
+ 'setter_signature',
277
+ ].includes(child.type)) ?? null);
278
+ }
279
+ function dartCallableName(node, parent) {
280
+ const callable = dartCallableNode(node);
281
+ if (!callable)
282
+ return null;
283
+ if (callable.type === 'operator_signature') {
284
+ const operator = callable.namedChildren.find((child) => child.type.endsWith('_operator'));
285
+ return operator ? `operator ${operator.text}` : null;
286
+ }
287
+ if (callable.type === 'constructor_signature' ||
288
+ callable.type === 'factory_constructor_signature' ||
289
+ callable.type === 'redirecting_factory_constructor_signature') {
290
+ const names = callable.namedChildren
291
+ .filter((child) => child.type === 'identifier')
292
+ .map((child) => child.text);
293
+ if (names.length === 0)
294
+ return null;
295
+ if (names.length === 1)
296
+ return names[0];
297
+ return names[0] === parent ? names[1] : names.at(-1);
298
+ }
299
+ return extractName(callable);
300
+ }
301
+ function dartAnnotatedStart(siblings, index) {
302
+ let start = siblings[index];
303
+ for (let i = index - 1; i >= 0 && siblings[i].type === 'annotation'; i--) {
304
+ start = siblings[i];
305
+ }
306
+ return start;
307
+ }
308
+ function dartDefinitionEnd(siblings, index) {
309
+ return siblings[index + 1]?.type === 'function_body'
310
+ ? siblings[index + 1]
311
+ : siblings[index];
312
+ }
313
+ function dartSignature(sourceLines, node) {
314
+ return sourceLines[node.startPosition.row]?.trim() ?? '';
315
+ }
316
+ function pushDartSymbol(sourceLines, symbols, name, kind, node, options = {}) {
317
+ symbols.push({
318
+ name,
319
+ kind,
320
+ ...(options.parent ? { parent: options.parent } : {}),
321
+ startLine: (options.start ?? node).startPosition.row + 1,
322
+ endLine: (options.end ?? node).endPosition.row + 1,
323
+ signature: dartSignature(sourceLines, node),
324
+ });
325
+ }
326
+ function dartVariableKind(siblings, index, container) {
327
+ if (container?.namedChildren.some((child) => child.type === 'const_builtin')) {
328
+ return 'const';
329
+ }
330
+ const row = siblings[index].startPosition.row;
331
+ for (let i = index - 1; i >= 0 && siblings[i].endPosition.row === row; i--) {
332
+ if (siblings[i].type === 'const_builtin')
333
+ return 'const';
334
+ }
335
+ return 'variable';
336
+ }
337
+ function extractDartVariables(sourceLines, symbols, node, kind, parent) {
338
+ const lists = node.type === 'initialized_identifier_list' ||
339
+ node.type === 'static_final_declaration_list'
340
+ ? [node]
341
+ : node.namedChildren.filter((child) => child.type === 'initialized_identifier_list' ||
342
+ child.type === 'static_final_declaration_list');
343
+ for (const list of lists) {
344
+ for (const declaration of list.namedChildren) {
345
+ if (declaration.type !== 'initialized_identifier' &&
346
+ declaration.type !== 'static_final_declaration') {
347
+ continue;
348
+ }
349
+ const name = dartDirectChild(declaration, 'identifier')?.text;
350
+ if (name) {
351
+ pushDartSymbol(sourceLines, symbols, name, kind, node, { parent });
352
+ }
353
+ }
354
+ }
355
+ }
356
+ function extractDartMembers(sourceLines, body, parent, symbols) {
357
+ const children = body.namedChildren;
358
+ for (let i = 0; i < children.length; i++) {
359
+ const node = children[i];
360
+ if (node.type === 'method_signature') {
361
+ const name = dartCallableName(node, parent);
362
+ if (name) {
363
+ pushDartSymbol(sourceLines, symbols, name, 'method', node, {
364
+ parent,
365
+ start: dartAnnotatedStart(children, i),
366
+ end: dartDefinitionEnd(children, i),
367
+ });
368
+ }
369
+ }
370
+ else if (node.type === 'declaration') {
371
+ const name = dartCallableName(node, parent);
372
+ if (name) {
373
+ pushDartSymbol(sourceLines, symbols, name, 'method', node, { parent });
374
+ }
375
+ extractDartVariables(sourceLines, symbols, node, dartVariableKind(children, i, node), parent);
376
+ }
377
+ else if (node.type === 'enum_constant') {
378
+ const name = extractName(node);
379
+ if (name) {
380
+ pushDartSymbol(sourceLines, symbols, name, 'const', node, { parent });
381
+ }
382
+ }
383
+ }
384
+ }
385
+ function extractDartSymbols(tree) {
386
+ const symbols = [];
387
+ const children = tree.rootNode.namedChildren;
388
+ const sourceLines = tree.rootNode.text.split('\n');
389
+ for (let i = 0; i < children.length; i++) {
390
+ const node = children[i];
391
+ const start = dartAnnotatedStart(children, i);
392
+ if (node.type === 'function_signature' ||
393
+ node.type === 'getter_signature' ||
394
+ node.type === 'setter_signature') {
395
+ const name = dartCallableName(node);
396
+ if (name) {
397
+ pushDartSymbol(sourceLines, symbols, name, 'function', node, {
398
+ start,
399
+ end: dartDefinitionEnd(children, i),
400
+ });
401
+ }
402
+ }
403
+ else if (node.type === 'class_definition') {
404
+ const name = dartDefinitionName(node);
405
+ if (!name)
406
+ continue;
407
+ pushDartSymbol(sourceLines, symbols, name, 'class', node, { start });
408
+ const body = node.childForFieldName('body');
409
+ if (body)
410
+ extractDartMembers(sourceLines, body, name, symbols);
411
+ }
412
+ else if (node.type === 'mixin_declaration') {
413
+ const name = dartDefinitionName(node);
414
+ if (!name)
415
+ continue;
416
+ pushDartSymbol(sourceLines, symbols, name, 'interface', node, { start });
417
+ const body = dartDirectChild(node, 'class_body');
418
+ if (body)
419
+ extractDartMembers(sourceLines, body, name, symbols);
420
+ }
421
+ else if (node.type === 'extension_declaration') {
422
+ const name = extractName(node);
423
+ if (!name)
424
+ continue;
425
+ pushDartSymbol(sourceLines, symbols, name, 'class', node, { start });
426
+ const body = node.childForFieldName('body');
427
+ if (body)
428
+ extractDartMembers(sourceLines, body, name, symbols);
429
+ }
430
+ else if (node.type === 'enum_declaration') {
431
+ const name = extractName(node);
432
+ if (!name)
433
+ continue;
434
+ pushDartSymbol(sourceLines, symbols, name, 'class', node, { start });
435
+ const body = node.childForFieldName('body');
436
+ if (body)
437
+ extractDartMembers(sourceLines, body, name, symbols);
438
+ }
439
+ else if (node.type === 'extension_type_declaration') {
440
+ const name = extractName(node);
441
+ if (!name)
442
+ continue;
443
+ pushDartSymbol(sourceLines, symbols, name, 'type', node, { start });
444
+ const representation = node.childForFieldName('representation');
445
+ const representationName = representation?.childForFieldName('name');
446
+ if (representation && representationName) {
447
+ pushDartSymbol(sourceLines, symbols, representationName.text, 'variable', representation, { parent: name });
448
+ }
449
+ const body = node.childForFieldName('body');
450
+ if (body)
451
+ extractDartMembers(sourceLines, body, name, symbols);
452
+ }
453
+ else if (node.type === 'type_alias') {
454
+ const name = dartDefinitionName(node);
455
+ if (name) {
456
+ pushDartSymbol(sourceLines, symbols, name, 'type', node, { start });
457
+ }
458
+ }
459
+ else if (node.type === 'initialized_identifier_list' ||
460
+ node.type === 'static_final_declaration_list') {
461
+ extractDartVariables(sourceLines, symbols, node, dartVariableKind(children, i));
462
+ }
463
+ }
464
+ return symbols;
465
+ }
466
+ const javaTypeKinds = {
467
+ annotation_type_declaration: 'interface',
468
+ class_declaration: 'class',
469
+ enum_declaration: 'class',
470
+ interface_declaration: 'interface',
471
+ record_declaration: 'class',
472
+ };
473
+ function javaSignature(sourceLines, node) {
474
+ const declarator = node.namedChildren.find((child) => child.type === 'variable_declarator');
475
+ const name = node.childForFieldName('name') ?? declarator?.childForFieldName('name');
476
+ return sourceLines[(name ?? node).startPosition.row]?.trim() ?? '';
477
+ }
478
+ function pushJavaSymbol(sourceLines, symbols, name, kind, node, parent) {
479
+ const symbol = {
480
+ name,
481
+ kind,
482
+ ...(parent ? { parent } : {}),
483
+ startLine: node.startPosition.row + 1,
484
+ endLine: node.endPosition.row + 1,
485
+ signature: javaSignature(sourceLines, node),
486
+ };
487
+ symbols.push(symbol);
488
+ return symbol;
489
+ }
490
+ function extractJavaVariables(sourceLines, symbols, node, parent) {
491
+ const kind = node.type === 'constant_declaration' ? 'const' : 'variable';
492
+ for (const declarator of node.namedChildren) {
493
+ if (declarator.type !== 'variable_declarator')
494
+ continue;
495
+ const name = extractName(declarator);
496
+ if (name) {
497
+ pushJavaSymbol(sourceLines, symbols, name, kind, node, parent);
498
+ }
499
+ }
500
+ }
501
+ function collectJavaScope(sourceLines, scope, parent, symbols) {
502
+ for (const node of scope.namedChildren) {
503
+ const typeKind = javaTypeKinds[node.type];
504
+ if (typeKind) {
505
+ const name = extractName(node);
506
+ if (!name)
507
+ continue;
508
+ const symbol = pushJavaSymbol(sourceLines, symbols, name, typeKind, node);
509
+ if (parent)
510
+ symbols.push({ ...symbol, parent });
511
+ if (node.type === 'record_declaration') {
512
+ const parameters = node.childForFieldName('parameters');
513
+ for (const parameter of parameters?.namedChildren ?? []) {
514
+ const component = extractName(parameter);
515
+ if (component) {
516
+ pushJavaSymbol(sourceLines, symbols, component, 'variable', parameter, name);
517
+ }
518
+ }
519
+ }
520
+ const body = node.childForFieldName('body');
521
+ if (body)
522
+ collectJavaScope(sourceLines, body, name, symbols);
523
+ continue;
524
+ }
525
+ if (!parent)
526
+ continue;
527
+ if (node.type === 'method_declaration' ||
528
+ node.type === 'constructor_declaration' ||
529
+ node.type === 'compact_constructor_declaration' ||
530
+ node.type === 'annotation_type_element_declaration') {
531
+ const name = extractName(node);
532
+ if (name) {
533
+ pushJavaSymbol(sourceLines, symbols, name, 'method', node, parent);
534
+ }
535
+ }
536
+ else if (node.type === 'field_declaration' ||
537
+ node.type === 'constant_declaration') {
538
+ extractJavaVariables(sourceLines, symbols, node, parent);
539
+ }
540
+ else if (node.type === 'enum_constant') {
541
+ const name = extractName(node);
542
+ if (name) {
543
+ pushJavaSymbol(sourceLines, symbols, name, 'const', node, parent);
544
+ }
545
+ }
546
+ else if (node.type === 'enum_body_declarations') {
547
+ collectJavaScope(sourceLines, node, parent, symbols);
548
+ }
549
+ }
550
+ }
551
+ function extractJavaSymbols(tree) {
552
+ const symbols = [];
553
+ const sourceLines = tree.rootNode.text.split('\n');
554
+ collectJavaScope(sourceLines, tree.rootNode, undefined, symbols);
555
+ return symbols;
556
+ }
249
557
  function extractRustSymbols(tree) {
250
558
  const symbols = [];
251
559
  const root = tree.rootNode;
@@ -784,72 +1092,200 @@ function firstLine(text) {
784
1092
  const nl = text.indexOf('\n');
785
1093
  return nl === -1 ? text : text.slice(0, nl);
786
1094
  }
1095
+ /** Every supported source extension must declare a symbol extractor. */
1096
+ const symbolExtractors = {
1097
+ '.c': extractCSymbols,
1098
+ '.dart': extractDartSymbols,
1099
+ '.go': extractGoSymbols,
1100
+ '.h': extractCSymbols,
1101
+ '.java': extractJavaSymbols,
1102
+ '.js': extractTsSymbols,
1103
+ '.jsx': extractTsSymbols,
1104
+ '.py': extractPySymbols,
1105
+ '.rs': extractRustSymbols,
1106
+ '.ts': extractTsSymbols,
1107
+ '.tsx': extractTsSymbols,
1108
+ };
787
1109
  export async function parseSourceSymbols(filePath, content) {
788
- const ext = filePath.match(/\.[^.]+$/)?.[0] ?? '';
789
- const lang = await getLanguage(ext);
790
- if (!lang)
1110
+ const ext = sourceFileExtension(filePath);
1111
+ if (!ext)
791
1112
  return [];
1113
+ const lang = await getLanguage(ext);
792
1114
  const p = await ensureParser();
793
1115
  p.setLanguage(lang);
794
1116
  const tree = p.parse(content);
795
1117
  if (!tree)
796
1118
  return [];
797
1119
  try {
798
- if (ext === '.py') {
799
- return extractPySymbols(tree);
800
- }
801
- if (ext === '.rs') {
802
- return extractRustSymbols(tree);
803
- }
804
- if (ext === '.go') {
805
- return extractGoSymbols(tree);
806
- }
807
- if (ext === '.c' || ext === '.h') {
808
- return extractCSymbols(tree);
809
- }
810
- return extractTsSymbols(tree);
1120
+ return symbolExtractors[ext](tree);
811
1121
  }
812
1122
  finally {
813
1123
  tree.delete();
814
1124
  }
815
1125
  }
816
- // Per-invocation cache for parsed source symbols, keyed by absolute file path.
817
- // Prevents re-parsing the same file when multiple wiki links reference it
818
- // (e.g. 20+ links to quickjs.c would otherwise parse a 60K-line file 20 times).
819
- const symbolCache = new Map();
1126
+ function isRecord(value) {
1127
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
1128
+ }
1129
+ const sourceSymbolKinds = new Set([
1130
+ 'function',
1131
+ 'class',
1132
+ 'const',
1133
+ 'type',
1134
+ 'interface',
1135
+ 'method',
1136
+ 'variable',
1137
+ ]);
1138
+ function isSourceSymbol(value) {
1139
+ if (!isRecord(value))
1140
+ return false;
1141
+ return (typeof value.name === 'string' &&
1142
+ typeof value.kind === 'string' &&
1143
+ sourceSymbolKinds.has(value.kind) &&
1144
+ (value.parent === undefined || typeof value.parent === 'string') &&
1145
+ Number.isInteger(value.startLine) &&
1146
+ value.startLine > 0 &&
1147
+ Number.isInteger(value.endLine) &&
1148
+ value.endLine >= value.startLine &&
1149
+ typeof value.signature === 'string');
1150
+ }
1151
+ function cachedSourceAnalysis(entry, contentHash, identity, timings) {
1152
+ if (!entry ||
1153
+ entry.version !== PARSER_CACHE_VERSION ||
1154
+ entry.contentHash !== contentHash ||
1155
+ !isRecord(entry.value) ||
1156
+ entry.value.path !== identity ||
1157
+ !Array.isArray(entry.value.symbols) ||
1158
+ !entry.value.symbols.every(isSourceSymbol)) {
1159
+ return null;
1160
+ }
1161
+ return {
1162
+ path: identity,
1163
+ symbols: entry.value.symbols,
1164
+ timings: {
1165
+ ...timings,
1166
+ cacheStatus: 'hit',
1167
+ cacheWriteMs: 0,
1168
+ parseMs: 0,
1169
+ },
1170
+ };
1171
+ }
1172
+ /** Request-scoped owner for in-flight and completed source parser work. */
1173
+ export class SourceParserRuntime {
1174
+ analyses = new Map();
1175
+ symbols = new Map();
1176
+ clear() {
1177
+ this.analyses.clear();
1178
+ this.symbols.clear();
1179
+ }
1180
+ }
1181
+ const defaultSourceParserRuntime = new SourceParserRuntime();
1182
+ /** Return the parser cache path for one project source file. */
1183
+ export function sourceAnalysisCachePath(latDir, projectRoot, absolutePath) {
1184
+ return parsedCachePath(latDir, parserCacheIdentity(absolutePath, projectRoot));
1185
+ }
1186
+ /** Analyze source content through the shared versioned persistent cache. */
1187
+ export async function analyzeSourceSymbols(filePath, content, latDir, options = {}) {
1188
+ const identity = (options.identity ?? filePath)
1189
+ .replaceAll('\\', '/')
1190
+ .normalize('NFC');
1191
+ const hashStarted = performance.now();
1192
+ const contentHash = hashParserContent(content);
1193
+ const hashMs = performance.now() - hashStarted;
1194
+ const cache = options.cache !== false;
1195
+ const cachePath = parsedCachePath(latDir, identity);
1196
+ const promiseKey = `${cache ? 'cache' : 'direct'}\0${cachePath}\0${contentHash}`;
1197
+ const runtime = options.runtime ?? defaultSourceParserRuntime;
1198
+ let analysis = runtime.analyses.get(promiseKey);
1199
+ if (!analysis) {
1200
+ analysis = (async () => {
1201
+ const cacheStarted = performance.now();
1202
+ const entry = cache ? await readParsedCache(cachePath) : null;
1203
+ const cacheReadMs = cache ? performance.now() - cacheStarted : 0;
1204
+ const timings = {
1205
+ readMs: options.readMs ?? 0,
1206
+ hashMs,
1207
+ cacheReadMs,
1208
+ cacheStatus: cache ? 'miss' : 'disabled',
1209
+ };
1210
+ const cached = cache
1211
+ ? cachedSourceAnalysis(entry, contentHash, identity, timings)
1212
+ : null;
1213
+ if (cached)
1214
+ return cached;
1215
+ const parseStarted = performance.now();
1216
+ const symbols = await parseSourceSymbols(filePath, content);
1217
+ const result = {
1218
+ path: identity,
1219
+ symbols,
1220
+ timings: {
1221
+ ...timings,
1222
+ cacheWriteMs: 0,
1223
+ parseMs: performance.now() - parseStarted,
1224
+ },
1225
+ };
1226
+ if (!cache)
1227
+ return result;
1228
+ const writeStarted = performance.now();
1229
+ try {
1230
+ await writeParsedCache(cachePath, contentHash, result);
1231
+ }
1232
+ catch {
1233
+ // The cache is a disposable optimization; parsing must work read-only.
1234
+ }
1235
+ result.timings.cacheWriteMs = performance.now() - writeStarted;
1236
+ return result;
1237
+ })();
1238
+ runtime.analyses.set(promiseKey, analysis);
1239
+ }
1240
+ return analysis;
1241
+ }
820
1242
  /** Clear the symbol cache. Call between top-level operations. */
821
1243
  export function clearSymbolCache() {
822
- symbolCache.clear();
1244
+ defaultSourceParserRuntime.clear();
823
1245
  }
824
1246
  /**
825
1247
  * Check whether a source file path (relative to projectRoot) has a given symbol.
826
1248
  * Used by lat check to validate source code wiki links lazily.
827
1249
  */
828
- export async function resolveSourceSymbol(filePath, symbolPath, projectRoot) {
1250
+ export async function resolveSourceSymbol(filePath, symbolPath, projectRoot, options = {}) {
829
1251
  const absPath = join(projectRoot, filePath);
830
- let cached = symbolCache.get(absPath);
831
- if (!cached) {
832
- let content;
833
- try {
834
- content = readFileSync(absPath, 'utf-8');
835
- }
836
- catch {
837
- cached = { symbols: [] };
838
- symbolCache.set(absPath, cached);
839
- return { found: false, symbols: [] };
840
- }
841
- try {
842
- const symbols = await parseSourceSymbols(filePath, content);
843
- cached = { symbols };
844
- }
845
- catch (err) {
846
- cached = {
847
- symbols: [],
848
- error: `failed to parse "${filePath}": ${err instanceof Error ? err.message : String(err)}`,
849
- };
850
- }
851
- symbolCache.set(absPath, cached);
1252
+ const latDir = options.latDir ?? join(projectRoot, 'lat.md');
1253
+ const cacheKey = `${latDir}\0${absPath}`;
1254
+ const runtime = options.runtime ?? defaultSourceParserRuntime;
1255
+ let cachedPromise = runtime.symbols.get(cacheKey);
1256
+ const created = !cachedPromise;
1257
+ if (!cachedPromise) {
1258
+ cachedPromise = (async () => {
1259
+ const readStarted = performance.now();
1260
+ let content;
1261
+ try {
1262
+ content = await readFile(absPath, 'utf-8');
1263
+ }
1264
+ catch {
1265
+ return { symbols: [] };
1266
+ }
1267
+ const readMs = performance.now() - readStarted;
1268
+ try {
1269
+ const analysis = await analyzeSourceSymbols(filePath, content, latDir, {
1270
+ cache: options.cache,
1271
+ identity: parserCacheIdentity(absPath, projectRoot),
1272
+ readMs,
1273
+ runtime,
1274
+ });
1275
+ return { symbols: analysis.symbols, analysis };
1276
+ }
1277
+ catch (err) {
1278
+ return {
1279
+ symbols: [],
1280
+ error: `failed to parse "${filePath}": ${err instanceof Error ? err.message : String(err)}`,
1281
+ };
1282
+ }
1283
+ })();
1284
+ runtime.symbols.set(cacheKey, cachedPromise);
852
1285
  }
1286
+ const cached = await cachedPromise;
1287
+ if (created && cached.analysis)
1288
+ options.onFileAnalyzed?.(cached.analysis);
853
1289
  if (cached.error) {
854
1290
  return { found: false, symbols: cached.symbols, error: cached.error };
855
1291
  }
@@ -873,6 +1309,7 @@ export async function resolveSourceSymbol(filePath, symbolPath, projectRoot) {
873
1309
  export function sourceSymbolsToSections(symbols, filePath) {
874
1310
  const sections = [];
875
1311
  const classMap = new Map();
1312
+ const parentNames = new Set(symbols.flatMap((symbol) => (symbol.parent ? [symbol.parent] : [])));
876
1313
  for (const sym of symbols) {
877
1314
  if (sym.parent)
878
1315
  continue; // Handle methods after their class
@@ -888,7 +1325,7 @@ export function sourceSymbolsToSections(symbols, filePath) {
888
1325
  firstParagraph: sym.signature,
889
1326
  };
890
1327
  sections.push(section);
891
- if (sym.kind === 'class') {
1328
+ if (parentNames.has(sym.name)) {
892
1329
  classMap.set(sym.name, section);
893
1330
  }
894
1331
  }