@plebeiantech/lat.md 0.12.3-fork.9 → 0.13.4-fork.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (330) hide show
  1. package/README.md +27 -3
  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/fork-instructions.d.ts +1 -0
  7. package/dist/src/cli/fork-instructions.js +8 -32
  8. package/dist/src/cli/fork-scaffold.js +2 -2
  9. package/dist/src/cli/graph.d.ts +1 -1
  10. package/dist/src/cli/hook.d.ts +26 -0
  11. package/dist/src/cli/hook.js +115 -64
  12. package/dist/src/cli/index.js +147 -70
  13. package/dist/src/cli/init-preferences.d.ts +4 -0
  14. package/dist/src/cli/init-preferences.js +36 -0
  15. package/dist/src/cli/init.d.ts +2 -1
  16. package/dist/src/cli/init.js +100 -60
  17. package/dist/src/cli/reindex.d.ts +1 -1
  18. package/dist/src/cli/reindex.js +7 -10
  19. package/dist/src/cli/search.d.ts +14 -4
  20. package/dist/src/cli/search.js +115 -101
  21. package/dist/src/cli/ui-build-server.d.ts +12 -0
  22. package/dist/src/cli/ui-build-server.js +26 -0
  23. package/dist/src/cli/ui-build.d.ts +1 -1
  24. package/dist/src/cli/ui-build.js +1 -1
  25. package/dist/src/cli/ui.d.ts +1 -1
  26. package/dist/src/cli/ui.js +1 -1
  27. package/dist/src/fork/antigravity-hook.d.ts +47 -0
  28. package/dist/src/fork/antigravity-hook.js +424 -0
  29. package/dist/src/fork/antigravity-init.d.ts +17 -0
  30. package/dist/src/fork/antigravity-init.js +124 -0
  31. package/dist/src/fork/upstream-drift.js +1 -1
  32. package/dist/src/fork/upstream-guard.d.ts +1 -1
  33. package/dist/src/fork/upstream-guard.js +8 -7
  34. package/dist/src/graph-export.js +7 -7
  35. package/dist/src/knowledge/index.js +2 -2
  36. package/dist/src/mcp/server.js +34 -18
  37. package/dist/src/search/cache.d.ts +3 -0
  38. package/dist/src/search/cache.js +104 -0
  39. package/dist/src/search/chunks.d.ts +23 -0
  40. package/dist/src/search/chunks.js +200 -0
  41. package/dist/src/search/db.d.ts +28 -16
  42. package/dist/src/search/db.js +100 -40
  43. package/dist/src/search/embedder.d.ts +2 -1
  44. package/dist/src/search/embedder.js +7 -6
  45. package/dist/src/search/index.d.ts +6 -2
  46. package/dist/src/search/index.js +176 -70
  47. package/dist/src/search/lexical.d.ts +6 -0
  48. package/dist/src/search/lexical.js +36 -0
  49. package/dist/src/search/lock.d.ts +5 -0
  50. package/dist/src/search/lock.js +45 -0
  51. package/dist/src/search/query.d.ts +26 -0
  52. package/dist/src/search/query.js +103 -0
  53. package/dist/src/search/search.d.ts +16 -7
  54. package/dist/src/search/search.js +165 -21
  55. package/dist/src/search/types.d.ts +15 -0
  56. package/dist/src/view/client/assets/GraphView-D_xnk0bP.js +456 -0
  57. package/dist/src/view/client/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
  58. package/dist/src/view/client/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
  59. package/dist/src/view/client/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
  60. package/dist/src/view/client/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
  61. package/dist/src/view/client/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
  62. package/dist/src/view/client/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
  63. package/dist/src/view/client/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
  64. package/dist/src/view/client/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
  65. package/dist/src/view/client/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
  66. package/dist/src/view/client/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
  67. package/dist/src/view/client/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
  68. package/dist/src/view/client/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
  69. package/dist/src/view/client/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
  70. package/dist/src/view/client/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
  71. package/dist/src/view/client/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
  72. package/dist/src/view/client/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
  73. package/dist/src/view/client/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
  74. package/dist/src/view/client/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
  75. package/dist/src/view/client/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
  76. package/dist/src/view/client/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
  77. package/dist/src/view/client/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
  78. package/dist/src/view/client/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
  79. package/dist/src/view/client/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
  80. package/dist/src/view/client/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
  81. package/dist/src/view/client/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
  82. package/dist/src/view/client/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
  83. package/dist/src/view/client/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
  84. package/dist/src/view/client/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
  85. package/dist/src/view/client/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
  86. package/dist/src/view/client/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
  87. package/dist/src/view/client/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
  88. package/dist/src/view/client/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
  89. package/dist/src/view/client/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
  90. package/dist/src/view/client/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
  91. package/dist/src/view/client/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
  92. package/dist/src/view/client/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
  93. package/dist/src/view/client/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
  94. package/dist/src/view/client/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
  95. package/dist/src/view/client/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
  96. package/dist/src/view/client/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
  97. package/dist/src/view/client/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
  98. package/dist/src/view/client/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
  99. package/dist/src/view/client/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
  100. package/dist/src/view/client/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
  101. package/dist/src/view/client/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
  102. package/dist/src/view/client/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
  103. package/dist/src/view/client/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
  104. package/dist/src/view/client/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
  105. package/dist/src/view/client/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
  106. package/dist/src/view/client/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
  107. package/dist/src/view/client/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
  108. package/dist/src/view/client/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
  109. package/dist/src/view/client/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
  110. package/dist/src/view/client/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
  111. package/dist/src/view/client/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
  112. package/dist/src/view/client/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
  113. package/dist/src/view/client/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
  114. package/dist/src/view/client/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
  115. package/dist/src/view/client/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
  116. package/dist/src/view/client/assets/MarkdownEditor-bjqt_FoF.js +28 -0
  117. package/dist/src/view/client/assets/OrbitControls-DwcpQNja.js +1 -0
  118. package/dist/src/view/client/assets/STLLoader-CLWTKt5i.js +1 -0
  119. package/dist/src/view/client/assets/_commonjsHelpers-CqkleIqs.js +1 -0
  120. package/dist/src/view/client/assets/abnfDiagram-VCTEODGH-kWGvtRnL.js +1 -0
  121. package/dist/src/view/client/assets/arc-BPAFd7cP.js +1 -0
  122. package/dist/src/view/client/assets/architectureDiagram-5GKGNRK7-CsY39oIR.js +36 -0
  123. package/dist/src/view/client/assets/blockDiagram-I7D4REHJ-DHGBG7BJ.js +129 -0
  124. package/dist/src/view/client/assets/c4Diagram-7LVT6UL2-vywK4eb7.js +38 -0
  125. package/dist/src/view/client/assets/channel-CX71L_qV.js +1 -0
  126. package/dist/src/view/client/assets/chunk-2Q5K7J3B-Do3Hz_ci.js +1 -0
  127. package/dist/src/view/client/assets/chunk-5VM5RSS4-B5R1lSeY.js +15 -0
  128. package/dist/src/view/client/assets/chunk-F27PBJKO-Dm55FM_W.js +1 -0
  129. package/dist/src/view/client/assets/chunk-IMKFNOWR-ChptrvvM.js +231 -0
  130. package/dist/src/view/client/assets/chunk-JWPE2WC7-BRQBjrKS.js +1 -0
  131. package/dist/src/view/client/assets/chunk-POPQ4Y6H-CainVZIL.js +1 -0
  132. package/dist/src/view/client/assets/chunk-SVP7TREG-DsKsNGmM.js +88 -0
  133. package/dist/src/view/client/assets/chunk-TICWLB2K-BctkMcJc.js +206 -0
  134. package/dist/src/view/client/assets/chunk-XXDRQBXY-BN7SgOUT.js +1 -0
  135. package/dist/src/view/client/assets/classDiagram-ZZMXUADV-B1VyU6zO.js +1 -0
  136. package/dist/src/view/client/assets/classDiagram-v2-VYDZK3BY-B1VyU6zO.js +1 -0
  137. package/dist/src/view/client/assets/cose-bilkent-JH36ORCC-BszzwrMe.js +1 -0
  138. package/dist/src/view/client/assets/cynefin-OW5HDTMX-CdRyAkPs.js +166 -0
  139. package/dist/src/view/client/assets/cynefinDiagram-5FMLGOSQ-BLvKPZ1u.js +62 -0
  140. package/dist/src/view/client/assets/cytoscape.esm-DzSz-X2X.js +321 -0
  141. package/dist/src/view/client/assets/dagre-GXQ25YYZ-V68w_l65.js +4 -0
  142. package/dist/src/view/client/assets/defaultLocale-DX6XiGOO.js +1 -0
  143. package/dist/src/view/client/assets/diagram-S7CK7UJ4-C2i4eEMg.js +30 -0
  144. package/dist/src/view/client/assets/diagram-UQ7AKVKN-BiwWh5jC.js +41 -0
  145. package/dist/src/view/client/assets/diagram-VSXAHHWV-hkKR_vyS.js +3 -0
  146. package/dist/src/view/client/assets/diagram-VX7I27RA-DzRCSMAc.js +24 -0
  147. package/dist/src/view/client/assets/diagram-Z3DM3KII-fhSFPxyK.js +24 -0
  148. package/dist/src/view/client/assets/ebnfDiagram-PWID7BFC-CCEUDKSA.js +1 -0
  149. package/dist/src/view/client/assets/erDiagram-RLTQ6QDP-FJ2IMyTi.js +99 -0
  150. package/dist/src/view/client/assets/flowDiagram-HODETNUW-BvasdLeK.js +168 -0
  151. package/dist/src/view/client/assets/ganttDiagram-EL5Y4UJY-CiwkBZvY.js +292 -0
  152. package/dist/src/view/client/assets/geist-cyrillic-ext-wght-normal-DjL33-gN.woff2 +0 -0
  153. package/dist/src/view/client/assets/geist-cyrillic-wght-normal-BEAKL7Jp.woff2 +0 -0
  154. package/dist/src/view/client/assets/geist-latin-ext-wght-normal-DC-KSUi6.woff2 +0 -0
  155. package/dist/src/view/client/assets/geist-latin-wght-normal-BgDaEnEv.woff2 +0 -0
  156. package/dist/src/view/client/assets/geist-mono-cyrillic-ext-wght-normal-X_5orZeX.woff2 +0 -0
  157. package/dist/src/view/client/assets/geist-mono-cyrillic-wght-normal-DiZS0aHC.woff2 +0 -0
  158. package/dist/src/view/client/assets/geist-mono-latin-ext-wght-normal-Bwz-egvJ.woff2 +0 -0
  159. package/dist/src/view/client/assets/geist-mono-latin-wght-normal-XN7g48iV.woff2 +0 -0
  160. package/dist/src/view/client/assets/geist-mono-symbols2-wght-normal-CO5SzqOn.woff2 +0 -0
  161. package/dist/src/view/client/assets/geist-mono-vietnamese-wght-normal-DadHysG0.woff2 +0 -0
  162. package/dist/src/view/client/assets/geist-vietnamese-wght-normal-6IgcOCM7.woff2 +0 -0
  163. package/dist/src/view/client/assets/gitGraphDiagram-WWUBYQGX-DYlP2_js.js +106 -0
  164. package/dist/src/view/client/assets/index-BnENo9bV.js +1 -0
  165. package/dist/src/view/client/assets/index-CQ7EOox7.css +1 -0
  166. package/dist/src/view/client/assets/index-CynNDkxt.js +13 -0
  167. package/dist/src/view/client/assets/infoDiagram-27XIBGKW-DRPB2c48.js +2 -0
  168. package/dist/src/view/client/assets/init-Gi6I4Gst.js +1 -0
  169. package/dist/src/view/client/assets/ishikawaDiagram-5VMMS53U-8VV429Cv.js +70 -0
  170. package/dist/src/view/client/assets/journeyDiagram-3NMN7TZE-Dzmwnf83.js +139 -0
  171. package/dist/src/view/client/assets/kanban-definition-UXKFOSKX-pYyZZ1i-.js +89 -0
  172. package/dist/src/view/client/assets/katex-HP8lGamR.js +257 -0
  173. package/dist/src/view/client/assets/layout-GF9k6yGo.js +1 -0
  174. package/dist/src/view/client/assets/linear-Yt2sSOYV.js +1 -0
  175. package/dist/src/view/client/assets/logo-RR_KBOAT.svg +149 -0
  176. package/dist/src/view/client/assets/maplibre-gl-CDX6Zuow.js +800 -0
  177. package/dist/src/view/client/assets/mermaid.core-ChWYCHN0.js +310 -0
  178. package/dist/src/view/client/assets/mindmap-definition-YA3MSWOX-Cc4fQvf1.js +96 -0
  179. package/dist/src/view/client/assets/ordinal-Cboi1Yqb.js +1 -0
  180. package/dist/src/view/client/assets/pegDiagram-XKGWAZYB-C0SsB8bZ.js +1 -0
  181. package/dist/src/view/client/assets/pieDiagram-E7YTZNPT-DIJpqERZ.js +39 -0
  182. package/dist/src/view/client/assets/quadrantDiagram-AXDQQJYC--d-gl6j-.js +7 -0
  183. package/dist/src/view/client/assets/railroadDiagram-O6MQD6OU-BQxwTt7z.js +1 -0
  184. package/dist/src/view/client/assets/requirementDiagram-BXWQKSXE-B_oTeD2A.js +84 -0
  185. package/dist/src/view/client/assets/sankeyDiagram-P5KCCOFB-DLukmE8X.js +40 -0
  186. package/dist/src/view/client/assets/sequenceDiagram-WJ2MYXX4-BNjVB2sc.js +162 -0
  187. package/dist/src/view/client/assets/sizeCapture-INFHLROL-BZecQTOw.js +1 -0
  188. package/dist/src/view/client/assets/stateDiagram-D77RDMKH-Bu1urvXC.js +1 -0
  189. package/dist/src/view/client/assets/stateDiagram-v2-MP3YSRHH-5pc_697G.js +1 -0
  190. package/dist/src/view/client/assets/swimlanes-42K2YHIH-bLAlcepB.js +1 -0
  191. package/dist/src/view/client/assets/swimlanesDiagram-VR7AAH4N-BbOpZjpp.js +8 -0
  192. package/dist/src/view/client/assets/three.module-PDSP0dbZ.js +4108 -0
  193. package/dist/src/view/client/assets/timeline-definition-24CTP7MA-tbwCNvcA.js +120 -0
  194. package/dist/src/view/client/assets/vennDiagram-4TSXK5OY-D8U8Fk0N.js +34 -0
  195. package/dist/src/view/client/assets/wardleyDiagram-VM6X3IG4-LHBVIeNb.js +78 -0
  196. package/dist/src/view/client/assets/xychartDiagram-S5SC5T6Z-CN4tfaFV.js +7 -0
  197. package/dist/src/view/client/index.html +2 -2
  198. package/dist/src/view/client-shell.d.ts +2 -0
  199. package/dist/src/view/client-shell.js +5 -0
  200. package/dist/src/view/diagnostics.d.ts +3 -2
  201. package/dist/src/view/diagnostics.js +49 -58
  202. package/dist/src/view/document-edit.d.ts +8 -0
  203. package/dist/src/view/document-edit.js +25 -0
  204. package/dist/src/view/document-route.d.ts +14 -0
  205. package/dist/src/view/document-route.js +137 -0
  206. package/dist/src/view/document-tree.d.ts +18 -0
  207. package/dist/src/view/document-tree.js +139 -0
  208. package/dist/src/view/external-document-tree.d.ts +3 -0
  209. package/dist/src/view/external-document-tree.js +674 -0
  210. package/dist/src/view/git-diff.js +202 -2
  211. package/dist/src/view/git.js +1 -1
  212. package/dist/src/view/graph.d.ts +4 -3
  213. package/dist/src/view/graph.js +100 -9
  214. package/dist/src/view/highlight.d.ts +10 -2
  215. package/dist/src/view/highlight.js +50648 -3166
  216. package/dist/src/view/markdown.d.ts +3 -2
  217. package/dist/src/view/markdown.js +256 -54
  218. package/dist/src/view/preindexed-search.d.ts +15 -0
  219. package/dist/src/view/preindexed-search.js +25 -0
  220. package/dist/src/view/protocol.d.ts +53 -7
  221. package/dist/src/view/publication.d.ts +2 -0
  222. package/dist/src/view/publication.js +78 -0
  223. package/dist/src/view/references.d.ts +11 -26
  224. package/dist/src/view/references.js +121 -112
  225. package/dist/src/view/repository.d.ts +14 -4
  226. package/dist/src/view/repository.js +260 -19
  227. package/dist/src/view/request-security.d.ts +5 -0
  228. package/dist/src/view/request-security.js +46 -0
  229. package/dist/src/view/search-result.d.ts +4 -0
  230. package/dist/src/view/search-result.js +25 -0
  231. package/dist/src/view/search.d.ts +7 -2
  232. package/dist/src/view/search.js +23 -34
  233. package/dist/src/view/server-build.d.ts +21 -0
  234. package/dist/src/view/server-build.js +145 -0
  235. package/dist/src/view/server-deployment.d.ts +31 -0
  236. package/dist/src/view/server-deployment.js +123 -0
  237. package/dist/src/view/server-index-worker.d.ts +6 -0
  238. package/dist/src/view/server-index-worker.js +14 -0
  239. package/dist/src/view/server.d.ts +11 -2
  240. package/dist/src/view/server.js +245 -73
  241. package/dist/src/view/source-target.d.ts +2 -0
  242. package/dist/src/view/source-target.js +49 -8
  243. package/dist/src/view/static-build.d.ts +18 -2
  244. package/dist/src/view/static-build.js +449 -110
  245. package/dist/src/view/static-protocol.d.ts +26 -2
  246. package/dist/src/view/static-protocol.js +5 -0
  247. package/dist/src/view/store.d.ts +20 -3
  248. package/dist/src/view/store.js +304 -48
  249. package/dist/src/view/table-of-contents.d.ts +2 -2
  250. package/dist/src/view/table-of-contents.js +2 -22
  251. package/dist/src/view/vercel-build.d.ts +24 -0
  252. package/dist/src/view/vercel-build.js +152 -0
  253. package/dist/src/view/vercel-server-build.d.ts +10 -0
  254. package/dist/src/view/vercel-server-build.js +61 -0
  255. package/dist/vendor/lat.md-server/cli.d.ts +2 -0
  256. package/dist/vendor/lat.md-server/cli.js +12 -0
  257. package/dist/vendor/lat.md-server/index.d.ts +38 -0
  258. package/dist/vendor/lat.md-server/index.js +128 -0
  259. package/package.json +68 -22
  260. package/plugins/lat-md/README.md +61 -0
  261. package/plugins/lat-md/hooks.json +38 -0
  262. package/plugins/lat-md/plugin.json +9 -0
  263. package/plugins/lat-md/rules/AGENTS.md +344 -0
  264. package/plugins/lat-md/skills/lat-md/SKILL.md +210 -0
  265. package/plugins/lat-md/skills/lat-md-conventions/SKILL.md +226 -0
  266. package/templates/AGENTS.md +26 -7
  267. package/templates/cursor-rules.md +23 -7
  268. package/templates/fork/conventions.md +133 -11
  269. package/templates/opencode-plugin.ts +9 -9
  270. package/templates/pi-extension.ts +11 -11
  271. package/templates/skill/SKILL.md +35 -3
  272. package/dist/src/cli/check-coverage.d.ts +0 -2
  273. package/dist/src/cli/check-coverage.js +0 -71
  274. package/dist/src/cli/check-frontmatter.d.ts +0 -12
  275. package/dist/src/cli/check-frontmatter.js +0 -44
  276. package/dist/src/cli/check-mode.d.ts +0 -21
  277. package/dist/src/cli/check-mode.js +0 -364
  278. package/dist/src/cli/check-status.d.ts +0 -74
  279. package/dist/src/cli/check-status.js +0 -217
  280. package/dist/src/cli/check.d.ts +0 -45
  281. package/dist/src/cli/check.js +0 -781
  282. package/dist/src/cli/context.d.ts +0 -11
  283. package/dist/src/cli/context.js +0 -58
  284. package/dist/src/cli/expand.d.ts +0 -8
  285. package/dist/src/cli/expand.js +0 -94
  286. package/dist/src/cli/gen-index.d.ts +0 -45
  287. package/dist/src/cli/gen-index.js +0 -235
  288. package/dist/src/cli/link-scheme.d.ts +0 -54
  289. package/dist/src/cli/link-scheme.js +0 -101
  290. package/dist/src/cli/locate.d.ts +0 -2
  291. package/dist/src/cli/locate.js +0 -17
  292. package/dist/src/cli/refs.d.ts +0 -22
  293. package/dist/src/cli/refs.js +0 -229
  294. package/dist/src/cli/section.d.ts +0 -43
  295. package/dist/src/cli/section.js +0 -252
  296. package/dist/src/cli/select-menu.d.ts +0 -13
  297. package/dist/src/cli/select-menu.js +0 -100
  298. package/dist/src/code-refs.d.ts +0 -17
  299. package/dist/src/code-refs.js +0 -298
  300. package/dist/src/config.d.ts +0 -29
  301. package/dist/src/config.js +0 -83
  302. package/dist/src/context.d.ts +0 -23
  303. package/dist/src/context.js +0 -11
  304. package/dist/src/extensions/wiki-link/from-markdown.d.ts +0 -5
  305. package/dist/src/extensions/wiki-link/from-markdown.js +0 -34
  306. package/dist/src/extensions/wiki-link/index.d.ts +0 -4
  307. package/dist/src/extensions/wiki-link/index.js +0 -3
  308. package/dist/src/extensions/wiki-link/syntax.d.ts +0 -14
  309. package/dist/src/extensions/wiki-link/syntax.js +0 -121
  310. package/dist/src/extensions/wiki-link/to-markdown.d.ts +0 -5
  311. package/dist/src/extensions/wiki-link/to-markdown.js +0 -28
  312. package/dist/src/extensions/wiki-link/types.d.ts +0 -34
  313. package/dist/src/format.d.ts +0 -8
  314. package/dist/src/format.js +0 -43
  315. package/dist/src/init-version.d.ts +0 -10
  316. package/dist/src/init-version.js +0 -49
  317. package/dist/src/lattice.d.ts +0 -109
  318. package/dist/src/lattice.js +0 -817
  319. package/dist/src/parser.d.ts +0 -3
  320. package/dist/src/parser.js +0 -18
  321. package/dist/src/source-parser.d.ts +0 -27
  322. package/dist/src/source-parser.js +0 -916
  323. package/dist/src/untrusted.d.ts +0 -18
  324. package/dist/src/untrusted.js +0 -93
  325. package/dist/src/view/client/assets/index-C3iaZyYT.css +0 -1
  326. package/dist/src/view/client/assets/index-KWi67IMz.js +0 -334
  327. package/dist/src/view/client/assets/logo-CNF8zs47.svg +0 -182
  328. package/dist/src/walk.d.ts +0 -18
  329. package/dist/src/walk.js +0 -27
  330. /package/dist/src/{extensions/wiki-link → search}/types.js +0 -0
