@rubytech/create-sitedesk-code 0.1.522 → 0.1.523

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 (338) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/lib/graph-style/dist/index.d.ts.map +1 -1
  3. package/payload/platform/lib/graph-style/dist/index.js +28 -0
  4. package/payload/platform/lib/graph-style/dist/index.js.map +1 -1
  5. package/payload/platform/lib/graph-style/src/__tests__/caption-coverage.test.ts +7 -0
  6. package/payload/platform/lib/graph-style/src/index.ts +24 -0
  7. package/payload/platform/lib/graph-write/dist/__tests__/merge-on.test.d.ts.map +1 -0
  8. package/payload/platform/lib/graph-write/dist/__tests__/merge-on.test.js.map +1 -0
  9. package/payload/platform/lib/graph-write/dist/index.d.ts +16 -0
  10. package/payload/platform/lib/graph-write/dist/index.d.ts.map +1 -1
  11. package/payload/platform/lib/graph-write/dist/index.js +83 -6
  12. package/payload/platform/lib/graph-write/dist/index.js.map +1 -1
  13. package/payload/platform/lib/graph-write/src/index.ts +117 -10
  14. package/payload/platform/lib/routine-templates/dist/index.d.ts +151 -0
  15. package/payload/platform/lib/routine-templates/dist/index.d.ts.map +1 -0
  16. package/payload/platform/lib/routine-templates/dist/index.js +207 -0
  17. package/payload/platform/lib/routine-templates/dist/index.js.map +1 -0
  18. package/payload/platform/lib/routine-templates/dist/roster.d.ts +57 -0
  19. package/payload/platform/lib/routine-templates/dist/roster.d.ts.map +1 -0
  20. package/payload/platform/lib/routine-templates/dist/roster.js +182 -0
  21. package/payload/platform/lib/routine-templates/dist/roster.js.map +1 -0
  22. package/payload/platform/lib/routine-templates/dist/seed-cli.d.ts +2 -0
  23. package/payload/platform/lib/routine-templates/dist/seed-cli.d.ts.map +1 -0
  24. package/payload/platform/lib/routine-templates/dist/seed-cli.js +64 -0
  25. package/payload/platform/lib/routine-templates/dist/seed-cli.js.map +1 -0
  26. package/payload/platform/lib/routine-templates/package.json +6 -0
  27. package/payload/platform/lib/routine-templates/src/__tests__/roster.test.ts +170 -0
  28. package/payload/platform/lib/routine-templates/src/__tests__/seed.test.ts +298 -0
  29. package/payload/platform/lib/routine-templates/src/index.ts +299 -0
  30. package/payload/platform/lib/routine-templates/src/roster.ts +206 -0
  31. package/payload/platform/lib/routine-templates/src/seed-cli.ts +65 -0
  32. package/payload/platform/lib/routine-templates/tsconfig.json +9 -0
  33. package/payload/platform/lib/routine-templates/vitest.config.ts +9 -0
  34. package/payload/platform/neo4j/edge-annotations.json +2 -2
  35. package/payload/platform/neo4j/schema.cypher +25 -1
  36. package/payload/platform/package.json +3 -2
  37. package/payload/platform/plugins/admin/PLUGIN.md +2 -2
  38. package/payload/platform/plugins/admin/mcp/dist/index.js +39 -1
  39. package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
  40. package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +277 -61
  41. package/payload/platform/plugins/admin/skills/whats-new/SKILL.md +6 -0
  42. package/payload/platform/plugins/docs/references/admin-ui.md +265 -59
  43. package/payload/platform/plugins/docs/references/memory-guide.md +11 -1
  44. package/payload/platform/plugins/graph/.claude-plugin/plugin.json +1 -1
  45. package/payload/platform/plugins/graph/PLUGIN.md +1 -1
  46. package/payload/platform/plugins/memory/PLUGIN.md +1 -1
  47. package/payload/platform/plugins/memory/mcp/dist/index.js +12 -5
  48. package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
  49. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/phase-estate-census.test.d.ts +2 -0
  50. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/phase-estate-census.test.d.ts.map +1 -0
  51. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/phase-estate-census.test.js +197 -0
  52. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/phase-estate-census.test.js.map +1 -0
  53. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-loader.test.js +55 -9
  54. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-loader.test.js.map +1 -1
  55. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-validator.test.js +96 -0
  56. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-validator.test.js.map +1 -1
  57. package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/index.d.ts +7 -0
  58. package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/index.d.ts.map +1 -1
  59. package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-estate-census.d.ts +29 -0
  60. package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-estate-census.d.ts.map +1 -0
  61. package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-estate-census.js +126 -0
  62. package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-estate-census.js.map +1 -0
  63. package/payload/platform/plugins/memory/mcp/dist/scripts/dream-cycle-sweep.js +7 -4
  64. package/payload/platform/plugins/memory/mcp/dist/scripts/dream-cycle-sweep.js.map +1 -1
  65. package/payload/platform/plugins/memory/mcp/dist/tools/memory-dream-run.d.ts +1 -0
  66. package/payload/platform/plugins/memory/mcp/dist/tools/memory-dream-run.d.ts.map +1 -1
  67. package/payload/platform/plugins/memory/mcp/dist/tools/memory-dream-run.js +18 -1
  68. package/payload/platform/plugins/memory/mcp/dist/tools/memory-dream-run.js.map +1 -1
  69. package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.d.ts +7 -0
  70. package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.d.ts.map +1 -1
  71. package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.js +4 -3
  72. package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.js.map +1 -1
  73. package/payload/platform/plugins/memory/mcp/vitest.config.ts +2 -0
  74. package/payload/platform/plugins/memory/references/schema-estate-agent.md +2 -2
  75. package/payload/platform/plugins/memory/skills/conversation-archive-enrich/SKILL.md +4 -4
  76. package/payload/platform/plugins/quickbooks/PLUGIN.md +10 -10
  77. package/payload/platform/plugins/scheduling/PLUGIN.md +49 -1
  78. package/payload/platform/plugins/scheduling/mcp/dist/index.js +48 -0
  79. package/payload/platform/plugins/scheduling/mcp/dist/index.js.map +1 -1
  80. package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/notes-cap.test.d.ts +2 -0
  81. package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/notes-cap.test.d.ts.map +1 -0
  82. package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/notes-cap.test.js +78 -0
  83. package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/notes-cap.test.js.map +1 -0
  84. package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/routine-run.test.d.ts +2 -0
  85. package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/routine-run.test.d.ts.map +1 -0
  86. package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/routine-run.test.js +457 -0
  87. package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/routine-run.test.js.map +1 -0
  88. package/payload/platform/plugins/scheduling/mcp/dist/lib/notes-cap.d.ts +35 -0
  89. package/payload/platform/plugins/scheduling/mcp/dist/lib/notes-cap.d.ts.map +1 -0
  90. package/payload/platform/plugins/scheduling/mcp/dist/lib/notes-cap.js +39 -0
  91. package/payload/platform/plugins/scheduling/mcp/dist/lib/notes-cap.js.map +1 -0
  92. package/payload/platform/plugins/scheduling/mcp/dist/lib/routine-run.d.ts +175 -0
  93. package/payload/platform/plugins/scheduling/mcp/dist/lib/routine-run.d.ts.map +1 -0
  94. package/payload/platform/plugins/scheduling/mcp/dist/lib/routine-run.js +533 -0
  95. package/payload/platform/plugins/scheduling/mcp/dist/lib/routine-run.js.map +1 -0
  96. package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/agent-turn-dispatch.test.js +123 -9
  97. package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/agent-turn-dispatch.test.js.map +1 -1
  98. package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/routine-roster-audit.test.d.ts +2 -0
  99. package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/routine-roster-audit.test.d.ts.map +1 -0
  100. package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/routine-roster-audit.test.js +189 -0
  101. package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/routine-roster-audit.test.js.map +1 -0
  102. package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/suspension-census.test.d.ts +2 -0
  103. package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/suspension-census.test.d.ts.map +1 -0
  104. package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/suspension-census.test.js +95 -0
  105. package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/suspension-census.test.js.map +1 -0
  106. package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/sweep-excludes-suspended.test.d.ts +2 -0
  107. package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/sweep-excludes-suspended.test.d.ts.map +1 -0
  108. package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/sweep-excludes-suspended.test.js +114 -0
  109. package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/sweep-excludes-suspended.test.js.map +1 -0
  110. package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.d.ts +109 -2
  111. package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.d.ts.map +1 -1
  112. package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.js +340 -9
  113. package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.js.map +1 -1
  114. package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.d.ts +9 -1
  115. package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.d.ts.map +1 -1
  116. package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.js +210 -45
  117. package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.js.map +1 -1
  118. package/payload/platform/plugins/scheduling/mcp/dist/scripts/reconcile-bookings.js +43 -1
  119. package/payload/platform/plugins/scheduling/mcp/dist/scripts/reconcile-bookings.js.map +1 -1
  120. package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-get-agent.test.js +55 -7
  121. package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-get-agent.test.js.map +1 -1
  122. package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-list.test.js +45 -1
  123. package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-list.test.js.map +1 -1
  124. package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-runs.test.d.ts +2 -0
  125. package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-runs.test.d.ts.map +1 -0
  126. package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-runs.test.js +96 -0
  127. package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-runs.test.js.map +1 -0
  128. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-cancel.d.ts.map +1 -1
  129. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-cancel.js +2 -1
  130. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-cancel.js.map +1 -1
  131. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-get.d.ts +5 -0
  132. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-get.d.ts.map +1 -1
  133. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-get.js +13 -0
  134. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-get.js.map +1 -1
  135. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-list.d.ts +4 -0
  136. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-list.d.ts.map +1 -1
  137. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-list.js +24 -3
  138. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-list.js.map +1 -1
  139. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-runs.d.ts +33 -0
  140. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-runs.d.ts.map +1 -0
  141. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-runs.js +51 -0
  142. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-runs.js.map +1 -0
  143. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-update.d.ts.map +1 -1
  144. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-update.js +12 -2
  145. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-update.js.map +1 -1
  146. package/payload/platform/plugins/whatsapp/references/channels-whatsapp.md +30 -2
  147. package/payload/platform/plugins/whatsapp/skills/connect-whatsapp/SKILL.md +1 -1
  148. package/payload/platform/scripts/check-specialist-tool-surface.mjs +92 -16
  149. package/payload/platform/scripts/seed-neo4j.sh +41 -0
  150. package/payload/platform/scripts/verify-skill-tool-surface.sh +91 -2
  151. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.d.ts.map +1 -1
  152. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js +1 -0
  153. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js.map +1 -1
  154. package/payload/platform/templates/specialists/agents/librarian.md +1 -1
  155. package/payload/platform/templates/specialists/agents/personal-assistant.md +1 -1
  156. package/payload/server/{chunk-K7CJGZPU.js → chunk-VUXKXOJU.js} +342 -152
  157. package/payload/server/{chunk-UX2FRNO7.js → chunk-WT2PFGY4.js} +37 -265
  158. package/payload/server/{chunk-PXNY2TAP.js → chunk-XCR5D2G3.js} +239 -10
  159. package/payload/server/{manager-RKL7JZ4Y.js → manager-4TJK3YOY.js} +2 -2
  160. package/payload/server/maxy-edge.js +2 -2
  161. package/payload/server/public/activity.html +5 -5
  162. package/payload/server/public/agents.html +4 -4
  163. package/payload/server/public/assets/{AdminLoginScreens-zc2_qqh-.js → AdminLoginScreens-uknqh2Pm.js} +1 -1
  164. package/payload/server/public/assets/AdminLoginScreens-uknqh2Pm.js.br +0 -0
  165. package/payload/server/public/assets/AdminLoginScreens-uknqh2Pm.js.gz +0 -0
  166. package/payload/server/public/assets/AdminShell-GqtMImyQ.js +2 -0
  167. package/payload/server/public/assets/AdminShell-GqtMImyQ.js.br +0 -0
  168. package/payload/server/public/assets/AdminShell-GqtMImyQ.js.gz +0 -0
  169. package/payload/server/public/assets/{activity-DVgO8YuM.js → activity-B4KfMJqO.js} +1 -1
  170. package/payload/server/public/assets/activity-B4KfMJqO.js.br +0 -0
  171. package/payload/server/public/assets/activity-B4KfMJqO.js.gz +0 -0
  172. package/payload/server/public/assets/admin-DxCZeVw0.js +1 -0
  173. package/payload/server/public/assets/admin-DxCZeVw0.js.br +0 -0
  174. package/payload/server/public/assets/admin-DxCZeVw0.js.gz +0 -0
  175. package/payload/server/public/assets/agents-BtwBuO4G.js +1 -0
  176. package/payload/server/public/assets/agents-BtwBuO4G.js.br +0 -0
  177. package/payload/server/public/assets/agents-BtwBuO4G.js.gz +0 -0
  178. package/payload/server/public/assets/{browser-Mw7DY3ft.js → browser-B3hSzI3O.js} +1 -1
  179. package/payload/server/public/assets/browser-B3hSzI3O.js.br +0 -0
  180. package/payload/server/public/assets/browser-B3hSzI3O.js.gz +0 -0
  181. package/payload/server/public/assets/{calendar-B9gvL_1_.js → calendar-BggxXxhS.js} +1 -1
  182. package/payload/server/public/assets/calendar-BggxXxhS.js.br +0 -0
  183. package/payload/server/public/assets/calendar-BggxXxhS.js.gz +0 -0
  184. package/payload/server/public/assets/chat-flivHt0t.js +1 -0
  185. package/payload/server/public/assets/chat-flivHt0t.js.br +0 -0
  186. package/payload/server/public/assets/chat-flivHt0t.js.gz +0 -0
  187. package/payload/server/public/assets/chevron-left-nVRThX7f.js +1 -0
  188. package/payload/server/public/assets/chevron-right-CLqfrkRA.js +1 -0
  189. package/payload/server/public/assets/chevron-right-CLqfrkRA.js.br +0 -0
  190. package/payload/server/public/assets/clock-Dj3SRZKo.js +1 -0
  191. package/payload/server/public/assets/clock-Dj3SRZKo.js.br +0 -0
  192. package/payload/server/public/assets/clock-Dj3SRZKo.js.gz +0 -0
  193. package/payload/server/public/assets/data-Ckjkne54.js +1 -0
  194. package/payload/server/public/assets/data-Ckjkne54.js.br +3 -0
  195. package/payload/server/public/assets/data-Ckjkne54.js.gz +0 -0
  196. package/payload/server/public/assets/{file-text-dYBnXNEX.js → file-text-BKs9eyiw.js} +1 -1
  197. package/payload/server/public/assets/file-text-BKs9eyiw.js.br +0 -0
  198. package/payload/server/public/assets/file-text-BKs9eyiw.js.gz +0 -0
  199. package/payload/server/public/assets/{graph-CDyzd1Et.js → graph-DTi71NaZ.js} +3 -3
  200. package/payload/server/public/assets/graph-DTi71NaZ.js.br +0 -0
  201. package/payload/server/public/assets/graph-DTi71NaZ.js.gz +0 -0
  202. package/payload/server/public/assets/graph-labels-BT3S6e9H.js +1 -0
  203. package/payload/server/public/assets/graph-labels-BT3S6e9H.js.br +0 -0
  204. package/payload/server/public/assets/graph-labels-BT3S6e9H.js.gz +0 -0
  205. package/payload/server/public/assets/{maximize-2-M-iSaznd.js → maximize-2-zC94tsxY.js} +1 -1
  206. package/payload/server/public/assets/maximize-2-zC94tsxY.js.br +0 -0
  207. package/payload/server/public/assets/maximize-2-zC94tsxY.js.gz +0 -0
  208. package/payload/server/public/assets/operator-BtWNEMh-.js +1 -0
  209. package/payload/server/public/assets/operator-BtWNEMh-.js.br +0 -0
  210. package/payload/server/public/assets/operator-BtWNEMh-.js.gz +0 -0
  211. package/payload/server/public/assets/page-BFm91p0e.js +1 -0
  212. package/payload/server/public/assets/page-BFm91p0e.js.br +0 -0
  213. package/payload/server/public/assets/page-BFm91p0e.js.gz +0 -0
  214. package/payload/server/public/assets/{page-CZ-73FAk.js → page-Ccl0FazM.js} +3 -3
  215. package/payload/server/public/assets/page-Ccl0FazM.js.br +0 -0
  216. package/payload/server/public/assets/page-Ccl0FazM.js.gz +0 -0
  217. package/payload/server/public/assets/{public-CN-ltC8x.js → public-BpC6cn9S.js} +1 -1
  218. package/payload/server/public/assets/public-BpC6cn9S.js.br +0 -0
  219. package/payload/server/public/assets/public-BpC6cn9S.js.gz +0 -0
  220. package/payload/server/public/assets/{rotate-ccw-Buopsc22.js → rotate-ccw-BNcqbHkZ.js} +1 -1
  221. package/payload/server/public/assets/rotate-ccw-BNcqbHkZ.js.br +0 -0
  222. package/payload/server/public/assets/rotate-ccw-BNcqbHkZ.js.gz +0 -0
  223. package/payload/server/public/assets/routines-D5iia-XG.js +1 -0
  224. package/payload/server/public/assets/routines-D5iia-XG.js.br +0 -0
  225. package/payload/server/public/assets/routines-D5iia-XG.js.gz +0 -0
  226. package/payload/server/public/assets/{skills-DiiuVzDK.js → skills-COLAw_jt.js} +1 -1
  227. package/payload/server/public/assets/skills-COLAw_jt.js.br +0 -0
  228. package/payload/server/public/assets/skills-COLAw_jt.js.gz +0 -0
  229. package/payload/server/public/assets/tasks-CZDQI4nB.js +1 -0
  230. package/payload/server/public/assets/tasks-CZDQI4nB.js.br +0 -0
  231. package/payload/server/public/assets/tasks-CZDQI4nB.js.gz +0 -0
  232. package/payload/server/public/assets/{time-entry-format-BBokCF-D.js → time-entry-format-laTFzawg.js} +1 -1
  233. package/payload/server/public/assets/time-entry-format-laTFzawg.js.br +0 -0
  234. package/payload/server/public/assets/time-entry-format-laTFzawg.js.gz +0 -0
  235. package/payload/server/public/assets/{triangle-alert-C_AcpTW5.js → triangle-alert-DrwqhEog.js} +1 -1
  236. package/payload/server/public/assets/triangle-alert-DrwqhEog.js.br +0 -0
  237. package/payload/server/public/assets/triangle-alert-DrwqhEog.js.gz +0 -0
  238. package/payload/server/public/assets/{useCopyFeedback-TdimmPVR.js → useCopyFeedback-Cxme5GK6.js} +1 -1
  239. package/payload/server/public/assets/useCopyFeedback-Cxme5GK6.js.br +0 -0
  240. package/payload/server/public/assets/useCopyFeedback-Cxme5GK6.js.gz +0 -0
  241. package/payload/server/public/assets/useSubAccountSwitcher-B-K8y5a4.css +1 -0
  242. package/payload/server/public/assets/useSubAccountSwitcher-B-K8y5a4.css.br +0 -0
  243. package/payload/server/public/assets/useSubAccountSwitcher-B-K8y5a4.css.gz +0 -0
  244. package/payload/server/public/assets/useSubAccountSwitcher-C_1E11Dv.js +14 -0
  245. package/payload/server/public/assets/useSubAccountSwitcher-C_1E11Dv.js.br +0 -0
  246. package/payload/server/public/assets/useSubAccountSwitcher-C_1E11Dv.js.gz +0 -0
  247. package/payload/server/public/assets/{useVoiceRecorder-BT2738ZS.js → useVoiceRecorder-DUBpVa2T.js} +1 -1
  248. package/payload/server/public/assets/useVoiceRecorder-DUBpVa2T.js.br +0 -0
  249. package/payload/server/public/assets/useVoiceRecorder-DUBpVa2T.js.gz +0 -0
  250. package/payload/server/public/assets/{wrench-B51s5kGA.js → wrench-DWuxPnzF.js} +1 -1
  251. package/payload/server/public/assets/wrench-DWuxPnzF.js.br +0 -0
  252. package/payload/server/public/assets/wrench-DWuxPnzF.js.gz +0 -0
  253. package/payload/server/public/browser.html +4 -4
  254. package/payload/server/public/calendar.html +7 -7
  255. package/payload/server/public/chat.html +13 -13
  256. package/payload/server/public/data.html +11 -11
  257. package/payload/server/public/graph.html +9 -9
  258. package/payload/server/public/index.html +14 -14
  259. package/payload/server/public/operator.html +14 -14
  260. package/payload/server/public/public.html +13 -13
  261. package/payload/server/public/routines.html +6 -6
  262. package/payload/server/public/skills.html +5 -5
  263. package/payload/server/public/tasks.html +6 -6
  264. package/payload/server/server.js +5910 -5369
  265. package/payload/server/public/assets/AdminLoginScreens-zc2_qqh-.js.br +0 -0
  266. package/payload/server/public/assets/AdminLoginScreens-zc2_qqh-.js.gz +0 -0
  267. package/payload/server/public/assets/AdminShell-IGUdTx5q.js +0 -2
  268. package/payload/server/public/assets/AdminShell-IGUdTx5q.js.br +0 -0
  269. package/payload/server/public/assets/AdminShell-IGUdTx5q.js.gz +0 -0
  270. package/payload/server/public/assets/activity-DVgO8YuM.js.br +0 -0
  271. package/payload/server/public/assets/activity-DVgO8YuM.js.gz +0 -0
  272. package/payload/server/public/assets/admin-xtpM7fgl.js +0 -1
  273. package/payload/server/public/assets/admin-xtpM7fgl.js.br +0 -0
  274. package/payload/server/public/assets/admin-xtpM7fgl.js.gz +0 -0
  275. package/payload/server/public/assets/agents-P0nTIxo-.js +0 -1
  276. package/payload/server/public/assets/agents-P0nTIxo-.js.br +0 -0
  277. package/payload/server/public/assets/agents-P0nTIxo-.js.gz +0 -0
  278. package/payload/server/public/assets/browser-Mw7DY3ft.js.br +0 -0
  279. package/payload/server/public/assets/browser-Mw7DY3ft.js.gz +0 -0
  280. package/payload/server/public/assets/calendar-B9gvL_1_.js.br +0 -0
  281. package/payload/server/public/assets/calendar-B9gvL_1_.js.gz +0 -0
  282. package/payload/server/public/assets/chat-DBGqh4wg.js +0 -1
  283. package/payload/server/public/assets/chat-DBGqh4wg.js.br +0 -2
  284. package/payload/server/public/assets/chat-DBGqh4wg.js.gz +0 -0
  285. package/payload/server/public/assets/chevron-left-Bl4vpOM0.js +0 -1
  286. package/payload/server/public/assets/chevron-left-Bl4vpOM0.js.br +0 -0
  287. package/payload/server/public/assets/chevron-right-BExigCnp.js +0 -1
  288. package/payload/server/public/assets/chevron-right-BExigCnp.js.br +0 -0
  289. package/payload/server/public/assets/clock-D8TJvgJC.js +0 -1
  290. package/payload/server/public/assets/clock-D8TJvgJC.js.br +0 -0
  291. package/payload/server/public/assets/data-HfFSxaC2.js +0 -1
  292. package/payload/server/public/assets/data-HfFSxaC2.js.br +0 -0
  293. package/payload/server/public/assets/data-HfFSxaC2.js.gz +0 -0
  294. package/payload/server/public/assets/file-text-dYBnXNEX.js.br +0 -0
  295. package/payload/server/public/assets/file-text-dYBnXNEX.js.gz +0 -0
  296. package/payload/server/public/assets/graph-CDyzd1Et.js.br +0 -0
  297. package/payload/server/public/assets/graph-CDyzd1Et.js.gz +0 -0
  298. package/payload/server/public/assets/graph-labels-D1LkKiJr.js +0 -1
  299. package/payload/server/public/assets/graph-labels-D1LkKiJr.js.br +0 -0
  300. package/payload/server/public/assets/graph-labels-D1LkKiJr.js.gz +0 -0
  301. package/payload/server/public/assets/maximize-2-M-iSaznd.js.br +0 -0
  302. package/payload/server/public/assets/maximize-2-M-iSaznd.js.gz +0 -0
  303. package/payload/server/public/assets/operator-9jfCv1Fg.js +0 -1
  304. package/payload/server/public/assets/operator-9jfCv1Fg.js.br +0 -0
  305. package/payload/server/public/assets/operator-9jfCv1Fg.js.gz +0 -0
  306. package/payload/server/public/assets/page-CZ-73FAk.js.br +0 -0
  307. package/payload/server/public/assets/page-CZ-73FAk.js.gz +0 -0
  308. package/payload/server/public/assets/page-CjwSt7kx.js +0 -1
  309. package/payload/server/public/assets/page-CjwSt7kx.js.br +0 -0
  310. package/payload/server/public/assets/page-CjwSt7kx.js.gz +0 -0
  311. package/payload/server/public/assets/public-CN-ltC8x.js.br +0 -0
  312. package/payload/server/public/assets/public-CN-ltC8x.js.gz +0 -0
  313. package/payload/server/public/assets/rotate-ccw-Buopsc22.js.br +0 -0
  314. package/payload/server/public/assets/rotate-ccw-Buopsc22.js.gz +0 -0
  315. package/payload/server/public/assets/routines-C-yr8ddT.js +0 -1
  316. package/payload/server/public/assets/routines-C-yr8ddT.js.br +0 -0
  317. package/payload/server/public/assets/routines-C-yr8ddT.js.gz +0 -0
  318. package/payload/server/public/assets/skills-DiiuVzDK.js.br +0 -0
  319. package/payload/server/public/assets/skills-DiiuVzDK.js.gz +0 -0
  320. package/payload/server/public/assets/tasks-CnHIfn2_.js +0 -1
  321. package/payload/server/public/assets/tasks-CnHIfn2_.js.br +0 -0
  322. package/payload/server/public/assets/tasks-CnHIfn2_.js.gz +0 -0
  323. package/payload/server/public/assets/time-entry-format-BBokCF-D.js.br +0 -0
  324. package/payload/server/public/assets/time-entry-format-BBokCF-D.js.gz +0 -0
  325. package/payload/server/public/assets/triangle-alert-C_AcpTW5.js.br +0 -0
  326. package/payload/server/public/assets/triangle-alert-C_AcpTW5.js.gz +0 -0
  327. package/payload/server/public/assets/useCopyFeedback-TdimmPVR.js.br +0 -0
  328. package/payload/server/public/assets/useCopyFeedback-TdimmPVR.js.gz +0 -0
  329. package/payload/server/public/assets/useSubAccountSwitcher-BwHqV55p.js +0 -14
  330. package/payload/server/public/assets/useSubAccountSwitcher-BwHqV55p.js.br +0 -0
  331. package/payload/server/public/assets/useSubAccountSwitcher-BwHqV55p.js.gz +0 -0
  332. package/payload/server/public/assets/useSubAccountSwitcher-CsrPYqtm.css +0 -1
  333. package/payload/server/public/assets/useSubAccountSwitcher-CsrPYqtm.css.br +0 -0
  334. package/payload/server/public/assets/useSubAccountSwitcher-CsrPYqtm.css.gz +0 -0
  335. package/payload/server/public/assets/useVoiceRecorder-BT2738ZS.js.br +0 -0
  336. package/payload/server/public/assets/useVoiceRecorder-BT2738ZS.js.gz +0 -0
  337. package/payload/server/public/assets/wrench-B51s5kGA.js.br +0 -0
  338. package/payload/server/public/assets/wrench-B51s5kGA.js.gz +0 -0
