@plebeiantech/lat.md 0.12.3-fork.2 → 0.12.3-fork.21

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 (341) hide show
  1. package/README.md +31 -2
  2. package/dist/src/cli/agent-invocation.d.ts +6 -0
  3. package/dist/src/cli/agent-invocation.js +23 -0
  4. package/dist/src/cli/checklist-menu.d.ts +2 -1
  5. package/dist/src/cli/checklist-menu.js +3 -2
  6. package/dist/src/cli/comment-guard.d.ts +14 -0
  7. package/dist/src/cli/comment-guard.js +10 -33
  8. package/dist/src/cli/comment-reminder.d.ts +65 -6
  9. package/dist/src/cli/comment-reminder.js +164 -28
  10. package/dist/src/cli/fork-instructions.d.ts +20 -0
  11. package/dist/src/cli/fork-instructions.js +184 -0
  12. package/dist/src/cli/fork-scaffold.d.ts +106 -0
  13. package/dist/src/cli/fork-scaffold.js +490 -0
  14. package/dist/src/cli/graph.d.ts +1 -1
  15. package/dist/src/cli/hook.d.ts +26 -0
  16. package/dist/src/cli/hook.js +115 -64
  17. package/dist/src/cli/index.js +166 -64
  18. package/dist/src/cli/init-preferences.d.ts +4 -0
  19. package/dist/src/cli/init-preferences.js +36 -0
  20. package/dist/src/cli/init.d.ts +2 -1
  21. package/dist/src/cli/init.js +107 -50
  22. package/dist/src/cli/reindex.d.ts +1 -1
  23. package/dist/src/cli/reindex.js +7 -10
  24. package/dist/src/cli/search.d.ts +14 -4
  25. package/dist/src/cli/search.js +116 -100
  26. package/dist/src/cli/ui-build-server.d.ts +12 -0
  27. package/dist/src/cli/ui-build-server.js +26 -0
  28. package/dist/src/cli/ui-build.d.ts +4 -0
  29. package/dist/src/cli/ui-build.js +13 -0
  30. package/dist/src/cli/ui.d.ts +1 -1
  31. package/dist/src/cli/ui.js +18 -2
  32. package/dist/src/fork/antigravity-hook.d.ts +47 -0
  33. package/dist/src/fork/antigravity-hook.js +424 -0
  34. package/dist/src/fork/antigravity-init.d.ts +17 -0
  35. package/dist/src/fork/antigravity-init.js +124 -0
  36. package/dist/src/fork/upstream-drift-cli.js +2 -0
  37. package/dist/src/fork/upstream-drift.d.ts +26 -0
  38. package/dist/src/fork/upstream-drift.js +185 -0
  39. package/dist/src/fork/upstream-guard-cli.d.ts +1 -0
  40. package/dist/src/fork/upstream-guard-cli.js +2 -0
  41. package/dist/src/fork/upstream-guard.d.ts +72 -0
  42. package/dist/src/fork/upstream-guard.js +445 -0
  43. package/dist/src/graph-export.d.ts +2 -0
  44. package/dist/src/graph-export.js +38 -19
  45. package/dist/src/knowledge/claude-memory.d.ts +1 -0
  46. package/dist/src/knowledge/claude-memory.js +33 -4
  47. package/dist/src/knowledge/index.js +2 -2
  48. package/dist/src/mcp/server.js +34 -18
  49. package/dist/src/search/cache.d.ts +3 -0
  50. package/dist/src/search/cache.js +104 -0
  51. package/dist/src/search/chunks.d.ts +23 -0
  52. package/dist/src/search/chunks.js +200 -0
  53. package/dist/src/search/db.d.ts +28 -16
  54. package/dist/src/search/db.js +106 -40
  55. package/dist/src/search/embedder.d.ts +2 -1
  56. package/dist/src/search/embedder.js +7 -6
  57. package/dist/src/search/index.d.ts +6 -2
  58. package/dist/src/search/index.js +176 -53
  59. package/dist/src/search/lexical.d.ts +6 -0
  60. package/dist/src/search/lexical.js +36 -0
  61. package/dist/src/search/lock.d.ts +5 -0
  62. package/dist/src/search/lock.js +45 -0
  63. package/dist/src/search/query.d.ts +26 -0
  64. package/dist/src/search/query.js +103 -0
  65. package/dist/src/search/search.d.ts +17 -7
  66. package/dist/src/search/search.js +164 -14
  67. package/dist/src/search/types.d.ts +15 -0
  68. package/dist/src/search/types.js +1 -0
  69. package/dist/src/view/client/assets/GraphView-0bPe_Q5I.js +456 -0
  70. package/dist/src/view/client/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
  71. package/dist/src/view/client/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
  72. package/dist/src/view/client/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
  73. package/dist/src/view/client/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
  74. package/dist/src/view/client/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
  75. package/dist/src/view/client/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
  76. package/dist/src/view/client/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
  77. package/dist/src/view/client/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
  78. package/dist/src/view/client/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
  79. package/dist/src/view/client/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
  80. package/dist/src/view/client/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
  81. package/dist/src/view/client/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
  82. package/dist/src/view/client/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
  83. package/dist/src/view/client/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
  84. package/dist/src/view/client/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
  85. package/dist/src/view/client/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
  86. package/dist/src/view/client/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
  87. package/dist/src/view/client/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
  88. package/dist/src/view/client/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
  89. package/dist/src/view/client/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
  90. package/dist/src/view/client/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
  91. package/dist/src/view/client/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
  92. package/dist/src/view/client/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
  93. package/dist/src/view/client/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
  94. package/dist/src/view/client/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
  95. package/dist/src/view/client/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
  96. package/dist/src/view/client/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
  97. package/dist/src/view/client/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
  98. package/dist/src/view/client/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
  99. package/dist/src/view/client/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
  100. package/dist/src/view/client/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
  101. package/dist/src/view/client/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
  102. package/dist/src/view/client/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
  103. package/dist/src/view/client/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
  104. package/dist/src/view/client/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
  105. package/dist/src/view/client/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
  106. package/dist/src/view/client/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
  107. package/dist/src/view/client/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
  108. package/dist/src/view/client/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
  109. package/dist/src/view/client/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
  110. package/dist/src/view/client/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
  111. package/dist/src/view/client/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
  112. package/dist/src/view/client/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
  113. package/dist/src/view/client/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
  114. package/dist/src/view/client/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
  115. package/dist/src/view/client/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
  116. package/dist/src/view/client/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
  117. package/dist/src/view/client/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
  118. package/dist/src/view/client/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
  119. package/dist/src/view/client/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
  120. package/dist/src/view/client/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
  121. package/dist/src/view/client/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
  122. package/dist/src/view/client/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
  123. package/dist/src/view/client/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
  124. package/dist/src/view/client/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
  125. package/dist/src/view/client/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
  126. package/dist/src/view/client/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
  127. package/dist/src/view/client/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
  128. package/dist/src/view/client/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
  129. package/dist/src/view/client/assets/MarkdownEditor-1_8mI7lO.js +28 -0
  130. package/dist/src/view/client/assets/OrbitControls-DwcpQNja.js +1 -0
  131. package/dist/src/view/client/assets/STLLoader-CLWTKt5i.js +1 -0
  132. package/dist/src/view/client/assets/_commonjsHelpers-CqkleIqs.js +1 -0
  133. package/dist/src/view/client/assets/abnfDiagram-VCTEODGH-BLIuikwY.js +1 -0
  134. package/dist/src/view/client/assets/arc-D4PzdKSA.js +1 -0
  135. package/dist/src/view/client/assets/architectureDiagram-5GKGNRK7-35Egww62.js +36 -0
  136. package/dist/src/view/client/assets/blockDiagram-I7D4REHJ-tqNy53-W.js +129 -0
  137. package/dist/src/view/client/assets/c4Diagram-7LVT6UL2-DZ_GcD9K.js +38 -0
  138. package/dist/src/view/client/assets/channel-DensupHE.js +1 -0
  139. package/dist/src/view/client/assets/chunk-2Q5K7J3B-BUjq4Q7b.js +1 -0
  140. package/dist/src/view/client/assets/chunk-5VM5RSS4-BsIix6I5.js +15 -0
  141. package/dist/src/view/client/assets/chunk-F27PBJKO-Dxo7UheG.js +1 -0
  142. package/dist/src/view/client/assets/chunk-IMKFNOWR-C5lzUDK5.js +231 -0
  143. package/dist/src/view/client/assets/chunk-JWPE2WC7-qCHQlKfY.js +1 -0
  144. package/dist/src/view/client/assets/chunk-POPQ4Y6H-CDPKw21I.js +1 -0
  145. package/dist/src/view/client/assets/chunk-SVP7TREG-CD_C-9M-.js +88 -0
  146. package/dist/src/view/client/assets/chunk-TICWLB2K-ZMatRvad.js +206 -0
  147. package/dist/src/view/client/assets/chunk-XXDRQBXY-dDs4quwg.js +1 -0
  148. package/dist/src/view/client/assets/classDiagram-ZZMXUADV-CV7ArHLW.js +1 -0
  149. package/dist/src/view/client/assets/classDiagram-v2-VYDZK3BY-CV7ArHLW.js +1 -0
  150. package/dist/src/view/client/assets/cose-bilkent-JH36ORCC-CwH3-T1N.js +1 -0
  151. package/dist/src/view/client/assets/cynefin-OW5HDTMX-DodS6r00.js +166 -0
  152. package/dist/src/view/client/assets/cynefinDiagram-5FMLGOSQ-D7WDoy0K.js +62 -0
  153. package/dist/src/view/client/assets/cytoscape.esm-DzSz-X2X.js +321 -0
  154. package/dist/src/view/client/assets/dagre-GXQ25YYZ-yc2GTi5h.js +4 -0
  155. package/dist/src/view/client/assets/defaultLocale-DX6XiGOO.js +1 -0
  156. package/dist/src/view/client/assets/diagram-S7CK7UJ4-CEP0FGL8.js +30 -0
  157. package/dist/src/view/client/assets/diagram-UQ7AKVKN-BZIEojBf.js +41 -0
  158. package/dist/src/view/client/assets/diagram-VSXAHHWV-BSB6COmM.js +3 -0
  159. package/dist/src/view/client/assets/diagram-VX7I27RA-DqfR3psV.js +24 -0
  160. package/dist/src/view/client/assets/diagram-Z3DM3KII-B79t0s5P.js +24 -0
  161. package/dist/src/view/client/assets/ebnfDiagram-PWID7BFC-CqbCQhE1.js +1 -0
  162. package/dist/src/view/client/assets/erDiagram-RLTQ6QDP-BVfoYIhJ.js +99 -0
  163. package/dist/src/view/client/assets/flowDiagram-HODETNUW-Dfyjm6ib.js +168 -0
  164. package/dist/src/view/client/assets/ganttDiagram-EL5Y4UJY-Da9ta_k3.js +292 -0
  165. package/dist/src/view/client/assets/geist-cyrillic-ext-wght-normal-DjL33-gN.woff2 +0 -0
  166. package/dist/src/view/client/assets/geist-cyrillic-wght-normal-BEAKL7Jp.woff2 +0 -0
  167. package/dist/src/view/client/assets/geist-latin-ext-wght-normal-DC-KSUi6.woff2 +0 -0
  168. package/dist/src/view/client/assets/geist-latin-wght-normal-BgDaEnEv.woff2 +0 -0
  169. package/dist/src/view/client/assets/geist-mono-cyrillic-ext-wght-normal-X_5orZeX.woff2 +0 -0
  170. package/dist/src/view/client/assets/geist-mono-cyrillic-wght-normal-DiZS0aHC.woff2 +0 -0
  171. package/dist/src/view/client/assets/geist-mono-latin-ext-wght-normal-Bwz-egvJ.woff2 +0 -0
  172. package/dist/src/view/client/assets/geist-mono-latin-wght-normal-XN7g48iV.woff2 +0 -0
  173. package/dist/src/view/client/assets/geist-mono-symbols2-wght-normal-CO5SzqOn.woff2 +0 -0
  174. package/dist/src/view/client/assets/geist-mono-vietnamese-wght-normal-DadHysG0.woff2 +0 -0
  175. package/dist/src/view/client/assets/geist-vietnamese-wght-normal-6IgcOCM7.woff2 +0 -0
  176. package/dist/src/view/client/assets/gitGraphDiagram-WWUBYQGX-BDqlQ6LG.js +106 -0
  177. package/dist/src/view/client/assets/index-BnENo9bV.js +1 -0
  178. package/dist/src/view/client/assets/index-DG0Ez15D.css +1 -0
  179. package/dist/src/view/client/assets/index-heNSjszK.js +13 -0
  180. package/dist/src/view/client/assets/infoDiagram-27XIBGKW-CozIUYm1.js +2 -0
  181. package/dist/src/view/client/assets/init-Gi6I4Gst.js +1 -0
  182. package/dist/src/view/client/assets/ishikawaDiagram-5VMMS53U-tkBLr-Tn.js +70 -0
  183. package/dist/src/view/client/assets/journeyDiagram-3NMN7TZE-Dcd_Ofwc.js +139 -0
  184. package/dist/src/view/client/assets/kanban-definition-UXKFOSKX-CQvZmdAf.js +89 -0
  185. package/dist/src/view/client/assets/katex-HP8lGamR.js +257 -0
  186. package/dist/src/view/client/assets/layout-BxuGL0Ip.js +1 -0
  187. package/dist/src/view/client/assets/linear-D8tR6G5K.js +1 -0
  188. package/dist/src/view/client/assets/logo-RR_KBOAT.svg +149 -0
  189. package/dist/src/view/client/assets/maplibre-gl-CDX6Zuow.js +800 -0
  190. package/dist/src/view/client/assets/mermaid.core-BlHZooLK.js +310 -0
  191. package/dist/src/view/client/assets/mindmap-definition-YA3MSWOX-BqvVz5lC.js +96 -0
  192. package/dist/src/view/client/assets/ordinal-Cboi1Yqb.js +1 -0
  193. package/dist/src/view/client/assets/pegDiagram-XKGWAZYB-BkbOOTxX.js +1 -0
  194. package/dist/src/view/client/assets/pieDiagram-E7YTZNPT-BToTpG0m.js +39 -0
  195. package/dist/src/view/client/assets/quadrantDiagram-AXDQQJYC-CerD2TfT.js +7 -0
  196. package/dist/src/view/client/assets/railroadDiagram-O6MQD6OU-B2oElPYD.js +1 -0
  197. package/dist/src/view/client/assets/requirementDiagram-BXWQKSXE-BCL8RGFd.js +84 -0
  198. package/dist/src/view/client/assets/sankeyDiagram-P5KCCOFB-BqnkNRPm.js +40 -0
  199. package/dist/src/view/client/assets/sequenceDiagram-WJ2MYXX4-DKSKYknp.js +162 -0
  200. package/dist/src/view/client/assets/sizeCapture-INFHLROL-D8reQ7IM.js +1 -0
  201. package/dist/src/view/client/assets/stateDiagram-D77RDMKH-B-Eme-BN.js +1 -0
  202. package/dist/src/view/client/assets/stateDiagram-v2-MP3YSRHH-yXL-Y-Ym.js +1 -0
  203. package/dist/src/view/client/assets/swimlanes-42K2YHIH-lK0158X4.js +1 -0
  204. package/dist/src/view/client/assets/swimlanesDiagram-VR7AAH4N-CGn5WOGw.js +8 -0
  205. package/dist/src/view/client/assets/three.module-PDSP0dbZ.js +4108 -0
  206. package/dist/src/view/client/assets/timeline-definition-24CTP7MA-imh-edhJ.js +120 -0
  207. package/dist/src/view/client/assets/vennDiagram-4TSXK5OY-Ixwhcd6r.js +34 -0
  208. package/dist/src/view/client/assets/wardleyDiagram-VM6X3IG4-Cvr_zzKI.js +78 -0
  209. package/dist/src/view/client/assets/xychartDiagram-S5SC5T6Z-BvcmHKlQ.js +7 -0
  210. package/dist/src/view/client/index.html +2 -2
  211. package/dist/src/view/client-shell.d.ts +2 -0
  212. package/dist/src/view/client-shell.js +5 -0
  213. package/dist/src/view/diagnostics.d.ts +3 -2
  214. package/dist/src/view/diagnostics.js +49 -58
  215. package/dist/src/view/document-edit.d.ts +8 -0
  216. package/dist/src/view/document-edit.js +25 -0
  217. package/dist/src/view/document-route.d.ts +14 -0
  218. package/dist/src/view/document-route.js +126 -0
  219. package/dist/src/view/document-tree.d.ts +18 -0
  220. package/dist/src/view/document-tree.js +139 -0
  221. package/dist/src/view/external-document-tree.d.ts +3 -0
  222. package/dist/src/view/external-document-tree.js +674 -0
  223. package/dist/src/view/git-diff.js +205 -1
  224. package/dist/src/view/git.js +1 -1
  225. package/dist/src/view/graph.d.ts +7 -0
  226. package/dist/src/view/graph.js +267 -0
  227. package/dist/src/view/highlight.d.ts +10 -2
  228. package/dist/src/view/highlight.js +50648 -3166
  229. package/dist/src/view/markdown.d.ts +8 -3
  230. package/dist/src/view/markdown.js +311 -41
  231. package/dist/src/view/preindexed-search.d.ts +15 -0
  232. package/dist/src/view/preindexed-search.js +25 -0
  233. package/dist/src/view/protocol.d.ts +95 -6
  234. package/dist/src/view/protocol.js +1 -1
  235. package/dist/src/view/publication.d.ts +2 -0
  236. package/dist/src/view/publication.js +78 -0
  237. package/dist/src/view/references.d.ts +13 -26
  238. package/dist/src/view/references.js +150 -119
  239. package/dist/src/view/repository.d.ts +18 -5
  240. package/dist/src/view/repository.js +269 -27
  241. package/dist/src/view/request-security.d.ts +5 -0
  242. package/dist/src/view/request-security.js +46 -0
  243. package/dist/src/view/search-result.d.ts +4 -0
  244. package/dist/src/view/search-result.js +25 -0
  245. package/dist/src/view/search.d.ts +7 -2
  246. package/dist/src/view/search.js +23 -33
  247. package/dist/src/view/server-build.d.ts +21 -0
  248. package/dist/src/view/server-build.js +145 -0
  249. package/dist/src/view/server-deployment.d.ts +31 -0
  250. package/dist/src/view/server-deployment.js +94 -0
  251. package/dist/src/view/server-index-worker.d.ts +6 -0
  252. package/dist/src/view/server-index-worker.js +14 -0
  253. package/dist/src/view/server.d.ts +14 -2
  254. package/dist/src/view/server.js +254 -51
  255. package/dist/src/view/source-target.d.ts +10 -0
  256. package/dist/src/view/source-target.js +43 -0
  257. package/dist/src/view/static-build.d.ts +32 -0
  258. package/dist/src/view/static-build.js +741 -0
  259. package/dist/src/view/static-protocol.d.ts +47 -0
  260. package/dist/src/view/static-protocol.js +15 -0
  261. package/dist/src/view/store.d.ts +26 -3
  262. package/dist/src/view/store.js +325 -44
  263. package/dist/src/view/table-of-contents.d.ts +9 -0
  264. package/dist/src/view/table-of-contents.js +83 -0
  265. package/dist/src/view/vercel-build.d.ts +24 -0
  266. package/dist/src/view/vercel-build.js +140 -0
  267. package/dist/src/view/vercel-server-build.d.ts +10 -0
  268. package/dist/src/view/vercel-server-build.js +61 -0
  269. package/dist/vendor/lat.md-server/cli.d.ts +2 -0
  270. package/dist/vendor/lat.md-server/cli.js +12 -0
  271. package/dist/vendor/lat.md-server/index.d.ts +38 -0
  272. package/dist/vendor/lat.md-server/index.js +128 -0
  273. package/package.json +72 -25
  274. package/plugins/lat-md/README.md +61 -0
  275. package/plugins/lat-md/hooks.json +38 -0
  276. package/plugins/lat-md/plugin.json +9 -0
  277. package/plugins/lat-md/rules/AGENTS.md +118 -0
  278. package/plugins/lat-md/skills/lat-md/SKILL.md +178 -0
  279. package/plugins/lat-md/skills/lat-md-conventions/SKILL.md +182 -0
  280. package/templates/AGENTS.md +19 -20
  281. package/templates/cursor-rules.md +14 -7
  282. package/templates/fork/conventions.md +173 -0
  283. package/templates/opencode-plugin.ts +9 -9
  284. package/templates/pi-extension.ts +11 -11
  285. package/templates/skill/SKILL.md +28 -17
  286. package/dist/src/cli/check-frontmatter.d.ts +0 -12
  287. package/dist/src/cli/check-frontmatter.js +0 -44
  288. package/dist/src/cli/check-mode.d.ts +0 -6
  289. package/dist/src/cli/check-mode.js +0 -303
  290. package/dist/src/cli/check-status.d.ts +0 -74
  291. package/dist/src/cli/check-status.js +0 -217
  292. package/dist/src/cli/check.d.ts +0 -45
  293. package/dist/src/cli/check.js +0 -777
  294. package/dist/src/cli/context.d.ts +0 -11
  295. package/dist/src/cli/context.js +0 -58
  296. package/dist/src/cli/expand.d.ts +0 -8
  297. package/dist/src/cli/expand.js +0 -94
  298. package/dist/src/cli/gen-index.d.ts +0 -45
  299. package/dist/src/cli/gen-index.js +0 -235
  300. package/dist/src/cli/link-scheme.d.ts +0 -54
  301. package/dist/src/cli/link-scheme.js +0 -101
  302. package/dist/src/cli/locate.d.ts +0 -2
  303. package/dist/src/cli/locate.js +0 -17
  304. package/dist/src/cli/refs.d.ts +0 -22
  305. package/dist/src/cli/refs.js +0 -229
  306. package/dist/src/cli/section.d.ts +0 -43
  307. package/dist/src/cli/section.js +0 -252
  308. package/dist/src/cli/select-menu.d.ts +0 -13
  309. package/dist/src/cli/select-menu.js +0 -100
  310. package/dist/src/code-refs.d.ts +0 -17
  311. package/dist/src/code-refs.js +0 -277
  312. package/dist/src/config.d.ts +0 -29
  313. package/dist/src/config.js +0 -83
  314. package/dist/src/context.d.ts +0 -23
  315. package/dist/src/context.js +0 -11
  316. package/dist/src/extensions/wiki-link/from-markdown.d.ts +0 -5
  317. package/dist/src/extensions/wiki-link/from-markdown.js +0 -34
  318. package/dist/src/extensions/wiki-link/index.d.ts +0 -4
  319. package/dist/src/extensions/wiki-link/index.js +0 -3
  320. package/dist/src/extensions/wiki-link/syntax.d.ts +0 -14
  321. package/dist/src/extensions/wiki-link/syntax.js +0 -121
  322. package/dist/src/extensions/wiki-link/to-markdown.d.ts +0 -5
  323. package/dist/src/extensions/wiki-link/to-markdown.js +0 -28
  324. package/dist/src/extensions/wiki-link/types.d.ts +0 -34
  325. package/dist/src/format.d.ts +0 -8
  326. package/dist/src/format.js +0 -43
  327. package/dist/src/init-version.d.ts +0 -10
  328. package/dist/src/init-version.js +0 -49
  329. package/dist/src/lattice.d.ts +0 -108
  330. package/dist/src/lattice.js +0 -816
  331. package/dist/src/parser.d.ts +0 -3
  332. package/dist/src/parser.js +0 -18
  333. package/dist/src/source-parser.d.ts +0 -27
  334. package/dist/src/source-parser.js +0 -916
  335. package/dist/src/untrusted.d.ts +0 -24
  336. package/dist/src/untrusted.js +0 -97
  337. package/dist/src/view/client/assets/index-B0n0u03y.css +0 -1
  338. package/dist/src/view/client/assets/index-xm2_px4q.js +0 -23
  339. package/dist/src/walk.d.ts +0 -18
  340. package/dist/src/walk.js +0 -27
  341. /package/dist/src/{extensions/wiki-link/types.js → fork/upstream-drift-cli.d.ts} +0 -0
