@rubytech/create-maxy-code 0.1.542 → 0.1.544

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 (371) hide show
  1. package/dist/__tests__/public-instruction-seed.test.js +102 -0
  2. package/dist/index.js +47 -0
  3. package/dist/public-instruction-seed.js +70 -0
  4. package/package.json +1 -1
  5. package/payload/platform/lib/shared-folder/dist/index.d.ts +47 -0
  6. package/payload/platform/lib/shared-folder/dist/index.d.ts.map +1 -0
  7. package/payload/platform/lib/shared-folder/dist/index.js +93 -0
  8. package/payload/platform/lib/shared-folder/dist/index.js.map +1 -0
  9. package/payload/platform/lib/shared-folder/src/index.ts +92 -0
  10. package/payload/platform/lib/shared-folder/tsconfig.json +5 -0
  11. package/payload/platform/package.json +2 -2
  12. package/payload/platform/plugins/admin/PLUGIN.md +2 -0
  13. package/payload/platform/plugins/admin/hooks/__tests__/public-tool-surface.test.sh +173 -0
  14. package/payload/platform/plugins/admin/hooks/public-tool-surface.sh +123 -0
  15. package/payload/platform/plugins/admin/mcp/dist/tools/agent-write.d.ts.map +1 -1
  16. package/payload/platform/plugins/admin/mcp/dist/tools/agent-write.js +13 -1
  17. package/payload/platform/plugins/admin/mcp/dist/tools/agent-write.js.map +1 -1
  18. package/payload/platform/plugins/admin/skills/channel-instruction/SKILL.md +46 -0
  19. package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +18 -1
  20. package/payload/platform/plugins/admin/skills/whats-new/SKILL.md +15 -0
  21. package/payload/platform/plugins/docs/references/access-control.md +14 -0
  22. package/payload/platform/plugins/docs/references/internals.md +2 -0
  23. package/payload/platform/plugins/docs/references/platform.md +1 -0
  24. package/payload/platform/plugins/filesystem/.claude-plugin/plugin.json +1 -1
  25. package/payload/platform/plugins/filesystem/PLUGIN.md +11 -1
  26. package/payload/platform/plugins/filesystem/mcp/dist/index.js +23 -7
  27. package/payload/platform/plugins/filesystem/mcp/dist/index.js.map +1 -1
  28. package/payload/platform/plugins/filesystem/mcp/dist/lib/__tests__/scope.test.js +104 -4
  29. package/payload/platform/plugins/filesystem/mcp/dist/lib/__tests__/scope.test.js.map +1 -1
  30. package/payload/platform/plugins/filesystem/mcp/dist/lib/__tests__/shared-folder.test.d.ts +2 -0
  31. package/payload/platform/plugins/filesystem/mcp/dist/lib/__tests__/shared-folder.test.d.ts.map +1 -0
  32. package/payload/platform/plugins/filesystem/mcp/dist/lib/__tests__/shared-folder.test.js +67 -0
  33. package/payload/platform/plugins/filesystem/mcp/dist/lib/__tests__/shared-folder.test.js.map +1 -0
  34. package/payload/platform/plugins/filesystem/mcp/dist/lib/scope.d.ts +16 -2
  35. package/payload/platform/plugins/filesystem/mcp/dist/lib/scope.d.ts.map +1 -1
  36. package/payload/platform/plugins/filesystem/mcp/dist/lib/scope.js +54 -1
  37. package/payload/platform/plugins/filesystem/mcp/dist/lib/scope.js.map +1 -1
  38. package/payload/platform/plugins/filesystem/mcp/dist/tools/__tests__/handlers.test.js +76 -2
  39. package/payload/platform/plugins/filesystem/mcp/dist/tools/__tests__/handlers.test.js.map +1 -1
  40. package/payload/platform/plugins/filesystem/mcp/dist/tools/file-edit.d.ts +1 -0
  41. package/payload/platform/plugins/filesystem/mcp/dist/tools/file-edit.d.ts.map +1 -1
  42. package/payload/platform/plugins/filesystem/mcp/dist/tools/file-edit.js +3 -3
  43. package/payload/platform/plugins/filesystem/mcp/dist/tools/file-edit.js.map +1 -1
  44. package/payload/platform/plugins/filesystem/mcp/dist/tools/file-glob.d.ts +1 -0
  45. package/payload/platform/plugins/filesystem/mcp/dist/tools/file-glob.d.ts.map +1 -1
  46. package/payload/platform/plugins/filesystem/mcp/dist/tools/file-glob.js +1 -1
  47. package/payload/platform/plugins/filesystem/mcp/dist/tools/file-glob.js.map +1 -1
  48. package/payload/platform/plugins/filesystem/mcp/dist/tools/file-grep.d.ts +1 -0
  49. package/payload/platform/plugins/filesystem/mcp/dist/tools/file-grep.d.ts.map +1 -1
  50. package/payload/platform/plugins/filesystem/mcp/dist/tools/file-grep.js +3 -3
  51. package/payload/platform/plugins/filesystem/mcp/dist/tools/file-grep.js.map +1 -1
  52. package/payload/platform/plugins/filesystem/mcp/dist/tools/file-list.d.ts +1 -0
  53. package/payload/platform/plugins/filesystem/mcp/dist/tools/file-list.d.ts.map +1 -1
  54. package/payload/platform/plugins/filesystem/mcp/dist/tools/file-list.js +3 -3
  55. package/payload/platform/plugins/filesystem/mcp/dist/tools/file-list.js.map +1 -1
  56. package/payload/platform/plugins/filesystem/mcp/dist/tools/file-read.d.ts +1 -0
  57. package/payload/platform/plugins/filesystem/mcp/dist/tools/file-read.d.ts.map +1 -1
  58. package/payload/platform/plugins/filesystem/mcp/dist/tools/file-read.js +3 -3
  59. package/payload/platform/plugins/filesystem/mcp/dist/tools/file-read.js.map +1 -1
  60. package/payload/platform/plugins/filesystem/mcp/dist/tools/file-write.d.ts +1 -0
  61. package/payload/platform/plugins/filesystem/mcp/dist/tools/file-write.d.ts.map +1 -1
  62. package/payload/platform/plugins/filesystem/mcp/dist/tools/file-write.js +3 -3
  63. package/payload/platform/plugins/filesystem/mcp/dist/tools/file-write.js.map +1 -1
  64. package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/agent-turn-dispatch.test.js +81 -1
  65. package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/agent-turn-dispatch.test.js.map +1 -1
  66. package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.d.ts +22 -0
  67. package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.d.ts.map +1 -1
  68. package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.js +80 -0
  69. package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.js.map +1 -1
  70. package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.js +13 -1
  71. package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.js.map +1 -1
  72. package/payload/platform/plugins/whatsapp/PLUGIN.md +2 -2
  73. package/payload/platform/plugins/whatsapp/mcp/dist/index.js +1 -1
  74. package/payload/platform/plugins/whatsapp/mcp/dist/index.js.map +1 -1
  75. package/payload/platform/plugins/whatsapp/references/channels-whatsapp.md +1 -1
  76. package/payload/platform/scripts/__tests__/public-surface-registered.test.sh +102 -0
  77. package/payload/platform/scripts/check-no-esm-require.mjs +5 -0
  78. package/payload/platform/scripts/lib/__tests__/account-settings-public-surface.test.sh +109 -0
  79. package/payload/platform/scripts/lib/account-settings-public-surface.sh +109 -0
  80. package/payload/platform/scripts/lib/provision-account-dir.sh +6 -3
  81. package/payload/platform/scripts/setup-account.sh +14 -0
  82. package/payload/platform/services/claude-session-manager/dist/agent-identity-locator.d.ts +8 -4
  83. package/payload/platform/services/claude-session-manager/dist/agent-identity-locator.d.ts.map +1 -1
  84. package/payload/platform/services/claude-session-manager/dist/agent-identity-locator.js +27 -7
  85. package/payload/platform/services/claude-session-manager/dist/agent-identity-locator.js.map +1 -1
  86. package/payload/platform/services/claude-session-manager/dist/config.d.ts +11 -6
  87. package/payload/platform/services/claude-session-manager/dist/config.d.ts.map +1 -1
  88. package/payload/platform/services/claude-session-manager/dist/config.js +8 -4
  89. package/payload/platform/services/claude-session-manager/dist/config.js.map +1 -1
  90. package/payload/platform/services/claude-session-manager/dist/fs-watcher.d.ts +24 -2
  91. package/payload/platform/services/claude-session-manager/dist/fs-watcher.d.ts.map +1 -1
  92. package/payload/platform/services/claude-session-manager/dist/fs-watcher.js +23 -1
  93. package/payload/platform/services/claude-session-manager/dist/fs-watcher.js.map +1 -1
  94. package/payload/platform/services/claude-session-manager/dist/http-server.d.ts +35 -0
  95. package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -1
  96. package/payload/platform/services/claude-session-manager/dist/http-server.js +286 -25
  97. package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
  98. package/payload/platform/services/claude-session-manager/dist/index.js +169 -51
  99. package/payload/platform/services/claude-session-manager/dist/index.js.map +1 -1
  100. package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts +24 -12
  101. package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts.map +1 -1
  102. package/payload/platform/services/claude-session-manager/dist/pty-spawner.js +194 -28
  103. package/payload/platform/services/claude-session-manager/dist/pty-spawner.js.map +1 -1
  104. package/payload/platform/services/claude-session-manager/dist/public-agent-reachability.d.ts.map +1 -1
  105. package/payload/platform/services/claude-session-manager/dist/public-agent-reachability.js +4 -0
  106. package/payload/platform/services/claude-session-manager/dist/public-agent-reachability.js.map +1 -1
  107. package/payload/platform/services/claude-session-manager/dist/public-surface-audit.d.ts +24 -3
  108. package/payload/platform/services/claude-session-manager/dist/public-surface-audit.d.ts.map +1 -1
  109. package/payload/platform/services/claude-session-manager/dist/public-surface-audit.js +29 -3
  110. package/payload/platform/services/claude-session-manager/dist/public-surface-audit.js.map +1 -1
  111. package/payload/platform/services/claude-session-manager/dist/rc-public-lockdown.d.ts +27 -0
  112. package/payload/platform/services/claude-session-manager/dist/rc-public-lockdown.d.ts.map +1 -1
  113. package/payload/platform/services/claude-session-manager/dist/rc-public-lockdown.js +32 -0
  114. package/payload/platform/services/claude-session-manager/dist/rc-public-lockdown.js.map +1 -1
  115. package/payload/platform/services/claude-session-manager/dist/role-census.d.ts +24 -0
  116. package/payload/platform/services/claude-session-manager/dist/role-census.d.ts.map +1 -0
  117. package/payload/platform/services/claude-session-manager/dist/role-census.js +50 -0
  118. package/payload/platform/services/claude-session-manager/dist/role-census.js.map +1 -0
  119. package/payload/platform/services/claude-session-manager/dist/session-sidecar.d.ts +24 -2
  120. package/payload/platform/services/claude-session-manager/dist/session-sidecar.d.ts.map +1 -1
  121. package/payload/platform/services/claude-session-manager/dist/session-sidecar.js +21 -0
  122. package/payload/platform/services/claude-session-manager/dist/session-sidecar.js.map +1 -1
  123. package/payload/platform/services/claude-session-manager/dist/stuck-turn-recover.d.ts +76 -0
  124. package/payload/platform/services/claude-session-manager/dist/stuck-turn-recover.d.ts.map +1 -1
  125. package/payload/platform/services/claude-session-manager/dist/stuck-turn-recover.js +110 -19
  126. package/payload/platform/services/claude-session-manager/dist/stuck-turn-recover.js.map +1 -1
  127. package/payload/platform/services/claude-session-manager/dist/stuck-turn-respawn.d.ts +60 -0
  128. package/payload/platform/services/claude-session-manager/dist/stuck-turn-respawn.d.ts.map +1 -0
  129. package/payload/platform/services/claude-session-manager/dist/stuck-turn-respawn.js +93 -0
  130. package/payload/platform/services/claude-session-manager/dist/stuck-turn-respawn.js.map +1 -0
  131. package/payload/platform/services/claude-session-manager/dist/stuck-turn.d.ts +31 -1
  132. package/payload/platform/services/claude-session-manager/dist/stuck-turn.d.ts.map +1 -1
  133. package/payload/platform/services/claude-session-manager/dist/stuck-turn.js +72 -9
  134. package/payload/platform/services/claude-session-manager/dist/stuck-turn.js.map +1 -1
  135. package/payload/platform/services/claude-session-manager/dist/system-prompt.d.ts +1 -1
  136. package/payload/platform/services/claude-session-manager/dist/system-prompt.d.ts.map +1 -1
  137. package/payload/platform/services/claude-session-manager/dist/system-prompt.js +9 -1
  138. package/payload/platform/services/claude-session-manager/dist/system-prompt.js.map +1 -1
  139. package/payload/platform/services/claude-session-manager/dist/types.d.ts +9 -3
  140. package/payload/platform/services/claude-session-manager/dist/types.d.ts.map +1 -1
  141. package/payload/platform/services/telegram-channel/dist/instructions.d.ts +0 -1
  142. package/payload/platform/services/telegram-channel/dist/instructions.d.ts.map +1 -1
  143. package/payload/platform/services/telegram-channel/dist/instructions.js +0 -46
  144. package/payload/platform/services/telegram-channel/dist/instructions.js.map +1 -1
  145. package/payload/platform/services/telegram-channel/dist/notification.d.ts +16 -4
  146. package/payload/platform/services/telegram-channel/dist/notification.d.ts.map +1 -1
  147. package/payload/platform/services/telegram-channel/dist/notification.js +27 -14
  148. package/payload/platform/services/telegram-channel/dist/notification.js.map +1 -1
  149. package/payload/platform/services/telegram-channel/dist/server.d.ts.map +1 -1
  150. package/payload/platform/services/telegram-channel/dist/server.js +10 -0
  151. package/payload/platform/services/telegram-channel/dist/server.js.map +1 -1
  152. package/payload/platform/services/webchat-channel/dist/instructions.d.ts +0 -1
  153. package/payload/platform/services/webchat-channel/dist/instructions.d.ts.map +1 -1
  154. package/payload/platform/services/webchat-channel/dist/instructions.js +0 -60
  155. package/payload/platform/services/webchat-channel/dist/instructions.js.map +1 -1
  156. package/payload/platform/services/webchat-channel/dist/notification.d.ts +14 -2
  157. package/payload/platform/services/webchat-channel/dist/notification.d.ts.map +1 -1
  158. package/payload/platform/services/webchat-channel/dist/notification.js +28 -12
  159. package/payload/platform/services/webchat-channel/dist/notification.js.map +1 -1
  160. package/payload/platform/services/webchat-channel/dist/server.d.ts.map +1 -1
  161. package/payload/platform/services/webchat-channel/dist/server.js +10 -0
  162. package/payload/platform/services/webchat-channel/dist/server.js.map +1 -1
  163. package/payload/platform/services/whatsapp-channel/dist/notification.d.ts +97 -33
  164. package/payload/platform/services/whatsapp-channel/dist/notification.d.ts.map +1 -1
  165. package/payload/platform/services/whatsapp-channel/dist/notification.js +98 -76
  166. package/payload/platform/services/whatsapp-channel/dist/notification.js.map +1 -1
  167. package/payload/platform/services/whatsapp-channel/dist/server.d.ts +18 -0
  168. package/payload/platform/services/whatsapp-channel/dist/server.d.ts.map +1 -1
  169. package/payload/platform/services/whatsapp-channel/dist/server.js +87 -5
  170. package/payload/platform/services/whatsapp-channel/dist/server.js.map +1 -1
  171. package/payload/platform/services/whatsapp-channel/dist/targets.d.ts +41 -9
  172. package/payload/platform/services/whatsapp-channel/dist/targets.d.ts.map +1 -1
  173. package/payload/platform/services/whatsapp-channel/dist/targets.js +42 -7
  174. package/payload/platform/services/whatsapp-channel/dist/targets.js.map +1 -1
  175. package/payload/platform/templates/agents/admin/INSTRUCTION.md +0 -0
  176. package/payload/server/{adminuser-self-heal-LC7HZAC6.js → adminuser-self-heal-ZHFNDKJK.js} +1 -1
  177. package/payload/server/{chunk-HZP7BKBF.js → chunk-CVUSUNXM.js} +128 -4
  178. package/payload/server/{chunk-CKTHAHL4.js → chunk-DU7GPDJJ.js} +4 -2
  179. package/payload/server/{chunk-PFF6I7KP.js → chunk-HYQNUVGO.js} +8 -1
  180. package/payload/server/{chunk-ERIM3EFB.js → chunk-X2RRMHVV.js} +1 -1
  181. package/payload/server/{manager-CM55K4J2.js → manager-TI2YJQVZ.js} +3 -3
  182. package/payload/server/maxy-edge.js +3 -3
  183. package/payload/server/public/activity.html +5 -5
  184. package/payload/server/public/agents.html +4 -4
  185. package/payload/server/public/assets/AdminLoginScreens-BGKtDqAk.js +1 -0
  186. package/payload/server/public/assets/AdminLoginScreens-BGKtDqAk.js.br +0 -0
  187. package/payload/server/public/assets/AdminLoginScreens-BGKtDqAk.js.gz +0 -0
  188. package/payload/server/public/assets/AdminShell-DnfgsAQl.js +2 -0
  189. package/payload/server/public/assets/AdminShell-DnfgsAQl.js.br +0 -0
  190. package/payload/server/public/assets/AdminShell-DnfgsAQl.js.gz +0 -0
  191. package/payload/server/public/assets/activity-ByJSut0Q.js +1 -0
  192. package/payload/server/public/assets/activity-ByJSut0Q.js.br +0 -0
  193. package/payload/server/public/assets/activity-ByJSut0Q.js.gz +0 -0
  194. package/payload/server/public/assets/admin-CkeJO6kA.js +1 -0
  195. package/payload/server/public/assets/admin-CkeJO6kA.js.br +0 -0
  196. package/payload/server/public/assets/admin-CkeJO6kA.js.gz +0 -0
  197. package/payload/server/public/assets/agents-D8phtRX5.js +1 -0
  198. package/payload/server/public/assets/agents-D8phtRX5.js.br +0 -0
  199. package/payload/server/public/assets/agents-D8phtRX5.js.gz +0 -0
  200. package/payload/server/public/assets/browser-DQSTjdom.js +1 -0
  201. package/payload/server/public/assets/browser-DQSTjdom.js.br +0 -0
  202. package/payload/server/public/assets/browser-DQSTjdom.js.gz +0 -0
  203. package/payload/server/public/assets/calendar-DFJu1XjP.js +1 -0
  204. package/payload/server/public/assets/calendar-DFJu1XjP.js.br +0 -0
  205. package/payload/server/public/assets/calendar-DFJu1XjP.js.gz +0 -0
  206. package/payload/server/public/assets/chat-DUqtIsOt.js +1 -0
  207. package/payload/server/public/assets/chat-DUqtIsOt.js.br +0 -0
  208. package/payload/server/public/assets/chat-DUqtIsOt.js.gz +0 -0
  209. package/payload/server/public/assets/chevron-left-DFK18xVX.js +1 -0
  210. package/payload/server/public/assets/chevron-left-DFK18xVX.js.br +0 -0
  211. package/payload/server/public/assets/chevron-right-DJ4oaHoN.js +1 -0
  212. package/payload/server/public/assets/chevron-right-DJ4oaHoN.js.br +0 -0
  213. package/payload/server/public/assets/clock-wHIan2DW.js +1 -0
  214. package/payload/server/public/assets/clock-wHIan2DW.js.br +0 -0
  215. package/payload/server/public/assets/{copy-3kj9Oaoc.js → copy-lFFhXRGk.js} +1 -1
  216. package/payload/server/public/assets/copy-lFFhXRGk.js.br +0 -0
  217. package/payload/server/public/assets/copy-lFFhXRGk.js.gz +0 -0
  218. package/payload/server/public/assets/data-Cxv97ARy.js +1 -0
  219. package/payload/server/public/assets/data-Cxv97ARy.js.br +0 -0
  220. package/payload/server/public/assets/data-Cxv97ARy.js.gz +0 -0
  221. package/payload/server/public/assets/{file-text-CBaewT76.js → file-text-D2Y-bkNy.js} +1 -1
  222. package/payload/server/public/assets/file-text-D2Y-bkNy.js.br +0 -0
  223. package/payload/server/public/assets/file-text-D2Y-bkNy.js.gz +0 -0
  224. package/payload/server/public/assets/{graph-B8-e2_Z-.js → graph-C-3yN6JD.js} +3 -3
  225. package/payload/server/public/assets/graph-C-3yN6JD.js.br +0 -0
  226. package/payload/server/public/assets/graph-C-3yN6JD.js.gz +0 -0
  227. package/payload/server/public/assets/{graph-labels-Bsc23eZU.js → graph-labels-DiaPLP27.js} +1 -1
  228. package/payload/server/public/assets/graph-labels-DiaPLP27.js.br +0 -0
  229. package/payload/server/public/assets/graph-labels-DiaPLP27.js.gz +0 -0
  230. package/payload/server/public/assets/operator-KuGPvSa9.js +1 -0
  231. package/payload/server/public/assets/operator-KuGPvSa9.js.br +0 -0
  232. package/payload/server/public/assets/operator-KuGPvSa9.js.gz +0 -0
  233. package/payload/server/public/assets/page-BhGeFXWA.js +1 -0
  234. package/payload/server/public/assets/page-BhGeFXWA.js.br +0 -0
  235. package/payload/server/public/assets/page-BhGeFXWA.js.gz +0 -0
  236. package/payload/server/public/assets/page-EnbVC-yM.js +32 -0
  237. package/payload/server/public/assets/page-EnbVC-yM.js.br +0 -0
  238. package/payload/server/public/assets/page-EnbVC-yM.js.gz +0 -0
  239. package/payload/server/public/assets/play-jZFZAG-t.js +1 -0
  240. package/payload/server/public/assets/play-jZFZAG-t.js.br +0 -0
  241. package/payload/server/public/assets/play-jZFZAG-t.js.gz +0 -0
  242. package/payload/server/public/assets/public-CdSgMNC7.js +1 -0
  243. package/payload/server/public/assets/public-CdSgMNC7.js.br +0 -0
  244. package/payload/server/public/assets/public-CdSgMNC7.js.gz +0 -0
  245. package/payload/server/public/assets/{rotate-ccw-FZW7c8p8.js → rotate-ccw-rTRuTqei.js} +1 -1
  246. package/payload/server/public/assets/rotate-ccw-rTRuTqei.js.br +0 -0
  247. package/payload/server/public/assets/rotate-ccw-rTRuTqei.js.gz +0 -0
  248. package/payload/server/public/assets/routines-DNRxNRSQ.js +2 -0
  249. package/payload/server/public/assets/routines-DNRxNRSQ.js.br +0 -0
  250. package/payload/server/public/assets/routines-DNRxNRSQ.js.gz +0 -0
  251. package/payload/server/public/assets/skills-DFWtZNkW.js +1 -0
  252. package/payload/server/public/assets/skills-DFWtZNkW.js.br +0 -0
  253. package/payload/server/public/assets/skills-DFWtZNkW.js.gz +0 -0
  254. package/payload/server/public/assets/tasks-B94AuKSy.js +3 -0
  255. package/payload/server/public/assets/tasks-B94AuKSy.js.br +0 -0
  256. package/payload/server/public/assets/tasks-B94AuKSy.js.gz +0 -0
  257. package/payload/server/public/assets/{triangle-alert-CR-jRJdI.js → triangle-alert-DtWUg6jR.js} +1 -1
  258. package/payload/server/public/assets/triangle-alert-DtWUg6jR.js.br +0 -0
  259. package/payload/server/public/assets/triangle-alert-DtWUg6jR.js.gz +0 -0
  260. package/payload/server/public/assets/useCopyFeedback-CjKYO-Qf.js +1 -0
  261. package/payload/server/public/assets/useCopyFeedback-CjKYO-Qf.js.br +0 -0
  262. package/payload/server/public/assets/useCopyFeedback-CjKYO-Qf.js.gz +0 -0
  263. package/payload/server/public/assets/useMediaQuery-BYIHo-xL.js +14 -0
  264. package/payload/server/public/assets/useMediaQuery-BYIHo-xL.js.br +0 -0
  265. package/payload/server/public/assets/useMediaQuery-BYIHo-xL.js.gz +0 -0
  266. package/payload/server/public/assets/useMediaQuery-DlOWP56H.css +1 -0
  267. package/payload/server/public/assets/useMediaQuery-DlOWP56H.css.br +0 -0
  268. package/payload/server/public/assets/useMediaQuery-DlOWP56H.css.gz +0 -0
  269. package/payload/server/public/assets/useVoiceRecorder-BKFAYuzz.js +2 -0
  270. package/payload/server/public/assets/useVoiceRecorder-BKFAYuzz.js.br +0 -0
  271. package/payload/server/public/assets/useVoiceRecorder-BKFAYuzz.js.gz +0 -0
  272. package/payload/server/public/assets/{wrench-CpCOYUBc.js → wrench-Ct4kf-uv.js} +1 -1
  273. package/payload/server/public/assets/wrench-Ct4kf-uv.js.br +0 -0
  274. package/payload/server/public/assets/wrench-Ct4kf-uv.js.gz +0 -0
  275. package/payload/server/public/browser.html +4 -4
  276. package/payload/server/public/calendar.html +8 -8
  277. package/payload/server/public/chat.html +13 -13
  278. package/payload/server/public/data.html +11 -11
  279. package/payload/server/public/graph.html +9 -9
  280. package/payload/server/public/index.html +14 -14
  281. package/payload/server/public/operator.html +14 -14
  282. package/payload/server/public/public.html +13 -13
  283. package/payload/server/public/routines.html +6 -6
  284. package/payload/server/public/skills.html +5 -5
  285. package/payload/server/public/tasks.html +6 -6
  286. package/payload/server/server.js +537 -263
  287. package/payload/server/{src-JN6PIAJN.js → src-MM64CYYZ.js} +1 -1
  288. package/payload/server/{userprofile-reconcile-QHVLY2AH.js → userprofile-reconcile-TL4JKBPG.js} +1 -1
  289. package/payload/server/public/assets/AdminLoginScreens-DuFCjbz2.js +0 -1
  290. package/payload/server/public/assets/AdminLoginScreens-DuFCjbz2.js.br +0 -0
  291. package/payload/server/public/assets/AdminLoginScreens-DuFCjbz2.js.gz +0 -0
  292. package/payload/server/public/assets/AdminShell-DJL5DzRX.js +0 -2
  293. package/payload/server/public/assets/AdminShell-DJL5DzRX.js.br +0 -0
  294. package/payload/server/public/assets/AdminShell-DJL5DzRX.js.gz +0 -0
  295. package/payload/server/public/assets/activity-CpMnNr5c.js +0 -1
  296. package/payload/server/public/assets/activity-CpMnNr5c.js.br +0 -0
  297. package/payload/server/public/assets/activity-CpMnNr5c.js.gz +0 -0
  298. package/payload/server/public/assets/admin-CBwKIfaI.js +0 -1
  299. package/payload/server/public/assets/admin-CBwKIfaI.js.br +0 -0
  300. package/payload/server/public/assets/admin-CBwKIfaI.js.gz +0 -0
  301. package/payload/server/public/assets/agents-C4LmSKjb.js +0 -1
  302. package/payload/server/public/assets/agents-C4LmSKjb.js.br +0 -0
  303. package/payload/server/public/assets/agents-C4LmSKjb.js.gz +0 -0
  304. package/payload/server/public/assets/browser-Bm9xm_yc.js +0 -1
  305. package/payload/server/public/assets/browser-Bm9xm_yc.js.br +0 -0
  306. package/payload/server/public/assets/browser-Bm9xm_yc.js.gz +0 -0
  307. package/payload/server/public/assets/calendar-CNY9FTWe.js +0 -1
  308. package/payload/server/public/assets/calendar-CNY9FTWe.js.br +0 -0
  309. package/payload/server/public/assets/calendar-CNY9FTWe.js.gz +0 -0
  310. package/payload/server/public/assets/chat-3WoUGCTd.js +0 -1
  311. package/payload/server/public/assets/chat-3WoUGCTd.js.br +0 -0
  312. package/payload/server/public/assets/chat-3WoUGCTd.js.gz +0 -0
  313. package/payload/server/public/assets/chevron-left-BE16BJnw.js +0 -1
  314. package/payload/server/public/assets/chevron-left-BE16BJnw.js.br +0 -0
  315. package/payload/server/public/assets/chevron-right-Bu2VKpeU.js +0 -1
  316. package/payload/server/public/assets/chevron-right-Bu2VKpeU.js.br +0 -0
  317. package/payload/server/public/assets/clock-C4Nu2aRV.js +0 -1
  318. package/payload/server/public/assets/clock-C4Nu2aRV.js.br +0 -0
  319. package/payload/server/public/assets/copy-3kj9Oaoc.js.br +0 -0
  320. package/payload/server/public/assets/copy-3kj9Oaoc.js.gz +0 -0
  321. package/payload/server/public/assets/data-C-x5EHyi.js +0 -1
  322. package/payload/server/public/assets/data-C-x5EHyi.js.br +0 -1
  323. package/payload/server/public/assets/data-C-x5EHyi.js.gz +0 -0
  324. package/payload/server/public/assets/file-text-CBaewT76.js.br +0 -0
  325. package/payload/server/public/assets/file-text-CBaewT76.js.gz +0 -0
  326. package/payload/server/public/assets/graph-B8-e2_Z-.js.br +0 -0
  327. package/payload/server/public/assets/graph-B8-e2_Z-.js.gz +0 -0
  328. package/payload/server/public/assets/graph-labels-Bsc23eZU.js.br +0 -0
  329. package/payload/server/public/assets/graph-labels-Bsc23eZU.js.gz +0 -0
  330. package/payload/server/public/assets/operator-Cve0-qfO.js +0 -1
  331. package/payload/server/public/assets/operator-Cve0-qfO.js.br +0 -0
  332. package/payload/server/public/assets/operator-Cve0-qfO.js.gz +0 -0
  333. package/payload/server/public/assets/page-BgVMs6Vf.js +0 -1
  334. package/payload/server/public/assets/page-BgVMs6Vf.js.br +0 -0
  335. package/payload/server/public/assets/page-BgVMs6Vf.js.gz +0 -0
  336. package/payload/server/public/assets/page-fABub-w8.js +0 -32
  337. package/payload/server/public/assets/page-fABub-w8.js.br +0 -0
  338. package/payload/server/public/assets/page-fABub-w8.js.gz +0 -0
  339. package/payload/server/public/assets/play-B6zXB9K7.js +0 -1
  340. package/payload/server/public/assets/play-B6zXB9K7.js.br +0 -0
  341. package/payload/server/public/assets/play-B6zXB9K7.js.gz +0 -0
  342. package/payload/server/public/assets/public--R2DbdWs.js +0 -1
  343. package/payload/server/public/assets/public--R2DbdWs.js.br +0 -0
  344. package/payload/server/public/assets/public--R2DbdWs.js.gz +0 -0
  345. package/payload/server/public/assets/rotate-ccw-FZW7c8p8.js.br +0 -0
  346. package/payload/server/public/assets/rotate-ccw-FZW7c8p8.js.gz +0 -0
  347. package/payload/server/public/assets/routines-BpZs2SaT.js +0 -2
  348. package/payload/server/public/assets/routines-BpZs2SaT.js.br +0 -0
  349. package/payload/server/public/assets/routines-BpZs2SaT.js.gz +0 -0
  350. package/payload/server/public/assets/skills-DF7uyEEz.js +0 -1
  351. package/payload/server/public/assets/skills-DF7uyEEz.js.br +0 -0
  352. package/payload/server/public/assets/skills-DF7uyEEz.js.gz +0 -0
  353. package/payload/server/public/assets/tasks-BfJJmoWO.js +0 -3
  354. package/payload/server/public/assets/tasks-BfJJmoWO.js.br +0 -0
  355. package/payload/server/public/assets/tasks-BfJJmoWO.js.gz +0 -0
  356. package/payload/server/public/assets/triangle-alert-CR-jRJdI.js.br +0 -0
  357. package/payload/server/public/assets/triangle-alert-CR-jRJdI.js.gz +0 -0
  358. package/payload/server/public/assets/useCopyFeedback-IOuPUAHY.js +0 -1
  359. package/payload/server/public/assets/useCopyFeedback-IOuPUAHY.js.br +0 -0
  360. package/payload/server/public/assets/useCopyFeedback-IOuPUAHY.js.gz +0 -0
  361. package/payload/server/public/assets/useMediaQuery-CA6dR5iz.js +0 -14
  362. package/payload/server/public/assets/useMediaQuery-CA6dR5iz.js.br +0 -0
  363. package/payload/server/public/assets/useMediaQuery-CA6dR5iz.js.gz +0 -0
  364. package/payload/server/public/assets/useMediaQuery-DpwgV1Da.css +0 -1
  365. package/payload/server/public/assets/useMediaQuery-DpwgV1Da.css.br +0 -0
  366. package/payload/server/public/assets/useMediaQuery-DpwgV1Da.css.gz +0 -0
  367. package/payload/server/public/assets/useVoiceRecorder-DGhsN7nV.js +0 -2
  368. package/payload/server/public/assets/useVoiceRecorder-DGhsN7nV.js.br +0 -0
  369. package/payload/server/public/assets/useVoiceRecorder-DGhsN7nV.js.gz +0 -0
  370. package/payload/server/public/assets/wrench-CpCOYUBc.js.br +0 -0
  371. package/payload/server/public/assets/wrench-CpCOYUBc.js.gz +0 -0