@@ -0,0 +1,457 @@
1
+ import { describe, it, expect, vi } from "vitest";
2
+ import { mkdtempSync, writeFileSync, rmSync } from "node:fs";
3
+ import { tmpdir } from "node:os";
4
+ import { join } from "node:path";
5
+ import { openRoutineRun, closeRoutineRun, recordRunSession, promoteRoutineRuns, sweepRoutineRuns, auditRunOrphans, auditFiresWithoutRecords, auditRunCensus, RETENTION_DAYS, ORPHAN_AFTER_MS, readTranscriptTail, classifyRunEvidence, } from "../routine-run.js";
6
+ function fakeDriver() {
7
+ const runs = [];
8
+ return {
9
+ runs,
10
+ session: () => ({
11
+ run: vi.fn(async (query, params) => {
12
+ runs.push({ query, params });
13
+ return { records: [] };
14
+ }),
15
+ close: vi.fn(async () => { }),
16
+ }),
17
+ };
18
+ }
19
+ describe("openRoutineRun", () => {
20
+ it("creates a RoutineRun linked to its Event and returns the runId", async () => {
21
+ const driver = fakeDriver();
22
+ const runId = await openRoutineRun(driver, {
23
+ eventId: "evt-1",
24
+ accountId: "acct-1",
25
+ kind: "recurring",
26
+ mode: "agent",
27
+ target: "whatsapp:+15550000000",
28
+ scheduledFor: "2026-07-29T09:00:00.000Z",
29
+ });
30
+ expect(runId).toMatch(/^[0-9a-f-]{36}$/);
31
+ expect(driver.runs).toHaveLength(1);
32
+ expect(driver.runs[0].query).toContain("CREATE (r:RoutineRun $props)");
33
+ expect(driver.runs[0].query).toContain("CREATE (r)-[:RUN_OF]->(e)");
34
+ const props = driver.runs[0].params.props;
35
+ expect(props).toMatchObject({
36
+ runId,
37
+ eventId: "evt-1",
38
+ accountId: "acct-1",
39
+ kind: "recurring",
40
+ mode: "agent",
41
+ status: "open",
42
+ target: "whatsapp:+15550000000",
43
+ scheduledFor: "2026-07-29T09:00:00.000Z",
44
+ bounded: false,
45
+ });
46
+ expect(typeof props.startedAt).toBe("string");
47
+ });
48
+ it("returns null and never throws when the write fails", async () => {
49
+ const driver = {
50
+ session: () => ({
51
+ run: vi.fn(async () => {
52
+ throw new Error("neo4j down");
53
+ }),
54
+ close: vi.fn(async () => { }),
55
+ }),
56
+ };
57
+ const runId = await openRoutineRun(driver, {
58
+ eventId: "evt-1",
59
+ accountId: "acct-1",
60
+ kind: "one-time",
61
+ mode: "none",
62
+ target: "-",
63
+ scheduledFor: "2026-07-29T09:00:00.000Z",
64
+ });
65
+ expect(runId).toBeNull();
66
+ });
67
+ it("two opens for one event produce two distinct runIds", async () => {
68
+ const driver = fakeDriver();
69
+ const input = {
70
+ eventId: "evt-1",
71
+ accountId: "acct-1",
72
+ kind: "recurring",
73
+ mode: "agent",
74
+ target: "whatsapp:+15550000000",
75
+ scheduledFor: "2026-07-29T09:00:00.000Z",
76
+ };
77
+ const a = await openRoutineRun(driver, input);
78
+ const b = await openRoutineRun(driver, input);
79
+ expect(a).not.toBe(b);
80
+ expect(driver.runs).toHaveLength(2);
81
+ });
82
+ });
83
+ describe("closeRoutineRun", () => {
84
+ it("sets the outcome, endedAt and a measured ranMs", async () => {
85
+ const driver = fakeDriver();
86
+ await closeRoutineRun(driver, "run-1", {
87
+ outcome: "accepted",
88
+ dispatchResult: "accepted",
89
+ httpStatus: 200,
90
+ });
91
+ expect(driver.runs).toHaveLength(1);
92
+ const q = driver.runs[0].query;
93
+ expect(q).toContain("MATCH (r:RoutineRun {runId: $runId})");
94
+ expect(q).toContain("r.status = $outcome");
95
+ expect(q).toContain("datetime($endedAt).epochMillis - datetime(r.startedAt).epochMillis");
96
+ expect(driver.runs[0].params).toMatchObject({
97
+ runId: "run-1",
98
+ outcome: "accepted",
99
+ dispatchResult: "accepted",
100
+ httpStatus: 200,
101
+ });
102
+ });
103
+ it("is a no-op on a null runId (the open failed or was never taken)", async () => {
104
+ const driver = fakeDriver();
105
+ await closeRoutineRun(driver, null, { outcome: "failed" });
106
+ expect(driver.runs).toHaveLength(0);
107
+ });
108
+ it("never throws when the write fails", async () => {
109
+ const driver = {
110
+ session: () => ({
111
+ run: vi.fn(async () => {
112
+ throw new Error("neo4j down");
113
+ }),
114
+ close: vi.fn(async () => { }),
115
+ }),
116
+ };
117
+ await expect(closeRoutineRun(driver, "run-1", { outcome: "failed", error: "boom" })).resolves.toBeUndefined();
118
+ });
119
+ });
120
+ describe("recordRunSession", () => {
121
+ it("stores the session key, the transcript offset and bounded=true", async () => {
122
+ const driver = fakeDriver();
123
+ await recordRunSession(driver, "run-1", {
124
+ sessionKey: "8ba1f109-280d-4c15-9e0b-1f7cba6a1a11",
125
+ transcriptOffset: 148213,
126
+ bounded: true,
127
+ });
128
+ expect(driver.runs[0].params).toMatchObject({
129
+ runId: "run-1",
130
+ sessionKey: "8ba1f109-280d-4c15-9e0b-1f7cba6a1a11",
131
+ transcriptOffset: 148213,
132
+ bounded: true,
133
+ });
134
+ });
135
+ it("stores bounded=false with a null offset when the transcript could not be located", async () => {
136
+ const driver = fakeDriver();
137
+ await recordRunSession(driver, "run-1", {
138
+ sessionKey: "8ba1f109-280d-4c15-9e0b-1f7cba6a1a11",
139
+ transcriptOffset: null,
140
+ bounded: false,
141
+ });
142
+ expect(driver.runs[0].params).toMatchObject({ bounded: false, transcriptOffset: null });
143
+ });
144
+ it("is a no-op on a null runId", async () => {
145
+ const driver = fakeDriver();
146
+ await recordRunSession(driver, null, {
147
+ sessionKey: null,
148
+ transcriptOffset: null,
149
+ bounded: false,
150
+ });
151
+ expect(driver.runs).toHaveLength(0);
152
+ });
153
+ });
154
+ function driverReturning(rows) {
155
+ const runs = [];
156
+ return {
157
+ runs,
158
+ session: () => ({
159
+ run: vi.fn(async (query, params) => {
160
+ runs.push({ query, params });
161
+ // The promote path issues a second, per-row UPDATE against the same
162
+ // driver; returning the selection rows for it would loop forever, so
163
+ // only the first query (the selection) yields rows.
164
+ return { records: runs.length === 1 ? rows.map((r) => ({ get: (k) => r[k] })) : [] };
165
+ }),
166
+ close: vi.fn(async () => { }),
167
+ }),
168
+ };
169
+ }
170
+ describe("promoteRoutineRuns", () => {
171
+ const EVENT = "9f3ab21c-0000-4000-8000-000000000000";
172
+ const MARK = `{"text":"… event 9f3ab21c, configured by …"}\n`;
173
+ const row = {
174
+ runId: "run-1",
175
+ sessionKey: "sess-1",
176
+ eventId: EVENT,
177
+ transcriptOffset: 100,
178
+ status: "accepted",
179
+ };
180
+ it("promotes to started when this run's marker landed but nothing answered", async () => {
181
+ const driver = driverReturning([row]);
182
+ const out = await promoteRoutineRuns(driver, "acct-1", {
183
+ projectDirFor: () => "/tmp/proj",
184
+ readTail: () => MARK,
185
+ });
186
+ expect(out).toEqual({ started: 1, finished: 0 });
187
+ const write = driver.runs.find((r) => r.query.includes("r.status = $status"));
188
+ expect(write?.params).toMatchObject({ runId: "run-1", status: "started", finishedAt: null });
189
+ });
190
+ it("promotes to finished when an assistant row follows this run's marker", async () => {
191
+ const driver = driverReturning([row]);
192
+ const out = await promoteRoutineRuns(driver, "acct-1", {
193
+ projectDirFor: () => "/tmp/proj",
194
+ readTail: () => MARK + '{"type":"assistant","message":{"role":"assistant"}}\n',
195
+ });
196
+ expect(out).toEqual({ started: 0, finished: 1 });
197
+ const write = driver.runs.find((r) => r.query.includes("r.status = $status"));
198
+ expect(write?.params).toMatchObject({ runId: "run-1", status: "finished" });
199
+ expect(typeof write?.params.finishedAt).toBe("string");
200
+ });
201
+ it("does NOT promote on the operator's own traffic in the shared transcript", async () => {
202
+ // The record-review defect: a fire that was accepted but never spawned, and
203
+ // the operator later chats on the same thread. Bytes appeared and an
204
+ // assistant answered, but this run produced none of it.
205
+ const driver = driverReturning([row]);
206
+ const out = await promoteRoutineRuns(driver, "acct-1", {
207
+ projectDirFor: () => "/tmp/proj",
208
+ readTail: () => '{"role":"user","text":"hi"}\n{"role":"assistant","text":"hello"}\n',
209
+ });
210
+ expect(out).toEqual({ started: 0, finished: 0 });
211
+ expect(driver.runs.some((r) => r.query.includes("r.status = $status"))).toBe(false);
212
+ });
213
+ it("bounds a run's window above by the next run's offset on the same transcript", async () => {
214
+ const reads = [];
215
+ const driver = driverReturning([
216
+ { ...row, runId: "run-1", transcriptOffset: 100 },
217
+ { ...row, runId: "run-2", transcriptOffset: 500, status: "finished" },
218
+ ]);
219
+ await promoteRoutineRuns(driver, "acct-1", {
220
+ projectDirFor: () => "/tmp/proj",
221
+ readTail: (_p, from, to) => {
222
+ reads.push([from, to]);
223
+ return MARK;
224
+ },
225
+ });
226
+ // run-1's ceiling is run-2's offset; run-2 is terminal and is not read.
227
+ expect(reads).toEqual([[100, 500]]);
228
+ });
229
+ it("leaves the newest run's window open-ended", async () => {
230
+ const reads = [];
231
+ const driver = driverReturning([row]);
232
+ await promoteRoutineRuns(driver, "acct-1", {
233
+ projectDirFor: () => "/tmp/proj",
234
+ readTail: (_p, from, to) => {
235
+ reads.push([from, to]);
236
+ return MARK;
237
+ },
238
+ });
239
+ expect(reads).toEqual([[100, null]]);
240
+ });
241
+ it("does not carry a ceiling across two different transcripts", async () => {
242
+ const reads = [];
243
+ const driver = driverReturning([
244
+ { ...row, runId: "run-1", sessionKey: "sess-1", transcriptOffset: 100 },
245
+ { ...row, runId: "run-2", sessionKey: "sess-2", transcriptOffset: 500 },
246
+ ]);
247
+ await promoteRoutineRuns(driver, "acct-1", {
248
+ projectDirFor: () => "/tmp/proj",
249
+ readTail: (_p, from, to) => {
250
+ reads.push([from, to]);
251
+ return MARK;
252
+ },
253
+ });
254
+ expect(reads).toEqual([
255
+ [100, null],
256
+ [500, null],
257
+ ]);
258
+ });
259
+ it("leaves the record alone when nothing was appended", async () => {
260
+ const driver = driverReturning([row]);
261
+ const out = await promoteRoutineRuns(driver, "acct-1", {
262
+ projectDirFor: () => "/tmp/proj",
263
+ readTail: () => "",
264
+ });
265
+ expect(out).toEqual({ started: 0, finished: 0 });
266
+ expect(driver.runs.some((r) => r.query.includes("r.status = $status"))).toBe(false);
267
+ });
268
+ it("leaves the record alone when the transcript cannot be located", async () => {
269
+ const driver = driverReturning([row]);
270
+ const out = await promoteRoutineRuns(driver, "acct-1", {
271
+ projectDirFor: () => null,
272
+ readTail: () => "should not be called",
273
+ });
274
+ expect(out).toEqual({ started: 0, finished: 0 });
275
+ });
276
+ it("does not re-promote a record already at the status the evidence implies", async () => {
277
+ const driver = driverReturning([{ ...row, status: "started" }]);
278
+ const out = await promoteRoutineRuns(driver, "acct-1", {
279
+ projectDirFor: () => "/tmp/proj",
280
+ readTail: () => MARK,
281
+ });
282
+ expect(out).toEqual({ started: 0, finished: 0 });
283
+ expect(driver.runs.some((r) => r.query.includes("r.status = $status"))).toBe(false);
284
+ });
285
+ it("selects every bounded record, ordered so each one's ceiling is its successor", async () => {
286
+ const driver = driverReturning([]);
287
+ await promoteRoutineRuns(driver, "acct-1", {
288
+ projectDirFor: () => null,
289
+ readTail: () => "",
290
+ });
291
+ const q = driver.runs[0].query;
292
+ expect(q).toContain("r.bounded = true");
293
+ // Terminal records are NOT filtered out in Cypher: a finished successor is
294
+ // what closes its predecessor's window, so it must come back in the rows.
295
+ expect(q).not.toContain("r.status IN");
296
+ expect(q).toContain("ORDER BY r.sessionKey, r.transcriptOffset");
297
+ });
298
+ });
299
+ describe("sweepRoutineRuns", () => {
300
+ it("deletes records older than the retention bound and reports the count", async () => {
301
+ const driver = driverReturning([{ deleted: 7 }]);
302
+ const nowMs = Date.parse("2026-07-29T12:00:00.000Z");
303
+ const deleted = await sweepRoutineRuns(driver, "acct-1", nowMs);
304
+ expect(deleted).toBe(7);
305
+ expect(driver.runs[0].query).toContain("DETACH DELETE r");
306
+ expect(driver.runs[0].params.cutoff).toBe(new Date(nowMs - RETENTION_DAYS * 24 * 60 * 60 * 1000).toISOString());
307
+ });
308
+ it("returns 0 and never throws when the delete fails", async () => {
309
+ const driver = {
310
+ session: () => ({
311
+ run: vi.fn(async () => {
312
+ throw new Error("neo4j down");
313
+ }),
314
+ close: vi.fn(async () => { }),
315
+ }),
316
+ };
317
+ await expect(sweepRoutineRuns(driver, "acct-1", Date.now())).resolves.toBe(0);
318
+ });
319
+ });
320
+ describe("auditRunOrphans", () => {
321
+ it("counts open records older than the dispatch ceiling and emits every tick", async () => {
322
+ const driver = driverReturning([{ runId: "run-1" }, { runId: "run-2" }]);
323
+ const lines = [];
324
+ const spy = vi.spyOn(console, "error").mockImplementation((m) => void lines.push(String(m)));
325
+ const nowMs = Date.parse("2026-07-29T12:00:00.000Z");
326
+ await auditRunOrphans(driver, "acct-1234abcd", nowMs);
327
+ spy.mockRestore();
328
+ expect(driver.runs[0].params.cutoff).toBe(new Date(nowMs - ORPHAN_AFTER_MS).toISOString());
329
+ expect(lines.join("\n")).toContain("op=run-orphans acct=acct-123 count=2 runIds=[run-1,run-2]");
330
+ });
331
+ it("emits count=0 when there are none", async () => {
332
+ const driver = driverReturning([]);
333
+ const lines = [];
334
+ const spy = vi.spyOn(console, "error").mockImplementation((m) => void lines.push(String(m)));
335
+ await auditRunOrphans(driver, "acct-1234abcd", Date.now());
336
+ spy.mockRestore();
337
+ expect(lines.join("\n")).toContain("op=run-orphans acct=acct-123 count=0 runIds=[]");
338
+ });
339
+ });
340
+ describe("auditFiresWithoutRecords", () => {
341
+ it("reports events whose lastTriggered moved past the watermark with no record", async () => {
342
+ const driver = driverReturning([{ eventId: "evt-1", lastTriggered: "2026-07-29T11:00:00.000Z" }]);
343
+ const lines = [];
344
+ const spy = vi.spyOn(console, "error").mockImplementation((m) => void lines.push(String(m)));
345
+ const next = await auditFiresWithoutRecords(driver, "acct-1234abcd", "2026-07-29T10:00:00.000Z");
346
+ spy.mockRestore();
347
+ expect(driver.runs[0].params.watermark).toBe("2026-07-29T10:00:00.000Z");
348
+ expect(driver.runs[0].query).toContain("r.scheduledFor = e.lastTriggered");
349
+ expect(lines.join("\n")).toContain("op=fires-without-records acct=acct-123 count=1 eventIds=[evt-1]");
350
+ expect(next).toBe("2026-07-29T11:00:00.000Z");
351
+ });
352
+ it("returns the previous watermark unchanged when nothing fired", async () => {
353
+ const driver = driverReturning([]);
354
+ const spy = vi.spyOn(console, "error").mockImplementation(() => { });
355
+ const next = await auditFiresWithoutRecords(driver, "acct-1", "2026-07-29T10:00:00.000Z");
356
+ spy.mockRestore();
357
+ expect(next).toBe("2026-07-29T10:00:00.000Z");
358
+ });
359
+ it("starts from the epoch when there is no stored watermark", async () => {
360
+ const driver = driverReturning([]);
361
+ const spy = vi.spyOn(console, "error").mockImplementation(() => { });
362
+ await auditFiresWithoutRecords(driver, "acct-1", null);
363
+ spy.mockRestore();
364
+ expect(driver.runs[0].params.watermark).toBe(new Date(0).toISOString());
365
+ });
366
+ });
367
+ describe("auditRunCensus", () => {
368
+ it("reports total and oldest every tick", async () => {
369
+ const driver = driverReturning([{ total: 2903, oldest: "2026-06-29T00:00:00.000Z" }]);
370
+ const lines = [];
371
+ const spy = vi.spyOn(console, "error").mockImplementation((m) => void lines.push(String(m)));
372
+ await auditRunCensus(driver, "acct-1234abcd");
373
+ spy.mockRestore();
374
+ expect(lines.join("\n")).toContain("op=run-census acct=acct-123 total=2903 oldest=2026-06-29T00:00:00.000Z");
375
+ });
376
+ it("reports oldest=- on an empty census", async () => {
377
+ const driver = driverReturning([{ total: 0, oldest: null }]);
378
+ const lines = [];
379
+ const spy = vi.spyOn(console, "error").mockImplementation((m) => void lines.push(String(m)));
380
+ await auditRunCensus(driver, "acct-1234abcd");
381
+ spy.mockRestore();
382
+ expect(lines.join("\n")).toContain("op=run-census acct=acct-123 total=0 oldest=-");
383
+ });
384
+ });
385
+ describe("readTranscriptTail", () => {
386
+ it("cuts at the BYTE offset, not the UTF-16 code-unit index", () => {
387
+ const dir = mkdtempSync(join(tmpdir(), "routine-run-tail-"));
388
+ const path = join(dir, "t.jsonl");
389
+ // 'é' is one code unit but two bytes. schedule-inject records
390
+ // statSync().size, a BYTE count, so a code-unit slice would start one
391
+ // character late here and drop the head of the run's output.
392
+ const head = '{"role":"user","text":"café"}\n';
393
+ writeFileSync(path, head + '{"role":"assistant"}\n', "utf8");
394
+ const byteOffset = Buffer.byteLength(head, "utf8");
395
+ expect(byteOffset).not.toBe(head.length); // the divergence this guards
396
+ expect(readTranscriptTail(path, byteOffset)).toBe('{"role":"assistant"}\n');
397
+ rmSync(dir, { recursive: true, force: true });
398
+ });
399
+ it("returns an empty string when nothing has been appended since the boundary", () => {
400
+ const dir = mkdtempSync(join(tmpdir(), "routine-run-tail-"));
401
+ const path = join(dir, "t.jsonl");
402
+ writeFileSync(path, "abc", "utf8");
403
+ expect(readTranscriptTail(path, 3)).toBe("");
404
+ rmSync(dir, { recursive: true, force: true });
405
+ });
406
+ it("returns null when the file is unreadable", () => {
407
+ expect(readTranscriptTail(join(tmpdir(), "definitely-not-here.jsonl"), 0)).toBeNull();
408
+ });
409
+ });
410
+ describe("classifyRunEvidence", () => {
411
+ const EVENT = "9f3ab21c-0000-4000-8000-000000000000";
412
+ const MARKER = "event 9f3ab21c";
413
+ it("is 'none' when this run's own marker never landed in the window", () => {
414
+ // The defect this rule exists to remove: an hourly routine whose 09:00 fire
415
+ // was accepted but never spawned, and at 09:30 the OPERATOR chats on the
416
+ // same thread. Bytes appeared and an assistant answered, but none of it is
417
+ // this run's, so the record must stay accepted rather than report finished.
418
+ const operatorTraffic = '{"role":"user","text":"hi"}\n{"role":"assistant","text":"hello"}\n';
419
+ expect(classifyRunEvidence(operatorTraffic, EVENT)).toBe("none");
420
+ });
421
+ it("is 'started' when the marker landed but nothing answered", () => {
422
+ expect(classifyRunEvidence(`{"text":"… ${MARKER}, configured by …"}\n`, EVENT)).toBe("started");
423
+ });
424
+ it("is 'finished' when an assistant row follows the marker", () => {
425
+ const w = `{"text":"… ${MARKER} …"}\n{"role":"assistant","text":"done"}\n`;
426
+ expect(classifyRunEvidence(w, EVENT)).toBe("finished");
427
+ });
428
+ it("does not credit an assistant row that PRECEDES the marker", () => {
429
+ // The operator's earlier conversation sits above this run's injection.
430
+ const w = `{"role":"assistant","text":"earlier reply"}\n{"text":"… ${MARKER} …"}\n`;
431
+ expect(classifyRunEvidence(w, EVENT)).toBe("started");
432
+ });
433
+ it("does not match another routine's marker", () => {
434
+ const w = '{"text":"… event deadbeef …"}\n{"role":"assistant"}\n';
435
+ expect(classifyRunEvidence(w, EVENT)).toBe("none");
436
+ });
437
+ });
438
+ describe("readTranscriptTail — upper bound", () => {
439
+ it("stops at the ceiling so one run cannot read the next run's output", () => {
440
+ const dir = mkdtempSync(join(tmpdir(), "routine-run-ceil-"));
441
+ const path = join(dir, "t.jsonl");
442
+ const mine = "AAAA";
443
+ const theirs = "BBBB";
444
+ writeFileSync(path, mine + theirs, "utf8");
445
+ expect(readTranscriptTail(path, 0, 4)).toBe("AAAA");
446
+ expect(readTranscriptTail(path, 0, null)).toBe("AAAABBBB");
447
+ rmSync(dir, { recursive: true, force: true });
448
+ });
449
+ it("clamps a ceiling past end of file", () => {
450
+ const dir = mkdtempSync(join(tmpdir(), "routine-run-ceil-"));
451
+ const path = join(dir, "t.jsonl");
452
+ writeFileSync(path, "AAAA", "utf8");
453
+ expect(readTranscriptTail(path, 0, 9999)).toBe("AAAA");
454
+ rmSync(dir, { recursive: true, force: true });
455
+ });
456
+ });
457
+ //# sourceMappingURL=routine-run.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routine-run.test.js","sourceRoot":"","sources":["../../../src/lib/__tests__/routine-run.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAC7D,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EACL,cAAc,EACd,eAAe,EACf,gBAAgB,EAChB,kBAAkB,EAClB,gBAAgB,EAChB,eAAe,EACf,wBAAwB,EACxB,cAAc,EACd,cAAc,EACd,eAAe,EACf,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,mBAAmB,CAAC;AAE3B,SAAS,UAAU;IACjB,MAAM,IAAI,GAA8D,EAAE,CAAC;IAC3E,OAAO;QACL,IAAI;QACJ,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC;YACd,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,EAAE,KAAa,EAAE,MAA+B,EAAE,EAAE;gBAClE,IAAI,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;gBAC7B,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;YACzB,CAAC,CAAC;YACF,KAAK,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE,GAAE,CAAC,CAAC;SAC7B,CAAC;KACH,CAAC;AACJ,CAAC;AAED,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,EAAE,CAAC,gEAAgE,EAAE,KAAK,IAAI,EAAE;QAC9E,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;QAC5B,MAAM,KAAK,GAAG,MAAM,cAAc,CAAC,MAAe,EAAE;YAClD,OAAO,EAAE,OAAO;YAChB,SAAS,EAAE,QAAQ;YACnB,IAAI,EAAE,WAAW;YACjB,IAAI,EAAE,OAAO;YACb,MAAM,EAAE,uBAAuB;YAC/B,YAAY,EAAE,0BAA0B;SACzC,CAAC,CAAC;QAEH,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC;QACzC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QACpC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,8BAA8B,CAAC,CAAC;QACvE,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,2BAA2B,CAAC,CAAC;QACpE,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAgC,CAAC;QACrE,MAAM,CAAC,KAAK,CAAC,CAAC,aAAa,CAAC;YAC1B,KAAK;YACL,OAAO,EAAE,OAAO;YAChB,SAAS,EAAE,QAAQ;YACnB,IAAI,EAAE,WAAW;YACjB,IAAI,EAAE,OAAO;YACb,MAAM,EAAE,MAAM;YACd,MAAM,EAAE,uBAAuB;YAC/B,YAAY,EAAE,0BAA0B;YACxC,OAAO,EAAE,KAAK;SACf,CAAC,CAAC;QACH,MAAM,CAAC,OAAO,KAAK,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oDAAoD,EAAE,KAAK,IAAI,EAAE;QAClE,MAAM,MAAM,GAAG;YACb,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC;gBACd,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE;oBACpB,MAAM,IAAI,KAAK,CAAC,YAAY,CAAC,CAAC;gBAChC,CAAC,CAAC;gBACF,KAAK,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE,GAAE,CAAC,CAAC;aAC7B,CAAC;SACH,CAAC;QACF,MAAM,KAAK,GAAG,MAAM,cAAc,CAAC,MAAe,EAAE;YAClD,OAAO,EAAE,OAAO;YAChB,SAAS,EAAE,QAAQ;YACnB,IAAI,EAAE,UAAU;YAChB,IAAI,EAAE,MAAM;YACZ,MAAM,EAAE,GAAG;YACX,YAAY,EAAE,0BAA0B;SACzC,CAAC,CAAC;QACH,MAAM,CAAC,KAAK,CAAC,CAAC,QAAQ,EAAE,CAAC;IAC3B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,KAAK,IAAI,EAAE;QACnE,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;QAC5B,MAAM,KAAK,GAAG;YACZ,OAAO,EAAE,OAAO;YAChB,SAAS,EAAE,QAAQ;YACnB,IAAI,EAAE,WAAoB;YAC1B,IAAI,EAAE,OAAgB;YACtB,MAAM,EAAE,uBAAuB;YAC/B,YAAY,EAAE,0BAA0B;SACzC,CAAC;QACF,MAAM,CAAC,GAAG,MAAM,cAAc,CAAC,MAAe,EAAE,KAAK,CAAC,CAAC;QACvD,MAAM,CAAC,GAAG,MAAM,cAAc,CAAC,MAAe,EAAE,KAAK,CAAC,CAAC;QACvD,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACtB,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IACtC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAC/B,EAAE,CAAC,gDAAgD,EAAE,KAAK,IAAI,EAAE;QAC9D,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;QAC5B,MAAM,eAAe,CAAC,MAAe,EAAE,OAAO,EAAE;YAC9C,OAAO,EAAE,UAAU;YACnB,cAAc,EAAE,UAAU;YAC1B,UAAU,EAAE,GAAG;SAChB,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QACpC,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;QAC/B,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,sCAAsC,CAAC,CAAC;QAC5D,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,qBAAqB,CAAC,CAAC;QAC3C,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,oEAAoE,CAAC,CAAC;QAC1F,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC;YAC1C,KAAK,EAAE,OAAO;YACd,OAAO,EAAE,UAAU;YACnB,cAAc,EAAE,UAAU;YAC1B,UAAU,EAAE,GAAG;SAChB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iEAAiE,EAAE,KAAK,IAAI,EAAE;QAC/E,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;QAC5B,MAAM,eAAe,CAAC,MAAe,EAAE,IAAI,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,CAAC;QACpE,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IACtC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mCAAmC,EAAE,KAAK,IAAI,EAAE;QACjD,MAAM,MAAM,GAAG;YACb,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC;gBACd,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE;oBACpB,MAAM,IAAI,KAAK,CAAC,YAAY,CAAC,CAAC;gBAChC,CAAC,CAAC;gBACF,KAAK,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE,GAAE,CAAC,CAAC;aAC7B,CAAC;SACH,CAAC;QACF,MAAM,MAAM,CACV,eAAe,CAAC,MAAe,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAChF,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAC;IAC7B,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;IAChC,EAAE,CAAC,gEAAgE,EAAE,KAAK,IAAI,EAAE;QAC9E,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;QAC5B,MAAM,gBAAgB,CAAC,MAAe,EAAE,OAAO,EAAE;YAC/C,UAAU,EAAE,sCAAsC;YAClD,gBAAgB,EAAE,MAAM;YACxB,OAAO,EAAE,IAAI;SACd,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC;YAC1C,KAAK,EAAE,OAAO;YACd,UAAU,EAAE,sCAAsC;YAClD,gBAAgB,EAAE,MAAM;YACxB,OAAO,EAAE,IAAI;SACd,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kFAAkF,EAAE,KAAK,IAAI,EAAE;QAChG,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;QAC5B,MAAM,gBAAgB,CAAC,MAAe,EAAE,OAAO,EAAE;YAC/C,UAAU,EAAE,sCAAsC;YAClD,gBAAgB,EAAE,IAAI;YACtB,OAAO,EAAE,KAAK;SACf,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,gBAAgB,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1F,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4BAA4B,EAAE,KAAK,IAAI,EAAE;QAC1C,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;QAC5B,MAAM,gBAAgB,CAAC,MAAe,EAAE,IAAI,EAAE;YAC5C,UAAU,EAAE,IAAI;YAChB,gBAAgB,EAAE,IAAI;YACtB,OAAO,EAAE,KAAK;SACf,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IACtC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,SAAS,eAAe,CAAC,IAAoC;IAC3D,MAAM,IAAI,GAA8D,EAAE,CAAC;IAC3E,OAAO;QACL,IAAI;QACJ,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC;YACd,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,EAAE,KAAa,EAAE,MAA+B,EAAE,EAAE;gBAClE,IAAI,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;gBAC7B,oEAAoE;gBACpE,qEAAqE;gBACrE,oDAAoD;gBACpD,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;YAC/F,CAAC,CAAC;YACF,KAAK,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE,GAAE,CAAC,CAAC;SAC7B,CAAC;KACH,CAAC;AACJ,CAAC;AAED,QAAQ,CAAC,oBAAoB,EAAE,GAAG,EAAE;IAClC,MAAM,KAAK,GAAG,sCAAsC,CAAC;IACrD,MAAM,IAAI,GAAG,gDAAgD,CAAC;IAC9D,MAAM,GAAG,GAAG;QACV,KAAK,EAAE,OAAO;QACd,UAAU,EAAE,QAAQ;QACpB,OAAO,EAAE,KAAK;QACd,gBAAgB,EAAE,GAAG;QACrB,MAAM,EAAE,UAAU;KACnB,CAAC;IAEF,EAAE,CAAC,wEAAwE,EAAE,KAAK,IAAI,EAAE;QACtF,MAAM,MAAM,GAAG,eAAe,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACtC,MAAM,GAAG,GAAG,MAAM,kBAAkB,CAAC,MAAe,EAAE,QAAQ,EAAE;YAC9D,aAAa,EAAE,GAAG,EAAE,CAAC,WAAW;YAChC,QAAQ,EAAE,GAAG,EAAE,CAAC,IAAI;SACrB,CAAC,CAAC;QACH,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,CAAC;QACjD,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,oBAAoB,CAAC,CAAC,CAAC;QAC9E,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,aAAa,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/F,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sEAAsE,EAAE,KAAK,IAAI,EAAE;QACpF,MAAM,MAAM,GAAG,eAAe,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACtC,MAAM,GAAG,GAAG,MAAM,kBAAkB,CAAC,MAAe,EAAE,QAAQ,EAAE;YAC9D,aAAa,EAAE,GAAG,EAAE,CAAC,WAAW;YAChC,QAAQ,EAAE,GAAG,EAAE,CAAC,IAAI,GAAG,uDAAuD;SAC/E,CAAC,CAAC;QACH,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,CAAC;QACjD,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,oBAAoB,CAAC,CAAC,CAAC;QAC9E,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,aAAa,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;QAC5E,MAAM,CAAC,OAAO,KAAK,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yEAAyE,EAAE,KAAK,IAAI,EAAE;QACvF,4EAA4E;QAC5E,qEAAqE;QACrE,wDAAwD;QACxD,MAAM,MAAM,GAAG,eAAe,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACtC,MAAM,GAAG,GAAG,MAAM,kBAAkB,CAAC,MAAe,EAAE,QAAQ,EAAE;YAC9D,aAAa,EAAE,GAAG,EAAE,CAAC,WAAW;YAChC,QAAQ,EAAE,GAAG,EAAE,CAAC,oEAAoE;SACrF,CAAC,CAAC;QACH,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,CAAC;QACjD,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACtF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6EAA6E,EAAE,KAAK,IAAI,EAAE;QAC3F,MAAM,KAAK,GAAmC,EAAE,CAAC;QACjD,MAAM,MAAM,GAAG,eAAe,CAAC;YAC7B,EAAE,GAAG,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,gBAAgB,EAAE,GAAG,EAAE;YACjD,EAAE,GAAG,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,gBAAgB,EAAE,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE;SACtE,CAAC,CAAC;QACH,MAAM,kBAAkB,CAAC,MAAe,EAAE,QAAQ,EAAE;YAClD,aAAa,EAAE,GAAG,EAAE,CAAC,WAAW;YAChC,QAAQ,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE;gBACzB,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC;gBACvB,OAAO,IAAI,CAAC;YACd,CAAC;SACF,CAAC,CAAC;QACH,wEAAwE;QACxE,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;IACtC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2CAA2C,EAAE,KAAK,IAAI,EAAE;QACzD,MAAM,KAAK,GAAmC,EAAE,CAAC;QACjD,MAAM,MAAM,GAAG,eAAe,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACtC,MAAM,kBAAkB,CAAC,MAAe,EAAE,QAAQ,EAAE;YAClD,aAAa,EAAE,GAAG,EAAE,CAAC,WAAW;YAChC,QAAQ,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE;gBACzB,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC;gBACvB,OAAO,IAAI,CAAC;YACd,CAAC;SACF,CAAC,CAAC;QACH,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2DAA2D,EAAE,KAAK,IAAI,EAAE;QACzE,MAAM,KAAK,GAAmC,EAAE,CAAC;QACjD,MAAM,MAAM,GAAG,eAAe,CAAC;YAC7B,EAAE,GAAG,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,gBAAgB,EAAE,GAAG,EAAE;YACvE,EAAE,GAAG,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,gBAAgB,EAAE,GAAG,EAAE;SACxE,CAAC,CAAC;QACH,MAAM,kBAAkB,CAAC,MAAe,EAAE,QAAQ,EAAE;YAClD,aAAa,EAAE,GAAG,EAAE,CAAC,WAAW;YAChC,QAAQ,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE;gBACzB,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC;gBACvB,OAAO,IAAI,CAAC;YACd,CAAC;SACF,CAAC,CAAC;QACH,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC;YACpB,CAAC,GAAG,EAAE,IAAI,CAAC;YACX,CAAC,GAAG,EAAE,IAAI,CAAC;SACZ,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mDAAmD,EAAE,KAAK,IAAI,EAAE;QACjE,MAAM,MAAM,GAAG,eAAe,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACtC,MAAM,GAAG,GAAG,MAAM,kBAAkB,CAAC,MAAe,EAAE,QAAQ,EAAE;YAC9D,aAAa,EAAE,GAAG,EAAE,CAAC,WAAW;YAChC,QAAQ,EAAE,GAAG,EAAE,CAAC,EAAE;SACnB,CAAC,CAAC;QACH,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,CAAC;QACjD,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACtF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+DAA+D,EAAE,KAAK,IAAI,EAAE;QAC7E,MAAM,MAAM,GAAG,eAAe,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACtC,MAAM,GAAG,GAAG,MAAM,kBAAkB,CAAC,MAAe,EAAE,QAAQ,EAAE;YAC9D,aAAa,EAAE,GAAG,EAAE,CAAC,IAAI;YACzB,QAAQ,EAAE,GAAG,EAAE,CAAC,sBAAsB;SACvC,CAAC,CAAC;QACH,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yEAAyE,EAAE,KAAK,IAAI,EAAE;QACvF,MAAM,MAAM,GAAG,eAAe,CAAC,CAAC,EAAE,GAAG,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC;QAChE,MAAM,GAAG,GAAG,MAAM,kBAAkB,CAAC,MAAe,EAAE,QAAQ,EAAE;YAC9D,aAAa,EAAE,GAAG,EAAE,CAAC,WAAW;YAChC,QAAQ,EAAE,GAAG,EAAE,CAAC,IAAI;SACrB,CAAC,CAAC;QACH,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,CAAC;QACjD,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACtF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8EAA8E,EAAE,KAAK,IAAI,EAAE;QAC5F,MAAM,MAAM,GAAG,eAAe,CAAC,EAAE,CAAC,CAAC;QACnC,MAAM,kBAAkB,CAAC,MAAe,EAAE,QAAQ,EAAE;YAClD,aAAa,EAAE,GAAG,EAAE,CAAC,IAAI;YACzB,QAAQ,EAAE,GAAG,EAAE,CAAC,EAAE;SACnB,CAAC,CAAC;QACH,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;QAC/B,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,kBAAkB,CAAC,CAAC;QACxC,2EAA2E;QAC3E,0EAA0E;QAC1E,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC;QACvC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,2CAA2C,CAAC,CAAC;IACnE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;IAChC,EAAE,CAAC,sEAAsE,EAAE,KAAK,IAAI,EAAE;QACpF,MAAM,MAAM,GAAG,eAAe,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QACjD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC;QACrD,MAAM,OAAO,GAAG,MAAM,gBAAgB,CAAC,MAAe,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;QACzE,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACxB,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,iBAAiB,CAAC,CAAC;QAC1D,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CACvC,IAAI,IAAI,CAAC,KAAK,GAAG,cAAc,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,WAAW,EAAE,CACrE,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kDAAkD,EAAE,KAAK,IAAI,EAAE;QAChE,MAAM,MAAM,GAAG;YACb,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC;gBACd,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE;oBACpB,MAAM,IAAI,KAAK,CAAC,YAAY,CAAC,CAAC;gBAChC,CAAC,CAAC;gBACF,KAAK,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE,GAAE,CAAC,CAAC;aAC7B,CAAC;SACH,CAAC;QACF,MAAM,MAAM,CAAC,gBAAgB,CAAC,MAAe,EAAE,QAAQ,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACzF,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAC/B,EAAE,CAAC,0EAA0E,EAAE,KAAK,IAAI,EAAE;QACxF,MAAM,MAAM,GAAG,eAAe,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;QACzE,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,MAAM,GAAG,GAAG,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC7F,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC;QACrD,MAAM,eAAe,CAAC,MAAe,EAAE,eAAe,EAAE,KAAK,CAAC,CAAC;QAC/D,GAAG,CAAC,WAAW,EAAE,CAAC;QAElB,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,GAAG,eAAe,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;QAC3F,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,2DAA2D,CAAC,CAAC;IAClG,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mCAAmC,EAAE,KAAK,IAAI,EAAE;QACjD,MAAM,MAAM,GAAG,eAAe,CAAC,EAAE,CAAC,CAAC;QACnC,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,MAAM,GAAG,GAAG,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC7F,MAAM,eAAe,CAAC,MAAe,EAAE,eAAe,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;QACpE,GAAG,CAAC,WAAW,EAAE,CAAC;QAClB,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,gDAAgD,CAAC,CAAC;IACvF,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,0BAA0B,EAAE,GAAG,EAAE;IACxC,EAAE,CAAC,4EAA4E,EAAE,KAAK,IAAI,EAAE;QAC1F,MAAM,MAAM,GAAG,eAAe,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,0BAA0B,EAAE,CAAC,CAAC,CAAC;QAClG,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,MAAM,GAAG,GAAG,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC7F,MAAM,IAAI,GAAG,MAAM,wBAAwB,CAAC,MAAe,EAAE,eAAe,EAAE,0BAA0B,CAAC,CAAC;QAC1G,GAAG,CAAC,WAAW,EAAE,CAAC;QAElB,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;QACzE,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,kCAAkC,CAAC,CAAC;QAC3E,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,iEAAiE,CAAC,CAAC;QACtG,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6DAA6D,EAAE,KAAK,IAAI,EAAE;QAC3E,MAAM,MAAM,GAAG,eAAe,CAAC,EAAE,CAAC,CAAC;QACnC,MAAM,GAAG,GAAG,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,kBAAkB,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QACpE,MAAM,IAAI,GAAG,MAAM,wBAAwB,CAAC,MAAe,EAAE,QAAQ,EAAE,0BAA0B,CAAC,CAAC;QACnG,GAAG,CAAC,WAAW,EAAE,CAAC;QAClB,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yDAAyD,EAAE,KAAK,IAAI,EAAE;QACvE,MAAM,MAAM,GAAG,eAAe,CAAC,EAAE,CAAC,CAAC;QACnC,MAAM,GAAG,GAAG,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,kBAAkB,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QACpE,MAAM,wBAAwB,CAAC,MAAe,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC;QAChE,GAAG,CAAC,WAAW,EAAE,CAAC;QAClB,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;IAC1E,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,EAAE,CAAC,qCAAqC,EAAE,KAAK,IAAI,EAAE;QACnD,MAAM,MAAM,GAAG,eAAe,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,0BAA0B,EAAE,CAAC,CAAC,CAAC;QACtF,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,MAAM,GAAG,GAAG,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC7F,MAAM,cAAc,CAAC,MAAe,EAAE,eAAe,CAAC,CAAC;QACvD,GAAG,CAAC,WAAW,EAAE,CAAC;QAClB,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,wEAAwE,CAAC,CAAC;IAC/G,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qCAAqC,EAAE,KAAK,IAAI,EAAE;QACnD,MAAM,MAAM,GAAG,eAAe,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QAC7D,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,MAAM,GAAG,GAAG,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC7F,MAAM,cAAc,CAAC,MAAe,EAAE,eAAe,CAAC,CAAC;QACvD,GAAG,CAAC,WAAW,EAAE,CAAC;QAClB,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,8CAA8C,CAAC,CAAC;IACrF,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,oBAAoB,EAAE,GAAG,EAAE;IAClC,EAAE,CAAC,yDAAyD,EAAE,GAAG,EAAE;QACjE,MAAM,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,mBAAmB,CAAC,CAAC,CAAC;QAC7D,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QAClC,8DAA8D;QAC9D,sEAAsE;QACtE,6DAA6D;QAC7D,MAAM,IAAI,GAAG,iCAAiC,CAAC;QAC/C,aAAa,CAAC,IAAI,EAAE,IAAI,GAAG,wBAAwB,EAAE,MAAM,CAAC,CAAC;QAC7D,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACnD,MAAM,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,6BAA6B;QAEvE,MAAM,CAAC,kBAAkB,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;QAC5E,MAAM,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2EAA2E,EAAE,GAAG,EAAE;QACnF,MAAM,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,mBAAmB,CAAC,CAAC,CAAC;QAC7D,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QAClC,aAAa,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;QACnC,MAAM,CAAC,kBAAkB,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC7C,MAAM,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;QAClD,MAAM,CAAC,kBAAkB,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,2BAA2B,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;IACxF,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,qBAAqB,EAAE,GAAG,EAAE;IACnC,MAAM,KAAK,GAAG,sCAAsC,CAAC;IACrD,MAAM,MAAM,GAAG,gBAAgB,CAAC;IAEhC,EAAE,CAAC,iEAAiE,EAAE,GAAG,EAAE;QACzE,4EAA4E;QAC5E,yEAAyE;QACzE,2EAA2E;QAC3E,4EAA4E;QAC5E,MAAM,eAAe,GAAG,oEAAoE,CAAC;QAC7F,MAAM,CAAC,mBAAmB,CAAC,eAAe,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACnE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0DAA0D,EAAE,GAAG,EAAE;QAClE,MAAM,CAAC,mBAAmB,CAAC,cAAc,MAAM,uBAAuB,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAClG,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wDAAwD,EAAE,GAAG,EAAE;QAChE,MAAM,CAAC,GAAG,cAAc,MAAM,4CAA4C,CAAC;QAC3E,MAAM,CAAC,mBAAmB,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2DAA2D,EAAE,GAAG,EAAE;QACnE,uEAAuE;QACvE,MAAM,CAAC,GAAG,2DAA2D,MAAM,QAAQ,CAAC;QACpF,MAAM,CAAC,mBAAmB,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;QACjD,MAAM,CAAC,GAAG,uDAAuD,CAAC;QAClE,MAAM,CAAC,mBAAmB,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,kCAAkC,EAAE,GAAG,EAAE;IAChD,EAAE,CAAC,mEAAmE,EAAE,GAAG,EAAE;QAC3E,MAAM,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,mBAAmB,CAAC,CAAC,CAAC;QAC7D,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QAClC,MAAM,IAAI,GAAG,MAAM,CAAC;QACpB,MAAM,MAAM,GAAG,MAAM,CAAC;QACtB,aAAa,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,EAAE,MAAM,CAAC,CAAC;QAC3C,MAAM,CAAC,kBAAkB,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACpD,MAAM,CAAC,kBAAkB,CAAC,IAAI,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC3D,MAAM,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE;QAC3C,MAAM,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,mBAAmB,CAAC,CAAC,CAAC;QAC7D,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QAClC,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;QACpC,MAAM,CAAC,kBAAkB,CAAC,IAAI,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACvD,MAAM,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Task 2136 — the notes blob, bounded.
3
+ *
4
+ * `e.notes` was an uncapped free-text string with nine appenders, all in the
5
+ * same `\n[<iso>] <prose>` shape, interleaving fires with cancellations and
6
+ * lifecycle notes. Five of those appenders were fire lines and are gone: those
7
+ * facts now live on `:RoutineRun`, where they are readable without parsing
8
+ * prose. The four that remain are operator-facing prose, not run history, and
9
+ * stay.
10
+ *
11
+ * Those four trim at write time rather than through a sweep, so the blob is
12
+ * bounded by construction and an already-oversized blob shrinks the next time
13
+ * anything writes to it. No migration is needed and none ships.
14
+ */
15
+ /** How many trailing lines survive an append. */
16
+ export declare const NOTES_MAX_LINES = 50;
17
+ /**
18
+ * The Cypher fragment for "append this note and keep only the last
19
+ * NOTES_MAX_LINES lines", for use inside a SET clause. `nodeVar` is the bound
20
+ * node, `paramName` the query parameter holding the new note (which already
21
+ * carries its own leading newline, as every appender writes it).
22
+ *
23
+ * Split-and-rejoin rather than a byte slice: a byte cap can cut mid-line and
24
+ * leave a fragment that reads as a corrupted entry rather than a truncated
25
+ * history.
26
+ *
27
+ * Empty elements are dropped before the rejoin. Every appender writes a LEADING
28
+ * `\n`, so `split` yields an empty first element on every call; a naive
29
+ * `reduce(acc + '\n' + line)` would re-emit those empties and add one more each
30
+ * time, so the blob grew a blank line per append and the 50-line cap retained
31
+ * only ~25 real entries. Filtering them means the cap means what it says, and
32
+ * the single leading newline is restored once by the reduce itself.
33
+ */
34
+ export declare function appendNotesCapped(nodeVar: string, paramName: string): string;
35
+ //# sourceMappingURL=notes-cap.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notes-cap.d.ts","sourceRoot":"","sources":["../../src/lib/notes-cap.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,iDAAiD;AACjD,eAAO,MAAM,eAAe,KAAK,CAAC;AAElC;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAM5E"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Task 2136 — the notes blob, bounded.
3
+ *
4
+ * `e.notes` was an uncapped free-text string with nine appenders, all in the
5
+ * same `\n[<iso>] <prose>` shape, interleaving fires with cancellations and
6
+ * lifecycle notes. Five of those appenders were fire lines and are gone: those
7
+ * facts now live on `:RoutineRun`, where they are readable without parsing
8
+ * prose. The four that remain are operator-facing prose, not run history, and
9
+ * stay.
10
+ *
11
+ * Those four trim at write time rather than through a sweep, so the blob is
12
+ * bounded by construction and an already-oversized blob shrinks the next time
13
+ * anything writes to it. No migration is needed and none ships.
14
+ */
15
+ /** How many trailing lines survive an append. */
16
+ export const NOTES_MAX_LINES = 50;
17
+ /**
18
+ * The Cypher fragment for "append this note and keep only the last
19
+ * NOTES_MAX_LINES lines", for use inside a SET clause. `nodeVar` is the bound
20
+ * node, `paramName` the query parameter holding the new note (which already
21
+ * carries its own leading newline, as every appender writes it).
22
+ *
23
+ * Split-and-rejoin rather than a byte slice: a byte cap can cut mid-line and
24
+ * leave a fragment that reads as a corrupted entry rather than a truncated
25
+ * history.
26
+ *
27
+ * Empty elements are dropped before the rejoin. Every appender writes a LEADING
28
+ * `\n`, so `split` yields an empty first element on every call; a naive
29
+ * `reduce(acc + '\n' + line)` would re-emit those empties and add one more each
30
+ * time, so the blob grew a blank line per append and the 50-line cap retained
31
+ * only ~25 real entries. Filtering them means the cap means what it says, and
32
+ * the single leading newline is restored once by the reduce itself.
33
+ */
34
+ export function appendNotesCapped(nodeVar, paramName) {
35
+ return (`${nodeVar}.notes = reduce(acc = '', line IN ` +
36
+ `[l IN split(COALESCE(${nodeVar}.notes, '') + $${paramName}, '\\n') WHERE l <> ''][-${NOTES_MAX_LINES}..]` +
37
+ ` | acc + '\\n' + line)`);
38
+ }
39
+ //# sourceMappingURL=notes-cap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notes-cap.js","sourceRoot":"","sources":["../../src/lib/notes-cap.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,iDAAiD;AACjD,MAAM,CAAC,MAAM,eAAe,GAAG,EAAE,CAAC;AAElC;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAAe,EAAE,SAAiB;IAClE,OAAO,CACL,GAAG,OAAO,oCAAoC;QAC9C,wBAAwB,OAAO,kBAAkB,SAAS,4BAA4B,eAAe,KAAK;QAC1G,wBAAwB,CACzB,CAAC;AACJ,CAAC"}