@rubytech/create-maxy-code 0.1.576 → 0.1.578

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 (259) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/lib/active-rules/dist/index.d.ts.map +1 -1
  3. package/payload/platform/lib/active-rules/dist/index.js +32 -1
  4. package/payload/platform/lib/active-rules/dist/index.js.map +1 -1
  5. package/payload/platform/lib/active-rules/src/index.test.ts +52 -3
  6. package/payload/platform/lib/active-rules/src/index.ts +36 -2
  7. package/payload/platform/lib/dispatch-read/dist/allocate.d.ts +57 -0
  8. package/payload/platform/lib/dispatch-read/dist/allocate.d.ts.map +1 -0
  9. package/payload/platform/lib/dispatch-read/dist/allocate.js +33 -0
  10. package/payload/platform/lib/dispatch-read/dist/allocate.js.map +1 -0
  11. package/payload/platform/lib/dispatch-read/dist/index.d.ts +2 -0
  12. package/payload/platform/lib/dispatch-read/dist/index.d.ts.map +1 -1
  13. package/payload/platform/lib/dispatch-read/dist/index.js +10 -1
  14. package/payload/platform/lib/dispatch-read/dist/index.js.map +1 -1
  15. package/payload/platform/lib/dispatch-read/src/__tests__/allocate.test.ts +41 -0
  16. package/payload/platform/lib/dispatch-read/src/allocate.ts +89 -0
  17. package/payload/platform/lib/dispatch-read/src/index.ts +14 -0
  18. package/payload/platform/lib/routine-templates/dist/index.d.ts +4 -4
  19. package/payload/platform/lib/routine-templates/dist/index.js +4 -4
  20. package/payload/platform/lib/routine-templates/src/index.ts +4 -4
  21. package/payload/platform/plugins/admin/hooks/__tests__/prompt-optimiser-compliance.test.sh +7 -2
  22. package/payload/platform/plugins/admin/hooks/prompt-optimiser-compliance.sh +8 -2
  23. package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +4 -2
  24. package/payload/platform/plugins/admin/skills/whats-new/SKILL.md +17 -0
  25. package/payload/platform/plugins/cloudflare/mcp/__tests__/portal-visit-status-write.test.ts +333 -22
  26. package/payload/platform/plugins/cloudflare/mcp/__tests__/portal-visits-scope.test.ts +262 -0
  27. package/payload/platform/plugins/cloudflare/skills/data-portal/schema.sql +126 -21
  28. package/payload/platform/plugins/cloudflare/skills/data-portal/template/functions/api/visit-status.ts +142 -2
  29. package/payload/platform/plugins/cloudflare/skills/data-portal/template/functions/api/visits.ts +118 -6
  30. package/payload/platform/plugins/dispatch/PLUGIN.md +2 -0
  31. package/payload/platform/plugins/dispatch/mcp/dist/lib/allocate.d.ts +19 -50
  32. package/payload/platform/plugins/dispatch/mcp/dist/lib/allocate.d.ts.map +1 -1
  33. package/payload/platform/plugins/dispatch/mcp/dist/lib/allocate.js +1 -28
  34. package/payload/platform/plugins/dispatch/mcp/dist/lib/allocate.js.map +1 -1
  35. package/payload/platform/plugins/dispatch/skills/dispatch-page/SKILL.md +45 -6
  36. package/payload/platform/plugins/dispatch/skills/dispatch-page/template/planner.css +60 -0
  37. package/payload/platform/plugins/dispatch/skills/dispatch-page/template/planner.html +13 -0
  38. package/payload/platform/plugins/dispatch/skills/dispatch-page/template/planner.js +203 -5
  39. package/payload/platform/plugins/docs/references/internals.md +1 -1
  40. package/payload/platform/plugins/docs/references/platform.md +2 -0
  41. package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.js +0 -2
  42. package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.js.map +1 -1
  43. package/payload/platform/plugins/telegram/mcp/dist/__tests__/webhook-path.test.d.ts +2 -0
  44. package/payload/platform/plugins/telegram/mcp/dist/__tests__/webhook-path.test.d.ts.map +1 -0
  45. package/payload/platform/plugins/telegram/mcp/dist/__tests__/webhook-path.test.js +19 -0
  46. package/payload/platform/plugins/telegram/mcp/dist/__tests__/webhook-path.test.js.map +1 -0
  47. package/payload/platform/plugins/telegram/mcp/dist/__tests__/webhook-register.test.d.ts +2 -0
  48. package/payload/platform/plugins/telegram/mcp/dist/__tests__/webhook-register.test.d.ts.map +1 -0
  49. package/payload/platform/plugins/telegram/mcp/dist/__tests__/webhook-register.test.js +110 -0
  50. package/payload/platform/plugins/telegram/mcp/dist/__tests__/webhook-register.test.js.map +1 -0
  51. package/payload/platform/plugins/telegram/mcp/dist/__tests__/webhook-verdict.test.d.ts +2 -0
  52. package/payload/platform/plugins/telegram/mcp/dist/__tests__/webhook-verdict.test.d.ts.map +1 -0
  53. package/payload/platform/plugins/telegram/mcp/dist/__tests__/webhook-verdict.test.js +22 -0
  54. package/payload/platform/plugins/telegram/mcp/dist/__tests__/webhook-verdict.test.js.map +1 -0
  55. package/payload/platform/plugins/telegram/mcp/dist/index.js +19 -163
  56. package/payload/platform/plugins/telegram/mcp/dist/index.js.map +1 -1
  57. package/payload/platform/plugins/telegram/mcp/dist/lib/account-write.d.ts +9 -0
  58. package/payload/platform/plugins/telegram/mcp/dist/lib/account-write.d.ts.map +1 -1
  59. package/payload/platform/plugins/telegram/mcp/dist/lib/account-write.js +11 -0
  60. package/payload/platform/plugins/telegram/mcp/dist/lib/account-write.js.map +1 -1
  61. package/payload/platform/plugins/telegram/mcp/dist/lib/telegram.d.ts +30 -3
  62. package/payload/platform/plugins/telegram/mcp/dist/lib/telegram.d.ts.map +1 -1
  63. package/payload/platform/plugins/telegram/mcp/dist/lib/telegram.js +29 -4
  64. package/payload/platform/plugins/telegram/mcp/dist/lib/telegram.js.map +1 -1
  65. package/payload/platform/plugins/telegram/mcp/dist/tools/webhook-register.d.ts +33 -0
  66. package/payload/platform/plugins/telegram/mcp/dist/tools/webhook-register.d.ts.map +1 -0
  67. package/payload/platform/plugins/telegram/mcp/dist/tools/webhook-register.js +145 -0
  68. package/payload/platform/plugins/telegram/mcp/dist/tools/webhook-register.js.map +1 -0
  69. package/payload/platform/plugins/telegram/skills/configure/SKILL.md +4 -2
  70. package/payload/platform/services/telegram-channel/dist/notification.d.ts +35 -3
  71. package/payload/platform/services/telegram-channel/dist/notification.d.ts.map +1 -1
  72. package/payload/platform/services/telegram-channel/dist/notification.js +38 -5
  73. package/payload/platform/services/telegram-channel/dist/notification.js.map +1 -1
  74. package/payload/platform/services/telegram-channel/dist/server.js +1 -1
  75. package/payload/platform/services/telegram-channel/dist/server.js.map +1 -1
  76. package/payload/platform/services/webchat-channel/dist/notification.d.ts +2 -1
  77. package/payload/platform/services/webchat-channel/dist/notification.d.ts.map +1 -1
  78. package/payload/platform/services/webchat-channel/dist/notification.js.map +1 -1
  79. package/payload/platform/services/whatsapp-channel/dist/notification.d.ts +2 -2
  80. package/payload/platform/templates/agents/admin/IDENTITY.md +1 -1
  81. package/payload/server/public/activity.html +4 -4
  82. package/payload/server/public/agents.html +3 -3
  83. package/payload/server/public/assets/{AdminLoginScreens-BLGZEaKU.js → AdminLoginScreens-CAZ3DSwA.js} +1 -1
  84. package/payload/server/public/assets/AdminLoginScreens-CAZ3DSwA.js.br +0 -0
  85. package/payload/server/public/assets/AdminLoginScreens-CAZ3DSwA.js.gz +0 -0
  86. package/payload/server/public/assets/{AdminShell-C_M7YE5Z.js → AdminShell-BLs5v0qF.js} +1 -1
  87. package/payload/server/public/assets/AdminShell-BLs5v0qF.js.br +0 -0
  88. package/payload/server/public/assets/AdminShell-BLs5v0qF.js.gz +0 -0
  89. package/payload/server/public/assets/{activity-BL6qbB9a.js → activity-BwPck2yT.js} +1 -1
  90. package/payload/server/public/assets/activity-BwPck2yT.js.br +0 -0
  91. package/payload/server/public/assets/activity-BwPck2yT.js.gz +0 -0
  92. package/payload/server/public/assets/{admin-jnJ3P2u4.js → admin-DjtOoabA.js} +1 -1
  93. package/payload/server/public/assets/admin-DjtOoabA.js.br +0 -0
  94. package/payload/server/public/assets/admin-DjtOoabA.js.gz +0 -0
  95. package/payload/server/public/assets/{agents-BzhfKZDN.js → agents-IQYaRvoh.js} +1 -1
  96. package/payload/server/public/assets/agents-IQYaRvoh.js.br +0 -0
  97. package/payload/server/public/assets/agents-IQYaRvoh.js.gz +0 -0
  98. package/payload/server/public/assets/{browser-C-6io2B9.js → browser-CPG8w8rQ.js} +1 -1
  99. package/payload/server/public/assets/browser-CPG8w8rQ.js.br +0 -0
  100. package/payload/server/public/assets/browser-CPG8w8rQ.js.gz +0 -0
  101. package/payload/server/public/assets/{calendar-Dt3gS88s.js → calendar-CRwrgNdq.js} +1 -1
  102. package/payload/server/public/assets/calendar-CRwrgNdq.js.br +0 -0
  103. package/payload/server/public/assets/calendar-CRwrgNdq.js.gz +0 -0
  104. package/payload/server/public/assets/chat-B7yZ4KLl.js +1 -0
  105. package/payload/server/public/assets/chat-B7yZ4KLl.js.br +3 -0
  106. package/payload/server/public/assets/chat-B7yZ4KLl.js.gz +0 -0
  107. package/payload/server/public/assets/chevron-left-BzKUQqLy.js +1 -0
  108. package/payload/server/public/assets/chevron-left-BzKUQqLy.js.br +0 -0
  109. package/payload/server/public/assets/clock-BafWFNGo.js +1 -0
  110. package/payload/server/public/assets/clock-BafWFNGo.js.br +0 -0
  111. package/payload/server/public/assets/{copy-TkPJgllS.js → copy-JyiMTV0k.js} +1 -1
  112. package/payload/server/public/assets/copy-JyiMTV0k.js.br +0 -0
  113. package/payload/server/public/assets/copy-JyiMTV0k.js.gz +0 -0
  114. package/payload/server/public/assets/data-DHtGCVrl.js +1 -0
  115. package/payload/server/public/assets/data-DHtGCVrl.js.br +0 -0
  116. package/payload/server/public/assets/data-DHtGCVrl.js.gz +0 -0
  117. package/payload/server/public/assets/{file-text-DyAL2DCh.js → file-text-cnHv9ZS6.js} +1 -1
  118. package/payload/server/public/assets/file-text-cnHv9ZS6.js.br +0 -0
  119. package/payload/server/public/assets/file-text-cnHv9ZS6.js.gz +0 -0
  120. package/payload/server/public/assets/{graph-PiNIcCfX.js → graph-lFwEUDSH.js} +1 -1
  121. package/payload/server/public/assets/graph-lFwEUDSH.js.br +0 -0
  122. package/payload/server/public/assets/graph-lFwEUDSH.js.gz +0 -0
  123. package/payload/server/public/assets/{graph-labels-8jKFrLHn.js → graph-labels-C6qUA0vO.js} +1 -1
  124. package/payload/server/public/assets/graph-labels-C6qUA0vO.js.br +0 -0
  125. package/payload/server/public/assets/graph-labels-C6qUA0vO.js.gz +0 -0
  126. package/payload/server/public/assets/{operator-DKGKGzrb.js → operator-BdoEy5mh.js} +1 -1
  127. package/payload/server/public/assets/operator-BdoEy5mh.js.br +0 -0
  128. package/payload/server/public/assets/operator-BdoEy5mh.js.gz +0 -0
  129. package/payload/server/public/assets/{page-DXz_K10G.js → page-DMrnnXNA.js} +1 -1
  130. package/payload/server/public/assets/page-DMrnnXNA.js.br +0 -0
  131. package/payload/server/public/assets/page-DMrnnXNA.js.gz +0 -0
  132. package/payload/server/public/assets/{page-BU5vlY9Y.js → page-DeMikGYL.js} +1 -1
  133. package/payload/server/public/assets/page-DeMikGYL.js.br +0 -0
  134. package/payload/server/public/assets/page-DeMikGYL.js.gz +0 -0
  135. package/payload/server/public/assets/play-D6OAQVJ_.js +1 -0
  136. package/payload/server/public/assets/play-D6OAQVJ_.js.br +0 -0
  137. package/payload/server/public/assets/play-D6OAQVJ_.js.gz +0 -0
  138. package/payload/server/public/assets/{public-BmA3-jLj.js → public-B-X1Cxfw.js} +1 -1
  139. package/payload/server/public/assets/public-B-X1Cxfw.js.br +0 -0
  140. package/payload/server/public/assets/public-B-X1Cxfw.js.gz +0 -0
  141. package/payload/server/public/assets/{rotate-ccw-fCH0LSMq.js → rotate-ccw-DVFvQAHG.js} +1 -1
  142. package/payload/server/public/assets/rotate-ccw-DVFvQAHG.js.br +0 -0
  143. package/payload/server/public/assets/rotate-ccw-DVFvQAHG.js.gz +0 -0
  144. package/payload/server/public/assets/{routines-BeFrmkls.js → routines-CgkkGJaS.js} +1 -1
  145. package/payload/server/public/assets/routines-CgkkGJaS.js.br +0 -0
  146. package/payload/server/public/assets/routines-CgkkGJaS.js.gz +0 -0
  147. package/payload/server/public/assets/{skills-mjls5HBa.js → skills-CW7gVcaG.js} +1 -1
  148. package/payload/server/public/assets/skills-CW7gVcaG.js.br +0 -0
  149. package/payload/server/public/assets/skills-CW7gVcaG.js.gz +0 -0
  150. package/payload/server/public/assets/{tasks-p6puHHD0.js → tasks-Ddjp0Rwh.js} +1 -1
  151. package/payload/server/public/assets/tasks-Ddjp0Rwh.js.br +0 -0
  152. package/payload/server/public/assets/tasks-Ddjp0Rwh.js.gz +0 -0
  153. package/payload/server/public/assets/{triangle-alert-CrZ1ewbd.js → triangle-alert-DUrUutX4.js} +1 -1
  154. package/payload/server/public/assets/triangle-alert-DUrUutX4.js.br +0 -0
  155. package/payload/server/public/assets/triangle-alert-DUrUutX4.js.gz +0 -0
  156. package/payload/server/public/assets/{useCopyFeedback-zOQNrIwd.js → useCopyFeedback-ClVINDrQ.js} +1 -1
  157. package/payload/server/public/assets/useCopyFeedback-ClVINDrQ.js.br +0 -0
  158. package/payload/server/public/assets/useCopyFeedback-ClVINDrQ.js.gz +0 -0
  159. package/payload/server/public/assets/{useMediaQuery-BmG090FR.js → useMediaQuery-BUFkZYRs.js} +1 -1
  160. package/payload/server/public/assets/useMediaQuery-BUFkZYRs.js.br +0 -0
  161. package/payload/server/public/assets/{useMediaQuery-BmG090FR.js.gz → useMediaQuery-BUFkZYRs.js.gz} +0 -0
  162. package/payload/server/public/assets/{useVoiceRecorder-9pf6FFJ-.js → useVoiceRecorder-DnyqQFet.js} +1 -1
  163. package/payload/server/public/assets/useVoiceRecorder-DnyqQFet.js.br +0 -0
  164. package/payload/server/public/assets/useVoiceRecorder-DnyqQFet.js.gz +0 -0
  165. package/payload/server/public/assets/{wrench-k4GYG5rc.js → wrench-BW28s_d0.js} +1 -1
  166. package/payload/server/public/assets/wrench-BW28s_d0.js.br +0 -0
  167. package/payload/server/public/assets/wrench-BW28s_d0.js.gz +0 -0
  168. package/payload/server/public/browser.html +3 -3
  169. package/payload/server/public/calendar.html +6 -6
  170. package/payload/server/public/chat.html +12 -12
  171. package/payload/server/public/data.html +10 -10
  172. package/payload/server/public/graph.html +8 -8
  173. package/payload/server/public/index.html +12 -12
  174. package/payload/server/public/operator.html +13 -13
  175. package/payload/server/public/public.html +12 -12
  176. package/payload/server/public/routines.html +6 -6
  177. package/payload/server/public/skills.html +4 -4
  178. package/payload/server/public/tasks.html +5 -5
  179. package/payload/server/server.js +1014 -375
  180. package/payload/platform/plugins/dispatch/mcp/dist/scripts/converge-visit-instants.d.ts +0 -6
  181. package/payload/platform/plugins/dispatch/mcp/dist/scripts/converge-visit-instants.d.ts.map +0 -1
  182. package/payload/platform/plugins/dispatch/mcp/dist/scripts/converge-visit-instants.js +0 -102
  183. package/payload/platform/plugins/dispatch/mcp/dist/scripts/converge-visit-instants.js.map +0 -1
  184. package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/converge-routine-description.test.d.ts +0 -2
  185. package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/converge-routine-description.test.d.ts.map +0 -1
  186. package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/converge-routine-description.test.js +0 -87
  187. package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/converge-routine-description.test.js.map +0 -1
  188. package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/converge-startdate-utc.test.d.ts +0 -2
  189. package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/converge-startdate-utc.test.d.ts.map +0 -1
  190. package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/converge-startdate-utc.test.js +0 -79
  191. package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/converge-startdate-utc.test.js.map +0 -1
  192. package/payload/platform/plugins/scheduling/mcp/dist/scripts/converge-routine-description.d.ts +0 -35
  193. package/payload/platform/plugins/scheduling/mcp/dist/scripts/converge-routine-description.d.ts.map +0 -1
  194. package/payload/platform/plugins/scheduling/mcp/dist/scripts/converge-routine-description.js +0 -56
  195. package/payload/platform/plugins/scheduling/mcp/dist/scripts/converge-routine-description.js.map +0 -1
  196. package/payload/platform/plugins/scheduling/mcp/dist/scripts/converge-startdate-utc.d.ts +0 -24
  197. package/payload/platform/plugins/scheduling/mcp/dist/scripts/converge-startdate-utc.d.ts.map +0 -1
  198. package/payload/platform/plugins/scheduling/mcp/dist/scripts/converge-startdate-utc.js +0 -87
  199. package/payload/platform/plugins/scheduling/mcp/dist/scripts/converge-startdate-utc.js.map +0 -1
  200. package/payload/server/public/assets/AdminLoginScreens-BLGZEaKU.js.br +0 -0
  201. package/payload/server/public/assets/AdminLoginScreens-BLGZEaKU.js.gz +0 -0
  202. package/payload/server/public/assets/AdminShell-C_M7YE5Z.js.br +0 -0
  203. package/payload/server/public/assets/AdminShell-C_M7YE5Z.js.gz +0 -0
  204. package/payload/server/public/assets/activity-BL6qbB9a.js.br +0 -0
  205. package/payload/server/public/assets/activity-BL6qbB9a.js.gz +0 -0
  206. package/payload/server/public/assets/admin-jnJ3P2u4.js.br +0 -0
  207. package/payload/server/public/assets/admin-jnJ3P2u4.js.gz +0 -0
  208. package/payload/server/public/assets/agents-BzhfKZDN.js.br +0 -0
  209. package/payload/server/public/assets/agents-BzhfKZDN.js.gz +0 -0
  210. package/payload/server/public/assets/browser-C-6io2B9.js.br +0 -0
  211. package/payload/server/public/assets/browser-C-6io2B9.js.gz +0 -0
  212. package/payload/server/public/assets/calendar-Dt3gS88s.js.br +0 -0
  213. package/payload/server/public/assets/calendar-Dt3gS88s.js.gz +0 -0
  214. package/payload/server/public/assets/chat-IUOvVkL-.js +0 -1
  215. package/payload/server/public/assets/chat-IUOvVkL-.js.br +0 -1
  216. package/payload/server/public/assets/chat-IUOvVkL-.js.gz +0 -0
  217. package/payload/server/public/assets/chevron-left-DSzR9zR7.js +0 -1
  218. package/payload/server/public/assets/chevron-left-DSzR9zR7.js.br +0 -0
  219. package/payload/server/public/assets/clock-C5xE5p2I.js +0 -1
  220. package/payload/server/public/assets/clock-C5xE5p2I.js.br +0 -0
  221. package/payload/server/public/assets/copy-TkPJgllS.js.br +0 -0
  222. package/payload/server/public/assets/copy-TkPJgllS.js.gz +0 -0
  223. package/payload/server/public/assets/data-Bhv0Pvfl.js +0 -1
  224. package/payload/server/public/assets/data-Bhv0Pvfl.js.br +0 -0
  225. package/payload/server/public/assets/data-Bhv0Pvfl.js.gz +0 -0
  226. package/payload/server/public/assets/file-text-DyAL2DCh.js.br +0 -0
  227. package/payload/server/public/assets/file-text-DyAL2DCh.js.gz +0 -0
  228. package/payload/server/public/assets/graph-PiNIcCfX.js.br +0 -0
  229. package/payload/server/public/assets/graph-PiNIcCfX.js.gz +0 -0
  230. package/payload/server/public/assets/graph-labels-8jKFrLHn.js.br +0 -0
  231. package/payload/server/public/assets/graph-labels-8jKFrLHn.js.gz +0 -0
  232. package/payload/server/public/assets/operator-DKGKGzrb.js.br +0 -0
  233. package/payload/server/public/assets/operator-DKGKGzrb.js.gz +0 -0
  234. package/payload/server/public/assets/page-BU5vlY9Y.js.br +0 -0
  235. package/payload/server/public/assets/page-BU5vlY9Y.js.gz +0 -0
  236. package/payload/server/public/assets/page-DXz_K10G.js.br +0 -0
  237. package/payload/server/public/assets/page-DXz_K10G.js.gz +0 -0
  238. package/payload/server/public/assets/play-CmSyYrB6.js +0 -1
  239. package/payload/server/public/assets/play-CmSyYrB6.js.br +0 -0
  240. package/payload/server/public/assets/play-CmSyYrB6.js.gz +0 -0
  241. package/payload/server/public/assets/public-BmA3-jLj.js.br +0 -0
  242. package/payload/server/public/assets/public-BmA3-jLj.js.gz +0 -0
  243. package/payload/server/public/assets/rotate-ccw-fCH0LSMq.js.br +0 -0
  244. package/payload/server/public/assets/rotate-ccw-fCH0LSMq.js.gz +0 -0
  245. package/payload/server/public/assets/routines-BeFrmkls.js.br +0 -0
  246. package/payload/server/public/assets/routines-BeFrmkls.js.gz +0 -0
  247. package/payload/server/public/assets/skills-mjls5HBa.js.br +0 -0
  248. package/payload/server/public/assets/skills-mjls5HBa.js.gz +0 -0
  249. package/payload/server/public/assets/tasks-p6puHHD0.js.br +0 -0
  250. package/payload/server/public/assets/tasks-p6puHHD0.js.gz +0 -0
  251. package/payload/server/public/assets/triangle-alert-CrZ1ewbd.js.br +0 -0
  252. package/payload/server/public/assets/triangle-alert-CrZ1ewbd.js.gz +0 -0
  253. package/payload/server/public/assets/useCopyFeedback-zOQNrIwd.js.br +0 -0
  254. package/payload/server/public/assets/useCopyFeedback-zOQNrIwd.js.gz +0 -0
  255. package/payload/server/public/assets/useMediaQuery-BmG090FR.js.br +0 -0
  256. package/payload/server/public/assets/useVoiceRecorder-9pf6FFJ-.js.br +0 -0
  257. package/payload/server/public/assets/useVoiceRecorder-9pf6FFJ-.js.gz +0 -0
  258. package/payload/server/public/assets/wrench-k4GYG5rc.js.br +0 -0
  259. package/payload/server/public/assets/wrench-k4GYG5rc.js.gz +0 -0