@@ -1,17 +1,30 @@
1
+ import { repositoryFilePath } from '@plebeiantech/lat.md-core/repository-path';
2
+ import { randomUUID } from 'node:crypto';
1
3
  import { watch as watchFiles } from 'node:fs';
2
- import { readFile, realpath } from 'node:fs/promises';
4
+ import { readFile, realpath, rename, rm, stat, writeFile, } from 'node:fs/promises';
3
5
  import { basename, extname, isAbsolute, relative, resolve, sep, } from 'node:path';
4
- import { LAT_REF_RE, scanCodeRefs } from '../code-refs.js';
5
- import { listLatticeFiles, parseFrontmatter, } from '../lattice.js';
6
- import { SOURCE_EXTENSIONS } from '../source-parser.js';
7
- import { toPosix } from '../walk.js';
6
+ import { createCodeReferenceDiscovery, LAT_REF_RE, } from '@plebeiantech/lat.md-core/code-refs';
7
+ import { createExternalResolver, } from '@plebeiantech/lat.md-core/external-sources';
8
+ import { listLatticeFiles } from '@plebeiantech/lat.md-core/project-discovery';
9
+ import { analyzeMarkdownPath } from '@plebeiantech/lat.md-core/markdown-analysis-cache';
10
+ import { isSourceFileExtension } from '@plebeiantech/lat.md-core/source-formats';
11
+ import { toPosix } from '@plebeiantech/lat.md-core/path';
8
12
  import { renderMarkdown } from './markdown.js';