@@ -0,0 +1,173 @@
1
+ #!/usr/bin/env bash
2
+ # Regression test for public-tool-surface.sh (Task 2339).
3
+ #
4
+ # The hook records the tool surface a public spawn REALISES: one line per tool
5
+ # call classified against that spawn's own --allowed-tools set, and a per-turn
6
+ # census. It is observability only and must never block, so every case here
7
+ # asserts exit 0 as well as the emitted line.
8
+
9
+ set -u
10
+
11
+ HOOK="$(cd "$(dirname "$0")/.." && pwd)/public-tool-surface.sh"
12
+ if [[ ! -x "$HOOK" ]]; then
13
+ echo "FAIL: $HOOK not executable" >&2
14
+ exit 1
15
+ fi
16
+
17
+ PASS=0
18
+ FAIL=0
19
+ ok() { echo "PASS: $1"; PASS=$((PASS+1)); }
20
+ bad() { echo "FAIL: $1" >&2; FAIL=$((FAIL+1)); }
21
+
22
+ SID=aa11bb22-cccc-dddd-eeee-ffff00001111
23
+ ALLOW='mcp__whatsapp-channel__reply'
24
+
25
+ # newlog -> prints a fresh LOG_DIR
26
+ newlog() { local d; d=$(mktemp -d); printf '%s' "$d"; }
27
+
28
+ # fire <logdir> <env-allowlist|-> <stdin-json> -> prints exit code; log at $1/server.log
29
+ fire() {
30
+ local d="$1" allow="$2" input="$3" rc
31
+ if [[ "$allow" == "-" ]]; then
32
+ printf '%s' "$input" | env -u MAXY_PUBLIC_ALLOWED_TOOLS LOG_DIR="$d" bash "$HOOK" >/dev/null 2>&1
33
+ else
34
+ printf '%s' "$input" | env MAXY_PUBLIC_ALLOWED_TOOLS="$allow" LOG_DIR="$d" bash "$HOOK" >/dev/null 2>&1
35
+ fi
36
+ rc=$?
37
+ printf '%s' "$rc"
38
+ }
39
+
40
+ pre() { printf '{"hook_event_name":"PreToolUse","tool_name":"%s","session_id":"%s"}' "$1" "$SID"; }
41
+ stop() { printf '{"hook_event_name":"Stop","session_id":"%s"}' "$SID"; }
42
+ ups() { printf '{"hook_event_name":"UserPromptSubmit","session_id":"%s","prompt":"hi"}' "$SID"; }
43
+
44
+ # --- 1. allowed tool -------------------------------------------------------
45
+ D=$(newlog)
46
+ RC=$(fire "$D" "$ALLOW" "$(pre "$ALLOW")")
47
+ if [[ "$RC" == "0" ]]; then ok "allowed tool exits 0"; else bad "allowed tool exit $RC"; fi
48
+ if /usr/bin/grep -qF "[public-surface] op=tool-realised sessionId=aa11bb22 tool=$ALLOW allowed=y" "$D/server.log"; then
49
+ ok "allowed tool logs allowed=y"
50
+ else
51
+ bad "allowed=y line absent"
52
+ fi
53
+
54
+ # --- 2. disallowed native tool ---------------------------------------------
55
+ D=$(newlog)
56
+ RC=$(fire "$D" "$ALLOW" "$(pre Bash)")
57
+ if [[ "$RC" == "0" ]]; then ok "disallowed tool exits 0"; else bad "disallowed tool exit $RC"; fi
58
+ if /usr/bin/grep -qF "[public-surface] op=tool-realised sessionId=aa11bb22 tool=Bash allowed=n" "$D/server.log"; then
59
+ ok "disallowed tool logs allowed=n"
60
+ else
61
+ bad "allowed=n line absent"
62
+ fi
63
+
64
+ # --- 3. no env stamp -> silent ---------------------------------------------
65
+ D=$(newlog)
66
+ RC=$(fire "$D" "-" "$(pre Bash)")
67
+ if [[ "$RC" == "0" ]]; then ok "unstamped session exits 0"; else bad "unstamped exit $RC"; fi
68
+ if [[ ! -f "$D/server.log" ]]; then ok "unstamped session writes nothing"; else bad "unstamped session wrote a log"; fi
69
+
70
+ # --- 4. census with zero calls ---------------------------------------------
71
+ D=$(newlog)
72
+ RC=$(fire "$D" "$ALLOW" "$(stop)")
73
+ if [[ "$RC" == "0" ]]; then ok "zero-call census exits 0"; else bad "zero-call census exit $RC"; fi
74
+ if /usr/bin/grep -qF "[public-surface] op=realised-census sessionId=aa11bb22 calls=0 disallowed=0" "$D/server.log"; then
75
+ ok "census is emitted at zero"
76
+ else
77
+ bad "zero census absent"
78
+ fi
79
+
80
+ # --- 5. census after one allowed and one disallowed call -------------------
81
+ D=$(newlog)
82
+ fire "$D" "$ALLOW" "$(pre "$ALLOW")" >/dev/null
83
+ fire "$D" "$ALLOW" "$(pre Bash)" >/dev/null
84
+ fire "$D" "$ALLOW" "$(stop)" >/dev/null
85
+ if /usr/bin/grep -qF "[public-surface] op=realised-census sessionId=aa11bb22 calls=2 disallowed=1" "$D/server.log"; then
86
+ ok "census counts calls and disallowed"
87
+ else
88
+ bad "census counts wrong"
89
+ fi
90
+ if [[ -z "$(ls -A "$D/public-surface" 2>/dev/null)" ]]; then
91
+ ok "census removes the tally"
92
+ else
93
+ bad "tally survived the census"
94
+ fi
95
+
96
+ # --- 6. a second turn starts from zero -------------------------------------
97
+ D=$(newlog)
98
+ fire "$D" "$ALLOW" "$(pre Bash)" >/dev/null
99
+ fire "$D" "$ALLOW" "$(stop)" >/dev/null
100
+ fire "$D" "$ALLOW" "$(stop)" >/dev/null
101
+ if [[ "$(/usr/bin/grep -cF 'op=realised-census sessionId=aa11bb22 calls=0 disallowed=0' "$D/server.log")" == "1" ]]; then
102
+ ok "the turn after a census starts from zero"
103
+ else
104
+ bad "second census did not reset"
105
+ fi
106
+
107
+ # --- 7. unparseable stdin --------------------------------------------------
108
+ D=$(newlog)
109
+ RC=$(fire "$D" "$ALLOW" 'not json at all')
110
+ if [[ "$RC" == "0" ]]; then ok "unparseable stdin exits 0"; else bad "unparseable stdin exit $RC"; fi
111
+ if [[ ! -f "$D/server.log" ]]; then ok "unparseable stdin writes nothing"; else bad "unparseable stdin wrote a log"; fi
112
+
113
+ # --- 8. a tool name containing a glob is compared literally -----------------
114
+ D=$(newlog)
115
+ RC=$(fire "$D" "$ALLOW" "$(pre '*')")
116
+ if /usr/bin/grep -qF "tool=* allowed=n" "$D/server.log"; then
117
+ ok "a glob tool name is compared literally, not expanded"
118
+ else
119
+ bad "glob tool name mishandled"
120
+ fi
121
+
122
+ # --- 9. multi-entry allowlist ----------------------------------------------
123
+ D=$(newlog)
124
+ fire "$D" "Read,$ALLOW" "$(pre Read)" >/dev/null
125
+ if /usr/bin/grep -qF "tool=Read allowed=y" "$D/server.log"; then
126
+ ok "membership matches any entry of a multi-entry allowlist"
127
+ else
128
+ bad "multi-entry allowlist mismatch"
129
+ fi
130
+
131
+ # --- 10. absent session_id still emits -------------------------------------
132
+ D=$(newlog)
133
+ fire "$D" "$ALLOW" '{"hook_event_name":"PreToolUse","tool_name":"Bash"}' >/dev/null
134
+ if /usr/bin/grep -qF "sessionId=none tool=Bash allowed=n" "$D/server.log"; then
135
+ ok "a call with no session_id is still recorded"
136
+ else
137
+ bad "no-session call was silent"
138
+ fi
139
+
140
+ # --- 11. a killed turn leaves no residue in the next turn's census ---------
141
+ # The stuck-turn recycler kills a wedged PTY and resumes the SAME sessionId, so
142
+ # the killed turn's Stop never fires. Without a turn-start reset its tally is
143
+ # inherited and the next census over-counts, which is exactly the number the
144
+ # task's verification asserts against that turn's tool_use count.
145
+ D=$(newlog)
146
+ for t in Bash Read ToolSearch; do fire "$D" "$ALLOW" "$(pre "$t")" >/dev/null; done
147
+ # no Stop: the turn was killed here.
148
+ fire "$D" "$ALLOW" "$(ups)" >/dev/null
149
+ fire "$D" "$ALLOW" "$(pre "$ALLOW")" >/dev/null
150
+ fire "$D" "$ALLOW" "$(stop)" >/dev/null
151
+ if /usr/bin/grep -qF "op=realised-census sessionId=aa11bb22 calls=1 disallowed=0" "$D/server.log"; then
152
+ ok "a killed turn's tally does not leak into the next turn's census"
153
+ else
154
+ bad "census inherited a killed turn's tally"
155
+ fi
156
+
157
+ # --- 12. the turn-start reset is silent and never blocks --------------------
158
+ D=$(newlog)
159
+ RC=$(fire "$D" "$ALLOW" "$(ups)")
160
+ if [[ "$RC" == "0" ]]; then ok "turn-start reset exits 0"; else bad "turn-start reset exit $RC"; fi
161
+ if [[ ! -f "$D/server.log" ]]; then ok "turn-start reset writes no log line"; else bad "turn-start reset wrote a log line"; fi
162
+
163
+ echo "----"
164
+ echo "PASS=$PASS FAIL=$FAIL"
165
+ # The count is asserted, not just the failures: a case that stops running leaves
166
+ # a green suite that tested less than it claims, and .husky/pre-commit reads only
167
+ # the exit status.
168
+ EXPECTED=19
169
+ if [[ $((PASS+FAIL)) -ne "$EXPECTED" ]]; then
170
+ echo "FAIL: expected $EXPECTED cases, ran $((PASS+FAIL))" >&2
171
+ exit 1
172
+ fi
173
+ [[ "$FAIL" -eq 0 ]]
@@ -0,0 +1,123 @@
1
+ #!/usr/bin/env bash
2
+ # public-tool-surface.sh — Task 2339. Records the tool surface a public spawn
3
+ # REALISES: one line per tool call, plus a per-turn census.
4
+ #
5
+ # `tool-allowlist` (rc-public-lockdown.ts, pty-spawner.ts) records the surface a
6
+ # spawn was GIVEN. `[public-surface] op=audit` (public-surface-audit.ts)
7
+ # reconciles MCP server names from spawn-tee filenames, so it is structurally
8
+ # blind to Read, Bash, Skill and ToolSearch: those spawn no MCP child and write
9
+ # no tee file. On 2026-08-01 five such tools ran in a session spawned with a
10
+ # one-tool allowlist and produced no log line at all.
11
+ #
12
+ # Registered on the matcher-less PreToolUse entry (which matches every tool,
13
+ # native and MCP alike) and on the Stop entry. Fires only when
14
+ # MAXY_PUBLIC_ALLOWED_TOOLS is set, which both spawn paths stamp for
15
+ # role='public' only.
16
+ #
17
+ # Observability only: never blocks, exits 0 on every path, and writes to
18
+ # server.log alone — a public visitor's PTY gains no new output.
19
+
20
+ set -uo pipefail
21
+
22
+ # No stamp means this is not a public spawn. Silent, and the common case.
23
+ [ -n "${MAXY_PUBLIC_ALLOWED_TOOLS:-}" ] || exit 0
24
+
25
+ # Log destination. LOG_DIR is stamped on the rc-spawn path and is brand-correct;
26
+ # MAXY_HOOK_SERVER_LOG is the override post-tool-use-agent.sh already honours;
27
+ # the literal is that hook's own default.
28
+ if [ -n "${LOG_DIR:-}" ]; then
29
+ : "${MAXY_HOOK_SERVER_LOG:=$LOG_DIR/server.log}"
30
+ fi
31
+ : "${MAXY_HOOK_SERVER_LOG:=$HOME/.maxy-code/logs/server.log}"
32
+ TALLY_DIR="$(dirname "$MAXY_HOOK_SERVER_LOG")/public-surface"
33
+
34
+ emit() {
35
+ mkdir -p "$(dirname "$MAXY_HOOK_SERVER_LOG")" 2>/dev/null || true
36
+ printf '%s\n' "$1" >>"$MAXY_HOOK_SERVER_LOG" 2>/dev/null || true
37
+ }
38
+
39
+ # No stdin (tty) — no call to classify. Fail-open.
40
+ [ -t 0 ] && exit 0
41
+ INPUT=$(cat)
42
+ [ -n "$INPUT" ] || exit 0
43
+
44
+ PARSED=$(printf '%s' "$INPUT" | python3 -c '
45
+ import sys, json
46
+ try:
47
+ d = json.load(sys.stdin)
48
+ except Exception:
49
+ sys.exit(1)
50
+ if not isinstance(d, dict):
51
+ sys.exit(1)
52
+ def s(k):
53
+ v = d.get(k)
54
+ return v if isinstance(v, str) else ""
55
+ print(s("hook_event_name"))
56
+ print(s("tool_name"))
57
+ print(s("session_id"))
58
+ ' 2>/dev/null) || exit 0
59
+
60
+ { IFS= read -r EVENT; IFS= read -r TOOL; IFS= read -r SID; } <<EOF
61
+ $PARSED
62
+ EOF
63
+ EVENT="${EVENT:-}"
64
+ TOOL="${TOOL:-}"
65
+ SID="${SID:-}"
66
+
67
+ # The 8-character form used by every other session-scoped line. An envelope with
68
+ # no session_id still emits: a public session must never be silent, and `none`
69
+ # is visibly not an id.
70
+ SID8="${SID:0:8}"
71
+ [ -n "$SID8" ] || SID8=none
72
+ # Tally filename. Sanitised the way the rc-spawn channel-config writers sanitise
73
+ # theirs, so no session id can escape the directory.
74
+ KEY=$(printf '%s' "${SID:-none}" | tr -c 'A-Za-z0-9_-' '_')
75
+
76
+ if [ "$EVENT" = "UserPromptSubmit" ]; then
77
+ # Turn start. Drop any tally left by a turn that never reached Stop — the
78
+ # stuck-turn recycler kills a wedged PTY and resumes the SAME sessionId, so
79
+ # that turn's Stop never fires and its tally would otherwise be counted into
80
+ # the next turn's census. Silent: the reset is not itself an observation.
81
+ rm -f "$TALLY_DIR/$KEY" 2>/dev/null || true
82
+ exit 0
83
+ fi
84
+
85
+ if [ "$EVENT" = "PreToolUse" ]; then
86
+ [ -n "$TOOL" ] || exit 0
87
+ ALLOWED=n
88
+ # -f so a tool name or allowlist entry containing a glob character is compared
89
+ # literally rather than expanded against the cwd.
90
+ set -f
91
+ OLDIFS=$IFS
92
+ IFS=','
93
+ for t in $MAXY_PUBLIC_ALLOWED_TOOLS; do
94
+ if [ "$t" = "$TOOL" ]; then ALLOWED=y; break; fi
95
+ done
96
+ IFS=$OLDIFS
97
+ set +f
98
+ emit "[public-surface] op=tool-realised sessionId=$SID8 tool=$TOOL allowed=$ALLOWED"
99
+ # Append one line per call rather than read-modify-writing a counter: an
100
+ # append needs no mutex, a counter would need the one hook-emit.sh carries.
101
+ mkdir -p "$TALLY_DIR" 2>/dev/null || true
102
+ printf '%s\n' "$ALLOWED" >>"$TALLY_DIR/$KEY" 2>/dev/null || true
103
+ exit 0
104
+ fi
105
+
106
+ if [ "$EVENT" = "Stop" ]; then
107
+ CALLS=0
108
+ DIS=0
109
+ if [ -f "$TALLY_DIR/$KEY" ]; then
110
+ while IFS= read -r v || [ -n "$v" ]; do
111
+ [ -n "$v" ] || continue
112
+ CALLS=$((CALLS+1))
113
+ if [ "$v" = "n" ]; then DIS=$((DIS+1)); fi
114
+ done <"$TALLY_DIR/$KEY"
115
+ rm -f "$TALLY_DIR/$KEY" 2>/dev/null || true
116
+ fi
117
+ # Emitted including zero, so a public session with no disallowed call is
118
+ # distinguishable from one this hook never saw.
119
+ emit "[public-surface] op=realised-census sessionId=$SID8 calls=$CALLS disallowed=$DIS"
120
+ exit 0
121
+ fi
122
+
123
+ exit 0
@@ -1 +1 @@
1
- {"version":3,"file":"agent-write.d.ts","sourceRoot":"","sources":["../../src/tools/agent-write.ts"],"names":[],"mappings":"AAiBA,MAAM,MAAM,iBAAiB,GACzB,aAAa,GACb,gBAAgB,GAChB,iBAAiB,GACjB,QAAQ,GACR,WAAW,CAAC;AAEhB,MAAM,MAAM,gBAAgB,GACxB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,EAAE,CAAA;CAAE,GAClD;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,iBAAiB,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAE7D,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IACjC,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IACjC,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AA8BD,wBAAgB,WAAW,CAAC,IAAI,EAAE,eAAe,GAAG,gBAAgB,CAsDnE;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,eAAe,GAAG,gBAAgB,CA4CnE;AAED,MAAM,WAAW,WAAW;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iFAAiF;IACjF,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CAC1B;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,uBAAuB,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAmB/G"}
1
+ {"version":3,"file":"agent-write.d.ts","sourceRoot":"","sources":["../../src/tools/agent-write.ts"],"names":[],"mappings":"AAiBA,MAAM,MAAM,iBAAiB,GACzB,aAAa,GACb,gBAAgB,GAChB,iBAAiB,GACjB,QAAQ,GACR,WAAW,CAAC;AAEhB,MAAM,MAAM,gBAAgB,GACxB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,EAAE,CAAA;CAAE,GAClD;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,iBAAiB,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAE7D,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IACjC,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IACjC,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AA8BD,wBAAgB,WAAW,CAAC,IAAI,EAAE,eAAe,GAAG,gBAAgB,CAkEnE;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,eAAe,GAAG,gBAAgB,CA4CnE;AAED,MAAM,WAAW,WAAW;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iFAAiF;IACjF,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CAC1B;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,uBAAuB,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAmB/G"}
@@ -62,6 +62,14 @@ export function createAgent(args) {
62
62
  writeFileSync(resolve(dir, "SOUL.md"), args.soul);
63
63
  writeFileSync(resolve(dir, "KNOWLEDGE.md"), args.knowledge);
64
64
  writeFileSync(resolve(dir, "config.json"), `${JSON.stringify(config, null, 2)}\n`);
65
+ // Task 2342 — the agent's own turn instruction, created empty. Its whole
66
+ // body becomes the `## Instruction` block of every channel turn this agent
67
+ // answers. Empty resolves 'absent' at the resolver and refuses the turn,
68
+ // which is the correct closed state for an agent whose per-turn behaviour
69
+ // nobody has written yet; before 2342 such a turn silently borrowed
70
+ // agents/admin/INSTRUCTION.md. Written inside this try with the others so
71
+ // the rollback below still leaves no half-made agent.
72
+ writeFileSync(resolve(dir, "INSTRUCTION.md"), "");
65
73
  }
66
74
  catch (err) {
67
75
  // The directory did not exist before this call, so removing it restores the
@@ -70,7 +78,11 @@ export function createAgent(args) {
70
78
  rmSync(dir, { recursive: true, force: true });
71
79
  throw err;
72
80
  }
73
- return { ok: true, slug: args.slug, filesWritten: ["IDENTITY.md", "SOUL.md", "KNOWLEDGE.md", "config.json"] };
81
+ return {
82
+ ok: true,
83
+ slug: args.slug,
84
+ filesWritten: ["IDENTITY.md", "SOUL.md", "KNOWLEDGE.md", "config.json", "INSTRUCTION.md"],
85
+ };
74
86
  }
75
87
  export function updateAgent(args) {
76
88
  const verdict = checkAgentSlug(args.slug);
@@ -1 +1 @@
1
- {"version":3,"file":"agent-write.js","sourceRoot":"","sources":["../../src/tools/agent-write.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"agent-write.js","sourceRoot":"","sources":["../../src/tools/agent-write.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ ---
2
+ name: channel-instruction
3
+ description: "Set up or change what this account's agent does with an incoming channel message. Triggers when the owner says 'set up what my agent does with incoming messages', 'change how you handle WhatsApp messages', 'write my channel instruction', 'my agent replied to a customer and it shouldn't have', or asks why an incoming message got no answer."
4
+ ---
5
+
6
+ # Channel instruction
7
+
8
+ Invoked by the admin agent directly.
9
+
10
+ A message arriving on a channel wakes a session and hands it a turn in two parts: a `## Context` block holding the message, and an `## Instruction` block holding this account's standing rules for what to do with it. This skill is about the file that supplies the second block.
11
+
12
+ ## The file
13
+
14
+ `$ACCOUNT_DIR/agents/admin/INSTRUCTION.md`
15
+
16
+ Its whole body becomes the `## Instruction` block, verbatim. The platform wraps it in nothing and adds no wording of its own, so that file is the entire instruction the agent gets on every channel turn. All three channels read it: WhatsApp, the admin webchat, and Telegram.
17
+
18
+ The install creates the file empty. What goes in it is the account owner's, not the platform's.
19
+
20
+ ## An empty file refuses every message
21
+
22
+ A file that is missing, unreadable, or holds only whitespace resolves to absent, and an absent instruction refuses the turn: no session wakes and no reply goes out. The sender gets silence.
23
+
24
+ Nothing warns the owner in advance. The only trace is two lines in `server.log`, written at the moment a message was dropped:
25
+
26
+ - `op=instruction-source accountId=<id> source=absent bytes=0`
27
+ - `op=inbound … delivery=refused` for the same message
28
+
29
+ So on an account whose channel is connected and whose file is empty, writing this file is the fix for "nobody is getting an answer". If the owner reports that, check this file before anything else.
30
+
31
+ ## Writing it
32
+
33
+ Read the file first and tell the owner what is in it. Then find out what they want and write it.
34
+
35
+ What belongs in it is the account's standing rules for handling an incoming message: who the agent may answer on its own and who it must not, what has to go to a person, what it must never say, how it should sound, and what it must always do before the turn ends.
36
+
37
+ Two rules on how you write it:
38
+
39
+ - Write only what the owner has told you. A rule they did not ask for is someone else's wording in their file, which is exactly what this file exists to keep out.
40
+ - Never carry rules over from another account or from another owner's file.
41
+
42
+ An edit takes effect on the next incoming message. No restart, no upgrade, no publish. So a change can be checked by sending one message to the account's channel and reading the reply.
43
+
44
+ ## What this file is not
45
+
46
+ It is not the agent's identity or its personality. Those are `IDENTITY.md` and `SOUL.md` in the same directory, and they apply to every session, not just a channel turn. Editing this file changes what happens to incoming messages and nothing else.
@@ -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:4140a189871ed59fff6f5edd3c48c8836a40f6999c584a611164533d12021cd2
4
+ content-hash: sha256:f14bd26752dbb6d11c821c26753ca43a5bd526f23e370067111fac8a4a6d4579
5
5
  brand: maxy-code
6
6
  product-name: Maxy
7
7
  ---
@@ -250,6 +250,7 @@ Inside the scope, `sh -c 'trap "" HUP; exec "$@"' sh <claudeBin> <args...>` keep
250
250
  | Step | Line shape |
251
251
  |------|-----------|
252
252
  | 1 | `[rc-spawn] op=request unitToken=<t> sessionId=<8|new> name=<…|none> mode=<resume|fresh> jsonl=<path|none>` |
253
+ | 1b | `[rc-spawn] op=role-resolution sessionId=<8> source=<body\|sidecar\|unresolved> outcome=<ok\|missing\|parse-failed>` — channel-bound spawns only. `source` is where the session's role came from; `outcome` is the `readSidecar` verdict behind it, which separates a deleted classification sidecar from a corrupted one. `source=unresolved` means neither the body nor the sidecar produced a role, so the spawn took the public lockdown rather than running unrestricted. The `tool-allowlist` line cannot make that distinction: it renders `role=none` for an unresolved role and for a legitimately roleless spawn alike. |
253
254
  | 2 | `[rc-spawn] op=argv unitToken=<t> cwd=<dir> argv=<json>` (inner claude argv; the `systemd-run --scope` wrap is composed by the spawnPty adapter) |
254
255
  | 3 | `[rc-spawn] op=pty-spawned unitToken=<t> pid=<pid> openFds=<n>` (fd baseline) |
255
256
  | 4 | `[rc-spawn] op=child-output unitToken=<t> pid=<pid> head=<json>` (first ≤1 KB or 500 ms idle — claude's own words) |
@@ -1661,6 +1662,20 @@ Changes are per-account and take effect immediately.
1661
1662
 
1662
1663
  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
1664
 
1665
+ ## The Shared Folder
1666
+
1667
+ Every install has one shared folder that all accounts can see. The house account writes it; every other account reads it.
1668
+
1669
+ It exists so the house can publish something once and have every sub-account use it. Brand tokens are the first use: put the house palette, typography and report template in the shared folder, and a sub-account can produce a report in the house format without being sent a copy.
1670
+
1671
+ Ask Maxy to "put this in the shared folder" from the house account, or "read the brand tokens from the shared folder" from any account.
1672
+
1673
+ A sub-account that tries to write there is refused, and says the folder is read-only. That refusal is the correct behaviour, not a fault. If a sub-account needs something changed in the shared folder, the change is made from the house account.
1674
+
1675
+ If the install's account records are in an odd state — no house account, or more than one — the folder becomes read-only for everyone until that is resolved. This is deliberate: with no single house account there is no one whose writes should be trusted.
1676
+
1677
+ One limit worth knowing. The read-only rule covers Maxy's file tools and the Data page. It does not cover shell commands, which an account's own operator can still run against the folder on their own install. The rule is there to stop accounts from changing shared material by accident, not to defend against the person who owns the install.
1678
+
1664
1679
  ---
1665
1680
  # What Wakes a Session
1666
1681
  Source: https://docs.getmaxy.com/channel-wake-and-prompt.md
@@ -5557,6 +5572,8 @@ The final step in the retrieval pipeline is injecting retrieved content into the
5557
5572
 
5558
5573
  The manager exposes three named spawn routes: `/rc-spawn` (a live `claude --remote-control` PTY — the operator sidebar, the channel admin, and the one-shot admin jobs), `/public-spawn` (the renamed `/spawn` — `spawnClaudeSession`, the zero-tool public surface), and the `rc-daemon` it drives. No route named `/spawn` remains; a manager boot line `[spawn-routes] live=[rc-spawn,public-spawn]` asserts this.
5559
5574
 
5575
+ **A public spawn may not name a specialist.** The zero-tool surface is built from four levers, and two of them — the `--allowed-tools` push and the resolved permission mode — branch on whether the spawn is a specialist rather than on whether it is public, so a specialist named on a public spawn would skip the allowlist entirely and resolve the caller's mode instead of the fail-closed `dontAsk`. Only the per-spawn `permissions.deny` and `--strict-mcp-config` bind on the public role alone. Neither production issuer sends the pairing: the channel bridge is the only caller whose role can be public and it carries no specialist field, while the cookie-auth session wrapper is admin-only. So the pairing is refused rather than reshaped — `/public-spawn` answers `400 specialist-not-permitted-on-public`, and `spawnClaudeSession` refuses it again with `reason=public-specialist-refused` at the single chokepoint every spawn route passes through. Refusing rather than narrowing the levers is deliberate: a narrowed lever would leave a specialist running silently on a one-tool surface. Every spawn that reaches `spawnClaudeSession` — which is every `/public-spawn`, that route being its only caller — logs the three deciding inputs together as `[spawn-lockdown] role=<role> specialist=<name|none> permissionMode=<mode>`. A refusal at either layer logs `op=public-specialist-refused` instead, told apart by `site=`.
5576
+
5560
5577
  The channel PTY-bridge (`ensureEntry`) routes each inbound by role: an **admin** WhatsApp/Telegram inbound spawns on `/rc-spawn` (keyed by a deterministic per-sender sessionId so the thread resumes across restarts) and drives every turn via `/<id>/input`; a **non-admin** inbound spawns on `/public-spawn`. Each dispatch logs `[<channel>-adaptor] route role=<role> target=<rc-spawn|public-spawn> senderId=…`. LinkedIn ingest and the public session-end review also run on `/rc-spawn`, carrying their prompt as `initialMessage` with `closeAfterTurn` so the PTY stops after one assistant turn.
5561
5578
 
5562
5579
  ### Public agent paths
@@ -9,6 +9,21 @@ 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-08-02 (0.1.544)
13
+
14
+ - Every channel, including Telegram, now takes its turn instruction from the account's own file rather than text fixed in the code, and a build check stops any of the three services hardcoding it again.
15
+ - Each public agent now has its own instruction file, created on install.
16
+ - A session whose role cannot be determined is now refused rather than allowed through, and a specialist can no longer be requested on a session serving someone outside your team.
17
+ - A frozen session serving someone outside your team is now restarted through the same restricted route it began on.
18
+
19
+ ## 2026-08-01 (0.1.543)
20
+
21
+ - There is now a shared folder every account can read and only the main account can write to, and an upload route that could reach out of an account into it has been closed.
22
+ - Every timestamp on screen now shows in the account's own timezone, with a build check that stops a new one slipping back to the browser's.
23
+ - A sub-account reading its WhatsApp now resolves its own conversations, and past messages that arrived on its connection have been filed to it.
24
+ - How the assistant is told to handle a WhatsApp turn is now set per account rather than fixed in the code, seeded on install.
25
+ - A chat session that freezes is now set aside and restarted rather than left stuck.
26
+
12
27
  ## 2026-08-01 (0.1.542)
13
28
 
14
29
  - A public agent's web chat now runs in the account that owns it, including its branding, rather than always the main account. A standing check reports the same agent name claimed by two accounts.
@@ -82,3 +82,17 @@ Changes are per-account and take effect immediately.
82
82
  ## Filesystem Access (SMB Share)
83
83
 
84
84
  Brand isolation extends to the device filesystem. Every {{productName}} install provisions an SMB share scoped to that brand's install folder, credentialled by the brand's install owner and the {{productName}} 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.
85
+
86
+ ## The Shared Folder
87
+
88
+ Every install has one shared folder that all accounts can see. The house account writes it; every other account reads it.
89
+
90
+ It exists so the house can publish something once and have every sub-account use it. Brand tokens are the first use: put the house palette, typography and report template in the shared folder, and a sub-account can produce a report in the house format without being sent a copy.
91
+
92
+ Ask {{productName}} to "put this in the shared folder" from the house account, or "read the brand tokens from the shared folder" from any account.
93
+
94
+ A sub-account that tries to write there is refused, and says the folder is read-only. That refusal is the correct behaviour, not a fault. If a sub-account needs something changed in the shared folder, the change is made from the house account.
95
+
96
+ If the install's account records are in an odd state — no house account, or more than one — the folder becomes read-only for everyone until that is resolved. This is deliberate: with no single house account there is no one whose writes should be trusted.
97
+
98
+ One limit worth knowing. The read-only rule covers {{productName}}'s file tools and the Data page. It does not cover shell commands, which an account's own operator can still run against the folder on their own install. The rule is there to stop accounts from changing shared material by accident, not to defend against the person who owns the install.
@@ -357,6 +357,8 @@ The final step in the retrieval pipeline is injecting retrieved content into the
357
357
 
358
358
  The manager exposes three named spawn routes: `/rc-spawn` (a live `claude --remote-control` PTY — the operator sidebar, the channel admin, and the one-shot admin jobs), `/public-spawn` (the renamed `/spawn` — `spawnClaudeSession`, the zero-tool public surface), and the `rc-daemon` it drives. No route named `/spawn` remains; a manager boot line `[spawn-routes] live=[rc-spawn,public-spawn]` asserts this.
359
359
 
360
+ **A public spawn may not name a specialist.** The zero-tool surface is built from four levers, and two of them — the `--allowed-tools` push and the resolved permission mode — branch on whether the spawn is a specialist rather than on whether it is public, so a specialist named on a public spawn would skip the allowlist entirely and resolve the caller's mode instead of the fail-closed `dontAsk`. Only the per-spawn `permissions.deny` and `--strict-mcp-config` bind on the public role alone. Neither production issuer sends the pairing: the channel bridge is the only caller whose role can be public and it carries no specialist field, while the cookie-auth session wrapper is admin-only. So the pairing is refused rather than reshaped — `/public-spawn` answers `400 specialist-not-permitted-on-public`, and `spawnClaudeSession` refuses it again with `reason=public-specialist-refused` at the single chokepoint every spawn route passes through. Refusing rather than narrowing the levers is deliberate: a narrowed lever would leave a specialist running silently on a one-tool surface. Every spawn that reaches `spawnClaudeSession` — which is every `/public-spawn`, that route being its only caller — logs the three deciding inputs together as `[spawn-lockdown] role=<role> specialist=<name|none> permissionMode=<mode>`. A refusal at either layer logs `op=public-specialist-refused` instead, told apart by `site=`.
361
+
360
362
  The channel PTY-bridge (`ensureEntry`) routes each inbound by role: an **admin** WhatsApp/Telegram inbound spawns on `/rc-spawn` (keyed by a deterministic per-sender sessionId so the thread resumes across restarts) and drives every turn via `/<id>/input`; a **non-admin** inbound spawns on `/public-spawn`. Each dispatch logs `[<channel>-adaptor] route role=<role> target=<rc-spawn|public-spawn> senderId=…`. LinkedIn ingest and the public session-end review also run on `/rc-spawn`, carrying their prompt as `initialMessage` with `closeAfterTurn` so the PTY stops after one assistant turn.
361
363
 
362
364
  ### Public agent paths
@@ -123,6 +123,7 @@ Inside the scope, `sh -c 'trap "" HUP; exec "$@"' sh <claudeBin> <args...>` keep
123
123
  | Step | Line shape |
124
124
  |------|-----------|
125
125
  | 1 | `[rc-spawn] op=request unitToken=<t> sessionId=<8|new> name=<…|none> mode=<resume|fresh> jsonl=<path|none>` |
126
+ | 1b | `[rc-spawn] op=role-resolution sessionId=<8> source=<body\|sidecar\|unresolved> outcome=<ok\|missing\|parse-failed>` — channel-bound spawns only. `source` is where the session's role came from; `outcome` is the `readSidecar` verdict behind it, which separates a deleted classification sidecar from a corrupted one. `source=unresolved` means neither the body nor the sidecar produced a role, so the spawn took the public lockdown rather than running unrestricted. The `tool-allowlist` line cannot make that distinction: it renders `role=none` for an unresolved role and for a legitimately roleless spawn alike. |
126
127
  | 2 | `[rc-spawn] op=argv unitToken=<t> cwd=<dir> argv=<json>` (inner claude argv; the `systemd-run --scope` wrap is composed by the spawnPty adapter) |
127
128
  | 3 | `[rc-spawn] op=pty-spawned unitToken=<t> pid=<pid> openFds=<n>` (fd baseline) |
128
129
  | 4 | `[rc-spawn] op=child-output unitToken=<t> pid=<pid> head=<json>` (first ≤1 KB or 500 ms idle — claude's own words) |
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "filesystem",
3
- "description": "Account-scoped file access. Read, write, edit, list, glob, and grep files under the session's own account directory; the house admin may reach any sub-account's files by naming targetAccountId, gated fail-closed and confined to that account's directory.",
3
+ "description": "Account-scoped file access. Read, write, edit, list, glob, and grep files under the session's own account directory; the house admin may reach any sub-account's files by naming targetAccountId, gated fail-closed and confined to that account's directory; every account may read the install-wide shared folder via shared:true, and only the house account may write it.",
4
4
  "version": "0.1.0",
5
5
  "author": {
6
6
  "name": "Rubytech LLC"
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: filesystem
3
- description: "Account-scoped file access. Read, write, edit, list, glob, and grep files under the session's own account directory; the house admin may reach any sub-account's files by naming targetAccountId, gated fail-closed and confined to that account's directory."
3
+ description: "Account-scoped file access. Read, write, edit, list, glob, and grep files under the session's own account directory; the house admin may reach any sub-account's files by naming targetAccountId, gated fail-closed and confined to that account's directory; every account may read the install-wide shared folder via shared:true, and only the house account may write it."
4
4
  tools:
5
5
  - name: file-read
6
6
  publicAllowlist: false
@@ -54,6 +54,16 @@ Omit `targetAccountId`. Every tool takes a `path` relative to your account direc
54
54
 
55
55
  Pass `targetAccountId` to operate on a sub-account's directory. This is honoured only for a house-scoped admin session. A sub-account, specialist, or public session that passes `targetAccountId` is refused with `cross-account-denied`; an account id that is not provisioned on disk is refused with `cross-account-target-not-provisioned`. The validity check re-scans the accounts dir on a miss, so a sub-account created at runtime this session resolves without a service restart (a stale boot-time cache no longer masks it). Use this to inspect or repair a client account's files from the house session without switching accounts.
56
56
 
57
+ ## Shared folder
58
+
59
+ Pass `shared: true` to operate on the install-wide shared folder at `data/shared/` instead of an account directory. `path` is then relative to the shared root.
60
+
61
+ Every account reads it: `file-read`, `file-list`, `file-glob` and `file-grep` are open to any session. Only the house account writes it: `file-write` and `file-edit` from any other account are refused with `shared-folder-read-only`. House-ness here is the account, not the session role, so a house specialist writes too. Under account-census drift (no house, or more than one) no account may write.
62
+
63
+ `shared: true` together with `targetAccountId` is refused with `shared-and-target-exclusive` — `targetAccountId` selects an account root, and the shared folder is not an account. An install whose shared folder is missing refuses every shared call with `shared-folder-absent`; the installer creates the folder, and no tool call creates it on demand.
64
+
65
+ Containment is identical to the account case: a path that escapes the shared root, including through a symlink into an account directory, is rejected before any filesystem operation.
66
+
57
67
  ## Boundaries
58
68
 
59
69
  Every path is confined to the resolved account directory. A path that escapes it — `../`, an absolute path outside the account root, or a symlink pointing out — is rejected before any filesystem operation. Reads and greps skip files over 5 MB; grep skips binary files.