package/README.md CHANGED
@@ -77,9 +77,33 @@ The hooks are also packaged as a plugin, installable straight from this reposito
77
77
 
78
78
  The plugin ships hooks only and finds `lat` on your `PATH`, accepting a build only if its version carries a `-fork` suffix.
79
79
 
80
+ ### As an Antigravity / Gemini CLI plugin
81
+
82
+ The hooks, rules, and skills are packaged as an Antigravity plugin under `plugins/lat-md/`.
83
+
84
+ You can install it directly without cloning the repository:
85
+
86
+ **Global installation (all local projects):**
87
+ ```bash
88
+ mkdir -p ~/.gemini/config/plugins/lat-md && \
89
+ curl -sL https://github.com/PlebeianTech/lat.md/archive/refs/heads/main.tar.gz | \
90
+ tar -xz -C ~/.gemini/config/plugins/lat-md --strip-components=2 lat.md-main/plugins/lat-md
91
+ ```
92
+
93
+ **Workspace installation (single repository):**
94
+ ```bash
95
+ mkdir -p .agents/plugins/lat-md && \
96
+ curl -sL https://github.com/PlebeianTech/lat.md/archive/refs/heads/main.tar.gz | \
97
+ tar -xz -C .agents/plugins/lat-md --strip-components=2 lat.md-main/plugins/lat-md
98
+ ```
99
+
100
+ Alternatively, install `@plebeiantech/lat.md` via npm/mise, run `lat init` in your project, and select **Antigravity / Gemini** from the agent checklist.
101
+
102
+
103
+
80
104
  ## How it works
