@rubytech/create-sitedesk-code 0.1.528 → 0.1.530
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/index.js +13 -0
- package/package.json +1 -1
- package/payload/platform/lib/account-ingest-token/dist/index.d.ts +21 -0
- package/payload/platform/lib/account-ingest-token/dist/index.d.ts.map +1 -0
- package/payload/platform/lib/account-ingest-token/dist/index.js +128 -0
- package/payload/platform/lib/account-ingest-token/dist/index.js.map +1 -0
- package/payload/platform/lib/account-ingest-token/src/index.ts +137 -0
- package/payload/platform/lib/account-ingest-token/tsconfig.json +8 -0
- package/payload/platform/lib/agent-dispatch-rule/dist/index.d.ts +5 -0
- package/payload/platform/lib/agent-dispatch-rule/dist/index.d.ts.map +1 -1
- package/payload/platform/lib/agent-dispatch-rule/dist/index.js.map +1 -1
- package/payload/platform/lib/agent-dispatch-rule/src/index.ts +5 -0
- package/payload/platform/lib/routine-templates/dist/index.d.ts +19 -3
- package/payload/platform/lib/routine-templates/dist/index.d.ts.map +1 -1
- package/payload/platform/lib/routine-templates/dist/index.js +22 -4
- package/payload/platform/lib/routine-templates/dist/index.js.map +1 -1
- package/payload/platform/lib/routine-templates/dist/roster.d.ts +19 -6
- package/payload/platform/lib/routine-templates/dist/roster.d.ts.map +1 -1
- package/payload/platform/lib/routine-templates/dist/roster.js +127 -17
- package/payload/platform/lib/routine-templates/dist/roster.js.map +1 -1
- package/payload/platform/lib/routine-templates/src/__tests__/roster.test.ts +46 -3
- package/payload/platform/lib/routine-templates/src/__tests__/seed.test.ts +52 -10
- package/payload/platform/lib/routine-templates/src/index.ts +30 -4
- package/payload/platform/lib/routine-templates/src/roster.ts +147 -17
- package/payload/platform/package.json +2 -2
- package/payload/platform/plugins/admin/.claude-plugin/plugin.json +1 -1
- package/payload/platform/plugins/admin/PLUGIN.md +5 -1
- package/payload/platform/plugins/admin/mcp/dist/index.js +37 -0
- package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/admin/mcp/dist/tools/linkedin-ingest-token.d.ts +10 -0
- package/payload/platform/plugins/admin/mcp/dist/tools/linkedin-ingest-token.d.ts.map +1 -0
- package/payload/platform/plugins/admin/mcp/dist/tools/linkedin-ingest-token.js +22 -0
- package/payload/platform/plugins/admin/mcp/dist/tools/linkedin-ingest-token.js.map +1 -0
- package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +31 -6
- package/payload/platform/plugins/admin/skills/whats-new/SKILL.md +12 -0
- package/payload/platform/plugins/docs/references/admin-ui.md +28 -3
- package/payload/platform/plugins/docs/references/linkedin-extension.md +2 -2
- package/payload/platform/plugins/linkedin-extension/extension/README.md +3 -3
- package/payload/platform/plugins/linkedin-extension/extension/background/sw.js +12 -7
- package/payload/platform/plugins/linkedin-extension/extension/content/profile.js +4 -1
- package/payload/platform/plugins/linkedin-extension/extension/content/thread.js +4 -1
- package/payload/platform/plugins/linkedin-extension/extension/options/options.html +3 -3
- package/payload/platform/plugins/linkedin-extension/extension/options/options.js +24 -16
- package/payload/platform/plugins/scheduling/PLUGIN.md +2 -0
- package/payload/platform/plugins/scheduling/mcp/dist/index.js +5 -0
- package/payload/platform/plugins/scheduling/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/normalise-start-date.test.d.ts +2 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/normalise-start-date.test.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/normalise-start-date.test.js +100 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/normalise-start-date.test.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/dispatcher-env.d.ts +36 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/dispatcher-env.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/dispatcher-env.js +82 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/dispatcher-env.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/time-format.d.ts +31 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/time-format.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/time-format.js +99 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/time-format.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/agent-turn-dispatch.test.js +12 -12
- 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/__tests__/converge-startdate-utc.test.d.ts +2 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/converge-startdate-utc.test.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/converge-startdate-utc.test.js +79 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/converge-startdate-utc.test.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/dispatch-lateness.test.d.ts +2 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/dispatch-lateness.test.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/dispatch-lateness.test.js +23 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/dispatch-lateness.test.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/routine-roster-audit.test.js +61 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/routine-roster-audit.test.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/suspension-census.test.js +45 -2
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/suspension-census.test.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.d.ts +33 -1
- 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 +111 -9
- 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 +21 -69
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/converge-startdate-utc.d.ts +24 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/converge-startdate-utc.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/converge-startdate-utc.js +87 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/converge-startdate-utc.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-event-startdate.test.d.ts +2 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-event-startdate.test.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-event-startdate.test.js +123 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-event-startdate.test.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-update-startdate.test.d.ts +2 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-update-startdate.test.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-update-startdate.test.js +71 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-update-startdate.test.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-update-status.test.js +14 -3
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-update-status.test.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-event.d.ts +9 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-event.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-event.js +19 -3
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-event.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-update.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-update.js +24 -9
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-update.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js +1 -0
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js.map +1 -1
- package/payload/server/{chunk-UTIHI6KV.js → chunk-2YMGNYA3.js} +12 -12
- package/payload/server/{manager-B4LRDZKC.js → manager-XPRN5UF5.js} +1 -1
- package/payload/server/package.json +1 -1
- package/payload/server/public/activity.html +5 -5
- package/payload/server/public/agents.html +4 -4
- package/payload/server/public/assets/{AdminLoginScreens-Bx9vPuUg.js → AdminLoginScreens-7Czw3MAC.js} +1 -1
- package/payload/server/public/assets/AdminLoginScreens-7Czw3MAC.js.br +0 -0
- package/payload/server/public/assets/AdminLoginScreens-7Czw3MAC.js.gz +0 -0
- package/payload/server/public/assets/{AdminShell-BxJPbC3p.js → AdminShell-D5GApZ_n.js} +1 -1
- package/payload/server/public/assets/AdminShell-D5GApZ_n.js.br +0 -0
- package/payload/server/public/assets/AdminShell-D5GApZ_n.js.gz +0 -0
- package/payload/server/public/assets/{CdpScreencastSurface-5HLhTQTV.js → CdpScreencastSurface-BbekDUFw.js} +1 -1
- package/payload/server/public/assets/CdpScreencastSurface-BbekDUFw.js.br +0 -0
- package/payload/server/public/assets/CdpScreencastSurface-BbekDUFw.js.gz +0 -0
- package/payload/server/public/assets/{activity-BaSYn62l.js → activity-ClI-RgJu.js} +1 -1
- package/payload/server/public/assets/activity-ClI-RgJu.js.br +0 -0
- package/payload/server/public/assets/activity-ClI-RgJu.js.gz +0 -0
- package/payload/server/public/assets/{admin-CYCKrV_x.js → admin-svtCmBPk.js} +1 -1
- package/payload/server/public/assets/admin-svtCmBPk.js.br +0 -0
- package/payload/server/public/assets/admin-svtCmBPk.js.gz +0 -0
- package/payload/server/public/assets/{agents-D8EJG-ta.js → agents-BO8YBj8d.js} +1 -1
- package/payload/server/public/assets/agents-BO8YBj8d.js.br +0 -0
- package/payload/server/public/assets/agents-BO8YBj8d.js.gz +0 -0
- package/payload/server/public/assets/{browser-D6Y_Zu8C.js → browser-Bj8oTG5R.js} +1 -1
- package/payload/server/public/assets/browser-Bj8oTG5R.js.br +0 -0
- package/payload/server/public/assets/browser-Bj8oTG5R.js.gz +0 -0
- package/payload/server/public/assets/{calendar-DD4oVa-r.js → calendar-CrkSY8U7.js} +1 -1
- package/payload/server/public/assets/calendar-CrkSY8U7.js.br +0 -0
- package/payload/server/public/assets/calendar-CrkSY8U7.js.gz +0 -0
- package/payload/server/public/assets/chat-Bvxoni2e.js +1 -0
- package/payload/server/public/assets/chat-Bvxoni2e.js.br +0 -0
- package/payload/server/public/assets/chat-Bvxoni2e.js.gz +0 -0
- package/payload/server/public/assets/chevron-left-CdUzxzeB.js +1 -0
- package/payload/server/public/assets/chevron-left-CdUzxzeB.js.br +0 -0
- package/payload/server/public/assets/chevron-right-CKGwd-M0.js +1 -0
- package/payload/server/public/assets/chevron-right-CKGwd-M0.js.br +0 -0
- package/payload/server/public/assets/clock-Cf8Oe9qi.js +1 -0
- package/payload/server/public/assets/clock-Cf8Oe9qi.js.br +0 -0
- package/payload/server/public/assets/clock-Cf8Oe9qi.js.gz +0 -0
- package/payload/server/public/assets/data-DF0Pstdp.js +1 -0
- package/payload/server/public/assets/data-DF0Pstdp.js.br +1 -0
- package/payload/server/public/assets/data-DF0Pstdp.js.gz +0 -0
- package/payload/server/public/assets/{file-download-sXU3_umF.js → file-download-Di_s0_4w.js} +1 -1
- package/payload/server/public/assets/file-download-Di_s0_4w.js.br +0 -0
- package/payload/server/public/assets/file-download-Di_s0_4w.js.gz +0 -0
- package/payload/server/public/assets/{file-text-CeXBviDH.js → file-text-CP1KIrJV.js} +1 -1
- package/payload/server/public/assets/file-text-CP1KIrJV.js.br +1 -0
- package/payload/server/public/assets/file-text-CP1KIrJV.js.gz +0 -0
- package/payload/server/public/assets/{graph-BSuDP6k7.js → graph-BCMscnCV.js} +1 -1
- package/payload/server/public/assets/graph-BCMscnCV.js.br +0 -0
- package/payload/server/public/assets/graph-BCMscnCV.js.gz +0 -0
- package/payload/server/public/assets/{graph-labels-D2pQkgYW.js → graph-labels-CgP17xHK.js} +1 -1
- package/payload/server/public/assets/graph-labels-CgP17xHK.js.br +0 -0
- package/payload/server/public/assets/graph-labels-CgP17xHK.js.gz +0 -0
- package/payload/server/public/assets/{maximize-2-DlzSNygU.js → maximize-2-DkQzDv-g.js} +1 -1
- package/payload/server/public/assets/maximize-2-DkQzDv-g.js.br +0 -0
- package/payload/server/public/assets/maximize-2-DkQzDv-g.js.gz +0 -0
- package/payload/server/public/assets/{operator-BP61-xjz.js → operator-CLbCar9e.js} +1 -1
- package/payload/server/public/assets/operator-CLbCar9e.js.br +0 -0
- package/payload/server/public/assets/operator-CLbCar9e.js.gz +0 -0
- package/payload/server/public/assets/{page-DX7ArY_s.js → page-CNJl3tWT.js} +1 -1
- package/payload/server/public/assets/page-CNJl3tWT.js.br +0 -0
- package/payload/server/public/assets/page-CNJl3tWT.js.gz +0 -0
- package/payload/server/public/assets/{page-eQ4OVros.js → page-CPVUAwb8.js} +1 -1
- package/payload/server/public/assets/page-CPVUAwb8.js.br +0 -0
- package/payload/server/public/assets/page-CPVUAwb8.js.gz +0 -0
- package/payload/server/public/assets/{public-DPDKFKM2.js → public-DQea3Ybz.js} +1 -1
- package/payload/server/public/assets/public-DQea3Ybz.js.br +0 -0
- package/payload/server/public/assets/public-DQea3Ybz.js.gz +0 -0
- package/payload/server/public/assets/{rotate-ccw-BR0JbPFV.js → rotate-ccw-DPw0vXC0.js} +1 -1
- package/payload/server/public/assets/rotate-ccw-DPw0vXC0.js.br +0 -0
- package/payload/server/public/assets/rotate-ccw-DPw0vXC0.js.gz +0 -0
- package/payload/server/public/assets/routines-CwiiYpfK.js +2 -0
- package/payload/server/public/assets/routines-CwiiYpfK.js.br +0 -0
- package/payload/server/public/assets/routines-CwiiYpfK.js.gz +0 -0
- package/payload/server/public/assets/{skills-fH0uA7cj.js → skills-0FOjKUM-.js} +1 -1
- package/payload/server/public/assets/skills-0FOjKUM-.js.br +0 -0
- package/payload/server/public/assets/skills-0FOjKUM-.js.gz +0 -0
- package/payload/server/public/assets/{tasks-CrVzFrTR.js → tasks-BUVsPEGm.js} +1 -1
- package/payload/server/public/assets/tasks-BUVsPEGm.js.br +0 -0
- package/payload/server/public/assets/tasks-BUVsPEGm.js.gz +0 -0
- package/payload/server/public/assets/{time-entry-format-C_0jiMpQ.js → time-entry-format-B6fX_19a.js} +1 -1
- package/payload/server/public/assets/time-entry-format-B6fX_19a.js.br +0 -0
- package/payload/server/public/assets/time-entry-format-B6fX_19a.js.gz +0 -0
- package/payload/server/public/assets/{triangle-alert-eLJHC_QJ.js → triangle-alert-vAaSDhVq.js} +1 -1
- package/payload/server/public/assets/triangle-alert-vAaSDhVq.js.br +0 -0
- package/payload/server/public/assets/triangle-alert-vAaSDhVq.js.gz +0 -0
- package/payload/server/public/assets/{useCopyFeedback-vPCmdOmY.js → useCopyFeedback-BvIRgs7W.js} +1 -1
- package/payload/server/public/assets/useCopyFeedback-BvIRgs7W.js.br +0 -0
- package/payload/server/public/assets/useCopyFeedback-BvIRgs7W.js.gz +0 -0
- package/payload/server/public/assets/{useSubAccountSwitcher-DxuUS_C7.css → useSubAccountSwitcher-DM5Y9eio.css} +1 -1
- package/payload/server/public/assets/useSubAccountSwitcher-DM5Y9eio.css.br +0 -0
- package/payload/server/public/assets/{useSubAccountSwitcher-DxuUS_C7.css.gz → useSubAccountSwitcher-DM5Y9eio.css.gz} +0 -0
- package/payload/server/public/assets/{useVoiceRecorder-D5bFDRqL.js → useVoiceRecorder-CiDOh8PG.js} +1 -1
- package/payload/server/public/assets/useVoiceRecorder-CiDOh8PG.js.br +0 -0
- package/payload/server/public/assets/useVoiceRecorder-CiDOh8PG.js.gz +0 -0
- package/payload/server/public/assets/{wrench-sXisQXkf.js → wrench-BNBtwT2p.js} +1 -1
- package/payload/server/public/assets/wrench-BNBtwT2p.js.br +0 -0
- package/payload/server/public/assets/wrench-BNBtwT2p.js.gz +0 -0
- package/payload/server/public/browser.html +5 -5
- package/payload/server/public/calendar.html +7 -7
- package/payload/server/public/chat.html +13 -13
- package/payload/server/public/data.html +12 -12
- package/payload/server/public/graph.html +9 -9
- package/payload/server/public/index.html +16 -16
- package/payload/server/public/operator.html +15 -15
- package/payload/server/public/public.html +13 -13
- package/payload/server/public/routines.html +7 -7
- package/payload/server/public/skills.html +5 -5
- package/payload/server/public/tasks.html +6 -6
- package/payload/server/server.js +353 -209
- package/payload/server/public/assets/AdminLoginScreens-Bx9vPuUg.js.br +0 -0
- package/payload/server/public/assets/AdminLoginScreens-Bx9vPuUg.js.gz +0 -0
- package/payload/server/public/assets/AdminShell-BxJPbC3p.js.br +0 -0
- package/payload/server/public/assets/AdminShell-BxJPbC3p.js.gz +0 -0
- package/payload/server/public/assets/CdpScreencastSurface-5HLhTQTV.js.br +0 -0
- package/payload/server/public/assets/CdpScreencastSurface-5HLhTQTV.js.gz +0 -0
- package/payload/server/public/assets/activity-BaSYn62l.js.br +0 -0
- package/payload/server/public/assets/activity-BaSYn62l.js.gz +0 -0
- package/payload/server/public/assets/admin-CYCKrV_x.js.br +0 -0
- package/payload/server/public/assets/admin-CYCKrV_x.js.gz +0 -0
- package/payload/server/public/assets/agents-D8EJG-ta.js.br +0 -0
- package/payload/server/public/assets/agents-D8EJG-ta.js.gz +0 -0
- package/payload/server/public/assets/browser-D6Y_Zu8C.js.br +0 -0
- package/payload/server/public/assets/browser-D6Y_Zu8C.js.gz +0 -0
- package/payload/server/public/assets/calendar-DD4oVa-r.js.br +0 -0
- package/payload/server/public/assets/calendar-DD4oVa-r.js.gz +0 -0
- package/payload/server/public/assets/chat-CwWs69PO.js +0 -1
- package/payload/server/public/assets/chat-CwWs69PO.js.br +0 -0
- package/payload/server/public/assets/chat-CwWs69PO.js.gz +0 -0
- package/payload/server/public/assets/chevron-left-ClfIy5Fx.js +0 -1
- package/payload/server/public/assets/chevron-right-B0QvXpxl.js +0 -1
- package/payload/server/public/assets/chevron-right-B0QvXpxl.js.br +0 -0
- package/payload/server/public/assets/clock-BIaRnIP_.js +0 -1
- package/payload/server/public/assets/clock-BIaRnIP_.js.br +0 -0
- package/payload/server/public/assets/clock-BIaRnIP_.js.gz +0 -0
- package/payload/server/public/assets/data-O_9Kiicl.js +0 -1
- package/payload/server/public/assets/data-O_9Kiicl.js.br +0 -2
- package/payload/server/public/assets/data-O_9Kiicl.js.gz +0 -0
- package/payload/server/public/assets/file-download-sXU3_umF.js.br +0 -0
- package/payload/server/public/assets/file-download-sXU3_umF.js.gz +0 -0
- package/payload/server/public/assets/file-text-CeXBviDH.js.br +0 -0
- package/payload/server/public/assets/file-text-CeXBviDH.js.gz +0 -0
- package/payload/server/public/assets/graph-BSuDP6k7.js.br +0 -0
- package/payload/server/public/assets/graph-BSuDP6k7.js.gz +0 -0
- package/payload/server/public/assets/graph-labels-D2pQkgYW.js.br +0 -0
- package/payload/server/public/assets/graph-labels-D2pQkgYW.js.gz +0 -0
- package/payload/server/public/assets/maximize-2-DlzSNygU.js.br +0 -0
- package/payload/server/public/assets/maximize-2-DlzSNygU.js.gz +0 -0
- package/payload/server/public/assets/operator-BP61-xjz.js.br +0 -0
- package/payload/server/public/assets/operator-BP61-xjz.js.gz +0 -0
- package/payload/server/public/assets/page-DX7ArY_s.js.br +0 -0
- package/payload/server/public/assets/page-DX7ArY_s.js.gz +0 -0
- package/payload/server/public/assets/page-eQ4OVros.js.br +0 -0
- package/payload/server/public/assets/page-eQ4OVros.js.gz +0 -0
- package/payload/server/public/assets/public-DPDKFKM2.js.br +0 -0
- package/payload/server/public/assets/public-DPDKFKM2.js.gz +0 -0
- package/payload/server/public/assets/rotate-ccw-BR0JbPFV.js.br +0 -0
- package/payload/server/public/assets/rotate-ccw-BR0JbPFV.js.gz +0 -0
- package/payload/server/public/assets/routines-y413YZa-.js +0 -1
- package/payload/server/public/assets/routines-y413YZa-.js.br +0 -0
- package/payload/server/public/assets/routines-y413YZa-.js.gz +0 -0
- package/payload/server/public/assets/skills-fH0uA7cj.js.br +0 -0
- package/payload/server/public/assets/skills-fH0uA7cj.js.gz +0 -0
- package/payload/server/public/assets/tasks-CrVzFrTR.js.br +0 -0
- package/payload/server/public/assets/tasks-CrVzFrTR.js.gz +0 -0
- package/payload/server/public/assets/time-entry-format-C_0jiMpQ.js.br +0 -1
- package/payload/server/public/assets/time-entry-format-C_0jiMpQ.js.gz +0 -0
- package/payload/server/public/assets/triangle-alert-eLJHC_QJ.js.br +0 -1
- package/payload/server/public/assets/triangle-alert-eLJHC_QJ.js.gz +0 -0
- package/payload/server/public/assets/useCopyFeedback-vPCmdOmY.js.br +0 -0
- package/payload/server/public/assets/useCopyFeedback-vPCmdOmY.js.gz +0 -0
- package/payload/server/public/assets/useSubAccountSwitcher-DxuUS_C7.css.br +0 -0
- package/payload/server/public/assets/useVoiceRecorder-D5bFDRqL.js.br +0 -0
- package/payload/server/public/assets/useVoiceRecorder-D5bFDRqL.js.gz +0 -0
- package/payload/server/public/assets/wrench-sXisQXkf.js.br +0 -0
- package/payload/server/public/assets/wrench-sXisQXkf.js.gz +0 -0
- /package/payload/server/public/assets/{useSubAccountSwitcher-DMr3DR5N.js → useSubAccountSwitcher-BEwQMRMo.js} +0 -0
- /package/payload/server/public/assets/{useSubAccountSwitcher-DMr3DR5N.js.br → useSubAccountSwitcher-BEwQMRMo.js.br} +0 -0
- /package/payload/server/public/assets/{useSubAccountSwitcher-DMr3DR5N.js.gz → useSubAccountSwitcher-BEwQMRMo.js.gz} +0 -0
|
@@ -4,15 +4,17 @@
|
|
|
4
4
|
*
|
|
5
5
|
* A fresh install used to ship zero routines, so the only working examples
|
|
6
6
|
* lived in one customer's graph and every operator wrote the prompts from
|
|
7
|
-
* scratch. These
|
|
7
|
+
* scratch. These thirteen are the catalogue that ships with the platform
|
|
8
|
+
* instead.
|
|
8
9
|
*
|
|
9
10
|
* Two properties make a routine shippable, and both are load-bearing:
|
|
10
11
|
*
|
|
11
12
|
* 1. It resolves its own surfaces at run time. Every prompt opens on
|
|
12
13
|
* `capabilities-here`, which reports the account's live install set, and
|
|
13
14
|
* ends the turn without replying when the surface it needs is absent. That
|
|
14
|
-
* is what makes the same
|
|
15
|
-
* and a field-service install rather than a template someone must
|
|
15
|
+
* is what makes the same thirteen rows correct on an estate agency, a web
|
|
16
|
+
* studio and a field-service install rather than a template someone must
|
|
17
|
+
* edit.
|
|
16
18
|
*
|
|
17
19
|
* 2. It names nobody. No prompt carries a person's name, an email address, a
|
|
18
20
|
* phone number, a hostname or a database name. `scripts/check-routine-
|
|
@@ -35,7 +37,7 @@ exports.ROUTINE_ROSTER_KEYS = exports.ROUTINE_ROSTER = exports.ROUTINE_TEMPLATE_
|
|
|
35
37
|
* routine's prompt only when the stored `routineTemplateVersion` is BELOW this
|
|
36
38
|
* and no operator has edited the row, so an unbumped edit ships to new installs
|
|
37
39
|
* and never reaches existing ones — bump it in the same commit as the edit. */
|
|
38
|
-
exports.ROUTINE_TEMPLATE_VERSION =
|
|
40
|
+
exports.ROUTINE_TEMPLATE_VERSION = 2;
|
|
39
41
|
const START_OF_DAY = `Prepare the operator's morning briefing and reply with it as a single message.
|
|
40
42
|
|
|
41
43
|
Call capabilities-here first and work only with the plugins it reports as enabled. Nothing below is mandatory: each part is included when its surface is present and skipped in silence when it is not.
|
|
@@ -159,21 +161,129 @@ If every link is connected, end the turn without replying. A message on a health
|
|
|
159
161
|
When a link is down, reply with one message naming the number it is paired to, the exact error it last reported, and how long it has been down. Say plainly whether the platform is still retrying it or has stopped. A link that was logged out, or replaced by another device, will not come back on its own: re-pairing needs someone holding the phone, so say that rather than implying it will recover by itself.
|
|
160
162
|
|
|
161
163
|
Never disconnect a link and never begin a re-pair from here. This routine reports; the remedy is a person's decision.`;
|
|
162
|
-
|
|
164
|
+
const GRAPH_HEALTH = `Report on the state of this account's graph and on what its maintenance sweep last found. This routine reads. It performs no graph writes at all.
|
|
165
|
+
|
|
166
|
+
Call capabilities-here first. If the memory plugin is not enabled, end the turn without replying.
|
|
167
|
+
|
|
168
|
+
Read the most recent maintenance report with memory-report-read-latest: it carries the run's per-phase counts and the time it ran. Read the two review queues with memory-review-queue. Orphan candidates are nodes the sweep could not attach to anything; citation proposals are timeline claims still waiting for a source.
|
|
169
|
+
|
|
170
|
+
Report four things: when the sweep last ran, how many orphan candidates are waiting, how large the citation backlog is, and how much compiled truth the last run found stale. A queue that has grown since the previous run matters more than its absolute size, so say which direction it is moving.
|
|
171
|
+
|
|
172
|
+
Never call memory-dream-run from here. The sweep already runs on its own hourly cadence and decides for itself whether an account is due; a second writer started from a scheduled turn would race it, and the surviving report would be whichever run finished last. Reading the sweep's output is the whole of this routine's authority.
|
|
173
|
+
|
|
174
|
+
If both queues are empty and the sweep ran within the past day, end the turn without replying. Nothing is wrong and there is nothing to decide.`;
|
|
175
|
+
const FILESYSTEM_HEALTH = `Report what has accumulated under this account's own directory, so growth is visible before it becomes a problem. This routine deletes nothing.
|
|
176
|
+
|
|
177
|
+
Call capabilities-here first. If the filesystem plugin is not enabled, end the turn without replying.
|
|
178
|
+
|
|
179
|
+
Walk the account directory with file-list, starting at its root and descending only where something is already large. Use file-glob to count the things that accumulate rather than get cleaned up: uploaded files, session transcripts, generated documents, logs, and anything a plugin writes once per run.
|
|
180
|
+
|
|
181
|
+
Report the few paths worth a person's attention, each with what is in it and roughly how much. Name every path relative to the account directory, never as an absolute one. Judgement is the point: one directory holding thousands of files is worth naming, and a hundred small ones spread evenly are not.
|
|
182
|
+
|
|
183
|
+
There is no deletion tool on this surface and this routine must not ask for one. Report what grew and leave the decision with the operator: a routine that removed files on a schedule would eventually remove the one that mattered, and nothing would say which.
|
|
184
|
+
|
|
185
|
+
If nothing has grown materially since the last run, end the turn without replying.`;
|
|
186
|
+
/** The thirteen. Order is the display order on `/routines` before the operator
|
|
163
187
|
* retimes anything: the daily rhythm first, then the reconciles, then the
|
|
164
|
-
* weekly, then the standing check.
|
|
188
|
+
* weekly, then the standing check, then the two health reports.
|
|
189
|
+
*
|
|
190
|
+
* `description` is what the card shows under the title. It says what the row
|
|
191
|
+
* does and, where the row is deliberately narrower than its name suggests,
|
|
192
|
+
* what it will not do — the send it never makes, the write it never performs,
|
|
193
|
+
* the file it never deletes. That second half is the part an operator cannot
|
|
194
|
+
* infer from a title, and it is why the sentence is not just the name again. */
|
|
165
195
|
exports.ROUTINE_ROSTER = [
|
|
166
|
-
{
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
{
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
196
|
+
{
|
|
197
|
+
key: "start-of-day",
|
|
198
|
+
name: "Start of day briefing",
|
|
199
|
+
description: "Sends one morning message covering what needs a decision, what is time-bound and what changed overnight; stays silent when there is nothing worth saying.",
|
|
200
|
+
recurrence: "30 7 * * 1-5",
|
|
201
|
+
prompt: START_OF_DAY,
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
key: "inbound-check",
|
|
205
|
+
name: "Working-hours inbound check",
|
|
206
|
+
description: "Triages mail that arrived since the last check and writes replies for you to approve; it never sends anything itself.",
|
|
207
|
+
recurrence: "*/30 9-17 * * 1-5",
|
|
208
|
+
prompt: INBOUND_CHECK,
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
key: "end-of-day",
|
|
212
|
+
name: "End of day wrap-up",
|
|
213
|
+
description: "Closes the day with your unsent drafts, overdue work and tomorrow's diary; says nothing when all three are empty.",
|
|
214
|
+
recurrence: "0 18 * * 1-5",
|
|
215
|
+
prompt: END_OF_DAY,
|
|
216
|
+
},
|
|
217
|
+
{
|
|
218
|
+
key: "appointment-reminder",
|
|
219
|
+
name: "Appointment reminders",
|
|
220
|
+
description: "Reminds each attendee once before a booked appointment, on a route they already use; it never opens a conversation with a stranger.",
|
|
221
|
+
recurrence: "0 * * * *",
|
|
222
|
+
prompt: APPOINTMENT_REMINDER,
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
key: "commitment-chase",
|
|
226
|
+
name: "Commitment chase",
|
|
227
|
+
description: "Surfaces promises the business made and did not keep, and promises made to it that nobody kept; it reports them rather than chasing them.",
|
|
228
|
+
recurrence: "0 10 * * 2",
|
|
229
|
+
prompt: COMMITMENT_CHASE,
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
key: "calendar-reconcile",
|
|
233
|
+
name: "Calendar reconcile",
|
|
234
|
+
description: "Reconciles the provider calendar against the appointments held in the graph, writing what is missing and marking what was cancelled; a clean run says nothing.",
|
|
235
|
+
recurrence: "*/15 * * * *",
|
|
236
|
+
prompt: CALENDAR_RECONCILE,
|
|
237
|
+
},
|
|
238
|
+
{
|
|
239
|
+
key: "contact-reconcile",
|
|
240
|
+
name: "Contact reconcile",
|
|
241
|
+
description: "Reconciles the people you correspond with against the people on record, creating and updating contacts; it never merges two records that might be two people.",
|
|
242
|
+
recurrence: "45 6 * * 1-5",
|
|
243
|
+
prompt: CONTACT_RECONCILE,
|
|
244
|
+
},
|
|
245
|
+
{
|
|
246
|
+
key: "crm-reconcile",
|
|
247
|
+
name: "Operational system reconcile",
|
|
248
|
+
description: "Brings across what changed in whichever operational system this business runs; it reads only and never writes back to that system.",
|
|
249
|
+
recurrence: "0 3 * * *",
|
|
250
|
+
prompt: CRM_RECONCILE,
|
|
251
|
+
},
|
|
252
|
+
{
|
|
253
|
+
key: "finance-reconcile",
|
|
254
|
+
name: "Finance reconcile",
|
|
255
|
+
description: "Reconciles the accounting system against the internal ledger and reports what does not agree; it never adjusts an entry to make the two sides match.",
|
|
256
|
+
recurrence: "0 4 * * 1",
|
|
257
|
+
prompt: FINANCE_RECONCILE,
|
|
258
|
+
},
|
|
259
|
+
{
|
|
260
|
+
key: "weekly-digest",
|
|
261
|
+
name: "Weekly digest",
|
|
262
|
+
description: "Writes the week in three paragraphs at most: what changed, what is stuck, and what next week turns on.",
|
|
263
|
+
recurrence: "0 16 * * 5",
|
|
264
|
+
prompt: WEEKLY_DIGEST,
|
|
265
|
+
},
|
|
266
|
+
{
|
|
267
|
+
key: "channel-link-check",
|
|
268
|
+
name: "Channel link check",
|
|
269
|
+
description: "Reports a messaging link that has gone down and whether it can recover on its own; it never disconnects a link or starts a re-pair.",
|
|
270
|
+
recurrence: "*/15 * * * *",
|
|
271
|
+
prompt: CHANNEL_LINK_CHECK,
|
|
272
|
+
},
|
|
273
|
+
{
|
|
274
|
+
key: "graph-health",
|
|
275
|
+
name: "Graph health report",
|
|
276
|
+
description: "Reports what the hourly graph sweep last did and what is waiting for review; it reads only and never runs the sweep itself.",
|
|
277
|
+
recurrence: "0 9 * * 1",
|
|
278
|
+
prompt: GRAPH_HEALTH,
|
|
279
|
+
},
|
|
280
|
+
{
|
|
281
|
+
key: "filesystem-health",
|
|
282
|
+
name: "Filesystem health report",
|
|
283
|
+
description: "Reports what has grown under the account directory and which paths are worth attention; it deletes nothing.",
|
|
284
|
+
recurrence: "0 9 * * 1",
|
|
285
|
+
prompt: FILESYSTEM_HEALTH,
|
|
286
|
+
},
|
|
177
287
|
];
|
|
178
288
|
/** Every roster key, in roster order. The scheduling heartbeat's `op=roster`
|
|
179
289
|
* drift check reconciles this expected set against what is actually in the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"roster.js","sourceRoot":"","sources":["../src/roster.ts"],"names":[],"mappings":";AAAA
|
|
1
|
+
{"version":3,"file":"roster.js","sourceRoot":"","sources":["../src/roster.ts"],"names":[],"mappings":"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"}
|
|
@@ -37,6 +37,11 @@ const CANONICAL_TOOL_NAMES: ReadonlySet<string> = (() => {
|
|
|
37
37
|
function citedToolCandidates(prompt: string): string[] {
|
|
38
38
|
const prefixes = [
|
|
39
39
|
"email-",
|
|
40
|
+
// `file-` is here because the filesystem routine is the first row to cite
|
|
41
|
+
// the filesystem plugin. Without the prefix its two tools are collected by
|
|
42
|
+
// nothing, and the registry assertion below passes over that prompt without
|
|
43
|
+
// ever examining it — a check that reports clean while checking nothing.
|
|
44
|
+
"file-",
|
|
40
45
|
"outlook-",
|
|
41
46
|
"google-",
|
|
42
47
|
"schedule-",
|
|
@@ -60,11 +65,11 @@ function citedToolCandidates(prompt: string): string[] {
|
|
|
60
65
|
}
|
|
61
66
|
|
|
62
67
|
describe("routine roster shape", () => {
|
|
63
|
-
it("ships exactly
|
|
64
|
-
expect(ROUTINE_ROSTER).toHaveLength(
|
|
68
|
+
it("ships exactly thirteen routines", () => {
|
|
69
|
+
expect(ROUTINE_ROSTER).toHaveLength(13);
|
|
65
70
|
});
|
|
66
71
|
|
|
67
|
-
it("has the
|
|
72
|
+
it("has the thirteen keys the task and the drift check agree on", () => {
|
|
68
73
|
expect([...ROUTINE_ROSTER_KEYS].sort()).toEqual(
|
|
69
74
|
[
|
|
70
75
|
"appointment-reminder",
|
|
@@ -74,7 +79,9 @@ describe("routine roster shape", () => {
|
|
|
74
79
|
"contact-reconcile",
|
|
75
80
|
"crm-reconcile",
|
|
76
81
|
"end-of-day",
|
|
82
|
+
"filesystem-health",
|
|
77
83
|
"finance-reconcile",
|
|
84
|
+
"graph-health",
|
|
78
85
|
"inbound-check",
|
|
79
86
|
"start-of-day",
|
|
80
87
|
"weekly-digest",
|
|
@@ -104,6 +111,42 @@ describe("routine roster shape", () => {
|
|
|
104
111
|
});
|
|
105
112
|
});
|
|
106
113
|
|
|
114
|
+
describe("routine descriptions", () => {
|
|
115
|
+
// The card renders this and nothing else about what the routine does, so an
|
|
116
|
+
// empty one is a card that says only its title — the state Task 2214 exists
|
|
117
|
+
// to end. Uniqueness matters because two rows sharing a sentence means one of
|
|
118
|
+
// them was copied and never rewritten.
|
|
119
|
+
it("every routine carries a non-empty description", () => {
|
|
120
|
+
for (const r of ROUTINE_ROSTER) {
|
|
121
|
+
expect(r.description.trim(), `${r.key} description`).not.toBe("");
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
it("descriptions are unique", () => {
|
|
126
|
+
const descriptions = ROUTINE_ROSTER.map((r) => r.description);
|
|
127
|
+
expect(new Set(descriptions).size).toBe(descriptions.length);
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
it("each description is one sentence under 200 characters", () => {
|
|
131
|
+
for (const r of ROUTINE_ROSTER) {
|
|
132
|
+
expect(r.description.length, `${r.key} description length`).toBeLessThan(200);
|
|
133
|
+
expect(r.description.endsWith("."), `${r.key} must end in a full stop`).toBe(true);
|
|
134
|
+
// A second sentence wraps to a second line on a card sized for one.
|
|
135
|
+
expect(r.description.slice(0, -1), `${r.key} must be one sentence`).not.toMatch(/\.\s/);
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
it("no prompt cites the graph routine's key as though it were a tool", () => {
|
|
140
|
+
// citedToolCandidates collects `graph-`-prefixed tokens and checks them
|
|
141
|
+
// against the canonical registry. `graph-health` is a MERGE key, not a
|
|
142
|
+
// tool, so a prompt that names itself fails the registry assertion with a
|
|
143
|
+
// message pointing at the registry rather than at this mistake.
|
|
144
|
+
for (const r of ROUTINE_ROSTER) {
|
|
145
|
+
expect(r.prompt, `${r.key} must not name the graph routine's key`).not.toContain("graph-health");
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
|
|
107
150
|
describe("routine prompts resolve their own surfaces", () => {
|
|
108
151
|
it("every prompt opens on capabilities-here", () => {
|
|
109
152
|
for (const r of ROUTINE_ROSTER) {
|
|
@@ -34,7 +34,7 @@ interface FakeCall {
|
|
|
34
34
|
function fakeSession(opts: {
|
|
35
35
|
timezone?: { timezone: string; timezoneSource: string } | null;
|
|
36
36
|
merges: Array<{ key: string; eventId: string; action: RoutineMergeAction }>;
|
|
37
|
-
verify: { actual: number; suspended: number; nextRunNull: number };
|
|
37
|
+
verify: { actual: number; suspended: number; nextRunNull: number; descNull: number };
|
|
38
38
|
}): { session: SeedSessionLike; calls: FakeCall[] } {
|
|
39
39
|
const calls: FakeCall[] = [];
|
|
40
40
|
const rec = (obj: Record<string, unknown>) => ({ get: (k: string) => obj[k] });
|
|
@@ -65,7 +65,7 @@ const allCreated = ROUTINE_ROSTER.map((r) => ({
|
|
|
65
65
|
action: "create" as RoutineMergeAction,
|
|
66
66
|
}));
|
|
67
67
|
|
|
68
|
-
const cleanVerify = { actual: 10, suspended: 10, nextRunNull: 10 };
|
|
68
|
+
const cleanVerify = { actual: 10, suspended: 10, nextRunNull: 10, descNull: 0 };
|
|
69
69
|
|
|
70
70
|
describe("MERGE statement shape", () => {
|
|
71
71
|
/** The property names assigned inside a `ON CREATE SET` / `ON MATCH SET`
|
|
@@ -84,6 +84,7 @@ describe("MERGE statement shape", () => {
|
|
|
84
84
|
for (const required of [
|
|
85
85
|
"eventId",
|
|
86
86
|
"name",
|
|
87
|
+
"routineDescription",
|
|
87
88
|
"agentPrompt",
|
|
88
89
|
"recurrence",
|
|
89
90
|
"routineTemplateVersion",
|
|
@@ -118,9 +119,30 @@ describe("MERGE statement shape", () => {
|
|
|
118
119
|
expect(body).toContain("e.sourcePlugin = null");
|
|
119
120
|
});
|
|
120
121
|
|
|
121
|
-
it("ON MATCH touches ONLY the prompt, name, version and updatedAt", () => {
|
|
122
|
+
it("ON MATCH touches ONLY the prompt, name, description, version and updatedAt", () => {
|
|
122
123
|
expect(new Set(propertiesSetIn("ON MATCH SET"))).toEqual(
|
|
123
|
-
new Set(["agentPrompt", "name", "routineTemplateVersion", "updatedAt"]),
|
|
124
|
+
new Set(["agentPrompt", "name", "routineDescription", "routineTemplateVersion", "updatedAt"]),
|
|
125
|
+
);
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it("ON MATCH writes the description unconditionally, not only when refreshing", () => {
|
|
129
|
+
// Task 2214. The description is roster-owned and absent from the routines
|
|
130
|
+
// PATCH field set, so there is no operator edit for this to clobber.
|
|
131
|
+
// Gating it on `refreshing` would leave every operator-edited row without
|
|
132
|
+
// a description permanently: `skip-operator-edited` takes neither branch,
|
|
133
|
+
// so its card would show a title and nothing else, for ever.
|
|
134
|
+
const start = MERGE_CYPHER.indexOf("ON MATCH SET");
|
|
135
|
+
const body = MERGE_CYPHER.slice(start, MERGE_CYPHER.indexOf("RETURN"));
|
|
136
|
+
expect(body).toContain("e.routineDescription = row.description");
|
|
137
|
+
expect(body).not.toContain("e.routineDescription = CASE");
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
it("verify counts the descriptions the graph actually holds", () => {
|
|
141
|
+
// The failure this exists for writes nothing and reports nothing: the
|
|
142
|
+
// MERGE succeeds, every action reads `refresh-version`, and the property
|
|
143
|
+
// is simply absent. `expected` and `actual` agree in that state.
|
|
144
|
+
expect(VERIFY_CYPHER).toContain(
|
|
145
|
+
"sum(CASE WHEN e.routineDescription IS NULL THEN 1 ELSE 0 END) AS descNull",
|
|
124
146
|
);
|
|
125
147
|
});
|
|
126
148
|
|
|
@@ -211,10 +233,15 @@ describe("seedRoutineRoster", () => {
|
|
|
211
233
|
return { report, lines, calls };
|
|
212
234
|
};
|
|
213
235
|
|
|
214
|
-
it("passes every roster row to the MERGE", async () => {
|
|
236
|
+
it("passes every roster row to the MERGE, description included", async () => {
|
|
215
237
|
const { calls } = await seed();
|
|
216
238
|
const mergeCall = calls.find((c) => c.query.includes("MERGE (e:Event"))!;
|
|
217
|
-
|
|
239
|
+
const rows = mergeCall.params.rows as Array<{ key: string; description: string }>;
|
|
240
|
+
expect(rows.length).toBe(ROUTINE_ROSTER.length);
|
|
241
|
+
// The Cypher can reference `row.description` and still write NULL for every
|
|
242
|
+
// row if the mapper never puts it on the parameter. That is the shape of
|
|
243
|
+
// the no-event failure, so assert the payload, not just the statement.
|
|
244
|
+
expect(rows.every((r) => typeof r.description === "string" && r.description.length > 0)).toBe(true);
|
|
218
245
|
expect(mergeCall.params.version).toBe(ROUTINE_TEMPLATE_VERSION);
|
|
219
246
|
expect(mergeCall.params.timezone).toBe("Europe/Lisbon");
|
|
220
247
|
});
|
|
@@ -248,14 +275,29 @@ describe("seedRoutineRoster", () => {
|
|
|
248
275
|
const { report, lines } = await seed({}, {
|
|
249
276
|
timezone: { timezone: "Europe/Lisbon", timezoneSource: "owner-set" },
|
|
250
277
|
merges: allUnchanged,
|
|
251
|
-
verify: { actual: short, suspended: short, nextRunNull: short },
|
|
278
|
+
verify: { actual: short, suspended: short, nextRunNull: short, descNull: 0 },
|
|
252
279
|
});
|
|
253
|
-
expect(report.verify).toEqual({ expected, actual: short, suspended: short, nextRunNull: short });
|
|
280
|
+
expect(report.verify).toEqual({ expected, actual: short, suspended: short, nextRunNull: short, descNull: 0 });
|
|
254
281
|
expect(lines).toContainEqual(
|
|
255
|
-
`[routine-seed] op=verify acct=abcd1234 expected=${expected} actual=${short} suspended=${short} nextRunNull=${short}`,
|
|
282
|
+
`[routine-seed] op=verify acct=abcd1234 expected=${expected} actual=${short} suspended=${short} nextRunNull=${short} descNull=0`,
|
|
256
283
|
);
|
|
257
284
|
});
|
|
258
285
|
|
|
286
|
+
it("reports a description that never landed, rather than reporting a healthy seed", async () => {
|
|
287
|
+
// Task 2214's no-event failure. Every action reads `unchanged`, expected
|
|
288
|
+
// and actual agree, and the only line that moves is this one — which is
|
|
289
|
+
// why it is measured back out of the graph rather than counted from the
|
|
290
|
+
// statements the seed issued.
|
|
291
|
+
const full = ROUTINE_ROSTER.length;
|
|
292
|
+
const { report, lines } = await seed({}, {
|
|
293
|
+
timezone: null,
|
|
294
|
+
merges: allUnchanged,
|
|
295
|
+
verify: { actual: full, suspended: full, nextRunNull: full, descNull: 3 },
|
|
296
|
+
});
|
|
297
|
+
expect(report.verify.descNull).toBe(3);
|
|
298
|
+
expect(lines.find((l) => l.includes("op=verify"))).toContain("descNull=3");
|
|
299
|
+
});
|
|
300
|
+
|
|
259
301
|
it("logs tz-resolved as null when no owner-set profile exists", async () => {
|
|
260
302
|
const { lines } = await seed({}, { timezone: null, merges: allUnchanged, verify: cleanVerify });
|
|
261
303
|
expect(lines).toContainEqual("[routine-seed] op=tz-resolved acct=abcd1234 tz=null source=absent");
|
|
@@ -271,7 +313,7 @@ describe("seedRoutineRoster", () => {
|
|
|
271
313
|
const { report } = await seed({}, {
|
|
272
314
|
timezone: null,
|
|
273
315
|
merges: mixed,
|
|
274
|
-
verify: { actual: 4, suspended: 3, nextRunNull: 3 },
|
|
316
|
+
verify: { actual: 4, suspended: 3, nextRunNull: 3, descNull: 0 },
|
|
275
317
|
});
|
|
276
318
|
expect(report.created).toBe(1);
|
|
277
319
|
expect(report.refreshed).toBe(1);
|
|
@@ -71,6 +71,14 @@ export interface RoutineVerifyCounts {
|
|
|
71
71
|
actual: number;
|
|
72
72
|
suspended: number;
|
|
73
73
|
nextRunNull: number;
|
|
74
|
+
/** Task 2214 — roster rows holding no description. Zero is the healthy value
|
|
75
|
+
* on every account, not only a fresh one: `VERIFY_CYPHER` matches
|
|
76
|
+
* `routineTemplate IS NOT NULL`, so operator-created routines are outside
|
|
77
|
+
* its scope and cannot contribute, and `ON MATCH` writes the description
|
|
78
|
+
* unconditionally, so an operator-edited row is covered too. Anything above
|
|
79
|
+
* zero while `expected === actual` is a MERGE that wrote no description —
|
|
80
|
+
* the one failure here that emits no error and does not reproduce. */
|
|
81
|
+
descNull: number;
|
|
74
82
|
}
|
|
75
83
|
|
|
76
84
|
export interface RoutineSeedReport {
|
|
@@ -144,7 +152,15 @@ export async function resolveOwnerTimezone(
|
|
|
144
152
|
* `agentChannel`, not `agentDestination`, not `recurrence`, not `timezone`. A
|
|
145
153
|
* re-seed on upgrade must not re-suspend an enabled routine, unbind a bound
|
|
146
154
|
* destination, or reset a retimed cron. Only the prompt, the name and the
|
|
147
|
-
* version move, and only when the row is behind and unedited.
|
|
155
|
+
* version move, and only when the row is behind and unedited.
|
|
156
|
+
*
|
|
157
|
+
* `routineDescription` (Task 2214) is the one property ON MATCH writes on
|
|
158
|
+
* every match rather than only on the refresh branch, and that is not an
|
|
159
|
+
* exception to the rule above. It is roster-owned: the routines route projects
|
|
160
|
+
* it but its PATCH field set refuses it, so no operator edit exists for this
|
|
161
|
+
* to overwrite. Gating it on `refreshing` would leave every operator-edited
|
|
162
|
+
* row description-less permanently, because `skip-operator-edited` takes
|
|
163
|
+
* neither branch, and that row's card would show a title and nothing else. */
|
|
148
164
|
export const MERGE_CYPHER = `
|
|
149
165
|
UNWIND $rows AS row
|
|
150
166
|
OPTIONAL MATCH (pre:Event {accountId: $accountId, routineTemplate: row.key})
|
|
@@ -157,6 +173,7 @@ WITH row, existed, priorVersion, edited,
|
|
|
157
173
|
MERGE (e:Event {accountId: $accountId, routineTemplate: row.key})
|
|
158
174
|
ON CREATE SET e.eventId = randomUUID(),
|
|
159
175
|
e.name = row.name,
|
|
176
|
+
e.routineDescription = row.description,
|
|
160
177
|
e.agentPrompt = row.prompt,
|
|
161
178
|
e.recurrence = row.recurrence,
|
|
162
179
|
e.routineTemplateVersion = $version,
|
|
@@ -176,6 +193,7 @@ MERGE (e:Event {accountId: $accountId, routineTemplate: row.key})
|
|
|
176
193
|
e.updatedAt = $now
|
|
177
194
|
ON MATCH SET e.agentPrompt = CASE WHEN refreshing THEN row.prompt ELSE e.agentPrompt END,
|
|
178
195
|
e.name = CASE WHEN refreshing THEN row.name ELSE e.name END,
|
|
196
|
+
e.routineDescription = row.description,
|
|
179
197
|
e.routineTemplateVersion = CASE WHEN refreshing THEN $version ELSE e.routineTemplateVersion END,
|
|
180
198
|
e.updatedAt = CASE WHEN refreshing THEN $now ELSE e.updatedAt END
|
|
181
199
|
RETURN row.key AS key,
|
|
@@ -192,7 +210,8 @@ MATCH (e:Event {accountId: $accountId})
|
|
|
192
210
|
WHERE e.routineTemplate IS NOT NULL
|
|
193
211
|
RETURN count(e) AS actual,
|
|
194
212
|
sum(CASE WHEN e.eventStatus = 'suspended' THEN 1 ELSE 0 END) AS suspended,
|
|
195
|
-
sum(CASE WHEN e.nextRun IS NULL THEN 1 ELSE 0 END) AS nextRunNull
|
|
213
|
+
sum(CASE WHEN e.nextRun IS NULL THEN 1 ELSE 0 END) AS nextRunNull,
|
|
214
|
+
sum(CASE WHEN e.routineDescription IS NULL THEN 1 ELSE 0 END) AS descNull`;
|
|
196
215
|
|
|
197
216
|
export interface SeedRoutineRosterArgs {
|
|
198
217
|
session: SeedSessionLike;
|
|
@@ -246,7 +265,13 @@ export async function seedRoutineRoster(args: SeedRoutineRosterArgs): Promise<Ro
|
|
|
246
265
|
version,
|
|
247
266
|
timezone,
|
|
248
267
|
now,
|
|
249
|
-
rows: roster.map((r) => ({
|
|
268
|
+
rows: roster.map((r) => ({
|
|
269
|
+
key: r.key,
|
|
270
|
+
name: r.name,
|
|
271
|
+
description: r.description,
|
|
272
|
+
prompt: r.prompt,
|
|
273
|
+
recurrence: r.recurrence,
|
|
274
|
+
})),
|
|
250
275
|
});
|
|
251
276
|
|
|
252
277
|
const merges: RoutineMergeRow[] = mergeRes.records.map((rec) => ({
|
|
@@ -266,10 +291,11 @@ export async function seedRoutineRoster(args: SeedRoutineRosterArgs): Promise<Ro
|
|
|
266
291
|
actual: toInt(verifyRec?.get("actual")),
|
|
267
292
|
suspended: toInt(verifyRec?.get("suspended")),
|
|
268
293
|
nextRunNull: toInt(verifyRec?.get("nextRunNull")),
|
|
294
|
+
descNull: toInt(verifyRec?.get("descNull")),
|
|
269
295
|
};
|
|
270
296
|
log(
|
|
271
297
|
`[routine-seed] op=verify acct=${acct} expected=${verify.expected} actual=${verify.actual} ` +
|
|
272
|
-
`suspended=${verify.suspended} nextRunNull=${verify.nextRunNull}`,
|
|
298
|
+
`suspended=${verify.suspended} nextRunNull=${verify.nextRunNull} descNull=${verify.descNull}`,
|
|
273
299
|
);
|
|
274
300
|
|
|
275
301
|
const created = merges.filter((m) => m.action === "create").length;
|