@rubytech/create-sitedesk-code 0.1.529 → 0.1.531

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (341) hide show
  1. package/dist/index.js +13 -0
  2. package/package.json +1 -1
  3. package/payload/platform/lib/graph-write/dist/index.d.ts.map +1 -1
  4. package/payload/platform/lib/graph-write/dist/index.js +4 -0
  5. package/payload/platform/lib/graph-write/dist/index.js.map +1 -1
  6. package/payload/platform/lib/graph-write/src/index.ts +4 -0
  7. package/payload/platform/lib/learning-constants/dist/index.d.ts +35 -0
  8. package/payload/platform/lib/learning-constants/dist/index.d.ts.map +1 -0
  9. package/payload/platform/lib/learning-constants/dist/index.js +50 -0
  10. package/payload/platform/lib/learning-constants/dist/index.js.map +1 -0
  11. package/payload/platform/lib/learning-constants/package.json +7 -0
  12. package/payload/platform/lib/learning-constants/src/index.test.ts +47 -0
  13. package/payload/platform/lib/learning-constants/src/index.ts +57 -0
  14. package/payload/platform/lib/learning-constants/tsconfig.json +9 -0
  15. package/payload/platform/lib/routine-templates/dist/index.d.ts +19 -3
  16. package/payload/platform/lib/routine-templates/dist/index.d.ts.map +1 -1
  17. package/payload/platform/lib/routine-templates/dist/index.js +22 -4
  18. package/payload/platform/lib/routine-templates/dist/index.js.map +1 -1
  19. package/payload/platform/lib/routine-templates/dist/roster.d.ts +19 -6
  20. package/payload/platform/lib/routine-templates/dist/roster.d.ts.map +1 -1
  21. package/payload/platform/lib/routine-templates/dist/roster.js +127 -17
  22. package/payload/platform/lib/routine-templates/dist/roster.js.map +1 -1
  23. package/payload/platform/lib/routine-templates/src/__tests__/roster.test.ts +46 -3
  24. package/payload/platform/lib/routine-templates/src/__tests__/seed.test.ts +52 -10
  25. package/payload/platform/lib/routine-templates/src/index.ts +30 -4
  26. package/payload/platform/lib/routine-templates/src/roster.ts +147 -17
  27. package/payload/platform/neo4j/schema.cypher +24 -0
  28. package/payload/platform/package.json +1 -1
  29. package/payload/platform/plugins/admin/.claude-plugin/plugin.json +1 -1
  30. package/payload/platform/plugins/admin/PLUGIN.md +1 -1
  31. package/payload/platform/plugins/admin/mcp/dist/index.js +2 -2
  32. package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
  33. package/payload/platform/plugins/admin/skills/insight/SKILL.md +1 -1
  34. package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +64 -12
  35. package/payload/platform/plugins/admin/skills/whats-new/SKILL.md +13 -0
  36. package/payload/platform/plugins/docs/references/admin-ui.md +6 -2
  37. package/payload/platform/plugins/docs/references/linkedin-extension.md +18 -9
  38. package/payload/platform/plugins/docs/references/session-retrospective.md +39 -0
  39. package/payload/platform/plugins/linkedin-extension/.claude-plugin/plugin.json +1 -1
  40. package/payload/platform/plugins/linkedin-extension/PLUGIN.md +7 -10
  41. package/payload/platform/plugins/linkedin-extension/extension/README.md +20 -17
  42. package/payload/platform/plugins/linkedin-extension/extension/background/sw.js +96 -13
  43. package/payload/platform/plugins/linkedin-extension/extension/manifest.json +3 -18
  44. package/payload/platform/plugins/linkedin-extension/extension/options/options.html +2 -2
  45. package/payload/platform/plugins/linkedin-extension/extension/options/options.js +1 -1
  46. package/payload/platform/plugins/memory/.claude-plugin/plugin.json +1 -1
  47. package/payload/platform/plugins/memory/PLUGIN.md +15 -1
  48. package/payload/platform/plugins/memory/mcp/dist/index.js +169 -0
  49. package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
  50. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/session-jsonl.test.d.ts +2 -0
  51. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/session-jsonl.test.d.ts.map +1 -0
  52. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/session-jsonl.test.js +95 -0
  53. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/session-jsonl.test.js.map +1 -0
  54. package/payload/platform/plugins/memory/mcp/dist/lib/session-jsonl.d.ts +60 -0
  55. package/payload/platform/plugins/memory/mcp/dist/lib/session-jsonl.d.ts.map +1 -0
  56. package/payload/platform/plugins/memory/mcp/dist/lib/session-jsonl.js +153 -0
  57. package/payload/platform/plugins/memory/mcp/dist/lib/session-jsonl.js.map +1 -0
  58. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/cross-account.test.js +6 -4
  59. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/cross-account.test.js.map +1 -1
  60. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/learnings-derive.test.d.ts +2 -0
  61. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/learnings-derive.test.d.ts.map +1 -0
  62. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/learnings-derive.test.js +160 -0
  63. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/learnings-derive.test.js.map +1 -0
  64. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/learnings-recall.test.d.ts +2 -0
  65. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/learnings-recall.test.d.ts.map +1 -0
  66. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/learnings-recall.test.js +64 -0
  67. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/learnings-recall.test.js.map +1 -0
  68. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/learnings-scan.test.d.ts +2 -0
  69. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/learnings-scan.test.d.ts.map +1 -0
  70. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/learnings-scan.test.js +78 -0
  71. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/learnings-scan.test.js.map +1 -0
  72. package/payload/platform/plugins/memory/mcp/dist/tools/learnings-derive.d.ts +41 -0
  73. package/payload/platform/plugins/memory/mcp/dist/tools/learnings-derive.d.ts.map +1 -0
  74. package/payload/platform/plugins/memory/mcp/dist/tools/learnings-derive.js +225 -0
  75. package/payload/platform/plugins/memory/mcp/dist/tools/learnings-derive.js.map +1 -0
  76. package/payload/platform/plugins/memory/mcp/dist/tools/learnings-recall.d.ts +31 -0
  77. package/payload/platform/plugins/memory/mcp/dist/tools/learnings-recall.d.ts.map +1 -0
  78. package/payload/platform/plugins/memory/mcp/dist/tools/learnings-recall.js +67 -0
  79. package/payload/platform/plugins/memory/mcp/dist/tools/learnings-recall.js.map +1 -0
  80. package/payload/platform/plugins/memory/mcp/dist/tools/learnings-scan.d.ts +40 -0
  81. package/payload/platform/plugins/memory/mcp/dist/tools/learnings-scan.d.ts.map +1 -0
  82. package/payload/platform/plugins/memory/mcp/dist/tools/learnings-scan.js +55 -0
  83. package/payload/platform/plugins/memory/mcp/dist/tools/learnings-scan.js.map +1 -0
  84. package/payload/platform/plugins/memory/references/schema-base.md +3 -0
  85. package/payload/platform/plugins/memory/skills/learnings-recall/SKILL.md +27 -0
  86. package/payload/platform/plugins/scheduling/PLUGIN.md +2 -0
  87. package/payload/platform/plugins/scheduling/mcp/dist/index.js +5 -0
  88. package/payload/platform/plugins/scheduling/mcp/dist/index.js.map +1 -1
  89. package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/normalise-start-date.test.d.ts +2 -0
  90. package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/normalise-start-date.test.d.ts.map +1 -0
  91. package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/normalise-start-date.test.js +100 -0
  92. package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/normalise-start-date.test.js.map +1 -0
  93. package/payload/platform/plugins/scheduling/mcp/dist/lib/dispatcher-env.d.ts +36 -0
  94. package/payload/platform/plugins/scheduling/mcp/dist/lib/dispatcher-env.d.ts.map +1 -0
  95. package/payload/platform/plugins/scheduling/mcp/dist/lib/dispatcher-env.js +82 -0
  96. package/payload/platform/plugins/scheduling/mcp/dist/lib/dispatcher-env.js.map +1 -0
  97. package/payload/platform/plugins/scheduling/mcp/dist/lib/time-format.d.ts +31 -0
  98. package/payload/platform/plugins/scheduling/mcp/dist/lib/time-format.d.ts.map +1 -1
  99. package/payload/platform/plugins/scheduling/mcp/dist/lib/time-format.js +99 -0
  100. package/payload/platform/plugins/scheduling/mcp/dist/lib/time-format.js.map +1 -1
  101. package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/agent-turn-dispatch.test.js +12 -12
  102. package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/agent-turn-dispatch.test.js.map +1 -1
  103. package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/converge-startdate-utc.test.d.ts +2 -0
  104. package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/converge-startdate-utc.test.d.ts.map +1 -0
  105. package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/converge-startdate-utc.test.js +79 -0
  106. package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/converge-startdate-utc.test.js.map +1 -0
  107. package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/dispatch-lateness.test.d.ts +2 -0
  108. package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/dispatch-lateness.test.d.ts.map +1 -0
  109. package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/dispatch-lateness.test.js +23 -0
  110. package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/dispatch-lateness.test.js.map +1 -0
  111. package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/routine-roster-audit.test.js +61 -1
  112. package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/routine-roster-audit.test.js.map +1 -1
  113. package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.d.ts +33 -1
  114. package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.d.ts.map +1 -1
  115. package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.js +96 -7
  116. package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.js.map +1 -1
  117. package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.js +21 -69
  118. package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.js.map +1 -1
  119. package/payload/platform/plugins/scheduling/mcp/dist/scripts/converge-startdate-utc.d.ts +24 -0
  120. package/payload/platform/plugins/scheduling/mcp/dist/scripts/converge-startdate-utc.d.ts.map +1 -0
  121. package/payload/platform/plugins/scheduling/mcp/dist/scripts/converge-startdate-utc.js +87 -0
  122. package/payload/platform/plugins/scheduling/mcp/dist/scripts/converge-startdate-utc.js.map +1 -0
  123. package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-event-startdate.test.d.ts +2 -0
  124. package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-event-startdate.test.d.ts.map +1 -0
  125. package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-event-startdate.test.js +123 -0
  126. package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-event-startdate.test.js.map +1 -0
  127. package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-update-startdate.test.d.ts +2 -0
  128. package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-update-startdate.test.d.ts.map +1 -0
  129. package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-update-startdate.test.js +71 -0
  130. package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-update-startdate.test.js.map +1 -0
  131. package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-update-status.test.js +14 -3
  132. package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-update-status.test.js.map +1 -1
  133. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-event.d.ts +9 -0
  134. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-event.d.ts.map +1 -1
  135. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-event.js +19 -3
  136. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-event.js.map +1 -1
  137. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-update.d.ts.map +1 -1
  138. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-update.js +24 -9
  139. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-update.js.map +1 -1
  140. package/payload/platform/plugins/whatsapp/mcp/dist/index.js +4 -4
  141. package/payload/platform/plugins/whatsapp/mcp/dist/index.js.map +1 -1
  142. package/payload/platform/plugins/whatsapp/references/channels-whatsapp.md +3 -3
  143. package/payload/platform/plugins/whatsapp/skills/connect-whatsapp/SKILL.md +6 -2
  144. package/payload/platform/plugins/whatsapp/skills/manage-whatsapp-config/SKILL.md +5 -1
  145. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.d.ts.map +1 -1
  146. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js +3 -0
  147. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js.map +1 -1
  148. package/payload/platform/services/claude-session-manager/dist/learning-index.d.ts +28 -0
  149. package/payload/platform/services/claude-session-manager/dist/learning-index.d.ts.map +1 -0
  150. package/payload/platform/services/claude-session-manager/dist/learning-index.js +70 -0
  151. package/payload/platform/services/claude-session-manager/dist/learning-index.js.map +1 -0
  152. package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts.map +1 -1
  153. package/payload/platform/services/claude-session-manager/dist/pty-spawner.js +18 -0
  154. package/payload/platform/services/claude-session-manager/dist/pty-spawner.js.map +1 -1
  155. package/payload/platform/services/claude-session-manager/dist/system-prompt.d.ts +6 -0
  156. package/payload/platform/services/claude-session-manager/dist/system-prompt.d.ts.map +1 -1
  157. package/payload/platform/services/claude-session-manager/dist/system-prompt.js +17 -0
  158. package/payload/platform/services/claude-session-manager/dist/system-prompt.js.map +1 -1
  159. package/payload/platform/templates/specialists/agents/librarian.md +1 -1
  160. package/payload/server/{chunk-UTIHI6KV.js → chunk-SVB5NZ64.js} +53 -42
  161. package/payload/server/{manager-B4LRDZKC.js → manager-4Q3DTLXO.js} +5 -1
  162. package/payload/server/package.json +1 -1
  163. package/payload/server/public/activity.html +5 -5
  164. package/payload/server/public/agents.html +4 -4
  165. package/payload/server/public/assets/{AdminLoginScreens-zfexKfbT.js → AdminLoginScreens-7Czw3MAC.js} +1 -1
  166. package/payload/server/public/assets/AdminLoginScreens-7Czw3MAC.js.br +0 -0
  167. package/payload/server/public/assets/AdminLoginScreens-7Czw3MAC.js.gz +0 -0
  168. package/payload/server/public/assets/{AdminShell-Cbk0TL1B.js → AdminShell-D5GApZ_n.js} +1 -1
  169. package/payload/server/public/assets/AdminShell-D5GApZ_n.js.br +0 -0
  170. package/payload/server/public/assets/AdminShell-D5GApZ_n.js.gz +0 -0
  171. package/payload/server/public/assets/{CdpScreencastSurface-CLSQHh4e.js → CdpScreencastSurface-BbekDUFw.js} +1 -1
  172. package/payload/server/public/assets/CdpScreencastSurface-BbekDUFw.js.br +0 -0
  173. package/payload/server/public/assets/CdpScreencastSurface-BbekDUFw.js.gz +0 -0
  174. package/payload/server/public/assets/{activity-u275Oc-u.js → activity-ClI-RgJu.js} +1 -1
  175. package/payload/server/public/assets/activity-ClI-RgJu.js.br +0 -0
  176. package/payload/server/public/assets/activity-ClI-RgJu.js.gz +0 -0
  177. package/payload/server/public/assets/{admin-Du1nR_hP.js → admin-svtCmBPk.js} +1 -1
  178. package/payload/server/public/assets/admin-svtCmBPk.js.br +0 -0
  179. package/payload/server/public/assets/admin-svtCmBPk.js.gz +0 -0
  180. package/payload/server/public/assets/{agents-DJTxRLLU.js → agents-BO8YBj8d.js} +1 -1
  181. package/payload/server/public/assets/agents-BO8YBj8d.js.br +0 -0
  182. package/payload/server/public/assets/agents-BO8YBj8d.js.gz +0 -0
  183. package/payload/server/public/assets/{browser-Bft6zVkX.js → browser-Bj8oTG5R.js} +1 -1
  184. package/payload/server/public/assets/browser-Bj8oTG5R.js.br +0 -0
  185. package/payload/server/public/assets/browser-Bj8oTG5R.js.gz +0 -0
  186. package/payload/server/public/assets/{calendar-Ct-DCCqY.js → calendar-CrkSY8U7.js} +1 -1
  187. package/payload/server/public/assets/calendar-CrkSY8U7.js.br +0 -0
  188. package/payload/server/public/assets/calendar-CrkSY8U7.js.gz +0 -0
  189. package/payload/server/public/assets/chat-Bvxoni2e.js +1 -0
  190. package/payload/server/public/assets/chat-Bvxoni2e.js.br +0 -0
  191. package/payload/server/public/assets/chat-Bvxoni2e.js.gz +0 -0
  192. package/payload/server/public/assets/chevron-left-CdUzxzeB.js +1 -0
  193. package/payload/server/public/assets/chevron-left-CdUzxzeB.js.br +0 -0
  194. package/payload/server/public/assets/chevron-right-CKGwd-M0.js +1 -0
  195. package/payload/server/public/assets/chevron-right-CKGwd-M0.js.br +0 -0
  196. package/payload/server/public/assets/clock-Cf8Oe9qi.js +1 -0
  197. package/payload/server/public/assets/clock-Cf8Oe9qi.js.br +0 -0
  198. package/payload/server/public/assets/clock-Cf8Oe9qi.js.gz +0 -0
  199. package/payload/server/public/assets/data-DF0Pstdp.js +1 -0
  200. package/payload/server/public/assets/data-DF0Pstdp.js.br +1 -0
  201. package/payload/server/public/assets/data-DF0Pstdp.js.gz +0 -0
  202. package/payload/server/public/assets/{file-download-C_fSe4dm.js → file-download-Di_s0_4w.js} +1 -1
  203. package/payload/server/public/assets/file-download-Di_s0_4w.js.br +0 -0
  204. package/payload/server/public/assets/file-download-Di_s0_4w.js.gz +0 -0
  205. package/payload/server/public/assets/{file-text-D7GbEcqj.js → file-text-CP1KIrJV.js} +1 -1
  206. package/payload/server/public/assets/file-text-CP1KIrJV.js.br +1 -0
  207. package/payload/server/public/assets/file-text-CP1KIrJV.js.gz +0 -0
  208. package/payload/server/public/assets/{graph-yl5qU1kO.js → graph-BCMscnCV.js} +1 -1
  209. package/payload/server/public/assets/graph-BCMscnCV.js.br +0 -0
  210. package/payload/server/public/assets/graph-BCMscnCV.js.gz +0 -0
  211. package/payload/server/public/assets/{graph-labels-Dlcb6cW7.js → graph-labels-CgP17xHK.js} +1 -1
  212. package/payload/server/public/assets/graph-labels-CgP17xHK.js.br +0 -0
  213. package/payload/server/public/assets/graph-labels-CgP17xHK.js.gz +0 -0
  214. package/payload/server/public/assets/{maximize-2-BS689r4W.js → maximize-2-DkQzDv-g.js} +1 -1
  215. package/payload/server/public/assets/maximize-2-DkQzDv-g.js.br +0 -0
  216. package/payload/server/public/assets/maximize-2-DkQzDv-g.js.gz +0 -0
  217. package/payload/server/public/assets/{operator-CvapnpIW.js → operator-CLbCar9e.js} +1 -1
  218. package/payload/server/public/assets/operator-CLbCar9e.js.br +0 -0
  219. package/payload/server/public/assets/operator-CLbCar9e.js.gz +0 -0
  220. package/payload/server/public/assets/{page-DWkUH4Z_.js → page-CNJl3tWT.js} +1 -1
  221. package/payload/server/public/assets/page-CNJl3tWT.js.br +0 -0
  222. package/payload/server/public/assets/page-CNJl3tWT.js.gz +0 -0
  223. package/payload/server/public/assets/{page-987y4JbQ.js → page-CPVUAwb8.js} +1 -1
  224. package/payload/server/public/assets/page-CPVUAwb8.js.br +0 -0
  225. package/payload/server/public/assets/page-CPVUAwb8.js.gz +0 -0
  226. package/payload/server/public/assets/{public-D5pi-VFn.js → public-DQea3Ybz.js} +1 -1
  227. package/payload/server/public/assets/public-DQea3Ybz.js.br +0 -0
  228. package/payload/server/public/assets/public-DQea3Ybz.js.gz +0 -0
  229. package/payload/server/public/assets/{rotate-ccw-zNxnK36R.js → rotate-ccw-DPw0vXC0.js} +1 -1
  230. package/payload/server/public/assets/rotate-ccw-DPw0vXC0.js.br +0 -0
  231. package/payload/server/public/assets/rotate-ccw-DPw0vXC0.js.gz +0 -0
  232. package/payload/server/public/assets/{routines-mZzrGA5y.js → routines-CwiiYpfK.js} +2 -2
  233. package/payload/server/public/assets/routines-CwiiYpfK.js.br +0 -0
  234. package/payload/server/public/assets/routines-CwiiYpfK.js.gz +0 -0
  235. package/payload/server/public/assets/{skills-5A8PockT.js → skills-0FOjKUM-.js} +1 -1
  236. package/payload/server/public/assets/skills-0FOjKUM-.js.br +0 -0
  237. package/payload/server/public/assets/skills-0FOjKUM-.js.gz +0 -0
  238. package/payload/server/public/assets/{tasks-B1_2wc6L.js → tasks-BUVsPEGm.js} +1 -1
  239. package/payload/server/public/assets/tasks-BUVsPEGm.js.br +0 -0
  240. package/payload/server/public/assets/tasks-BUVsPEGm.js.gz +0 -0
  241. package/payload/server/public/assets/{time-entry-format-CJ2FSSQt.js → time-entry-format-B6fX_19a.js} +1 -1
  242. package/payload/server/public/assets/time-entry-format-B6fX_19a.js.br +0 -0
  243. package/payload/server/public/assets/time-entry-format-B6fX_19a.js.gz +0 -0
  244. package/payload/server/public/assets/{triangle-alert-CedsrgME.js → triangle-alert-vAaSDhVq.js} +1 -1
  245. package/payload/server/public/assets/triangle-alert-vAaSDhVq.js.br +0 -0
  246. package/payload/server/public/assets/triangle-alert-vAaSDhVq.js.gz +0 -0
  247. package/payload/server/public/assets/{useCopyFeedback-zjZZUC2-.js → useCopyFeedback-BvIRgs7W.js} +1 -1
  248. package/payload/server/public/assets/useCopyFeedback-BvIRgs7W.js.br +0 -0
  249. package/payload/server/public/assets/useCopyFeedback-BvIRgs7W.js.gz +0 -0
  250. package/payload/server/public/assets/{useSubAccountSwitcher-72THldvm.css → useSubAccountSwitcher-DM5Y9eio.css} +1 -1
  251. package/payload/server/public/assets/useSubAccountSwitcher-DM5Y9eio.css.br +0 -0
  252. package/payload/server/public/assets/{useSubAccountSwitcher-72THldvm.css.gz → useSubAccountSwitcher-DM5Y9eio.css.gz} +0 -0
  253. package/payload/server/public/assets/{useVoiceRecorder-CJecnefX.js → useVoiceRecorder-CiDOh8PG.js} +1 -1
  254. package/payload/server/public/assets/useVoiceRecorder-CiDOh8PG.js.br +0 -0
  255. package/payload/server/public/assets/useVoiceRecorder-CiDOh8PG.js.gz +0 -0
  256. package/payload/server/public/assets/{wrench-D8BH20W8.js → wrench-BNBtwT2p.js} +1 -1
  257. package/payload/server/public/assets/wrench-BNBtwT2p.js.br +0 -0
  258. package/payload/server/public/assets/wrench-BNBtwT2p.js.gz +0 -0
  259. package/payload/server/public/browser.html +5 -5
  260. package/payload/server/public/calendar.html +7 -7
  261. package/payload/server/public/chat.html +13 -13
  262. package/payload/server/public/data.html +12 -12
  263. package/payload/server/public/graph.html +9 -9
  264. package/payload/server/public/index.html +16 -16
  265. package/payload/server/public/operator.html +15 -15
  266. package/payload/server/public/public.html +13 -13
  267. package/payload/server/public/routines.html +7 -7
  268. package/payload/server/public/skills.html +5 -5
  269. package/payload/server/public/tasks.html +6 -6
  270. package/payload/server/server.js +73 -19
  271. package/payload/platform/plugins/linkedin-extension/extension/assets/pill.css +0 -52
  272. package/payload/platform/plugins/linkedin-extension/extension/content/profile.js +0 -100
  273. package/payload/platform/plugins/linkedin-extension/extension/content/thread.js +0 -102
  274. package/payload/server/public/assets/AdminLoginScreens-zfexKfbT.js.br +0 -0
  275. package/payload/server/public/assets/AdminLoginScreens-zfexKfbT.js.gz +0 -0
  276. package/payload/server/public/assets/AdminShell-Cbk0TL1B.js.br +0 -0
  277. package/payload/server/public/assets/AdminShell-Cbk0TL1B.js.gz +0 -0
  278. package/payload/server/public/assets/CdpScreencastSurface-CLSQHh4e.js.br +0 -0
  279. package/payload/server/public/assets/CdpScreencastSurface-CLSQHh4e.js.gz +0 -0
  280. package/payload/server/public/assets/activity-u275Oc-u.js.br +0 -0
  281. package/payload/server/public/assets/activity-u275Oc-u.js.gz +0 -0
  282. package/payload/server/public/assets/admin-Du1nR_hP.js.br +0 -0
  283. package/payload/server/public/assets/admin-Du1nR_hP.js.gz +0 -0
  284. package/payload/server/public/assets/agents-DJTxRLLU.js.br +0 -0
  285. package/payload/server/public/assets/agents-DJTxRLLU.js.gz +0 -0
  286. package/payload/server/public/assets/browser-Bft6zVkX.js.br +0 -0
  287. package/payload/server/public/assets/browser-Bft6zVkX.js.gz +0 -0
  288. package/payload/server/public/assets/calendar-Ct-DCCqY.js.br +0 -0
  289. package/payload/server/public/assets/calendar-Ct-DCCqY.js.gz +0 -0
  290. package/payload/server/public/assets/chat-pqasbAg8.js +0 -1
  291. package/payload/server/public/assets/chat-pqasbAg8.js.br +0 -0
  292. package/payload/server/public/assets/chat-pqasbAg8.js.gz +0 -0
  293. package/payload/server/public/assets/chevron-left-C8LTc7lb.js +0 -1
  294. package/payload/server/public/assets/chevron-right-Lz9t7Hed.js +0 -1
  295. package/payload/server/public/assets/chevron-right-Lz9t7Hed.js.br +0 -0
  296. package/payload/server/public/assets/clock-D6QQFHwJ.js +0 -1
  297. package/payload/server/public/assets/clock-D6QQFHwJ.js.br +0 -0
  298. package/payload/server/public/assets/clock-D6QQFHwJ.js.gz +0 -0
  299. package/payload/server/public/assets/data-B1JJ3Y1T.js +0 -1
  300. package/payload/server/public/assets/data-B1JJ3Y1T.js.br +0 -0
  301. package/payload/server/public/assets/data-B1JJ3Y1T.js.gz +0 -0
  302. package/payload/server/public/assets/file-download-C_fSe4dm.js.br +0 -0
  303. package/payload/server/public/assets/file-download-C_fSe4dm.js.gz +0 -0
  304. package/payload/server/public/assets/file-text-D7GbEcqj.js.br +0 -0
  305. package/payload/server/public/assets/file-text-D7GbEcqj.js.gz +0 -0
  306. package/payload/server/public/assets/graph-labels-Dlcb6cW7.js.br +0 -0
  307. package/payload/server/public/assets/graph-labels-Dlcb6cW7.js.gz +0 -0
  308. package/payload/server/public/assets/graph-yl5qU1kO.js.br +0 -0
  309. package/payload/server/public/assets/graph-yl5qU1kO.js.gz +0 -0
  310. package/payload/server/public/assets/maximize-2-BS689r4W.js.br +0 -0
  311. package/payload/server/public/assets/maximize-2-BS689r4W.js.gz +0 -0
  312. package/payload/server/public/assets/operator-CvapnpIW.js.br +0 -0
  313. package/payload/server/public/assets/operator-CvapnpIW.js.gz +0 -0
  314. package/payload/server/public/assets/page-987y4JbQ.js.br +0 -0
  315. package/payload/server/public/assets/page-987y4JbQ.js.gz +0 -0
  316. package/payload/server/public/assets/page-DWkUH4Z_.js.br +0 -0
  317. package/payload/server/public/assets/page-DWkUH4Z_.js.gz +0 -0
  318. package/payload/server/public/assets/public-D5pi-VFn.js.br +0 -0
  319. package/payload/server/public/assets/public-D5pi-VFn.js.gz +0 -0
  320. package/payload/server/public/assets/rotate-ccw-zNxnK36R.js.br +0 -0
  321. package/payload/server/public/assets/rotate-ccw-zNxnK36R.js.gz +0 -0
  322. package/payload/server/public/assets/routines-mZzrGA5y.js.br +0 -0
  323. package/payload/server/public/assets/routines-mZzrGA5y.js.gz +0 -0
  324. package/payload/server/public/assets/skills-5A8PockT.js.br +0 -0
  325. package/payload/server/public/assets/skills-5A8PockT.js.gz +0 -0
  326. package/payload/server/public/assets/tasks-B1_2wc6L.js.br +0 -0
  327. package/payload/server/public/assets/tasks-B1_2wc6L.js.gz +0 -0
  328. package/payload/server/public/assets/time-entry-format-CJ2FSSQt.js.br +0 -0
  329. package/payload/server/public/assets/time-entry-format-CJ2FSSQt.js.gz +0 -0
  330. package/payload/server/public/assets/triangle-alert-CedsrgME.js.br +0 -0
  331. package/payload/server/public/assets/triangle-alert-CedsrgME.js.gz +0 -0
  332. package/payload/server/public/assets/useCopyFeedback-zjZZUC2-.js.br +0 -0
  333. package/payload/server/public/assets/useCopyFeedback-zjZZUC2-.js.gz +0 -0
  334. package/payload/server/public/assets/useSubAccountSwitcher-72THldvm.css.br +0 -0
  335. package/payload/server/public/assets/useVoiceRecorder-CJecnefX.js.br +0 -0
  336. package/payload/server/public/assets/useVoiceRecorder-CJecnefX.js.gz +0 -0
  337. package/payload/server/public/assets/wrench-D8BH20W8.js.br +0 -0
  338. package/payload/server/public/assets/wrench-D8BH20W8.js.gz +0 -0
  339. /package/payload/server/public/assets/{useSubAccountSwitcher-HjQZjJBr.js → useSubAccountSwitcher-BEwQMRMo.js} +0 -0
  340. /package/payload/server/public/assets/{useSubAccountSwitcher-HjQZjJBr.js.br → useSubAccountSwitcher-BEwQMRMo.js.br} +0 -0
  341. /package/payload/server/public/assets/{useSubAccountSwitcher-HjQZjJBr.js.gz → useSubAccountSwitcher-BEwQMRMo.js.gz} +0 -0
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Task 2220 — session transcript reading for the learnings pass.
3
+ *
4
+ * The task specified `readJsonlSession` / `readJsonlSessionAtPath` from
5
+ * `claude-session-manager`. Both return a `DehydratedSession` of metadata
6
+ * (id, mtime, title, turn count) parsed from a bounded tail; neither can
7
+ * produce transcript content, and nothing outside that service imports the
8
+ * package. So the reading lives here, self-contained.
9
+ *
10
+ * Directory shape, per `runDuplicateSenderAudit` (ui/server/index.ts:627):
11
+ * $CLAUDE_CONFIG_DIR/projects/<slug>/<sessionId>.jsonl
12
+ * $CLAUDE_CONFIG_DIR/projects/<slug>/subagents/<id>.jsonl <- flagged, skipped by callers
13
+ * $CLAUDE_CONFIG_DIR/projects/<slug>/archive/<id>.jsonl <- flagged, skipped by callers
14
+ * Account scope comes from the `<sessionId>.meta.json` sidecar, never from the
15
+ * transcript body.
16
+ */
17
+ export interface SessionFile {
18
+ path: string;
19
+ sessionId: string;
20
+ isSubagent: boolean;
21
+ archived: boolean;
22
+ }
23
+ export interface EnumerateResult {
24
+ files: SessionFile[];
25
+ /** On-disk .jsonl count BEFORE any filtering. The discriminator between a
26
+ * broken sinceIso comparison and a broken enumerator path. */
27
+ candidateFiles: number;
28
+ /** Directories that existed but could not be read. */
29
+ skipped: number;
30
+ }
31
+ /**
32
+ * `$CLAUDE_CONFIG_DIR/projects`. Throws when the variable is absent or empty.
33
+ *
34
+ * Deliberately no default path: pty-spawner stamps CLAUDE_CONFIG_DIR only for
35
+ * `isSpecialistSpawn || role === 'admin'`, so a spawn shape that does not carry
36
+ * it must fail loudly. Falling back to `~/.claude` would read another brand's
37
+ * sessions, and brand isolation is absolute.
38
+ */
39
+ export declare function claudeProjectsRoot(): string;
40
+ /**
41
+ * Walk every slug directory under `projectsRoot`, plus its `subagents/` and
42
+ * `archive/` subdirectories. Flags rather than drops, so the caller's counters
43
+ * can distinguish "nothing on disk" from "everything filtered".
44
+ */
45
+ export declare function enumerateSessionJsonls(projectsRoot: string): EnumerateResult;
46
+ /** Account scope for one session, from its `.meta.json` sidecar. Null when the
47
+ * sidecar is missing, unreadable, or carries no accountId. */
48
+ export declare function readSidecarAccountId(jsonlPath: string): string | null;
49
+ /** ISO of the session's last write, used for the sinceIso filter. */
50
+ export declare function sessionLastWriteIso(jsonlPath: string): string | null;
51
+ /**
52
+ * One page of turn-attributed transcript. `chunkLines` counts TURNS, not file
53
+ * lines: a transcript's line count is dominated by tool traffic the claim pass
54
+ * has no use for.
55
+ */
56
+ export declare function chunkTranscript(jsonlPath: string, chunkIndex: number, chunkLines: number): {
57
+ body: string;
58
+ totalChunks: number;
59
+ };
60
+ //# sourceMappingURL=session-jsonl.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-jsonl.d.ts","sourceRoot":"","sources":["../../src/lib/session-jsonl.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAKH,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,OAAO,CAAC;IACpB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB;mEAC+D;IAC/D,cAAc,EAAE,MAAM,CAAC;IACvB,sDAAsD;IACtD,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAQ3C;AAaD;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,YAAY,EAAE,MAAM,GAAG,eAAe,CA+B5E;AAED;+DAC+D;AAC/D,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQrE;AAED,qEAAqE;AACrE,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAMpE;AA4BD;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,GACjB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAevC"}
@@ -0,0 +1,153 @@
1
+ /**
2
+ * Task 2220 — session transcript reading for the learnings pass.
3
+ *
4
+ * The task specified `readJsonlSession` / `readJsonlSessionAtPath` from
5
+ * `claude-session-manager`. Both return a `DehydratedSession` of metadata
6
+ * (id, mtime, title, turn count) parsed from a bounded tail; neither can
7
+ * produce transcript content, and nothing outside that service imports the
8
+ * package. So the reading lives here, self-contained.
9
+ *
10
+ * Directory shape, per `runDuplicateSenderAudit` (ui/server/index.ts:627):
11
+ * $CLAUDE_CONFIG_DIR/projects/<slug>/<sessionId>.jsonl
12
+ * $CLAUDE_CONFIG_DIR/projects/<slug>/subagents/<id>.jsonl <- flagged, skipped by callers
13
+ * $CLAUDE_CONFIG_DIR/projects/<slug>/archive/<id>.jsonl <- flagged, skipped by callers
14
+ * Account scope comes from the `<sessionId>.meta.json` sidecar, never from the
15
+ * transcript body.
16
+ */
17
+ import { readdirSync, readFileSync, statSync } from "node:fs";
18
+ import { basename, join } from "node:path";
19
+ /**
20
+ * `$CLAUDE_CONFIG_DIR/projects`. Throws when the variable is absent or empty.
21
+ *
22
+ * Deliberately no default path: pty-spawner stamps CLAUDE_CONFIG_DIR only for
23
+ * `isSpecialistSpawn || role === 'admin'`, so a spawn shape that does not carry
24
+ * it must fail loudly. Falling back to `~/.claude` would read another brand's
25
+ * sessions, and brand isolation is absolute.
26
+ */
27
+ export function claudeProjectsRoot() {
28
+ const configDir = process.env.CLAUDE_CONFIG_DIR;
29
+ if (!configDir) {
30
+ throw new Error("learnings: CLAUDE_CONFIG_DIR is not set — refusing to guess a projects root");
31
+ }
32
+ return join(configDir, "projects");
33
+ }
34
+ function jsonlsIn(dir, isSubagent, archived) {
35
+ return readdirSync(dir, { withFileTypes: true })
36
+ .filter((e) => e.isFile() && e.name.endsWith(".jsonl"))
37
+ .map((e) => ({
38
+ path: join(dir, e.name),
39
+ sessionId: basename(e.name, ".jsonl"),
40
+ isSubagent,
41
+ archived,
42
+ }));
43
+ }
44
+ /**
45
+ * Walk every slug directory under `projectsRoot`, plus its `subagents/` and
46
+ * `archive/` subdirectories. Flags rather than drops, so the caller's counters
47
+ * can distinguish "nothing on disk" from "everything filtered".
48
+ */
49
+ export function enumerateSessionJsonls(projectsRoot) {
50
+ const files = [];
51
+ let skipped = 0;
52
+ let slugs;
53
+ try {
54
+ slugs = readdirSync(projectsRoot, { withFileTypes: true })
55
+ .filter((d) => d.isDirectory())
56
+ .map((d) => d.name);
57
+ }
58
+ catch (err) {
59
+ if (err.code === "ENOENT") {
60
+ return { files, candidateFiles: 0, skipped: 0 };
61
+ }
62
+ throw err;
63
+ }
64
+ const shapes = [
65
+ ["", false, false],
66
+ ["subagents", true, false],
67
+ ["archive", false, true],
68
+ ];
69
+ for (const slug of slugs) {
70
+ const slugDir = join(projectsRoot, slug);
71
+ for (const [sub, isSubagent, archived] of shapes) {
72
+ const dir = sub ? join(slugDir, sub) : slugDir;
73
+ try {
74
+ files.push(...jsonlsIn(dir, isSubagent, archived));
75
+ }
76
+ catch (err) {
77
+ if (err.code !== "ENOENT")
78
+ skipped += 1;
79
+ }
80
+ }
81
+ }
82
+ return { files, candidateFiles: files.length, skipped };
83
+ }
84
+ /** Account scope for one session, from its `.meta.json` sidecar. Null when the
85
+ * sidecar is missing, unreadable, or carries no accountId. */
86
+ export function readSidecarAccountId(jsonlPath) {
87
+ try {
88
+ const raw = readFileSync(jsonlPath.replace(/\.jsonl$/, ".meta.json"), "utf8");
89
+ const parsed = JSON.parse(raw);
90
+ return typeof parsed.accountId === "string" ? parsed.accountId : null;
91
+ }
92
+ catch {
93
+ return null;
94
+ }
95
+ }
96
+ /** ISO of the session's last write, used for the sinceIso filter. */
97
+ export function sessionLastWriteIso(jsonlPath) {
98
+ try {
99
+ return statSync(jsonlPath).mtime.toISOString();
100
+ }
101
+ catch {
102
+ return null;
103
+ }
104
+ }
105
+ function turnText(line) {
106
+ let parsed;
107
+ try {
108
+ parsed = JSON.parse(line);
109
+ }
110
+ catch {
111
+ return null;
112
+ }
113
+ if (parsed.type !== "user" && parsed.type !== "assistant")
114
+ return null;
115
+ const content = parsed.message?.content;
116
+ if (typeof content === "string")
117
+ return `${parsed.type}: ${content}`;
118
+ if (Array.isArray(content)) {
119
+ const text = content
120
+ .filter((b) => typeof b === "object" &&
121
+ b !== null &&
122
+ b.type === "text" &&
123
+ typeof b.text === "string")
124
+ .map((b) => b.text)
125
+ .join("\n");
126
+ return text ? `${parsed.type}: ${text}` : null;
127
+ }
128
+ return null;
129
+ }
130
+ /**
131
+ * One page of turn-attributed transcript. `chunkLines` counts TURNS, not file
132
+ * lines: a transcript's line count is dominated by tool traffic the claim pass
133
+ * has no use for.
134
+ */
135
+ export function chunkTranscript(jsonlPath, chunkIndex, chunkLines) {
136
+ let raw;
137
+ try {
138
+ raw = readFileSync(jsonlPath, "utf8");
139
+ }
140
+ catch {
141
+ return { body: "", totalChunks: 0 };
142
+ }
143
+ const turns = raw
144
+ .split("\n")
145
+ .map(turnText)
146
+ .filter((t) => t !== null);
147
+ if (turns.length === 0)
148
+ return { body: "", totalChunks: 0 };
149
+ const totalChunks = Math.ceil(turns.length / chunkLines);
150
+ const start = chunkIndex * chunkLines;
151
+ return { body: turns.slice(start, start + chunkLines).join("\n"), totalChunks };
152
+ }
153
+ //# sourceMappingURL=session-jsonl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-jsonl.js","sourceRoot":"","sources":["../../src/lib/session-jsonl.ts"],"names":[],"mappings":"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"}
@@ -11,7 +11,7 @@ import { fileURLToPath } from "node:url";
11
11
  // handler and nowhere it should not be.