@@ -17,6 +17,47 @@ export interface VisitRow {
17
17
  status: string
18
18
  startDate: string
19
19
  purpose: string
20
+ /**
21
+ * What the worker recorded, as COUNTS (Task 2511).
22
+ *
23
+ * Counts and never contents, which is this interface's own rule above applied
24
+ * rather than relaxed: the contents are files and the Task 1910 exchange
25
+ * carries them. A count says what was recorded and what is still missing,
26
+ * which is what the office could not see at all before, without putting a
27
+ * real person's written note or signature in a mirror on the open web. The
28
+ * contents are Task 2563.
29
+ *
30
+ * `checklistDone` is read against `checklistTotal` and never alone: a count
31
+ * of ticked items with no total says nothing about whether the work is done.
32
+ */
33
+ notes: number
34
+ media: number
35
+ parts: number
36
+ checklistDone: number
37
+ checklistTotal: number
38
+ signatures: number
39
+ }
40
+
41
+ /**
42
+ * One candidate for one unallocated visit (Task 2511).
43
+ *
44
+ * Precomputed on the install by the one implementation of qualification and
45
+ * clash, and rendered as returned. This endpoint applies no such rule of its own
46
+ * and neither does the page, for the reason `processVisits` states below.
47
+ *
48
+ * `kind` decides which of the last two fields carries anything. An `offered`
49
+ * row has an empty `reason` and its conflicts, which is `[]` when the worker is
50
+ * free; an `excluded` row has empty conflicts and its reason. A qualified
51
+ * worker already committed is OFFERED with the conflict shown and never
52
+ * dropped, because the office double-books on purpose.
53
+ */
54
+ export interface CandidateRow {
55
+ visitId: string
56
+ workerId: string
57
+ name: string
58
+ kind: string
59
+ reason: string
60
+ conflicts: Array<{ visitId: string; start: string; end: string }>
20
61
  }
