@rubytech/create-sitedesk-code 0.1.522 → 0.1.523
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/package.json +1 -1
- package/payload/platform/lib/graph-style/dist/index.d.ts.map +1 -1
- package/payload/platform/lib/graph-style/dist/index.js +28 -0
- package/payload/platform/lib/graph-style/dist/index.js.map +1 -1
- package/payload/platform/lib/graph-style/src/__tests__/caption-coverage.test.ts +7 -0
- package/payload/platform/lib/graph-style/src/index.ts +24 -0
- package/payload/platform/lib/graph-write/dist/__tests__/merge-on.test.d.ts.map +1 -0
- package/payload/platform/lib/graph-write/dist/__tests__/merge-on.test.js.map +1 -0
- package/payload/platform/lib/graph-write/dist/index.d.ts +16 -0
- package/payload/platform/lib/graph-write/dist/index.d.ts.map +1 -1
- package/payload/platform/lib/graph-write/dist/index.js +83 -6
- package/payload/platform/lib/graph-write/dist/index.js.map +1 -1
- package/payload/platform/lib/graph-write/src/index.ts +117 -10
- package/payload/platform/lib/routine-templates/dist/index.d.ts +151 -0
- package/payload/platform/lib/routine-templates/dist/index.d.ts.map +1 -0
- package/payload/platform/lib/routine-templates/dist/index.js +207 -0
- package/payload/platform/lib/routine-templates/dist/index.js.map +1 -0
- package/payload/platform/lib/routine-templates/dist/roster.d.ts +57 -0
- package/payload/platform/lib/routine-templates/dist/roster.d.ts.map +1 -0
- package/payload/platform/lib/routine-templates/dist/roster.js +182 -0
- package/payload/platform/lib/routine-templates/dist/roster.js.map +1 -0
- package/payload/platform/lib/routine-templates/dist/seed-cli.d.ts +2 -0
- package/payload/platform/lib/routine-templates/dist/seed-cli.d.ts.map +1 -0
- package/payload/platform/lib/routine-templates/dist/seed-cli.js +64 -0
- package/payload/platform/lib/routine-templates/dist/seed-cli.js.map +1 -0
- package/payload/platform/lib/routine-templates/package.json +6 -0
- package/payload/platform/lib/routine-templates/src/__tests__/roster.test.ts +170 -0
- package/payload/platform/lib/routine-templates/src/__tests__/seed.test.ts +298 -0
- package/payload/platform/lib/routine-templates/src/index.ts +299 -0
- package/payload/platform/lib/routine-templates/src/roster.ts +206 -0
- package/payload/platform/lib/routine-templates/src/seed-cli.ts +65 -0
- package/payload/platform/lib/routine-templates/tsconfig.json +9 -0
- package/payload/platform/lib/routine-templates/vitest.config.ts +9 -0
- package/payload/platform/neo4j/edge-annotations.json +2 -2
- package/payload/platform/neo4j/schema.cypher +25 -1
- package/payload/platform/package.json +3 -2
- package/payload/platform/plugins/admin/PLUGIN.md +2 -2
- package/payload/platform/plugins/admin/mcp/dist/index.js +39 -1
- package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +277 -61
- package/payload/platform/plugins/admin/skills/whats-new/SKILL.md +6 -0
- package/payload/platform/plugins/docs/references/admin-ui.md +265 -59
- package/payload/platform/plugins/docs/references/memory-guide.md +11 -1
- package/payload/platform/plugins/graph/.claude-plugin/plugin.json +1 -1
- package/payload/platform/plugins/graph/PLUGIN.md +1 -1
- package/payload/platform/plugins/memory/PLUGIN.md +1 -1
- package/payload/platform/plugins/memory/mcp/dist/index.js +12 -5
- package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/phase-estate-census.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/phase-estate-census.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/phase-estate-census.test.js +197 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/phase-estate-census.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-loader.test.js +55 -9
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-loader.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-validator.test.js +96 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-validator.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/index.d.ts +7 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/index.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-estate-census.d.ts +29 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-estate-census.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-estate-census.js +126 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/dream-cycle/phase-estate-census.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/scripts/dream-cycle-sweep.js +7 -4
- package/payload/platform/plugins/memory/mcp/dist/scripts/dream-cycle-sweep.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-dream-run.d.ts +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-dream-run.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-dream-run.js +18 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-dream-run.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.d.ts +7 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.js +4 -3
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/vitest.config.ts +2 -0
- package/payload/platform/plugins/memory/references/schema-estate-agent.md +2 -2
- package/payload/platform/plugins/memory/skills/conversation-archive-enrich/SKILL.md +4 -4
- package/payload/platform/plugins/quickbooks/PLUGIN.md +10 -10
- package/payload/platform/plugins/scheduling/PLUGIN.md +49 -1
- package/payload/platform/plugins/scheduling/mcp/dist/index.js +48 -0
- package/payload/platform/plugins/scheduling/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/notes-cap.test.d.ts +2 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/notes-cap.test.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/notes-cap.test.js +78 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/notes-cap.test.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/routine-run.test.d.ts +2 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/routine-run.test.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/routine-run.test.js +457 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/__tests__/routine-run.test.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/notes-cap.d.ts +35 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/notes-cap.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/notes-cap.js +39 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/notes-cap.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/routine-run.d.ts +175 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/routine-run.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/routine-run.js +533 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/routine-run.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/agent-turn-dispatch.test.js +123 -9
- 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__/routine-roster-audit.test.d.ts +2 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/routine-roster-audit.test.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/routine-roster-audit.test.js +189 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/routine-roster-audit.test.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/suspension-census.test.d.ts +2 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/suspension-census.test.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/suspension-census.test.js +95 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/suspension-census.test.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/sweep-excludes-suspended.test.d.ts +2 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/sweep-excludes-suspended.test.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/sweep-excludes-suspended.test.js +114 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/__tests__/sweep-excludes-suspended.test.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/agent-turn-dispatch.d.ts +109 -2
- 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 +340 -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.d.ts +9 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.js +210 -45
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/reconcile-bookings.js +43 -1
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/reconcile-bookings.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-get-agent.test.js +55 -7
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-get-agent.test.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-list.test.js +45 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-list.test.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-runs.test.d.ts +2 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-runs.test.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-runs.test.js +96 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/__tests__/schedule-runs.test.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-cancel.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-cancel.js +2 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-cancel.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-get.d.ts +5 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-get.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-get.js +13 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-get.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-list.d.ts +4 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-list.d.ts.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-list.js +24 -3
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-list.js.map +1 -1
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-runs.d.ts +33 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-runs.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-runs.js +51 -0
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-runs.js.map +1 -0
- 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 +12 -2
- package/payload/platform/plugins/scheduling/mcp/dist/tools/schedule-update.js.map +1 -1
- package/payload/platform/plugins/whatsapp/references/channels-whatsapp.md +30 -2
- package/payload/platform/plugins/whatsapp/skills/connect-whatsapp/SKILL.md +1 -1
- package/payload/platform/scripts/check-specialist-tool-surface.mjs +92 -16
- package/payload/platform/scripts/seed-neo4j.sh +41 -0
- package/payload/platform/scripts/verify-skill-tool-surface.sh +91 -2
- 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/platform/templates/specialists/agents/librarian.md +1 -1
- package/payload/platform/templates/specialists/agents/personal-assistant.md +1 -1
- package/payload/server/{chunk-K7CJGZPU.js → chunk-VUXKXOJU.js} +342 -152
- package/payload/server/{chunk-UX2FRNO7.js → chunk-WT2PFGY4.js} +37 -265
- package/payload/server/{chunk-PXNY2TAP.js → chunk-XCR5D2G3.js} +239 -10
- package/payload/server/{manager-RKL7JZ4Y.js → manager-4TJK3YOY.js} +2 -2
- package/payload/server/maxy-edge.js +2 -2
- package/payload/server/public/activity.html +5 -5
- package/payload/server/public/agents.html +4 -4
- package/payload/server/public/assets/{AdminLoginScreens-zc2_qqh-.js → AdminLoginScreens-uknqh2Pm.js} +1 -1
- package/payload/server/public/assets/AdminLoginScreens-uknqh2Pm.js.br +0 -0
- package/payload/server/public/assets/AdminLoginScreens-uknqh2Pm.js.gz +0 -0
- package/payload/server/public/assets/AdminShell-GqtMImyQ.js +2 -0
- package/payload/server/public/assets/AdminShell-GqtMImyQ.js.br +0 -0
- package/payload/server/public/assets/AdminShell-GqtMImyQ.js.gz +0 -0
- package/payload/server/public/assets/{activity-DVgO8YuM.js → activity-B4KfMJqO.js} +1 -1
- package/payload/server/public/assets/activity-B4KfMJqO.js.br +0 -0
- package/payload/server/public/assets/activity-B4KfMJqO.js.gz +0 -0
- package/payload/server/public/assets/admin-DxCZeVw0.js +1 -0
- package/payload/server/public/assets/admin-DxCZeVw0.js.br +0 -0
- package/payload/server/public/assets/admin-DxCZeVw0.js.gz +0 -0
- package/payload/server/public/assets/agents-BtwBuO4G.js +1 -0
- package/payload/server/public/assets/agents-BtwBuO4G.js.br +0 -0
- package/payload/server/public/assets/agents-BtwBuO4G.js.gz +0 -0
- package/payload/server/public/assets/{browser-Mw7DY3ft.js → browser-B3hSzI3O.js} +1 -1
- package/payload/server/public/assets/browser-B3hSzI3O.js.br +0 -0
- package/payload/server/public/assets/browser-B3hSzI3O.js.gz +0 -0
- package/payload/server/public/assets/{calendar-B9gvL_1_.js → calendar-BggxXxhS.js} +1 -1
- package/payload/server/public/assets/calendar-BggxXxhS.js.br +0 -0
- package/payload/server/public/assets/calendar-BggxXxhS.js.gz +0 -0
- package/payload/server/public/assets/chat-flivHt0t.js +1 -0
- package/payload/server/public/assets/chat-flivHt0t.js.br +0 -0
- package/payload/server/public/assets/chat-flivHt0t.js.gz +0 -0
- package/payload/server/public/assets/chevron-left-nVRThX7f.js +1 -0
- package/payload/server/public/assets/chevron-right-CLqfrkRA.js +1 -0
- package/payload/server/public/assets/chevron-right-CLqfrkRA.js.br +0 -0
- package/payload/server/public/assets/clock-Dj3SRZKo.js +1 -0
- package/payload/server/public/assets/clock-Dj3SRZKo.js.br +0 -0
- package/payload/server/public/assets/clock-Dj3SRZKo.js.gz +0 -0
- package/payload/server/public/assets/data-Ckjkne54.js +1 -0
- package/payload/server/public/assets/data-Ckjkne54.js.br +3 -0
- package/payload/server/public/assets/data-Ckjkne54.js.gz +0 -0
- package/payload/server/public/assets/{file-text-dYBnXNEX.js → file-text-BKs9eyiw.js} +1 -1
- package/payload/server/public/assets/file-text-BKs9eyiw.js.br +0 -0
- package/payload/server/public/assets/file-text-BKs9eyiw.js.gz +0 -0
- package/payload/server/public/assets/{graph-CDyzd1Et.js → graph-DTi71NaZ.js} +3 -3
- package/payload/server/public/assets/graph-DTi71NaZ.js.br +0 -0
- package/payload/server/public/assets/graph-DTi71NaZ.js.gz +0 -0
- package/payload/server/public/assets/graph-labels-BT3S6e9H.js +1 -0
- package/payload/server/public/assets/graph-labels-BT3S6e9H.js.br +0 -0
- package/payload/server/public/assets/graph-labels-BT3S6e9H.js.gz +0 -0
- package/payload/server/public/assets/{maximize-2-M-iSaznd.js → maximize-2-zC94tsxY.js} +1 -1
- package/payload/server/public/assets/maximize-2-zC94tsxY.js.br +0 -0
- package/payload/server/public/assets/maximize-2-zC94tsxY.js.gz +0 -0
- package/payload/server/public/assets/operator-BtWNEMh-.js +1 -0
- package/payload/server/public/assets/operator-BtWNEMh-.js.br +0 -0
- package/payload/server/public/assets/operator-BtWNEMh-.js.gz +0 -0
- package/payload/server/public/assets/page-BFm91p0e.js +1 -0
- package/payload/server/public/assets/page-BFm91p0e.js.br +0 -0
- package/payload/server/public/assets/page-BFm91p0e.js.gz +0 -0
- package/payload/server/public/assets/{page-CZ-73FAk.js → page-Ccl0FazM.js} +3 -3
- package/payload/server/public/assets/page-Ccl0FazM.js.br +0 -0
- package/payload/server/public/assets/page-Ccl0FazM.js.gz +0 -0
- package/payload/server/public/assets/{public-CN-ltC8x.js → public-BpC6cn9S.js} +1 -1
- package/payload/server/public/assets/public-BpC6cn9S.js.br +0 -0
- package/payload/server/public/assets/public-BpC6cn9S.js.gz +0 -0
- package/payload/server/public/assets/{rotate-ccw-Buopsc22.js → rotate-ccw-BNcqbHkZ.js} +1 -1
- package/payload/server/public/assets/rotate-ccw-BNcqbHkZ.js.br +0 -0
- package/payload/server/public/assets/rotate-ccw-BNcqbHkZ.js.gz +0 -0
- package/payload/server/public/assets/routines-D5iia-XG.js +1 -0
- package/payload/server/public/assets/routines-D5iia-XG.js.br +0 -0
- package/payload/server/public/assets/routines-D5iia-XG.js.gz +0 -0
- package/payload/server/public/assets/{skills-DiiuVzDK.js → skills-COLAw_jt.js} +1 -1
- package/payload/server/public/assets/skills-COLAw_jt.js.br +0 -0
- package/payload/server/public/assets/skills-COLAw_jt.js.gz +0 -0
- package/payload/server/public/assets/tasks-CZDQI4nB.js +1 -0
- package/payload/server/public/assets/tasks-CZDQI4nB.js.br +0 -0
- package/payload/server/public/assets/tasks-CZDQI4nB.js.gz +0 -0
- package/payload/server/public/assets/{time-entry-format-BBokCF-D.js → time-entry-format-laTFzawg.js} +1 -1
- package/payload/server/public/assets/time-entry-format-laTFzawg.js.br +0 -0
- package/payload/server/public/assets/time-entry-format-laTFzawg.js.gz +0 -0
- package/payload/server/public/assets/{triangle-alert-C_AcpTW5.js → triangle-alert-DrwqhEog.js} +1 -1
- package/payload/server/public/assets/triangle-alert-DrwqhEog.js.br +0 -0
- package/payload/server/public/assets/triangle-alert-DrwqhEog.js.gz +0 -0
- package/payload/server/public/assets/{useCopyFeedback-TdimmPVR.js → useCopyFeedback-Cxme5GK6.js} +1 -1
- package/payload/server/public/assets/useCopyFeedback-Cxme5GK6.js.br +0 -0
- package/payload/server/public/assets/useCopyFeedback-Cxme5GK6.js.gz +0 -0
- package/payload/server/public/assets/useSubAccountSwitcher-B-K8y5a4.css +1 -0
- package/payload/server/public/assets/useSubAccountSwitcher-B-K8y5a4.css.br +0 -0
- package/payload/server/public/assets/useSubAccountSwitcher-B-K8y5a4.css.gz +0 -0
- package/payload/server/public/assets/useSubAccountSwitcher-C_1E11Dv.js +14 -0
- package/payload/server/public/assets/useSubAccountSwitcher-C_1E11Dv.js.br +0 -0
- package/payload/server/public/assets/useSubAccountSwitcher-C_1E11Dv.js.gz +0 -0
- package/payload/server/public/assets/{useVoiceRecorder-BT2738ZS.js → useVoiceRecorder-DUBpVa2T.js} +1 -1
- package/payload/server/public/assets/useVoiceRecorder-DUBpVa2T.js.br +0 -0
- package/payload/server/public/assets/useVoiceRecorder-DUBpVa2T.js.gz +0 -0
- package/payload/server/public/assets/{wrench-B51s5kGA.js → wrench-DWuxPnzF.js} +1 -1
- package/payload/server/public/assets/wrench-DWuxPnzF.js.br +0 -0
- package/payload/server/public/assets/wrench-DWuxPnzF.js.gz +0 -0
- package/payload/server/public/browser.html +4 -4
- package/payload/server/public/calendar.html +7 -7
- 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 +5910 -5369
- package/payload/server/public/assets/AdminLoginScreens-zc2_qqh-.js.br +0 -0
- package/payload/server/public/assets/AdminLoginScreens-zc2_qqh-.js.gz +0 -0
- package/payload/server/public/assets/AdminShell-IGUdTx5q.js +0 -2
- package/payload/server/public/assets/AdminShell-IGUdTx5q.js.br +0 -0
- package/payload/server/public/assets/AdminShell-IGUdTx5q.js.gz +0 -0
- package/payload/server/public/assets/activity-DVgO8YuM.js.br +0 -0
- package/payload/server/public/assets/activity-DVgO8YuM.js.gz +0 -0
- package/payload/server/public/assets/admin-xtpM7fgl.js +0 -1
- package/payload/server/public/assets/admin-xtpM7fgl.js.br +0 -0
- package/payload/server/public/assets/admin-xtpM7fgl.js.gz +0 -0
- package/payload/server/public/assets/agents-P0nTIxo-.js +0 -1
- package/payload/server/public/assets/agents-P0nTIxo-.js.br +0 -0
- package/payload/server/public/assets/agents-P0nTIxo-.js.gz +0 -0
- package/payload/server/public/assets/browser-Mw7DY3ft.js.br +0 -0
- package/payload/server/public/assets/browser-Mw7DY3ft.js.gz +0 -0
- package/payload/server/public/assets/calendar-B9gvL_1_.js.br +0 -0
- package/payload/server/public/assets/calendar-B9gvL_1_.js.gz +0 -0
- package/payload/server/public/assets/chat-DBGqh4wg.js +0 -1
- package/payload/server/public/assets/chat-DBGqh4wg.js.br +0 -2
- package/payload/server/public/assets/chat-DBGqh4wg.js.gz +0 -0
- package/payload/server/public/assets/chevron-left-Bl4vpOM0.js +0 -1
- package/payload/server/public/assets/chevron-left-Bl4vpOM0.js.br +0 -0
- package/payload/server/public/assets/chevron-right-BExigCnp.js +0 -1
- package/payload/server/public/assets/chevron-right-BExigCnp.js.br +0 -0
- package/payload/server/public/assets/clock-D8TJvgJC.js +0 -1
- package/payload/server/public/assets/clock-D8TJvgJC.js.br +0 -0
- package/payload/server/public/assets/data-HfFSxaC2.js +0 -1
- package/payload/server/public/assets/data-HfFSxaC2.js.br +0 -0
- package/payload/server/public/assets/data-HfFSxaC2.js.gz +0 -0
- package/payload/server/public/assets/file-text-dYBnXNEX.js.br +0 -0
- package/payload/server/public/assets/file-text-dYBnXNEX.js.gz +0 -0
- package/payload/server/public/assets/graph-CDyzd1Et.js.br +0 -0
- package/payload/server/public/assets/graph-CDyzd1Et.js.gz +0 -0
- package/payload/server/public/assets/graph-labels-D1LkKiJr.js +0 -1
- package/payload/server/public/assets/graph-labels-D1LkKiJr.js.br +0 -0
- package/payload/server/public/assets/graph-labels-D1LkKiJr.js.gz +0 -0
- package/payload/server/public/assets/maximize-2-M-iSaznd.js.br +0 -0
- package/payload/server/public/assets/maximize-2-M-iSaznd.js.gz +0 -0
- package/payload/server/public/assets/operator-9jfCv1Fg.js +0 -1
- package/payload/server/public/assets/operator-9jfCv1Fg.js.br +0 -0
- package/payload/server/public/assets/operator-9jfCv1Fg.js.gz +0 -0
- package/payload/server/public/assets/page-CZ-73FAk.js.br +0 -0
- package/payload/server/public/assets/page-CZ-73FAk.js.gz +0 -0
- package/payload/server/public/assets/page-CjwSt7kx.js +0 -1
- package/payload/server/public/assets/page-CjwSt7kx.js.br +0 -0
- package/payload/server/public/assets/page-CjwSt7kx.js.gz +0 -0
- package/payload/server/public/assets/public-CN-ltC8x.js.br +0 -0
- package/payload/server/public/assets/public-CN-ltC8x.js.gz +0 -0
- package/payload/server/public/assets/rotate-ccw-Buopsc22.js.br +0 -0
- package/payload/server/public/assets/rotate-ccw-Buopsc22.js.gz +0 -0
- package/payload/server/public/assets/routines-C-yr8ddT.js +0 -1
- package/payload/server/public/assets/routines-C-yr8ddT.js.br +0 -0
- package/payload/server/public/assets/routines-C-yr8ddT.js.gz +0 -0
- package/payload/server/public/assets/skills-DiiuVzDK.js.br +0 -0
- package/payload/server/public/assets/skills-DiiuVzDK.js.gz +0 -0
- package/payload/server/public/assets/tasks-CnHIfn2_.js +0 -1
- package/payload/server/public/assets/tasks-CnHIfn2_.js.br +0 -0
- package/payload/server/public/assets/tasks-CnHIfn2_.js.gz +0 -0
- package/payload/server/public/assets/time-entry-format-BBokCF-D.js.br +0 -0
- package/payload/server/public/assets/time-entry-format-BBokCF-D.js.gz +0 -0
- package/payload/server/public/assets/triangle-alert-C_AcpTW5.js.br +0 -0
- package/payload/server/public/assets/triangle-alert-C_AcpTW5.js.gz +0 -0
- package/payload/server/public/assets/useCopyFeedback-TdimmPVR.js.br +0 -0
- package/payload/server/public/assets/useCopyFeedback-TdimmPVR.js.gz +0 -0
- package/payload/server/public/assets/useSubAccountSwitcher-BwHqV55p.js +0 -14
- package/payload/server/public/assets/useSubAccountSwitcher-BwHqV55p.js.br +0 -0
- package/payload/server/public/assets/useSubAccountSwitcher-BwHqV55p.js.gz +0 -0
- package/payload/server/public/assets/useSubAccountSwitcher-CsrPYqtm.css +0 -1
- package/payload/server/public/assets/useSubAccountSwitcher-CsrPYqtm.css.br +0 -0
- package/payload/server/public/assets/useSubAccountSwitcher-CsrPYqtm.css.gz +0 -0
- package/payload/server/public/assets/useVoiceRecorder-BT2738ZS.js.br +0 -0
- package/payload/server/public/assets/useVoiceRecorder-BT2738ZS.js.gz +0 -0
- package/payload/server/public/assets/wrench-B51s5kGA.js.br +0 -0
- package/payload/server/public/assets/wrench-B51s5kGA.js.gz +0 -0
|
@@ -0,0 +1,457 @@
|
|
|
1
|
+
import { describe, it, expect, vi } from "vitest";
|
|
2
|
+
import { mkdtempSync, writeFileSync, rmSync } from "node:fs";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { openRoutineRun, closeRoutineRun, recordRunSession, promoteRoutineRuns, sweepRoutineRuns, auditRunOrphans, auditFiresWithoutRecords, auditRunCensus, RETENTION_DAYS, ORPHAN_AFTER_MS, readTranscriptTail, classifyRunEvidence, } from "../routine-run.js";
|
|
6
|
+
function fakeDriver() {
|
|
7
|
+
const runs = [];
|
|
8
|
+
return {
|
|
9
|
+
runs,
|
|
10
|
+
session: () => ({
|
|
11
|
+
run: vi.fn(async (query, params) => {
|
|
12
|
+
runs.push({ query, params });
|
|
13
|
+
return { records: [] };
|
|
14
|
+
}),
|
|
15
|
+
close: vi.fn(async () => { }),
|
|
16
|
+
}),
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
describe("openRoutineRun", () => {
|
|
20
|
+
it("creates a RoutineRun linked to its Event and returns the runId", async () => {
|
|
21
|
+
const driver = fakeDriver();
|
|
22
|
+
const runId = await openRoutineRun(driver, {
|
|
23
|
+
eventId: "evt-1",
|
|
24
|
+
accountId: "acct-1",
|
|
25
|
+
kind: "recurring",
|
|
26
|
+
mode: "agent",
|
|
27
|
+
target: "whatsapp:+15550000000",
|
|
28
|
+
scheduledFor: "2026-07-29T09:00:00.000Z",
|
|
29
|
+
});
|
|
30
|
+
expect(runId).toMatch(/^[0-9a-f-]{36}$/);
|
|
31
|
+
expect(driver.runs).toHaveLength(1);
|
|
32
|
+
expect(driver.runs[0].query).toContain("CREATE (r:RoutineRun $props)");
|
|
33
|
+
expect(driver.runs[0].query).toContain("CREATE (r)-[:RUN_OF]->(e)");
|
|
34
|
+
const props = driver.runs[0].params.props;
|
|
35
|
+
expect(props).toMatchObject({
|
|
36
|
+
runId,
|
|
37
|
+
eventId: "evt-1",
|
|
38
|
+
accountId: "acct-1",
|
|
39
|
+
kind: "recurring",
|
|
40
|
+
mode: "agent",
|
|
41
|
+
status: "open",
|
|
42
|
+
target: "whatsapp:+15550000000",
|
|
43
|
+
scheduledFor: "2026-07-29T09:00:00.000Z",
|
|
44
|
+
bounded: false,
|
|
45
|
+
});
|
|
46
|
+
expect(typeof props.startedAt).toBe("string");
|
|
47
|
+
});
|
|
48
|
+
it("returns null and never throws when the write fails", async () => {
|
|
49
|
+
const driver = {
|
|
50
|
+
session: () => ({
|
|
51
|
+
run: vi.fn(async () => {
|
|
52
|
+
throw new Error("neo4j down");
|
|
53
|
+
}),
|
|
54
|
+
close: vi.fn(async () => { }),
|
|
55
|
+
}),
|
|
56
|
+
};
|
|
57
|
+
const runId = await openRoutineRun(driver, {
|
|
58
|
+
eventId: "evt-1",
|
|
59
|
+
accountId: "acct-1",
|
|
60
|
+
kind: "one-time",
|
|
61
|
+
mode: "none",
|
|
62
|
+
target: "-",
|
|
63
|
+
scheduledFor: "2026-07-29T09:00:00.000Z",
|
|
64
|
+
});
|
|
65
|
+
expect(runId).toBeNull();
|
|
66
|
+
});
|
|
67
|
+
it("two opens for one event produce two distinct runIds", async () => {
|
|
68
|
+
const driver = fakeDriver();
|
|
69
|
+
const input = {
|
|
70
|
+
eventId: "evt-1",
|
|
71
|
+
accountId: "acct-1",
|
|
72
|
+
kind: "recurring",
|
|
73
|
+
mode: "agent",
|
|
74
|
+
target: "whatsapp:+15550000000",
|
|
75
|
+
scheduledFor: "2026-07-29T09:00:00.000Z",
|
|
76
|
+
};
|
|
77
|
+
const a = await openRoutineRun(driver, input);
|
|
78
|
+
const b = await openRoutineRun(driver, input);
|
|
79
|
+
expect(a).not.toBe(b);
|
|
80
|
+
expect(driver.runs).toHaveLength(2);
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
describe("closeRoutineRun", () => {
|
|
84
|
+
it("sets the outcome, endedAt and a measured ranMs", async () => {
|
|
85
|
+
const driver = fakeDriver();
|
|
86
|
+
await closeRoutineRun(driver, "run-1", {
|
|
87
|
+
outcome: "accepted",
|
|
88
|
+
dispatchResult: "accepted",
|
|
89
|
+
httpStatus: 200,
|
|
90
|
+
});
|
|
91
|
+
expect(driver.runs).toHaveLength(1);
|
|
92
|
+
const q = driver.runs[0].query;
|
|
93
|
+
expect(q).toContain("MATCH (r:RoutineRun {runId: $runId})");
|
|
94
|
+
expect(q).toContain("r.status = $outcome");
|
|
95
|
+
expect(q).toContain("datetime($endedAt).epochMillis - datetime(r.startedAt).epochMillis");
|
|
96
|
+
expect(driver.runs[0].params).toMatchObject({
|
|
97
|
+
runId: "run-1",
|
|
98
|
+
outcome: "accepted",
|
|
99
|
+
dispatchResult: "accepted",
|
|
100
|
+
httpStatus: 200,
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
it("is a no-op on a null runId (the open failed or was never taken)", async () => {
|
|
104
|
+
const driver = fakeDriver();
|
|
105
|
+
await closeRoutineRun(driver, null, { outcome: "failed" });
|
|
106
|
+
expect(driver.runs).toHaveLength(0);
|
|
107
|
+
});
|
|
108
|
+
it("never throws when the write fails", async () => {
|
|
109
|
+
const driver = {
|
|
110
|
+
session: () => ({
|
|
111
|
+
run: vi.fn(async () => {
|
|
112
|
+
throw new Error("neo4j down");
|
|
113
|
+
}),
|
|
114
|
+
close: vi.fn(async () => { }),
|
|
115
|
+
}),
|
|
116
|
+
};
|
|
117
|
+
await expect(closeRoutineRun(driver, "run-1", { outcome: "failed", error: "boom" })).resolves.toBeUndefined();
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
describe("recordRunSession", () => {
|
|
121
|
+
it("stores the session key, the transcript offset and bounded=true", async () => {
|
|
122
|
+
const driver = fakeDriver();
|
|
123
|
+
await recordRunSession(driver, "run-1", {
|
|
124
|
+
sessionKey: "8ba1f109-280d-4c15-9e0b-1f7cba6a1a11",
|
|
125
|
+
transcriptOffset: 148213,
|
|
126
|
+
bounded: true,
|
|
127
|
+
});
|
|
128
|
+
expect(driver.runs[0].params).toMatchObject({
|
|
129
|
+
runId: "run-1",
|
|
130
|
+
sessionKey: "8ba1f109-280d-4c15-9e0b-1f7cba6a1a11",
|
|
131
|
+
transcriptOffset: 148213,
|
|
132
|
+
bounded: true,
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
it("stores bounded=false with a null offset when the transcript could not be located", async () => {
|
|
136
|
+
const driver = fakeDriver();
|
|
137
|
+
await recordRunSession(driver, "run-1", {
|
|
138
|
+
sessionKey: "8ba1f109-280d-4c15-9e0b-1f7cba6a1a11",
|
|
139
|
+
transcriptOffset: null,
|
|
140
|
+
bounded: false,
|
|
141
|
+
});
|
|
142
|
+
expect(driver.runs[0].params).toMatchObject({ bounded: false, transcriptOffset: null });
|
|
143
|
+
});
|
|
144
|
+
it("is a no-op on a null runId", async () => {
|
|
145
|
+
const driver = fakeDriver();
|
|
146
|
+
await recordRunSession(driver, null, {
|
|
147
|
+
sessionKey: null,
|
|
148
|
+
transcriptOffset: null,
|
|
149
|
+
bounded: false,
|
|
150
|
+
});
|
|
151
|
+
expect(driver.runs).toHaveLength(0);
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
function driverReturning(rows) {
|
|
155
|
+
const runs = [];
|
|
156
|
+
return {
|
|
157
|
+
runs,
|
|
158
|
+
session: () => ({
|
|
159
|
+
run: vi.fn(async (query, params) => {
|
|
160
|
+
runs.push({ query, params });
|
|
161
|
+
// The promote path issues a second, per-row UPDATE against the same
|
|
162
|
+
// driver; returning the selection rows for it would loop forever, so
|
|
163
|
+
// only the first query (the selection) yields rows.
|
|
164
|
+
return { records: runs.length === 1 ? rows.map((r) => ({ get: (k) => r[k] })) : [] };
|
|
165
|
+
}),
|
|
166
|
+
close: vi.fn(async () => { }),
|
|
167
|
+
}),
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
describe("promoteRoutineRuns", () => {
|
|
171
|
+
const EVENT = "9f3ab21c-0000-4000-8000-000000000000";
|
|
172
|
+
const MARK = `{"text":"… event 9f3ab21c, configured by …"}\n`;
|
|
173
|
+
const row = {
|
|
174
|
+
runId: "run-1",
|
|
175
|
+
sessionKey: "sess-1",
|
|
176
|
+
eventId: EVENT,
|
|
177
|
+
transcriptOffset: 100,
|
|
178
|
+
status: "accepted",
|
|
179
|
+
};
|
|
180
|
+
it("promotes to started when this run's marker landed but nothing answered", async () => {
|
|
181
|
+
const driver = driverReturning([row]);
|
|
182
|
+
const out = await promoteRoutineRuns(driver, "acct-1", {
|
|
183
|
+
projectDirFor: () => "/tmp/proj",
|
|
184
|
+
readTail: () => MARK,
|
|
185
|
+
});
|
|
186
|
+
expect(out).toEqual({ started: 1, finished: 0 });
|
|
187
|
+
const write = driver.runs.find((r) => r.query.includes("r.status = $status"));
|
|
188
|
+
expect(write?.params).toMatchObject({ runId: "run-1", status: "started", finishedAt: null });
|
|
189
|
+
});
|
|
190
|
+
it("promotes to finished when an assistant row follows this run's marker", async () => {
|
|
191
|
+
const driver = driverReturning([row]);
|
|
192
|
+
const out = await promoteRoutineRuns(driver, "acct-1", {
|
|
193
|
+
projectDirFor: () => "/tmp/proj",
|
|
194
|
+
readTail: () => MARK + '{"type":"assistant","message":{"role":"assistant"}}\n',
|
|
195
|
+
});
|
|
196
|
+
expect(out).toEqual({ started: 0, finished: 1 });
|
|
197
|
+
const write = driver.runs.find((r) => r.query.includes("r.status = $status"));
|
|
198
|
+
expect(write?.params).toMatchObject({ runId: "run-1", status: "finished" });
|
|
199
|
+
expect(typeof write?.params.finishedAt).toBe("string");
|
|
200
|
+
});
|
|
201
|
+
it("does NOT promote on the operator's own traffic in the shared transcript", async () => {
|
|
202
|
+
// The record-review defect: a fire that was accepted but never spawned, and
|
|
203
|
+
// the operator later chats on the same thread. Bytes appeared and an
|
|
204
|
+
// assistant answered, but this run produced none of it.
|
|
205
|
+
const driver = driverReturning([row]);
|
|
206
|
+
const out = await promoteRoutineRuns(driver, "acct-1", {
|
|
207
|
+
projectDirFor: () => "/tmp/proj",
|
|
208
|
+
readTail: () => '{"role":"user","text":"hi"}\n{"role":"assistant","text":"hello"}\n',
|
|
209
|
+
});
|
|
210
|
+
expect(out).toEqual({ started: 0, finished: 0 });
|
|
211
|
+
expect(driver.runs.some((r) => r.query.includes("r.status = $status"))).toBe(false);
|
|
212
|
+
});
|
|
213
|
+
it("bounds a run's window above by the next run's offset on the same transcript", async () => {
|
|
214
|
+
const reads = [];
|
|
215
|
+
const driver = driverReturning([
|
|
216
|
+
{ ...row, runId: "run-1", transcriptOffset: 100 },
|
|
217
|
+
{ ...row, runId: "run-2", transcriptOffset: 500, status: "finished" },
|
|
218
|
+
]);
|
|
219
|
+
await promoteRoutineRuns(driver, "acct-1", {
|
|
220
|
+
projectDirFor: () => "/tmp/proj",
|
|
221
|
+
readTail: (_p, from, to) => {
|
|
222
|
+
reads.push([from, to]);
|
|
223
|
+
return MARK;
|
|
224
|
+
},
|
|
225
|
+
});
|
|
226
|
+
// run-1's ceiling is run-2's offset; run-2 is terminal and is not read.
|
|
227
|
+
expect(reads).toEqual([[100, 500]]);
|
|
228
|
+
});
|
|
229
|
+
it("leaves the newest run's window open-ended", async () => {
|
|
230
|
+
const reads = [];
|
|
231
|
+
const driver = driverReturning([row]);
|
|
232
|
+
await promoteRoutineRuns(driver, "acct-1", {
|
|
233
|
+
projectDirFor: () => "/tmp/proj",
|
|
234
|
+
readTail: (_p, from, to) => {
|
|
235
|
+
reads.push([from, to]);
|
|
236
|
+
return MARK;
|
|
237
|
+
},
|
|
238
|
+
});
|
|
239
|
+
expect(reads).toEqual([[100, null]]);
|
|
240
|
+
});
|
|
241
|
+
it("does not carry a ceiling across two different transcripts", async () => {
|
|
242
|
+
const reads = [];
|
|
243
|
+
const driver = driverReturning([
|
|
244
|
+
{ ...row, runId: "run-1", sessionKey: "sess-1", transcriptOffset: 100 },
|
|
245
|
+
{ ...row, runId: "run-2", sessionKey: "sess-2", transcriptOffset: 500 },
|
|
246
|
+
]);
|
|
247
|
+
await promoteRoutineRuns(driver, "acct-1", {
|
|
248
|
+
projectDirFor: () => "/tmp/proj",
|
|
249
|
+
readTail: (_p, from, to) => {
|
|
250
|
+
reads.push([from, to]);
|
|
251
|
+
return MARK;
|
|
252
|
+
},
|
|
253
|
+
});
|
|
254
|
+
expect(reads).toEqual([
|
|
255
|
+
[100, null],
|
|
256
|
+
[500, null],
|
|
257
|
+
]);
|
|
258
|
+
});
|
|
259
|
+
it("leaves the record alone when nothing was appended", async () => {
|
|
260
|
+
const driver = driverReturning([row]);
|
|
261
|
+
const out = await promoteRoutineRuns(driver, "acct-1", {
|
|
262
|
+
projectDirFor: () => "/tmp/proj",
|
|
263
|
+
readTail: () => "",
|
|
264
|
+
});
|
|
265
|
+
expect(out).toEqual({ started: 0, finished: 0 });
|
|
266
|
+
expect(driver.runs.some((r) => r.query.includes("r.status = $status"))).toBe(false);
|
|
267
|
+
});
|
|
268
|
+
it("leaves the record alone when the transcript cannot be located", async () => {
|
|
269
|
+
const driver = driverReturning([row]);
|
|
270
|
+
const out = await promoteRoutineRuns(driver, "acct-1", {
|
|
271
|
+
projectDirFor: () => null,
|
|
272
|
+
readTail: () => "should not be called",
|
|
273
|
+
});
|
|
274
|
+
expect(out).toEqual({ started: 0, finished: 0 });
|
|
275
|
+
});
|
|
276
|
+
it("does not re-promote a record already at the status the evidence implies", async () => {
|
|
277
|
+
const driver = driverReturning([{ ...row, status: "started" }]);
|
|
278
|
+
const out = await promoteRoutineRuns(driver, "acct-1", {
|
|
279
|
+
projectDirFor: () => "/tmp/proj",
|
|
280
|
+
readTail: () => MARK,
|
|
281
|
+
});
|
|
282
|
+
expect(out).toEqual({ started: 0, finished: 0 });
|
|
283
|
+
expect(driver.runs.some((r) => r.query.includes("r.status = $status"))).toBe(false);
|
|
284
|
+
});
|
|
285
|
+
it("selects every bounded record, ordered so each one's ceiling is its successor", async () => {
|
|
286
|
+
const driver = driverReturning([]);
|
|
287
|
+
await promoteRoutineRuns(driver, "acct-1", {
|
|
288
|
+
projectDirFor: () => null,
|
|
289
|
+
readTail: () => "",
|
|
290
|
+
});
|
|
291
|
+
const q = driver.runs[0].query;
|
|
292
|
+
expect(q).toContain("r.bounded = true");
|
|
293
|
+
// Terminal records are NOT filtered out in Cypher: a finished successor is
|
|
294
|
+
// what closes its predecessor's window, so it must come back in the rows.
|
|
295
|
+
expect(q).not.toContain("r.status IN");
|
|
296
|
+
expect(q).toContain("ORDER BY r.sessionKey, r.transcriptOffset");
|
|
297
|
+
});
|
|
298
|
+
});
|
|
299
|
+
describe("sweepRoutineRuns", () => {
|
|
300
|
+
it("deletes records older than the retention bound and reports the count", async () => {
|
|
301
|
+
const driver = driverReturning([{ deleted: 7 }]);
|
|
302
|
+
const nowMs = Date.parse("2026-07-29T12:00:00.000Z");
|
|
303
|
+
const deleted = await sweepRoutineRuns(driver, "acct-1", nowMs);
|
|
304
|
+
expect(deleted).toBe(7);
|
|
305
|
+
expect(driver.runs[0].query).toContain("DETACH DELETE r");
|
|
306
|
+
expect(driver.runs[0].params.cutoff).toBe(new Date(nowMs - RETENTION_DAYS * 24 * 60 * 60 * 1000).toISOString());
|
|
307
|
+
});
|
|
308
|
+
it("returns 0 and never throws when the delete fails", async () => {
|
|
309
|
+
const driver = {
|
|
310
|
+
session: () => ({
|
|
311
|
+
run: vi.fn(async () => {
|
|
312
|
+
throw new Error("neo4j down");
|
|
313
|
+
}),
|
|
314
|
+
close: vi.fn(async () => { }),
|
|
315
|
+
}),
|
|
316
|
+
};
|
|
317
|
+
await expect(sweepRoutineRuns(driver, "acct-1", Date.now())).resolves.toBe(0);
|
|
318
|
+
});
|
|
319
|
+
});
|
|
320
|
+
describe("auditRunOrphans", () => {
|
|
321
|
+
it("counts open records older than the dispatch ceiling and emits every tick", async () => {
|
|
322
|
+
const driver = driverReturning([{ runId: "run-1" }, { runId: "run-2" }]);
|
|
323
|
+
const lines = [];
|
|
324
|
+
const spy = vi.spyOn(console, "error").mockImplementation((m) => void lines.push(String(m)));
|
|
325
|
+
const nowMs = Date.parse("2026-07-29T12:00:00.000Z");
|
|
326
|
+
await auditRunOrphans(driver, "acct-1234abcd", nowMs);
|
|
327
|
+
spy.mockRestore();
|
|
328
|
+
expect(driver.runs[0].params.cutoff).toBe(new Date(nowMs - ORPHAN_AFTER_MS).toISOString());
|
|
329
|
+
expect(lines.join("\n")).toContain("op=run-orphans acct=acct-123 count=2 runIds=[run-1,run-2]");
|
|
330
|
+
});
|
|
331
|
+
it("emits count=0 when there are none", async () => {
|
|
332
|
+
const driver = driverReturning([]);
|
|
333
|
+
const lines = [];
|
|
334
|
+
const spy = vi.spyOn(console, "error").mockImplementation((m) => void lines.push(String(m)));
|
|
335
|
+
await auditRunOrphans(driver, "acct-1234abcd", Date.now());
|
|
336
|
+
spy.mockRestore();
|
|
337
|
+
expect(lines.join("\n")).toContain("op=run-orphans acct=acct-123 count=0 runIds=[]");
|
|
338
|
+
});
|
|
339
|
+
});
|
|
340
|
+
describe("auditFiresWithoutRecords", () => {
|
|
341
|
+
it("reports events whose lastTriggered moved past the watermark with no record", async () => {
|
|
342
|
+
const driver = driverReturning([{ eventId: "evt-1", lastTriggered: "2026-07-29T11:00:00.000Z" }]);
|
|
343
|
+
const lines = [];
|
|
344
|
+
const spy = vi.spyOn(console, "error").mockImplementation((m) => void lines.push(String(m)));
|
|
345
|
+
const next = await auditFiresWithoutRecords(driver, "acct-1234abcd", "2026-07-29T10:00:00.000Z");
|
|
346
|
+
spy.mockRestore();
|
|
347
|
+
expect(driver.runs[0].params.watermark).toBe("2026-07-29T10:00:00.000Z");
|
|
348
|
+
expect(driver.runs[0].query).toContain("r.scheduledFor = e.lastTriggered");
|
|
349
|
+
expect(lines.join("\n")).toContain("op=fires-without-records acct=acct-123 count=1 eventIds=[evt-1]");
|
|
350
|
+
expect(next).toBe("2026-07-29T11:00:00.000Z");
|
|
351
|
+
});
|
|
352
|
+
it("returns the previous watermark unchanged when nothing fired", async () => {
|
|
353
|
+
const driver = driverReturning([]);
|
|
354
|
+
const spy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
355
|
+
const next = await auditFiresWithoutRecords(driver, "acct-1", "2026-07-29T10:00:00.000Z");
|
|
356
|
+
spy.mockRestore();
|
|
357
|
+
expect(next).toBe("2026-07-29T10:00:00.000Z");
|
|
358
|
+
});
|
|
359
|
+
it("starts from the epoch when there is no stored watermark", async () => {
|
|
360
|
+
const driver = driverReturning([]);
|
|
361
|
+
const spy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
362
|
+
await auditFiresWithoutRecords(driver, "acct-1", null);
|
|
363
|
+
spy.mockRestore();
|
|
364
|
+
expect(driver.runs[0].params.watermark).toBe(new Date(0).toISOString());
|
|
365
|
+
});
|
|
366
|
+
});
|
|
367
|
+
describe("auditRunCensus", () => {
|
|
368
|
+
it("reports total and oldest every tick", async () => {
|
|
369
|
+
const driver = driverReturning([{ total: 2903, oldest: "2026-06-29T00:00:00.000Z" }]);
|
|
370
|
+
const lines = [];
|
|
371
|
+
const spy = vi.spyOn(console, "error").mockImplementation((m) => void lines.push(String(m)));
|
|
372
|
+
await auditRunCensus(driver, "acct-1234abcd");
|
|
373
|
+
spy.mockRestore();
|
|
374
|
+
expect(lines.join("\n")).toContain("op=run-census acct=acct-123 total=2903 oldest=2026-06-29T00:00:00.000Z");
|
|
375
|
+
});
|
|
376
|
+
it("reports oldest=- on an empty census", async () => {
|
|
377
|
+
const driver = driverReturning([{ total: 0, oldest: null }]);
|
|
378
|
+
const lines = [];
|
|
379
|
+
const spy = vi.spyOn(console, "error").mockImplementation((m) => void lines.push(String(m)));
|
|
380
|
+
await auditRunCensus(driver, "acct-1234abcd");
|
|
381
|
+
spy.mockRestore();
|
|
382
|
+
expect(lines.join("\n")).toContain("op=run-census acct=acct-123 total=0 oldest=-");
|
|
383
|
+
});
|
|
384
|
+
});
|
|
385
|
+
describe("readTranscriptTail", () => {
|
|
386
|
+
it("cuts at the BYTE offset, not the UTF-16 code-unit index", () => {
|
|
387
|
+
const dir = mkdtempSync(join(tmpdir(), "routine-run-tail-"));
|
|
388
|
+
const path = join(dir, "t.jsonl");
|
|
389
|
+
// 'é' is one code unit but two bytes. schedule-inject records
|
|
390
|
+
// statSync().size, a BYTE count, so a code-unit slice would start one
|
|
391
|
+
// character late here and drop the head of the run's output.
|
|
392
|
+
const head = '{"role":"user","text":"café"}\n';
|
|
393
|
+
writeFileSync(path, head + '{"role":"assistant"}\n', "utf8");
|
|
394
|
+
const byteOffset = Buffer.byteLength(head, "utf8");
|
|
395
|
+
expect(byteOffset).not.toBe(head.length); // the divergence this guards
|
|
396
|
+
expect(readTranscriptTail(path, byteOffset)).toBe('{"role":"assistant"}\n');
|
|
397
|
+
rmSync(dir, { recursive: true, force: true });
|
|
398
|
+
});
|
|
399
|
+
it("returns an empty string when nothing has been appended since the boundary", () => {
|
|
400
|
+
const dir = mkdtempSync(join(tmpdir(), "routine-run-tail-"));
|
|
401
|
+
const path = join(dir, "t.jsonl");
|
|
402
|
+
writeFileSync(path, "abc", "utf8");
|
|
403
|
+
expect(readTranscriptTail(path, 3)).toBe("");
|
|
404
|
+
rmSync(dir, { recursive: true, force: true });
|
|
405
|
+
});
|
|
406
|
+
it("returns null when the file is unreadable", () => {
|
|
407
|
+
expect(readTranscriptTail(join(tmpdir(), "definitely-not-here.jsonl"), 0)).toBeNull();
|
|
408
|
+
});
|
|
409
|
+
});
|
|
410
|
+
describe("classifyRunEvidence", () => {
|
|
411
|
+
const EVENT = "9f3ab21c-0000-4000-8000-000000000000";
|
|
412
|
+
const MARKER = "event 9f3ab21c";
|
|
413
|
+
it("is 'none' when this run's own marker never landed in the window", () => {
|
|
414
|
+
// The defect this rule exists to remove: an hourly routine whose 09:00 fire
|
|
415
|
+
// was accepted but never spawned, and at 09:30 the OPERATOR chats on the
|
|
416
|
+
// same thread. Bytes appeared and an assistant answered, but none of it is
|
|
417
|
+
// this run's, so the record must stay accepted rather than report finished.
|
|
418
|
+
const operatorTraffic = '{"role":"user","text":"hi"}\n{"role":"assistant","text":"hello"}\n';
|
|
419
|
+
expect(classifyRunEvidence(operatorTraffic, EVENT)).toBe("none");
|
|
420
|
+
});
|
|
421
|
+
it("is 'started' when the marker landed but nothing answered", () => {
|
|
422
|
+
expect(classifyRunEvidence(`{"text":"… ${MARKER}, configured by …"}\n`, EVENT)).toBe("started");
|
|
423
|
+
});
|
|
424
|
+
it("is 'finished' when an assistant row follows the marker", () => {
|
|
425
|
+
const w = `{"text":"… ${MARKER} …"}\n{"role":"assistant","text":"done"}\n`;
|
|
426
|
+
expect(classifyRunEvidence(w, EVENT)).toBe("finished");
|
|
427
|
+
});
|
|
428
|
+
it("does not credit an assistant row that PRECEDES the marker", () => {
|
|
429
|
+
// The operator's earlier conversation sits above this run's injection.
|
|
430
|
+
const w = `{"role":"assistant","text":"earlier reply"}\n{"text":"… ${MARKER} …"}\n`;
|
|
431
|
+
expect(classifyRunEvidence(w, EVENT)).toBe("started");
|
|
432
|
+
});
|
|
433
|
+
it("does not match another routine's marker", () => {
|
|
434
|
+
const w = '{"text":"… event deadbeef …"}\n{"role":"assistant"}\n';
|
|
435
|
+
expect(classifyRunEvidence(w, EVENT)).toBe("none");
|
|
436
|
+
});
|
|
437
|
+
});
|
|
438
|
+
describe("readTranscriptTail — upper bound", () => {
|
|
439
|
+
it("stops at the ceiling so one run cannot read the next run's output", () => {
|
|
440
|
+
const dir = mkdtempSync(join(tmpdir(), "routine-run-ceil-"));
|
|
441
|
+
const path = join(dir, "t.jsonl");
|
|
442
|
+
const mine = "AAAA";
|
|
443
|
+
const theirs = "BBBB";
|
|
444
|
+
writeFileSync(path, mine + theirs, "utf8");
|
|
445
|
+
expect(readTranscriptTail(path, 0, 4)).toBe("AAAA");
|
|
446
|
+
expect(readTranscriptTail(path, 0, null)).toBe("AAAABBBB");
|
|
447
|
+
rmSync(dir, { recursive: true, force: true });
|
|
448
|
+
});
|
|
449
|
+
it("clamps a ceiling past end of file", () => {
|
|
450
|
+
const dir = mkdtempSync(join(tmpdir(), "routine-run-ceil-"));
|
|
451
|
+
const path = join(dir, "t.jsonl");
|
|
452
|
+
writeFileSync(path, "AAAA", "utf8");
|
|
453
|
+
expect(readTranscriptTail(path, 0, 9999)).toBe("AAAA");
|
|
454
|
+
rmSync(dir, { recursive: true, force: true });
|
|
455
|
+
});
|
|
456
|
+
});
|
|
457
|
+
//# sourceMappingURL=routine-run.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routine-run.test.js","sourceRoot":"","sources":["../../../src/lib/__tests__/routine-run.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Task 2136 — the notes blob, bounded.
|
|
3
|
+
*
|
|
4
|
+
* `e.notes` was an uncapped free-text string with nine appenders, all in the
|
|
5
|
+
* same `\n[<iso>] <prose>` shape, interleaving fires with cancellations and
|
|
6
|
+
* lifecycle notes. Five of those appenders were fire lines and are gone: those
|
|
7
|
+
* facts now live on `:RoutineRun`, where they are readable without parsing
|
|
8
|
+
* prose. The four that remain are operator-facing prose, not run history, and
|
|
9
|
+
* stay.
|
|
10
|
+
*
|
|
11
|
+
* Those four trim at write time rather than through a sweep, so the blob is
|
|
12
|
+
* bounded by construction and an already-oversized blob shrinks the next time
|
|
13
|
+
* anything writes to it. No migration is needed and none ships.
|
|
14
|
+
*/
|
|
15
|
+
/** How many trailing lines survive an append. */
|
|
16
|
+
export declare const NOTES_MAX_LINES = 50;
|
|
17
|
+
/**
|
|
18
|
+
* The Cypher fragment for "append this note and keep only the last
|
|
19
|
+
* NOTES_MAX_LINES lines", for use inside a SET clause. `nodeVar` is the bound
|
|
20
|
+
* node, `paramName` the query parameter holding the new note (which already
|
|
21
|
+
* carries its own leading newline, as every appender writes it).
|
|
22
|
+
*
|
|
23
|
+
* Split-and-rejoin rather than a byte slice: a byte cap can cut mid-line and
|
|
24
|
+
* leave a fragment that reads as a corrupted entry rather than a truncated
|
|
25
|
+
* history.
|
|
26
|
+
*
|
|
27
|
+
* Empty elements are dropped before the rejoin. Every appender writes a LEADING
|
|
28
|
+
* `\n`, so `split` yields an empty first element on every call; a naive
|
|
29
|
+
* `reduce(acc + '\n' + line)` would re-emit those empties and add one more each
|
|
30
|
+
* time, so the blob grew a blank line per append and the 50-line cap retained
|
|
31
|
+
* only ~25 real entries. Filtering them means the cap means what it says, and
|
|
32
|
+
* the single leading newline is restored once by the reduce itself.
|
|
33
|
+
*/
|
|
34
|
+
export declare function appendNotesCapped(nodeVar: string, paramName: string): string;
|
|
35
|
+
//# sourceMappingURL=notes-cap.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notes-cap.d.ts","sourceRoot":"","sources":["../../src/lib/notes-cap.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,iDAAiD;AACjD,eAAO,MAAM,eAAe,KAAK,CAAC;AAElC;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAM5E"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Task 2136 — the notes blob, bounded.
|
|
3
|
+
*
|
|
4
|
+
* `e.notes` was an uncapped free-text string with nine appenders, all in the
|
|
5
|
+
* same `\n[<iso>] <prose>` shape, interleaving fires with cancellations and
|
|
6
|
+
* lifecycle notes. Five of those appenders were fire lines and are gone: those
|
|
7
|
+
* facts now live on `:RoutineRun`, where they are readable without parsing
|
|
8
|
+
* prose. The four that remain are operator-facing prose, not run history, and
|
|
9
|
+
* stay.
|
|
10
|
+
*
|
|
11
|
+
* Those four trim at write time rather than through a sweep, so the blob is
|
|
12
|
+
* bounded by construction and an already-oversized blob shrinks the next time
|
|
13
|
+
* anything writes to it. No migration is needed and none ships.
|
|
14
|
+
*/
|
|
15
|
+
/** How many trailing lines survive an append. */
|
|
16
|
+
export const NOTES_MAX_LINES = 50;
|
|
17
|
+
/**
|
|
18
|
+
* The Cypher fragment for "append this note and keep only the last
|
|
19
|
+
* NOTES_MAX_LINES lines", for use inside a SET clause. `nodeVar` is the bound
|
|
20
|
+
* node, `paramName` the query parameter holding the new note (which already
|
|
21
|
+
* carries its own leading newline, as every appender writes it).
|
|
22
|
+
*
|
|
23
|
+
* Split-and-rejoin rather than a byte slice: a byte cap can cut mid-line and
|
|
24
|
+
* leave a fragment that reads as a corrupted entry rather than a truncated
|
|
25
|
+
* history.
|
|
26
|
+
*
|
|
27
|
+
* Empty elements are dropped before the rejoin. Every appender writes a LEADING
|
|
28
|
+
* `\n`, so `split` yields an empty first element on every call; a naive
|
|
29
|
+
* `reduce(acc + '\n' + line)` would re-emit those empties and add one more each
|
|
30
|
+
* time, so the blob grew a blank line per append and the 50-line cap retained
|
|
31
|
+
* only ~25 real entries. Filtering them means the cap means what it says, and
|
|
32
|
+
* the single leading newline is restored once by the reduce itself.
|
|
33
|
+
*/
|
|
34
|
+
export function appendNotesCapped(nodeVar, paramName) {
|
|
35
|
+
return (`${nodeVar}.notes = reduce(acc = '', line IN ` +
|
|
36
|
+
`[l IN split(COALESCE(${nodeVar}.notes, '') + $${paramName}, '\\n') WHERE l <> ''][-${NOTES_MAX_LINES}..]` +
|
|
37
|
+
` | acc + '\\n' + line)`);
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=notes-cap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notes-cap.js","sourceRoot":"","sources":["../../src/lib/notes-cap.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,iDAAiD;AACjD,MAAM,CAAC,MAAM,eAAe,GAAG,EAAE,CAAC;AAElC;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAAe,EAAE,SAAiB;IAClE,OAAO,CACL,GAAG,OAAO,oCAAoC;QAC9C,wBAAwB,OAAO,kBAAkB,SAAS,4BAA4B,eAAe,KAAK;QAC1G,wBAAwB,CACzB,CAAC;AACJ,CAAC"}
|