@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.
- package/dist/__tests__/public-instruction-seed.test.js +102 -0
- package/dist/index.js +47 -0
- package/dist/public-instruction-seed.js +70 -0
- package/package.json +1 -1
- package/payload/platform/lib/shared-folder/dist/index.d.ts +47 -0
- package/payload/platform/lib/shared-folder/dist/index.d.ts.map +1 -0
- package/payload/platform/lib/shared-folder/dist/index.js +93 -0
- package/payload/platform/lib/shared-folder/dist/index.js.map +1 -0
- package/payload/platform/lib/shared-folder/src/index.ts +92 -0
- package/payload/platform/lib/shared-folder/tsconfig.json +5 -0
- package/payload/platform/package.json +2 -2
- package/payload/platform/plugins/admin/PLUGIN.md +2 -0
- package/payload/platform/plugins/admin/hooks/__tests__/public-tool-surface.test.sh +173 -0
- package/payload/platform/plugins/admin/hooks/public-tool-surface.sh +123 -0
- package/payload/platform/plugins/admin/mcp/dist/tools/agent-write.d.ts.map +1 -1
- package/payload/platform/plugins/admin/mcp/dist/tools/agent-write.js +13 -1
- package/payload/platform/plugins/admin/mcp/dist/tools/agent-write.js.map +1 -1
- package/payload/platform/plugins/admin/skills/channel-instruction/SKILL.md +46 -0
- package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +18 -1
- package/payload/platform/plugins/admin/skills/whats-new/SKILL.md +15 -0
- package/payload/platform/plugins/docs/references/access-control.md +14 -0
- package/payload/platform/plugins/docs/references/internals.md +2 -0
- package/payload/platform/plugins/docs/references/platform.md +1 -0
- package/payload/platform/plugins/filesystem/.claude-plugin/plugin.json +1 -1
- package/payload/platform/plugins/filesystem/PLUGIN.md +11 -1
- package/payload/platform/plugins/filesystem/mcp/dist/index.js +23 -7
- package/payload/platform/plugins/filesystem/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/filesystem/mcp/dist/lib/__tests__/scope.test.js +104 -4
- package/payload/platform/plugins/filesystem/mcp/dist/lib/__tests__/scope.test.js.map +1 -1
- package/payload/platform/plugins/filesystem/mcp/dist/lib/__tests__/shared-folder.test.d.ts +2 -0
- package/payload/platform/plugins/filesystem/mcp/dist/lib/__tests__/shared-folder.test.d.ts.map +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/lib/__tests__/shared-folder.test.js +67 -0
- package/payload/platform/plugins/filesystem/mcp/dist/lib/__tests__/shared-folder.test.js.map +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/lib/scope.d.ts +16 -2
- package/payload/platform/plugins/filesystem/mcp/dist/lib/scope.d.ts.map +1 -1
- package/payload/platform/plugins/filesystem/mcp/dist/lib/scope.js +54 -1
- package/payload/platform/plugins/filesystem/mcp/dist/lib/scope.js.map +1 -1
- package/payload/platform/plugins/filesystem/mcp/dist/tools/__tests__/handlers.test.js +76 -2
- package/payload/platform/plugins/filesystem/mcp/dist/tools/__tests__/handlers.test.js.map +1 -1
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-edit.d.ts +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-edit.d.ts.map +1 -1
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-edit.js +3 -3
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-edit.js.map +1 -1
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-glob.d.ts +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-glob.d.ts.map +1 -1
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-glob.js +1 -1
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-glob.js.map +1 -1
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-grep.d.ts +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-grep.d.ts.map +1 -1
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-grep.js +3 -3
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-grep.js.map +1 -1
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-list.d.ts +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-list.d.ts.map +1 -1
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-list.js +3 -3
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-list.js.map +1 -1
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-read.d.ts +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-read.d.ts.map +1 -1
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-read.js +3 -3
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-read.js.map +1 -1
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-write.d.ts +1 -0
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-write.d.ts.map +1 -1
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-write.js +3 -3
- package/payload/platform/plugins/filesystem/mcp/dist/tools/file-write.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/agent-turn-dispatch.test.js +81 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/agent-turn-dispatch.test.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.d.ts +22 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.js +80 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.js +13 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.js.map +1 -1
- package/payload/platform/plugins/whatsapp/PLUGIN.md +2 -2
- package/payload/platform/plugins/whatsapp/mcp/dist/index.js +1 -1
- package/payload/platform/plugins/whatsapp/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/whatsapp/references/channels-whatsapp.md +1 -1
- package/payload/platform/scripts/__tests__/public-surface-registered.test.sh +102 -0
- package/payload/platform/scripts/check-no-esm-require.mjs +5 -0
- package/payload/platform/scripts/lib/__tests__/account-settings-public-surface.test.sh +109 -0
- package/payload/platform/scripts/lib/account-settings-public-surface.sh +109 -0
- package/payload/platform/scripts/lib/provision-account-dir.sh +6 -3
- package/payload/platform/scripts/setup-account.sh +14 -0
- package/payload/platform/services/claude-session-manager/dist/agent-identity-locator.d.ts +8 -4
- package/payload/platform/services/claude-session-manager/dist/agent-identity-locator.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/agent-identity-locator.js +27 -7
- package/payload/platform/services/claude-session-manager/dist/agent-identity-locator.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/config.d.ts +11 -6
- package/payload/platform/services/claude-session-manager/dist/config.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/config.js +8 -4
- package/payload/platform/services/claude-session-manager/dist/config.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/fs-watcher.d.ts +24 -2
- package/payload/platform/services/claude-session-manager/dist/fs-watcher.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/fs-watcher.js +23 -1
- package/payload/platform/services/claude-session-manager/dist/fs-watcher.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/http-server.d.ts +35 -0
- package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/http-server.js +286 -25
- package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/index.js +169 -51
- package/payload/platform/services/claude-session-manager/dist/index.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts +24 -12
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.js +194 -28
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/public-agent-reachability.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/public-agent-reachability.js +4 -0
- package/payload/platform/services/claude-session-manager/dist/public-agent-reachability.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/public-surface-audit.d.ts +24 -3
- package/payload/platform/services/claude-session-manager/dist/public-surface-audit.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/public-surface-audit.js +29 -3
- package/payload/platform/services/claude-session-manager/dist/public-surface-audit.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/rc-public-lockdown.d.ts +27 -0
- package/payload/platform/services/claude-session-manager/dist/rc-public-lockdown.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/rc-public-lockdown.js +32 -0
- package/payload/platform/services/claude-session-manager/dist/rc-public-lockdown.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/role-census.d.ts +24 -0
- package/payload/platform/services/claude-session-manager/dist/role-census.d.ts.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/role-census.js +50 -0
- package/payload/platform/services/claude-session-manager/dist/role-census.js.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/session-sidecar.d.ts +24 -2
- package/payload/platform/services/claude-session-manager/dist/session-sidecar.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/session-sidecar.js +21 -0
- package/payload/platform/services/claude-session-manager/dist/session-sidecar.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/stuck-turn-recover.d.ts +76 -0
- package/payload/platform/services/claude-session-manager/dist/stuck-turn-recover.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/stuck-turn-recover.js +110 -19
- package/payload/platform/services/claude-session-manager/dist/stuck-turn-recover.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/stuck-turn-respawn.d.ts +60 -0
- package/payload/platform/services/claude-session-manager/dist/stuck-turn-respawn.d.ts.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/stuck-turn-respawn.js +93 -0
- package/payload/platform/services/claude-session-manager/dist/stuck-turn-respawn.js.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/stuck-turn.d.ts +31 -1
- package/payload/platform/services/claude-session-manager/dist/stuck-turn.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/stuck-turn.js +72 -9
- package/payload/platform/services/claude-session-manager/dist/stuck-turn.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/system-prompt.d.ts +1 -1
- package/payload/platform/services/claude-session-manager/dist/system-prompt.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/system-prompt.js +9 -1
- package/payload/platform/services/claude-session-manager/dist/system-prompt.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/types.d.ts +9 -3
- package/payload/platform/services/claude-session-manager/dist/types.d.ts.map +1 -1
- package/payload/platform/services/telegram-channel/dist/instructions.d.ts +0 -1
- package/payload/platform/services/telegram-channel/dist/instructions.d.ts.map +1 -1
- package/payload/platform/services/telegram-channel/dist/instructions.js +0 -46
- package/payload/platform/services/telegram-channel/dist/instructions.js.map +1 -1
- package/payload/platform/services/telegram-channel/dist/notification.d.ts +16 -4
- package/payload/platform/services/telegram-channel/dist/notification.d.ts.map +1 -1
- package/payload/platform/services/telegram-channel/dist/notification.js +27 -14
- package/payload/platform/services/telegram-channel/dist/notification.js.map +1 -1
- package/payload/platform/services/telegram-channel/dist/server.d.ts.map +1 -1
- package/payload/platform/services/telegram-channel/dist/server.js +10 -0
- package/payload/platform/services/telegram-channel/dist/server.js.map +1 -1
- package/payload/platform/services/webchat-channel/dist/instructions.d.ts +0 -1
- package/payload/platform/services/webchat-channel/dist/instructions.d.ts.map +1 -1
- package/payload/platform/services/webchat-channel/dist/instructions.js +0 -60
- package/payload/platform/services/webchat-channel/dist/instructions.js.map +1 -1
- package/payload/platform/services/webchat-channel/dist/notification.d.ts +14 -2
- package/payload/platform/services/webchat-channel/dist/notification.d.ts.map +1 -1
- package/payload/platform/services/webchat-channel/dist/notification.js +28 -12
- package/payload/platform/services/webchat-channel/dist/notification.js.map +1 -1
- package/payload/platform/services/webchat-channel/dist/server.d.ts.map +1 -1
- package/payload/platform/services/webchat-channel/dist/server.js +10 -0
- package/payload/platform/services/webchat-channel/dist/server.js.map +1 -1
- package/payload/platform/services/whatsapp-channel/dist/notification.d.ts +97 -33
- package/payload/platform/services/whatsapp-channel/dist/notification.d.ts.map +1 -1
- package/payload/platform/services/whatsapp-channel/dist/notification.js +98 -76
- package/payload/platform/services/whatsapp-channel/dist/notification.js.map +1 -1
- package/payload/platform/services/whatsapp-channel/dist/server.d.ts +18 -0
- package/payload/platform/services/whatsapp-channel/dist/server.d.ts.map +1 -1
- package/payload/platform/services/whatsapp-channel/dist/server.js +87 -5
- package/payload/platform/services/whatsapp-channel/dist/server.js.map +1 -1
- package/payload/platform/services/whatsapp-channel/dist/targets.d.ts +41 -9
- package/payload/platform/services/whatsapp-channel/dist/targets.d.ts.map +1 -1
- package/payload/platform/services/whatsapp-channel/dist/targets.js +42 -7
- package/payload/platform/services/whatsapp-channel/dist/targets.js.map +1 -1
- package/payload/platform/templates/agents/admin/INSTRUCTION.md +0 -0
- package/payload/server/{adminuser-self-heal-LC7HZAC6.js → adminuser-self-heal-ZHFNDKJK.js} +1 -1
- package/payload/server/{chunk-HZP7BKBF.js → chunk-CVUSUNXM.js} +128 -4
- package/payload/server/{chunk-CKTHAHL4.js → chunk-DU7GPDJJ.js} +4 -2
- package/payload/server/{chunk-PFF6I7KP.js → chunk-HYQNUVGO.js} +8 -1
- package/payload/server/{chunk-ERIM3EFB.js → chunk-X2RRMHVV.js} +1 -1
- package/payload/server/{manager-CM55K4J2.js → manager-TI2YJQVZ.js} +3 -3
- package/payload/server/maxy-edge.js +3 -3
- package/payload/server/public/activity.html +5 -5
- package/payload/server/public/agents.html +4 -4
- package/payload/server/public/assets/AdminLoginScreens-BGKtDqAk.js +1 -0
- package/payload/server/public/assets/AdminLoginScreens-BGKtDqAk.js.br +0 -0
- package/payload/server/public/assets/AdminLoginScreens-BGKtDqAk.js.gz +0 -0
- package/payload/server/public/assets/AdminShell-DnfgsAQl.js +2 -0
- package/payload/server/public/assets/AdminShell-DnfgsAQl.js.br +0 -0
- package/payload/server/public/assets/AdminShell-DnfgsAQl.js.gz +0 -0
- package/payload/server/public/assets/activity-ByJSut0Q.js +1 -0
- package/payload/server/public/assets/activity-ByJSut0Q.js.br +0 -0
- package/payload/server/public/assets/activity-ByJSut0Q.js.gz +0 -0
- package/payload/server/public/assets/admin-CkeJO6kA.js +1 -0
- package/payload/server/public/assets/admin-CkeJO6kA.js.br +0 -0
- package/payload/server/public/assets/admin-CkeJO6kA.js.gz +0 -0
- package/payload/server/public/assets/agents-D8phtRX5.js +1 -0
- package/payload/server/public/assets/agents-D8phtRX5.js.br +0 -0
- package/payload/server/public/assets/agents-D8phtRX5.js.gz +0 -0
- package/payload/server/public/assets/browser-DQSTjdom.js +1 -0
- package/payload/server/public/assets/browser-DQSTjdom.js.br +0 -0
- package/payload/server/public/assets/browser-DQSTjdom.js.gz +0 -0
- package/payload/server/public/assets/calendar-DFJu1XjP.js +1 -0
- package/payload/server/public/assets/calendar-DFJu1XjP.js.br +0 -0
- package/payload/server/public/assets/calendar-DFJu1XjP.js.gz +0 -0
- package/payload/server/public/assets/chat-DUqtIsOt.js +1 -0
- package/payload/server/public/assets/chat-DUqtIsOt.js.br +0 -0
- package/payload/server/public/assets/chat-DUqtIsOt.js.gz +0 -0
- package/payload/server/public/assets/chevron-left-DFK18xVX.js +1 -0
- package/payload/server/public/assets/chevron-left-DFK18xVX.js.br +0 -0
- package/payload/server/public/assets/chevron-right-DJ4oaHoN.js +1 -0
- package/payload/server/public/assets/chevron-right-DJ4oaHoN.js.br +0 -0
- package/payload/server/public/assets/clock-wHIan2DW.js +1 -0
- package/payload/server/public/assets/clock-wHIan2DW.js.br +0 -0
- package/payload/server/public/assets/{copy-3kj9Oaoc.js → copy-lFFhXRGk.js} +1 -1
- package/payload/server/public/assets/copy-lFFhXRGk.js.br +0 -0
- package/payload/server/public/assets/copy-lFFhXRGk.js.gz +0 -0
- package/payload/server/public/assets/data-Cxv97ARy.js +1 -0
- package/payload/server/public/assets/data-Cxv97ARy.js.br +0 -0
- package/payload/server/public/assets/data-Cxv97ARy.js.gz +0 -0
- package/payload/server/public/assets/{file-text-CBaewT76.js → file-text-D2Y-bkNy.js} +1 -1
- package/payload/server/public/assets/file-text-D2Y-bkNy.js.br +0 -0
- package/payload/server/public/assets/file-text-D2Y-bkNy.js.gz +0 -0
- package/payload/server/public/assets/{graph-B8-e2_Z-.js → graph-C-3yN6JD.js} +3 -3
- package/payload/server/public/assets/graph-C-3yN6JD.js.br +0 -0
- package/payload/server/public/assets/graph-C-3yN6JD.js.gz +0 -0
- package/payload/server/public/assets/{graph-labels-Bsc23eZU.js → graph-labels-DiaPLP27.js} +1 -1
- package/payload/server/public/assets/graph-labels-DiaPLP27.js.br +0 -0
- package/payload/server/public/assets/graph-labels-DiaPLP27.js.gz +0 -0
- package/payload/server/public/assets/operator-KuGPvSa9.js +1 -0
- package/payload/server/public/assets/operator-KuGPvSa9.js.br +0 -0
- package/payload/server/public/assets/operator-KuGPvSa9.js.gz +0 -0
- package/payload/server/public/assets/page-BhGeFXWA.js +1 -0
- package/payload/server/public/assets/page-BhGeFXWA.js.br +0 -0
- package/payload/server/public/assets/page-BhGeFXWA.js.gz +0 -0
- package/payload/server/public/assets/page-EnbVC-yM.js +32 -0
- package/payload/server/public/assets/page-EnbVC-yM.js.br +0 -0
- package/payload/server/public/assets/page-EnbVC-yM.js.gz +0 -0
- package/payload/server/public/assets/play-jZFZAG-t.js +1 -0
- package/payload/server/public/assets/play-jZFZAG-t.js.br +0 -0
- package/payload/server/public/assets/play-jZFZAG-t.js.gz +0 -0
- package/payload/server/public/assets/public-CdSgMNC7.js +1 -0
- package/payload/server/public/assets/public-CdSgMNC7.js.br +0 -0
- package/payload/server/public/assets/public-CdSgMNC7.js.gz +0 -0
- package/payload/server/public/assets/{rotate-ccw-FZW7c8p8.js → rotate-ccw-rTRuTqei.js} +1 -1
- package/payload/server/public/assets/rotate-ccw-rTRuTqei.js.br +0 -0
- package/payload/server/public/assets/rotate-ccw-rTRuTqei.js.gz +0 -0
- package/payload/server/public/assets/routines-DNRxNRSQ.js +2 -0
- package/payload/server/public/assets/routines-DNRxNRSQ.js.br +0 -0
- package/payload/server/public/assets/routines-DNRxNRSQ.js.gz +0 -0
- package/payload/server/public/assets/skills-DFWtZNkW.js +1 -0
- package/payload/server/public/assets/skills-DFWtZNkW.js.br +0 -0
- package/payload/server/public/assets/skills-DFWtZNkW.js.gz +0 -0
- package/payload/server/public/assets/tasks-B94AuKSy.js +3 -0
- package/payload/server/public/assets/tasks-B94AuKSy.js.br +0 -0
- package/payload/server/public/assets/tasks-B94AuKSy.js.gz +0 -0
- package/payload/server/public/assets/{triangle-alert-CR-jRJdI.js → triangle-alert-DtWUg6jR.js} +1 -1
- package/payload/server/public/assets/triangle-alert-DtWUg6jR.js.br +0 -0
- package/payload/server/public/assets/triangle-alert-DtWUg6jR.js.gz +0 -0
- package/payload/server/public/assets/useCopyFeedback-CjKYO-Qf.js +1 -0
- package/payload/server/public/assets/useCopyFeedback-CjKYO-Qf.js.br +0 -0
- package/payload/server/public/assets/useCopyFeedback-CjKYO-Qf.js.gz +0 -0
- package/payload/server/public/assets/useMediaQuery-BYIHo-xL.js +14 -0
- package/payload/server/public/assets/useMediaQuery-BYIHo-xL.js.br +0 -0
- package/payload/server/public/assets/useMediaQuery-BYIHo-xL.js.gz +0 -0
- package/payload/server/public/assets/useMediaQuery-DlOWP56H.css +1 -0
- package/payload/server/public/assets/useMediaQuery-DlOWP56H.css.br +0 -0
- package/payload/server/public/assets/useMediaQuery-DlOWP56H.css.gz +0 -0
- package/payload/server/public/assets/useVoiceRecorder-BKFAYuzz.js +2 -0
- package/payload/server/public/assets/useVoiceRecorder-BKFAYuzz.js.br +0 -0
- package/payload/server/public/assets/useVoiceRecorder-BKFAYuzz.js.gz +0 -0
- package/payload/server/public/assets/{wrench-CpCOYUBc.js → wrench-Ct4kf-uv.js} +1 -1
- package/payload/server/public/assets/wrench-Ct4kf-uv.js.br +0 -0
- package/payload/server/public/assets/wrench-Ct4kf-uv.js.gz +0 -0
- package/payload/server/public/browser.html +4 -4
- package/payload/server/public/calendar.html +8 -8
- package/payload/server/public/chat.html +13 -13
- package/payload/server/public/data.html +11 -11
- package/payload/server/public/graph.html +9 -9
- package/payload/server/public/index.html +14 -14
- package/payload/server/public/operator.html +14 -14
- package/payload/server/public/public.html +13 -13
- package/payload/server/public/routines.html +6 -6
- package/payload/server/public/skills.html +5 -5
- package/payload/server/public/tasks.html +6 -6
- package/payload/server/server.js +537 -263
- package/payload/server/{src-JN6PIAJN.js → src-MM64CYYZ.js} +1 -1
- package/payload/server/{userprofile-reconcile-QHVLY2AH.js → userprofile-reconcile-TL4JKBPG.js} +1 -1
- package/payload/server/public/assets/AdminLoginScreens-DuFCjbz2.js +0 -1
- package/payload/server/public/assets/AdminLoginScreens-DuFCjbz2.js.br +0 -0
- package/payload/server/public/assets/AdminLoginScreens-DuFCjbz2.js.gz +0 -0
- package/payload/server/public/assets/AdminShell-DJL5DzRX.js +0 -2
- package/payload/server/public/assets/AdminShell-DJL5DzRX.js.br +0 -0
- package/payload/server/public/assets/AdminShell-DJL5DzRX.js.gz +0 -0
- package/payload/server/public/assets/activity-CpMnNr5c.js +0 -1
- package/payload/server/public/assets/activity-CpMnNr5c.js.br +0 -0
- package/payload/server/public/assets/activity-CpMnNr5c.js.gz +0 -0
- package/payload/server/public/assets/admin-CBwKIfaI.js +0 -1
- package/payload/server/public/assets/admin-CBwKIfaI.js.br +0 -0
- package/payload/server/public/assets/admin-CBwKIfaI.js.gz +0 -0
- package/payload/server/public/assets/agents-C4LmSKjb.js +0 -1
- package/payload/server/public/assets/agents-C4LmSKjb.js.br +0 -0
- package/payload/server/public/assets/agents-C4LmSKjb.js.gz +0 -0
- package/payload/server/public/assets/browser-Bm9xm_yc.js +0 -1
- package/payload/server/public/assets/browser-Bm9xm_yc.js.br +0 -0
- package/payload/server/public/assets/browser-Bm9xm_yc.js.gz +0 -0
- package/payload/server/public/assets/calendar-CNY9FTWe.js +0 -1
- package/payload/server/public/assets/calendar-CNY9FTWe.js.br +0 -0
- package/payload/server/public/assets/calendar-CNY9FTWe.js.gz +0 -0
- package/payload/server/public/assets/chat-3WoUGCTd.js +0 -1
- package/payload/server/public/assets/chat-3WoUGCTd.js.br +0 -0
- package/payload/server/public/assets/chat-3WoUGCTd.js.gz +0 -0
- package/payload/server/public/assets/chevron-left-BE16BJnw.js +0 -1
- package/payload/server/public/assets/chevron-left-BE16BJnw.js.br +0 -0
- package/payload/server/public/assets/chevron-right-Bu2VKpeU.js +0 -1
- package/payload/server/public/assets/chevron-right-Bu2VKpeU.js.br +0 -0
- package/payload/server/public/assets/clock-C4Nu2aRV.js +0 -1
- package/payload/server/public/assets/clock-C4Nu2aRV.js.br +0 -0
- package/payload/server/public/assets/copy-3kj9Oaoc.js.br +0 -0
- package/payload/server/public/assets/copy-3kj9Oaoc.js.gz +0 -0
- package/payload/server/public/assets/data-C-x5EHyi.js +0 -1
- package/payload/server/public/assets/data-C-x5EHyi.js.br +0 -1
- package/payload/server/public/assets/data-C-x5EHyi.js.gz +0 -0
- package/payload/server/public/assets/file-text-CBaewT76.js.br +0 -0
- package/payload/server/public/assets/file-text-CBaewT76.js.gz +0 -0
- package/payload/server/public/assets/graph-B8-e2_Z-.js.br +0 -0
- package/payload/server/public/assets/graph-B8-e2_Z-.js.gz +0 -0
- package/payload/server/public/assets/graph-labels-Bsc23eZU.js.br +0 -0
- package/payload/server/public/assets/graph-labels-Bsc23eZU.js.gz +0 -0
- package/payload/server/public/assets/operator-Cve0-qfO.js +0 -1
- package/payload/server/public/assets/operator-Cve0-qfO.js.br +0 -0
- package/payload/server/public/assets/operator-Cve0-qfO.js.gz +0 -0
- package/payload/server/public/assets/page-BgVMs6Vf.js +0 -1
- package/payload/server/public/assets/page-BgVMs6Vf.js.br +0 -0
- package/payload/server/public/assets/page-BgVMs6Vf.js.gz +0 -0
- package/payload/server/public/assets/page-fABub-w8.js +0 -32
- package/payload/server/public/assets/page-fABub-w8.js.br +0 -0
- package/payload/server/public/assets/page-fABub-w8.js.gz +0 -0
- package/payload/server/public/assets/play-B6zXB9K7.js +0 -1
- package/payload/server/public/assets/play-B6zXB9K7.js.br +0 -0
- package/payload/server/public/assets/play-B6zXB9K7.js.gz +0 -0
- package/payload/server/public/assets/public--R2DbdWs.js +0 -1
- package/payload/server/public/assets/public--R2DbdWs.js.br +0 -0
- package/payload/server/public/assets/public--R2DbdWs.js.gz +0 -0
- package/payload/server/public/assets/rotate-ccw-FZW7c8p8.js.br +0 -0
- package/payload/server/public/assets/rotate-ccw-FZW7c8p8.js.gz +0 -0
- package/payload/server/public/assets/routines-BpZs2SaT.js +0 -2
- package/payload/server/public/assets/routines-BpZs2SaT.js.br +0 -0
- package/payload/server/public/assets/routines-BpZs2SaT.js.gz +0 -0
- package/payload/server/public/assets/skills-DF7uyEEz.js +0 -1
- package/payload/server/public/assets/skills-DF7uyEEz.js.br +0 -0
- package/payload/server/public/assets/skills-DF7uyEEz.js.gz +0 -0
- package/payload/server/public/assets/tasks-BfJJmoWO.js +0 -3
- package/payload/server/public/assets/tasks-BfJJmoWO.js.br +0 -0
- package/payload/server/public/assets/tasks-BfJJmoWO.js.gz +0 -0
- package/payload/server/public/assets/triangle-alert-CR-jRJdI.js.br +0 -0
- package/payload/server/public/assets/triangle-alert-CR-jRJdI.js.gz +0 -0
- package/payload/server/public/assets/useCopyFeedback-IOuPUAHY.js +0 -1
- package/payload/server/public/assets/useCopyFeedback-IOuPUAHY.js.br +0 -0
- package/payload/server/public/assets/useCopyFeedback-IOuPUAHY.js.gz +0 -0
- package/payload/server/public/assets/useMediaQuery-CA6dR5iz.js +0 -14
- package/payload/server/public/assets/useMediaQuery-CA6dR5iz.js.br +0 -0
- package/payload/server/public/assets/useMediaQuery-CA6dR5iz.js.gz +0 -0
- package/payload/server/public/assets/useMediaQuery-DpwgV1Da.css +0 -1
- package/payload/server/public/assets/useMediaQuery-DpwgV1Da.css.br +0 -0
- package/payload/server/public/assets/useMediaQuery-DpwgV1Da.css.gz +0 -0
- package/payload/server/public/assets/useVoiceRecorder-DGhsN7nV.js +0 -2
- package/payload/server/public/assets/useVoiceRecorder-DGhsN7nV.js.br +0 -0
- package/payload/server/public/assets/useVoiceRecorder-DGhsN7nV.js.gz +0 -0
- package/payload/server/public/assets/wrench-CpCOYUBc.js.br +0 -0
- 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,
|
|
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 {
|
|
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:
|
|
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.
|