9
13
  import { buildViewDiagnostics } from './diagnostics.js';
14
+ import { applyDocumentEdit, ViewDocumentConflictError, } from './document-edit.js';
10
15
  import { buildGitDiffTree } from './git-diff.js';
16
+ import { buildViewGraph } from './graph.js';
17
+ import { buildViewTableOfContents } from './table-of-contents.js';
11
18
  import { emptyViewGitSnapshot, findViewGitRepository, readViewGitSnapshot, sameViewGitSnapshot, } from './git.js';
12
- import { createMarkdownWikiLinkResolver, getViewSource, ViewDocumentNotFoundError, } from './repository.js';
13
- import { buildViewReferenceIndex, parseViewMarkdownFile, renderSectionBackReferences, } from './references.js';
19
+ import { DEFAULT_VIEW_LOGO_TEXT } from './protocol.js';
20
+ import { createMarkdownWikiLinkResolver, getViewExternal, getViewSource, ViewDocumentNotFoundError, ViewSourceNotFoundError, } from './repository.js';
21
+ import { buildViewReferenceIndex, renderSectionBackReferences, } from './references.js';
22
+ import { rewriteLocalFileLink } from './source-target.js';
14
23
  const DEFAULT_DEBOUNCE_MS = 75;
24
+ const DEFAULT_GIT_POLL_MS = 2_000;
25
+ const EXTERNAL_REFRESH_PATH = '@lat-external-refresh';
26
+ const DOCUMENT_EDIT_WRITE_ATTEMPTS = 3;
27
+ const DOCUMENT_EDIT_TEMP_PREFIX = '.lat-edit-';
15
28
  function isInside(root, candidate) {
16
29
  const rel = relative(root, candidate);
17
30
  return (rel === '' ||
@@ -21,8 +34,16 @@ function projectPath(projectRoot, path) {
21
34
  const normalized = isAbsolute(path) ? relative(projectRoot, path) : path;
22
35
  return toPosix(normalized).replace(/^\.\//, '');
23
36
  }
37
+ function isInternalLatCachePath(path, latPath) {
38
+ const cachePath = latPath ? `${latPath}/.cache` : '.cache';
39
+ return path === cachePath || path.startsWith(`${cachePath}/`);
40
+ }
41
+ function excludedCodePath(projectRoot, path, excludedPaths) {
42
+ const absolutePath = resolve(projectRoot, path);
43
+ return excludedPaths.some((root) => isInside(resolve(root), absolutePath));
44
+ }
24
45
  function sourcePath(path) {
25
- return SOURCE_EXTENSIONS.has(extname(path).toLowerCase());
46
+ return isSourceFileExtension(extname(path).toLowerCase());
26
47
  }
27
48
  function obviouslyIgnoredCodePath(path, latPath) {
28
49
  const parts = path.split('/');
@@ -55,7 +76,10 @@ async function loadCodeReferenceFiles(projectRoot, refs) {
55
76
  const files = new Map();
56
77
  await Promise.all([...refsByFile].map(async ([path, fileRefs]) => {
57
78
  try {
58
- const content = await readFile(resolve(projectRoot, path), 'utf8');
79
+ const safePath = await repositoryFilePath(projectRoot, path);
80
+ if (!safePath)
81
+ return;
82
+ const content = await readFile(safePath, 'utf8');
59
83
  files.set(path, { path, lines: content.split('\n'), refs: fileRefs });
60
84
  }
61
85
  catch {
@@ -64,22 +88,61 @@ async function loadCodeReferenceFiles(projectRoot, refs) {
64
88
  }));
65
89
  return files;
66
90
  }
67
- async function scanCodeState(projectRoot) {
68
- const scan = await scanCodeRefs(projectRoot);
69
- const scope = new Set(scan.files.map((path) => projectPath(projectRoot, path)));
91
+ async function scanCodeState(projectRoot, excludedPaths = [], publishable) {
92
+ const discovery = createCodeReferenceDiscovery(projectRoot);
93
+ const [scan, sourceFiles] = await Promise.all([
94
+ discovery.scan(),
95
+ discovery.listSourceFiles(),
96
+ ]);
97
+ const allowed = (path) => !excludedCodePath(projectRoot, path, excludedPaths);
98
+ const candidates = sourceFiles.filter(allowed);
99
+ const decisions = await Promise.all(candidates.map((path) => publishable?.(projectPath(projectRoot, path)) ?? true));
100
+ const files = candidates.filter((_, index) => decisions[index]);
101
+ const scope = new Set(files.map((path) => projectPath(projectRoot, path)));
102
+ const refs = scan.refs.filter((ref) => allowed(ref.file) && scope.has(ref.file));
70
103
  return {
71
- files: await loadCodeReferenceFiles(projectRoot, scan.refs),
104
+ files: await loadCodeReferenceFiles(projectRoot, refs),
72
105
  scope,
73
106
  };
74
107
  }
75
- function viewIndex(latDir, paths, diagnostics, git) {
76
- const files = [...paths].sort();
108
+ function viewIndex(latDir, markdownFiles, diagnostics, git, references, external) {
109
+ const files = [...markdownFiles.keys()].sort();
110
+ const externalFiles = new Map();
111
+ for (const target of references.externalByTarget.keys()) {
112
+ try {
113
+ const parsed = external.parse(target);
114
+ if (!parsed)
115
+ continue;
116
+ const hash = parsed.identity.indexOf('#');
117
+ const baseTarget = hash === -1 ? parsed.identity : parsed.identity.slice(0, hash);
118
+ externalFiles.set(baseTarget, {
119
+ handle: parsed.handle,
120
+ path: parsed.resolvedPath,
121
+ target: baseTarget,
122
+ });
123
+ }
124
+ catch {
125
+ // Invalid external targets remain diagnostics, not sidebar entries.
126
+ }
127
+ }
77
128
  const directoryName = basename(latDir);
78
129
  const indexName = directoryName.endsWith('.md')
79
130
  ? directoryName
80
131
  : `${directoryName}.md`;
132
+ const directoryOrder = Object.fromEntries([...markdownFiles].flatMap(([path, file]) => {
133
+ const separator = path.lastIndexOf('/');
134
+ const directory = separator === -1 ? '' : path.slice(0, separator);
135
+ const name = directory ? basename(directory) : directoryName;
136
+ const filename = name.endsWith('.md') ? name : `${name}.md`;
137
+ if (path.slice(separator + 1) !== filename)
138
+ return [];
139
+ return [[directory, file.indexEntries]];
140
+ }));
81
141
  return {
82
142
  files,
143
+ directoryOrder,
144
+ externalFiles: [...externalFiles.values()].sort((left, right) => left.handle.localeCompare(right.handle) ||
145
+ left.path.localeCompare(right.path)),
83
146
  entry: files.includes(indexName) ? indexName : (files[0] ?? ''),
84
147
  errorCounts: Object.fromEntries([...diagnostics]
85
148
  .filter(([, errors]) => errors.length > 0)
@@ -89,21 +152,37 @@ function viewIndex(latDir, paths, diagnostics, git) {
89
152
  files: Object.fromEntries([...git.files].map(([path, file]) => [path, file.status])),
90
153
  }
91
154
  : null,
155
+ logoText: DEFAULT_VIEW_LOGO_TEXT,
92
156
  };
93
157
  }
94
- async function buildSnapshot(latDir, projectRoot, markdownFiles, codeFiles, git, generation, markdownGeneration) {
158
+ async function buildSnapshot(latDir, projectRoot, markdownFiles, codeFiles, git, generation, markdownGeneration, options) {
95
159
  const files = new Map([...markdownFiles].sort(([left], [right]) => left.localeCompare(right)));
96
160
  const allSections = [...files.values()].flatMap((file) => file.sections);
97
- const diagnostics = await buildViewDiagnostics(files.values(), codeFiles.values(), allSections, projectRoot);
161
+ const external = await createExternalResolver(latDir, projectRoot, {
162
+ ignoreLocal: options.externalIgnoreLocal,
163
+ ca: options.externalCa,
164
+ });
165
+ await external.reconcile();
166
+ const diagnostics = await buildViewDiagnostics(files.values(), codeFiles.values(), allSections, projectRoot, external, latDir);
167
+ const references = buildViewReferenceIndex(files.values(), codeFiles.values(), allSections, (target) => {
168
+ try {
169
+ return external.parse(target)?.identity ?? null;
170
+ }
171
+ catch {
172
+ return target;
173
+ }
174
+ });
98
175
  return {
99
176
  generation,
100
177
  markdownGeneration,
101
178
  files,
102
179
  allSections,
103
- references: buildViewReferenceIndex(files.values(), codeFiles.values(), allSections),
180
+ references,
181
+ graph: buildViewGraph(files.values(), codeFiles.values(), allSections, diagnostics, git, generation, references, external),
104
182
  diagnostics,
105
183
  git,
106
- index: viewIndex(latDir, [...files.keys()], diagnostics, git),
184
+ index: viewIndex(latDir, files, diagnostics, git, references, external),
185
+ external,
107
186
  };
108
187
  }
109
188
  /** Own the immutable, incrementally refreshed project snapshot for `lat ui`. */
@@ -119,9 +198,13 @@ export class ViewStore {
119
198
  ignoredCodePaths = new Set();
120
199
  listeners = new Set();
121
200
  watcher = null;
201
+ externalWatchers = [];
122
202
  pendingPaths = new Set();
123
203
  debounceTimer = null;
204
+ gitPollTimer = null;
205
+ gitPollQueued = false;
124
206
  refreshTail = Promise.resolve();
207
+ editTail = Promise.resolve();
125
208
  closed = false;
126
209
  constructor(latDir, projectRoot, realLatDir, snapshot, codeFiles, codeScope, gitRepository, options) {
127
210
  this.latDir = latDir;
@@ -140,6 +223,7 @@ export class ViewStore {
140
223
  return this.snapshotValue.markdownGeneration;
141
224
  }
142
225
  startWatching() {
226
+ this.startGitPolling();
143
227
  if (this.options.watch === false || this.watcher)
144
228
  return;
145
229
  try {
@@ -151,6 +235,29 @@ export class ViewStore {
151
235
  catch (error) {
152
236
  process.stderr.write(`lat ui watcher: ${error.message}\n`);
153
237
  }
238
+ this.refreshExternalWatchers();
239
+ }
240
+ refreshExternalWatchers() {
241
+ for (const watcher of this.externalWatchers)
242
+ watcher.close();
243
+ this.externalWatchers = [];
244
+ if (this.options.watch === false)
245
+ return;
246
+ const paths = new Set([...this.snapshotValue.external.snapshot.sources.values()]
247
+ .map((source) => source.localPath)
248
+ .filter((path) => Boolean(path)));
249
+ for (const path of paths) {
250
+ try {
251
+ const watcher = watchFiles(path, { recursive: true }, () => this.scheduleRefresh(EXTERNAL_REFRESH_PATH));
252
+ watcher.on('error', (error) => {
253
+ process.stderr.write(`lat ui external watcher: ${error.message}\n`);
254
+ });
255
+ this.externalWatchers.push(watcher);
256
+ }
257
+ catch (error) {
258
+ process.stderr.write(`lat ui external watcher: ${error.message}\n`);
259
+ }
260
+ }
154
261
  }
155
262
  subscribe(listener) {
156
263
  this.listeners.add(listener);
@@ -159,6 +266,18 @@ export class ViewStore {
159
266
  getIndex() {
160
267
  return this.snapshotValue.index;
161
268
  }
269
+ getGraph() {
270
+ return this.snapshotValue.graph;
271
+ }
272
+ async renderSectionOutput(markdown, sectionId) {
273
+ const snapshot = this.snapshotValue;
274
+ const section = snapshot.allSections.find((candidate) => candidate.id.toLowerCase() === sectionId.toLowerCase());
275
+ const requestedPath = section
276
+ ? toPosix(relative(this.latDir, resolve(this.projectRoot, section.filePath)))
277
+ : 'section-output.md';
278
+ const resolver = await createMarkdownWikiLinkResolver(this.latDir, requestedPath, snapshot.allSections, snapshot.references, snapshot.external, this.options.publishable);
279
+ return (await renderMarkdown(markdown, requestedPath, resolver)).tree;
280
+ }
162
281
  async getDocument(requestedPath) {
163
282
  if (!requestedPath ||
164
283
  requestedPath.includes('\\') ||
@@ -171,33 +290,152 @@ export class ViewStore {
171
290
  if (!file) {
172
291
  throw new ViewDocumentNotFoundError('Markdown document not found');
173
292
  }
174
- const resolver = await createMarkdownWikiLinkResolver(this.latDir, requestedPath, snapshot.allSections);
175
- const rendered = await renderMarkdown(file.content, requestedPath, resolver, { errors: [...(snapshot.diagnostics.get(requestedPath) ?? [])] }, file.tree);
293
+ const resolver = await createMarkdownWikiLinkResolver(this.latDir, requestedPath, snapshot.allSections, snapshot.references, snapshot.external, this.options.publishable);
294
+ const rendered = await renderMarkdown(file.content, requestedPath, resolver, {
295
+ errors: [...(snapshot.diagnostics.get(requestedPath) ?? [])],
296
+ rewriteMarkdownLink: (url) => rewriteLocalFileLink(url, requestedPath),
297
+ });
298
+ const errors = [...(snapshot.diagnostics.get(requestedPath) ?? [])];
176
299
  const gitFile = snapshot.git.files.get(requestedPath);
177
- const gitRendered = gitFile
178
- ? await renderMarkdown(file.content, requestedPath, resolver, { errors: [...(snapshot.diagnostics.get(requestedPath) ?? [])] }, buildGitDiffTree(gitFile.baseContent, file.content, file.tree))
300
+ const gitTree = gitFile
301
+ ? buildGitDiffTree(gitFile.baseContent, file.content)
302
+ : null;
303
+ const gitRendered = gitTree
304
+ ? await renderMarkdown(file.content, requestedPath, resolver, {
305
+ errors,
306
+ rewriteMarkdownLink: (url) => rewriteLocalFileLink(url, requestedPath),
307
+ }, gitTree)
179
308
  : null;
180
- const errors = [...(snapshot.diagnostics.get(requestedPath) ?? [])];
181
309
  return {
182
310
  path: requestedPath,
183
311
  ...rendered,
184
- gitHtml: gitRendered?.html ?? null,
312
+ gitTree: gitRendered?.tree ?? null,
313
+ tableOfContents: buildViewTableOfContents(file.sections, file.headingTitles, { errors, gitTree }),
314
+ graphNodeIds: Object.fromEntries(snapshot.graph.nodes
315
+ .filter((node) => node.documentPath === requestedPath && node.kind === 'document')
316
+ .map((node) => {
317
+ const hash = new URL(node.url, 'http://lat.local').hash.slice(1);
318
+ let headingId = hash;
319
+ try {
320
+ headingId = decodeURIComponent(hash);
321
+ }
322
+ catch {
323
+ // Keep malformed fragments as-is; they cannot collide with valid ids.
324
+ }
325
+ return [headingId, node.id];
326
+ })),
185
327
  errors,
186
- backReferences: await renderSectionBackReferences(snapshot.references, file.sections, this.latDir, this.projectRoot, (path) => createMarkdownWikiLinkResolver(this.latDir, path, snapshot.allSections)),
328
+ backReferences: await renderSectionBackReferences(snapshot.references, file.sections, this.latDir, this.projectRoot, (path) => createMarkdownWikiLinkResolver(this.latDir, path, snapshot.allSections, snapshot.references, snapshot.external, this.options.publishable)),
187
329
  frontmatter: {
188
- requireCodeMention: parseFrontmatter(file.content).requireCodeMention === true,
330
+ requireCodeMention: file.frontmatter.requireCodeMention === true,
189
331
  },
190
332
  };
191
333
  }
192
- getSource(requestedPath, requestedSymbol = '', origin, requestedLine = 0) {
334
+ async editableDocumentPath(requestedPath) {
335
+ if (!requestedPath ||
336
+ requestedPath.includes('\\') ||
337
+ isAbsolute(requestedPath) ||
338
+ !requestedPath.toLowerCase().endsWith('.md') ||
339
+ !this.snapshotValue.files.has(requestedPath)) {
340
+ throw new ViewDocumentNotFoundError('Markdown document not found');
341
+ }
342
+ let realFile;
343
+ try {
344
+ realFile = await realpath(resolve(this.latDir, requestedPath));
345
+ }
346
+ catch {
347
+ throw new ViewDocumentNotFoundError('Markdown document not found');
348
+ }
349
+ if (!isInside(this.realLatDir, realFile)) {
350
+ throw new ViewDocumentNotFoundError('Markdown document not found');
351
+ }
352
+ return realFile;
353
+ }
354
+ async getDocumentSource(requestedPath) {
355
+ const path = await this.editableDocumentPath(requestedPath);
356
+ return { path: requestedPath, content: await readFile(path, 'utf8') };
357
+ }
358
+ async getDocumentResource(requestedPath) {
359
+ if (this.options.publishable &&
360
+ !(await this.options.publishable(projectPath(this.projectRoot, resolve(this.latDir, requestedPath)))))
361
+ throw new ViewDocumentNotFoundError(`Resource is excluded from publication: ${requestedPath}`);
362
+ if (!requestedPath ||
363
+ requestedPath.includes('\\') ||
364
+ isAbsolute(requestedPath) ||
365
+ requestedPath.toLowerCase().endsWith('.md')) {
366
+ throw new ViewDocumentNotFoundError('Document resource not found');
367
+ }
368
+ let path;
369
+ try {
370
+ path = await realpath(resolve(this.latDir, requestedPath));
371
+ if (!isInside(this.realLatDir, path) || !(await stat(path)).isFile()) {
372
+ throw new ViewDocumentNotFoundError('Document resource not found');
373
+ }
374
+ return await readFile(path);
375
+ }
376
+ catch (error) {
377
+ if (error instanceof ViewDocumentNotFoundError)
378
+ throw error;
379
+ throw new ViewDocumentNotFoundError('Document resource not found');
380
+ }
381
+ }
382
+ editDocument(requestedPath, baseContent, editedContent) {
383
+ const operation = this.editTail.then(async () => {
384
+ const path = await this.editableDocumentPath(requestedPath);
385
+ for (let attempt = 0; attempt < DOCUMENT_EDIT_WRITE_ATTEMPTS; attempt++) {
386
+ const currentContent = await readFile(path, 'utf8');
387
+ const edit = applyDocumentEdit(baseContent, editedContent, currentContent);
388
+ if (edit.content === currentContent) {
389
+ return { path: requestedPath, ...edit };
390
+ }
391
+ const currentStat = await stat(path);
392
+ const temporaryPath = resolve(this.latDir, `${DOCUMENT_EDIT_TEMP_PREFIX}${process.pid}-${randomUUID()}.tmp`);
393
+ try {
394
+ await writeFile(temporaryPath, edit.content, {
395
+ encoding: 'utf8',
396
+ flag: 'wx',
397
+ mode: currentStat.mode,
398
+ });
399
+ if ((await readFile(path, 'utf8')) !== currentContent)
400
+ continue;
401
+ await rename(temporaryPath, path);
402
+ }
403
+ finally {
404
+ await rm(temporaryPath, { force: true });
405
+ }
406
+ await this.refresh([resolve(this.latDir, requestedPath)]);
407
+ return { path: requestedPath, ...edit };
408
+ }
409
+ throw new ViewDocumentConflictError('Could not save because this file kept changing. Your edits are still in the editor.');
410
+ });
411
+ this.editTail = operation.then(() => undefined, () => undefined);
412
+ return operation;
413
+ }
414
+ async getSource(requestedPath, requestedSymbol = '', origin, requestedLine = 0) {
415
+ if (this.options.publishable &&
416
+ !(await this.options.publishable(requestedPath)))
417
+ throw new ViewSourceNotFoundError(`Source is excluded from publication: ${requestedPath}`);
193
418
  const snapshot = this.snapshotValue;
194
- return getViewSource(this.latDir, this.projectRoot, requestedPath, requestedSymbol, origin, requestedLine, snapshot.allSections, snapshot.references);
419
+ return getViewSource(this.latDir, this.projectRoot, requestedPath, requestedSymbol, origin, requestedLine, snapshot.allSections, snapshot.references, this.options.publishable);
420
+ }
421
+ getExternal(target) {
422
+ const snapshot = this.snapshotValue;
423
+ return getViewExternal(this.latDir, this.projectRoot, target, snapshot.external, snapshot.allSections, snapshot.references, this.options.publishable);
195
424
  }
196
425
  refresh(paths) {
197
426
  if (this.closed)
198
427
  return Promise.resolve();
199
- const normalized = paths.map((path) => path ? projectPath(this.projectRoot, path) : '');
200
- const refresh = this.refreshTail.then(() => this.applyRefresh(normalized));
428
+ const latPath = projectPath(this.projectRoot, this.latDir);
429
+ const normalized = paths
430
+ .map((path) => (path ? projectPath(this.projectRoot, path) : ''))
431
+ .filter((path) => !isInternalLatCachePath(path, latPath));
432
+ if (paths.length > 0 && normalized.length === 0) {
433
+ return Promise.resolve();
434
+ }
435
+ return this.queueRefresh(normalized, false);
436
+ }
437
+ queueRefresh(paths, pollGit) {
438
+ const refresh = this.refreshTail.then(() => this.applyRefresh(paths, pollGit));
201
439
  this.refreshTail = refresh.catch(() => { });
202
440
  return refresh;
203
441
  }
@@ -206,15 +444,35 @@ export class ViewStore {
206
444
  if (this.debounceTimer)
207
445
  clearTimeout(this.debounceTimer);
208
446
  this.debounceTimer = null;
447
+ if (this.gitPollTimer)
448
+ clearInterval(this.gitPollTimer);
449
+ this.gitPollTimer = null;
209
450
  this.watcher?.close();
210
451
  this.watcher = null;
452
+ for (const watcher of this.externalWatchers)
453
+ watcher.close();
454
+ this.externalWatchers = [];
455
+ await this.editTail;
211
456
  await this.refreshTail;
212
457
  this.listeners.clear();
213
458
  }
214
459
  scheduleRefresh(path) {
215
460
  if (this.closed)
216
461
  return;
217
- this.pendingPaths.add(path ? projectPath(this.projectRoot, path) : '');
462
+ if (path !== EXTERNAL_REFRESH_PATH &&
463
+ basename(path).startsWith(DOCUMENT_EDIT_TEMP_PREFIX) &&
464
+ path.endsWith('.tmp')) {
465
+ return;
466
+ }
467
+ const normalizedPath = path === EXTERNAL_REFRESH_PATH
468
+ ? path
469
+ : path
470
+ ? projectPath(this.projectRoot, path)
471
+ : '';
472
+ const latPath = projectPath(this.projectRoot, this.latDir);
473
+ if (isInternalLatCachePath(normalizedPath, latPath))
474
+ return;
475
+ this.pendingPaths.add(normalizedPath);
218
476
  if (this.debounceTimer)
219
477
  clearTimeout(this.debounceTimer);
220
478
  this.debounceTimer = setTimeout(() => {
@@ -226,6 +484,24 @@ export class ViewStore {
226
484
  });
227
485
  }, this.options.debounceMs ?? DEFAULT_DEBOUNCE_MS);
228
486
  }
487
+ startGitPolling() {
488
+ const interval = this.options.gitPollMs ?? DEFAULT_GIT_POLL_MS;
489
+ if (!this.gitRepository || interval <= 0 || this.gitPollTimer)
490
+ return;
491
+ this.gitPollTimer = setInterval(() => {
492
+ if (this.closed || this.gitPollQueued)
493
+ return;
494
+ this.gitPollQueued = true;
495
+ void this.queueRefresh([], true)
496
+ .catch((error) => {
497
+ process.stderr.write(`lat ui git: ${error.message}\n`);
498
+ })
499
+ .finally(() => {
500
+ this.gitPollQueued = false;
501
+ });
502
+ }, interval);
503
+ this.gitPollTimer.unref();
504
+ }
229
505
  async readMarkdownFile(absolutePath) {
230
506
  let realFile;
231
507
  try {
@@ -236,12 +512,13 @@ export class ViewStore {
236
512
  }
237
513
  if (!isInside(this.realLatDir, realFile))
238
514
  return null;
239
- const content = await readFile(realFile, 'utf8');
240
- return parseViewMarkdownFile(absolutePath, content, this.latDir, this.projectRoot);
515
+ return analyzeMarkdownPath(absolutePath, this.latDir, this.projectRoot);
241
516
  }
242
- async applyRefresh(paths) {
517
+ async applyRefresh(paths, pollGit) {
243
518
  const fullRefresh = paths.includes('');
244
519
  const latPath = projectPath(this.projectRoot, this.latDir);
520
+ const externalChanged = paths.includes(EXTERNAL_REFRESH_PATH) ||
521
+ paths.includes(`${latPath}/config.local.yaml`);
245
522
  const touchesMarkdown = fullRefresh ||
246
523
  paths.some((path) => path === latPath || path.startsWith(`${latPath}/`));
247
524
  let markdownFiles = new Map(this.snapshotValue.files);
@@ -298,7 +575,7 @@ export class ViewStore {
298
575
  }
299
576
  linkedResourceChanged = paths.some((path) => path.startsWith(`${latPath}/`) && !path.toLowerCase().endsWith('.md'));
300
577
  }
301
- if (touchesMarkdown && this.gitRepository) {
578
+ if ((touchesMarkdown || pollGit) && this.gitRepository) {
302
579
  try {
303
580
  const nextGit = await readViewGitSnapshot(this.gitRepository, markdownFiles);
304
581
  gitChanged = !sameViewGitSnapshot(git, nextGit);
@@ -308,12 +585,15 @@ export class ViewStore {
308
585
  process.stderr.write(`lat ui git: ${error.message}\n`);
309
586
  }
310
587
  }
311
- const codePaths = paths.filter((path) => path && sourcePath(path) && !obviouslyIgnoredCodePath(path, latPath));
588
+ const codePaths = paths.filter((path) => path &&
589
+ sourcePath(path) &&
590
+ !obviouslyIgnoredCodePath(path, latPath) &&
591
+ !excludedCodePath(this.projectRoot, path, this.options.codeExcludePaths ?? []));
312
592
  const refreshCodeScope = fullRefresh ||
313
593
  paths.some((path) => path === '.gitignore' || path.endsWith('/.gitignore')) ||
314
594
  codePaths.some((path) => !this.codeScope.has(path) && !this.ignoredCodePaths.has(path));
315
595
  if (refreshCodeScope) {
316
- const nextCode = await scanCodeState(this.projectRoot);
596
+ const nextCode = await scanCodeState(this.projectRoot, this.options.codeExcludePaths, this.options.publishable);
317
597
  codeFiles = nextCode.files;
318
598
  this.codeScope = nextCode.scope;
319
599
  this.ignoredCodePaths.clear();
@@ -352,10 +632,12 @@ export class ViewStore {
352
632
  if (!markdownChanged &&
353
633
  !codeChanged &&
354
634
  !gitChanged &&
355
- !linkedResourceChanged)
635
+ !linkedResourceChanged &&
636
+ !externalChanged)
356
637
  return;
357
638
  this.codeFiles = codeFiles;
358
- this.snapshotValue = await buildSnapshot(this.latDir, this.projectRoot, markdownFiles, codeFiles, git, this.snapshotValue.generation + 1, this.snapshotValue.markdownGeneration + (markdownChanged ? 1 : 0));
639
+ this.snapshotValue = await buildSnapshot(this.latDir, this.projectRoot, markdownFiles, codeFiles, git, this.snapshotValue.generation + 1, this.snapshotValue.markdownGeneration + (markdownChanged ? 1 : 0), this.options);
640
+ this.refreshExternalWatchers();
359
641
  const change = {
360
642
  generation: this.snapshotValue.generation,
361
643
  markdownGeneration: this.snapshotValue.markdownGeneration,
@@ -369,7 +651,7 @@ export async function createViewStore(latDir, projectRoot, options = {}) {
369
651
  const [realLatDir, markdownPaths, codeState, gitRepository] = await Promise.all([
370
652
  realpath(latDir),
371
653
  listLatticeFiles(latDir),
372
- scanCodeState(projectRoot),
654
+ scanCodeState(projectRoot, options.codeExcludePaths, options.publishable),
373
655
  options.git === false
374
656
  ? Promise.resolve(null)
375
657
  : findViewGitRepository(projectRoot, latDir),
@@ -382,8 +664,7 @@ export async function createViewStore(latDir, projectRoot, options = {}) {
382
664
  const realFile = await realpath(absolutePath);
383
665
  if (!isInside(realLatDir, realFile))
384
666
  return;
385
- const content = await readFile(realFile, 'utf8');
386
- const parsed = parseViewMarkdownFile(absolutePath, content, latDir, projectRoot);
667
+ const parsed = await analyzeMarkdownPath(absolutePath, latDir, projectRoot);
387
668
  markdownFiles.set(parsed.path, parsed);
388
669
  }));
389
670
  if (markdownFiles.size === 0) {
@@ -398,7 +679,7 @@ export async function createViewStore(latDir, projectRoot, options = {}) {
398
679
  process.stderr.write(`lat ui git: ${error.message}\n`);
399
680
  }
400
681
  }
401
- const store = new ViewStore(latDir, projectRoot, realLatDir, await buildSnapshot(latDir, projectRoot, markdownFiles, codeState.files, git, 0, 0), codeState.files, codeState.scope, gitRepository, options);
682
+ const store = new ViewStore(latDir, projectRoot, realLatDir, await buildSnapshot(latDir, projectRoot, markdownFiles, codeState.files, git, 0, 0, options), codeState.files, codeState.scope, gitRepository, options);
402
683
  store.startWatching();
403
684
  return store;
404
685
  }
@@ -0,0 +1,9 @@
1
+ import type { Root } from 'mdast';
2
+ import { type Section } from '@plebeiantech/lat.md-core/lattice-model';
3
+ import type { ViewDocumentError, ViewDocumentTocItem } from './protocol.js';
4
+ export type ViewTableOfContentsOptions = {
5
+ errors?: readonly ViewDocumentError[];
6
+ gitTree?: Root | null;
7
+ };
8
+ /** Project rendered headings into the document's local navigation. */
9
+ export declare function buildViewTableOfContents(sections: Section[], titles: readonly string[], options?: ViewTableOfContentsOptions): ViewDocumentTocItem[];
@@ -0,0 +1,83 @@
1
+ import { flattenSections, } from '@plebeiantech/lat.md-core/lattice-model';
2
+ function sectionAtLine(sections, line) {
3
+ let owner = null;
4
+ for (const section of sections) {
5
+ if (line < section.startLine || line > section.endLine)
6
+ continue;
7
+ if (!owner || section.depth >= owner.depth)
8
+ owner = section;
9
+ }
10
+ return owner;
11
+ }
12
+ function classNames(node) {
13
+ const value = node.data?.hProperties?.className;
14
+ if (Array.isArray(value))
15
+ return value.map(String);
16
+ return value ? [String(value)] : [];
17
+ }
18
+ function hasGitChanges(node) {
19
+ if (classNames(node).some((name) => name.startsWith('git-'))) {
20
+ return true;
21
+ }
22
+ if (!('children' in node) || !Array.isArray(node.children))
23
+ return false;
24
+ return node.children.some((child) => hasGitChanges(child));
25
+ }
26
+ function gitChangedSections(sections, tree) {
27
+ const changed = new Set();
28
+ if (!tree)
29
+ return changed;
30
+ const headingStack = [];
31
+ const rootSection = sections[0] ?? null;
32
+ for (const node of tree.children) {
33
+ if (node.type === 'heading') {
34
+ while (headingStack.length > 0 &&
35
+ headingStack[headingStack.length - 1].depth >= node.depth) {
36
+ headingStack.pop();
37
+ }
38
+ const line = node.position?.start.line;
39
+ const section = line
40
+ ? (sections.find((candidate) => candidate.startLine === line && candidate.depth === node.depth) ?? null)
41
+ : null;
42
+ if (section)
43
+ headingStack.push(section);
44
+ if (hasGitChanges(node)) {
45
+ const owner = section ?? headingStack[headingStack.length - 1] ?? rootSection;
46
+ if (owner)
47
+ changed.add(owner.id);
48
+ }
49
+ continue;
50
+ }
51
+ if (!hasGitChanges(node))
52
+ continue;
53
+ const line = node.position?.start.line;
54
+ const owner = (line ? sectionAtLine(sections, line) : null) ??
55
+ headingStack[headingStack.length - 1] ??
56
+ rootSection;
57
+ if (owner)
58
+ changed.add(owner.id);
59
+ }
60
+ return changed;
61
+ }
62
+ /** Project rendered headings into the document's local navigation. */
63
+ export function buildViewTableOfContents(sections, titles, options = {}) {
64
+ const flatSections = flattenSections(sections);
65
+ const errorCounts = new Map();
66
+ for (const error of options.errors ?? []) {
67
+ const owner = sectionAtLine(flatSections, error.line);
68
+ if (owner)
69
+ errorCounts.set(owner.id, (errorCounts.get(owner.id) ?? 0) + 1);
70
+ }
71
+ const gitChanges = gitChangedSections(flatSections, options.gitTree);
72
+ return flatSections.flatMap((section, index) => section.githubSlug
73
+ ? [
74
+ {
75
+ id: section.githubSlug,
76
+ title: titles[index] || section.heading,
77
+ depth: section.depth,
78
+ errorCount: errorCounts.get(section.id) ?? 0,
79
+ hasGitChanges: gitChanges.has(section.id),
80
+ },
81
+ ]
82
+ : []);
83
+ }
@@ -0,0 +1,24 @@
1
+ type FileTraceResult = {
2
+ fileList: Set<string>;
3
+ warnings: Set<Error>;
4
+ };
5
+ export type VercelBuildDependencies = {
6
+ traceFiles: (files: string[], options: {
7
+ base: string;
8
+ conditions: string[];
9
+ exportsOnly: boolean;
10
+ processCwd: string;
11
+ }) => Promise<FileTraceResult>;
12
+ };
13
+ export type VercelBuildOptions = {
14
+ force?: boolean;
15
+ warn?: (message: string) => void;
16
+ };
17
+ export type VercelBuildResult = {
18
+ files: number;
19
+ functionPath: string;
20
+ outputDir: string;
21
+ };
22
+ /** Convert an installed portable Lat UI server into Vercel Build Output API v3. */
23
+ export declare function buildVercelOutput(requestedArtifact: string, requestedOutput?: string, options?: VercelBuildOptions, dependencies?: VercelBuildDependencies): Promise<VercelBuildResult>;
24
+ export {};