@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,55 @@
1
+ #!/usr/bin/env node
2
+
3
+ 'use strict';
4
+
5
+ const { exec } = require('child_process');
6
+ const fs = require('fs');
7
+ const path = require('path');
8
+
9
+ const SHARDS_DIR = path.join(process.cwd(), '.shards');
10
+ const PORT_FILE = path.join(SHARDS_DIR, 'ui.port');
11
+
12
+ function getPort() {
13
+ try {
14
+ const raw = fs.readFileSync(PORT_FILE, 'utf8').trim();
15
+ // Support both JSON format (new) and plain number (old)
16
+ try {
17
+ const info = JSON.parse(raw);
18
+ return info.port;
19
+ } catch {
20
+ return parseInt(raw, 10);
21
+ }
22
+ } catch {
23
+ return 7842;
24
+ }
25
+ }
26
+
27
+ const port = getPort();
28
+
29
+ // Optional --hash argument: /shards-guide passes --hash guide so the UI
30
+ // opens the guide panel immediately on load.
31
+ let hash = '';
32
+ const args = process.argv.slice(2);
33
+ for (let i = 0; i < args.length; i++) {
34
+ if (args[i] === '--hash' && args[i + 1]) { hash = args[i + 1]; i++; }
35
+ }
36
+
37
+ const url = `http://localhost:${port}${hash ? '#' + hash : ''}`;
38
+
39
+ console.log(`Shards UI: ${url}`);
40
+
41
+ const platform = process.platform;
42
+ let command;
43
+ if (platform === 'darwin') {
44
+ command = `open "${url}"`;
45
+ } else if (platform === 'win32') {
46
+ command = `start "" "${url}"`;
47
+ } else {
48
+ command = `xdg-open "${url}"`;
49
+ }
50
+
51
+ exec(command, (err) => {
52
+ if (err) {
53
+ console.log(`Could not auto-open browser. Visit: ${url}`);
54
+ }
55
+ });
@@ -0,0 +1,42 @@
1
+ 'use strict';
2
+
3
+ // "Launcher" commands where the first argument is a subcommand that meaningfully
4
+ // narrows the permission's blast radius. Clicking Always Allow on `git status`
5
+ // should persist Bash(git status:*) — not Bash(git:*) — so the decision doesn't
6
+ // also authorize `git push` or `git reset --hard`.
7
+ const LAUNCHER_COMMANDS = new Set([
8
+ 'git', 'dbt', 'npm', 'pnpm', 'yarn',
9
+ 'pip', 'pip3', 'uv', 'poetry',
10
+ 'docker', 'kubectl', 'helm',
11
+ 'gh', 'aws', 'gcloud',
12
+ 'cargo', 'go', 'mvn', 'gradle',
13
+ 'make', 'just',
14
+ ]);
15
+
16
+ // Build the Bash permission pattern persisted when the user clicks Always Allow
17
+ // (or Always Deny) on a permission card. Returns a glob like Bash(cmd:*) so
18
+ // future invocations with different arguments don't re-prompt.
19
+ //
20
+ // Heuristic:
21
+ // - Single-token commands ("python3 foo.py") → Bash(python3:*)
22
+ // - Launcher + subcommand ("git status --short") → Bash(git status:*)
23
+ // - Absolute/relative path commands are preserved as-is in the prefix so that
24
+ // Bash(/usr/local/bin/dbt run:*) still disambiguates from a system dbt.
25
+ // - Empty / whitespace-only input falls back to the literal command, matching
26
+ // the pre-fix behavior so we don't silently broaden scope on garbage input.
27
+ function permissionPattern(command) {
28
+ if (typeof command !== 'string') return `Bash(${command})`;
29
+ const tokens = command.trim().split(/\s+/).filter(Boolean);
30
+ if (tokens.length === 0) return `Bash(${command})`;
31
+
32
+ const head = tokens[0];
33
+ const lastSlash = head.lastIndexOf('/');
34
+ const bareHead = lastSlash >= 0 ? head.slice(lastSlash + 1) : head;
35
+
36
+ if (LAUNCHER_COMMANDS.has(bareHead) && tokens.length > 1) {
37
+ return `Bash(${head} ${tokens[1]}:*)`;
38
+ }
39
+ return `Bash(${head}:*)`;
40
+ }
41
+
42
+ module.exports = { permissionPattern, LAUNCHER_COMMANDS };
@@ -0,0 +1,513 @@
1
+ #!/usr/bin/env node
2
+
3
+ 'use strict';
4
+
5
+ const http = require('http');
6
+ const fs = require('fs');
7
+ const path = require('path');
8
+ const { randomUUID } = require('crypto');
9
+
10
+ // Read-only allowlist shared with the gate hook. Used to short-circuit the
11
+ // HTTP round-trip to the shards-ui server for obvious read-only Bash ops.
12
+ // Graceful degradation: if the module isn't available (standalone deploy,
13
+ // install partially rolled back, etc.) we fall through to the normal POST.
14
+ let isAutoApprovable;
15
+ try {
16
+ ({ isAutoApprovable } = require('../hooks/gate-hook/auto-allowlist.js'));
17
+ } catch (_) {
18
+ isAutoApprovable = () => false;
19
+ }
20
+
21
+ // Claude Code's built-in read-only classifier (ls, cat, grep, read-only git
22
+ // forms, read-only tools). Mirrors what the CLI auto-approves in every mode
23
+ // so the UI doesn't surface permission cards for them. Same graceful
24
+ // degradation as above.
25
+ let isCcReadOnly;
26
+ try {
27
+ ({ isCcReadOnlyAutoApprovable: isCcReadOnly } = require('./cc-readonly.js'));
28
+ } catch (_) {
29
+ isCcReadOnly = () => false;
30
+ }
31
+
32
+ const SHARDS_DIR = path.join(process.cwd(), '.shards');
33
+ const PORT_FILE = path.join(SHARDS_DIR, 'ui.port');
34
+ const STATE_FILE = path.join(SHARDS_DIR, 'ui-state.json');
35
+ const QUEUE_FILE = path.join(SHARDS_DIR, 'event-queue.jsonl');
36
+
37
+ // P2: Queue constraints
38
+ const MAX_QUEUE_AGE_MS = 5 * 60 * 1000; // 5 minutes
39
+ const MAX_QUEUE_SIZE = 500;
40
+
41
+ const eventType = process.argv[2]; // user-prompt | stop | post-tool-use | session-end
42
+
43
+ // P2: Per-event UUID for server-side dedup. Previously a process-local
44
+ // integer counter — but every Claude Code hook invocation spawns a fresh
45
+ // relay process, so two concurrent hooks both started at seq=1 and the
46
+ // server's dedup set saw collisions. UUIDs are opaque on the server side
47
+ // (used only as Set keys in the dedup check) so this is a drop-in swap.
48
+ function nextSeq() { return randomUUID(); }
49
+
50
+ // P1: Read port and auth token from JSON port file
51
+ function getServerInfo() {
52
+ try {
53
+ const raw = fs.readFileSync(PORT_FILE, 'utf8').trim();
54
+ // Support both old (plain number) and new (JSON) formats
55
+ try {
56
+ const info = JSON.parse(raw);
57
+ return { port: info.port, token: info.token || null };
58
+ } catch {
59
+ return { port: parseInt(raw, 10), token: null };
60
+ }
61
+ } catch {
62
+ return null;
63
+ }
64
+ }
65
+
66
+ function getState() {
67
+ try {
68
+ return JSON.parse(fs.readFileSync(STATE_FILE, 'utf8'));
69
+ } catch {
70
+ return { currentAgent: 'syn', sessionId: null, messageCount: 0 };
71
+ }
72
+ }
73
+
74
+ function saveState(state) {
75
+ try {
76
+ fs.writeFileSync(STATE_FILE, JSON.stringify(state, null, 2));
77
+ } catch {}
78
+ }
79
+
80
+ // ─── P2: Event queue ─────────────────────────────────────────────────────────
81
+
82
+ function readQueue() {
83
+ try {
84
+ const raw = fs.readFileSync(QUEUE_FILE, 'utf8').trim();
85
+ if (!raw) return [];
86
+ const now = Date.now();
87
+ return raw.split('\n')
88
+ .map(line => { try { return JSON.parse(line); } catch { return null; } })
89
+ .filter(e => e !== null)
90
+ // Discard events older than MAX_QUEUE_AGE_MS
91
+ .filter(e => (now - e.timestamp) < MAX_QUEUE_AGE_MS);
92
+ } catch {
93
+ return [];
94
+ }
95
+ }
96
+
97
+ function writeQueue(events) {
98
+ try {
99
+ // Enforce max queue size — keep the newest events
100
+ const trimmed = events.slice(-MAX_QUEUE_SIZE);
101
+ const lines = trimmed.map(e => JSON.stringify(e)).join('\n');
102
+ fs.writeFileSync(QUEUE_FILE, lines ? lines + '\n' : '');
103
+ } catch {}
104
+ }
105
+
106
+ function appendToQueue(payload) {
107
+ const entry = { seq: nextSeq(), timestamp: Date.now(), payload };
108
+ try {
109
+ fs.appendFileSync(QUEUE_FILE, JSON.stringify(entry) + '\n');
110
+ } catch {}
111
+ return entry;
112
+ }
113
+
114
+ // P1 + P2: POST event with auth header, expect ack response
115
+ function postEvent(port, token, payload) {
116
+ return new Promise((resolve) => {
117
+ if (!port) { resolve(false); return; }
118
+ const body = JSON.stringify(payload);
119
+ const headers = {
120
+ 'Content-Type': 'application/json',
121
+ 'Content-Length': Buffer.byteLength(body),
122
+ };
123
+ if (token) {
124
+ headers['Authorization'] = `Bearer ${token}`;
125
+ }
126
+ const req = http.request({
127
+ hostname: '127.0.0.1',
128
+ port,
129
+ path: '/event',
130
+ method: 'POST',
131
+ headers,
132
+ timeout: 5000,
133
+ }, (res) => {
134
+ let data = '';
135
+ res.on('data', (chunk) => { data += chunk; });
136
+ res.on('end', () => {
137
+ if (res.statusCode === 200) {
138
+ try {
139
+ const result = JSON.parse(data);
140
+ resolve(result.ack === true);
141
+ return;
142
+ } catch {}
143
+ }
144
+ resolve(false);
145
+ });
146
+ });
147
+ req.on('error', () => resolve(false));
148
+ req.on('timeout', () => { req.destroy(); resolve(false); });
149
+ req.write(body);
150
+ req.end();
151
+ });
152
+ }
153
+
154
+ // ─── Pre-tool-use helpers ────────────────────────────────────────────────────
155
+
156
+ function sleep(ms) {
157
+ return new Promise(r => setTimeout(r, ms));
158
+ }
159
+
160
+ function postPermissionRequest(port, token, payload) {
161
+ return new Promise((resolve) => {
162
+ if (!port) { resolve(null); return; }
163
+ const body = JSON.stringify(payload);
164
+ const headers = {
165
+ 'Content-Type': 'application/json',
166
+ 'Content-Length': Buffer.byteLength(body),
167
+ };
168
+ if (token) {
169
+ headers['Authorization'] = `Bearer ${token}`;
170
+ }
171
+ const req = http.request({
172
+ hostname: '127.0.0.1',
173
+ port,
174
+ path: '/pre-tool-use',
175
+ method: 'POST',
176
+ headers,
177
+ timeout: 5000,
178
+ }, (res) => {
179
+ let data = '';
180
+ res.on('data', (chunk) => { data += chunk; });
181
+ res.on('end', () => {
182
+ try {
183
+ resolve(JSON.parse(data));
184
+ } catch {
185
+ resolve(null);
186
+ }
187
+ });
188
+ });
189
+ req.on('error', () => resolve(null));
190
+ req.on('timeout', () => { req.destroy(); resolve(null); });
191
+ req.write(body);
192
+ req.end();
193
+ });
194
+ }
195
+
196
+ function pollDecision(port, token, id) {
197
+ return new Promise((resolve) => {
198
+ const headers = {};
199
+ if (token) {
200
+ headers['Authorization'] = `Bearer ${token}`;
201
+ }
202
+ const req = http.request({
203
+ hostname: '127.0.0.1',
204
+ port,
205
+ path: `/chat/permission/${id}`,
206
+ method: 'GET',
207
+ headers,
208
+ timeout: 5000,
209
+ }, (res) => {
210
+ let data = '';
211
+ res.on('data', (chunk) => { data += chunk; });
212
+ res.on('end', () => {
213
+ try {
214
+ const result = JSON.parse(data);
215
+ resolve(result.status || 'pending');
216
+ } catch {
217
+ resolve('pending');
218
+ }
219
+ });
220
+ });
221
+ req.on('error', () => resolve('pending'));
222
+ req.on('timeout', () => { req.destroy(); resolve('pending'); });
223
+ req.end();
224
+ });
225
+ }
226
+
227
+ // Emit the structured PreToolUse hook output Claude Code expects to override
228
+ // its internal permission gate. Exit 0 for both allow and deny — exit 2 is
229
+ // reserved for hook *failures*, not user denials. Without this shape, a bare
230
+ // exit(0) doesn't actually override acceptEdits mode's internal deny of
231
+ // non-allowlisted Bash commands.
232
+ //
233
+ // updatedInput is an optional object the hook can use to rewrite the tool's
234
+ // parameters before execution (Claude Code PreToolUse contract). We use it to
235
+ // attach dangerouslyDisableSandbox=true on allowed Bash commands — see
236
+ // buildBashAllowInput below for why.
237
+ function emitDecision(decision, reason, updatedInput) {
238
+ const hookSpecificOutput = {
239
+ hookEventName: 'PreToolUse',
240
+ permissionDecision: decision,
241
+ permissionDecisionReason: reason || '',
242
+ };
243
+ if (updatedInput) hookSpecificOutput.updatedInput = updatedInput;
244
+ process.stdout.write(JSON.stringify({ hookSpecificOutput }));
245
+ process.exit(0);
246
+ }
247
+
248
+ // When the user (or their persisted allowlist) approves a Bash command, attach
249
+ // dangerouslyDisableSandbox=true so the command isn't then silently blocked by
250
+ // the OS-level sandbox (Seatbelt/bubblewrap) — which would force a second
251
+ // permission round-trip that the shards-ui flow doesn't surface cleanly. Scope
252
+ // is per-call: the flag rides along with this single tool invocation only.
253
+ function buildBashAllowInput(toolName, toolInput) {
254
+ if (toolName !== 'Bash') return null;
255
+ if (!toolInput || typeof toolInput !== 'object') return null;
256
+ if (toolInput.dangerouslyDisableSandbox === true) return null; // already set
257
+ return { ...toolInput, dangerouslyDisableSandbox: true };
258
+ }
259
+
260
+ async function handlePreToolUse(port, token, payload) {
261
+ const toolName = payload.tool_name || '';
262
+ const toolInput = payload.tool_input || {};
263
+ const command = toolInput.command || '';
264
+ const sessionId = payload.session_id || '';
265
+
266
+ // Fast path: read-only inspection ops auto-approve without an HTTP round-trip.
267
+ // The shards-ui server's settings allowlist would also approve these — this
268
+ // just shaves the ~5-50ms POST per call across long specialist sessions.
269
+ // Same authority as a server "allowed" response: deny rules still beat us
270
+ // (CC evaluates deny before any hook decision).
271
+ if (isAutoApprovable(toolName, toolInput) || isCcReadOnly(toolName, toolInput)) {
272
+ emitDecision('allow', 'Auto-approved by shards read-only allowlist',
273
+ buildBashAllowInput(toolName, toolInput));
274
+ }
275
+
276
+ // POST to server
277
+ const response = await postPermissionRequest(port, token, {
278
+ tool: toolName,
279
+ command: command,
280
+ sessionId: sessionId,
281
+ });
282
+
283
+ // Server unreachable — fall through to Claude Code's own permission rules
284
+ // (exit 0 without structured output). Matches previous fail-open posture.
285
+ if (!response) {
286
+ process.stderr.write('shards-ui: server unreachable, deferring to Claude Code permission rules\n');
287
+ process.exit(0);
288
+ }
289
+
290
+ // Fast paths
291
+ if (response.status === 'allowed') {
292
+ emitDecision('allow', 'Allowed by shards-ui permission rules', buildBashAllowInput(toolName, toolInput));
293
+ }
294
+ if (response.status === 'denied') {
295
+ emitDecision('deny', 'Denied by shards-ui permission rules');
296
+ }
297
+
298
+ // Pending — poll the UI until the user decides, OR until the poll deadline
299
+ // expires. The deadline is generous (default 10 minutes) so a user who steps
300
+ // away mid-call doesn't have their tool silently rejected. On expiry we exit
301
+ // 0 with no structured output — same posture as "server unreachable" above —
302
+ // which hands control back to Claude Code's built-in permission rules.
303
+ //
304
+ // Tunable via SHARDS_UI_PERMISSION_TIMEOUT_MS; the hard ceiling is the
305
+ // .claude/settings.json hook `timeout` (1800s today). Setting the env var to
306
+ // 0 restores the old wait-forever behavior.
307
+ const POLL_MS = 200;
308
+ const DEFAULT_TIMEOUT_MS = 10 * 60 * 1000;
309
+ const envTimeout = parseInt(process.env.SHARDS_UI_PERMISSION_TIMEOUT_MS, 10);
310
+ const timeoutMs = Number.isFinite(envTimeout) && envTimeout >= 0
311
+ ? envTimeout
312
+ : DEFAULT_TIMEOUT_MS;
313
+ const deadline = timeoutMs > 0 ? Date.now() + timeoutMs : null;
314
+
315
+ for (;;) {
316
+ await sleep(POLL_MS);
317
+ const decision = await pollDecision(port, token, response.id);
318
+ if (decision === 'allow') {
319
+ emitDecision('allow', 'Approved by user in Shards UI', buildBashAllowInput(toolName, toolInput));
320
+ }
321
+ if (decision === 'deny') {
322
+ emitDecision('deny', 'Denied by user in Shards UI');
323
+ }
324
+ if (deadline && Date.now() >= deadline) {
325
+ process.stderr.write(
326
+ `shards-ui: no user decision after ${Math.round(timeoutMs / 1000)}s — ` +
327
+ `deferring to Claude Code permission rules\n`
328
+ );
329
+ process.exit(0);
330
+ }
331
+ // 'pending' or 'not_found' — keep polling
332
+ }
333
+ }
334
+
335
+ function extractTextContent(content) {
336
+ if (typeof content === 'string') return content;
337
+ if (Array.isArray(content)) {
338
+ return content
339
+ .filter((b) => b && b.type === 'text')
340
+ .map((b) => b.text || '')
341
+ .join('');
342
+ }
343
+ return '';
344
+ }
345
+
346
+ async function main() {
347
+ const serverInfo = getServerInfo();
348
+ if (!serverInfo || !serverInfo.port) {
349
+ // For pre-tool-use, fail open if server info unavailable
350
+ if (eventType === 'pre-tool-use') process.exit(0);
351
+ return;
352
+ }
353
+
354
+ const { port, token } = serverInfo;
355
+
356
+ let rawData = '';
357
+ process.stdin.setEncoding('utf8');
358
+ for await (const chunk of process.stdin) {
359
+ rawData += chunk;
360
+ }
361
+
362
+ let payload;
363
+ try {
364
+ payload = JSON.parse(rawData);
365
+ } catch {
366
+ if (eventType === 'pre-tool-use') process.exit(0);
367
+ return;
368
+ }
369
+
370
+ // Pre-tool-use: blocking mode — handle separately and exit
371
+ if (eventType === 'pre-tool-use') {
372
+ await handlePreToolUse(port, token, payload);
373
+ return; // handlePreToolUse always calls process.exit
374
+ }
375
+
376
+ const state = getState();
377
+
378
+ // Claude Code injects session_id into every hook stdin payload (verified by
379
+ // the pre-tool-use branch above which already reads it). Forward it on every
380
+ // event we post so the server can target SSE delivery per browser session
381
+ // instead of misattributing to "most recently active session." Sessions
382
+ // started via the shards-ui server use --session-id <uuid>, so this value
383
+ // matches the SessionStore key 1:1 for UI-spawned sessions; sessions started
384
+ // outside the UI simply won't match any store (server falls through to the
385
+ // legacy broadcast path).
386
+ const ccSessionId = payload.session_id || null;
387
+
388
+ // ─── P2: Drain pending events from queue before processing current ───
389
+ // Note: queued events were captured with their *original* sessionId. Don't
390
+ // overwrite it with the current process's session_id — that would re-target
391
+ // an old session's event to the wrong browser. Fall through to the entry's
392
+ // stored sessionId, or null for legacy entries written before this change.
393
+ const pending = readQueue();
394
+ const stillPending = [];
395
+ for (const entry of pending) {
396
+ const acked = await postEvent(port, token, {
397
+ ...entry.payload,
398
+ seq: entry.seq,
399
+ sessionId: entry.payload && entry.payload.sessionId !== undefined
400
+ ? entry.payload.sessionId
401
+ : (entry.sessionId || null),
402
+ });
403
+ if (!acked) {
404
+ stillPending.push(entry);
405
+ }
406
+ }
407
+
408
+ // ─── Build current event payload ───
409
+ let currentPayload = null;
410
+
411
+ if (eventType === 'user-prompt') {
412
+ const transcript = payload.transcript || [];
413
+ const lastMsg = transcript[transcript.length - 1];
414
+ if (lastMsg && lastMsg.role === 'user') {
415
+ const content = extractTextContent(lastMsg.content);
416
+ currentPayload = {
417
+ eventType: 'user-message',
418
+ content,
419
+ agent: state.currentAgent,
420
+ };
421
+ }
422
+
423
+ } else if (eventType === 'stop') {
424
+ const transcript = payload.transcript || [];
425
+ const lastMsg = transcript[transcript.length - 1];
426
+ if (lastMsg && lastMsg.role === 'assistant') {
427
+ const content = extractTextContent(lastMsg.content);
428
+ if (content) {
429
+ currentPayload = {
430
+ eventType: 'agent-message',
431
+ content,
432
+ agent: state.currentAgent,
433
+ };
434
+ }
435
+ }
436
+
437
+ } else if (eventType === 'post-tool-use') {
438
+ const toolName = payload.tool_name || '';
439
+ const toolInput = payload.tool_input || {};
440
+
441
+ if (toolName === 'Task') {
442
+ const consultAgent = toolInput.subagent_type;
443
+ if (consultAgent) {
444
+ // Send both events — queue the first, send second as current
445
+ const evt1 = { eventType: 'agent-consulting', agent: consultAgent, sessionId: ccSessionId };
446
+ const entry1 = { seq: nextSeq(), timestamp: Date.now(), payload: evt1 };
447
+ const acked1 = await postEvent(port, token, { ...evt1, seq: entry1.seq });
448
+ if (!acked1) stillPending.push(entry1);
449
+
450
+ currentPayload = { eventType: 'event-log', text: `Consulting ${consultAgent}...`, sessionId: ccSessionId };
451
+ }
452
+
453
+ } else if (toolName === 'Read') {
454
+ const filePath = toolInput.file_path || '';
455
+ const agentMatch = filePath.match(/\.claude\/agents\/([^/]+)\.md$/);
456
+ if (agentMatch && state.currentAgent === 'syn') {
457
+ const newAgent = agentMatch[1];
458
+ const prevAgent = state.currentAgent;
459
+ state.currentAgent = newAgent;
460
+ saveState(state);
461
+
462
+ // Send activation events
463
+ const evt1 = { eventType: 'agent-activated', agent: newAgent, sessionId: ccSessionId };
464
+ const entry1 = { seq: nextSeq(), timestamp: Date.now(), payload: evt1 };
465
+ const acked1 = await postEvent(port, token, { ...evt1, seq: entry1.seq });
466
+ if (!acked1) stillPending.push(entry1);
467
+
468
+ const evt2 = { eventType: 'agent-changed', from: prevAgent, to: newAgent, sessionId: ccSessionId };
469
+ const entry2 = { seq: nextSeq(), timestamp: Date.now(), payload: evt2 };
470
+ const acked2 = await postEvent(port, token, { ...evt2, seq: entry2.seq });
471
+ if (!acked2) stillPending.push(entry2);
472
+
473
+ currentPayload = { eventType: 'event-log', text: `Persona transfer: ${prevAgent} -> ${newAgent}`, sessionId: ccSessionId };
474
+ }
475
+
476
+ } else if (toolName === 'Write' || toolName === 'Edit') {
477
+ const fp = toolInput.file_path || toolInput.path || 'file';
478
+ const evt1 = { eventType: 'event-log', text: `${toolName}: ${fp}`, sessionId: ccSessionId };
479
+ const entry1 = { seq: nextSeq(), timestamp: Date.now(), payload: evt1 };
480
+ const acked1 = await postEvent(port, token, { ...evt1, seq: entry1.seq });
481
+ if (!acked1) stillPending.push(entry1);
482
+
483
+ currentPayload = { eventType: 'file-touched', filePath: fp, sessionId: ccSessionId };
484
+
485
+ } else if (toolName === 'Bash') {
486
+ currentPayload = { eventType: 'event-log', text: `Bash: ${(toolInput.command || '').slice(0, 60)}`, sessionId: ccSessionId };
487
+ }
488
+
489
+ } else if (eventType === 'session-end') {
490
+ currentPayload = { eventType: 'session-end', sessionId: ccSessionId };
491
+ saveState({ currentAgent: 'syn', sessionId: null, messageCount: 0 });
492
+ }
493
+
494
+ // Tag user-prompt / stop payloads built earlier with the CC session_id too
495
+ // so the server can target SSE delivery per browser session.
496
+ if (currentPayload && currentPayload.sessionId === undefined) {
497
+ currentPayload.sessionId = ccSessionId;
498
+ }
499
+
500
+ // ─── P2: Send current event, queue on failure ───
501
+ if (currentPayload) {
502
+ const entry = { seq: nextSeq(), timestamp: Date.now(), payload: currentPayload };
503
+ const acked = await postEvent(port, token, { ...currentPayload, seq: entry.seq });
504
+ if (!acked) {
505
+ stillPending.push(entry);
506
+ }
507
+ }
508
+
509
+ // Write remaining unacked events back to queue
510
+ writeQueue(stillPending);
511
+ }
512
+
513
+ main().catch(function(err) { process.stderr.write('shards-ui relay: ' + (err && err.message || err) + '\n'); });