@proflandrigan/shards 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (397) hide show
  1. package/README.md +475 -0
  2. package/package.json +37 -0
  3. package/src/agents/academic.md +276 -0
  4. package/src/agents/ai-engineer.md +377 -0
  5. package/src/agents/analytics-engineer.md +364 -0
  6. package/src/agents/applied-ml-scientist.md +410 -0
  7. package/src/agents/backend-engineer.md +255 -0
  8. package/src/agents/bi-engineer.md +333 -0
  9. package/src/agents/data-analyst.md +343 -0
  10. package/src/agents/data-engineer.md +260 -0
  11. package/src/agents/data-modeller.md +386 -0
  12. package/src/agents/data-scientist.md +366 -0
  13. package/src/agents/deep-learning-engineer.md +389 -0
  14. package/src/agents/ml-engineer.md +424 -0
  15. package/src/agents/mlops-engineer.md +339 -0
  16. package/src/agents/researcher.md +187 -0
  17. package/src/agents/specific_instructions/academic/critical_review.md +263 -0
  18. package/src/agents/specific_instructions/academic/report.md +113 -0
  19. package/src/agents/specific_instructions/ai_engineer/advise.md +162 -0
  20. package/src/agents/specific_instructions/ai_engineer/bi_engineer_handoff.md +86 -0
  21. package/src/agents/specific_instructions/ai_engineer/experiment.md +471 -0
  22. package/src/agents/specific_instructions/ai_engineer/experiment_ui_mode.md +44 -0
  23. package/src/agents/specific_instructions/ai_engineer/phases/index.md +45 -0
  24. package/src/agents/specific_instructions/ai_engineer/phases/phase-1.md +55 -0
  25. package/src/agents/specific_instructions/ai_engineer/phases/phase-2.md +86 -0
  26. package/src/agents/specific_instructions/ai_engineer/phases/phase-3.md +96 -0
  27. package/src/agents/specific_instructions/ai_engineer/phases/phase-4.md +138 -0
  28. package/src/agents/specific_instructions/ai_engineer/phases/phase-5.md +157 -0
  29. package/src/agents/specific_instructions/ai_engineer/phases/phase-6.md +196 -0
  30. package/src/agents/specific_instructions/ai_engineer/phases/phase-7.md +313 -0
  31. package/src/agents/specific_instructions/ai_engineer/phases.md +1011 -0
  32. package/src/agents/specific_instructions/ai_engineer/prompt_lab.md +161 -0
  33. package/src/agents/specific_instructions/ai_engineer/prompt_lab_ui_mode.md +28 -0
  34. package/src/agents/specific_instructions/ai_engineer/research.md +393 -0
  35. package/src/agents/specific_instructions/ai_engineer/research_ui_mode.md +66 -0
  36. package/src/agents/specific_instructions/ai_engineer/review.md +159 -0
  37. package/src/agents/specific_instructions/ai_engineer/validation_checklist.md +182 -0
  38. package/src/agents/specific_instructions/analytics_engineer/advise.md +155 -0
  39. package/src/agents/specific_instructions/analytics_engineer/bi_engineer_handoff.md +91 -0
  40. package/src/agents/specific_instructions/analytics_engineer/data_analyst_handoff.md +84 -0
  41. package/src/agents/specific_instructions/analytics_engineer/deep_phases.md +818 -0
  42. package/src/agents/specific_instructions/analytics_engineer/phases_deep/index.md +24 -0
  43. package/src/agents/specific_instructions/analytics_engineer/phases_deep/phase-1.md +77 -0
  44. package/src/agents/specific_instructions/analytics_engineer/phases_deep/phase-2.md +106 -0
  45. package/src/agents/specific_instructions/analytics_engineer/phases_deep/phase-3.md +93 -0
  46. package/src/agents/specific_instructions/analytics_engineer/phases_deep/phase-4.md +79 -0
  47. package/src/agents/specific_instructions/analytics_engineer/phases_deep/phase-5.md +61 -0
  48. package/src/agents/specific_instructions/analytics_engineer/phases_deep/phase-6.md +45 -0
  49. package/src/agents/specific_instructions/analytics_engineer/phases_deep/phase-7.md +235 -0
  50. package/src/agents/specific_instructions/analytics_engineer/phases_deep/phase-8.md +221 -0
  51. package/src/agents/specific_instructions/analytics_engineer/phases_quick/index.md +19 -0
  52. package/src/agents/specific_instructions/analytics_engineer/phases_quick/phase-1.md +47 -0
  53. package/src/agents/specific_instructions/analytics_engineer/phases_quick/phase-2.md +78 -0
  54. package/src/agents/specific_instructions/analytics_engineer/quick_phases.md +112 -0
  55. package/src/agents/specific_instructions/analytics_engineer/review.md +167 -0
  56. package/src/agents/specific_instructions/analytics_engineer/service_mode.md +369 -0
  57. package/src/agents/specific_instructions/analytics_engineer/ui_mode.md +45 -0
  58. package/src/agents/specific_instructions/analytics_engineer/update.md +162 -0
  59. package/src/agents/specific_instructions/analytics_engineer/validation_checklist.md +121 -0
  60. package/src/agents/specific_instructions/applied_ml_scientist/advise.md +143 -0
  61. package/src/agents/specific_instructions/applied_ml_scientist/phases/index.md +21 -0
  62. package/src/agents/specific_instructions/applied_ml_scientist/phases/phase-1.md +51 -0
  63. package/src/agents/specific_instructions/applied_ml_scientist/phases/phase-2.md +66 -0
  64. package/src/agents/specific_instructions/applied_ml_scientist/phases/phase-3.md +113 -0
  65. package/src/agents/specific_instructions/applied_ml_scientist/phases/phase-4.md +104 -0
  66. package/src/agents/specific_instructions/applied_ml_scientist/phases/phase-5.md +156 -0
  67. package/src/agents/specific_instructions/applied_ml_scientist/phases.md +428 -0
  68. package/src/agents/specific_instructions/applied_ml_scientist/research.md +379 -0
  69. package/src/agents/specific_instructions/applied_ml_scientist/review.md +142 -0
  70. package/src/agents/specific_instructions/applied_ml_scientist/validation_checklist.md +136 -0
  71. package/src/agents/specific_instructions/backend_engineer/clean.md +149 -0
  72. package/src/agents/specific_instructions/backend_engineer/review.md +91 -0
  73. package/src/agents/specific_instructions/backend_engineer/review_checklist.md +54 -0
  74. package/src/agents/specific_instructions/backend_engineer/service_mode.md +67 -0
  75. package/src/agents/specific_instructions/bi_engineer/advise.md +137 -0
  76. package/src/agents/specific_instructions/bi_engineer/data_analyst_handoff.md +77 -0
  77. package/src/agents/specific_instructions/bi_engineer/incoming_handoff.md +45 -0
  78. package/src/agents/specific_instructions/bi_engineer/phases/index.md +20 -0
  79. package/src/agents/specific_instructions/bi_engineer/phases/phase-1.md +164 -0
  80. package/src/agents/specific_instructions/bi_engineer/phases/phase-2.md +92 -0
  81. package/src/agents/specific_instructions/bi_engineer/phases/phase-3.md +121 -0
  82. package/src/agents/specific_instructions/bi_engineer/phases/phase-4.md +106 -0
  83. package/src/agents/specific_instructions/bi_engineer/phases.md +451 -0
  84. package/src/agents/specific_instructions/bi_engineer/review.md +166 -0
  85. package/src/agents/specific_instructions/bi_engineer/update.md +147 -0
  86. package/src/agents/specific_instructions/bi_engineer/validation_checklist.md +124 -0
  87. package/src/agents/specific_instructions/data_analyst/advise.md +138 -0
  88. package/src/agents/specific_instructions/data_analyst/explain.md +221 -0
  89. package/src/agents/specific_instructions/data_analyst/incoming_handoff.md +40 -0
  90. package/src/agents/specific_instructions/data_analyst/phases/index.md +20 -0
  91. package/src/agents/specific_instructions/data_analyst/phases/phase-1.md +159 -0
  92. package/src/agents/specific_instructions/data_analyst/phases/phase-2.md +112 -0
  93. package/src/agents/specific_instructions/data_analyst/phases/phase-3.md +265 -0
  94. package/src/agents/specific_instructions/data_analyst/phases/phase-4.md +100 -0
  95. package/src/agents/specific_instructions/data_analyst/phases.md +501 -0
  96. package/src/agents/specific_instructions/data_analyst/review.md +138 -0
  97. package/src/agents/specific_instructions/data_analyst/ui_mode.md +26 -0
  98. package/src/agents/specific_instructions/data_analyst/update.md +144 -0
  99. package/src/agents/specific_instructions/data_analyst/validation_checklist.md +95 -0
  100. package/src/agents/specific_instructions/data_engineer/advise.md +137 -0
  101. package/src/agents/specific_instructions/data_engineer/phases.md +466 -0
  102. package/src/agents/specific_instructions/data_engineer/phases_deep/index.md +23 -0
  103. package/src/agents/specific_instructions/data_engineer/phases_deep/phase-1.md +49 -0
  104. package/src/agents/specific_instructions/data_engineer/phases_deep/phase-2.md +93 -0
  105. package/src/agents/specific_instructions/data_engineer/phases_deep/phase-3.md +55 -0
  106. package/src/agents/specific_instructions/data_engineer/phases_deep/phase-4.md +48 -0
  107. package/src/agents/specific_instructions/data_engineer/phases_deep/phase-5.md +40 -0
  108. package/src/agents/specific_instructions/data_engineer/phases_deep/phase-6.md +102 -0
  109. package/src/agents/specific_instructions/data_engineer/phases_deep/phase-7.md +87 -0
  110. package/src/agents/specific_instructions/data_engineer/phases_quick/index.md +19 -0
  111. package/src/agents/specific_instructions/data_engineer/phases_quick/phase-1.md +45 -0
  112. package/src/agents/specific_instructions/data_engineer/phases_quick/phase-2.md +54 -0
  113. package/src/agents/specific_instructions/data_engineer/review.md +135 -0
  114. package/src/agents/specific_instructions/data_engineer/validation_checklist.md +136 -0
  115. package/src/agents/specific_instructions/data_modeller/advise.md +137 -0
  116. package/src/agents/specific_instructions/data_modeller/phases.md +581 -0
  117. package/src/agents/specific_instructions/data_modeller/phases_deep/index.md +23 -0
  118. package/src/agents/specific_instructions/data_modeller/phases_deep/phase-1.md +52 -0
  119. package/src/agents/specific_instructions/data_modeller/phases_deep/phase-2.md +113 -0
  120. package/src/agents/specific_instructions/data_modeller/phases_deep/phase-3.md +47 -0
  121. package/src/agents/specific_instructions/data_modeller/phases_deep/phase-4.md +51 -0
  122. package/src/agents/specific_instructions/data_modeller/phases_deep/phase-5.md +45 -0
  123. package/src/agents/specific_instructions/data_modeller/phases_deep/phase-6.md +105 -0
  124. package/src/agents/specific_instructions/data_modeller/phases_deep/phase-7.md +136 -0
  125. package/src/agents/specific_instructions/data_modeller/phases_quick/index.md +19 -0
  126. package/src/agents/specific_instructions/data_modeller/phases_quick/phase-1.md +47 -0
  127. package/src/agents/specific_instructions/data_modeller/phases_quick/phase-2.md +65 -0
  128. package/src/agents/specific_instructions/data_modeller/review.md +141 -0
  129. package/src/agents/specific_instructions/data_modeller/service_mode.md +218 -0
  130. package/src/agents/specific_instructions/data_modeller/validation_checklist.md +125 -0
  131. package/src/agents/specific_instructions/data_scientist/advise.md +158 -0
  132. package/src/agents/specific_instructions/data_scientist/bi_engineer_handoff.md +63 -0
  133. package/src/agents/specific_instructions/data_scientist/experiment.md +482 -0
  134. package/src/agents/specific_instructions/data_scientist/experiment_ui_mode.md +44 -0
  135. package/src/agents/specific_instructions/data_scientist/explain.md +247 -0
  136. package/src/agents/specific_instructions/data_scientist/greenfield_data.md +35 -0
  137. package/src/agents/specific_instructions/data_scientist/ml_engineer_handoff.md +52 -0
  138. package/src/agents/specific_instructions/data_scientist/notebook_walkthrough.md +76 -0
  139. package/src/agents/specific_instructions/data_scientist/phases/index.md +24 -0
  140. package/src/agents/specific_instructions/data_scientist/phases/phase-1.md +45 -0
  141. package/src/agents/specific_instructions/data_scientist/phases/phase-2.md +67 -0
  142. package/src/agents/specific_instructions/data_scientist/phases/phase-3.md +89 -0
  143. package/src/agents/specific_instructions/data_scientist/phases/phase-4.md +143 -0
  144. package/src/agents/specific_instructions/data_scientist/phases/phase-5.md +71 -0
  145. package/src/agents/specific_instructions/data_scientist/phases/phase-6.md +239 -0
  146. package/src/agents/specific_instructions/data_scientist/phases/phase-7.md +207 -0
  147. package/src/agents/specific_instructions/data_scientist/phases.md +651 -0
  148. package/src/agents/specific_instructions/data_scientist/research.md +345 -0
  149. package/src/agents/specific_instructions/data_scientist/research_ui_mode.md +52 -0
  150. package/src/agents/specific_instructions/data_scientist/review.md +136 -0
  151. package/src/agents/specific_instructions/data_scientist/service_mode.md +247 -0
  152. package/src/agents/specific_instructions/data_scientist/validation_checklist.md +183 -0
  153. package/src/agents/specific_instructions/deep_learning_engineer/advise.md +145 -0
  154. package/src/agents/specific_instructions/deep_learning_engineer/phases/index.md +21 -0
  155. package/src/agents/specific_instructions/deep_learning_engineer/phases/phase-1.md +74 -0
  156. package/src/agents/specific_instructions/deep_learning_engineer/phases/phase-2.md +98 -0
  157. package/src/agents/specific_instructions/deep_learning_engineer/phases/phase-3.md +76 -0
  158. package/src/agents/specific_instructions/deep_learning_engineer/phases/phase-4.md +128 -0
  159. package/src/agents/specific_instructions/deep_learning_engineer/phases/phase-5.md +292 -0
  160. package/src/agents/specific_instructions/deep_learning_engineer/phases.md +567 -0
  161. package/src/agents/specific_instructions/deep_learning_engineer/research.md +389 -0
  162. package/src/agents/specific_instructions/deep_learning_engineer/review.md +155 -0
  163. package/src/agents/specific_instructions/deep_learning_engineer/validation_checklist.md +147 -0
  164. package/src/agents/specific_instructions/ml_engineer/advise.md +174 -0
  165. package/src/agents/specific_instructions/ml_engineer/bi_engineer_handoff.md +71 -0
  166. package/src/agents/specific_instructions/ml_engineer/experiment.md +474 -0
  167. package/src/agents/specific_instructions/ml_engineer/experiment_ui_mode.md +44 -0
  168. package/src/agents/specific_instructions/ml_engineer/notebook_walkthrough.md +75 -0
  169. package/src/agents/specific_instructions/ml_engineer/phases/index.md +25 -0
  170. package/src/agents/specific_instructions/ml_engineer/phases/phase-1.md +49 -0
  171. package/src/agents/specific_instructions/ml_engineer/phases/phase-2.md +75 -0
  172. package/src/agents/specific_instructions/ml_engineer/phases/phase-3.md +124 -0
  173. package/src/agents/specific_instructions/ml_engineer/phases/phase-4.md +279 -0
  174. package/src/agents/specific_instructions/ml_engineer/phases/phase-5.md +160 -0
  175. package/src/agents/specific_instructions/ml_engineer/phases/phase-6-5.md +170 -0
  176. package/src/agents/specific_instructions/ml_engineer/phases/phase-6.md +295 -0
  177. package/src/agents/specific_instructions/ml_engineer/phases/phase-7.md +337 -0
  178. package/src/agents/specific_instructions/ml_engineer/phases.md +1068 -0
  179. package/src/agents/specific_instructions/ml_engineer/research.md +437 -0
  180. package/src/agents/specific_instructions/ml_engineer/research_ui_mode.md +71 -0
  181. package/src/agents/specific_instructions/ml_engineer/review.md +187 -0
  182. package/src/agents/specific_instructions/ml_engineer/service_mode.md +273 -0
  183. package/src/agents/specific_instructions/ml_engineer/validation_checklist.md +185 -0
  184. package/src/agents/specific_instructions/mlops_engineer/advise.md +139 -0
  185. package/src/agents/specific_instructions/mlops_engineer/phases/index.md +23 -0
  186. package/src/agents/specific_instructions/mlops_engineer/phases/phase-1.md +52 -0
  187. package/src/agents/specific_instructions/mlops_engineer/phases/phase-2.md +86 -0
  188. package/src/agents/specific_instructions/mlops_engineer/phases/phase-3.md +105 -0
  189. package/src/agents/specific_instructions/mlops_engineer/phases/phase-4.md +128 -0
  190. package/src/agents/specific_instructions/mlops_engineer/phases/phase-5.md +106 -0
  191. package/src/agents/specific_instructions/mlops_engineer/phases/phase-6.md +128 -0
  192. package/src/agents/specific_instructions/mlops_engineer/phases/phase-7.md +144 -0
  193. package/src/agents/specific_instructions/mlops_engineer/phases.md +671 -0
  194. package/src/agents/specific_instructions/mlops_engineer/review.md +164 -0
  195. package/src/agents/specific_instructions/mlops_engineer/service_mode.md +81 -0
  196. package/src/agents/specific_instructions/mlops_engineer/validation_checklist.md +151 -0
  197. package/src/agents/specific_instructions/researcher/critical_review.md +292 -0
  198. package/src/agents/specific_instructions/researcher/review_checklist.md +67 -0
  199. package/src/agents/specific_instructions/researcher/service_mode.md +224 -0
  200. package/src/agents/specific_instructions/shared/auto_verify_mode.md +141 -0
  201. package/src/agents/specific_instructions/shared/autonomous_research.md +1289 -0
  202. package/src/agents/specific_instructions/shared/behavioral_rules.md +36 -0
  203. package/src/agents/specific_instructions/shared/diverge_protocol.md +387 -0
  204. package/src/agents/specific_instructions/shared/engineering_guidelines.md +136 -0
  205. package/src/agents/specific_instructions/shared/experiment_versioning.md +184 -0
  206. package/src/agents/specific_instructions/shared/goal_mode.md +187 -0
  207. package/src/agents/specific_instructions/shared/incremental_testing.md +139 -0
  208. package/src/agents/specific_instructions/shared/intent_discovery.md +223 -0
  209. package/src/agents/specific_instructions/shared/join_path_protocol.md +168 -0
  210. package/src/agents/specific_instructions/shared/knowledge_checkpoint.md +83 -0
  211. package/src/agents/specific_instructions/shared/knowledge_harvest.md +220 -0
  212. package/src/agents/specific_instructions/shared/knowledge_retrieval.md +100 -0
  213. package/src/agents/specific_instructions/shared/notebook_walkthrough_protocol.md +367 -0
  214. package/src/agents/specific_instructions/shared/reviewer_verdict_protocol.md +74 -0
  215. package/src/agents/specific_instructions/shared/swarm_protocol.md +97 -0
  216. package/src/agents/specific_instructions/shared/validation_protocol.md +139 -0
  217. package/src/agents/specific_instructions/syn/arbiter.md +140 -0
  218. package/src/agents/specific_instructions/syn/brainstorm.md +550 -0
  219. package/src/agents/specific_instructions/syn/code_review.md +232 -0
  220. package/src/agents/specific_instructions/syn/diff.md +239 -0
  221. package/src/agents/specific_instructions/syn/final_review.md +65 -0
  222. package/src/agents/specific_instructions/syn/fixer.md +240 -0
  223. package/src/agents/specific_instructions/syn/free_form.md +130 -0
  224. package/src/agents/specific_instructions/syn/knowledge.md +468 -0
  225. package/src/agents/specific_instructions/syn/notebook_walkthrough.md +78 -0
  226. package/src/agents/specific_instructions/syn/panel_review.md +634 -0
  227. package/src/agents/specific_instructions/syn/pm.md +453 -0
  228. package/src/agents/specific_instructions/syn/pr_review.md +255 -0
  229. package/src/agents/specific_instructions/syn/slides.md +417 -0
  230. package/src/agents/syn.md +729 -0
  231. package/src/commands/academic.md +41 -0
  232. package/src/commands/ai-engineer.md +45 -0
  233. package/src/commands/analytics-engineer.md +48 -0
  234. package/src/commands/applied-ml-scientist.md +45 -0
  235. package/src/commands/backend-engineer.md +35 -0
  236. package/src/commands/bi-engineer.md +40 -0
  237. package/src/commands/brainstorm.md +24 -0
  238. package/src/commands/data-analyst.md +38 -0
  239. package/src/commands/data-engineer.md +37 -0
  240. package/src/commands/data-modeller.md +38 -0
  241. package/src/commands/data-scientist.md +38 -0
  242. package/src/commands/deep-learning-engineer.md +47 -0
  243. package/src/commands/end.md +49 -0
  244. package/src/commands/knowledge.md +24 -0
  245. package/src/commands/ml-engineer.md +42 -0
  246. package/src/commands/mlops-engineer.md +47 -0
  247. package/src/commands/notebook-walkthrough.md +58 -0
  248. package/src/commands/researcher.md +40 -0
  249. package/src/commands/resume.md +57 -0
  250. package/src/commands/review-pr.md +26 -0
  251. package/src/commands/shards-guide.md +41 -0
  252. package/src/commands/shards-ui.md +32 -0
  253. package/src/commands/shards.md +41 -0
  254. package/src/docs/01-getting-started/concepts.md +109 -0
  255. package/src/docs/01-getting-started/first-session.md +79 -0
  256. package/src/docs/01-getting-started/install.md +61 -0
  257. package/src/docs/02-agents/academic.md +71 -0
  258. package/src/docs/02-agents/ai-engineer.md +78 -0
  259. package/src/docs/02-agents/analytics-engineer.md +58 -0
  260. package/src/docs/02-agents/applied-ml-scientist.md +59 -0
  261. package/src/docs/02-agents/backend-engineer.md +58 -0
  262. package/src/docs/02-agents/bi-engineer.md +65 -0
  263. package/src/docs/02-agents/data-analyst.md +67 -0
  264. package/src/docs/02-agents/data-engineer.md +57 -0
  265. package/src/docs/02-agents/data-modeller.md +51 -0
  266. package/src/docs/02-agents/data-scientist.md +78 -0
  267. package/src/docs/02-agents/deep-learning-engineer.md +64 -0
  268. package/src/docs/02-agents/ml-engineer.md +80 -0
  269. package/src/docs/02-agents/mlops-engineer.md +59 -0
  270. package/src/docs/02-agents/overview.md +62 -0
  271. package/src/docs/02-agents/researcher.md +73 -0
  272. package/src/docs/02-agents/syn.md +88 -0
  273. package/src/docs/03-protocols/auto-verify.md +82 -0
  274. package/src/docs/03-protocols/autonomous-research.md +59 -0
  275. package/src/docs/03-protocols/behavioral-rules.md +35 -0
  276. package/src/docs/03-protocols/diverge.md +50 -0
  277. package/src/docs/03-protocols/engineering-guidelines.md +56 -0
  278. package/src/docs/03-protocols/experiment-versioning.md +38 -0
  279. package/src/docs/03-protocols/gate-pattern.md +65 -0
  280. package/src/docs/03-protocols/incremental-testing.md +68 -0
  281. package/src/docs/03-protocols/join-path.md +46 -0
  282. package/src/docs/03-protocols/knowledge-ledger.md +70 -0
  283. package/src/docs/03-protocols/reviewer-verdicts.md +39 -0
  284. package/src/docs/03-protocols/swarm.md +40 -0
  285. package/src/docs/03-protocols/validation.md +174 -0
  286. package/src/docs/04-ui/activity-bar.md +70 -0
  287. package/src/docs/04-ui/chat-pane.md +80 -0
  288. package/src/docs/04-ui/code-intel.md +62 -0
  289. package/src/docs/04-ui/file-editing.md +61 -0
  290. package/src/docs/04-ui/git.md +54 -0
  291. package/src/docs/04-ui/keybindings.md +79 -0
  292. package/src/docs/04-ui/knowledge-map.md +76 -0
  293. package/src/docs/04-ui/overview.md +93 -0
  294. package/src/docs/04-ui/panels.md +49 -0
  295. package/src/docs/04-ui/pinboard-selection.md +66 -0
  296. package/src/docs/04-ui/quick-open-palette.md +56 -0
  297. package/src/docs/04-ui/sessions.md +81 -0
  298. package/src/docs/04-ui/settings-permissions.md +56 -0
  299. package/src/docs/05-commands/reference.md +59 -0
  300. package/src/docs/06-outputs/directory-map.md +116 -0
  301. package/src/docs/07-workflows/ai-eval-first.md +57 -0
  302. package/src/docs/07-workflows/deep-study-to-production.md +76 -0
  303. package/src/docs/07-workflows/diverge-exploration.md +77 -0
  304. package/src/docs/07-workflows/quick-analysis.md +45 -0
  305. package/src/docs/08-integrations/claude-code-auto-mode.md +191 -0
  306. package/src/docs/08-integrations/google-slides.md +175 -0
  307. package/src/docs/README.md +30 -0
  308. package/src/docs/manifest.json +108 -0
  309. package/src/templates/analysis-template.md +20 -0
  310. package/src/templates/branch-report.md +46 -0
  311. package/src/templates/diff-report.md +88 -0
  312. package/src/templates/knowledge-index.md +7 -0
  313. package/src/templates/model-card-schema.json +186 -0
  314. package/src/templates/model-card-schema.md +88 -0
  315. package/src/templates/model-card.md +124 -0
  316. package/src/templates/project-plan.md +47 -0
  317. package/src/templates/project-specs.md +81 -0
  318. package/src/templates/report-template.md +43 -0
  319. package/src/templates/study-template.md +25 -0
  320. package/src/ui/cc-readonly.js +181 -0
  321. package/src/ui/chat-session.js +466 -0
  322. package/src/ui/css/base.css +136 -0
  323. package/src/ui/css/brainstorm.css +525 -0
  324. package/src/ui/css/chat.css +1405 -0
  325. package/src/ui/css/editor.css +546 -0
  326. package/src/ui/css/eval-dashboard.css +157 -0
  327. package/src/ui/css/experiment.css +237 -0
  328. package/src/ui/css/guide.css +186 -0
  329. package/src/ui/css/knowledge-map.css +383 -0
  330. package/src/ui/css/layout.css +431 -0
  331. package/src/ui/css/model-card.css +161 -0
  332. package/src/ui/css/notebook-walkthrough.css +271 -0
  333. package/src/ui/css/pr-review.css +403 -0
  334. package/src/ui/css/prompt-lab.css +325 -0
  335. package/src/ui/css/sessions.css +258 -0
  336. package/src/ui/css/sidebar.css +661 -0
  337. package/src/ui/css/terminal.css +113 -0
  338. package/src/ui/css/theme-light.css +542 -0
  339. package/src/ui/index.html +389 -0
  340. package/src/ui/js/agents.js +32 -0
  341. package/src/ui/js/bookmarks.js +230 -0
  342. package/src/ui/js/chat.js +1776 -0
  343. package/src/ui/js/code-intel.js +328 -0
  344. package/src/ui/js/command-palette.js +142 -0
  345. package/src/ui/js/events.js +591 -0
  346. package/src/ui/js/explorer.js +317 -0
  347. package/src/ui/js/file-view.js +477 -0
  348. package/src/ui/js/git.js +536 -0
  349. package/src/ui/js/guide.js +198 -0
  350. package/src/ui/js/hud.js +75 -0
  351. package/src/ui/js/init.js +351 -0
  352. package/src/ui/js/knowledge-map.js +906 -0
  353. package/src/ui/js/markdown.js +114 -0
  354. package/src/ui/js/monaco.js +164 -0
  355. package/src/ui/js/notebook-walkthrough.js +272 -0
  356. package/src/ui/js/notebook.js +448 -0
  357. package/src/ui/js/panels.js +2681 -0
  358. package/src/ui/js/pinboard.js +186 -0
  359. package/src/ui/js/quick-open.js +164 -0
  360. package/src/ui/js/selection-context.js +131 -0
  361. package/src/ui/js/sessions.js +256 -0
  362. package/src/ui/js/settings.js +476 -0
  363. package/src/ui/js/split-view.js +82 -0
  364. package/src/ui/js/state.js +343 -0
  365. package/src/ui/js/table.js +161 -0
  366. package/src/ui/js/tabs.js +284 -0
  367. package/src/ui/js/tabular.js +125 -0
  368. package/src/ui/js/terminal.js +354 -0
  369. package/src/ui/js/timeline.js +137 -0
  370. package/src/ui/js/utils.js +293 -0
  371. package/src/ui/notebook-kernel.py +790 -0
  372. package/src/ui/open-browser.js +55 -0
  373. package/src/ui/permission-pattern.js +42 -0
  374. package/src/ui/relay.js +513 -0
  375. package/src/ui/server.js +3072 -0
  376. package/src/ui/session-index.js +225 -0
  377. package/src/ui/shards_icon.png +0 -0
  378. package/src/ui/spawn-server.js +41 -0
  379. package/src/ui/symbol-index.js +813 -0
  380. package/src/ui/ui-push.js +177 -0
  381. package/tools/gate-hook/VALIDATION_SPEC.md +273 -0
  382. package/tools/gate-hook/__tests__/auto-verify.test.js +343 -0
  383. package/tools/gate-hook/auto-allowlist.js +179 -0
  384. package/tools/gate-hook/auto-state.js +68 -0
  385. package/tools/gate-hook/classify.js +21 -0
  386. package/tools/gate-hook/log.js +57 -0
  387. package/tools/gate-hook/parser.js +205 -0
  388. package/tools/gate-hook/sql-guard.js +230 -0
  389. package/tools/gate-hook/state.js +170 -0
  390. package/tools/gate-hook/sweep.js +139 -0
  391. package/tools/gate-hook/transcript.js +45 -0
  392. package/tools/gate-hook/validation.js +321 -0
  393. package/tools/gate-hook.js +475 -0
  394. package/tools/install.js +914 -0
  395. package/tools/shards-gates.js +311 -0
  396. package/tools/shards-sessions.js +261 -0
  397. package/tools/shards-ui.js +377 -0
