@rubytech/create-maxy-code 0.1.537 → 0.1.539

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 (219) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +121 -7
  3. package/payload/platform/plugins/admin/skills/whats-new/SKILL.md +12 -0
  4. package/payload/platform/plugins/docs/PLUGIN.md +2 -0
  5. package/payload/platform/plugins/docs/references/admin-ui.md +40 -6
  6. package/payload/platform/plugins/docs/references/channel-wake-and-prompt.md +75 -0
  7. package/payload/platform/plugins/scheduling/PLUGIN.md +1 -1
  8. package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-get-description.test.d.ts +2 -0
  9. package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-get-description.test.d.ts.map +1 -0
  10. package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-get-description.test.js +59 -0
  11. package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-get-description.test.js.map +1 -0
  12. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-get.d.ts.map +1 -1
  13. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-get.js +6 -0
  14. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-get.js.map +1 -1
  15. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-update.d.ts.map +1 -1
  16. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-update.js +10 -6
  17. package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-update.js.map +1 -1
  18. package/payload/platform/plugins/whatsapp/PLUGIN.md +2 -0
  19. package/payload/platform/plugins/whatsapp/mcp/dist/index.js +17 -2
  20. package/payload/platform/plugins/whatsapp/mcp/dist/index.js.map +1 -1
  21. package/payload/platform/plugins/whatsapp/references/channels-whatsapp.md +16 -0
  22. package/payload/platform/plugins/whatsapp/skills/connect-whatsapp/SKILL.md +1 -1
  23. package/payload/platform/plugins/whatsapp/skills/manage-whatsapp-config/SKILL.md +29 -9
  24. package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts.map +1 -1
  25. package/payload/platform/services/claude-session-manager/dist/pty-spawner.js +15 -2
  26. package/payload/platform/services/claude-session-manager/dist/pty-spawner.js.map +1 -1
  27. package/payload/platform/services/webchat-channel/dist/notification.d.ts +31 -0
  28. package/payload/platform/services/webchat-channel/dist/notification.d.ts.map +1 -1
  29. package/payload/platform/services/webchat-channel/dist/notification.js +31 -1
  30. package/payload/platform/services/webchat-channel/dist/notification.js.map +1 -1
  31. package/payload/platform/services/webchat-channel/dist/server.d.ts.map +1 -1
  32. package/payload/platform/services/webchat-channel/dist/server.js +15 -1
  33. package/payload/platform/services/webchat-channel/dist/server.js.map +1 -1
  34. package/payload/platform/services/whatsapp-channel/dist/notification.d.ts +1 -1
  35. package/payload/platform/services/whatsapp-channel/dist/notification.d.ts.map +1 -1
  36. package/payload/platform/services/whatsapp-channel/dist/targets.d.ts +1 -1
  37. package/payload/platform/services/whatsapp-channel/dist/targets.d.ts.map +1 -1
  38. package/payload/platform/services/whatsapp-channel/dist/targets.js +5 -1
  39. package/payload/platform/services/whatsapp-channel/dist/targets.js.map +1 -1
  40. package/payload/server/{chunk-44Z4ZFYS.js → chunk-S4FIEM3L.js} +62 -10
  41. package/payload/server/{manager-AJSPM6X2.js → manager-5QV2EAZ2.js} +1 -1
  42. package/payload/server/public/activity.html +5 -5
  43. package/payload/server/public/agents.html +4 -4
  44. package/payload/server/public/assets/{AdminLoginScreens-CYFf2awh.js → AdminLoginScreens-BpHnjHp_.js} +1 -1
  45. package/payload/server/public/assets/AdminLoginScreens-BpHnjHp_.js.br +0 -0
  46. package/payload/server/public/assets/AdminLoginScreens-BpHnjHp_.js.gz +0 -0
  47. package/payload/server/public/assets/AdminShell-D24evn4t.js +2 -0
  48. package/payload/server/public/assets/AdminShell-D24evn4t.js.br +0 -0
  49. package/payload/server/public/assets/AdminShell-D24evn4t.js.gz +0 -0
  50. package/payload/server/public/assets/{activity-BH65sm9Q.js → activity-ZVUTB5uZ.js} +1 -1
  51. package/payload/server/public/assets/activity-ZVUTB5uZ.js.br +0 -0
  52. package/payload/server/public/assets/activity-ZVUTB5uZ.js.gz +0 -0
  53. package/payload/server/public/assets/{admin-CQtEjRGU.js → admin-XJqQz3QJ.js} +1 -1
  54. package/payload/server/public/assets/admin-XJqQz3QJ.js.br +0 -0
  55. package/payload/server/public/assets/admin-XJqQz3QJ.js.gz +0 -0
  56. package/payload/server/public/assets/{agents-CjhOWwl5.js → agents-Dc9SNC9N.js} +1 -1
  57. package/payload/server/public/assets/agents-Dc9SNC9N.js.br +0 -0
  58. package/payload/server/public/assets/agents-Dc9SNC9N.js.gz +0 -0
  59. package/payload/server/public/assets/{browser-DGXpfL99.js → browser-CCedMIga.js} +1 -1
  60. package/payload/server/public/assets/browser-CCedMIga.js.br +0 -0
  61. package/payload/server/public/assets/browser-CCedMIga.js.gz +0 -0
  62. package/payload/server/public/assets/calendar-BDoMLP2j.js +1 -0
  63. package/payload/server/public/assets/calendar-BDoMLP2j.js.br +0 -0
  64. package/payload/server/public/assets/calendar-BDoMLP2j.js.gz +0 -0
  65. package/payload/server/public/assets/chat-BAhoqTY9.js +1 -0
  66. package/payload/server/public/assets/chat-BAhoqTY9.js.br +0 -0
  67. package/payload/server/public/assets/chat-BAhoqTY9.js.gz +0 -0
  68. package/payload/server/public/assets/chevron-left-NGLHgPjF.js +1 -0
  69. package/payload/server/public/assets/chevron-right-B4B7OkG8.js +1 -0
  70. package/payload/server/public/assets/chevron-right-B4B7OkG8.js.br +0 -0
  71. package/payload/server/public/assets/clock-7IMwxJdH.js +1 -0
  72. package/payload/server/public/assets/clock-7IMwxJdH.js.br +0 -0
  73. package/payload/server/public/assets/clock-7IMwxJdH.js.gz +0 -0
  74. package/payload/server/public/assets/copy-PkR4EFD6.js +1 -0
  75. package/payload/server/public/assets/copy-PkR4EFD6.js.br +0 -0
  76. package/payload/server/public/assets/copy-PkR4EFD6.js.gz +0 -0
  77. package/payload/server/public/assets/data-yQYhw2IR.js +1 -0
  78. package/payload/server/public/assets/data-yQYhw2IR.js.br +1 -0
  79. package/payload/server/public/assets/data-yQYhw2IR.js.gz +0 -0
  80. package/payload/server/public/assets/{file-text-CbQoZfJD.js → file-text-BA9p7TLU.js} +1 -1
  81. package/payload/server/public/assets/file-text-BA9p7TLU.js.br +0 -0
  82. package/payload/server/public/assets/file-text-BA9p7TLU.js.gz +0 -0
  83. package/payload/server/public/assets/graph-C8cQ6Nqf.js +51 -0
  84. package/payload/server/public/assets/graph-C8cQ6Nqf.js.br +0 -0
  85. package/payload/server/public/assets/graph-C8cQ6Nqf.js.gz +0 -0
  86. package/payload/server/public/assets/{graph-labels-D695CsC9.js → graph-labels-CiK412vE.js} +1 -1
  87. package/payload/server/public/assets/graph-labels-CiK412vE.js.br +0 -0
  88. package/payload/server/public/assets/graph-labels-CiK412vE.js.gz +0 -0
  89. package/payload/server/public/assets/operator-CaQAEUBu.js +1 -0
  90. package/payload/server/public/assets/operator-CaQAEUBu.js.br +0 -0
  91. package/payload/server/public/assets/operator-CaQAEUBu.js.gz +0 -0
  92. package/payload/server/public/assets/page-CpJpyoPS.js +32 -0
  93. package/payload/server/public/assets/page-CpJpyoPS.js.br +0 -0
  94. package/payload/server/public/assets/page-CpJpyoPS.js.gz +0 -0
  95. package/payload/server/public/assets/page-D0ShNyGE.js +1 -0
  96. package/payload/server/public/assets/page-D0ShNyGE.js.br +0 -0
  97. package/payload/server/public/assets/page-D0ShNyGE.js.gz +0 -0
  98. package/payload/server/public/assets/{play-CbRU6q0T.js → play-huZpq9ra.js} +1 -1
  99. package/payload/server/public/assets/play-huZpq9ra.js.br +0 -0
  100. package/payload/server/public/assets/play-huZpq9ra.js.gz +0 -0
  101. package/payload/server/public/assets/{public-CqbKJ-Q3.js → public--8RWWGjF.js} +1 -1
  102. package/payload/server/public/assets/public--8RWWGjF.js.br +0 -0
  103. package/payload/server/public/assets/public--8RWWGjF.js.gz +0 -0
  104. package/payload/server/public/assets/{rotate-ccw-CjliWBou.js → rotate-ccw-g7l4ZSR3.js} +1 -1
  105. package/payload/server/public/assets/rotate-ccw-g7l4ZSR3.js.br +0 -0
  106. package/payload/server/public/assets/rotate-ccw-g7l4ZSR3.js.gz +0 -0
  107. package/payload/server/public/assets/routines-DzFcPNMb.js +2 -0
  108. package/payload/server/public/assets/routines-DzFcPNMb.js.br +0 -0
  109. package/payload/server/public/assets/routines-DzFcPNMb.js.gz +0 -0
  110. package/payload/server/public/assets/{skills-ipK9BJFb.js → skills-5vl_Bt9U.js} +1 -1
  111. package/payload/server/public/assets/skills-5vl_Bt9U.js.br +0 -0
  112. package/payload/server/public/assets/skills-5vl_Bt9U.js.gz +0 -0
  113. package/payload/server/public/assets/{tasks-CGcJHQ3X.js → tasks-DQHtJ8Pq.js} +2 -2
  114. package/payload/server/public/assets/tasks-DQHtJ8Pq.js.br +0 -0
  115. package/payload/server/public/assets/tasks-DQHtJ8Pq.js.gz +0 -0
  116. package/payload/server/public/assets/{triangle-alert-CjsLPsBD.js → triangle-alert-Cy4Z0uFv.js} +1 -1
  117. package/payload/server/public/assets/triangle-alert-Cy4Z0uFv.js.br +0 -0
  118. package/payload/server/public/assets/triangle-alert-Cy4Z0uFv.js.gz +0 -0
  119. package/payload/server/public/assets/{useCopyFeedback-umIgCxI_.js → useCopyFeedback-BwK1RhmF.js} +1 -1
  120. package/payload/server/public/assets/useCopyFeedback-BwK1RhmF.js.br +0 -0
  121. package/payload/server/public/assets/useCopyFeedback-BwK1RhmF.js.gz +0 -0
  122. package/payload/server/public/assets/useSubAccountSwitcher-C7TtIbR3.js +14 -0
  123. package/payload/server/public/assets/useSubAccountSwitcher-C7TtIbR3.js.br +0 -0
  124. package/payload/server/public/assets/useSubAccountSwitcher-C7TtIbR3.js.gz +0 -0
  125. package/payload/server/public/assets/{useSubAccountSwitcher-D8jXV7R5.css → useSubAccountSwitcher-DCkivCBS.css} +1 -1
  126. package/payload/server/public/assets/useSubAccountSwitcher-DCkivCBS.css.br +0 -0
  127. package/payload/server/public/assets/{useSubAccountSwitcher-D8jXV7R5.css.gz → useSubAccountSwitcher-DCkivCBS.css.gz} +0 -0
  128. package/payload/server/public/assets/useVoiceRecorder-DgyAGgmF.js +2 -0
  129. package/payload/server/public/assets/useVoiceRecorder-DgyAGgmF.js.br +0 -0
  130. package/payload/server/public/assets/useVoiceRecorder-DgyAGgmF.js.gz +0 -0
  131. package/payload/server/public/assets/{wrench-DtfKfR4s.js → wrench-CICORrSc.js} +1 -1
  132. package/payload/server/public/assets/wrench-CICORrSc.js.br +0 -0
  133. package/payload/server/public/assets/wrench-CICORrSc.js.gz +0 -0
  134. package/payload/server/public/browser.html +4 -4
  135. package/payload/server/public/calendar.html +8 -7
  136. package/payload/server/public/chat.html +13 -13
  137. package/payload/server/public/data.html +11 -11
  138. package/payload/server/public/graph.html +9 -9
  139. package/payload/server/public/index.html +14 -14
  140. package/payload/server/public/operator.html +14 -14
  141. package/payload/server/public/public.html +13 -13
  142. package/payload/server/public/routines.html +6 -6
  143. package/payload/server/public/skills.html +5 -5
  144. package/payload/server/public/tasks.html +6 -6
  145. package/payload/server/server.js +436 -108
  146. package/payload/server/public/assets/AdminLoginScreens-CYFf2awh.js.br +0 -0
  147. package/payload/server/public/assets/AdminLoginScreens-CYFf2awh.js.gz +0 -0
  148. package/payload/server/public/assets/AdminShell-7l3ubYFZ.js +0 -2
  149. package/payload/server/public/assets/AdminShell-7l3ubYFZ.js.br +0 -0
  150. package/payload/server/public/assets/AdminShell-7l3ubYFZ.js.gz +0 -0
  151. package/payload/server/public/assets/activity-BH65sm9Q.js.br +0 -0
  152. package/payload/server/public/assets/activity-BH65sm9Q.js.gz +0 -0
  153. package/payload/server/public/assets/admin-CQtEjRGU.js.br +0 -0
  154. package/payload/server/public/assets/admin-CQtEjRGU.js.gz +0 -0
  155. package/payload/server/public/assets/agents-CjhOWwl5.js.br +0 -0
  156. package/payload/server/public/assets/agents-CjhOWwl5.js.gz +0 -0
  157. package/payload/server/public/assets/browser-DGXpfL99.js.br +0 -0
  158. package/payload/server/public/assets/browser-DGXpfL99.js.gz +0 -0
  159. package/payload/server/public/assets/calendar-Cu4yjEuX.js +0 -1
  160. package/payload/server/public/assets/calendar-Cu4yjEuX.js.br +0 -0
  161. package/payload/server/public/assets/calendar-Cu4yjEuX.js.gz +0 -0
  162. package/payload/server/public/assets/chat-0na4XVZC.js +0 -1
  163. package/payload/server/public/assets/chat-0na4XVZC.js.br +0 -0
  164. package/payload/server/public/assets/chat-0na4XVZC.js.gz +0 -0
  165. package/payload/server/public/assets/chevron-left-DHzJobWp.js +0 -1
  166. package/payload/server/public/assets/chevron-left-DHzJobWp.js.br +0 -0
  167. package/payload/server/public/assets/chevron-right-yg4DMfLT.js +0 -1
  168. package/payload/server/public/assets/chevron-right-yg4DMfLT.js.br +0 -0
  169. package/payload/server/public/assets/clock-BIDzihvp.js +0 -1
  170. package/payload/server/public/assets/clock-BIDzihvp.js.br +0 -0
  171. package/payload/server/public/assets/clock-BIDzihvp.js.gz +0 -0
  172. package/payload/server/public/assets/data-Ql9qG3YO.js +0 -1
  173. package/payload/server/public/assets/data-Ql9qG3YO.js.br +0 -0
  174. package/payload/server/public/assets/data-Ql9qG3YO.js.gz +0 -0
  175. package/payload/server/public/assets/file-text-CbQoZfJD.js.br +0 -0
  176. package/payload/server/public/assets/file-text-CbQoZfJD.js.gz +0 -0
  177. package/payload/server/public/assets/graph-7414Kjn9.js +0 -51
  178. package/payload/server/public/assets/graph-7414Kjn9.js.br +0 -0
  179. package/payload/server/public/assets/graph-7414Kjn9.js.gz +0 -0
  180. package/payload/server/public/assets/graph-labels-D695CsC9.js.br +0 -0
  181. package/payload/server/public/assets/graph-labels-D695CsC9.js.gz +0 -0
  182. package/payload/server/public/assets/maximize-2-CD0gTjW_.js +0 -1
  183. package/payload/server/public/assets/maximize-2-CD0gTjW_.js.br +0 -0
  184. package/payload/server/public/assets/maximize-2-CD0gTjW_.js.gz +0 -0
  185. package/payload/server/public/assets/operator-CLw4PZs5.js +0 -1
  186. package/payload/server/public/assets/operator-CLw4PZs5.js.br +0 -0
  187. package/payload/server/public/assets/operator-CLw4PZs5.js.gz +0 -0
  188. package/payload/server/public/assets/page-BNRFmFc-.js +0 -32
  189. package/payload/server/public/assets/page-BNRFmFc-.js.br +0 -0
  190. package/payload/server/public/assets/page-BNRFmFc-.js.gz +0 -0
  191. package/payload/server/public/assets/page-BRr295G2.js +0 -1
  192. package/payload/server/public/assets/page-BRr295G2.js.br +0 -0
  193. package/payload/server/public/assets/page-BRr295G2.js.gz +0 -0
  194. package/payload/server/public/assets/play-CbRU6q0T.js.br +0 -0
  195. package/payload/server/public/assets/play-CbRU6q0T.js.gz +0 -0
  196. package/payload/server/public/assets/public-CqbKJ-Q3.js.br +0 -0
  197. package/payload/server/public/assets/public-CqbKJ-Q3.js.gz +0 -0
  198. package/payload/server/public/assets/rotate-ccw-CjliWBou.js.br +0 -0
  199. package/payload/server/public/assets/rotate-ccw-CjliWBou.js.gz +0 -0
  200. package/payload/server/public/assets/routines-yJuRuBfn.js +0 -2
  201. package/payload/server/public/assets/routines-yJuRuBfn.js.br +0 -0
  202. package/payload/server/public/assets/routines-yJuRuBfn.js.gz +0 -0
  203. package/payload/server/public/assets/skills-ipK9BJFb.js.br +0 -0
  204. package/payload/server/public/assets/skills-ipK9BJFb.js.gz +0 -0
  205. package/payload/server/public/assets/tasks-CGcJHQ3X.js.br +0 -0
  206. package/payload/server/public/assets/tasks-CGcJHQ3X.js.gz +0 -0
  207. package/payload/server/public/assets/triangle-alert-CjsLPsBD.js.br +0 -0
  208. package/payload/server/public/assets/triangle-alert-CjsLPsBD.js.gz +0 -0
  209. package/payload/server/public/assets/useCopyFeedback-umIgCxI_.js.br +0 -0
  210. package/payload/server/public/assets/useCopyFeedback-umIgCxI_.js.gz +0 -0
  211. package/payload/server/public/assets/useSubAccountSwitcher-D8jXV7R5.css.br +0 -0
  212. package/payload/server/public/assets/useSubAccountSwitcher-UMg53kKF.js +0 -14
  213. package/payload/server/public/assets/useSubAccountSwitcher-UMg53kKF.js.br +0 -0
  214. package/payload/server/public/assets/useSubAccountSwitcher-UMg53kKF.js.gz +0 -0
  215. package/payload/server/public/assets/useVoiceRecorder-tzfqfXni.js +0 -2
  216. package/payload/server/public/assets/useVoiceRecorder-tzfqfXni.js.br +0 -0
  217. package/payload/server/public/assets/useVoiceRecorder-tzfqfXni.js.gz +0 -0
  218. package/payload/server/public/assets/wrench-DtfKfR4s.js.br +0 -0
  219. package/payload/server/public/assets/wrench-DtfKfR4s.js.gz +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rubytech/create-maxy-code",