12
12
  const SRC = resolve(dirname(fileURLToPath(import.meta.url)), "../../index.ts");
13
13
  const src = readFileSync(SRC, "utf8");
14
- // The 38 tools whose read/write re-scopes on the resolved account. The first 35
14
+ // The 41 tools whose read/write re-scopes on the resolved account. The first 38
15
15
  // key SOLELY on accountId (Task 1455). profile-read/update/delete (Task 1461)
16
16
  // additionally key on userId, but the cross-account path resolves the target
17
17
  // sub-account's OWNER AdminUser userId, so the resolved account still governs
@@ -20,6 +20,8 @@ const TARGETABLE = [
20
20
  "memory-search", "memory-lookup-by-name", "memory-node-exists", "memory-find-candidates",
21
21
  "memory-brain-capture-recent", "memory-write", "memory-update", "memory-update-by-name",
22
22
  "memory-edge", "memory-delete", "memory-restore", "memory-empty-trash", "memory-archive-write",
23
+ // Task 2220 — the learnings surface.
24
+ "learnings-scan", "learnings-derive", "learnings-recall",
23
25
  "memory-list-attachments", "memory-read-attachment", "memory-edit-attachment",
24
26
  "memory-rename-attachment", "memory-report-write", "memory-report-read-latest",
25
27
  "memory-report-list", "conversation-list", "conversation-search", "conversation-memory-expunge",
@@ -54,10 +56,10 @@ describe("cross-account tool coverage (Task 1455)", () => {
54
56
  it("image-fetch is NOT threaded (n/a — no sub-account scope)", () => {
55
57
  expect(src).not.toContain(`resolveToolAccount("image-fetch"`);
56
58
  });
57
- it("exactly 38 tools take a target; 5 are own-account-only", () => {
59
+ it("exactly 41 tools take a target; 5 are own-account-only", () => {
58
60
  const withTarget = src.match(/resolveToolAccount\("[a-z0-9-]+", targetAccountId\)/g) ?? [];
59
61
  const ownOnly = src.match(/resolveToolAccount\("[a-z0-9-]+", undefined\)/g) ?? [];
60
- expect(TARGETABLE.length).toBe(38);
62
+ expect(TARGETABLE.length).toBe(41);
61
63
  expect(NOT_TARGETABLE.length).toBe(5);
62
64
  expect(withTarget.length).toBe(TARGETABLE.length);
63
65
  expect(ownOnly.length).toBe(NOT_TARGETABLE.length);
@@ -66,7 +68,7 @@ describe("cross-account tool coverage (Task 1455)", () => {
66
68
  const shadows = src.match(/const accountId = scoped\.accountId;/g) ?? [];
67
69
  expect(shadows.length).toBe(TARGETABLE.length + NOT_TARGETABLE.length);
68
70
  });
69
- it("no schema exposes targetAccountId beyond the 38 targetable tools", () => {
71
+ it("no schema exposes targetAccountId beyond the 41 targetable tools", () => {
70
72
  const fields = src.match(/targetAccountId: z\.string\(\)\.optional\(\)/g) ?? [];
71
73
  expect(fields.length).toBe(TARGETABLE.length);
72
74
  });
@@ -1 +1 @@
1
- {"version":3,"file":"cross-account.test.js","sourceRoot":"","sources":["../../../src/tools/__tests__/cross-account.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cross-account.test.js","sourceRoot":"","sources":["../../../src/tools/__tests__/cross-account.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=learnings-derive.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"learnings-derive.test.d.ts","sourceRoot":"","sources":["../../../src/tools/__tests__/learnings-derive.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,160 @@
1
+ // Task 2220 — four branches: novel create at initial confidence, amplify on
2
+ // re-observation, relegate on contradiction with contradictedAt stamped, and
3
+ // the decay pass reproducing the preference curve off a STRING observedAt.
4
+ import { describe, it, expect, beforeEach, vi } from "vitest";
5
+ const mockSession = {
6
+ run: vi.fn(),
7
+ close: vi.fn().mockResolvedValue(undefined),
8
+ };
9
+ vi.mock("../../lib/neo4j.js", () => ({ getSession: () => mockSession }));
10
+ vi.mock("../../lib/embeddings.js", () => ({
11
+ embed: vi.fn().mockResolvedValue([0.1, 0.2, 0.3]),
12
+ }));
13
+ import { learningsDerive } from "../learnings-derive.js";
14
+ const rec = (row) => ({ get: (k) => row[k] });
15
+ function wireSession(opts) {
16
+ mockSession.run.mockReset();
17
+ mockSession.run.mockImplementation(async (q) => {
18
+ if (q.includes("queryNodes('learning_embedding'")) {
19
+ return { records: (opts.neighbourRows ?? []).map(rec) };
20
+ }
21
+ if (q.includes("RETURN l.learningId AS learningId")) {
22
+ return { records: (opts.decayRows ?? []).map(rec) };
23
+ }
24
+ return { records: [] };
25
+ });
26
+ }
27
+ beforeEach(() => wireSession({}));
28
+ describe("learningsDerive", () => {
29
+ it("creates a novel claim at initial confidence", async () => {
30
+ const out = await learningsDerive({
31
+ accountId: "acct-1",
32
+ sessionId: "sess-1",
33
+ claims: [{ title: "Prefer exit codes", body: "Never grep prose.", mode: "reinforce" }],
34
+ });
35
+ expect(out).toMatchObject({ created: 1, amplified: 0, relegated: 0 });
36
+ const create = mockSession.run.mock.calls.find(([q]) => String(q).includes("CREATE (l:Learning"));
37
+ expect(create).toBeDefined();
38
+ expect(create[1].confidence).toBe(0.5);
39
+ });
40
+ it("amplifies a matched claim on the reinforcement curve", async () => {
41
+ // similarity = 2 * 0.95 - 1 = 0.9, above SAME_SUBJECT_COSINE (0.85)
42
+ wireSession({
43
+ neighbourRows: [
44
+ { learningId: "L1", title: "Prefer exit codes", confidence: 0.5, score: 0.95 },
45
+ ],
46
+ });
47
+ const out = await learningsDerive({
48
+ accountId: "acct-1",
49
+ sessionId: "sess-2",
50
+ claims: [{ title: "Use exit codes", body: "Same rule, new words.", mode: "reinforce" }],
51
+ });
52
+ expect(out).toMatchObject({ created: 0, amplified: 1, relegated: 0 });
53
+ const set = mockSession.run.mock.calls.find(([q]) => String(q).includes("SET l.confidence = $confidence"));
54
+ // 0.5 + 0.15 * (1 - 0.5) = 0.575
55
+ expect(set[1].confidence).toBeCloseTo(0.575, 10);
56
+ });
57
+ it("relegates on contradiction and stamps contradictedAt", async () => {
58
+ wireSession({
59
+ neighbourRows: [
60
+ { learningId: "L1", title: "Prefer exit codes", confidence: 0.8, score: 0.95 },
61
+ ],
62
+ });
63
+ const out = await learningsDerive({
64
+ accountId: "acct-1",
65
+ sessionId: "sess-3",
66
+ claims: [
67
+ { title: "Exit codes are wrong", body: "Operator said otherwise.", mode: "contradict" },
68
+ ],
69
+ });
70
+ expect(out).toMatchObject({ created: 0, amplified: 0, relegated: 1 });
71
+ const set = mockSession.run.mock.calls.find(([q]) => String(q).includes("SET l.confidence = $confidence"));
72
+ expect(set[1].confidence).toBeCloseTo(0.5, 10);
73
+ expect(String(set[0])).toContain("contradictedAt");
74
+ });
75
+ it("creates rather than matching when the neighbour is below the cosine floor", async () => {
76
+ // similarity = 2 * 0.8 - 1 = 0.6, below 0.85
77
+ wireSession({
78
+ neighbourRows: [{ learningId: "L1", title: "Unrelated", confidence: 0.5, score: 0.8 }],
79
+ });
80
+ const out = await learningsDerive({
81
+ accountId: "acct-1",
82
+ sessionId: "sess-4",
83
+ claims: [{ title: "New thing", body: "Nothing like the other.", mode: "reinforce" }],
84
+ });
85
+ expect(out).toMatchObject({ created: 1, amplified: 0 });
86
+ });
87
+ it("decays a string observedAt past the threshold and floors at zero", async () => {
88
+ const now = Date.now();
89
+ const daysAgo = (n) => new Date(now - n * 86_400_000).toISOString();
90
+ wireSession({
91
+ decayRows: [
92
+ { learningId: "A", confidence: 0.8, observedAt: daysAgo(5) },
93
+ { learningId: "B", confidence: 0.8, observedAt: daysAgo(20) },
94
+ { learningId: "C", confidence: 0.1, observedAt: daysAgo(200) },
95
+ ],
96
+ });
97
+ const out = await learningsDerive({
98
+ accountId: "acct-1",
99
+ sessionId: "sess-5",
100
+ claims: [],
101
+ runDecay: true,
102
+ });
103
+ expect(out.decay).toEqual({ examined: 3, decayed: 2, floored: 1 });
104
+ });
105
+ it("does not run the decay pass unless asked", async () => {
106
+ const out = await learningsDerive({
107
+ accountId: "acct-1",
108
+ sessionId: "sess-6",
109
+ claims: [],
110
+ });
111
+ expect(out.decay).toBeNull();
112
+ });
113
+ // Review finding: `MATCH (p:UserProfile ...) CREATE ...` silently no-ops when
114
+ // the profile is absent (profile-update.ts:309-311), and MERGE on accountId
115
+ // alone would mint a UserProfile missing its required userId.
116
+ it("creates the learning without a UserProfile and attaches the edge only if one exists", async () => {
117
+ await learningsDerive({
118
+ accountId: "acct-1",
119
+ sessionId: "sess-8",
120
+ claims: [{ title: "Standalone", body: "No profile in this graph.", mode: "reinforce" }],
121
+ });
122
+ const create = mockSession.run.mock.calls.find(([q]) => String(q).includes("CREATE (l:Learning"));
123
+ const q = String(create[0]);
124
+ expect(q).not.toContain("MERGE (p:UserProfile");
125
+ expect(q).toContain("OPTIONAL MATCH (p:UserProfile");
126
+ // The CREATE is unconditional: it precedes the profile lookup.
127
+ expect(q.indexOf("CREATE (l:Learning")).toBeLessThan(q.indexOf("OPTIONAL MATCH"));
128
+ });
129
+ // Review finding: :Learning is vector-indexed, so a zero-length embedding
130
+ // makes the node permanently invisible to the neighbour query — it could
131
+ // never amplify, and every re-observation would mint a duplicate.
132
+ it("omits the embedding property entirely when the embedder returns nothing", async () => {
133
+ const { embed } = await import("../../lib/embeddings.js");
134
+ embed
135
+ .mockResolvedValueOnce(null);
136
+ const write = vi.spyOn(process.stderr, "write").mockReturnValue(true);
137
+ await learningsDerive({
138
+ accountId: "acct-1",
139
+ sessionId: "sess-9",
140
+ claims: [{ title: "Unembeddable", body: "Embedder was down.", mode: "reinforce" }],
141
+ });
142
+ const create = mockSession.run.mock.calls.find(([q]) => String(q).includes("CREATE (l:Learning"));
143
+ // Never an empty array in the created property block.
144
+ expect(create[1].embedding).toBeNull();
145
+ const line = write.mock.calls
146
+ .map(([c]) => String(c))
147
+ .find((c) => c.includes("op=derive-embed-missing"));
148
+ expect(line).toContain("reason=embedder-returned-nothing");
149
+ write.mockRestore();
150
+ });
151
+ it("rejects an unrecognised mode by name", async () => {
152
+ await expect(learningsDerive({
153
+ accountId: "acct-1",
154
+ sessionId: "sess-7",
155
+ // deliberately outside the union
156
+ claims: [{ title: "x", body: "y", mode: "merge" }],
157
+ })).rejects.toThrow(/Invalid mode "merge"/);
158
+ });
159
+ });
160
+ //# sourceMappingURL=learnings-derive.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"learnings-derive.test.js","sourceRoot":"","sources":["../../../src/tools/__tests__/learnings-derive.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=learnings-recall.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"learnings-recall.test.d.ts","sourceRoot":"","sources":["../../../src/tools/__tests__/learnings-recall.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,64 @@
1
+ // Task 2220 — the only path to a learning body. The skill cannot emit a log
2
+ // line, so the tool does: op=recall with the id and the matched title. Without
3
+ // it, "index injected but never invoked" would be unobservable, and that
4
+ // measurement is what decides whether MAX_INDEXED_LEARNINGS falls.
5
+ import { describe, it, expect, beforeEach, vi } from "vitest";
6
+ const mockSession = { run: vi.fn(), close: vi.fn().mockResolvedValue(undefined) };
7
+ vi.mock("../../lib/neo4j.js", () => ({ getSession: () => mockSession }));
8
+ import { learningsRecall } from "../learnings-recall.js";
9
+ const rec = (row) => ({ get: (k) => row[k] });
10
+ beforeEach(() => {
11
+ mockSession.run.mockReset();
12
+ mockSession.run.mockResolvedValue({ records: [] });
13
+ });
14
+ describe("learningsRecall", () => {
15
+ it("returns the body for a matched title and emits op=recall", async () => {
16
+ const write = vi.spyOn(process.stderr, "write").mockReturnValue(true);
17
+ mockSession.run.mockResolvedValue({
18
+ records: [
19
+ rec({
20
+ learningId: "L1",
21
+ title: "Prefer exit codes",
22
+ body: "Never grep a CLI's prose for control flow.",
23
+ confidence: 0.7,
24
+ observedAt: "2026-07-29T00:00:00.000Z",
25
+ observationCount: 3,
26
+ contradictedAt: null,
27
+ }),
28
+ ],
29
+ });
30
+ const out = await learningsRecall({ accountId: "acct-1", title: "exit codes" });
31
+ expect(out.rows[0].body).toContain("Never grep");
32
+ const line = write.mock.calls
33
+ .map(([c]) => String(c))
34
+ .find((c) => c.includes("op=recall"));
35
+ expect(line).toContain("learningId=L1");
36
+ expect(line).toContain("matchedTitle=");
37
+ write.mockRestore();
38
+ });
39
+ it("surfaces contradictedAt so a disputed learning is not read as settled", async () => {
40
+ mockSession.run.mockResolvedValue({
41
+ records: [
42
+ rec({
43
+ learningId: "L2",
44
+ title: "Disputed",
45
+ body: "text",
46
+ confidence: 0.2,
47
+ observedAt: "2026-07-29T00:00:00.000Z",
48
+ observationCount: 2,
49
+ contradictedAt: "2026-07-30T00:00:00.000Z",
50
+ }),
51
+ ],
52
+ });
53
+ const out = await learningsRecall({ accountId: "acct-1", learningId: "L2" });
54
+ expect(out.rows[0].contradictedAt).toBe("2026-07-30T00:00:00.000Z");
55
+ });
56
+ it("requires one of title or learningId", async () => {
57
+ await expect(learningsRecall({ accountId: "acct-1" })).rejects.toThrow(/title or learningId is required/);
58
+ });
59
+ it("returns no rows without throwing when nothing matches", async () => {
60
+ const out = await learningsRecall({ accountId: "acct-1", title: "nothing" });
61
+ expect(out.rows).toEqual([]);
62
+ });
63
+ });
64
+ //# sourceMappingURL=learnings-recall.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"learnings-recall.test.js","sourceRoot":"","sources":["../../../src/tools/__tests__/learnings-recall.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=learnings-scan.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"learnings-scan.test.d.ts","sourceRoot":"","sources":["../../../src/tools/__tests__/learnings-scan.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,78 @@
1
+ // Task 2220 — learnings-scan returns only sessions written after sinceIso,
2
+ // skips subagent and archived transcripts, and scopes by sidecar accountId.
3
+ import { describe, it, expect, beforeEach, afterEach } from "vitest";
4
+ import { mkdtempSync, mkdirSync, writeFileSync, rmSync, utimesSync } from "node:fs";
5
+ import { tmpdir } from "node:os";
6
+ import { join } from "node:path";
7
+ import { learningsScan } from "../learnings-scan.js";
8
+ let root;
9
+ let slug;
10
+ function seedSession(name, accountId, mtime, dir) {
11
+ const target = dir ?? slug;
12
+ const p = join(target, `${name}.jsonl`);
13
+ writeFileSync(p, [
14
+ JSON.stringify({ type: "user", message: { content: `hello from ${name}` } }),
15
+ JSON.stringify({
16
+ type: "assistant",
17
+ message: { content: [{ type: "text", text: "ack" }] },
18
+ }),
19
+ ].join("\n"));
20
+ if (accountId !== null) {
21
+ writeFileSync(join(target, `${name}.meta.json`), JSON.stringify({ accountId }));
22
+ }
23
+ utimesSync(p, mtime, mtime);
24
+ }
25
+ beforeEach(() => {
26
+ root = mkdtempSync(join(tmpdir(), "learnings-scan-tool-"));
27
+ slug = join(root, "projects", "-Users-neo-proj");
28
+ mkdirSync(join(slug, "subagents"), { recursive: true });
29
+ mkdirSync(join(slug, "archive"), { recursive: true });
30
+ process.env.CLAUDE_CONFIG_DIR = root;
31
+ });
32
+ afterEach(() => {
33
+ rmSync(root, { recursive: true, force: true });
34
+ delete process.env.CLAUDE_CONFIG_DIR;
35
+ });
36
+ describe("learningsScan", () => {
37
+ it("returns only sessions written after sinceIso", async () => {
38
+ seedSession("old", "acct-1", new Date("2026-07-01T00:00:00Z"));
39
+ seedSession("new", "acct-1", new Date("2026-07-29T00:00:00Z"));
40
+ const out = await learningsScan({
41
+ accountId: "acct-1",
42
+ sinceIso: "2026-07-15T00:00:00.000Z",
43
+ });
44
+ expect(out.rows.map((r) => r.sessionId)).toEqual(["new"]);
45
+ expect(out.sessions).toBe(1);
46
+ expect(out.candidateFiles).toBe(2);
47
+ });
48
+ it("skips subagent and archived transcripts", async () => {
49
+ seedSession("live", "acct-1", new Date("2026-07-29T00:00:00Z"));
50
+ seedSession("sub", "acct-1", new Date("2026-07-29T00:00:00Z"), join(slug, "subagents"));
51
+ seedSession("arch", "acct-1", new Date("2026-07-29T00:00:00Z"), join(slug, "archive"));
52
+ const out = await learningsScan({ accountId: "acct-1" });
53
+ expect(out.rows.map((r) => r.sessionId)).toEqual(["live"]);
54
+ expect(out.candidateFiles).toBe(3);
55
+ });
56
+ it("drops sessions belonging to another account and untagged sessions", async () => {
57
+ seedSession("mine", "acct-1", new Date("2026-07-29T00:00:00Z"));
58
+ seedSession("theirs", "acct-2", new Date("2026-07-29T00:00:00Z"));
59
+ seedSession("untagged", null, new Date("2026-07-29T00:00:00Z"));
60
+ const out = await learningsScan({ accountId: "acct-1" });
61
+ expect(out.rows.map((r) => r.sessionId)).toEqual(["mine"]);
62
+ });
63
+ it("refuses when CLAUDE_CONFIG_DIR is unset", async () => {
64
+ delete process.env.CLAUDE_CONFIG_DIR;
65
+ await expect(learningsScan({ accountId: "acct-1" })).rejects.toThrow(/CLAUDE_CONFIG_DIR is not set/);
66
+ });
67
+ it("rejects a malformed sinceIso rather than scanning everything", async () => {
68
+ seedSession("any", "acct-1", new Date("2026-07-29T00:00:00Z"));
69
+ await expect(learningsScan({ accountId: "acct-1", sinceIso: "last tuesday" })).rejects.toThrow(/not a valid ISO timestamp/);
70
+ });
71
+ it("pages chunks within a session", async () => {
72
+ seedSession("multi", "acct-1", new Date("2026-07-29T00:00:00Z"));
73
+ const out = await learningsScan({ accountId: "acct-1", chunkTurns: 1, chunkIndex: 1 });
74
+ expect(out.rows[0].totalChunks).toBe(2);
75
+ expect(out.rows[0].body).toContain("ack");
76
+ });
77
+ });
78
+ //# sourceMappingURL=learnings-scan.test.js.map