@@ -0,0 +1,813 @@
1
+ 'use strict';
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+ const { execSync, execFileSync } = require('child_process');
6
+
7
+ // ─── Symbol Index Engine ─────────────────────────────────────────────────────
8
+ // Builds and maintains an in-memory symbol index using ctags (with regex fallback).
9
+
10
+ const SKIP_DIRS = new Set(['.git', 'node_modules', '__pycache__', '.shards', '.venv', 'venv', '.tox', '.mypy_cache', '.pytest_cache', 'dist', 'build']);
11
+ const SUPPORTED_EXTS = new Set(['.py', '.js', '.ts', '.tsx', '.jsx', '.go', '.rs', '.java', '.rb', '.c', '.cpp', '.h', '.hpp', '.cs', '.php', '.swift', '.kt', '.r', '.R', '.sql', '.sh', '.bash']);
12
+
13
+ let symbolsByName = new Map(); // name -> SymbolEntry[]
14
+ let symbolsByFile = new Map(); // relPath -> SymbolEntry[]
15
+ let ctagsAvailable = false;
16
+ let indexedAt = null;
17
+ let projectDir = null;
18
+ let watcher = null;
19
+ let watchDebounce = new Map(); // relPath -> timeout
20
+
21
+ // ─── Reference cache for hover enrichment ───────────────────────────────────
22
+ let referenceCache = new Map(); // name -> { refs: {count, byFile}, callers, callees, builtAt }
23
+ let fileToRefNames = new Map(); // file -> Set<name> — reverse map for cache invalidation
24
+ let cacheBuilding = false;
25
+ let cacheQueue = []; // names queued for background cache build
26
+
27
+ // ─── Ctags detection ─────────────────────────────────────────────────────────
28
+
29
+ function detectCtags() {
30
+ try {
31
+ execSync('ctags --version', { timeout: 3000, stdio: 'pipe' });
32
+ ctagsAvailable = true;
33
+ } catch {
34
+ ctagsAvailable = false;
35
+ }
36
+ return ctagsAvailable;
37
+ }
38
+
39
+ // ─── Ctags-based indexing ────────────────────────────────────────────────────
40
+
41
+ function parseCtagsJson(output) {
42
+ const entries = [];
43
+ for (const line of output.split('\n')) {
44
+ if (!line.trim()) continue;
45
+ try {
46
+ const tag = JSON.parse(line);
47
+ if (!tag.name || !tag.path) continue;
48
+ entries.push({
49
+ name: tag.name,
50
+ kind: mapCtagsKind(tag.kind),
51
+ file: tag.path,
52
+ line: tag.line || 0,
53
+ pattern: tag.pattern || '',
54
+ scope: tag.scope || null,
55
+ scopeKind: tag.scopeKind || null,
56
+ signature: tag.signature || null,
57
+ });
58
+ } catch {
59
+ // skip malformed lines
60
+ }
61
+ }
62
+ return entries;
63
+ }
64
+
65
+ function mapCtagsKind(kind) {
66
+ if (!kind) return 'symbol';
67
+ const map = {
68
+ f: 'function', F: 'function', function: 'function',
69
+ c: 'class', class: 'class',
70
+ m: 'method', method: 'method', member: 'method',
71
+ v: 'variable', variable: 'variable',
72
+ p: 'property', property: 'property',
73
+ i: 'interface', interface: 'interface',
74
+ e: 'enum', enum: 'enum',
75
+ t: 'type', typedef: 'type', type: 'type',
76
+ s: 'struct', struct: 'struct',
77
+ n: 'namespace', namespace: 'namespace', module: 'module',
78
+ d: 'macro', macro: 'macro', define: 'macro',
79
+ C: 'constant', constant: 'constant',
80
+ };
81
+ return map[kind] || kind;
82
+ }
83
+
84
+ function runCtagsOnProject(dir) {
85
+ try {
86
+ const args = [
87
+ '--output-format=json',
88
+ '--fields=+nKS',
89
+ '--extras=-{anonymous}',
90
+ '-R',
91
+ '--exclude=node_modules',
92
+ '--exclude=.git',
93
+ '--exclude=__pycache__',
94
+ '--exclude=.venv',
95
+ '--exclude=venv',
96
+ '--exclude=.shards',
97
+ '--exclude=dist',
98
+ '--exclude=build',
99
+ '--exclude=.tox',
100
+ '.',
101
+ ];
102
+ const output = execFileSync('ctags', args, {
103
+ cwd: dir,
104
+ encoding: 'utf8',
105
+ timeout: 15000,
106
+ maxBuffer: 50 * 1024 * 1024,
107
+ });
108
+ return parseCtagsJson(output);
109
+ } catch (err) {
110
+ return null;
111
+ }
112
+ }
113
+
114
+ function runCtagsOnFile(dir, relPath) {
115
+ try {
116
+ const absPath = path.join(dir, relPath);
117
+ if (!fs.existsSync(absPath)) return [];
118
+ const args = ['--output-format=json', '--fields=+nKS', '--extras=-{anonymous}', absPath];
119
+ const output = execFileSync('ctags', args, {
120
+ cwd: dir,
121
+ encoding: 'utf8',
122
+ timeout: 5000,
123
+ maxBuffer: 10 * 1024 * 1024,
124
+ });
125
+ // ctags outputs absolute paths when given absolute input; normalize to relative
126
+ const entries = parseCtagsJson(output);
127
+ for (const e of entries) {
128
+ e.file = path.relative(dir, e.file);
129
+ }
130
+ return entries;
131
+ } catch {
132
+ return [];
133
+ }
134
+ }
135
+
136
+ // ─── Regex-based fallback indexing ───────────────────────────────────────────
137
+
138
+ const REGEX_PATTERNS = {
139
+ '.py': [
140
+ { regex: /^(?:async\s+)?def\s+(\w+)\s*\(([^)]*)\)/gm, kind: 'function', sigGroup: 2 },
141
+ { regex: /^class\s+(\w+)(?:\s*\(([^)]*)\))?/gm, kind: 'class', sigGroup: 2 },
142
+ { regex: /^(\w+)\s*=\s*/gm, kind: 'variable' },
143
+ ],
144
+ '.js': [
145
+ { regex: /^(?:export\s+)?(?:async\s+)?function\s+(\w+)\s*\(([^)]*)\)/gm, kind: 'function', sigGroup: 2 },
146
+ { regex: /^(?:export\s+)?class\s+(\w+)/gm, kind: 'class' },
147
+ { regex: /^(?:export\s+)?(?:const|let|var)\s+(\w+)\s*=/gm, kind: 'variable' },
148
+ { regex: /(\w+)\s*[:=]\s*(?:async\s+)?function\s*\(([^)]*)\)/gm, kind: 'function', sigGroup: 2 },
149
+ { regex: /(\w+)\s*\(([^)]*)\)\s*\{/gm, kind: 'function', sigGroup: 2 },
150
+ ],
151
+ '.ts': null, // same as .js
152
+ '.tsx': null,
153
+ '.jsx': null,
154
+ '.go': [
155
+ { regex: /^func\s+(?:\(\w+\s+\*?\w+\)\s+)?(\w+)\s*\(([^)]*)\)/gm, kind: 'function', sigGroup: 2 },
156
+ { regex: /^type\s+(\w+)\s+struct/gm, kind: 'struct' },
157
+ { regex: /^type\s+(\w+)\s+interface/gm, kind: 'interface' },
158
+ ],
159
+ '.rs': [
160
+ { regex: /^(?:pub\s+)?(?:async\s+)?fn\s+(\w+)\s*(?:<[^>]*>)?\s*\(([^)]*)\)/gm, kind: 'function', sigGroup: 2 },
161
+ { regex: /^(?:pub\s+)?struct\s+(\w+)/gm, kind: 'struct' },
162
+ { regex: /^(?:pub\s+)?enum\s+(\w+)/gm, kind: 'enum' },
163
+ { regex: /^(?:pub\s+)?trait\s+(\w+)/gm, kind: 'interface' },
164
+ ],
165
+ '.java': [
166
+ { regex: /(?:public|private|protected|static|\s)+[\w<>\[\]]+\s+(\w+)\s*\(([^)]*)\)/gm, kind: 'method', sigGroup: 2 },
167
+ { regex: /(?:public\s+)?class\s+(\w+)/gm, kind: 'class' },
168
+ { regex: /(?:public\s+)?interface\s+(\w+)/gm, kind: 'interface' },
169
+ ],
170
+ '.rb': [
171
+ { regex: /^\s*def\s+(\w+)(?:\(([^)]*)\))?/gm, kind: 'function', sigGroup: 2 },
172
+ { regex: /^\s*class\s+(\w+)/gm, kind: 'class' },
173
+ { regex: /^\s*module\s+(\w+)/gm, kind: 'module' },
174
+ ],
175
+ '.sql': [
176
+ { regex: /CREATE\s+(?:OR\s+REPLACE\s+)?(?:FUNCTION|PROCEDURE)\s+(\w+)\s*\(([^)]*)\)/gim, kind: 'function', sigGroup: 2 },
177
+ { regex: /CREATE\s+(?:OR\s+REPLACE\s+)?(?:TABLE|VIEW)\s+(?:IF\s+NOT\s+EXISTS\s+)?(\w+)/gim, kind: 'class' },
178
+ ],
179
+ };
180
+
181
+ // Alias entries
182
+ REGEX_PATTERNS['.ts'] = REGEX_PATTERNS['.js'];
183
+ REGEX_PATTERNS['.tsx'] = REGEX_PATTERNS['.js'];
184
+ REGEX_PATTERNS['.jsx'] = REGEX_PATTERNS['.js'];
185
+
186
+ function regexIndexFile(dir, relPath) {
187
+ const ext = path.extname(relPath).toLowerCase();
188
+ const patterns = REGEX_PATTERNS[ext];
189
+ if (!patterns) return [];
190
+
191
+ let content;
192
+ try {
193
+ const absPath = path.join(dir, relPath);
194
+ const stat = fs.statSync(absPath);
195
+ if (stat.size > 2 * 1024 * 1024) return []; // skip large files
196
+ content = fs.readFileSync(absPath, 'utf8');
197
+ } catch {
198
+ return [];
199
+ }
200
+
201
+ const entries = [];
202
+ const lines = content.split('\n');
203
+
204
+ for (const pat of patterns) {
205
+ pat.regex.lastIndex = 0;
206
+ let match;
207
+ while ((match = pat.regex.exec(content)) !== null) {
208
+ const name = match[1];
209
+ if (!name || name.length < 2) continue;
210
+
211
+ // Calculate line number
212
+ const offset = match.index;
213
+ let lineNum = 1;
214
+ for (let i = 0; i < offset && i < content.length; i++) {
215
+ if (content[i] === '\n') lineNum++;
216
+ }
217
+
218
+ const sig = pat.sigGroup ? (match[pat.sigGroup] || '') : null;
219
+
220
+ entries.push({
221
+ name,
222
+ kind: pat.kind,
223
+ file: relPath,
224
+ line: lineNum,
225
+ pattern: lines[lineNum - 1] || '',
226
+ scope: null,
227
+ scopeKind: null,
228
+ signature: sig ? `(${sig})` : null,
229
+ });
230
+ }
231
+ }
232
+
233
+ // Deduplicate entries with same name+line (multiple patterns can match the same symbol)
234
+ const seen = new Set();
235
+ return entries.filter(e => {
236
+ const key = `${e.name}:${e.line}`;
237
+ if (seen.has(key)) return false;
238
+ seen.add(key);
239
+ return true;
240
+ });
241
+ }
242
+
243
+ function regexIndexProject(dir) {
244
+ const entries = [];
245
+ function walk(currentDir, relDir) {
246
+ let items;
247
+ try { items = fs.readdirSync(currentDir); } catch { return; }
248
+ for (const item of items) {
249
+ if (SKIP_DIRS.has(item)) continue;
250
+ const fullPath = path.join(currentDir, item);
251
+ const relPath = relDir ? `${relDir}/${item}` : item;
252
+ let stat;
253
+ try { stat = fs.statSync(fullPath); } catch { continue; }
254
+ if (stat.isDirectory()) {
255
+ walk(fullPath, relPath);
256
+ } else if (stat.isFile() && SUPPORTED_EXTS.has(path.extname(item).toLowerCase())) {
257
+ const fileEntries = regexIndexFile(dir, relPath);
258
+ entries.push(...fileEntries);
259
+ }
260
+ }
261
+ }
262
+ walk(dir, '');
263
+ return entries;
264
+ }
265
+
266
+ // ─── Index management ────────────────────────────────────────────────────────
267
+
268
+ function insertEntries(entries) {
269
+ for (const entry of entries) {
270
+ // By name
271
+ if (!symbolsByName.has(entry.name)) {
272
+ symbolsByName.set(entry.name, []);
273
+ }
274
+ symbolsByName.get(entry.name).push(entry);
275
+
276
+ // By file
277
+ if (!symbolsByFile.has(entry.file)) {
278
+ symbolsByFile.set(entry.file, []);
279
+ }
280
+ symbolsByFile.get(entry.file).push(entry);
281
+ }
282
+ }
283
+
284
+ function removeFileEntries(relPath) {
285
+ const entries = symbolsByFile.get(relPath);
286
+ if (!entries) return;
287
+
288
+ // Remove from symbolsByName
289
+ for (const entry of entries) {
290
+ const nameEntries = symbolsByName.get(entry.name);
291
+ if (nameEntries) {
292
+ const filtered = nameEntries.filter(e => e.file !== relPath);
293
+ if (filtered.length > 0) {
294
+ symbolsByName.set(entry.name, filtered);
295
+ } else {
296
+ symbolsByName.delete(entry.name);
297
+ }
298
+ }
299
+ }
300
+
301
+ symbolsByFile.delete(relPath);
302
+ }
303
+
304
+ function buildIndex(dir, logFn) {
305
+ projectDir = dir;
306
+ const log = logFn || (() => {});
307
+
308
+ detectCtags();
309
+ symbolsByName = new Map();
310
+ symbolsByFile = new Map();
311
+
312
+ let entries;
313
+ if (ctagsAvailable) {
314
+ entries = runCtagsOnProject(dir);
315
+ if (!entries) {
316
+ // ctags failed, fall back
317
+ log('ctags execution failed, falling back to regex indexer');
318
+ entries = regexIndexProject(dir);
319
+ } else {
320
+ log(`ctags indexed ${entries.length} symbols`);
321
+ }
322
+ } else {
323
+ log('ctags not found — using regex fallback (install universal-ctags for full features)');
324
+ entries = regexIndexProject(dir);
325
+ log(`regex indexed ${entries.length} symbols`);
326
+ }
327
+
328
+ insertEntries(entries);
329
+ indexedAt = new Date().toISOString();
330
+ }
331
+
332
+ function updateFileIndex(dir, relPath) {
333
+ if (!SUPPORTED_EXTS.has(path.extname(relPath).toLowerCase())) return;
334
+
335
+ // Invalidate reference cache entries affected by this file change
336
+ invalidateCacheForFile(relPath, dir);
337
+
338
+ removeFileEntries(relPath);
339
+
340
+ let entries;
341
+ if (ctagsAvailable) {
342
+ entries = runCtagsOnFile(dir, relPath);
343
+ if (!entries || entries.length === 0) {
344
+ entries = regexIndexFile(dir, relPath);
345
+ }
346
+ } else {
347
+ entries = regexIndexFile(dir, relPath);
348
+ }
349
+
350
+ insertEntries(entries);
351
+ }
352
+
353
+ // ─── Query functions ─────────────────────────────────────────────────────────
354
+
355
+ function getDefinitions(name, contextFile) {
356
+ const entries = symbolsByName.get(name) || [];
357
+ if (entries.length === 0) return [];
358
+
359
+ // Rank by proximity to context file
360
+ const contextDir = contextFile ? path.dirname(contextFile) : '';
361
+ const contextExt = contextFile ? path.extname(contextFile) : '';
362
+
363
+ // Prefer non-variable definitions, but fall back to variables if that's all we have
364
+ const nonVariables = entries.filter(e => e.kind !== 'variable');
365
+ const candidates = nonVariables.length > 0 ? nonVariables : entries;
366
+
367
+ return candidates
368
+ .sort((a, b) => {
369
+ // Same file first
370
+ const aFile = a.file === contextFile ? 0 : 1;
371
+ const bFile = b.file === contextFile ? 0 : 1;
372
+ if (aFile !== bFile) return aFile - bFile;
373
+
374
+ // Same directory
375
+ const aDir = path.dirname(a.file) === contextDir ? 0 : 1;
376
+ const bDir = path.dirname(b.file) === contextDir ? 0 : 1;
377
+ if (aDir !== bDir) return aDir - bDir;
378
+
379
+ // Same extension
380
+ const aExt = path.extname(a.file) === contextExt ? 0 : 1;
381
+ const bExt = path.extname(b.file) === contextExt ? 0 : 1;
382
+ if (aExt !== bExt) return aExt - bExt;
383
+
384
+ // Prefer functions/classes over variables
385
+ const kindRank = { 'function': 0, 'method': 0, 'class': 1, 'struct': 1, 'interface': 1, 'type': 2 };
386
+ const aKind = kindRank[a.kind] ?? 3;
387
+ const bKind = kindRank[b.kind] ?? 3;
388
+ return aKind - bKind;
389
+ })
390
+ .slice(0, 20);
391
+ }
392
+
393
+ function getReferences(name, dir) {
394
+ if (!name || name.length < 2) return [];
395
+
396
+ // Use grep for textual references
397
+ const includeFlags = [];
398
+ for (const ext of SUPPORTED_EXTS) {
399
+ includeFlags.push(`--include=*${ext}`);
400
+ }
401
+
402
+ try {
403
+ const escapedName = name.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
404
+ const args = ['-rn', ...includeFlags, '--max-count=200', `\\b${escapedName}\\b`, '.'];
405
+ const output = execFileSync('grep', args, {
406
+ cwd: dir, encoding: 'utf8', timeout: 5000, maxBuffer: 5 * 1024 * 1024, stdio: ['pipe', 'pipe', 'pipe'],
407
+ });
408
+
409
+ const results = [];
410
+ for (const line of output.split('\n')) {
411
+ if (!line.trim()) continue;
412
+ const match = line.match(/^\.\/(.+?):(\d+):(.*)$/);
413
+ if (match) {
414
+ const [, file, lineNum, text] = match;
415
+ // Skip files in skip dirs
416
+ if (SKIP_DIRS.has(file.split('/')[0])) continue;
417
+ results.push({ file, line: parseInt(lineNum, 10), text: text.trim() });
418
+ }
419
+ }
420
+ return results.slice(0, 200);
421
+ } catch {
422
+ // grep returns exit code 1 when no matches — that's fine
423
+ return [];
424
+ }
425
+ }
426
+
427
+ function getCompletions(prefix, contextFile) {
428
+ if (!prefix || prefix.length < 1) return [];
429
+
430
+ const lowerPrefix = prefix.toLowerCase();
431
+ const results = [];
432
+ const contextDir = contextFile ? path.dirname(contextFile) : '';
433
+
434
+ for (const [name, entries] of symbolsByName) {
435
+ if (name.toLowerCase().startsWith(lowerPrefix)) {
436
+ // Pick the best entry for this name (slice to avoid mutating the index)
437
+ const best = entries.slice().sort((a, b) => {
438
+ if (a.file === contextFile && b.file !== contextFile) return -1;
439
+ if (b.file === contextFile && a.file !== contextFile) return 1;
440
+ if (path.dirname(a.file) === contextDir) return -1;
441
+ if (path.dirname(b.file) === contextDir) return 1;
442
+ return 0;
443
+ })[0];
444
+
445
+ results.push({
446
+ name: best.name,
447
+ kind: best.kind,
448
+ detail: best.signature || '',
449
+ file: best.file,
450
+ line: best.line,
451
+ });
452
+ }
453
+ }
454
+
455
+ // Sort: exact prefix match first, then shorter names, then alphabetical
456
+ results.sort((a, b) => {
457
+ const aExact = a.name.startsWith(prefix) ? 0 : 1;
458
+ const bExact = b.name.startsWith(prefix) ? 0 : 1;
459
+ if (aExact !== bExact) return aExact - bExact;
460
+ if (a.name.length !== b.name.length) return a.name.length - b.name.length;
461
+ return a.name.localeCompare(b.name);
462
+ });
463
+
464
+ return results.slice(0, 50);
465
+ }
466
+
467
+ function getHoverInfo(name, contextFile, line) {
468
+ const entries = symbolsByName.get(name);
469
+ if (!entries || entries.length === 0) return null;
470
+
471
+ // Best match: same file + closest line
472
+ let best = null;
473
+ let bestScore = Infinity;
474
+
475
+ for (const entry of entries) {
476
+ let score = 1000;
477
+ if (entry.file === contextFile) {
478
+ score = Math.abs(entry.line - (line || 0));
479
+ } else if (contextFile && path.dirname(entry.file) === path.dirname(contextFile)) {
480
+ score = 500;
481
+ }
482
+ if (score < bestScore) {
483
+ bestScore = score;
484
+ best = entry;
485
+ }
486
+ }
487
+
488
+ return best;
489
+ }
490
+
491
+ function getStatus() {
492
+ let symbolCount = 0;
493
+ for (const entries of symbolsByName.values()) {
494
+ symbolCount += entries.length;
495
+ }
496
+ return {
497
+ indexed: indexedAt !== null,
498
+ symbolCount,
499
+ fileCount: symbolsByFile.size,
500
+ ctagsAvailable,
501
+ lastIndexed: indexedAt,
502
+ };
503
+ }
504
+
505
+ // ─── File watcher ────────────────────────────────────────────────────────────
506
+
507
+ function startWatcher(dir, logFn) {
508
+ if (watcher) return;
509
+ const log = logFn || (() => {});
510
+
511
+ try {
512
+ watcher = fs.watch(dir, { recursive: true }, (eventType, filename) => {
513
+ if (!filename) return;
514
+
515
+ // Normalize path separators
516
+ const relPath = filename.replace(/\\/g, '/');
517
+
518
+ // Skip non-supported files and skip dirs
519
+ const parts = relPath.split('/');
520
+ for (const part of parts) {
521
+ if (SKIP_DIRS.has(part)) return;
522
+ }
523
+ if (!SUPPORTED_EXTS.has(path.extname(relPath).toLowerCase())) return;
524
+
525
+ // Debounce per file
526
+ if (watchDebounce.has(relPath)) {
527
+ clearTimeout(watchDebounce.get(relPath));
528
+ }
529
+ watchDebounce.set(relPath, setTimeout(() => {
530
+ watchDebounce.delete(relPath);
531
+ updateFileIndex(dir, relPath);
532
+ }, 500));
533
+ });
534
+
535
+ watcher.on('error', (err) => {
536
+ log(`File watcher error: ${err.message}`);
537
+ });
538
+ } catch (err) {
539
+ log(`Could not start file watcher: ${err.message}`);
540
+ }
541
+ }
542
+
543
+ function stopWatcher() {
544
+ if (watcher) {
545
+ watcher.close();
546
+ watcher = null;
547
+ }
548
+ for (const timeout of watchDebounce.values()) {
549
+ clearTimeout(timeout);
550
+ }
551
+ watchDebounce.clear();
552
+ }
553
+
554
+ // ─── Reference cache & lineage ───────────────────────────────────────────────
555
+
556
+ const CALLABLE_KINDS = new Set(['function', 'method', 'class', 'struct', 'interface', 'macro']);
557
+
558
+ function getCallersFromRefs(refs) {
559
+ // For each reference, find the enclosing function/method in that file
560
+ const callers = new Map(); // key -> caller entry (deduplicated)
561
+ for (const ref of refs) {
562
+ const fileSymbols = symbolsByFile.get(ref.file);
563
+ if (!fileSymbols) continue;
564
+
565
+ // Find the closest symbol defined before this reference line
566
+ let enclosing = null;
567
+ for (const sym of fileSymbols) {
568
+ if (!CALLABLE_KINDS.has(sym.kind)) continue;
569
+ if (sym.line <= ref.line) {
570
+ if (!enclosing || sym.line > enclosing.line) {
571
+ enclosing = sym;
572
+ }
573
+ }
574
+ }
575
+ if (enclosing) {
576
+ const key = `${enclosing.name}:${enclosing.file}:${enclosing.line}`;
577
+ if (!callers.has(key)) {
578
+ callers.set(key, { name: enclosing.name, kind: enclosing.kind, file: enclosing.file, line: enclosing.line });
579
+ }
580
+ }
581
+ }
582
+ return Array.from(callers.values());
583
+ }
584
+
585
+ function getCalleesFromBody(entry) {
586
+ if (!projectDir) return [];
587
+ const fileSymbols = symbolsByFile.get(entry.file);
588
+ if (!fileSymbols) return [];
589
+
590
+ // Find the function body boundaries: from entry.line to next symbol's line in same file
591
+ const sortedSyms = fileSymbols.slice().sort((a, b) => a.line - b.line);
592
+ let bodyEnd = Infinity;
593
+ for (const sym of sortedSyms) {
594
+ if (sym.line > entry.line && sym !== entry) {
595
+ bodyEnd = sym.line - 1;
596
+ break;
597
+ }
598
+ }
599
+
600
+ // Read the function body from disk
601
+ let bodyText;
602
+ try {
603
+ const absPath = path.join(projectDir, entry.file);
604
+ const content = fs.readFileSync(absPath, 'utf8');
605
+ const lines = content.split('\n');
606
+ const startLine = entry.line; // 1-indexed; skip the def line itself
607
+ const endLine = Math.min(bodyEnd, lines.length);
608
+ bodyText = lines.slice(startLine, endLine).join(' ');
609
+ } catch {
610
+ return [];
611
+ }
612
+
613
+ if (!bodyText) return [];
614
+
615
+ // Tokenize body into words and intersect with known symbols
616
+ const words = new Set(bodyText.match(/\b[a-zA-Z_]\w{2,}\b/g) || []);
617
+ const callees = [];
618
+ const seen = new Set();
619
+
620
+ for (const word of words) {
621
+ if (word === entry.name) continue; // skip self-references
622
+ if (seen.has(word)) continue;
623
+
624
+ const candidates = symbolsByName.get(word);
625
+ if (!candidates) continue;
626
+
627
+ // Only include callable kinds
628
+ const callable = candidates.find(c => CALLABLE_KINDS.has(c.kind));
629
+ if (callable) {
630
+ seen.add(word);
631
+ callees.push({ name: callable.name, kind: callable.kind, file: callable.file, line: callable.line });
632
+ }
633
+ }
634
+
635
+ return callees.slice(0, 10);
636
+ }
637
+
638
+ function buildRefEntry(name, dir) {
639
+ const refs = getReferences(name, dir);
640
+
641
+ // Summarize references by file
642
+ const byFileMap = new Map();
643
+ for (const ref of refs) {
644
+ if (!byFileMap.has(ref.file)) byFileMap.set(ref.file, []);
645
+ byFileMap.get(ref.file).push(ref.line);
646
+ }
647
+ const byFile = Array.from(byFileMap.entries())
648
+ .map(([file, lines]) => ({ file, lines }))
649
+ .sort((a, b) => b.lines.length - a.lines.length);
650
+
651
+ // Track reverse mapping for cache invalidation
652
+ for (const ref of refs) {
653
+ if (!fileToRefNames.has(ref.file)) fileToRefNames.set(ref.file, new Set());
654
+ fileToRefNames.get(ref.file).add(name);
655
+ }
656
+
657
+ // Find callers from reference locations
658
+ const callers = getCallersFromRefs(refs);
659
+
660
+ // Find callees from function body
661
+ const entries = symbolsByName.get(name) || [];
662
+ const defEntry = entries.find(e => CALLABLE_KINDS.has(e.kind)) || entries[0];
663
+ const callees = defEntry ? getCalleesFromBody(defEntry) : [];
664
+
665
+ const cacheEntry = {
666
+ refs: {
667
+ count: refs.length,
668
+ byFile: byFile.slice(0, 5),
669
+ truncated: byFile.length > 5,
670
+ },
671
+ callers: callers.slice(0, 5),
672
+ callees: callees.slice(0, 5),
673
+ builtAt: Date.now(),
674
+ };
675
+
676
+ referenceCache.set(name, cacheEntry);
677
+ return cacheEntry;
678
+ }
679
+
680
+ function buildCacheAsync(dir, logFn) {
681
+ const log = logFn || (() => {});
682
+ if (cacheBuilding) return;
683
+
684
+ referenceCache.clear();
685
+ fileToRefNames.clear();
686
+ cacheBuilding = true;
687
+
688
+ // Queue all callable symbols for background cache build
689
+ cacheQueue = [];
690
+ for (const [name, entries] of symbolsByName) {
691
+ if (entries.some(e => CALLABLE_KINDS.has(e.kind))) {
692
+ cacheQueue.push(name);
693
+ }
694
+ }
695
+
696
+ const total = cacheQueue.length;
697
+ log(`Building reference cache for ${total} symbols...`);
698
+
699
+ function processBatch() {
700
+ const batchSize = 10;
701
+ let processed = 0;
702
+ while (processed < batchSize && cacheQueue.length > 0) {
703
+ const name = cacheQueue.shift();
704
+ try {
705
+ buildRefEntry(name, dir);
706
+ } catch {
707
+ // skip failures
708
+ }
709
+ processed++;
710
+ }
711
+
712
+ if (cacheQueue.length > 0) {
713
+ setImmediate(processBatch);
714
+ } else {
715
+ cacheBuilding = false;
716
+ log(`Reference cache built: ${referenceCache.size} entries`);
717
+ }
718
+ }
719
+
720
+ setImmediate(processBatch);
721
+ }
722
+
723
+ function invalidateCacheForFile(relPath, dir) {
724
+ // Invalidate symbols defined in this file
725
+ const fileSymbols = symbolsByFile.get(relPath) || [];
726
+ const toRebuild = new Set();
727
+ for (const sym of fileSymbols) {
728
+ if (referenceCache.has(sym.name)) {
729
+ referenceCache.delete(sym.name);
730
+ toRebuild.add(sym.name);
731
+ }
732
+ }
733
+
734
+ // Invalidate symbols that had references in this file
735
+ const refNames = fileToRefNames.get(relPath);
736
+ if (refNames) {
737
+ for (const name of refNames) {
738
+ if (referenceCache.has(name)) {
739
+ referenceCache.delete(name);
740
+ toRebuild.add(name);
741
+ }
742
+ }
743
+ fileToRefNames.delete(relPath);
744
+ }
745
+
746
+ // Queue invalidated symbols for background rebuild
747
+ if (toRebuild.size > 0 && dir) {
748
+ for (const name of toRebuild) {
749
+ cacheQueue.push(name);
750
+ }
751
+ if (!cacheBuilding) {
752
+ cacheBuilding = true;
753
+ setImmediate(function rebuildBatch() {
754
+ let processed = 0;
755
+ while (processed < 10 && cacheQueue.length > 0) {
756
+ const name = cacheQueue.shift();
757
+ try { buildRefEntry(name, dir); } catch { /* skip */ }
758
+ processed++;
759
+ }
760
+ if (cacheQueue.length > 0) {
761
+ setImmediate(rebuildBatch);
762
+ } else {
763
+ cacheBuilding = false;
764
+ }
765
+ });
766
+ }
767
+ }
768
+ }
769
+
770
+ function getHoverEnriched(name, contextFile, line) {
771
+ const info = getHoverInfo(name, contextFile, line);
772
+ if (!info) return null;
773
+
774
+ let cached = referenceCache.get(name);
775
+
776
+ // Lazily build cache entry on first hover
777
+ if (!cached && projectDir) {
778
+ try {
779
+ cached = buildRefEntry(name, projectDir);
780
+ } catch {
781
+ // skip — will just return without enrichment
782
+ }
783
+ }
784
+
785
+ if (cached) {
786
+ return {
787
+ ...info,
788
+ references: cached.refs,
789
+ callers: cached.callers,
790
+ callees: cached.callees,
791
+ enrichAvailable: true,
792
+ };
793
+ }
794
+
795
+ return { ...info, enrichAvailable: false };
796
+ }
797
+
798
+ // ─── Exports ─────────────────────────────────────────────────────────────────
799
+
800
+ module.exports = {
801
+ buildIndex,
802
+ updateFileIndex,
803
+ getDefinitions,
804
+ getReferences,
805
+ getCompletions,
806
+ getHoverInfo,
807
+ getHoverEnriched,
808
+ buildCacheAsync,
809
+ getStatus,
810
+ startWatcher,
811
+ stopWatcher,
812
+ detectCtags,
813
+ };