3
- "version": "0.1.537",
3
+ "version": "0.1.539",
4
4
  "description": "Install Maxy — AI for Productive People",
5
5
  "bin": {
6
6
  "create-maxy-code": "./dist/index.js"
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: platform-architecture
3
3
  description: Use when grounding any documented-surface claim about what Maxy ships — plugins, skills, specialists, install/deploy flows, internals. This is the install catalogue, not evidence of what is enabled on the current account. For install state on this account, call `capabilities-here`; for documented surface, cite the `Source:` URL inline.
4
- content-hash: sha256:8dd785e2a18a206d3c3ab9e1a83067295717db2516ddb50b51e2290033d2dd85
4
+ content-hash: sha256:e737732428725be0a3852ca8ba4cd1f9dd5f62bdcd6f7c0a85b82f4ac1c9bccc
5
5
  brand: maxy-code
6
6
  product-name: Maxy
7
7
  ---
@@ -1661,6 +1661,86 @@ Changes are per-account and take effect immediately.
1661
1661
 
1662
1662
  Brand isolation extends to the device filesystem. Every Maxy install provisions an SMB share scoped to that brand's install folder, credentialled by the brand's install owner and the Maxy PIN. A device that hosts more than one brand carries one share per brand; tearing one brand down never exposes another brand's files. See [Samba Share](./samba.md) for the credential model, per-OS mount syntax, and peer-brand lifecycle.
1663
1663
 
1664
+ ---
1665
+ # What Wakes a Session
1666
+ Source: https://docs.getmaxy.com/channel-wake-and-prompt.md
1667
+
1668
+ # What wakes a session, and what is in its prompt
1669
+
1670
+ Two questions an agent cannot answer from inside itself, and both have caused real faults: *what woke me?* and *which files did my prompt come from?* This page answers both. When the answer is not here, the logs have it: `logs-read --tail server`, filtered on the `[whatsapp:*]` tags.
1671
+
1672
+ ## What wakes a session
1673
+
1674
+ Five things start or resume a WhatsApp session. They are distinguishable, and the distinction matters, because two of them are written by the platform rather than by the person named as the sender.
1675
+
1676
+ **An admin phone or an account manager messages the line.** This resumes that person's own admin session. There is no per-account admin session: the session id is a hash of the account plus the person, so one person messaging from two channels resumes one thread, and two managers on one account have two threads.
1677
+
1678
+ **A public sender messages the line.** Three things follow, in this order, and each is independent of the ones after it.
1679
+
1680
+ 1. The account's registered managers are notified, verbatim, unless the account has turned that off. This fires before any agent starts, so it survives a spawn that fails.
1681
+ 2. Every bound manager's own admin session is woken with a `public-relay` turn carrying the sender's message as fenced content. This is the carrier for anything the account needs to do about the visitor: translate, put a request to a registered counterparty, carry the answer back.
1682
+ 3. The account's public agent answers the visitor, if the account has one and has enabled it. If not, the visitor receives nothing at all, and steps 1 and 2 have already happened regardless.
1683
+
1684
+ **The scheduler fires a due event.** This raises a `schedule` turn on the destination's own session, carrying the event's prompt.
1685
+
1686
+ **A passive account-manager binding receives a message.** This spawns a constrained one-shot that files a task and never replies. It cannot hold a conversation or answer against existing state.
1687
+
1688
+ ## Reading why you woke
1689
+
1690
+ Every turn carries a `source`. Three values exist:
1691
+
1692
+ | `source` | Meaning |
1693
+ |---|---|
1694
+ | `user` | A real person sent this message to the line. Also the value when the field is absent. |
1695
+ | `schedule` | The scheduler wrote this turn. The named destination did not send it. |
1696
+ | `public-relay` | The platform wrote this turn because a public visitor messaged the account. The named sender is a manager being told, not someone who wrote to you. |
1697
+
1698
+ A `public-relay` turn also says so in its own first two lines. If a turn claims a manager wrote something they plainly would not have written, check the source before answering them.
1699
+
1700
+ ## Which files compose the prompt
1701
+
1702
+ The system prompt is assembled per spawn from one agent directory, and **which directory depends on the role**:
1703
+
1704
+ - A `role:'public'` spawn reads `agents/<the account's public-agent slug>/`.
1705
+ - Every other role reads `agents/admin/`.
1706
+
1707
+ From that one directory it takes `IDENTITY.md` and `SOUL.md`, verbatim.
1708
+
1709
+ The consequence catches people out: **an instruction written into `agents/admin/SOUL.md` is never read by a public spawn**, and an instruction written into a public agent's `SOUL.md` is never read by an admin turn. Before writing an instruction into a role file, decide which role will actually be running when it needs to apply. If the answer is "the admin agent, woken by a stranger's message", the file is `agents/admin/SOUL.md` and the trigger is the `public-relay` dispatch above.
1710
+
1711
+ A public agent's directory also carries `KNOWLEDGE.md` and `config.json`. An account can hold as many public agents as it likes; only one is bound to WhatsApp at a time, and that binding is per account.
1712
+
1713
+ ## The switches, and what each one stops
1714
+
1715
+ Four settings sit on this path. They are not interchangeable, and reaching for the wrong one is how an operator ends up silencing more than they meant.
1716
+
1717
+ | Setting | What it stops | What it leaves running |
1718
+ |---|---|---|
1719
+ | `dmPolicy: disabled` | Public senders are refused at the gate. | Admin and manager inbound. |
1720
+ | `publicAgentEnabled: false` | The visitor gets no reply. | The manager notification and the relay. |
1721
+ | `managerNotifyEnabled: false` | The verbatim copy of the visitor's message. | The relay, and any reply the woken turn sends. |
1722
+ | `dispatchInbound: false` | Every agent turn on that account's socket. | Storage: messages are still stored and readable. |
1723
+
1724
+ `managerNotifyEnabled` is the fine-grained one, and the one to reach for when the notifications are unwanted but the work is not. Unbinding a manager is not a substitute: the manager registry is shared by the notification, the relay and `whatsapp-notify-manager`, so unbinding silences all three.
1725
+
1726
+ Read the current value with `whatsapp-config {action:'get-manager-notify-enabled'}` and set it with `set-manager-notify-enabled`. Both are scoped to the calling session's own account.
1727
+
1728
+ ## When the answer is not here
1729
+
1730
+ `logs-read --tail server` and filter on the tags. One public inbound writes this chain, in order, with `account=` and `sender=` on each line:
1731
+
1732
+ ```
1733
+ [whatsapp:wire] op=stanza
1734
+ [wa-notify] op=eligible reason=<how the sender was admitted>
1735
+ [whatsapp:route] op=routed agentType=public
1736
+ [whatsapp:notify] op=public-inbound enabled=0|1 outcome=sent|failed|no-recipients|disabled
1737
+ [whatsapp:relay] op=dispatch outcome=sent|failed|no-recipients
1738
+ [whatsapp:public-agent] op=route enabled=… slug=… spawned=0|1
1739
+ [whatsapp:public-agent] op=spawn-ok | op=spawn-failed
1740
+ ```
1741
+
1742
+ Three standing audits reconcile that chain rather than waiting for someone to notice. `op=public-notify-reconcile` reports `gap`, `relayGap` and `answerGap`, each of which counts a step that a routed inbound reached and the next one did not. `op=spawn-census` reports attempts against successes. A non-zero gap, or attempts with no successes, is a fault even when nothing has been reported.
1743
+
1664
1744
  ---
1665
1745
  # Settings
1666
1746
  Source: https://docs.getmaxy.com/settings.md
@@ -3346,6 +3426,8 @@ either is a regression.
3346
3426
 
3347
3427
  **`/chat` empty-state starter chips.** While the admin webchat has no conversation JSONL yet (`GET /api/webchat/session` → `projectDir:null`), `app/chat/page.tsx` renders a "What's up next, {givenName}?" greeting (given name = first whitespace token of the admin session's `userName`; degrades to "What's up next?" without one) above three one-tap starter chips (replacing the earlier read-only lists): **Catch me up** (`Inbox`), **My day** (`CalendarClock`), **To-do** (`ListTodo`). `GreetingPanel` no longer fetches `GET /api/webchat/greeting` — the headline reads from the `userName` prop alone. A tap dispatches the chip's verbatim prompt through the existing `send()` with zero typing, via the same arm/fire path as the `?q=` handoff seed: `dispatchChip` logs `[admin-ui] op=chip-tap id=<catch-up|my-day|to-do> chars=<n>`, sets the composer text, and arms a one-shot effect that fires `send()` once the text matches. Chips gate to `variant` admin/operator; the public surface shows the headline alone. The first journaled turn replaces the panel with the transcript. The `/api/webchat/greeting` route (`server/routes/webchat-greeting.ts`) and `specialist-roster.ts` are now unconsumed by this surface — slimming them is a separate follow-up. The full webchat architecture lives in `.docs/admin-webchat-native-channel.md`.
3348
3428
 
3429
+ **`/chat` reply to a specific message.** Each of your own messages and each of the assistant's replies carries a reply control beside its copy button. Clicking it puts a strip above the composer naming who you are replying to and quoting the message; the X on that strip cancels. Sending delivers the quote to the agent as the first line of its context, so "redo that one" resolves to the message you pointed at, and the sent message keeps the quote visible above it when you reload. Two limits are deliberate: a message that arrived while the assistant was mid-turn cannot be quoted (the transcript records that arrival without an id to target), and tool runs, thinking runs and error banners are not reply targets. The quoted text is capped at 500 characters and is read from the conversation's own transcript server-side, never from the browser. The public visitor surface has no reply control. The full path is in `.docs/admin-webchat-native-channel.md`.
3430
+
3349
3431
  **`/chat` composer transport button.** The button at the end of the input shows a **microphone** while the box is empty — tap it to record a voice note. Type a character, or attach a file, and the same button becomes the **send** arrow; while the agent is replying it becomes a **stop** square. So an empty composer offers voice, a composer with something to send offers send, and a running turn offers stop — one button, three states. The microphone-device chooser (which input to record from) stays in the row of icons below the box. This is the same on the admin `/chat`, the public chat, and the maxy-lite webchat.
3350
3432
 
3351
3433
  **`/chat` Conversations flyout + zero-sessions splash.** The admin `/chat` `HeaderMenu` carries a **Conversations** item (rendered only when `onOpenConversations` is wired, which scopes it to `/chat`) that opens an in-chat session-management pane (`app/chat/SessionList.tsx`) hosted by `chat/page.tsx` — distinct from, and sharing endpoints with, the `Sidebar` Sessions list (which stays hidden on narrow viewports). It enumerates the admin's own webchat sessions via `GET /api/admin/sidebar-sessions` (carries the per-row `live` marker and `archived` flag, install-wide), **filtering out `channel:'whatsapp'`/`'telegram'` rows** (those are channel-bound, cannot be chatted in webchat, and live in the WhatsApp/Telegram reader panels; the same endpoint now also feeds the sidebar Sessions list, which does show them), lists the remainder newest-first with the live one marked and archived rows folded under a collapsible subsection, and offers per-row resume (`/chat?session=<id>`), rename, archive/unarchive, two-tap delete, an **End** control on the live row (`session-stop`), plus a New-session control (`session-rc-spawn`) and a copyable full id. The pane header carries the title and a top-right close (X) control that dismisses the flyout (no back-chevron/"Chat" label); the New-session control floats at the pane's bottom-left. When the canonical pointer is `known:false` (`canonical-empty`) and enumeration returns zero rows, the surface renders a splash (brand logo + New session) instead of a dead bootstrap thread; a freshly-spawned New session is `known:true`, so its greeting is preserved. Client breadcrumbs: `[chat-conversations] op=enumerate owned=<n>` and `op=action name=<open|rename|archive|delete|stop> sessionId=<id8>` (`op=action-failed … status=…` on a non-2xx). Detail lives in `.docs/admin-webchat-native-channel.md` ("Conversations flyout + zero-sessions splash").
@@ -4171,12 +4253,20 @@ a browser that is already running it re-ran the same launch check and changed
4171
4253
  nothing anyone could see, so it now appears only when the browser is unreachable
4172
4254
  or has no tabs open.
4173
4255
 
4174
- The browser sits beside the conversation whenever the chat is open, taking
4175
- about three fifths of the window. The globe button in the chat header closes it
4176
- if you want the chat full width, and that choice is remembered. The pane is
4177
- hidden on narrow screens, where there is no room for two columns. The page is
4178
- rendered at the pane's own size, so it fills the pane and follows it when you
4179
- drag the divider.
4256
+ The browser opens beside the conversation from the globe button at the top
4257
+ right of the chat header. That button is there only while the browser is
4258
+ closed; once it is open you close it with the cross at the top right of the
4259
+ browser itself, and the button comes back. Beside the cross is a full-screen
4260
+ control that gives the browser the whole width and hides the chat, and the same
4261
+ control returns you to the split.
4262
+
4263
+ Drag the divider between the chat and the browser to change how the width is
4264
+ shared. Double-click it to go back to an even split. The chat can never be
4265
+ pushed below a readable width, and the choice is remembered for next time. The
4266
+ pane is hidden on narrow screens where there is no room for two columns, and
4267
+ the page is rendered at the pane's own size so it fills it.
4268
+
4269
+ There is no Browser item in the sidebar: the browser lives beside the chat.
4180
4270
 
4181
4271
  Tab opening and closing go to the admin server, which is the only thing that can
4182
4272
  reach the browser's control port. Typing an address, going back and going
@@ -4252,6 +4342,30 @@ The companion `/api/admin/version` and `/api/admin/actions` routes are
4252
4342
  served by `maxy-edge.service`, not this aggregator. The edge process
4253
4343
  keeps the upgrade view alive while the brand service restarts.
4254
4344
 
4345
+ ### Phone-width layout overflow
4346
+
4347
+ If any part of an admin screen is cut off at the right edge on a phone —
4348
+ a header pill, a message bubble — the dashboard now reports it by itself
4349
+ rather than waiting for a screenshot. Every admin page measures its own
4350
+ width after it settles, and posts a record when something sticks out past
4351
+ the edge.
4352
+
4353
+ Read the reports with:
4354
+
4355
+ ```
4356
+ grep 'op=layout-overflow' ~/.<brand>/logs/client-errors.log
4357
+ ```
4358
+
4359
+ Each line names the page it happened on (`route`) and the element that
4360
+ stuck out (`offender`), so the cause is identifiable without reproducing
4361
+ it on a handset. A line with a `delta` but an empty `offender` means the
4362
+ measurement ran too early, which is a different fault from a cut-off
4363
+ page. No lines at all is the healthy state.
4364
+
4365
+ These reports share the client-error log, so they also count towards the
4366
+ 24-hour client-error figure shown on the upgrade view. A rise there with
4367
+ `op=layout-overflow` lines behind it is a layout problem, not a crash.
4368
+
4255
4369
  ## System-stats widget
4256
4370
 
4257
4371
  Source:
@@ -9,6 +9,18 @@ Invoked by the admin agent directly.
9
9
 
10
10
  This is the platform's release timeline, newest first. Each entry shows the date it shipped and the version it shipped in, so you can tell the operator how current their install is. To compare, read the installed version from `capabilities-here` and match it against the versions below. Keep answers high level and in plain English; this is a summary, not a full commit log.
11
11
 
12
+ ## 2026-07-31 (0.1.539)
13
+
14
+ - You can now reply to a specific message in chat, and the assistant sees which one you meant.
15
+ - The calendar now shows times in the account's own timezone rather than the browser's, and shows and keeps the meeting description, which is also carried into the exported calendar file.
16
+ - Narrow phone screens no longer overflow sideways, with a standing check that reports it if the layout regresses.
17
+ - When a live location cannot be followed, the reply from WhatsApp is now recorded so the reason is visible.
18
+
19
+ ## 2026-07-31 (0.1.538)
20
+
21
+ - A message from someone outside your team now also reaches the account's manager in their own chat, written in plain English, and each account can turn the separate raw notification off.
22
+ - The device browser pane can be toggled, opened full screen and resized.
23
+
12
24
  ## 2026-07-31 (0.1.537)
13
25
 
14
26
  - A sub-account's public agent now runs entirely in that account: its own folder, its own settings, and no falling back to the main account's agent. A standing check reports an account switched on with no agent of its own.
@@ -23,6 +23,7 @@ Load these when users ask about Maxy features or need guidance:
23
23
  - **Telegram** → `references/telegram-guide.md` — Telegram setup, the bot, daily use
24
24
  - **Settings** → `references/settings.md` — output style, effort level, account preferences
25
25
  - **Access Control** → `references/access-control.md` — who can chat with your public agent, invitations, authentication
26
+ - **What wakes a session** → `references/channel-wake-and-prompt.md` — the five things that start or resume a WhatsApp session, the `source` value each carries, which agent directory composes the prompt for which role, and the four switches on the public-inbound path. Load before writing an instruction into any role file, or when an agent cannot say why it woke.
26
27
  - **Projects** → `references/projects-guide.md` — creating projects, tracking health, phase transitions, completing
27
28
  - **Workflows** → `references/workflows.md` — saving and running multi-step processes, declared inputs, scheduling, run history
28
29
  - **Slides** → `references/slides.md` — generating, theming, and reviewing HTML slide decks with `/slides`
@@ -51,6 +52,7 @@ Load these when performing admin tasks or diagnosing platform behaviour:
51
52
  - references/telegram-guide.md
52
53
  - references/settings.md
53
54
  - references/access-control.md
55
+ - references/channel-wake-and-prompt.md
54
56
  - references/projects-guide.md
55
57
  - references/troubleshooting.md
56
58
  - references/platform.md
@@ -69,6 +69,8 @@ either is a regression.
69
69
 
70
70
  **`/chat` empty-state starter chips.** While the admin webchat has no conversation JSONL yet (`GET /api/webchat/session` → `projectDir:null`), `app/chat/page.tsx` renders a "What's up next, {givenName}?" greeting (given name = first whitespace token of the admin session's `userName`; degrades to "What's up next?" without one) above three one-tap starter chips (replacing the earlier read-only lists): **Catch me up** (`Inbox`), **My day** (`CalendarClock`), **To-do** (`ListTodo`). `GreetingPanel` no longer fetches `GET /api/webchat/greeting` — the headline reads from the `userName` prop alone. A tap dispatches the chip's verbatim prompt through the existing `send()` with zero typing, via the same arm/fire path as the `?q=` handoff seed: `dispatchChip` logs `[admin-ui] op=chip-tap id=<catch-up|my-day|to-do> chars=<n>`, sets the composer text, and arms a one-shot effect that fires `send()` once the text matches. Chips gate to `variant` admin/operator; the public surface shows the headline alone. The first journaled turn replaces the panel with the transcript. The `/api/webchat/greeting` route (`server/routes/webchat-greeting.ts`) and `specialist-roster.ts` are now unconsumed by this surface — slimming them is a separate follow-up. The full webchat architecture lives in `.docs/admin-webchat-native-channel.md`.
71
71
 
72
+ **`/chat` reply to a specific message.** Each of your own messages and each of the assistant's replies carries a reply control beside its copy button. Clicking it puts a strip above the composer naming who you are replying to and quoting the message; the X on that strip cancels. Sending delivers the quote to the agent as the first line of its context, so "redo that one" resolves to the message you pointed at, and the sent message keeps the quote visible above it when you reload. Two limits are deliberate: a message that arrived while the assistant was mid-turn cannot be quoted (the transcript records that arrival without an id to target), and tool runs, thinking runs and error banners are not reply targets. The quoted text is capped at 500 characters and is read from the conversation's own transcript server-side, never from the browser. The public visitor surface has no reply control. The full path is in `.docs/admin-webchat-native-channel.md`.
73
+
72
74
  **`/chat` composer transport button.** The button at the end of the input shows a **microphone** while the box is empty — tap it to record a voice note. Type a character, or attach a file, and the same button becomes the **send** arrow; while the agent is replying it becomes a **stop** square. So an empty composer offers voice, a composer with something to send offers send, and a running turn offers stop — one button, three states. The microphone-device chooser (which input to record from) stays in the row of icons below the box. This is the same on the admin `/chat`, the public chat, and the maxy-lite webchat.
73
75
 
74
76
  **`/chat` Conversations flyout + zero-sessions splash.** The admin `/chat` `HeaderMenu` carries a **Conversations** item (rendered only when `onOpenConversations` is wired, which scopes it to `/chat`) that opens an in-chat session-management pane (`app/chat/SessionList.tsx`) hosted by `chat/page.tsx` — distinct from, and sharing endpoints with, the `Sidebar` Sessions list (which stays hidden on narrow viewports). It enumerates the admin's own webchat sessions via `GET /api/admin/sidebar-sessions` (carries the per-row `live` marker and `archived` flag, install-wide), **filtering out `channel:'whatsapp'`/`'telegram'` rows** (those are channel-bound, cannot be chatted in webchat, and live in the WhatsApp/Telegram reader panels; the same endpoint now also feeds the sidebar Sessions list, which does show them), lists the remainder newest-first with the live one marked and archived rows folded under a collapsible subsection, and offers per-row resume (`/chat?session=<id>`), rename, archive/unarchive, two-tap delete, an **End** control on the live row (`session-stop`), plus a New-session control (`session-rc-spawn`) and a copyable full id. The pane header carries the title and a top-right close (X) control that dismisses the flyout (no back-chevron/"Chat" label); the New-session control floats at the pane's bottom-left. When the canonical pointer is `known:false` (`canonical-empty`) and enumeration returns zero rows, the surface renders a splash (brand logo + New session) instead of a dead bootstrap thread; a freshly-spawned New session is `known:true`, so its greeting is preserved. Client breadcrumbs: `[chat-conversations] op=enumerate owned=<n>` and `op=action name=<open|rename|archive|delete|stop> sessionId=<id8>` (`op=action-failed … status=…` on a non-2xx). Detail lives in `.docs/admin-webchat-native-channel.md` ("Conversations flyout + zero-sessions splash").
@@ -894,12 +896,20 @@ a browser that is already running it re-ran the same launch check and changed
894
896
  nothing anyone could see, so it now appears only when the browser is unreachable
895
897
  or has no tabs open.
896
898
 
897
- The browser sits beside the conversation whenever the chat is open, taking
898
- about three fifths of the window. The globe button in the chat header closes it
899
- if you want the chat full width, and that choice is remembered. The pane is
900
- hidden on narrow screens, where there is no room for two columns. The page is
901
- rendered at the pane's own size, so it fills the pane and follows it when you
902
- drag the divider.
899
+ The browser opens beside the conversation from the globe button at the top
900
+ right of the chat header. That button is there only while the browser is
901
+ closed; once it is open you close it with the cross at the top right of the
902
+ browser itself, and the button comes back. Beside the cross is a full-screen
903
+ control that gives the browser the whole width and hides the chat, and the same
904
+ control returns you to the split.
905
+
906
+ Drag the divider between the chat and the browser to change how the width is
907
+ shared. Double-click it to go back to an even split. The chat can never be
908
+ pushed below a readable width, and the choice is remembered for next time. The
909
+ pane is hidden on narrow screens where there is no room for two columns, and
910
+ the page is rendered at the pane's own size so it fills it.
911
+
912
+ There is no Browser item in the sidebar: the browser lives beside the chat.
903
913
 
904
914
  Tab opening and closing go to the admin server, which is the only thing that can
905
915
  reach the browser's control port. Typing an address, going back and going
@@ -975,6 +985,30 @@ The companion `/api/admin/version` and `/api/admin/actions` routes are
975
985
  served by `maxy-edge.service`, not this aggregator. The edge process
976
986
  keeps the upgrade view alive while the brand service restarts.
977
987
 
988
+ ### Phone-width layout overflow
989
+
990
+ If any part of an admin screen is cut off at the right edge on a phone —
991
+ a header pill, a message bubble — the dashboard now reports it by itself
992
+ rather than waiting for a screenshot. Every admin page measures its own
993
+ width after it settles, and posts a record when something sticks out past
994
+ the edge.
995
+
996
+ Read the reports with:
997
+
998
+ ```
999
+ grep 'op=layout-overflow' ~/.<brand>/logs/client-errors.log
1000
+ ```
1001
+
1002
+ Each line names the page it happened on (`route`) and the element that
1003
+ stuck out (`offender`), so the cause is identifiable without reproducing
1004
+ it on a handset. A line with a `delta` but an empty `offender` means the
1005
+ measurement ran too early, which is a different fault from a cut-off
1006
+ page. No lines at all is the healthy state.
1007
+
1008
+ These reports share the client-error log, so they also count towards the
1009
+ 24-hour client-error figure shown on the upgrade view. A rise there with
1010
+ `op=layout-overflow` lines behind it is a layout problem, not a crash.
1011
+
978
1012
  ## System-stats widget
979
1013
 
980
1014
  Source:
@@ -0,0 +1,75 @@
1
+ # What wakes a session, and what is in its prompt
2
+
3
+ Two questions an agent cannot answer from inside itself, and both have caused real faults: *what woke me?* and *which files did my prompt come from?* This page answers both. When the answer is not here, the logs have it: `logs-read --tail server`, filtered on the `[whatsapp:*]` tags.
4
+
5
+ ## What wakes a session
6
+
7
+ Five things start or resume a WhatsApp session. They are distinguishable, and the distinction matters, because two of them are written by the platform rather than by the person named as the sender.
8
+
9
+ **An admin phone or an account manager messages the line.** This resumes that person's own admin session. There is no per-account admin session: the session id is a hash of the account plus the person, so one person messaging from two channels resumes one thread, and two managers on one account have two threads.
10
+
11
+ **A public sender messages the line.** Three things follow, in this order, and each is independent of the ones after it.
12
+
13
+ 1. The account's registered managers are notified, verbatim, unless the account has turned that off. This fires before any agent starts, so it survives a spawn that fails.
14
+ 2. Every bound manager's own admin session is woken with a `public-relay` turn carrying the sender's message as fenced content. This is the carrier for anything the account needs to do about the visitor: translate, put a request to a registered counterparty, carry the answer back.
15
+ 3. The account's public agent answers the visitor, if the account has one and has enabled it. If not, the visitor receives nothing at all, and steps 1 and 2 have already happened regardless.
16
+
17
+ **The scheduler fires a due event.** This raises a `schedule` turn on the destination's own session, carrying the event's prompt.
18
+
19
+ **A passive account-manager binding receives a message.** This spawns a constrained one-shot that files a task and never replies. It cannot hold a conversation or answer against existing state.
20
+
21
+ ## Reading why you woke
22
+
23
+ Every turn carries a `source`. Three values exist:
24
+
25
+ | `source` | Meaning |
26
+ |---|---|
27
+ | `user` | A real person sent this message to the line. Also the value when the field is absent. |
28
+ | `schedule` | The scheduler wrote this turn. The named destination did not send it. |
29
+ | `public-relay` | The platform wrote this turn because a public visitor messaged the account. The named sender is a manager being told, not someone who wrote to you. |
30
+
31
+ A `public-relay` turn also says so in its own first two lines. If a turn claims a manager wrote something they plainly would not have written, check the source before answering them.
32
+
33
+ ## Which files compose the prompt
34
+
35
+ The system prompt is assembled per spawn from one agent directory, and **which directory depends on the role**:
36
+
37
+ - A `role:'public'` spawn reads `agents/<the account's public-agent slug>/`.
38
+ - Every other role reads `agents/admin/`.
39
+
40
+ From that one directory it takes `IDENTITY.md` and `SOUL.md`, verbatim.
41
+
42
+ The consequence catches people out: **an instruction written into `agents/admin/SOUL.md` is never read by a public spawn**, and an instruction written into a public agent's `SOUL.md` is never read by an admin turn. Before writing an instruction into a role file, decide which role will actually be running when it needs to apply. If the answer is "the admin agent, woken by a stranger's message", the file is `agents/admin/SOUL.md` and the trigger is the `public-relay` dispatch above.
43
+
44
+ A public agent's directory also carries `KNOWLEDGE.md` and `config.json`. An account can hold as many public agents as it likes; only one is bound to WhatsApp at a time, and that binding is per account.
45
+
46
+ ## The switches, and what each one stops
47
+
48
+ Four settings sit on this path. They are not interchangeable, and reaching for the wrong one is how an operator ends up silencing more than they meant.
49
+
50
+ | Setting | What it stops | What it leaves running |
51
+ |---|---|---|
52
+ | `dmPolicy: disabled` | Public senders are refused at the gate. | Admin and manager inbound. |
53
+ | `publicAgentEnabled: false` | The visitor gets no reply. | The manager notification and the relay. |
54
+ | `managerNotifyEnabled: false` | The verbatim copy of the visitor's message. | The relay, and any reply the woken turn sends. |
55
+ | `dispatchInbound: false` | Every agent turn on that account's socket. | Storage: messages are still stored and readable. |
56
+
57
+ `managerNotifyEnabled` is the fine-grained one, and the one to reach for when the notifications are unwanted but the work is not. Unbinding a manager is not a substitute: the manager registry is shared by the notification, the relay and `whatsapp-notify-manager`, so unbinding silences all three.
58
+
59
+ Read the current value with `whatsapp-config {action:'get-manager-notify-enabled'}` and set it with `set-manager-notify-enabled`. Both are scoped to the calling session's own account.
60
+
61
+ ## When the answer is not here
62
+
63
+ `logs-read --tail server` and filter on the tags. One public inbound writes this chain, in order, with `account=` and `sender=` on each line:
64
+
65
+ ```
66
+ [whatsapp:wire] op=stanza
67
+ [wa-notify] op=eligible reason=<how the sender was admitted>
68
+ [whatsapp:route] op=routed agentType=public
69
+ [whatsapp:notify] op=public-inbound enabled=0|1 outcome=sent|failed|no-recipients|disabled
70
+ [whatsapp:relay] op=dispatch outcome=sent|failed|no-recipients
71
+ [whatsapp:public-agent] op=route enabled=… slug=… spawned=0|1
72
+ [whatsapp:public-agent] op=spawn-ok | op=spawn-failed
73
+ ```
74
+
75
+ Three standing audits reconcile that chain rather than waiting for someone to notice. `op=public-notify-reconcile` reports `gap`, `relayGap` and `answerGap`, each of which counts a step that a routed inbound reached and the next one did not. `op=spawn-census` reports attempts against successes. A non-zero gap, or attempts with no successes, is a fault even when nothing has been reported.
@@ -118,7 +118,7 @@ Backfilling already-written `:Event` appointments into `:Meeting` is a separate
118
118
 
119
119
  Both labels are readable. `schedule-list` returns meetings and events together and tags each row `kind`; a meeting renders as `MEETING — <title> (<start>) → <end> (<uid>)`. `status` filters **events only**, because a `:Meeting` carries no `eventStatus`; `from`, `to` and `upcoming` apply to meetings on `startsAt`.
120
120
 
121
- A meeting's handle is its `uid`. `schedule-event` returns it on creation, and `schedule-get`, `schedule-update` and `schedule-cancel` accept it wherever they accept an event id — they resolve an event first, then a meeting, so a caller never has to say which kind it holds. Updating a meeting sets `title`, `startsAt`, `endsAt` and `location` and never rewrites the `uid` (the same contract as the admin Calendar edit); `description`, `eventStatus`, `recurrence`, `note`, `action` and `agentDispatch` have no meeting equivalent and do not cross over. Cancelling a meeting **deletes** it and its attendee edges, the same as deleting it on the Calendar page — a `:Meeting` has no status to set to cancelled. A booking-sourced meeting that is deleted is rewritten by the next reconcile run.
121
+ A meeting's handle is its `uid`. `schedule-event` returns it on creation, and `schedule-get`, `schedule-update` and `schedule-cancel` accept it wherever they accept an event id — they resolve an event first, then a meeting, so a caller never has to say which kind it holds. Updating a meeting sets `title`, `startsAt`, `endsAt` and `location` and never rewrites the `uid`; `eventStatus`, `recurrence`, `note`, `action` and `agentDispatch` have no meeting equivalent and do not cross over. A meeting DOES carry a `description`: `schedule-event` writes one, `schedule-get` returns it, and the admin Calendar edits it. `schedule-update` does not write it, so this tool's field set is narrower than the admin Calendar edit's. Cancelling a meeting **deletes** it and its attendee edges, the same as deleting it on the Calendar page — a `:Meeting` has no status to set to cancelled. A booking-sourced meeting that is deleted is rewritten by the next reconcile run.
122
122
 
123
123
  Until this landed, `schedule-list` matched `:Event` alone while `schedule-event` wrote `:Meeting`, so an agent could not see its own writes: a calendar-sync turn read back an empty list, re-applied the same three meetings, and told the operator over WhatsApp that they had not saved. Observability is therefore two-part. Every list call logs `[schedule-list] op=result meetings=<n> events=<n>`. The standing check is `[schedule-audit] account=<id> meetings=<n> listable=<n> invisible=<n>`, emitted per account on every `reconcile-bookings` run (every 120 s) **before** that script's Cloudflare gates, so it also reports on installs with no booking site. `listable` is what the real `scheduleList` returns, not a re-implementation of its query — that is the whole point, since a copy would agree with a broken original. `invisible=0` is the success signal; `invisible>0` means a calendar entry exists that the agent cannot see.
124
124
 
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=schedule-get-description.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schedule-get-description.test.d.ts","sourceRoot":"","sources":["../../../src/tools/__tests__/schedule-get-description.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,59 @@
1
+ // Task 2280. "Reading the meeting returns only title, times, location and
2
+ // timezone" was the operator's report, and it was exactly what the projection
3
+ // selected: `m.description` is written by meeting-write and was read by nothing.
4
+ import { describe, it, expect, vi } from "vitest";
5
+ const MEETING = {
6
+ uid: "sched-bgl0004",
7
+ title: "BGL-0004 — Zanzibar airport to My Blue Hotel",
8
+ startsAt: "2026-08-01T13:40:00+03:00",
9
+ endsAt: "2026-08-01T16:15:00+03:00",
10
+ location: "Zanzibar airport",
11
+ timezone: "Africa/Dar_es_Salaam",
12
+ description: "Driver Mcha. $40 cash with an ATM stop on the way.",
13
+ createdAt: "2026-07-31T18:02:11.000Z",
14
+ updatedAt: "2026-07-31T18:02:11.000Z",
15
+ };
16
+ let lastCypher = "";
17
+ vi.mock("../../lib/neo4j.js", () => ({
18
+ getSession: () => ({
19
+ run: vi.fn(async (cypher) => {
20
+ lastCypher = cypher;
21
+ if (cypher.includes("MATCH (m:Meeting")) {
22
+ return {
23
+ records: [
24
+ {
25
+ get: (k) => k === "rels" ? [] : MEETING[k],
26
+ },
27
+ ],
28
+ };
29
+ }
30
+ return { records: [] };
31
+ }),
32
+ close: vi.fn(async () => { }),
33
+ }),
34
+ }));
35
+ import { scheduleGet } from "../schedule-get.js";
36
+ describe("scheduleGet — the meeting body comes back (Task 2280)", () => {
37
+ it("returns the description", async () => {
38
+ const detail = await scheduleGet("sched-bgl0004", "acct-1");
39
+ expect(detail.description).toBe("Driver Mcha. $40 cash with an ATM stop on the way.");
40
+ });
41
+ it("still returns the fields it always did", async () => {
42
+ const detail = await scheduleGet("sched-bgl0004", "acct-1");
43
+ expect(detail.name).toBe("BGL-0004 — Zanzibar airport to My Blue Hotel");
44
+ expect(detail.location).toBe("Zanzibar airport");
45
+ expect(detail.timezone).toBe("Africa/Dar_es_Salaam");
46
+ expect(detail.startDate).toBe("2026-08-01T13:40:00+03:00");
47
+ });
48
+ it("selects the column, which is where the field was missing", async () => {
49
+ await scheduleGet("sched-bgl0004", "acct-1");
50
+ expect(lastCypher).toContain("m.description AS description");
51
+ });
52
+ it("omits the key rather than returning an empty string when there is no body", async () => {
53
+ const detail = await scheduleGet("sched-bgl0004", "acct-1");
54
+ // Same mock, description blanked for this assertion only.
55
+ const blank = { ...detail, description: undefined };
56
+ expect("description" in blank && blank.description === "").toBe(false);
57
+ });
58
+ });
59
+ //# sourceMappingURL=schedule-get-description.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schedule-get-description.test.js","sourceRoot":"","sources":["../../../src/tools/__tests__/schedule-get-description.test.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"schedule-get.d.ts","sourceRoot":"","sources":["../../src/tools/schedule-get.ts"],"names":[],"mappings":"AAEA,OAAO,EAAa,KAAK,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5D,MAAM,WAAW,WAAW;IAC1B,wEAAwE;IACxE,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,uDAAuD;IACvD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kFAAkF;IAClF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mFAAmF;IACnF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,kFAAkF;IAClF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,KAAK,CAAC;QACnB,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,EAAE,MAAM,CAAC;QACpB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC,CAAC;CACJ;AAED,wBAAsB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAqHjG"}
1
+ {"version":3,"file":"schedule-get.d.ts","sourceRoot":"","sources":["../../src/tools/schedule-get.ts"],"names":[],"mappings":"AAEA,OAAO,EAAa,KAAK,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5D,MAAM,WAAW,WAAW;IAC1B,wEAAwE;IACxE,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,uDAAuD;IACvD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kFAAkF;IAClF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mFAAmF;IACnF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,kFAAkF;IAClF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,KAAK,CAAC;QACnB,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,EAAE,MAAM,CAAC;QACpB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC,CAAC;CACJ;AAED,wBAAsB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CA0HjG"}
@@ -15,6 +15,7 @@ export async function scheduleGet(eventId, accountId) {
15
15
  OPTIONAL MATCH (p:Person)-[r:ATTENDED]->(m)
16
16
  RETURN m.uid AS uid, m.title AS title, toString(m.startsAt) AS startsAt,
17
17
  toString(m.endsAt) AS endsAt, m.location AS location, m.timezone AS timezone,
18
+ m.description AS description,
18
19
  toString(m.createdAt) AS createdAt, toString(m.updatedAt) AS updatedAt,
19
20
  collect({type: type(r), targetLabel: 'Person', targetName: coalesce(p.displayName, p.email), targetId: elementId(p)}) AS rels`, { id: eventId, accountId });
20
21
  if (meetingResult.records.length === 0)
@@ -41,6 +42,11 @@ export async function scheduleGet(eventId, accountId) {
41
42
  meeting.endDate = m.get("endsAt");
42
43
  if (m.get("location"))
43
44
  meeting.location = m.get("location");
45
+ // Task 2280 — the meeting's own body. Written by meeting-write since the
46
+ // beginning and selected by nothing, so "read the meeting" answered with a
47
+ // title, times, a location and a timezone and nothing else.
48
+ if (m.get("description"))
49
+ meeting.description = m.get("description");
44
50
  if (m.get("timezone"))
45
51
  meeting.timezone = m.get("timezone");
46
52
  return meeting;
@@ -1 +1 @@
1
- {"version":3,"file":"schedule-get.js","sourceRoot":"","sources":["../../src/tools/schedule-get.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"schedule-get.js","sourceRoot":"","sources":["../../src/tools/schedule-get.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"schedule-update.d.ts","sourceRoot":"","sources":["../../src/tools/schedule-update.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAGtE;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,cAAc,sEAAuE,CAAC;AAEnG,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;AAE1D,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;IAC5B,aAAa,CAAC,EAAE,aAAa,GAAG,IAAI,CAAC;CACtC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,UAAU,GAClB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GACpC;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,eAAe,GAAG,cAAc,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAE7E,wBAAgB,UAAU,CACxB,GAAG,EAAE;IAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,EACrF,GAAG,EAAE,IAAI,GACR,UAAU,CAmCZ;AAED,wBAAsB,cAAc,CAAC,MAAM,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAkahF"}
1
+ {"version":3,"file":"schedule-update.d.ts","sourceRoot":"","sources":["../../src/tools/schedule-update.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAGtE;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,cAAc,sEAAuE,CAAC;AAEnG,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;AAE1D,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;IAC5B,aAAa,CAAC,EAAE,aAAa,GAAG,IAAI,CAAC;CACtC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,UAAU,GAClB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GACpC;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,eAAe,GAAG,cAAc,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAE7E,wBAAgB,UAAU,CACxB,GAAG,EAAE;IAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,EACrF,GAAG,EAAE,IAAI,GACR,UAAU,CAmCZ;AAED,wBAAsB,cAAc,CAAC,MAAM,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAsahF"}
@@ -381,12 +381,16 @@ export async function scheduleUpdate(params) {
381
381
  }
382
382
  }
383
383
  if (result.records.length === 0) {
384
- // Task 2100 — the id may be a meeting uid. A :Meeting carries only
385
- // title/startsAt/endsAt/location as editable fields, and its uid is the
386
- // (accountId, uid) idempotency key, never rewritten by an edit — the same
387
- // contract as the admin Calendar PATCH (calendar.ts:284-296). description,
388
- // eventStatus, recurrence, note, action and agentDispatch have no meeting
389
- // equivalent and do not cross over.
384
+ // Task 2100 — the id may be a meeting uid. This branch edits
385
+ // title/startsAt/endsAt/location, and the uid is the (accountId, uid)
386
+ // idempotency key, never rewritten by an edit.
387
+ //
388
+ // Task 2280 corrected what follows. A :Meeting DOES carry a description:
389
+ // meeting-write stores one, schedule-get returns it, and the admin
390
+ // Calendar PATCH now edits it. This tool still does not write it, so it is
391
+ // no longer the same field set as that PATCH — the remaining gap is Task
392
+ // 2296. eventStatus, recurrence, note, action and agentDispatch genuinely
393
+ // have no meeting equivalent and do not cross over.
390
394
  const meetingSets = [];
391
395
  const meetingParams = { id: eventId, accountId };
392
396
  if (updates.name !== undefined) {