@rubytech/create-maxy-code 0.1.158 → 0.1.159
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/admin-conversation-purge/dist/index.d.ts +1 -1
- package/payload/platform/lib/admin-conversation-purge/dist/index.d.ts.map +1 -1
- package/payload/platform/lib/admin-conversation-purge/dist/index.js +4 -4
- package/payload/platform/lib/admin-conversation-purge/dist/index.js.map +1 -1
- package/payload/platform/lib/admin-conversation-purge/src/index.ts +5 -5
- package/payload/platform/lib/graph-style/dist/index.js +2 -2
- package/payload/platform/lib/graph-style/dist/index.js.map +1 -1
- package/payload/platform/lib/graph-style/src/__tests__/parity.test.ts +1 -1
- package/payload/platform/lib/graph-style/src/index.ts +2 -2
- package/payload/platform/lib/graph-trash/dist/index.js +1 -1
- package/payload/platform/lib/graph-trash/dist/index.js.map +1 -1
- package/payload/platform/lib/graph-trash/src/index.ts +1 -1
- package/payload/platform/lib/graph-write/dist/__tests__/action-provenance-gate.test.js +1 -1
- package/payload/platform/lib/graph-write/dist/__tests__/action-provenance-gate.test.js.map +1 -1
- package/payload/platform/lib/graph-write/dist/conversation-provenance.d.ts +3 -3
- package/payload/platform/lib/graph-write/dist/conversation-provenance.js +5 -5
- package/payload/platform/lib/graph-write/dist/conversation-provenance.js.map +1 -1
- package/payload/platform/lib/graph-write/dist/index.js +1 -1
- package/payload/platform/lib/graph-write/dist/index.js.map +1 -1
- package/payload/platform/lib/graph-write/src/__tests__/action-provenance-gate.test.ts +1 -1
- package/payload/platform/lib/graph-write/src/conversation-provenance.ts +8 -8
- package/payload/platform/lib/graph-write/src/index.ts +1 -1
- package/payload/platform/neo4j/schema.cypher +30 -13
- package/payload/platform/plugins/admin/.claude-plugin/plugin.json +1 -1
- package/payload/platform/plugins/admin/PLUGIN.md +8 -4
- package/payload/platform/plugins/admin/hooks/__tests__/archive-ingest-surface-gate.test.sh +1 -1
- package/payload/platform/plugins/admin/hooks/__tests__/per-turn-graph-pass-gate.test.sh +361 -0
- package/payload/platform/plugins/admin/hooks/__tests__/pre-turn-graph-pass.test.sh +13 -13
- package/payload/platform/plugins/admin/hooks/__tests__/turn-completed-graph-write.test.sh +1 -1
- package/payload/platform/plugins/admin/hooks/lib/admin-graph-pass-common.sh +102 -0
- package/payload/platform/plugins/admin/hooks/per-turn-graph-pass-gate.sh +106 -0
- package/payload/platform/plugins/admin/hooks/pre-turn-graph-pass.sh +15 -8
- package/payload/platform/plugins/admin/hooks/turn-completed-graph-write.sh +4 -4
- package/payload/platform/plugins/admin/mcp/dist/index.js +65 -24
- package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/admin/skills/session-management/SKILL.md +2 -2
- package/payload/platform/plugins/admin/skills/stream-log-review/SKILL.md +5 -5
- package/payload/platform/plugins/admin/skills/stream-log-review/references/analysis-patterns.md +6 -6
- package/payload/platform/plugins/business-assistant/references/profiling.md +1 -1
- package/payload/platform/plugins/contacts/PLUGIN.md +1 -1
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-create.js +2 -2
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-create.js.map +1 -1
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-erase.js +3 -3
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-export.d.ts +1 -1
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-export.js +2 -2
- package/payload/platform/plugins/contacts/mcp/dist/tools/group-create.d.ts +1 -1
- package/payload/platform/plugins/contacts/mcp/dist/tools/group-create.d.ts.map +1 -1
- package/payload/platform/plugins/contacts/mcp/dist/tools/group-create.js +4 -4
- package/payload/platform/plugins/contacts/mcp/dist/tools/group-create.js.map +1 -1
- package/payload/platform/plugins/contacts/mcp/dist/tools/group-manage.js +10 -10
- package/payload/platform/plugins/contacts/mcp/dist/tools/group-manage.js.map +1 -1
- package/payload/platform/plugins/docs/references/admin-session.md +6 -6
- package/payload/platform/plugins/docs/references/admin-ui.md +1 -1
- package/payload/platform/plugins/docs/references/internals.md +5 -5
- package/payload/platform/plugins/docs/references/plugins-guide.md +3 -3
- package/payload/platform/plugins/docs/references/troubleshooting.md +1 -1
- package/payload/platform/plugins/email/.claude-plugin/plugin.json +1 -1
- package/payload/platform/plugins/email/PLUGIN.md +15 -2
- package/payload/platform/plugins/email/mcp/dist/index.js +53 -0
- package/payload/platform/plugins/email/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/lib/embedding.js +2 -2
- package/payload/platform/plugins/email/mcp/dist/lib/embedding.js.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/lib/graph.js +1 -1
- package/payload/platform/plugins/email/mcp/dist/lib/graph.js.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/lib/imap.d.ts +1 -1
- package/payload/platform/plugins/email/mcp/dist/lib/ingest-batch.d.ts +23 -0
- package/payload/platform/plugins/email/mcp/dist/lib/ingest-batch.d.ts.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/lib/ingest-batch.js +15 -0
- package/payload/platform/plugins/email/mcp/dist/lib/ingest-batch.js.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/tools/email-fetch.d.ts +15 -0
- package/payload/platform/plugins/email/mcp/dist/tools/email-fetch.d.ts.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/tools/email-fetch.js +49 -0
- package/payload/platform/plugins/email/mcp/dist/tools/email-fetch.js.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/tools/email-ingest.d.ts +20 -0
- package/payload/platform/plugins/email/mcp/dist/tools/email-ingest.d.ts.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/tools/email-ingest.js +86 -0
- package/payload/platform/plugins/email/mcp/dist/tools/email-ingest.js.map +1 -0
- package/payload/platform/plugins/email/mcp/dist/tools/email-setup.d.ts.map +1 -1
- package/payload/platform/plugins/email/mcp/dist/tools/email-setup.js +32 -52
- package/payload/platform/plugins/email/mcp/dist/tools/email-setup.js.map +1 -1
- package/payload/platform/plugins/email/references/email-reference.md +19 -83
- package/payload/platform/plugins/email/skills/email-ingest/SKILL.md +87 -0
- package/payload/platform/plugins/memory/PLUGIN.md +1 -1
- package/payload/platform/plugins/memory/mcp/dist/index.js +29 -29
- package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/x-dm.js +2 -2
- package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/x-dm.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/graph-prune.d.ts +3 -3
- package/payload/platform/plugins/memory/mcp/dist/lib/graph-prune.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/graph-prune.js +6 -6
- package/payload/platform/plugins/memory/mcp/dist/lib/graph-prune.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/log-ingest.js +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/log-ingest.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/neo4j.d.ts +2 -2
- package/payload/platform/plugins/memory/mcp/dist/lib/neo4j.js +2 -2
- package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-pass.d.ts +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-pass.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-memory-expunge-emit.test.js +3 -3
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-memory-expunge-emit.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/log-ingest.test.js +2 -2
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/log-ingest.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-empty-trash-admin-conversation.test.js +8 -8
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-empty-trash-admin-conversation.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-report-tools.test.js +2 -2
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-report-tools.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/conversation-memory-expunge.d.ts +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/conversation-memory-expunge.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/conversation-memory-expunge.js +2 -2
- package/payload/platform/plugins/memory/mcp/dist/tools/conversation-memory-expunge.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-brain-capture-recent.d.ts +2 -2
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-brain-capture-recent.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-brain-capture-recent.js +4 -4
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-brain-capture-recent.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-empty-trash.d.ts +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-empty-trash.js +8 -8
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-empty-trash.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-find-candidates.d.ts +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-find-candidates.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-find-candidates.js +2 -2
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-find-candidates.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-report-write.d.ts +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-report-write.js +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-typed-edge-pass.d.ts +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-typed-edge-pass.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-typed-edge-pass.js +2 -2
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-typed-edge-pass.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.js +2 -2
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/profile-update.d.ts +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/profile-update.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/profile-update.js +11 -11
- package/payload/platform/plugins/memory/mcp/dist/tools/profile-update.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/scripts/backfill-typed-edges.ts +1 -1
- package/payload/platform/plugins/memory/mcp/scripts/graph/fixture.cypher +1 -1
- package/payload/platform/plugins/memory/references/graph-primitives.md +1 -1
- package/payload/platform/plugins/memory/references/schema-base.md +4 -4
- package/payload/platform/plugins/memory/skills/conversational-memory/SKILL.md +1 -1
- package/payload/platform/plugins/whatsapp/PLUGIN.md +1 -1
- package/payload/platform/plugins/whatsapp/mcp/dist/index.js +2 -2
- package/payload/platform/plugins/whatsapp/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/work/mcp/dist/index.js +2 -2
- package/payload/platform/plugins/work/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/work/mcp/dist/tools/project-create.js +6 -6
- package/payload/platform/plugins/work/mcp/dist/tools/project-create.js.map +1 -1
- package/payload/platform/plugins/work/mcp/dist/tools/session-list.d.ts +1 -1
- package/payload/platform/plugins/work/mcp/dist/tools/session-list.d.ts.map +1 -1
- package/payload/platform/plugins/work/mcp/dist/tools/session-list.js +1 -1
- package/payload/platform/plugins/work/mcp/dist/tools/session-list.js.map +1 -1
- package/payload/platform/plugins/x-import/references/archive-shape.md +2 -2
- package/payload/platform/plugins/x-import/skills/x-import/SKILL.md +3 -3
- package/payload/platform/scripts/admin-persist-audit.ts +18 -18
- package/payload/platform/scripts/identity-forbidden-token-check.mjs +2 -0
- package/payload/platform/scripts/seed-neo4j.sh +1 -0
- package/payload/platform/services/claude-session-manager/dist/http-server.js +3 -3
- package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts +3 -3
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.js +4 -4
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/system-prompt.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/system-prompt.js +2 -0
- package/payload/platform/services/claude-session-manager/dist/system-prompt.js.map +1 -1
- package/payload/platform/templates/specialists/agents/personal-assistant.md +1 -1
- package/payload/server/{chunk-AXOL2PPG.js → chunk-3TRIXQSJ.js} +101 -101
- package/payload/server/maxy-edge.js +1 -1
- package/payload/server/public/assets/{admin-3fLFD5h_.js → admin-Dal5FWaD.js} +2 -2
- package/payload/server/public/assets/{architectureDiagram-Q4EWVU46-Breg9-99.js → architectureDiagram-Q4EWVU46-Do2zYONG.js} +1 -1
- package/payload/server/public/assets/{blockDiagram-DXYQGD6D-DXf1_673.js → blockDiagram-DXYQGD6D-DpIX_bRu.js} +1 -1
- package/payload/server/public/assets/{c4Diagram-AHTNJAMY-CSZ36W4-.js → c4Diagram-AHTNJAMY-Cz335ZSY.js} +1 -1
- package/payload/server/public/assets/channel-PC4_IjI1.js +1 -0
- package/payload/server/public/assets/{chunk-336JU56O-DsrLk2eK.js → chunk-336JU56O-Dmknn3Wo.js} +2 -2
- package/payload/server/public/assets/{chunk-426QAEUC-JpNfNf81.js → chunk-426QAEUC-ClfGjizN.js} +1 -1
- package/payload/server/public/assets/{chunk-4TB4RGXK-DmClEAD0.js → chunk-4TB4RGXK-BPKctJ5c.js} +1 -1
- package/payload/server/public/assets/{chunk-5FUZZQ4R-BI9blW3N.js → chunk-5FUZZQ4R-BWDCO9zw.js} +1 -1
- package/payload/server/public/assets/{chunk-5PVQY5BW-BbgttEFO.js → chunk-5PVQY5BW-BE34_Db0.js} +1 -1
- package/payload/server/public/assets/{chunk-EDXVE4YY-BX_LCFOx.js → chunk-EDXVE4YY-BysA-_6v.js} +1 -1
- package/payload/server/public/assets/{chunk-ENJZ2VHE-Bb7EoD0w.js → chunk-ENJZ2VHE-BMVyMsqA.js} +1 -1
- package/payload/server/public/assets/{chunk-ICPOFSXX-DH8uQk-s.js → chunk-ICPOFSXX-C5KRdLV4.js} +1 -1
- package/payload/server/public/assets/{chunk-OYMX7WX6-FH5kgXsw.js → chunk-OYMX7WX6-DVZD-AVc.js} +1 -1
- package/payload/server/public/assets/{chunk-U2HBQHQK-D_ljlkHr.js → chunk-U2HBQHQK-DYmQdx8x.js} +1 -1
- package/payload/server/public/assets/{chunk-X2U36JSP-BX3EmZvm.js → chunk-X2U36JSP-DrZenIl3.js} +1 -1
- package/payload/server/public/assets/{chunk-YZCP3GAM-Vu7-E93h.js → chunk-YZCP3GAM-CDuGbvMq.js} +1 -1
- package/payload/server/public/assets/{chunk-ZZ45TVLE-CwjhNPX5.js → chunk-ZZ45TVLE-COztbiu5.js} +1 -1
- package/payload/server/public/assets/classDiagram-6PBFFD2Q-B_pMa-SX.js +1 -0
- package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-BdBAgF20.js +1 -0
- package/payload/server/public/assets/clone-CkNt9L9r.js +1 -0
- package/payload/server/public/assets/{dagre-Ce6gsj0C.js → dagre-Cv9Ib2OM.js} +1 -1
- package/payload/server/public/assets/{dagre-KV5264BT-BaMGpsoy.js → dagre-KV5264BT-CoEd61KZ.js} +1 -1
- package/payload/server/public/assets/{data-BHASh0_Y.js → data-DbSORCl4.js} +1 -1
- package/payload/server/public/assets/{diagram-5BDNPKRD-CHEE9rjq.js → diagram-5BDNPKRD-WXNzw3uW.js} +1 -1
- package/payload/server/public/assets/{diagram-G4DWMVQ6-C98sZLW1.js → diagram-G4DWMVQ6-C6IuQ2VV.js} +1 -1
- package/payload/server/public/assets/{diagram-MMDJMWI5-DNvMGsTZ.js → diagram-MMDJMWI5-CdJdir5A.js} +1 -1
- package/payload/server/public/assets/{diagram-TYMM5635-Cdte4IBa.js → diagram-TYMM5635-DxWKQH5T.js} +1 -1
- package/payload/server/public/assets/{erDiagram-SMLLAGMA-C9VZsWXK.js → erDiagram-SMLLAGMA-C9fvs33K.js} +1 -1
- package/payload/server/public/assets/{flowDiagram-DWJPFMVM-tuP5fzzR.js → flowDiagram-DWJPFMVM-BO7Yrbqv.js} +1 -1
- package/payload/server/public/assets/{ganttDiagram-T4ZO3ILL-SJgRPUwx.js → ganttDiagram-T4ZO3ILL-CQJyWBZq.js} +1 -1
- package/payload/server/public/assets/{gitGraphDiagram-UUTBAWPF-DU_cI_50.js → gitGraphDiagram-UUTBAWPF-DZfQHrYw.js} +1 -1
- package/payload/server/public/assets/{graph-labels-DXlmm1og.js → graph-labels-BBB5jsZk.js} +1 -1
- package/payload/server/public/assets/{graph-BhEI09tF.js → graph-ys_joP2o.js} +1 -1
- package/payload/server/public/assets/{graphlib-D_nAsvmx.js → graphlib-C40H-Q5E.js} +1 -1
- package/payload/server/public/assets/{infoDiagram-42DDH7IO-Cj2Y19m6.js → infoDiagram-42DDH7IO-CakfV5f9.js} +1 -1
- package/payload/server/public/assets/{ishikawaDiagram-UXIWVN3A-DMc1xq1y.js → ishikawaDiagram-UXIWVN3A-CPuBPyfa.js} +1 -1
- package/payload/server/public/assets/{journeyDiagram-VCZTEJTY-C4CRAQma.js → journeyDiagram-VCZTEJTY-zpZm2Mmo.js} +1 -1
- package/payload/server/public/assets/{kanban-definition-6JOO6SKY-CTr4AldU.js → kanban-definition-6JOO6SKY-DfJduQCo.js} +1 -1
- package/payload/server/public/assets/{line-Btlm_IAl.js → line-BpYQqO5R.js} +1 -1
- package/payload/server/public/assets/{mermaid-parser.core-DXFdj_y1.js → mermaid-parser.core-C5Mwi14D.js} +1 -1
- package/payload/server/public/assets/{mermaid.core-DFBhoCr5.js → mermaid.core-D8qBtvvT.js} +3 -3
- package/payload/server/public/assets/{mindmap-definition-QFDTVHPH-r9gVQybo.js → mindmap-definition-QFDTVHPH-Bli9JhIN.js} +1 -1
- package/payload/server/public/assets/{page-CDWu1Aft.js → page--bl5Y7ZI.js} +2 -2
- package/payload/server/public/assets/page-CwmZ76U7.js +1 -0
- package/payload/server/public/assets/{pieDiagram-DEJITSTG-CHKZjSaH.js → pieDiagram-DEJITSTG-MsLXTSLg.js} +1 -1
- package/payload/server/public/assets/{public-DyGWgfaZ.js → public-DltgEfA9.js} +2 -2
- package/payload/server/public/assets/{quadrantDiagram-34T5L4WZ-CSGR1HJr.js → quadrantDiagram-34T5L4WZ-De1sh2K0.js} +1 -1
- package/payload/server/public/assets/{requirementDiagram-MS252O5E-DZ6hX9D6.js → requirementDiagram-MS252O5E-D5Sfg1t_.js} +1 -1
- package/payload/server/public/assets/{sankeyDiagram-XADWPNL6-DbZBKh0m.js → sankeyDiagram-XADWPNL6-DHA3LIbv.js} +1 -1
- package/payload/server/public/assets/{sequenceDiagram-FGHM5R23-BHHpb8dt.js → sequenceDiagram-FGHM5R23-BE_QlG1B.js} +1 -1
- package/payload/server/public/assets/{stateDiagram-FHFEXIEX-DQ1jiLB4.js → stateDiagram-FHFEXIEX-NIwp3F4u.js} +1 -1
- package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-pfk2F6st.js +1 -0
- package/payload/server/public/assets/{timeline-definition-GMOUNBTQ-BlGiEU7p.js → timeline-definition-GMOUNBTQ-CPE9jyDF.js} +1 -1
- package/payload/server/public/assets/{vennDiagram-DHZGUBPP-DmEH-hsB.js → vennDiagram-DHZGUBPP-CKfoyYmH.js} +1 -1
- package/payload/server/public/assets/{wardleyDiagram-NUSXRM2D-C7KJJ40d.js → wardleyDiagram-NUSXRM2D-B9yJek-o.js} +1 -1
- package/payload/server/public/assets/{xychartDiagram-5P7HB3ND-JDnusCaa.js → xychartDiagram-5P7HB3ND-DuCcSLqX.js} +1 -1
- package/payload/server/public/data.html +3 -3
- package/payload/server/public/graph.html +3 -3
- package/payload/server/public/index.html +4 -4
- package/payload/server/public/public.html +1 -1
- package/payload/server/server.js +133 -133
- package/payload/server/public/assets/channel-BmZnt3PP.js +0 -1
- package/payload/server/public/assets/classDiagram-6PBFFD2Q-kmMLFUpV.js +0 -1
- package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-BV7Ae8ct.js +0 -1
- package/payload/server/public/assets/clone-B5eqoN9I.js +0 -1
- package/payload/server/public/assets/page-cyvshX4Z.js +0 -1
- package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-CByT2RzF.js +0 -1
|
@@ -10,7 +10,7 @@ description: >
|
|
|
10
10
|
|
|
11
11
|
# Stream Log Review
|
|
12
12
|
|
|
13
|
-
Analyse Claude agent stream logs — the `claude-agent-stream-{
|
|
13
|
+
Analyse Claude agent stream logs — the `claude-agent-stream-{sessionId}.log` files generated by the platform. Each file is scoped to exactly one conversation; a resumed conversation accumulates in one file across multiple process lifetimes, delimited by `[spawn]` / `[process-exit]`. Pre-conversation events (CDP auth-poll, module-init warnings) live in `preconversation-claude-agent-stream-{YYYY-MM-DD}.log` — a separate file per UTC day, read only when investigating boot-time failures.
|
|
14
14
|
|
|
15
15
|
Parse the log, identify problems, attempt diagnosis, and produce a structured report.
|
|
16
16
|
|
|
@@ -32,11 +32,11 @@ Parse the log, identify problems, attempt diagnosis, and produce a structured re
|
|
|
32
32
|
|
|
33
33
|
## Log Retrieval
|
|
34
34
|
|
|
35
|
-
On the Pi, use the `logs-read` MCP tool with `
|
|
35
|
+
On the Pi, use the `logs-read` MCP tool with `sessionId` to retrieve a single conversation's log. From the dev machine (SSH), use the shell counterpart:
|
|
36
36
|
|
|
37
37
|
```bash
|
|
38
38
|
# Read a single conversation's stream log (primary mode)
|
|
39
|
-
sshpass -p 'password' ssh admin@<hostname>.local "~/<installDir>/platform/scripts/logs-read.sh <
|
|
39
|
+
sshpass -p 'password' ssh admin@<hostname>.local "~/<installDir>/platform/scripts/logs-read.sh <sessionId> system"
|
|
40
40
|
|
|
41
41
|
# Tail the most-recently-active stream log (any conversation)
|
|
42
42
|
sshpass -p 'password' ssh admin@<hostname>.local "~/<installDir>/platform/scripts/logs-read.sh --tail system 200"
|
|
@@ -45,7 +45,7 @@ sshpass -p 'password' ssh admin@<hostname>.local "~/<installDir>/platform/script
|
|
|
45
45
|
sshpass -p 'password' ssh admin@<hostname>.local "~/<installDir>/platform/scripts/logs-read.sh --grep <sessionKey>"
|
|
46
46
|
```
|
|
47
47
|
|
|
48
|
-
The `
|
|
48
|
+
The `sessionId` is visible in the admin UI and appears on every `[spawn]` / `[process-exit]` line in the log itself. A single `logs-read.sh <sessionId> system` returns the full conversation-scoped record — no grep filter required, no cross-file correlation.
|
|
49
49
|
|
|
50
50
|
## What to Look For
|
|
51
51
|
|
|
@@ -62,7 +62,7 @@ The `conversationId` is visible in the admin UI and appears on every `[spawn]` /
|
|
|
62
62
|
## Boundaries
|
|
63
63
|
|
|
64
64
|
- This skill analyses logs. It does not fix the bugs it finds — that's a separate task.
|
|
65
|
-
- Applies to `claude-agent-stream-{
|
|
65
|
+
- Applies to `claude-agent-stream-{sessionId}.log` files only. SSE event logs and stderr logs are handled by `logs-read` directly.
|
|
66
66
|
- Does not modify or rotate log files.
|
|
67
67
|
- Does not correlate across conversations — each report covers a single conversation's log.
|
|
68
68
|
|
package/payload/platform/plugins/admin/skills/stream-log-review/references/analysis-patterns.md
CHANGED
|
@@ -57,22 +57,22 @@ Three independent identifiers trace a conversation through the system:
|
|
|
57
57
|
| Identifier | Scope | Where it lives | Survives restart |
|
|
58
58
|
|------------|-------|-----------------|-----------------|
|
|
59
59
|
| `sessionKey` | Single agent process lifetime | Server memory, stream logs (`sessionKey=XXXXXXXX…`) | No |
|
|
60
|
-
| `
|
|
60
|
+
| `sessionId` | Entire conversation (may span multiple sessionKeys) | Neo4j `Conversation` node, stream logs on resume/attribution | Yes |
|
|
61
61
|
| `visitorId` (public) / `userId` (admin) | Visitor or admin identity across conversations | `maxy_visitor` cookie (public), users.json (admin) | Yes |
|
|
62
62
|
|
|
63
63
|
### Finding the right session in logs
|
|
64
64
|
|
|
65
|
-
**From the admin UI**: The sessions modal and Claude info panel both display the first 8 characters of `
|
|
65
|
+
**From the admin UI**: The sessions modal and Claude info panel both display the first 8 characters of `sessionId`. Use `logs-read` with the corresponding `sessionKey` to pull the full timeline.
|
|
66
66
|
|
|
67
|
-
**From a
|
|
68
|
-
- `[session] conversation attributed:
|
|
69
|
-
- `[session-resume] updated
|
|
67
|
+
**From a sessionId**: The stream log lines that link `sessionId` to `sessionKey` are:
|
|
68
|
+
- `[session] conversation attributed: sessionId=XXXX… userId=… admin/…` (new sessions)
|
|
69
|
+
- `[session-resume] updated sessionId to XXXX… for session YYYY…` (resumed sessions)
|
|
70
70
|
- `[session] cold-resume visitor=XXXX… conversation=YYYY…` (public cold resume)
|
|
71
71
|
|
|
72
72
|
**From a visitorId**: Query Neo4j to find all conversations for a visitor, then trace the `sessionKey` into logs:
|
|
73
73
|
```cypher
|
|
74
74
|
MATCH (c:Conversation {visitorId: $visitorId, accountId: $accountId})
|
|
75
|
-
RETURN c.
|
|
75
|
+
RETURN c.sessionId, c.sessionKey, c.createdAt
|
|
76
76
|
ORDER BY c.createdAt DESC
|
|
77
77
|
```
|
|
78
78
|
|
|
@@ -19,7 +19,7 @@ Call `profile-update` with:
|
|
|
19
19
|
- `value`: the preference in natural language (e.g. "terse — prefers 1-3 sentence responses")
|
|
20
20
|
- `source`: `explicit` (they said it) or `behavioural` (you observed it)
|
|
21
21
|
- `mode`: `reinforce` (re-observed), `update` (value changed), `contradict` (value contradicts prior)
|
|
22
|
-
- `
|
|
22
|
+
- `sessionId`: the current conversation ID for evidence linking
|
|
23
23
|
|
|
24
24
|
When the owner shares personal details (timezone, role, expertise), include `profileFields` to update the UserProfile directly.
|
|
25
25
|
|
|
@@ -54,7 +54,7 @@ Tools are available via the `contacts` MCP server.
|
|
|
54
54
|
|
|
55
55
|
## Provenance anchoring
|
|
56
56
|
|
|
57
|
-
`contact-create` writes a `:Person` node, which is one of the action-provenance-gated labels in `writeNodeWithEdges`. The write must carry an inbound `:PRODUCED` edge from `:Task`, `:Conversation`, or `:Message`. There is no agent-visible field for this — the admin server stamps `
|
|
57
|
+
`contact-create` writes a `:Person` node, which is one of the action-provenance-gated labels in `writeNodeWithEdges`. The write must carry an inbound `:PRODUCED` edge from `:Task`, `:Conversation`, or `:Message`. There is no agent-visible field for this — the admin server stamps `SESSION_NODE_ID` (the `sessionId` UUID of the active `:AdminConversation`) at MCP spawn time, and the wrapper auto-injects the `:PRODUCED` edge via `injectConversationProvenance`. The helper MATCHes `(c:Conversation {sessionId, accountId})` — account isolation is enforced inside the natural key, not as a separate gate, so a cross-account env-stamp returns zero rows and never injects.
|
|
58
58
|
|
|
59
59
|
The agent passes whichever organic relationships are appropriate (`PARTICIPATES_IN` to a Conversation, `WORKS_FOR` to an Organization, `KNOWN_VIA` to a referral source) — the provenance edge is composed automatically and is not an agent concern. When the env-stamp resolution fails (loud `[mcp:contacts] [provenance-missing] reason=<...>`), the downstream gate emits `missing-provenance` and the write fails closed.
|
|
60
60
|
|
|
@@ -87,7 +87,7 @@ export async function contactCreate(params) {
|
|
|
87
87
|
}
|
|
88
88
|
// direct admin asks ("add Anneke as person") need a PRODUCED
|
|
89
89
|
// edge from the active :AdminConversation rather than a synthetic :Task.
|
|
90
|
-
// The admin server stamps `
|
|
90
|
+
// The admin server stamps `SESSION_NODE_ID` in the spawn env; the
|
|
91
91
|
// helper resolves the node, verifies accountId parity, and prepends the
|
|
92
92
|
// synthetic edge. No-op when env is unset or `relationships` already
|
|
93
93
|
// carries an inbound `:PRODUCED`.
|
|
@@ -96,7 +96,7 @@ export async function contactCreate(params) {
|
|
|
96
96
|
relationships,
|
|
97
97
|
accountId: accountId ?? "",
|
|
98
98
|
writeLabels: ["Person"],
|
|
99
|
-
conversationNodeId: process.env.
|
|
99
|
+
conversationNodeId: process.env.SESSION_NODE_ID,
|
|
100
100
|
logNamespace: "mcp:contacts",
|
|
101
101
|
tool: "contact-create",
|
|
102
102
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contact-create.js","sourceRoot":"","sources":["../../src/tools/contact-create.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,8CAA8C,CAAC;AAC1E,OAAO,EACL,kBAAkB,EAClB,4BAA4B,GAG7B,MAAM,8CAA8C,CAAC;AAEtD,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,wBAAwB,CAAC;AACtE,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,kBAAkB,CAAC;AAElE,KAAK,UAAU,gBAAgB,CAAC,IAAY;IAC1C,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,UAAU,YAAY,EAAE;YACjD,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;SAC1D,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,CAAC,EAAE;YAAE,OAAO,EAAE,CAAC;QACvB,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAA+B,CAAC;QAC9D,OAAO,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAClC,CAAC;IAAC,MAAM,CAAC;QACP,yEAAyE;QACzE,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAuBD,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,MAA2B;IAE3B,MAAM,EACJ,SAAS,EACT,UAAU,EACV,KAAK,EACL,SAAS,EACT,QAAQ,EACR,MAAM,EACN,MAAM,GAAG,UAAU,EACnB,SAAS,EACT,aAAa,EACb,SAAS,GACV,GAAG,MAAM,CAAC;IAEX,MAAM,eAAe,GAAG,KAAK,EAAE,WAAW,EAAE,CAAC,IAAI,EAAE,CAAC;IACpD,MAAM,eAAe,GAAG,SAAS,EAAE,IAAI,EAAE,CAAC;IAE1C,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAE7B,IAAI,CAAC;QACH,0EAA0E;QAC1E,uEAAuE;QACvE,qDAAqD;QACrD,gDAAgD;QAChD,MAAM,eAAe,GAAa,EAAE,CAAC;QACrC,MAAM,WAAW,GAA4B,EAAE,SAAS,EAAE,CAAC;QAE3D,IAAI,eAAe,EAAE,CAAC;YACpB,eAAe,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;YACzC,WAAW,CAAC,KAAK,GAAG,eAAe,CAAC;QACtC,CAAC;QACD,IAAI,eAAe,EAAE,CAAC;YACpB,eAAe,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;YACjD,WAAW,CAAC,SAAS,GAAG,eAAe,CAAC;QAC1C,CAAC;QAED,IAAI,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC/B,oDAAoD;YACpD,sEAAsE;YACtE,qEAAqE;YACrE,sCAAsC;YACtC,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,GAAG,CAChC;kBACU,eAAe,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,UAAU,CAAC,GAAG,CAAC;mFACa,EAC3E,WAAW,CACZ,CAAC;YAEF,IAAI,QAAQ,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAChC,MAAM,YAAY,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAkB,CAAC;gBACvE,MAAM,YAAY,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,WAAW,CAEhD,CAAC;gBACT,MAAM,iBAAiB,GAAG,YAAY,IAAI,YAAY,IAAI,SAAS,CAAC;gBAEpE,OAAO;oBACL,MAAM,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAW;oBACnD,UAAU,EAAE,iBAAiB;oBAC7B,OAAO,EAAE,KAAK;oBACd,aAAa,EAAE,IAAI;iBACpB,CAAC;YACJ,CAAC;QACH,CAAC;QAED,MAAM,KAAK,GAA4B;YACrC,MAAM;YACN,MAAM;YACN,SAAS;YACT,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACpC,CAAC;QAEF,IAAI,SAAS;YAAE,KAAK,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3C,IAAI,eAAe;YAAE,KAAK,CAAC,KAAK,GAAG,eAAe,CAAC;QACnD,IAAI,eAAe;YAAE,KAAK,CAAC,SAAS,GAAG,eAAe,CAAC;QACvD,IAAI,UAAU;YAAE,KAAK,CAAC,UAAU,GAAG,UAAU,CAAC;QAC9C,IAAI,QAAQ;YAAE,KAAK,CAAC,QAAQ,GAAG,QAAQ,CAAC;QAExC,MAAM,cAAc,GAAG,eAAe;YACpC,CAAC,CAAC,IAAI,eAAe,GAAG;YACxB,CAAC,CAAC,eAAe,IAAI,EAAE,CAAC;QAC1B,MAAM,QAAQ,GAAG,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACnE,MAAM,gBAAgB,GACpB,WAAW,QAAQ,IAAI,WAAW,IAAI,cAAc,YAAY,MAAM,YAAY,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC;QACpG,MAAM,SAAS,GAAG,MAAM,gBAAgB,CAAC,gBAAgB,CAAC,CAAC;QAC3D,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACzB,KAAK,CAAC,SAAS,GAAG,SAAS,CAAC;QAC9B,CAAC;QAED,6DAA6D;QAC7D,yEAAyE;QACzE,
|
|
1
|
+
{"version":3,"file":"contact-create.js","sourceRoot":"","sources":["../../src/tools/contact-create.ts"],"names":[],"mappings":"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"}
|
|
@@ -73,7 +73,7 @@ export async function contactErase(params) {
|
|
|
73
73
|
}
|
|
74
74
|
// Count Messages + Conversations via sessionId
|
|
75
75
|
if (sessionId) {
|
|
76
|
-
const convCountResult = await session.run(`MATCH (c:Conversation {
|
|
76
|
+
const convCountResult = await session.run(`MATCH (c:Conversation {sessionId: $sessionId, accountId: $accountId})
|
|
77
77
|
OPTIONAL MATCH (m:Message)-[:PART_OF]->(c)
|
|
78
78
|
RETURN count(DISTINCT c) AS convCount, count(m) AS msgCount`, { sessionId, accountId });
|
|
79
79
|
if (convCountResult.records.length > 0) {
|
|
@@ -117,10 +117,10 @@ export async function contactErase(params) {
|
|
|
117
117
|
try {
|
|
118
118
|
// 3a. Delete Messages in attributed Conversations
|
|
119
119
|
if (sessionId) {
|
|
120
|
-
await tx.run(`MATCH (m:Message)-[:PART_OF]->(c:Conversation {
|
|
120
|
+
await tx.run(`MATCH (m:Message)-[:PART_OF]->(c:Conversation {sessionId: $sessionId, accountId: $accountId})
|
|
121
121
|
DETACH DELETE m`, { sessionId, accountId });
|
|
122
122
|
// 3b. Delete now-empty Conversations
|
|
123
|
-
await tx.run(`MATCH (c:Conversation {
|
|
123
|
+
await tx.run(`MATCH (c:Conversation {sessionId: $sessionId, accountId: $accountId})
|
|
124
124
|
WHERE NOT EXISTS { MATCH (m:Message)-[:PART_OF]->(c) }
|
|
125
125
|
DETACH DELETE c`, { sessionId, accountId });
|
|
126
126
|
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Gathers all data held on a specific contact across Neo4j stores:
|
|
5
5
|
* Person → AccessGrants (via relationship)
|
|
6
|
-
* Person → Conversations + Messages (via Person.sessionId → Conversation.
|
|
6
|
+
* Person → Conversations + Messages (via Person.sessionId → Conversation.sessionId)
|
|
7
7
|
* Person → email-source KnowledgeDocuments (via Person.email matching the KD's FROM/TO/CC edges)
|
|
8
8
|
*
|
|
9
9
|
* Returns a self-contained JSON document suitable for handing to the data subject.
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Gathers all data held on a specific contact across Neo4j stores:
|
|
5
5
|
* Person → AccessGrants (via relationship)
|
|
6
|
-
* Person → Conversations + Messages (via Person.sessionId → Conversation.
|
|
6
|
+
* Person → Conversations + Messages (via Person.sessionId → Conversation.sessionId)
|
|
7
7
|
* Person → email-source KnowledgeDocuments (via Person.email matching the KD's FROM/TO/CC edges)
|
|
8
8
|
*
|
|
9
9
|
* Returns a self-contained JSON document suitable for handing to the data subject.
|
|
@@ -47,7 +47,7 @@ export async function contactExport(params) {
|
|
|
47
47
|
const conversations = [];
|
|
48
48
|
const sessionId = personProps.sessionId;
|
|
49
49
|
if (sessionId) {
|
|
50
|
-
const convResult = await session.run(`MATCH (c:Conversation {
|
|
50
|
+
const convResult = await session.run(`MATCH (c:Conversation {sessionId: $sessionId, accountId: $accountId})
|
|
51
51
|
RETURN c, elementId(c) AS cNodeId`, { sessionId, accountId });
|
|
52
52
|
for (const convRecord of convResult.records) {
|
|
53
53
|
const cNodeId = convRecord.get("cNodeId");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"group-create.d.ts","sourceRoot":"","sources":["../../src/tools/group-create.ts"],"names":[],"mappings":"AAGA,OAAO,EAAkB,KAAK,SAAS,EAAE,MAAM,8CAA8C,CAAC;AAW9F,UAAU,iBAAiB;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,SAAS,CAAC;CACtB;AAED,UAAU,iBAAiB;IACzB,
|
|
1
|
+
{"version":3,"file":"group-create.d.ts","sourceRoot":"","sources":["../../src/tools/group-create.ts"],"names":[],"mappings":"AAGA,OAAO,EAAkB,KAAK,SAAS,EAAE,MAAM,8CAA8C,CAAC;AAW9F,UAAU,iBAAiB;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,SAAS,CAAC;CACtB;AAED,UAAU,iBAAiB;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,wBAAsB,WAAW,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CA6GvF"}
|
|
@@ -15,7 +15,7 @@ export async function groupCreate(params) {
|
|
|
15
15
|
if (!participants || participants.length < 2) {
|
|
16
16
|
throw new Error("At least 2 participants are required to create a group.");
|
|
17
17
|
}
|
|
18
|
-
const
|
|
18
|
+
const sessionId = randomUUID();
|
|
19
19
|
let groupSlug = generateGroupSlug(groupName);
|
|
20
20
|
const session = getSession();
|
|
21
21
|
try {
|
|
@@ -57,7 +57,7 @@ export async function groupCreate(params) {
|
|
|
57
57
|
throw new Error(`Write doctrine violated: group-create could not resolve any of the ${participants.length} participant(s) (${notFound.join(", ")}). A group Conversation with no live participants is an orphan.`);
|
|
58
58
|
}
|
|
59
59
|
const convoProps = stampCreatedBy({
|
|
60
|
-
|
|
60
|
+
sessionId,
|
|
61
61
|
accountId,
|
|
62
62
|
agentType: "public",
|
|
63
63
|
agentSlug,
|
|
@@ -85,8 +85,8 @@ export async function groupCreate(params) {
|
|
|
85
85
|
const hostname = brandResult.records[0]?.get("hostname");
|
|
86
86
|
const baseUrl = hostname ? `https://${hostname}` : "https://maxy.bot";
|
|
87
87
|
const shareableUrl = `${baseUrl}/g/${groupSlug}`;
|
|
88
|
-
console.error(`[group] created id=${
|
|
89
|
-
return {
|
|
88
|
+
console.error(`[group] created id=${sessionId.slice(0, 8)}… slug=${groupSlug} participants=${joined.length}${notFound.length > 0 ? ` notFound=${notFound.length}` : ""}`);
|
|
89
|
+
return { sessionId, groupSlug, joined, notFound, shareableUrl };
|
|
90
90
|
}
|
|
91
91
|
finally {
|
|
92
92
|
await session.close();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"group-create.js","sourceRoot":"","sources":["../../src/tools/group-create.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,8CAA8C,CAAC;AAC1E,OAAO,EAAE,cAAc,EAAkB,MAAM,8CAA8C,CAAC;AAE9F,SAAS,iBAAiB,CAAC,IAAY;IACrC,MAAM,IAAI,GAAG,IAAI;SACd,WAAW,EAAE;SACb,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC;SAC3B,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC;SACrB,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAChB,OAAO,IAAI,IAAI,OAAO,CAAC;AACzB,CAAC;AAkBD,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,MAAyB;IACzD,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,YAAY,EAAE,SAAS,EAAE,SAAS,EAAE,GAAG,MAAM,CAAC;IAE5E,IAAI,CAAC,YAAY,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7C,MAAM,IAAI,KAAK,CAAC,yDAAyD,CAAC,CAAC;IAC7E,CAAC;IAED,MAAM,
|
|
1
|
+
{"version":3,"file":"group-create.js","sourceRoot":"","sources":["../../src/tools/group-create.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,12 +7,12 @@ export async function groupManage(params) {
|
|
|
7
7
|
// Find the group (skip trashed — they should behave as not-found).
|
|
8
8
|
const groupResult = await session.run(`MATCH (c:Conversation {groupSlug: $groupSlug, accountId: $accountId, type: 'group'})
|
|
9
9
|
WHERE ${notTrashed("c")}
|
|
10
|
-
RETURN c.
|
|
10
|
+
RETURN c.sessionId AS sessionId, c.groupName AS groupName`, { groupSlug, accountId });
|
|
11
11
|
const record = groupResult.records[0];
|
|
12
12
|
if (!record) {
|
|
13
13
|
throw new Error(`Group not found: ${groupSlug}`);
|
|
14
14
|
}
|
|
15
|
-
const
|
|
15
|
+
const sessionId = record.get("sessionId");
|
|
16
16
|
const groupName = record.get("groupName");
|
|
17
17
|
if (action === "add") {
|
|
18
18
|
if (!participant)
|
|
@@ -23,40 +23,40 @@ export async function groupManage(params) {
|
|
|
23
23
|
OR p.telephone = $participant)
|
|
24
24
|
AND ${notTrashed("p")}
|
|
25
25
|
WITH p LIMIT 1
|
|
26
|
-
MATCH (c:Conversation {
|
|
26
|
+
MATCH (c:Conversation {sessionId: $sessionId})
|
|
27
27
|
MERGE (p)-[r:PARTICIPATES_IN]->(c)
|
|
28
28
|
ON CREATE SET r.joinedAt = datetime(), r.displayName = p.givenName
|
|
29
|
-
RETURN p.givenName AS name`, { accountId, participant,
|
|
29
|
+
RETURN p.givenName AS name`, { accountId, participant, sessionId });
|
|
30
30
|
const name = addResult.records[0]?.get("name");
|
|
31
31
|
if (!name) {
|
|
32
32
|
throw new Error(`Contact not found: ${participant}`);
|
|
33
33
|
}
|
|
34
|
-
console.error(`[group] participant-added id=${
|
|
34
|
+
console.error(`[group] participant-added id=${sessionId.slice(0, 8)}… name=${name}`);
|
|
35
35
|
}
|
|
36
36
|
else if (action === "remove") {
|
|
37
37
|
if (!participant)
|
|
38
38
|
throw new Error("participant is required for remove action");
|
|
39
|
-
const removeResult = await session.run(`MATCH (p:Person {accountId: $accountId})-[r:PARTICIPATES_IN]->(c:Conversation {
|
|
39
|
+
const removeResult = await session.run(`MATCH (p:Person {accountId: $accountId})-[r:PARTICIPATES_IN]->(c:Conversation {sessionId: $sessionId})
|
|
40
40
|
WHERE (p.givenName + COALESCE(' ' + p.familyName, '') = $participant
|
|
41
41
|
OR p.email = $participant
|
|
42
42
|
OR p.telephone = $participant)
|
|
43
43
|
AND ${notTrashed("p")}
|
|
44
44
|
DELETE r
|
|
45
|
-
RETURN count(r) AS removed`, { accountId, participant,
|
|
45
|
+
RETURN count(r) AS removed`, { accountId, participant, sessionId });
|
|
46
46
|
const removed = removeResult.records[0]?.get("removed")?.toNumber?.() ?? 0;
|
|
47
47
|
if (removed === 0) {
|
|
48
48
|
throw new Error(`Participant not found in group: ${participant}`);
|
|
49
49
|
}
|
|
50
|
-
console.error(`[group] participant-removed id=${
|
|
50
|
+
console.error(`[group] participant-removed id=${sessionId.slice(0, 8)}… name=${participant}`);
|
|
51
51
|
}
|
|
52
52
|
// Always return current participants. Trashed persons are filtered out
|
|
53
53
|
// so the group view reflects active membership only — the PARTICIPATES_IN
|
|
54
54
|
// edge survives soft-delete, but the participant list shouldn't surface
|
|
55
55
|
// them.
|
|
56
|
-
const listResult = await session.run(`MATCH (p:Person)-[r:PARTICIPATES_IN]->(c:Conversation {
|
|
56
|
+
const listResult = await session.run(`MATCH (p:Person)-[r:PARTICIPATES_IN]->(c:Conversation {sessionId: $sessionId})
|
|
57
57
|
WHERE ${notTrashed("p")}
|
|
58
58
|
RETURN r.displayName AS displayName
|
|
59
|
-
ORDER BY r.joinedAt ASC`, {
|
|
59
|
+
ORDER BY r.joinedAt ASC`, { sessionId });
|
|
60
60
|
const participants = listResult.records.map((r) => r.get("displayName"));
|
|
61
61
|
return {
|
|
62
62
|
action,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"group-manage.js","sourceRoot":"","sources":["../../src/tools/group-manage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,8CAA8C,CAAC;AAgB1E,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,MAAyB;IACzD,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,SAAS,EAAE,GAAG,MAAM,CAAC;IAE7D,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAC7B,IAAI,CAAC;QACH,mEAAmE;QACnE,MAAM,WAAW,GAAG,MAAM,OAAO,CAAC,GAAG,CACnC;eACS,UAAU,CAAC,GAAG,CAAC;
|
|
1
|
+
{"version":3,"file":"group-manage.js","sourceRoot":"","sources":["../../src/tools/group-manage.ts"],"names":[],"mappings":"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"}
|
|
@@ -30,11 +30,11 @@ The HMAC secret lives at `~/.${brand}/credentials/admin-session-secret` (mode `0
|
|
|
30
30
|
|
|
31
31
|
The Anthropic SDK is stateless against its own JSONL: every cold-create with `resume: <agentSessionId>` reads `${CLAUDE_CONFIG_DIR}/projects/<encoded-cwd>/<agentSessionId>.jsonl` verbatim. The Maxy graph (`Conversation.agentSessionId`) is just the pointer into the JSONL, not a parallel transcript. The PIN-rebind contract preserves this:
|
|
32
32
|
|
|
33
|
-
1. **Rehydrate** restores `(accountId, userId)` into the in-memory session. `
|
|
33
|
+
1. **Rehydrate** restores `(accountId, userId)` into the in-memory session. `sessionId` and `agentSessionId` are empty.
|
|
34
34
|
2. **Chat-route first POST** (`platform/ui/server/routes/admin/chat.ts`):
|
|
35
35
|
- `consumeWantsPriorConversation(sessionKey)` returns true → look up prior admin conversation.
|
|
36
|
-
- `getMostRecentAdminConversationForUser(accountId, userId)` returns `{
|
|
37
|
-
- `
|
|
36
|
+
- `getMostRecentAdminConversationForUser(accountId, userId)` returns `{sessionId, agentSessionId}` for the most recent admin Conversation node carrying a non-null `agentSessionId`.
|
|
37
|
+
- `setSessionIdForSession(sessionKey, sessionId)` binds the prior `sessionId` so the operator's chat lands in the SAME conversation, not a new one.
|
|
38
38
|
- `setAgentSessionId(sessionKey, agentSessionId)` seeds the in-memory session's pointer; subsequent `invokeAdminAgent`'s `getAgentSessionId(sessionKey)` returns this value naturally.
|
|
39
39
|
3. **`invokeAdminAgent`** passes `resume: <priorAgentSessionId>` to the SDK options. The SDK opens its on-disk JSONL for that session id and continues from there.
|
|
40
40
|
|
|
@@ -50,11 +50,11 @@ The `wantsPriorConversation` marker is the discriminator between continuity and
|
|
|
50
50
|
| Explicit PIN re-entry (`POST /api/admin/session`, `createAdminSession`) | yes | Resume prior conversation |
|
|
51
51
|
| Operator clicks "New conversation" (`POST /api/admin/sessions/new`) | NO | Cold-mint new conversation |
|
|
52
52
|
|
|
53
|
-
Single-shot: the chat-route consumes the marker on the first POST, so subsequent chats in the same session continue with the bound `
|
|
53
|
+
Single-shot: the chat-route consumes the marker on the first POST, so subsequent chats in the same session continue with the bound `sessionId` naturally.
|
|
54
54
|
|
|
55
55
|
## Observability summary
|
|
56
56
|
|
|
57
|
-
Per chat POST, one `[client-acquire]` line lands in the per-conversation stream log at `{accountDir}/logs/claude-agent-stream-<
|
|
57
|
+
Per chat POST, one `[client-acquire]` line lands in the per-conversation stream log at `{accountDir}/logs/claude-agent-stream-<sessionId>.log`:
|
|
58
58
|
|
|
59
59
|
```
|
|
60
60
|
[client-acquire] sessionKey=<sk12>… resume=<priorAgentSessionId8|none> reason=<warm|cold|pin-rebind>
|
|
@@ -116,7 +116,7 @@ At fire time the Stop hook substitutes both placeholders and sends the filled pa
|
|
|
116
116
|
|
|
117
117
|
The envelope walker still runs (so `[turn-recorder] envelope ...` continues to land for observability and the `trigger-skipped reason=conversation-empty` gate still fires on a turns-empty transcript), but its JSON shape never reaches the model.
|
|
118
118
|
|
|
119
|
-
Walker semantics for `turns` (preserved from Task 177): oldest first, newest last; every user / assistant message in the operator's JSONL from session start to the moment the recorder fired; no windowing, no truncation, no env knob; multi-record assistant messages collapse on `message.id`; `tool_use` and `tool_result` blocks are paired by `tool_use_id` so the result attaches to the assistant turn that owned the call rather than fabricating a separate user turn; if `turns` is empty after the walker runs the hook emits `trigger-skipped reason=conversation-empty` and no recorder is spawned. The Task 177 envelope shape — `{turns,
|
|
119
|
+
Walker semantics for `turns` (preserved from Task 177): oldest first, newest last; every user / assistant message in the operator's JSONL from session start to the moment the recorder fired; no windowing, no truncation, no env knob; multi-record assistant messages collapse on `message.id`; `tool_use` and `tool_result` blocks are paired by `tool_use_id` so the result attaches to the assistant turn that owned the call rather than fabricating a separate user turn; if `turns` is empty after the walker runs the hook emits `trigger-skipped reason=conversation-empty` and no recorder is spawned. The Task 177 envelope shape — `{turns, sessionId, accountId, occurredAt}` — is now an internal hook structure; it is not what the model sees.
|
|
120
120
|
|
|
121
121
|
The hook emits two summary lines per fire immediately before `spawn-request`:
|
|
122
122
|
|
|
@@ -83,7 +83,7 @@ either is a regression.
|
|
|
83
83
|
|
|
84
84
|
| Mount | Purpose |
|
|
85
85
|
|---|---|
|
|
86
|
-
| `/logs` | Server log tail with `type=stream\|error\|sse` and `
|
|
86
|
+
| `/logs` | Server log tail with `type=stream\|error\|sse` and `sessionId` filters; powers the in-chat **View logs** popover (see [`internals.md`](internals.md) "Conversations modal — View logs"). |
|
|
87
87
|
| `/events` | Generic SSE event ingest from the UI client. |
|
|
88
88
|
| `/log-ingest` | Loopback-only structured log ingest for MCP and PTY-spawn observability lines (see [`admin-session.md`](admin-session.md) "Memory MCP write-path outcome lines"). |
|
|
89
89
|
| `/claude-info` | Returns Claude CLI binary path, version, and OAuth status. |
|
|
@@ -238,7 +238,7 @@ Public: `[public-query-classifier]` log line with `search`, `effectiveQuery`, `r
|
|
|
238
238
|
|
|
239
239
|
The `:Report` label is the platform's durable shape for workflow output the operator may want back later — daily briefings, dream cycle runs, ad-hoc analyses. Three MCP tools own the surface, all on the memory plugin:
|
|
240
240
|
|
|
241
|
-
- `memory-report-write` — append-only writer. Validates body ≤ 10,000 chars, embeds title+body, and CREATEs a `:Report` node. Idempotent on `(accountId, title, occurredAt-within-same-minute)` — a second call with the same title in the same minute returns the existing node instead of duplicating. Parented to the active `:Conversation` via `:PRODUCED` when `
|
|
241
|
+
- `memory-report-write` — append-only writer. Validates body ≤ 10,000 chars, embeds title+body, and CREATEs a `:Report` node. Idempotent on `(accountId, title, occurredAt-within-same-minute)` — a second call with the same title in the same minute returns the existing node instead of duplicating. Parented to the active `:Conversation` via `:PRODUCED` when `SESSION_NODE_ID` is set (the chat-driven default); falls back to the account's `:AdminUser` so the graph-hierarchy doctrine holds even outside a conversation.
|
|
242
242
|
- `memory-report-read-latest` — fetches the newest `:Report` (default `limit=1`) tagged with a given keyword. The expected route for any operator phrasing of "latest X", "last night's X", "show me X report".
|
|
243
243
|
- `memory-report-list` — metadata-only paginated listing (newest first), with optional `keyword` and `sourceWorkflow` filters. Use to scan the catalogue without paying for full bodies.
|
|
244
244
|
|
|
@@ -316,7 +316,7 @@ This tool is read-only and available to both public and admin agents.
|
|
|
316
316
|
|
|
317
317
|
`:Conversation` nodes on webchat (admin login, "New conversation" in the burger, a new public visitor) are created lazily. Opening the chat or logging in does not write anything to the graph — {{productName}} only records the conversation once the user sends a second message. This keeps `conversation-search` and the Conversations modal free of one-turn abandoned threads. WhatsApp and Telegram take the opposite posture: every inbound — DM or group, allowed or activation-off, agent-invoked or gated — MERGEs the `:Conversation` and writes a forensic `:Message:WhatsAppMessage` row before any access-control decision. The graph is the durable record of every message the device received, not just the ones the agent replied to. See `.docs/web-chat.md` "Deferred conversation persistence" and `.docs/whatsapp.md` "Session continuity" for the full contract.
|
|
318
318
|
|
|
319
|
-
Each row in the Conversations modal exposes a `View logs` row-action that opens a popover with three links — **Stream**, **Errors**, **SSE** — each of which targets `/api/admin/logs?type={stream|error|sse}&
|
|
319
|
+
Each row in the Conversations modal exposes a `View logs` row-action that opens a popover with three links — **Stream**, **Errors**, **SSE** — each of which targets `/api/admin/logs?type={stream|error|sse}&sessionId={full-id}` in a new tab. The row's 8-char id chip is click-to-copy; hover reveals the full `sessionId` as a tooltip. See `.docs/web-chat.md` "In-chat retrieval" for the route contract and `console.debug` observability.
|
|
320
320
|
|
|
321
321
|
### Static publish surface — `/sites/*`
|
|
322
322
|
|
|
@@ -483,7 +483,7 @@ Each ToolCall record contains:
|
|
|
483
483
|
| output | Truncated response text |
|
|
484
484
|
| isError | Whether the tool call resulted in an error |
|
|
485
485
|
| startedAt / completedAt | Timestamps for the invocation |
|
|
486
|
-
|
|
|
486
|
+
| sessionId | Links back to the originating conversation |
|
|
487
487
|
|
|
488
488
|
Records persist indefinitely and are queryable by the admin agent. Ask {{productName}} "what tools ran in the last session?" or "show me all tool calls from today" to review the audit trail.
|
|
489
489
|
|
|
@@ -506,10 +506,10 @@ The doctrine is enforced at the storage primitive: writes to `:Person`, `:UserPr
|
|
|
506
506
|
|
|
507
507
|
Two surfaces emit the lifecycle: agent-driven actions call `work-create`/`work-update`/`work-complete` over MCP (`work-create` accepts `kind`, the canonical `inputsProvided` call-shape record, `inputs` + `inputSchema` for the operator-meaningful form payload, and `raisedDuringConversationKey` to resolve the `RAISED_DURING` edge). Shell-driven actions wrap their script invocation in [platform/ui/app/lib/cloudflare-task-tracker.ts](../../../ui/app/lib/cloudflare-task-tracker.ts) (cloudflare is the first; installer / brand-publish / OAuth-login deferred). Both surfaces emit the same `[task] action-start|step|done` log lines so operators can grep one channel uniformly. Both also call the central `redactSecrets` primitive ([platform/lib/task-secrets/](../../../lib/task-secrets/)) to strip schema-tagged secret keys before persisting `inputs.<field>` props on the Task — see `.docs/neo4j.md § Audit Task input contract` for the contract that replaces per-kind allow-lists.
|
|
508
508
|
|
|
509
|
-
Two surfaces feed the gate. (1) **Workflow path:** `memory-write` accepts an optional `producedByTaskId` parameter. When set, an inbound `:PRODUCED` edge from that Task is composed into the write's relationships before the gate runs — the typical agent-side pattern is to call `work-create` at the start of an autonomous flow, capture `taskId`, and pass it as `producedByTaskId` on every subsequent `memory-write` for a gated label. The gate verifies Task and write share the same `accountId`; mismatch is rejected loud. (2) **Direct-ask path:** the admin server resolves the active `:AdminConversation`'s `
|
|
509
|
+
Two surfaces feed the gate. (1) **Workflow path:** `memory-write` accepts an optional `producedByTaskId` parameter. When set, an inbound `:PRODUCED` edge from that Task is composed into the write's relationships before the gate runs — the typical agent-side pattern is to call `work-create` at the start of an autonomous flow, capture `taskId`, and pass it as `producedByTaskId` on every subsequent `memory-write` for a gated label. The gate verifies Task and write share the same `accountId`; mismatch is rejected loud. (2) **Direct-ask path:** the admin server resolves the active `:AdminConversation`'s `sessionId` UUID and stamps it as `SESSION_NODE_ID` in the spawn env at PTY-spawn time. The same stamp propagates onto specialist subagent spawns the admin dispatches (Task 382) so listing-curator, content-producer, database-operator etc. inherit the same conversation anchor. The `contact-create` and `memory-write` wrappers call `injectConversationProvenance` (exported from [`@maxy/graph-write`](../../../lib/graph-write/src/conversation-provenance.ts)) which MATCHes `(c:Conversation {sessionId, accountId})` — account isolation is part of the natural key, not a separate gate — and prepends the synthetic `:PRODUCED` edge (composed by Neo4j elementId, which the helper reads off the MATCH). No agent-visible schema field changes. `memory-write` uses the env-stamp only as a fallback when `producedByTaskId` is unset; `contact-create` has no `producedByTaskId` parameter today and relies on the env-stamp alone. Autonomous (cron-driven) specialists with no parent conversation legitimately have no env-stamp; those must thread `producedByTaskId`.
|
|
510
510
|
|
|
511
511
|
Operator audit cyphers:
|
|
512
|
-
- "What entities did this conversation's actions produce?" — `MATCH (c:AdminConversation {
|
|
512
|
+
- "What entities did this conversation's actions produce?" — `MATCH (c:AdminConversation {sessionId:$id})<-[:RAISED_DURING]-(t:Task)-[:PRODUCED]->(e) RETURN labels(e), e.name, t.kind, t.status`
|
|
513
513
|
- "What cloudflare resources did this tunnel-login produce?" — `MATCH (t:Task {kind:'cloudflare-tunnel-login', status:'completed'})-[:PRODUCED]->(r) RETURN t.taskId, r.tunnelId, r.hostnameValue ORDER BY t.completedAt DESC`
|
|
514
514
|
|
|
515
515
|
See `.docs/neo4j.md § Process provenance doctrine` for the full enforcement contract, observability surface, and out-of-scope deferrals.
|
|
@@ -40,7 +40,7 @@ These are enabled during onboarding and can be added or removed at any time. Som
|
|
|
40
40
|
| `linkedin-import` | Import a LinkedIn Basic Data Export — Profile and Connections today, more CSVs as references land | Database operator |
|
|
41
41
|
| `notion-import` | Import a Notion workspace export (markdown + CSV) — pages, databases, hierarchy, attachments, schema-bounded relations, `@person` mentions account-filtered | Database operator |
|
|
42
42
|
| `obsidian-import` | Import an extracted Obsidian vault — pages map to `:KnowledgeDocument`, wikilinks resolve to intra-vault pages or existing entities, tags become `:DefinedTerm`, embedded images become `:DigitalDocument`. Two-phase tool (dry-run → operator disambiguation → commit). | Database operator |
|
|
43
|
-
| `x-import` | Import an X (Twitter) Basic Data Export — tweet stream renders as one chronological transcript and ingests as a single `:KnowledgeDocument` (`source='x'`); each DM `
|
|
43
|
+
| `x-import` | Import an X (Twitter) Basic Data Export — tweet stream renders as one chronological transcript and ingests as a single `:KnowledgeDocument` (`source='x'`); each DM `sessionId` ingests as one `:ConversationArchive` (`source='x-dm'`, keyed on `conversationIdentity`) via `conversation-archive-ingest.sh`. Mentions, replies, and quote-tweet authors resolve to `:Person` on lowercased `xHandle`; every handle and DM senderId confirms against existing nodes (no auto-create). Per-thread KD granularity and `:Post` / `:DirectMessage` labels are explicitly rejected. | Database operator |
|
|
44
44
|
| `memory/skills/conversation-archive` | Source-agnostic conversation transcript ingest. One skill for WhatsApp `_chat.txt`, Telegram, Signal, LinkedIn DMs, Zoom transcript, meeting minutes, iMessage, Slack, X DMs — `--source <enum>` selects the per-source normaliser. Single Bash entry — `bash platform/plugins/memory/bin/conversation-archive-ingest.sh <archive> --source <enum> --owner-element-id <id> --participant-person-ids <csv> --scope <admin\|public>` — runs normalise → operator-confirms owner + every distinct sender → sessionize at gap-hours boundaries (default 12h) → classify each session in-turn (the dispatched specialist produces topic-bounded chunk JSON from the parsed lines; the server-side `memory-classify` step was deleted in Task 424, and Task 435 finishes the driver-side cleanup) → memory-ingest with `conversationIdentity` set (writes `:ConversationArchive`), `source=<enum>`. Re-imports are delta-append. Auto-creating participants is forbidden — any sender outside the operator-confirmed closed set LOUD-FAILs with `parser-miss`. Distinct from the live `whatsapp` plugin (Baileys). | Database operator |
|
|
45
45
|
| `memory/skills/conversation-archive-enrich` | Phase 2 for any named `:ConversationArchive` — source-agnostic per-row insight derivation. Operator-triggered (never auto-fires on Phase 1 completion). Walks the parent's `:Section` chunks in pages via the read-only MCP tool `mcp__memory__conversation-archive-derive-insights`; surfaces high-confidence claims for per-row operator gate (`wire / skip / reject`) over four kinds — `mention`, `task`, `preference`, `observed-relationship`. Idempotent on `(elementId(chunk), kind, contentHash)` — re-runs collapse identical claims. Confidence floor is a hedging-avoidance instruction in the system prompt, not a numeric post-filter; per Task 424 the LLM step now runs in-turn from the dispatched specialist rather than as a separate server-side OAuth round-trip. | Database operator |
|
|
46
46
|
|
|
@@ -148,7 +148,7 @@ import { initStderrTee } from "../../../../lib/mcp-stderr-tee/dist/index.js";
|
|
|
148
148
|
initStderrTee("your-plugin-name");
|
|
149
149
|
```
|
|
150
150
|
|
|
151
|
-
After this, every `console.error("[your-tool]...")` from any tool in the plugin appears as `[<iso-ts>] [mcp:your-plugin-name] [your-tool]...` in the per-conversation stream log `claude-agent-stream-{
|
|
151
|
+
After this, every `console.error("[your-tool]...")` from any tool in the plugin appears as `[<iso-ts>] [mcp:your-plugin-name] [your-tool]...` in the per-conversation stream log `claude-agent-stream-{sessionId}.log`, alongside the usual agent events. The raw per-server file `mcp-your-plugin-name-stderr-{date}.log` is still produced for deep-dive grep.
|
|
152
152
|
|
|
153
153
|
**Premium plugins.** Source lives at `premium-plugins/<bundle>/plugins/<name>/mcp/src/` — deeper than platform plugins, so the source-relative import to `platform/lib/mcp-stderr-tee/dist/index.js` uses more `../` segments. The bundler rewrites the compiled output to the canonical `../../../../lib/mcp-stderr-tee/dist/index.js` at staging time and ships `platform/lib/mcp-stderr-tee/{dist,package.json}` into `premium-plugins/<bundle>/lib/mcp-stderr-tee/` so the import resolves at deployed depth. The bundler fails loudly if `platform/lib/mcp-stderr-tee/package.json` is missing (it must pin `type` so install-location parent walks cannot mis-classify the dist file) or if any lib referenced by a rewritten import has no source dist.
|
|
154
154
|
|
|
@@ -158,7 +158,7 @@ After this, every `console.error("[your-tool]...")` from any tool in the plugin
|
|
|
158
158
|
|
|
159
159
|
**Retrieve MCP diagnostic lines for a conversation:**
|
|
160
160
|
|
|
161
|
-
- All servers: `logs-read { type: "system",
|
|
161
|
+
- All servers: `logs-read { type: "system", sessionId: "..." }` → grep `[mcp:<name>]` on the returned stream log.
|
|
162
162
|
- One server raw feed: `logs-read { type: "mcp" }` → tails the most recent `mcp-<name>-stderr-*.log` (per-plugin, not per-conversation).
|
|
163
163
|
|
|
164
164
|
**Tee-state markers** land in the stream log: `[platform] [mcp-tee-attach] server=<name> streamLogPath=...` when the tee wires up, `[platform] [mcp-tee-skip] server=<name> destination=... reason=...` when a destination fails (missing `LOG_DIR`, unwritable path, `STREAM_LOG_PATH` not set, etc.), `[platform] [mcp-tee-detach] server=<name>` on graceful shutdown. If a server invoked tools but no `[mcp:<name>]` lines appear in the conversation's log, look for the skip marker first.
|
|
@@ -80,7 +80,7 @@ tail -200 ~/.maxy/logs/maxy-ui.log | rg '\[remote-auth\].*resolvedKind='
|
|
|
80
80
|
|
|
81
81
|
**Agent searches the filesystem after uploading a zip.** If you uploaded a zip and the agent burns several turns running `find` / `Glob` instead of unzipping, that is the symptom of the recovery-retry attachment-context regression (now closed by the recovery context preservation contract in `.docs/agents.md`). Greppable confirmation is the `[context-overflow-recovery] retry … attachmentsCarried=<n>` line in the conversation stream log. If you see `[context-overflow-recovery] WARN attachment-context-lost`, the regression has returned — surface to support.
|
|
82
82
|
|
|
83
|
-
**Turn budget exhausted with a horizontal rule separating two assistant turns.** When {{productName}} reaches its turn budget and the doubled retry also runs out, the chat now shows a one-paragraph assistant message that opens with `error_max_turns turns=A→B` (initial budget → final budget) followed by the recovery copy: "I reached my turn budget of N before I could finish this request. Try sending a smaller or more focused request, or ask me to use higher effort." That message is persisted to the graph, so the next page-refresh still shows it. The thin horizontal rule labelled "Session restored after timeout." that appears above your following turn signals that the prior turn forced a cold SDK-session restart inside the same conversation (pool eviction) — the agent's response after the rule is from a fresh SDK session even though the conversation thread is unchanged. Greppable post-deploy invariants: `[context-overflow-recovery] exhausted cause=max-turns-interrupted` count equals `[admin-persist] writer=persistMessageExhaust outcome=ok` count for the same
|
|
83
|
+
**Turn budget exhausted with a horizontal rule separating two assistant turns.** When {{productName}} reaches its turn budget and the doubled retry also runs out, the chat now shows a one-paragraph assistant message that opens with `error_max_turns turns=A→B` (initial budget → final budget) followed by the recovery copy: "I reached my turn budget of N before I could finish this request. Try sending a smaller or more focused request, or ask me to use higher effort." That message is persisted to the graph, so the next page-refresh still shows it. The thin horizontal rule labelled "Session restored after timeout." that appears above your following turn signals that the prior turn forced a cold SDK-session restart inside the same conversation (pool eviction) — the agent's response after the rule is from a fresh SDK session even though the conversation thread is unchanged. Greppable post-deploy invariants: `[context-overflow-recovery] exhausted cause=max-turns-interrupted` count equals `[admin-persist] writer=persistMessageExhaust outcome=ok` count for the same sessionId window, and one `[session-store] storeAgentSessionId` line marks the cold-restart that drove the on-screen rule.
|
|
84
84
|
|
|
85
85
|
|
|
86
86
|
**A turn rendered in chat is missing on next page-refresh.** Pre-the 2026-05-07 mandate this was a class of silent failure — Neo4j persists were wrapped in a no-op error catch and a write that threw left the artefact "rendered then disappeared on resume". The 2026-05-07 mandate makes JSONL canonical: the resume route reads the SDK transcript file at `~/.claude/projects/<project-key>/<sessionId>.jsonl` first, supplements from Neo4j, and triggers async heal-on-resume writes for any turn the JSONL has but Neo4j does not. So a refreshed conversation always renders what the SDK saw, regardless of write outcome. If a heal write itself fails, the chat shows a top-of-conversation banner naming the count; if every heal succeeds the resume is silent and the missing rows are quietly restored to Neo4j. Greppable post-deploy invariants in the per-session stream log (`logs/claude-agent-stream-<sessionKey>.log`): `[admin-resume] reason=<…> source=<jsonl|jsonl-missing|neo4j-only>` (one per resume), `[admin-persist] convId=<8> writer=<…> outcome=<ok|fail|skip>` (per persist site), `[admin-persist-heal] convId=<8> turnIndex=<n> outcome=<ok|fail>` (per heal write). To force-audit a specific conversation against its Neo4j projection without re-executing it, run `tsx platform/scripts/admin-persist-audit.ts --conversation-id=<uuid> --account-id=<uuid> --session-id=<uuid>` — non-zero exit + per-divergence `[admin-persist-audit] expected=<message|component> missing reason=neo4j-row-absent` lines name what would have been silently lost pre-mandate.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "email",
|
|
3
|
-
"description": "Email — dedicated email account. Retrieval: email-graph-query for stored email-thread history as :KnowledgeDocument {source:'email'} (recall, search, 'threads about X', 'what did Y send?'); email-read / email-search for live IMAP inbox. Sending: email-send (new), email-reply (threaded). Config: email-setup, email-status, email-otp-extract.",
|
|
3
|
+
"description": "Email — dedicated email account. Retrieval: email-graph-query for stored email-thread history as :KnowledgeDocument {source:'email'} (recall, search, 'threads about X', 'what did Y send?'); email-read / email-search for live IMAP inbox. Ingestion (operator-initiated, human-in-the-loop): email-fetch lists new messages, email-ingest writes the operator-approved subset. Sending: email-send (new), email-reply (threaded). Config: email-setup, email-status, email-otp-extract.",
|
|
4
4
|
"version": "0.1.0",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Rubytech LLC"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: email
|
|
3
|
-
description: "Email — dedicated email account. Retrieval: email-graph-query for stored email-thread history as :KnowledgeDocument {source:'email'} (recall, search, 'threads about X', 'what did Y send?'); email-read / email-search for live IMAP inbox. Sending: email-send (new), email-reply (threaded). Config: email-setup, email-status, email-otp-extract."
|
|
3
|
+
description: "Email — dedicated email account. Retrieval: email-graph-query for stored email-thread history as :KnowledgeDocument {source:'email'} (recall, search, 'threads about X', 'what did Y send?'); email-read / email-search for live IMAP inbox. Ingestion (operator-initiated, human-in-the-loop): email-fetch lists new messages, email-ingest writes the operator-approved subset. Sending: email-send (new), email-reply (threaded). Config: email-setup, email-status, email-otp-extract."
|
|
4
4
|
tools:
|
|
5
5
|
- name: email-setup
|
|
6
6
|
publicAllowlist: false
|
|
@@ -20,6 +20,12 @@ tools:
|
|
|
20
20
|
- name: email-graph-query
|
|
21
21
|
publicAllowlist: false
|
|
22
22
|
adminAllowlist: false
|
|
23
|
+
- name: email-fetch
|
|
24
|
+
publicAllowlist: false
|
|
25
|
+
adminAllowlist: false
|
|
26
|
+
- name: email-ingest
|
|
27
|
+
publicAllowlist: false
|
|
28
|
+
adminAllowlist: false
|
|
23
29
|
- name: email-otp-extract
|
|
24
30
|
publicAllowlist: false
|
|
25
31
|
adminAllowlist: false
|
|
@@ -56,10 +62,16 @@ Manages the agent's own dedicated email account — IMAP for reading, SMTP for s
|
|
|
56
62
|
- **Search inbox:** `email-search` — live IMAP search by sender, subject, body keyword, date range.
|
|
57
63
|
- **Send:** `email-send` — new outbound email.
|
|
58
64
|
- **Reply:** `email-reply` — threaded reply to an existing email by `messageId`. Supports `replyAll`.
|
|
65
|
+
- **Ingestion — fetch:** `email-fetch` — list new IMAP messages since the stored high-water mark. Metadata + body preview only. No graph writes, no classification. Stages the batch in-memory for `email-ingest`.
|
|
66
|
+
- **Ingestion — apply:** `email-ingest` — apply the operator's per-message decisions to the staged batch. Each Message-ID must carry a disposition (`ingest` or `discard`). Writes only the approved subset and advances the inbox high-water mark.
|
|
59
67
|
- **Recall/history:** `email-graph-query` — search stored email threads in Neo4j by natural language, sender, date, direction. Each thread is one `:KnowledgeDocument {source:'email'}` carrying the verbatim chronological transcript with `:Person` `FROM`/`TO`/`CC` edges.
|
|
60
68
|
- **Status:** `email-status` — connection health and configuration state.
|
|
61
69
|
- **OTP:** `email-otp-extract` — poll for verification codes during service authentication.
|
|
62
70
|
|
|
71
|
+
## Ingestion model
|
|
72
|
+
|
|
73
|
+
Email ingestion is **operator-initiated and human-in-the-loop**. There is no background poll, cron, or auto-classifier. New messages enter the graph only when the operator says "check my emails" and approves each one. See `skills/email-ingest/SKILL.md` for the conversation flow and `skills/email-composition/SKILL.md` for drafting replies once a thread is stored.
|
|
74
|
+
|
|
63
75
|
## Retrieval paths
|
|
64
76
|
|
|
65
77
|
- **Live inbox** (`email-read`, `email-search`) — real-time IMAP queries. Use for checking the inbox or reading recent messages.
|
|
@@ -70,12 +82,13 @@ Manages the agent's own dedicated email account — IMAP for reading, SMTP for s
|
|
|
70
82
|
|
|
71
83
|
| Skill | Purpose |
|
|
72
84
|
|-------|---------|
|
|
85
|
+
| [email-ingest](skills/email-ingest/SKILL.md) | Operator-initiated ingestion. Drives "check my emails" → list via `email-fetch` → summarise → ask the operator per message → write the approved subset via `email-ingest`. |
|
|
73
86
|
| [email-composition](skills/email-composition/SKILL.md) | Conversational wrapper for drafting replies, new emails, and inbox triage. Orchestrates the five `email-*` tools with human-in-the-loop approval on every send. |
|
|
74
87
|
|
|
75
88
|
## References
|
|
76
89
|
|
|
77
90
|
| Reference | Topics |
|
|
78
91
|
|-----------|--------|
|
|
79
|
-
| [email-reference.md](references/email-reference.md) | Setup form fields, pagination, filtering, replying, alias support,
|
|
92
|
+
| [email-reference.md](references/email-reference.md) | Setup form fields, pagination, filtering, replying, alias support, operator-initiated ingestion, threading, OTP integration |
|
|
80
93
|
|
|
81
94
|
Load the reference via `plugin-read` when detailed configuration or behaviour information is needed.
|