81
105
 
82
- Run `lat init` to scaffold a `lat.md/` directory, then write markdown files describing your architecture, business logic, test specs — whatever matters. Link between sections using `[[file#Section#Subsection]]` syntax. Link to source code symbols with `[[src/auth.ts#validateToken]]`. Annotate source code with `// @lat: [[section-id]]` (or `# @lat: [[section-id]]` in Python) comments to tie implementation back to concepts.
106
+ Run `lat init` to scaffold a `lat.md/` directory, then write markdown files describing your architecture, business logic, test specs — whatever matters. Link between sections using `[[file#Section#Subsection]]` syntax. Link to source code symbols with `[[src/auth.ts#validateToken]]`. Annotate source code with `// @lat: [[section-id]]` (or `# @lat: [[section-id]]` in Python and PHP) comments to tie implementation back to concepts.
83
107
 
84
108
  ```
85
109
  my-project/
@@ -115,7 +139,7 @@ To use higher-quality hosted embeddings instead, provide an OpenAI (`sk-...`) or
115
139
  1. `LAT_LLM_KEY` env var — direct value
116
140
  2. `LAT_LLM_KEY_FILE` env var — path to a file containing the key
117
141
  3. `LAT_LLM_KEY_HELPER` env var — shell command that prints the key (10s timeout)
118
- 4. Config file — power users can set `llm_key` manually. Run `lat config` to print its location.
142
+ 4. Config file — power users can set `llm_key` manually. Run `lat paths --config` to print its location. Run `lat paths` to see cache and other storage paths with their purposes.
119
143
 
120
144
  Switch backends any time with `lat reindex` (`--local` to force the offline model, `--remote` to use your key).
121
145
 
@@ -123,7 +147,7 @@ Switch backends any time with `lat reindex` (`--local` to force the offline mode
123
147
 
124
148
  Development requires Node.js 22, pnpm, and Rust installed through rustup. The
125
149
  pnpm setup installs the matching WASM target and build tools project-locally.
126
- See the [development process](lat.md/dev-process.md) for complete setup and
150
+ See the [development process](lat.md/knowledge/dev-process.md) for complete setup and
127
151
  contribution guidance.
128
152
 
129
153
  ```bash