21
62
 
22
63
  /**
@@ -46,6 +87,16 @@ export interface RosterRow {
46
87
  export interface Meta {
47
88
  vocabulary: { job: string; visit: string; worker: string }
48
89
  statuses: Array<{ name: string; terminal: boolean }>
90
+ /**
91
+ * The account's legal moves, `[from, to]` (Task 2511).
92
+ *
93
+ * Absent from the list means refused, and an empty list therefore refuses
94
+ * every move, which is what an account declaring none means. The page refuses
95
+ * from this published copy, so an illegal drag is refused while the install is
96
+ * offline; `visit-status.ts` refuses from the same copy, which is the refusal
97
+ * that binds.
98
+ */
99
+ transitions: Array<[string, string]>
49
100
  zone: string
50
101
  publishedAt: string
51
102
  }
@@ -100,7 +151,10 @@ export async function processVisits(
100
151
  // makes against directory_state, for the same reason.
101
152
  const sql =
102
153
  `SELECT v.visitId AS visitId, v.ownerId AS ownerId, v.jobId AS jobId,
103
- v.status AS status, v.startDate AS startDate, v.purpose AS purpose
154
+ v.status AS status, v.startDate AS startDate, v.purpose AS purpose,
155
+ v.notes AS notes, v.media AS media, v.parts AS parts,
156
+ v.checklistDone AS checklistDone, v.checklistTotal AS checklistTotal,
157
+ v.signatures AS signatures
104
158
  FROM visits v
105
159
  JOIN visits_state s
106
160
  ON s.accountId = v.accountId AND s.currentGeneration = v.generation
@@ -143,16 +197,69 @@ export async function processVisits(
143
197
  workingHours: parseJson<Record<string, [string, string]>>(r.workingHours, {}),
144
198
  }))
145
199
 
200
+ // THE SAME TWO FILTERS, applied through the visits join rather than beside it
201
+ // (Task 2511). A candidate row names a colleague, so an own-scoped person
202
+ // receiving candidates for a visit they cannot see would learn the roster the
203
+ // roster read above deliberately withholds from them. The join IS the owner
204
+ // filter; there is no second check to keep in step with it.
205
+ //
206
+ // Read through the generation pointer, and joined to the visits at the SAME
207
+ // generation, so the offers on screen always belong to the week on screen.
208
+ const candidateSql =
209
+ `SELECT c.visitId AS visitId, c.workerId AS workerId, c.name AS name,
210
+ c.kind AS kind, c.reason AS reason, c.conflicts AS conflicts
211
+ FROM visit_candidates c
212
+ JOIN visits v
213
+ ON v.accountId = c.accountId AND v.visitId = c.visitId
214
+ AND v.generation = c.generation
215
+ JOIN visits_state s
216
+ ON s.accountId = c.accountId AND s.currentGeneration = c.generation
217
+ WHERE c.accountId = ?` +
218
+ (scoped ? ' AND v.ownerId = ?' : '') +
219
+ ' ORDER BY c.visitId ASC, c.workerId ASC'
220
+ const candidateStmt = env.DB.prepare(candidateSql)
221
+ const candidateRows = await (
222
+ scoped
223
+ ? candidateStmt.bind(env.PORTAL_ACCOUNT_ID, session.ownerId)
224
+ : candidateStmt.bind(env.PORTAL_ACCOUNT_ID)
225
+ ).all<{
226
+ visitId: string
227
+ workerId: string
228
+ name: string
229
+ kind: string
230
+ reason: string
231
+ conflicts: string
232
+ }>()
233
+
234
+ // Parsed here, once, for the reason the roster's workingHours is: a column of
235
+ // JSON parsed by every consumer is a shape each of them can disagree about.
236
+ // An excluded row carries no conflicts at all, so its empty column reads as
237
+ // an empty list rather than throwing.
238
+ const candidates: CandidateRow[] = (candidateRows.results ?? []).map((c) => ({
239
+ visitId: c.visitId,
240
+ workerId: c.workerId,
241
+ name: c.name,
242
+ kind: c.kind,
243
+ reason: c.reason,
244
+ conflicts: parseJson<Array<{ visitId: string; start: string; end: string }>>(c.conflicts, []),
245
+ }))
246
+
146
247
  const metaRow = await env.DB.prepare(
147
- `SELECT m.vocabulary AS vocabulary, m.statuses AS statuses, m.zone AS zone,
148
- m.publishedAt AS publishedAt
248
+ `SELECT m.vocabulary AS vocabulary, m.statuses AS statuses, m.transitions AS transitions,
249
+ m.zone AS zone, m.publishedAt AS publishedAt
149
250
  FROM dispatch_meta m
150
251
  JOIN visits_state s
151
252
  ON s.accountId = m.accountId AND s.currentGeneration = m.generation
152
253
  WHERE m.accountId = ?`,
153
254
  )