@@ -0,0 +1,6 @@
1
+ export interface AgentInvocation {
2
+ command: string;
3
+ args: string[];
4
+ }
5
+ /** Generated tools pass user input as argv, never as shell program text. */
6
+ export declare function agentInvocation(style: 'local' | 'global' | 'npx', local: AgentInvocation, platform?: NodeJS.Platform): AgentInvocation;
@@ -0,0 +1,23 @@
1
+ import { existsSync } from 'node:fs';
2
+ import { delimiter, dirname, join } from 'node:path';
3
+ /** Generated tools pass user input as argv, never as shell program text. */
4
+ export function agentInvocation(style, local, platform = process.platform) {
5
+ if (style === 'local')
6
+ return local;
7
+ // Windows npm command shims require cmd.exe. Use the installed entry point
8
+ // directly instead, retaining the Node launcher and its loader arguments.
9
+ if (style === 'global')
10
+ return platform === 'win32' ? local : { command: 'lat', args: [] };
11
+ if (platform !== 'win32')
12
+ return { command: 'npx', args: ['lat.md@latest'] };
13
+ const directories = [
14
+ dirname(process.execPath),
15
+ ...(process.env.PATH ?? '').split(delimiter),
16
+ ];
17
+ for (const directory of directories) {
18
+ const cli = join(directory, 'node_modules', 'npm', 'bin', 'npx-cli.js');
19
+ if (existsSync(cli))
20
+ return { command: process.execPath, args: [cli, 'lat.md@latest'] };
21
+ }
22
+ throw new Error('Cannot find the npm npx entry point. Choose the local command style or install npm.');
23
+ }
@@ -5,8 +5,9 @@ export interface ChecklistOption {
5
5
  /**
6
6
  * Display an interactive multi-select checklist with arrow-key navigation.
7
7
  * Returns an array of checked values.
8
+ * Known initial values start checked; unknown values are ignored.
8
9
  *
9
10
  * Keys: Up/Down (j/k) to move, Space to toggle, Enter to confirm, Ctrl+C to exit.
10
11
  * Non-TTY fallback: returns [].
11
12
  */
12
- export declare function checklistMenu(options: ChecklistOption[], prompt?: string): Promise<string[]>;
13
+ export declare function checklistMenu(options: ChecklistOption[], prompt?: string, initialValues?: readonly string[]): Promise<string[]>;
@@ -2,18 +2,19 @@ import { styleText } from 'node:util';
2
2
  /**
3
3
  * Display an interactive multi-select checklist with arrow-key navigation.
4
4
  * Returns an array of checked values.
5
+ * Known initial values start checked; unknown values are ignored.
5
6
  *
6
7
  * Keys: Up/Down (j/k) to move, Space to toggle, Enter to confirm, Ctrl+C to exit.
7
8
  * Non-TTY fallback: returns [].
8
9
  */
9
- export async function checklistMenu(options, prompt) {
10
+ export async function checklistMenu(options, prompt, initialValues = []) {
10
11
  if (options.length === 0)
11
12
  return [];
12
13
  if (!process.stdin.isTTY)
13
14
  return [];
14
15
  return new Promise((resolve) => {
15
16
  let cursor = 0;
16
- const checked = new Set();
17
+ const checked = new Set(options.flatMap((option, index) => initialValues.includes(option.value) ? [index] : []));
17
18
  const stdin = process.stdin;
18
19
  const wasRaw = stdin.isRaw;
19
20
  stdin.setRawMode(true);
@@ -1,3 +1,4 @@
1
+ export declare const SKILL_FRONTMATTER = "---\nname: lat-md-conventions\ndescription: >-\n Rules and writing conventions for this project: Di\u00E1taxis mode placement for\n every lat.md/ document, Strunk & White prose style, mandatory @lat: code refs\n starting at the application entrypoint, and test specs wired to their tests.\n Load alongside lat-md whenever creating or editing files under lat.md/.\n---\n\n";
1
2
  export declare function readForkConventions(): string;
2
3
  /**
3
4
  * Replace the fork block in `content`, or append one when absent.
@@ -1,33 +1,9 @@
1
1
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
2
2
  import { join } from 'node:path';
3
3
  import { styleText } from 'node:util';
4
- import { contentHash, readFileHash } from '../init-version.js';
4
+ import { contentHash, readFileHash, } from '@plebeiantech/lat.md-core/init-version';
5
5
  import { findTemplatesDir } from './templates.js';
6
- /**
7
- * The fork's own instruction channel into a consumer project.
8
- *
9
- * Upstream teaches a consumer's agent through `templates/AGENTS.md` and
10
- * `templates/skill/SKILL.md`. Both are upstream files, and both are the ones
11
- * upstream is most likely to rewrite, so every sentence this fork adds to them
12
- * is a merge conflict bought on credit. The fork's Diátaxis block cost 13
13
- * lines in one and 14 in the other before this module existed.
14
- *
15
- * Everything here writes into fork-owned paths instead. The entire upstream
16
- * footprint is one import and one call in `initCmd`.
17
- *
18
- * Two shapes, because the destinations behave differently:
19
- *
20
- * - Always-loaded instruction files (`CLAUDE.md`, `AGENTS.md`,
21
- * `.github/copilot-instructions.md`) already carry upstream's
22
- * `%% lat:begin %%` block, so this appends a *second* block under its own
23
- * `%% lat-fork:begin %%` markers. Upstream's `appendTemplateSection` slices
24
- * between its own markers and leaves anything after them intact, so the two
25
- * blocks do not fight on re-run.
26
- * - Skill directories get a separate `lat-md-conventions/SKILL.md`. Upstream
27
- * writes its `lat-md` skill with a whole-file hash comparison, so appending
28
- * to that file would make every later `lat init` report it as
29
- * user-modified and prompt.
30
- */
6
+ // @lat: [[fork#Fork#The instruction channel]]
31
7
  const FORK_BEGIN = '%% lat-fork:begin %%';
32
8
  const FORK_END = '%% lat-fork:end %%';
33
9
  /**
@@ -40,8 +16,8 @@ function forkHashKey(relPath) {
40
16
  }
41
17
  /** Instruction files that use upstream's marker-append shape. */
42
18
  const BLOCK_TARGETS = [
43
- 'CLAUDE.md',
44
19
  'AGENTS.md',
20
+ 'GEMINI.md',
45
21
  '.github/copilot-instructions.md',
46
22
  ];
47
23
  /**
@@ -56,13 +32,13 @@ const SKILL_ROOTS = [
56
32
  '.codex/skills',
57
33
  ];
58
34
  const SKILL_NAME = 'lat-md-conventions';
59
- const SKILL_FRONTMATTER = `---
35
+ export const SKILL_FRONTMATTER = `---
60
36
  name: ${SKILL_NAME}
61
37
  description: >-
62
- Rules lat check enforces in this project: Diátaxis mode placement for every
63
- lat.md/ document, mandatory @lat: code refs starting at the application
64
- entrypoint, and test specs wired to their tests. Load alongside lat-md
65
- whenever creating or editing files under lat.md/.
38
+ Rules and writing conventions for this project: Diátaxis mode placement for
39
+ every lat.md/ document, Strunk & White prose style, mandatory @lat: code refs
40
+ starting at the application entrypoint, and test specs wired to their tests.
41
+ Load alongside lat-md whenever creating or editing files under lat.md/.
66
42
  ---
67
43
 
68
44
  `;
@@ -2,8 +2,8 @@ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
2
2
  import { basename, dirname, join } from 'node:path';
3
3
  import { styleText } from 'node:util';
4
4
  import { isMap, isScalar, isSeq, parseDocument } from 'yaml';
5
- import { parseFrontmatter } from '../lattice.js';
6
- import { DIATAXIS_MODES, MODE_DIRS, checkMode, indexNameFor, } from './check-mode.js';
5
+ import { parseFrontmatter } from '@plebeiantech/lat.md-core/lattice';
6
+ import { DIATAXIS_MODES, MODE_DIRS, checkMode, indexNameFor, } from '@plebeiantech/lat.md-core/cli/check-mode';
7
7
  /**
8
8
  * Give a freshly created `lat.md/` the Diátaxis shape, and turn the gate on.
9
9
  *
@@ -1,4 +1,4 @@
1
- import type { CmdContext, CmdResult } from '../context.js';
1
+ import type { CmdContext, CmdResult } from '@plebeiantech/lat.md-core/context';
2
2
  export type GraphOptions = {
3
3
  format?: string;
4
4
  at?: string;
@@ -1 +1,27 @@
1
+ /**
2
+ * Measure code vs `lat.md/` churn since HEAD, in lines. Combines tracked
3
+ * changes (`git diff HEAD --numstat`) with untracked files
4
+ * (`git ls-files --others --exclude-standard -z`). Counting untracked files is
5
+ * what makes a freshly scaffolded, never-committed `lat.md/` register as
6
+ * updated — otherwise its edits are invisible to `git diff HEAD` and the sync
7
+ * reminder fires on every turn until `lat.md/` is committed (issue #61).
8
+ * Both scans are scoped and made relative to `projectRoot`, so a Lat project
9
+ * nested in a larger worktree neither misses its own `lat.md/` paths nor counts
10
+ * changes from sibling projects.
11
+ * Outside a Git worktree both scans contribute zero churn by design: Git is
12
+ * optional, so the hook still validates the project but skips the sync ratio.
13
+ */
14
+ export declare function analyzeDiff(projectRoot: string): {
15
+ codeLines: number;
16
+ latMdLines: number;
17
+ };
18
+ export type StopStatus = {
19
+ checkFailed: boolean;
20
+ totalErrors: number;
21
+ needsSync: boolean;
22
+ codeLines: number;
23
+ latMdLines: number;
24
+ };
25
+ export declare function getStopStatus(latDir: string): Promise<StopStatus>;
26
+ export declare function formatStopReason({ checkFailed, totalErrors, needsSync, codeLines, latMdLines, }: StopStatus): string | null;
1
27
  export declare function hookCmd(agent: string, event: string): Promise<void>;
@@ -1,17 +1,22 @@
1
1
  import { execSync } from 'node:child_process';
2
- import { dirname, extname } from 'node:path';
3
- import { findLatticeDir, loadAllSections, findSections, } from '../lattice.js';
4
- import { plainStyler } from '../context.js';
5
- import { expandPrompt } from './expand.js';
2
+ import { lstatSync, readFileSync } from 'node:fs';
3
+ import { dirname, extname, join } from 'node:path';
4
+ import { findLatticeDir } from '@plebeiantech/lat.md-core/project-discovery';
5
+ import { findSections } from '@plebeiantech/lat.md-core/lattice-model';
6
+ import { plainStyler, } from '@plebeiantech/lat.md-core/context';
6
7
  import { runSearch } from './search.js';
7
- import { getSection, formatSectionOutput } from './section.js';
8
- import { checkMd, checkCodeRefs, checkIndex, checkSections } from './check.js';
9
- import { checkMode } from './check-mode.js';
10
- import { SOURCE_EXTENSIONS } from '../source-parser.js';
8
+ import { DEFAULT_SEARCH_LIMIT } from '../search/search.js';
9
+ import { getSection, formatSectionOutput, } from '@plebeiantech/lat.md-core/cli/section';
10
+ import { checkMd, checkCodeRefs, checkIndex, checkSections, } from '@plebeiantech/lat.md-core/cli/check';
11
+ import { CheckRunContext } from '@plebeiantech/lat.md-core/cli/check-context';
12
+ import { isSourceFileExtension } from '@plebeiantech/lat.md-core/source-formats';
13
+ import { commandProjectAnalysis } from '@plebeiantech/lat.md-core/project-analysis';
14
+ import { checkMode } from '@plebeiantech/lat.md-core/cli/check-mode';
11
15
  import { federateTags, taggedDocsForFiles } from '../knowledge/index.js';
12
16
  import { loadSessionMarkers, saveSessionMarkers, } from '../knowledge/session.js';
13
17
  import { computeCommentReminder, } from './comment-reminder.js';
14
18
  import { handlePreToolUse } from './comment-guard.js';
19
+ import { handleAntigravityHook } from '../fork/antigravity-hook.js';
15
20
  function outputPromptSubmit(context) {
16
21
  process.stdout.write(JSON.stringify({
17
22
  hookSpecificOutput: {
@@ -53,9 +58,6 @@ async function readStdin() {
53
58
  }
54
59
  return Buffer.concat(chunks).toString('utf-8');
55
60
  }
56
- function hasWikiLinks(text) {
57
- return /\[\[[^\]]+\]\]/.test(text);
58
- }
59
61
  function makeHookCtx(latDir) {
60
62
  return {
61
63
  latDir,
@@ -64,15 +66,15 @@ function makeHookCtx(latDir) {
64
66
  mode: 'cli',
65
67
  };
66
68
  }
67
- async function searchAndExpand(ctx, userPrompt, preloadedSections) {
69
+ async function searchContextForPrompt(ctx, userPrompt) {
68
70
  let result;
69
71
  try {
70
72
  // Read-only: search an existing index but never build/update it here. A fresh
71
73
  // repo's first prompt must not trigger a full local embed pass — that's what
72
74
  // `lat search` / `lat reindex` are for. Returns no matches until then.
73
- result = await runSearch(ctx.latDir, userPrompt, 5, undefined, {
75
+ result = await runSearch(ctx.latDir, userPrompt, DEFAULT_SEARCH_LIMIT, undefined, {
74
76
  buildIndex: false,
75
- preloadedSections,
77
+ project: await commandProjectAnalysis(ctx),
76
78
  });
77
79
  }
78
80
  catch {
@@ -109,32 +111,16 @@ async function handleUserPromptSubmit() {
109
111
  // If we can't parse stdin, still emit the reminder
110
112
  }
111
113
  const parts = [];
112
- parts.push("Before starting work, run `lat search` with one or more queries describing the user's intent.", 'ALWAYS do this, even when the task seems straightforward — search results may reveal critical design details, protocols, or constraints.', 'Use `lat section` to read the full content of relevant matches.', 'Do not read files, write code, or run commands until you have searched.', '', 'Remember: `lat.md/` must stay in sync with meaningful codebase state. If you change behavior, architecture, tests, or planned work, update the relevant current-state sections and run `lat check` before finishing. Do not use `lat.md/` as a journal/changelog or add notes for insignificant details.');
114
+ parts.push("Before starting work, run `lat search` with one or more queries describing the user's intent.", 'ALWAYS do this, even when the task seems straightforward — search results may reveal critical design details, protocols, or constraints.', 'Use `lat section` to read the full content of relevant matches.', 'Do not read files, write code, or run commands until you have searched.', '', 'Remember: `lat.md/` must stay in sync with meaningful codebase state. If you change implemented behavior, architecture, or tests, update the relevant current-state sections and run `lat check` before finishing. Plans may be drafted in `lat.md/` alongside implementation, with the intent that by commit time they describe what was implemented. Otherwise, keep proposals, hypothetical designs, and future work outside `lat.md/` unless the user explicitly requests them there. Do not use `lat.md/` as a journal/changelog or add notes for insignificant details.');
113
115
  const latDir = findLatticeDir();
114
116
  if (latDir && userPrompt) {
115
117
  const ctx = makeHookCtx(latDir);
116
- // Loaded once and threaded through expansion, search, and federation
117
- // below — each of those otherwise walks and parses the whole tree itself.
118
- const allSections = await loadAllSections(latDir);
119
- // If the user prompt contains [[refs]], resolve them inline
120
- if (hasWikiLinks(userPrompt)) {
121
- try {
122
- const expanded = await expandPrompt(ctx, userPrompt, allSections);
123
- if (expanded) {
124
- parts.push('', 'Expanded user prompt with resolved [[refs]]:', expanded);
125
- }
126
- else {
127
- parts.push('', 'NOTE: The user prompt contains [[refs]] but they could not be resolved. Ask the user to correct them.');
128
- }
129
- }
130
- catch {
131
- parts.push('', 'NOTE: The user prompt contains [[refs]] but resolution failed. Run `lat expand` on the prompt text manually.');
132
- }
133
- }
118
+ // Search and federation share the analysis memoised on `ctx`.
119
+ const { allSections } = await commandProjectAnalysis(ctx);
134
120
  // Search for relevant sections and include their full content
135
121
  let searchFilePaths = [];
136
122
  try {
137
- const searchContext = await searchAndExpand(ctx, userPrompt, allSections);
123
+ const searchContext = await searchContextForPrompt(ctx, userPrompt);
138
124
  searchFilePaths = searchContext.filePaths;
139
125
  if (searchContext.text) {
140
126
  parts.push('', searchContext.text);
@@ -161,7 +147,7 @@ async function handleUserPromptSubmit() {
161
147
  }
162
148
  }
163
149
  }
164
- // Reuses what searchAndExpand already matched. Searching again here
150
+ // Reuses what searchContextForPrompt already matched. Searching again here
165
151
  // would double the cost of every prompt, and an unusable index makes
166
152
  // runSearch throw — which abandoned the [[ref]] paths collected above,
167
153
  // even though resolving those never touches the index at all.
@@ -252,55 +238,116 @@ const DIFF_THRESHOLD = 5;
252
238
  const LATMD_RATIO = 0.05;
253
239
  /** If lat.md/ changes exceed this many lines, skip the ratio check entirely. */
254
240
  const LATMD_UPPER_THRESHOLD = 50;
255
- /** Run `git diff --numstat` and return { codeLines, latMdLines }. */
256
- function analyzeDiff(projectRoot) {
257
- let output;
241
+ function diffFileKind(file) {
242
+ if (file.startsWith('lat.md/'))
243
+ return 'latMd';
244
+ if (isSourceFileExtension(extname(file)))
245
+ return 'code';
246
+ return null;
247
+ }
248
+ /** Count a regular text file's lines as additions, matching Git numstat. */
249
+ function countUntrackedFileLines(projectRoot, file) {
258
250
  try {
259
- output = execSync('git diff HEAD --numstat', {
260
- cwd: projectRoot,
261
- encoding: 'utf-8',
262
- timeout: 2000,
263
- });
251
+ const path = join(projectRoot, file);
252
+ if (!lstatSync(path).isFile())
253
+ return 0;
254
+ const text = readFileSync(path, 'utf-8');
255
+ if (text.length === 0)
256
+ return 0;
257
+ return text.split('\n').length - (text.endsWith('\n') ? 1 : 0);
264
258
  }
265
259
  catch {
266
- return { codeLines: 0, latMdLines: 0 };
260
+ return 0;
267
261
  }
262
+ }
263
+ /**
264
+ * Measure code vs `lat.md/` churn since HEAD, in lines. Combines tracked
265
+ * changes (`git diff HEAD --numstat`) with untracked files
266
+ * (`git ls-files --others --exclude-standard -z`). Counting untracked files is
267
+ * what makes a freshly scaffolded, never-committed `lat.md/` register as
268
+ * updated — otherwise its edits are invisible to `git diff HEAD` and the sync
269
+ * reminder fires on every turn until `lat.md/` is committed (issue #61).
270
+ * Both scans are scoped and made relative to `projectRoot`, so a Lat project
271
+ * nested in a larger worktree neither misses its own `lat.md/` paths nor counts
272
+ * changes from sibling projects.
273
+ * Outside a Git worktree both scans contribute zero churn by design: Git is
274
+ * optional, so the hook still validates the project but skips the sync ratio.
275
+ */
276
+ export function analyzeDiff(projectRoot) {
268
277
  let codeLines = 0;
269
278
  let latMdLines = 0;
270
- // Each line: "added\tremoved\tfile" (e.g. "42\t11\tsrc/cli/hook.ts")
271
- for (const line of output.split('\n')) {
272
- const parts = line.split('\t');
273
- if (parts.length < 3)
274
- continue;
275
- const added = parseInt(parts[0], 10) || 0;
276
- const removed = parseInt(parts[1], 10) || 0;
277
- const file = parts[2];
278
- const changed = added + removed;
279
- if (file.startsWith('lat.md/')) {
279
+ const tally = (kind, changed) => {
280
+ if (kind === 'latMd') {
280
281
  latMdLines += changed;
281
282
  }
282
- else if (SOURCE_EXTENSIONS.has(extname(file))) {
283
+ else {
283
284
  codeLines += changed;
284
285
  }
286
+ };
287
+ // Tracked changes vs HEAD. Throws when there is no HEAD yet (a repo with no
288
+ // commits) or no repo at all; the untracked scan below still runs.
289
+ try {
290
+ const output = execSync('git diff HEAD --numstat --relative -- .', {
291
+ cwd: projectRoot,
292
+ encoding: 'utf-8',
293
+ stdio: ['ignore', 'pipe', 'ignore'],
294
+ });
295
+ // Each line: "added\tremoved\tfile" (e.g. "42\t11\tsrc/cli/hook.ts")
296
+ for (const line of output.split('\n')) {
297
+ const parts = line.split('\t');
298
+ if (parts.length < 3)
299
+ continue;
300
+ const added = parseInt(parts[0], 10) || 0;
301
+ const removed = parseInt(parts[1], 10) || 0;
302
+ const kind = diffFileKind(parts[2]);
303
+ if (kind)
304
+ tally(kind, added + removed);
305
+ }
306
+ }
307
+ catch {
308
+ // Not a git repo, or no HEAD — fall through to the untracked scan.
309
+ }
310
+ // NUL-delimited output preserves spaces, non-ASCII names, and newlines.
311
+ // Classify paths before reading so unrelated untracked files are never read.
312
+ try {
313
+ const output = execSync('git ls-files --others --exclude-standard -z -- .', {
314
+ cwd: projectRoot,
315
+ encoding: 'utf-8',
316
+ stdio: ['ignore', 'pipe', 'ignore'],
317
+ });
318
+ for (const file of output.split('\0')) {
319
+ if (!file)
320
+ continue;
321
+ const kind = diffFileKind(file);
322
+ if (!kind)
323
+ continue;
324
+ tally(kind, countUntrackedFileLines(projectRoot, file));
325
+ }
326
+ }
327
+ catch {
328
+ // Not a Git repo — diff-based sync analysis is intentionally disabled.
285
329
  }
286
330
  return { codeLines, latMdLines };
287
331
  }
288
- async function getStopStatus(latDir) {
289
- const md = await checkMd(latDir);
290
- const code = await checkCodeRefs(latDir);
291
- const indexErrors = await checkIndex(latDir);
292
- const sectionErrors = await checkSections(latDir);
332
+ export async function getStopStatus(latDir) {
333
+ const projectRoot = dirname(latDir);
334
+ const run = new CheckRunContext(latDir, projectRoot);
293
335
  // Must stay in step with `checkAllCommand` in check.ts. A check counted
294
336
  // there but not here lets the Stop hook call a failing tree clean, which
295
337
  // silently disables the very enforcement the check was added for.
296
- const modeErrors = await checkMode(latDir);
338
+ const [md, code, indexErrors, sectionErrors, modeErrors] = await Promise.all([
339
+ checkMd(latDir, projectRoot, run),
340
+ checkCodeRefs(latDir, projectRoot, run),
341
+ checkIndex(latDir, run),
342
+ checkSections(latDir, projectRoot, run),
343
+ checkMode(latDir, projectRoot),
344
+ ]);
297
345
  const totalErrors = md.errors.length +
298
346
  code.errors.length +
299
347
  indexErrors.length +
300
348
  sectionErrors.length +
301
349
  modeErrors.length;
302
350
  const checkFailed = totalErrors > 0;
303
- const projectRoot = dirname(latDir);
304
351
  const { codeLines, latMdLines } = analyzeDiff(projectRoot);
305
352
  let needsSync = false;
306
353
  if (codeLines >= DIFF_THRESHOLD && latMdLines < LATMD_UPPER_THRESHOLD) {
@@ -315,7 +362,7 @@ async function getStopStatus(latDir) {
315
362
  latMdLines,
316
363
  };
317
364
  }
318
- function formatStopReason({ checkFailed, totalErrors, needsSync, codeLines, latMdLines, }) {
365
+ export function formatStopReason({ checkFailed, totalErrors, needsSync, codeLines, latMdLines, }) {
319
366
  if (!checkFailed && !needsSync)
320
367
  return null;
321
368
  const parts = [];
@@ -425,8 +472,12 @@ export async function hookCmd(agent, event) {
425
472
  console.error(`Unknown hook event for cursor: ${event}. Supported: stop, postToolUse`);
426
473
  process.exit(1);
427
474
  }
475
+ case 'antigravity':
476
+ case 'gemini':
477
+ await handleAntigravityHook(event);
478
+ return;
428
479
  default:
429
- console.error(`Unknown agent: ${agent}. Supported: claude, codex, cursor`);
480
+ console.error(`Unknown agent: ${agent}. Supported: claude, codex, cursor, antigravity, gemini`);
430
481
  process.exit(1);
431
482
  }
432
483
  }