154
255
  .bind(env.PORTAL_ACCOUNT_ID)
155
- .first<{ vocabulary: string; statuses: string; zone: string; publishedAt: string }>()
256
+ .first<{
257
+ vocabulary: string
258
+ statuses: string
259
+ transitions: string
260
+ zone: string
261
+ publishedAt: string
262
+ }>()
156
263
 
157
264
  // NOT owner-scoped. The nouns, the statuses and the account's timezone are
158
265
  // configuration, not a record about a person, and the page cannot draw a day
@@ -161,6 +268,11 @@ export async function processVisits(
161
268
  ? {
162
269
  vocabulary: parseJson(metaRow.vocabulary, { job: '', visit: '', worker: '' }),
163
270
  statuses: parseJson<Array<{ name: string; terminal: boolean }>>(metaRow.statuses, []),
271
+ // A malformed list falls back to EMPTY, which refuses every move. The
272
+ // other direction would be worse in kind rather than in degree: a page
273
+ // that accepts every move enforces nothing and is indistinguishable on
274
+ // screen from one that enforces correctly.
275
+ transitions: parseJson<Array<[string, string]>>(metaRow.transitions, []),
164
276
  zone: metaRow.zone,
165
277
  publishedAt: metaRow.publishedAt,
166
278
  }
@@ -172,9 +284,9 @@ export async function processVisits(
172
284
  log(
173
285
  `[data-portal] op=visits owner=${q(session.ownerId)} account=${q(session.accountId)} ` +
174
286
  `scope=${session.recordScope} visits=${visits.length} roster=${roster.length} ` +
175
- `meta=${meta !== null} result=ok`,
287
+ `candidates=${candidates.length} meta=${meta !== null} result=ok`,
176
288
  )
177
- return { status: 200, payload: { ok: true, visits, roster, meta } }
289
+ return { status: 200, payload: { ok: true, visits, roster, meta, candidates } }
178
290
  }
179
291
 
180
292
  interface PagesContext {
@@ -123,6 +123,8 @@ A move from one status to another is legal when the account's own transition lis
123
123
 
124
124
  Neither refusal is swallowed. A status that quietly failed to change cannot be told apart from one nobody tried to change.
125
125
 
126
+ The office planner on an account's own portal enforces the same list, from a copy published with the week. The page refuses an undeclared move before sending it, so an illegal drag is refused even while the device is offline, and the portal's write door refuses it again from that same copy. Only the door's refusal binds; the page's exists so the person is told at once rather than a minute later. A status equal to the one already held is not a move on either side, so re-timing or re-assigning a record never has to invent a transition to itself.
127
+
126
128
  ## A busy worker is offered, not hidden
127
129
 
128
130
  Only a missing qualification excludes a worker from the candidate list, and every exclusion is named with its worker and its reason. A qualified worker who is already committed in the window is offered with the clash shown.
@@ -1,59 +1,28 @@
1
1
  /**
2
2
  * Who can be sent to this job, and why the others cannot.
3
3
  *
4
- * The rule that matters: **a qualified worker who is already committed in the
5
- * window is offered WITH the conflict shown, never dropped.** The office
6
- * routinely double-books on purpose a job runs short, a customer is on the
7
- * way home, an engineer volunteers. A tool that silently removes the busy
8
- * option makes that decision for them and gives no way to see it was made.
4
+ * `selectCandidates`, `overlaps` and their types moved to
5
+ * `platform/lib/dispatch-read` in Task 2511, so the portal visits push and these
6
+ * tools share one implementation of qualification and clash. The push runs in
7
+ * `platform/ui` and cannot import a plugin's build output, and a second copy of
8
+ * these rules is the defect `functions/api/visits.ts:33-36` names. The queries
9
+ * and the rules moved; they did not change. This module stays as the plugin's
10
+ * import surface, exactly as `lib/read.ts` did for the Cypher reads.
9
11
  *
10
- * Only a missing qualification excludes, and every exclusion is named with its
11
- * worker and its reason, because `offered=0` with no explanation is the shape a
12
- * quiet day and an unstaffable job type share.
12
+ * `Commitment` now comes from that package's `read.ts`, where
13
+ * `readCommitments` declares it. The second structurally-identical declaration
14
+ * that used to live here is gone: two declarations of one contract can drift on
15
+ * a field.
13
16
  *
14
- * Task 2509 added the travel estimate. A candidate carries `travelMinutes` when
15
- * one could be produced and **omits the key** when it could not, with the
16
- * reason in `travelReason` — never a zero and never a null, either of which
17
- * would read as a measurement. `selectCandidates` below is deliberately
18
- * untouched by it: no estimator state may change who is offered.
17
+ * Task 2509 added the travel estimate, and it stays here. A candidate carries
18
+ * `travelMinutes` when one could be produced and **omits the key** when it
19
+ * could not, with the reason in `travelReason` — never a zero and never a null,
20
+ * either of which would read as a measurement. `selectCandidates` is
21
+ * deliberately untouched by it: no estimator state may change who is offered.
19
22
  */
20
- import type { DispatchConfig } from "./types.js";
21
- export interface Commitment {
22
- readonly visitId: string;
23
- readonly start: string;
24
- readonly end: string;
25
- }
26
- export interface Candidate {
27
- readonly workerId: string;
28
- readonly name: string;
29
- /** Commitments overlapping the requested window. Empty means free. */
30
- readonly conflicts: readonly Commitment[];
31
- }
32
- export interface Exclusion {
33
- readonly workerId: string;
34
- readonly reason: "missing-qualification";
35
- }
36
- export interface SelectCandidatesParams {
37
- readonly jobType: string;
38
- readonly cfg: DispatchConfig;
39
- /** Committed visits per workerId, already narrowed to the window. */
40
- readonly commitments: ReadonlyMap<string, readonly Commitment[]>;
41
- }
42
- export interface CandidateSelection {
43
- readonly offered: readonly Candidate[];
44
- readonly excluded: readonly Exclusion[];
45
- /** The qualification the job type demands, echoed for the log line. */
46
- readonly required: string;
47
- }
48
- export declare function selectCandidates(params: SelectCandidatesParams): CandidateSelection;
49
- /** `[a, b)` overlap. Touching endpoints do not overlap. */
50
- export declare function overlaps(a: {
51
- start: string;
52
- end: string;
53
- }, b: {
54
- start: string;
55
- end: string;
56
- }): boolean;
23
+ import type { Exclusion } from "../../../../../lib/dispatch-read/dist/index.js";
24
+ export { overlaps, selectCandidates, } from "../../../../../lib/dispatch-read/dist/index.js";
25
+ export type { Candidate, CandidateSelection, Commitment, Exclusion, SelectCandidatesParams, } from "../../../../../lib/dispatch-read/dist/index.js";
57
26
  /**
58
27
  * Why a candidate carries no estimate, or the estimate itself.
59
28
  *
@@ -1 +1 @@
1
- {"version":3,"file":"allocate.d.ts","sourceRoot":"","sources":["../../src/lib/allocate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,sEAAsE;IACtE,QAAQ,CAAC,SAAS,EAAE,SAAS,UAAU,EAAE,CAAC;CAC3C;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,uBAAuB,CAAC;CAC1C;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,GAAG,EAAE,cAAc,CAAC;IAC7B,qEAAqE;IACrE,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE,CAAC,CAAC;CAClE;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,OAAO,EAAE,SAAS,SAAS,EAAE,CAAC;IACvC,QAAQ,CAAC,QAAQ,EAAE,SAAS,SAAS,EAAE,CAAC;IACxC,uEAAuE;IACvE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,sBAAsB,GAAG,kBAAkB,CAuBnF;AAED,2DAA2D;AAC3D,wBAAgB,QAAQ,CACtB,CAAC,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,EACjC,CAAC,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAChC,OAAO,CAET;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,mBAAmB,GAAG,aAAa,CAAC;AAExE,wBAAgB,oBAAoB,CAAC,CAAC,EAAE;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,2DAA2D;IAC3D,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,YAAY,CAAC;IACrB,EAAE,EAAE,MAAM,CAAC;CACZ,GAAG,MAAM,CAKT;AAED,wBAAgB,wBAAwB,CAAC,CAAC,EAAE;IAC1C,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,SAAS,SAAS,EAAE,CAAC;CAChC,GAAG,MAAM,CAST"}
1
+ {"version":3,"file":"allocate.d.ts","sourceRoot":"","sources":["../../src/lib/allocate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gDAAgD,CAAC;AAEhF,OAAO,EACL,QAAQ,EACR,gBAAgB,GACjB,MAAM,gDAAgD,CAAC;AACxD,YAAY,EACV,SAAS,EACT,kBAAkB,EAClB,UAAU,EACV,SAAS,EACT,sBAAsB,GACvB,MAAM,gDAAgD,CAAC;AAExD;;;;;;;GAOG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,mBAAmB,GAAG,aAAa,CAAC;AAExE,wBAAgB,oBAAoB,CAAC,CAAC,EAAE;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,2DAA2D;IAC3D,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,YAAY,CAAC;IACrB,EAAE,EAAE,MAAM,CAAC;CACZ,GAAG,MAAM,CAKT;AAED,wBAAgB,wBAAwB,CAAC,CAAC,EAAE;IAC1C,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,SAAS,SAAS,EAAE,CAAC;CAChC,GAAG,MAAM,CAST"}
@@ -1,31 +1,4 @@
1
- export function selectCandidates(params) {
2
- const { jobType, cfg, commitments } = params;
3
- const type = cfg.jobTypes.find((t) => t.name === jobType);
4
- if (!type) {
5
- // An unknown job type is the caller's error, not a staffing outcome. Every
6
- // worker is excluded for a reason that would be a lie, so none are: the
7
- // caller checks the type before asking.
8
- return { offered: [], excluded: [], required: "" };
9
- }
10
- const offered = [];
11
- const excluded = [];
12
- for (const worker of cfg.workers) {
13
- if (!worker.qualifications.includes(type.requiredQualification)) {
14
- excluded.push({ workerId: worker.workerId, reason: "missing-qualification" });
15
- continue;
16
- }
17
- offered.push({
18
- workerId: worker.workerId,
19
- name: worker.name,
20
- conflicts: commitments.get(worker.workerId) ?? [],
21
- });
22
- }
23
- return { offered, excluded, required: type.requiredQualification };
24
- }
25
- /** `[a, b)` overlap. Touching endpoints do not overlap. */
26
- export function overlaps(a, b) {
27
- return a.start < b.end && b.start < a.end;
28
- }
1
+ export { overlaps, selectCandidates, } from "../../../../../lib/dispatch-read/dist/index.js";
29
2
  export function formatTravelEstimate(p) {
30
3
  return (`[dispatch] op=travel-estimate jobId=${p.jobId} fromVisitId=${p.fromVisitId ?? "none"} ` +
31
4
  `provider=${p.provider} result=${p.result} ms=${p.ms}`);
@@ -1 +1 @@
1
- {"version":3,"file":"allocate.js","sourceRoot":"","sources":["../../src/lib/allocate.ts"],"names":[],"mappings":"AAqDA,MAAM,UAAU,gBAAgB,CAAC,MAA8B;IAC7D,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,WAAW,EAAE,GAAG,MAAM,CAAC;IAC7C,MAAM,IAAI,GAAG,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC;IAC1D,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,2EAA2E;QAC3E,wEAAwE;QACxE,wCAAwC;QACxC,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;IACrD,CAAC;IACD,MAAM,OAAO,GAAgB,EAAE,CAAC;IAChC,MAAM,QAAQ,GAAgB,EAAE,CAAC;IACjC,KAAK,MAAM,MAAM,IAAI,GAAG,CAAC,OAAO,EAAE,CAAC;QACjC,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC,QAAQ,CAAC,IAAI,CAAC,qBAAqB,CAAC,EAAE,CAAC;YAChE,QAAQ,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,uBAAuB,EAAE,CAAC,CAAC;YAC9E,SAAS;QACX,CAAC;QACD,OAAO,CAAC,IAAI,CAAC;YACX,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,SAAS,EAAE,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE;SAClD,CAAC,CAAC;IACL,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,CAAC,qBAAqB,EAAE,CAAC;AACrE,CAAC;AAED,2DAA2D;AAC3D,MAAM,UAAU,QAAQ,CACtB,CAAiC,EACjC,CAAiC;IAEjC,OAAO,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,CAAC;AAC5C,CAAC;AAYD,MAAM,UAAU,oBAAoB,CAAC,CAOpC;IACC,OAAO,CACL,uCAAuC,CAAC,CAAC,KAAK,gBAAgB,CAAC,CAAC,WAAW,IAAI,MAAM,GAAG;QACxF,YAAY,CAAC,CAAC,QAAQ,WAAW,CAAC,CAAC,MAAM,OAAO,CAAC,CAAC,EAAE,EAAE,CACvD,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,CAKxC;IACC,MAAM,UAAU,GACd,CAAC,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC;QACrB,CAAC,CAAC,MAAM;QACR,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACnE,OAAO,CACL,2CAA2C,CAAC,CAAC,KAAK,aAAa,CAAC,CAAC,QAAQ,IAAI,MAAM,GAAG;QACtF,WAAW,CAAC,CAAC,OAAO,aAAa,CAAC,CAAC,QAAQ,CAAC,MAAM,eAAe,UAAU,EAAE,CAC9E,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"allocate.js","sourceRoot":"","sources":["../../src/lib/allocate.ts"],"names":[],"mappings":"AA0BA,OAAO,EACL,QAAQ,EACR,gBAAgB,GACjB,MAAM,gDAAgD,CAAC;AAmBxD,MAAM,UAAU,oBAAoB,CAAC,CAOpC;IACC,OAAO,CACL,uCAAuC,CAAC,CAAC,KAAK,gBAAgB,CAAC,CAAC,WAAW,IAAI,MAAM,GAAG;QACxF,YAAY,CAAC,CAAC,QAAQ,WAAW,CAAC,CAAC,MAAM,OAAO,CAAC,CAAC,EAAE,EAAE,CACvD,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,CAKxC;IACC,MAAM,UAAU,GACd,CAAC,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC;QACrB,CAAC,CAAC,MAAM;QACR,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACnE,OAAO,CACL,2CAA2C,CAAC,CAAC,KAAK,aAAa,CAAC,CAAC,QAAQ,IAAI,MAAM,GAAG;QACtF,WAAW,CAAC,CAAC,OAAO,aAAa,CAAC,CAAC,QAAQ,CAAC,MAAM,eAAe,UAAU,EAAE,CAC9E,CAAC;AACJ,CAAC"}
@@ -56,15 +56,41 @@ redeploy of a site that gained a page, not a new site.
56
56
  Nothing else is copied. The endpoint, the session library and the schema are the portal's and are
57
57
  already deployed with it.
58
58
 
59
+ ## What the office can do with a day
60
+
61
+ Every action goes through the portal's existing `/api/visit-status` door, and the device carries the
62
+ result into the graph within a minute. There is no second write endpoint and no second credential
63
+ path.
64
+
65
+ - **Advance a status.** Clicking a record moves it to the next status the account declared.
66
+ - **Re-time it.** Dragging it to another day keeps its clock time and changes its date, computed in
67
+ the account's own timezone.
68
+ - **Re-assign it.** Dragging it to another worker's row moves it to that worker. The device replaces
69
+ the attendance; a record two workers share is refused rather than silently losing one of them.
70
+ - **See who could go.** Opening a record's panel lists the workers the install offered, each with
71
+ their commitments in that window, and the ones it excluded with the reason. Both lists are
72
+ computed on the device, never on the page.
73
+ - **See what was recorded.** The panel shows how many notes, media, parts, checklist items and
74
+ signatures the record carries. Counts only; the contents are files and the portal's own file drop
75
+ already carries them.
76
+
77
+ **A move the account did not declare is refused twice.** The page refuses it from the transition
78
+ list published with the week, so an illegal drag is refused even while the device is offline, and
79
+ the door refuses it again. Only the door's refusal binds; the page's exists so the person is told
80
+ now rather than in a minute. A refused move returns the record to where it came from and says why,
81
+ because a card that silently slides back is indistinguishable from a gesture that missed.
82
+
59
83
  ## What it does not do
60
84
 
61
- It does not allocate, re-time or re-assign. Clicking a visit moves it to the next status the account
62
- declared, through the portal's existing `/api/visit-status` door, and the device carries that into
63
- the graph within a minute. Enforcing which transitions are legal, and acting on a day rather than
64
- recording it, are not built here.
85
+ It does not show a job list, counts of unallocated or past-target work, or the
86
+ pressed-against-observed arrival panel. None of those is on this page today.
87
+
88
+ A candidate carries no estimate of how long it takes to reach the site from where that worker
89
+ already is. The office sees who is qualified and who is busy, and picks between two names with no
90
+ idea one of them is ninety minutes away.
65
91
 
66
- It does not show a job list, counts of unallocated or past-target work, or the pressed-against-observed
67
- arrival panel. None of those is on this page today.
92
+ The completed-work panel shows counts, not contents. Reading the note a worker wrote, or the
93
+ signature they captured, still means opening the file drop.
68
94
 
69
95
  ## Done-gate
70
96
 
@@ -80,6 +106,19 @@ The page is not done until all five hold on the live domain:
80
106
  from a day off.
81
107
  5. Clicking a visit changes its status on screen, and `grep '\[portal-visits-pull\]' server.log`
82
108
  carries `op=applied visitId=` for it within one minute.
109
+ 6. `grep '\[portal-visits-push\]' server.log` shows `transitions=` above zero for this account. Zero
110
+ there is not a quiet account: it is a page that refuses every move while looking identical to one
111
+ that enforces correctly.
112
+ 7. Dragging a visit onto another worker's row shows it there, and the pull carries
113
+ `op=applied visitId= field=assignedOwnerId` within one minute.
114
+ 8. Attempting a move the account did not declare shows the refusal, returns the card, and the Pages
115
+ log carries `op=rejected reason=illegal-transition` while `grep 'op=applied' server.log` reports
116
+ nothing for that visit. A refusal that still wrote is the failure the transition gate exists to
117
+ prevent.
118
+
119
+ Condition 5 could not pass before the write half shipped: the pull emitted `op=merged` and
120
+ `op=unresolved` and no `op=applied` line existed anywhere. It does now, and it names the visit and
121
+ the field, which is the only way to pair a write the door accepted to one the device applied.
83
122
 
84
123
  The freshness line in the page header states the age of what is on screen. "Never published" there
85
124
  means this account has never completed a push, not that the week is empty.
@@ -87,6 +87,66 @@
87
87
  font-size: 0.8rem;
88
88
  }
89
89
 
90
+ /* Task 2511. A card is dragged to re-time or re-assign it. `grab` rather than
91
+ `move`, because the click that advances the status still works. */
92
+ .pl-visit[draggable='true'] {
93
+ cursor: grab;
94
+ }
95
+
96
+ /* The cell under the pointer during a drag. `currentColor` and opacity rather
97
+ than a colour: portal.css owns the palette and rewrites its own :root, so a
98
+ literal here would render one install's colour on every other. */
99
+ .pl-cell[data-over='true'] {
100
+ outline: 2px dashed currentColor;
101
+ outline-offset: -2px;
102
+ }
103
+
104
+ .pl-allocate {
105
+ margin-top: 0.75rem;
106
+ padding: 0.6rem 0.75rem;
107
+ border: 1px solid currentColor;
108
+ border-radius: 0.4rem;
109
+ position: relative;
110
+ }
111
+
112
+ .pl-allocate-close {
113
+ position: absolute;
114
+ top: 0.3rem;
115
+ right: 0.4rem;
116
+ }
117
+
118
+ .pl-allocate-head {
119
+ font-size: 0.82rem;
120
+ font-weight: 600;
121
+ margin: 0 0 0.4rem;
122
+ /* Room for the close button, which is positioned over this corner. */
123
+ padding-right: 2rem;
124
+ }
125
+
126
+ .pl-allocate-list {
127
+ list-style: none;
128
+ margin: 0;
129
+ padding: 0;
130
+ font-size: 0.78rem;
131
+ }
132
+
133
+ /* An excluded worker is dimmed rather than hidden. Hiding them would leave
134
+ `offered=0` with no explanation, which is the shape a quiet day and an
135
+ unstaffable job type share. */
136
+ .pl-candidate[data-kind='excluded'] {
137
+ opacity: 0.6;
138
+ }
139
+
140
+ .pl-candidate + .pl-candidate {
141
+ margin-top: 0.2rem;
142
+ }
143
+
144
+ .pl-record {
145
+ font-size: 0.78rem;
146
+ margin: 0.5rem 0 0;
147
+ opacity: 0.85;
148
+ }
149
+
90
150
  @media (max-width: 720px) {
91
151
  /* Seven readable columns that scroll, rather than seven unreadable slivers
92
152
  that do not. The scroll is the GRID's, never the page's. */
@@ -52,6 +52,19 @@
52
52
  </header>
53
53
  <div class="pl-grid" id="pl-grid"></div>
54
54
  <p class="pl-unplaceable" id="pl-unplaceable" hidden></p>
55
+
56
+ <!-- One record at a time: who may be sent to it, why the others may
57
+ not, and what has been recorded against it so far. Everything here
58
+ is rendered from what /api/visits returned. The page holds no rule
59
+ about who is qualified, who clashes, or which moves are legal. -->
60
+ <section id="pl-allocate" class="pl-allocate" hidden>
61
+ <button class="dp-iconbtn pl-allocate-close" id="pl-allocate-close" type="button">
62
+ &#215;
63
+ </button>
64
+ <p class="pl-allocate-head" id="pl-allocate-head"></p>
65
+ <ul class="pl-allocate-list" id="pl-allocate-list"></ul>
66
+ <p class="pl-record" id="pl-record"></p>
67
+ </section>
55
68
  </section>
56
69
  </main>
57
70
  <script src="/planner.js"></script>