@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.
Files changed (233) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/lib/admin-conversation-purge/dist/index.d.ts +1 -1
  3. package/payload/platform/lib/admin-conversation-purge/dist/index.d.ts.map +1 -1
  4. package/payload/platform/lib/admin-conversation-purge/dist/index.js +4 -4
  5. package/payload/platform/lib/admin-conversation-purge/dist/index.js.map +1 -1
  6. package/payload/platform/lib/admin-conversation-purge/src/index.ts +5 -5
  7. package/payload/platform/lib/graph-style/dist/index.js +2 -2
  8. package/payload/platform/lib/graph-style/dist/index.js.map +1 -1
  9. package/payload/platform/lib/graph-style/src/__tests__/parity.test.ts +1 -1
  10. package/payload/platform/lib/graph-style/src/index.ts +2 -2
  11. package/payload/platform/lib/graph-trash/dist/index.js +1 -1
  12. package/payload/platform/lib/graph-trash/dist/index.js.map +1 -1
  13. package/payload/platform/lib/graph-trash/src/index.ts +1 -1
  14. package/payload/platform/lib/graph-write/dist/__tests__/action-provenance-gate.test.js +1 -1
  15. package/payload/platform/lib/graph-write/dist/__tests__/action-provenance-gate.test.js.map +1 -1
  16. package/payload/platform/lib/graph-write/dist/conversation-provenance.d.ts +3 -3
  17. package/payload/platform/lib/graph-write/dist/conversation-provenance.js +5 -5
  18. package/payload/platform/lib/graph-write/dist/conversation-provenance.js.map +1 -1
  19. package/payload/platform/lib/graph-write/dist/index.js +1 -1
  20. package/payload/platform/lib/graph-write/dist/index.js.map +1 -1
  21. package/payload/platform/lib/graph-write/src/__tests__/action-provenance-gate.test.ts +1 -1
  22. package/payload/platform/lib/graph-write/src/conversation-provenance.ts +8 -8
  23. package/payload/platform/lib/graph-write/src/index.ts +1 -1
  24. package/payload/platform/neo4j/schema.cypher +30 -13
  25. package/payload/platform/plugins/admin/.claude-plugin/plugin.json +1 -1
  26. package/payload/platform/plugins/admin/PLUGIN.md +8 -4
  27. package/payload/platform/plugins/admin/hooks/__tests__/archive-ingest-surface-gate.test.sh +1 -1
  28. package/payload/platform/plugins/admin/hooks/__tests__/per-turn-graph-pass-gate.test.sh +361 -0
  29. package/payload/platform/plugins/admin/hooks/__tests__/pre-turn-graph-pass.test.sh +13 -13
  30. package/payload/platform/plugins/admin/hooks/__tests__/turn-completed-graph-write.test.sh +1 -1
  31. package/payload/platform/plugins/admin/hooks/lib/admin-graph-pass-common.sh +102 -0
  32. package/payload/platform/plugins/admin/hooks/per-turn-graph-pass-gate.sh +106 -0
  33. package/payload/platform/plugins/admin/hooks/pre-turn-graph-pass.sh +15 -8
  34. package/payload/platform/plugins/admin/hooks/turn-completed-graph-write.sh +4 -4
  35. package/payload/platform/plugins/admin/mcp/dist/index.js +65 -24
  36. package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
  37. package/payload/platform/plugins/admin/skills/session-management/SKILL.md +2 -2
  38. package/payload/platform/plugins/admin/skills/stream-log-review/SKILL.md +5 -5
  39. package/payload/platform/plugins/admin/skills/stream-log-review/references/analysis-patterns.md +6 -6
  40. package/payload/platform/plugins/business-assistant/references/profiling.md +1 -1
  41. package/payload/platform/plugins/contacts/PLUGIN.md +1 -1
  42. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-create.js +2 -2
  43. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-create.js.map +1 -1
  44. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-erase.js +3 -3
  45. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-export.d.ts +1 -1
  46. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-export.js +2 -2
  47. package/payload/platform/plugins/contacts/mcp/dist/tools/group-create.d.ts +1 -1
  48. package/payload/platform/plugins/contacts/mcp/dist/tools/group-create.d.ts.map +1 -1
  49. package/payload/platform/plugins/contacts/mcp/dist/tools/group-create.js +4 -4
  50. package/payload/platform/plugins/contacts/mcp/dist/tools/group-create.js.map +1 -1
  51. package/payload/platform/plugins/contacts/mcp/dist/tools/group-manage.js +10 -10
  52. package/payload/platform/plugins/contacts/mcp/dist/tools/group-manage.js.map +1 -1
  53. package/payload/platform/plugins/docs/references/admin-session.md +6 -6
  54. package/payload/platform/plugins/docs/references/admin-ui.md +1 -1
  55. package/payload/platform/plugins/docs/references/internals.md +5 -5
  56. package/payload/platform/plugins/docs/references/plugins-guide.md +3 -3
  57. package/payload/platform/plugins/docs/references/troubleshooting.md +1 -1
  58. package/payload/platform/plugins/email/.claude-plugin/plugin.json +1 -1
  59. package/payload/platform/plugins/email/PLUGIN.md +15 -2
  60. package/payload/platform/plugins/email/mcp/dist/index.js +53 -0
  61. package/payload/platform/plugins/email/mcp/dist/index.js.map +1 -1
  62. package/payload/platform/plugins/email/mcp/dist/lib/embedding.js +2 -2
  63. package/payload/platform/plugins/email/mcp/dist/lib/embedding.js.map +1 -1
  64. package/payload/platform/plugins/email/mcp/dist/lib/graph.js +1 -1
  65. package/payload/platform/plugins/email/mcp/dist/lib/graph.js.map +1 -1
  66. package/payload/platform/plugins/email/mcp/dist/lib/imap.d.ts +1 -1
  67. package/payload/platform/plugins/email/mcp/dist/lib/ingest-batch.d.ts +23 -0
  68. package/payload/platform/plugins/email/mcp/dist/lib/ingest-batch.d.ts.map +1 -0
  69. package/payload/platform/plugins/email/mcp/dist/lib/ingest-batch.js +15 -0
  70. package/payload/platform/plugins/email/mcp/dist/lib/ingest-batch.js.map +1 -0
  71. package/payload/platform/plugins/email/mcp/dist/tools/email-fetch.d.ts +15 -0
  72. package/payload/platform/plugins/email/mcp/dist/tools/email-fetch.d.ts.map +1 -0
  73. package/payload/platform/plugins/email/mcp/dist/tools/email-fetch.js +49 -0
  74. package/payload/platform/plugins/email/mcp/dist/tools/email-fetch.js.map +1 -0
  75. package/payload/platform/plugins/email/mcp/dist/tools/email-ingest.d.ts +20 -0
  76. package/payload/platform/plugins/email/mcp/dist/tools/email-ingest.d.ts.map +1 -0
  77. package/payload/platform/plugins/email/mcp/dist/tools/email-ingest.js +86 -0
  78. package/payload/platform/plugins/email/mcp/dist/tools/email-ingest.js.map +1 -0
  79. package/payload/platform/plugins/email/mcp/dist/tools/email-setup.d.ts.map +1 -1
  80. package/payload/platform/plugins/email/mcp/dist/tools/email-setup.js +32 -52
  81. package/payload/platform/plugins/email/mcp/dist/tools/email-setup.js.map +1 -1
  82. package/payload/platform/plugins/email/references/email-reference.md +19 -83
  83. package/payload/platform/plugins/email/skills/email-ingest/SKILL.md +87 -0
  84. package/payload/platform/plugins/memory/PLUGIN.md +1 -1
  85. package/payload/platform/plugins/memory/mcp/dist/index.js +29 -29
  86. package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
  87. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/x-dm.js +2 -2
  88. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/x-dm.js.map +1 -1
  89. package/payload/platform/plugins/memory/mcp/dist/lib/graph-prune.d.ts +3 -3
  90. package/payload/platform/plugins/memory/mcp/dist/lib/graph-prune.d.ts.map +1 -1
  91. package/payload/platform/plugins/memory/mcp/dist/lib/graph-prune.js +6 -6
  92. package/payload/platform/plugins/memory/mcp/dist/lib/graph-prune.js.map +1 -1
  93. package/payload/platform/plugins/memory/mcp/dist/lib/log-ingest.js +1 -1
  94. package/payload/platform/plugins/memory/mcp/dist/lib/log-ingest.js.map +1 -1
  95. package/payload/platform/plugins/memory/mcp/dist/lib/neo4j.d.ts +2 -2
  96. package/payload/platform/plugins/memory/mcp/dist/lib/neo4j.js +2 -2
  97. package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-pass.d.ts +1 -1
  98. package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-pass.d.ts.map +1 -1
  99. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-memory-expunge-emit.test.js +3 -3
  100. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-memory-expunge-emit.test.js.map +1 -1
  101. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/log-ingest.test.js +2 -2
  102. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/log-ingest.test.js.map +1 -1
  103. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-empty-trash-admin-conversation.test.js +8 -8
  104. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-empty-trash-admin-conversation.test.js.map +1 -1
  105. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-report-tools.test.js +2 -2
  106. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-report-tools.test.js.map +1 -1
  107. package/payload/platform/plugins/memory/mcp/dist/tools/conversation-memory-expunge.d.ts +1 -1
  108. package/payload/platform/plugins/memory/mcp/dist/tools/conversation-memory-expunge.d.ts.map +1 -1
  109. package/payload/platform/plugins/memory/mcp/dist/tools/conversation-memory-expunge.js +2 -2
  110. package/payload/platform/plugins/memory/mcp/dist/tools/conversation-memory-expunge.js.map +1 -1
  111. package/payload/platform/plugins/memory/mcp/dist/tools/memory-brain-capture-recent.d.ts +2 -2
  112. package/payload/platform/plugins/memory/mcp/dist/tools/memory-brain-capture-recent.d.ts.map +1 -1
  113. package/payload/platform/plugins/memory/mcp/dist/tools/memory-brain-capture-recent.js +4 -4
  114. package/payload/platform/plugins/memory/mcp/dist/tools/memory-brain-capture-recent.js.map +1 -1
  115. package/payload/platform/plugins/memory/mcp/dist/tools/memory-empty-trash.d.ts +1 -1
  116. package/payload/platform/plugins/memory/mcp/dist/tools/memory-empty-trash.js +8 -8
  117. package/payload/platform/plugins/memory/mcp/dist/tools/memory-empty-trash.js.map +1 -1
  118. package/payload/platform/plugins/memory/mcp/dist/tools/memory-find-candidates.d.ts +1 -1
  119. package/payload/platform/plugins/memory/mcp/dist/tools/memory-find-candidates.d.ts.map +1 -1
  120. package/payload/platform/plugins/memory/mcp/dist/tools/memory-find-candidates.js +2 -2
  121. package/payload/platform/plugins/memory/mcp/dist/tools/memory-find-candidates.js.map +1 -1
  122. package/payload/platform/plugins/memory/mcp/dist/tools/memory-report-write.d.ts +1 -1
  123. package/payload/platform/plugins/memory/mcp/dist/tools/memory-report-write.js +1 -1
  124. package/payload/platform/plugins/memory/mcp/dist/tools/memory-typed-edge-pass.d.ts +1 -1
  125. package/payload/platform/plugins/memory/mcp/dist/tools/memory-typed-edge-pass.d.ts.map +1 -1
  126. package/payload/platform/plugins/memory/mcp/dist/tools/memory-typed-edge-pass.js +2 -2
  127. package/payload/platform/plugins/memory/mcp/dist/tools/memory-typed-edge-pass.js.map +1 -1
  128. package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.js +2 -2
  129. package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.js.map +1 -1
  130. package/payload/platform/plugins/memory/mcp/dist/tools/profile-update.d.ts +1 -1
  131. package/payload/platform/plugins/memory/mcp/dist/tools/profile-update.d.ts.map +1 -1
  132. package/payload/platform/plugins/memory/mcp/dist/tools/profile-update.js +11 -11
  133. package/payload/platform/plugins/memory/mcp/dist/tools/profile-update.js.map +1 -1
  134. package/payload/platform/plugins/memory/mcp/scripts/backfill-typed-edges.ts +1 -1
  135. package/payload/platform/plugins/memory/mcp/scripts/graph/fixture.cypher +1 -1
  136. package/payload/platform/plugins/memory/references/graph-primitives.md +1 -1
  137. package/payload/platform/plugins/memory/references/schema-base.md +4 -4
  138. package/payload/platform/plugins/memory/skills/conversational-memory/SKILL.md +1 -1
  139. package/payload/platform/plugins/whatsapp/PLUGIN.md +1 -1
  140. package/payload/platform/plugins/whatsapp/mcp/dist/index.js +2 -2
  141. package/payload/platform/plugins/whatsapp/mcp/dist/index.js.map +1 -1
  142. package/payload/platform/plugins/work/mcp/dist/index.js +2 -2
  143. package/payload/platform/plugins/work/mcp/dist/index.js.map +1 -1
  144. package/payload/platform/plugins/work/mcp/dist/tools/project-create.js +6 -6
  145. package/payload/platform/plugins/work/mcp/dist/tools/project-create.js.map +1 -1
  146. package/payload/platform/plugins/work/mcp/dist/tools/session-list.d.ts +1 -1
  147. package/payload/platform/plugins/work/mcp/dist/tools/session-list.d.ts.map +1 -1
  148. package/payload/platform/plugins/work/mcp/dist/tools/session-list.js +1 -1
  149. package/payload/platform/plugins/work/mcp/dist/tools/session-list.js.map +1 -1
  150. package/payload/platform/plugins/x-import/references/archive-shape.md +2 -2
  151. package/payload/platform/plugins/x-import/skills/x-import/SKILL.md +3 -3
  152. package/payload/platform/scripts/admin-persist-audit.ts +18 -18
  153. package/payload/platform/scripts/identity-forbidden-token-check.mjs +2 -0
  154. package/payload/platform/scripts/seed-neo4j.sh +1 -0
  155. package/payload/platform/services/claude-session-manager/dist/http-server.js +3 -3
  156. package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
  157. package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts +3 -3
  158. package/payload/platform/services/claude-session-manager/dist/pty-spawner.js +4 -4
  159. package/payload/platform/services/claude-session-manager/dist/pty-spawner.js.map +1 -1
  160. package/payload/platform/services/claude-session-manager/dist/system-prompt.d.ts.map +1 -1
  161. package/payload/platform/services/claude-session-manager/dist/system-prompt.js +2 -0
  162. package/payload/platform/services/claude-session-manager/dist/system-prompt.js.map +1 -1
  163. package/payload/platform/templates/specialists/agents/personal-assistant.md +1 -1
  164. package/payload/server/{chunk-AXOL2PPG.js → chunk-3TRIXQSJ.js} +101 -101
  165. package/payload/server/maxy-edge.js +1 -1
  166. package/payload/server/public/assets/{admin-3fLFD5h_.js → admin-Dal5FWaD.js} +2 -2
  167. package/payload/server/public/assets/{architectureDiagram-Q4EWVU46-Breg9-99.js → architectureDiagram-Q4EWVU46-Do2zYONG.js} +1 -1
  168. package/payload/server/public/assets/{blockDiagram-DXYQGD6D-DXf1_673.js → blockDiagram-DXYQGD6D-DpIX_bRu.js} +1 -1
  169. package/payload/server/public/assets/{c4Diagram-AHTNJAMY-CSZ36W4-.js → c4Diagram-AHTNJAMY-Cz335ZSY.js} +1 -1
  170. package/payload/server/public/assets/channel-PC4_IjI1.js +1 -0
  171. package/payload/server/public/assets/{chunk-336JU56O-DsrLk2eK.js → chunk-336JU56O-Dmknn3Wo.js} +2 -2
  172. package/payload/server/public/assets/{chunk-426QAEUC-JpNfNf81.js → chunk-426QAEUC-ClfGjizN.js} +1 -1
  173. package/payload/server/public/assets/{chunk-4TB4RGXK-DmClEAD0.js → chunk-4TB4RGXK-BPKctJ5c.js} +1 -1
  174. package/payload/server/public/assets/{chunk-5FUZZQ4R-BI9blW3N.js → chunk-5FUZZQ4R-BWDCO9zw.js} +1 -1
  175. package/payload/server/public/assets/{chunk-5PVQY5BW-BbgttEFO.js → chunk-5PVQY5BW-BE34_Db0.js} +1 -1
  176. package/payload/server/public/assets/{chunk-EDXVE4YY-BX_LCFOx.js → chunk-EDXVE4YY-BysA-_6v.js} +1 -1
  177. package/payload/server/public/assets/{chunk-ENJZ2VHE-Bb7EoD0w.js → chunk-ENJZ2VHE-BMVyMsqA.js} +1 -1
  178. package/payload/server/public/assets/{chunk-ICPOFSXX-DH8uQk-s.js → chunk-ICPOFSXX-C5KRdLV4.js} +1 -1
  179. package/payload/server/public/assets/{chunk-OYMX7WX6-FH5kgXsw.js → chunk-OYMX7WX6-DVZD-AVc.js} +1 -1
  180. package/payload/server/public/assets/{chunk-U2HBQHQK-D_ljlkHr.js → chunk-U2HBQHQK-DYmQdx8x.js} +1 -1
  181. package/payload/server/public/assets/{chunk-X2U36JSP-BX3EmZvm.js → chunk-X2U36JSP-DrZenIl3.js} +1 -1
  182. package/payload/server/public/assets/{chunk-YZCP3GAM-Vu7-E93h.js → chunk-YZCP3GAM-CDuGbvMq.js} +1 -1
  183. package/payload/server/public/assets/{chunk-ZZ45TVLE-CwjhNPX5.js → chunk-ZZ45TVLE-COztbiu5.js} +1 -1
  184. package/payload/server/public/assets/classDiagram-6PBFFD2Q-B_pMa-SX.js +1 -0
  185. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-BdBAgF20.js +1 -0
  186. package/payload/server/public/assets/clone-CkNt9L9r.js +1 -0
  187. package/payload/server/public/assets/{dagre-Ce6gsj0C.js → dagre-Cv9Ib2OM.js} +1 -1
  188. package/payload/server/public/assets/{dagre-KV5264BT-BaMGpsoy.js → dagre-KV5264BT-CoEd61KZ.js} +1 -1
  189. package/payload/server/public/assets/{data-BHASh0_Y.js → data-DbSORCl4.js} +1 -1
  190. package/payload/server/public/assets/{diagram-5BDNPKRD-CHEE9rjq.js → diagram-5BDNPKRD-WXNzw3uW.js} +1 -1
  191. package/payload/server/public/assets/{diagram-G4DWMVQ6-C98sZLW1.js → diagram-G4DWMVQ6-C6IuQ2VV.js} +1 -1
  192. package/payload/server/public/assets/{diagram-MMDJMWI5-DNvMGsTZ.js → diagram-MMDJMWI5-CdJdir5A.js} +1 -1
  193. package/payload/server/public/assets/{diagram-TYMM5635-Cdte4IBa.js → diagram-TYMM5635-DxWKQH5T.js} +1 -1
  194. package/payload/server/public/assets/{erDiagram-SMLLAGMA-C9VZsWXK.js → erDiagram-SMLLAGMA-C9fvs33K.js} +1 -1
  195. package/payload/server/public/assets/{flowDiagram-DWJPFMVM-tuP5fzzR.js → flowDiagram-DWJPFMVM-BO7Yrbqv.js} +1 -1
  196. package/payload/server/public/assets/{ganttDiagram-T4ZO3ILL-SJgRPUwx.js → ganttDiagram-T4ZO3ILL-CQJyWBZq.js} +1 -1
  197. package/payload/server/public/assets/{gitGraphDiagram-UUTBAWPF-DU_cI_50.js → gitGraphDiagram-UUTBAWPF-DZfQHrYw.js} +1 -1
  198. package/payload/server/public/assets/{graph-labels-DXlmm1og.js → graph-labels-BBB5jsZk.js} +1 -1
  199. package/payload/server/public/assets/{graph-BhEI09tF.js → graph-ys_joP2o.js} +1 -1
  200. package/payload/server/public/assets/{graphlib-D_nAsvmx.js → graphlib-C40H-Q5E.js} +1 -1
  201. package/payload/server/public/assets/{infoDiagram-42DDH7IO-Cj2Y19m6.js → infoDiagram-42DDH7IO-CakfV5f9.js} +1 -1
  202. package/payload/server/public/assets/{ishikawaDiagram-UXIWVN3A-DMc1xq1y.js → ishikawaDiagram-UXIWVN3A-CPuBPyfa.js} +1 -1
  203. package/payload/server/public/assets/{journeyDiagram-VCZTEJTY-C4CRAQma.js → journeyDiagram-VCZTEJTY-zpZm2Mmo.js} +1 -1
  204. package/payload/server/public/assets/{kanban-definition-6JOO6SKY-CTr4AldU.js → kanban-definition-6JOO6SKY-DfJduQCo.js} +1 -1
  205. package/payload/server/public/assets/{line-Btlm_IAl.js → line-BpYQqO5R.js} +1 -1
  206. package/payload/server/public/assets/{mermaid-parser.core-DXFdj_y1.js → mermaid-parser.core-C5Mwi14D.js} +1 -1
  207. package/payload/server/public/assets/{mermaid.core-DFBhoCr5.js → mermaid.core-D8qBtvvT.js} +3 -3
  208. package/payload/server/public/assets/{mindmap-definition-QFDTVHPH-r9gVQybo.js → mindmap-definition-QFDTVHPH-Bli9JhIN.js} +1 -1
  209. package/payload/server/public/assets/{page-CDWu1Aft.js → page--bl5Y7ZI.js} +2 -2
  210. package/payload/server/public/assets/page-CwmZ76U7.js +1 -0
  211. package/payload/server/public/assets/{pieDiagram-DEJITSTG-CHKZjSaH.js → pieDiagram-DEJITSTG-MsLXTSLg.js} +1 -1
  212. package/payload/server/public/assets/{public-DyGWgfaZ.js → public-DltgEfA9.js} +2 -2
  213. package/payload/server/public/assets/{quadrantDiagram-34T5L4WZ-CSGR1HJr.js → quadrantDiagram-34T5L4WZ-De1sh2K0.js} +1 -1
  214. package/payload/server/public/assets/{requirementDiagram-MS252O5E-DZ6hX9D6.js → requirementDiagram-MS252O5E-D5Sfg1t_.js} +1 -1
  215. package/payload/server/public/assets/{sankeyDiagram-XADWPNL6-DbZBKh0m.js → sankeyDiagram-XADWPNL6-DHA3LIbv.js} +1 -1
  216. package/payload/server/public/assets/{sequenceDiagram-FGHM5R23-BHHpb8dt.js → sequenceDiagram-FGHM5R23-BE_QlG1B.js} +1 -1
  217. package/payload/server/public/assets/{stateDiagram-FHFEXIEX-DQ1jiLB4.js → stateDiagram-FHFEXIEX-NIwp3F4u.js} +1 -1
  218. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-pfk2F6st.js +1 -0
  219. package/payload/server/public/assets/{timeline-definition-GMOUNBTQ-BlGiEU7p.js → timeline-definition-GMOUNBTQ-CPE9jyDF.js} +1 -1
  220. package/payload/server/public/assets/{vennDiagram-DHZGUBPP-DmEH-hsB.js → vennDiagram-DHZGUBPP-CKfoyYmH.js} +1 -1
  221. package/payload/server/public/assets/{wardleyDiagram-NUSXRM2D-C7KJJ40d.js → wardleyDiagram-NUSXRM2D-B9yJek-o.js} +1 -1
  222. package/payload/server/public/assets/{xychartDiagram-5P7HB3ND-JDnusCaa.js → xychartDiagram-5P7HB3ND-DuCcSLqX.js} +1 -1
  223. package/payload/server/public/data.html +3 -3
  224. package/payload/server/public/graph.html +3 -3
  225. package/payload/server/public/index.html +4 -4
  226. package/payload/server/public/public.html +1 -1
  227. package/payload/server/server.js +133 -133
  228. package/payload/server/public/assets/channel-BmZnt3PP.js +0 -1
  229. package/payload/server/public/assets/classDiagram-6PBFFD2Q-kmMLFUpV.js +0 -1
  230. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-BV7Ae8ct.js +0 -1
  231. package/payload/server/public/assets/clone-B5eqoN9I.js +0 -1
  232. package/payload/server/public/assets/page-cyvshX4Z.js +0 -1
  233. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-CByT2RzF.js +0 -1
@@ -54,7 +54,7 @@ The tool accepts the `messageId` of the email being replied to (visible in `emai
54
54
  - **Reply to sender:** Default behaviour — replies to the original sender only.
55
55
  - **Reply all:** Set `replyAll: true` to include all original recipients (TO + CC). The agent's own address is automatically excluded from the recipient list.
56
56
  - **Threading:** The reply appears in the same conversation thread in Gmail, Apple Mail, Outlook, and other RFC 2822-compliant clients.
57
- - **Prerequisite:** The original email must exist in the graph (stored by the background polling job). If the email hasn't been fetched yet, the tool returns a clear error.
57
+ - **Prerequisite:** The original email must exist in the graph (ingested via the operator-initiated `email-ingest` flow). If the message hasn't been ingested yet, the tool returns a clear error.
58
58
 
59
59
  Use `email-reply` when responding to a received email. Use `email-send` for new outbound messages.
60
60
 
@@ -71,26 +71,28 @@ When `agentAddress` is not set or matches the auth email, all tools behave as be
71
71
 
72
72
  ## Email Persistence
73
73
 
74
- Emails are fetched from IMAP and stored as `Email` nodes in the graph. The fetcher binary lives at `email/mcp/dist/scripts/email-fetch.js`. It is **not currently scheduled on any install** — migration to Desktop scheduled tasks (the canonical dispatch surface, see `maxy-code-prd.md` §Scheduled tasks) is tracked separately. Until that landing, new email is only ingested when an operator invokes the fetcher manually.
74
+ Emails enter the graph as `:KnowledgeDocument {source:'email'}` thread documents via the **operator-initiated ingestion flow** (see `skills/email-ingest/SKILL.md`). There is no background poll, cron, or auto-classifier new messages are written only when the operator says "check my emails" and approves each one.
75
75
 
76
- - **Polling:** After `email-setup` completes, the platform polls IMAP at the configured interval (default: every 5 minutes). Only emails addressed TO the agent's `agentAddress` are stored.
77
- - **Deduplication:** Each email is identified by its Message-ID header. Re-polling the same messages does not create duplicates, even if the agent's email address changes between poll cycles. A composite unique constraint on `(messageId, accountId)` provides database-level enforcement.
78
- - **Semantic search:** Stored emails are vector-indexed (subject + body preview), enabling natural-language search over email history via `email-graph-query`.
79
- - **Isolation:** Each agent sees only emails addressed to its own bound email address, even when sharing a catchall mailbox.
76
+ The two ingestion tools:
80
77
 
81
- ## Email Threading
78
+ - **`email-fetch`** — lists new IMAP messages since the stored high-water mark (`lastFetchedUid` on the `:EmailAccount` node). Returns sender, subject, date, Message-ID, UID, and a body preview. Writes nothing to the graph; stages the batch in-memory for the follow-up `email-ingest` call.
79
+ - **`email-ingest`** — takes a `decisions` array (`messageId` + `ingest` or `discard` per message). Writes only the `ingest` subset to the graph, advances `lastFetchedUid` to the batch's max UID, and consumes the staged batch. Refuses if any pending Message-ID lacks a decision.
82
80
 
83
- Emails are linked into conversation threads via `REPLY_TO` graph edges. When an email has an `In-Reply-To` header, the platform looks up the parent email by `Message-ID` within the same account and creates an edge. Thread linking happens as part of each fetch run (which is operator-invoked until the dispatcher is wired — see above).
81
+ Properties of the persistence layer:
84
82
 
85
- - **Out-of-order delivery:** If a reply arrives before its parent, the edge is created later when the parent is stored (orphan back-fill).
86
- - **Thread context:** `email-read` and `email-search` include `Thread-Depth` (number of hops to the thread root) and `Thread-ID` (emailId of the root message) for any email that is part of a thread. Root emails (no parent) have no thread fields.
87
- - **Scope:** Thread edges never cross account boundaries parent lookups are always scoped to the same account.
83
+ - **Operator-initiated only.** No `setInterval`, cron, or systemd timer ever invokes `email-fetch`. The operator drives every cycle.
84
+ - **Deduplication:** Each message is identified by Message-ID. Re-ingesting the same message MERGEs without duplicating; a composite unique constraint on `(messageId, accountId)` provides database-level enforcement.
85
+ - **Alias filtering:** Only emails addressed TO the agent's `agentAddress` are listed and ingested.
86
+ - **Semantic search:** Ingested threads are vector-indexed (subject + body preview), enabling natural-language search via `email-graph-query`.
87
+ - **Isolation:** Each agent sees only emails addressed to its own bound email address, even when sharing a catchall mailbox.
88
88
 
89
- ## Auto-Respond Audit Trail
89
+ ## Email Threading
90
90
 
91
- When auto-respond sends a reply, the outbound message is stored as an `Email` node with `direction: "outbound"` and a `REPLY_TO` edge to the original inbound email. This creates a queryable audit trail of every automated reply — what the agent said, when, and to whom.
91
+ Ingested messages are linked into conversation threads as one `:KnowledgeDocument {source:'email'}` per thread, with `:Person` `FROM`/`TO`/`CC` edges. Threading is resolved by `In-Reply-To`/`References` headers at ingest time.
92
92
 
93
- Outbound email nodes have the same properties as inbound emails (subject, bodyPreview, fromAddress, toAddresses, timestamps) plus the `direction` property. They appear in thread traversals alongside inbound messages.
93
+ - **Out-of-order arrival:** If a reply is ingested before its parent, the reply lives in its own thread until the parent is ingested, at which point future ingests fold them together via the shared root.
94
+ - **Thread context:** `email-read` and `email-search` include `Thread-Depth` (number of hops to the thread root) and `Thread-ID` (emailId of the root message) for any message already in the graph. Root emails (no parent) have no thread fields.
95
+ - **Scope:** Thread linkage never crosses account boundaries — parent lookups are always scoped to the same `accountId`.
94
96
 
95
97
  ### Agent-Email Binding
96
98
 
@@ -112,31 +114,9 @@ When the user asks about stored emails, email history, or email recall — use `
112
114
 
113
115
  ## Inbound Email Screening
114
116
 
115
- Every inbound email is classified by Claude Haiku before entering Neo4j. The classifier examines `fromAddress`, `fromName`, `subject`, and the first 1024 characters of `bodyPreview`.
116
-
117
- ### Verdicts
118
-
119
- | Verdict | Stored? | Embedding? | Auto-respond? | Graph query? |
120
- |---------|---------|------------|---------------|--------------|
121
- | `clean` | Yes | Yes | Yes | Yes |
122
- | `suspicious` | Yes (with `screeningReason`) | Yes | No | Yes |
123
- | `discarded` | Yes (with `screeningReason`) | No | No | No (list mode) |
124
-
125
- - **clean** — legitimate personal or business correspondence
126
- - **suspicious** — phishing indicators (urgency + credential requests, mismatched sender), prompt injection patterns, or classification failure (safe default)
127
- - **discarded** — obvious spam, marketing bulk mail, auto-generated notifications with no actionable content
128
-
129
- ### Prompt injection flag
117
+ There is no automated screener. The operator screens by eye during the `email-ingest` skill flow: `email-fetch` lists the new messages with sender, subject, and a body preview; the operator picks which ones to ingest and which to discard. A `screening` property of `clean` is stamped on every operator-approved row as a provenance marker (operator-approved), and discarded messages never enter the graph.
130
118
 
131
- When `promptInjectionFlag` is true (body contains instruction-like patterns targeting an AI agent), auto-respond skips the email entirely regardless of verdict. No reply is generated. The email is visible in Neo4j for admin review.
132
-
133
- ### Failure handling
134
-
135
- If the Haiku API is unavailable (network, rate limit, auth failure), the email defaults to `suspicious`. The entire fetch batch is never blocked — each email is classified independently. API key absence causes all emails in the batch to default to `suspicious`.
136
-
137
- ### Logs
138
-
139
- Classification verdicts are logged to `{accountDir}/logs/email-fetch.log` with per-email detail (fromAddress, verdict, reason, promptInjectionRisk) and batch summaries.
119
+ The previous Haiku classifier was removed in Task 424; the auto-respond binary that depended on it was removed alongside the screener. Both are intentionally absent the doctrine is that every LLM-bearing pipeline is operator-initiated.
140
120
 
141
121
  ## Security
142
122
 
@@ -144,51 +124,7 @@ Classification verdicts are logged to `{accountDir}/logs/email-fetch.log` with p
144
124
  - IMAP and SMTP connections require TLS or STARTTLS — plaintext is rejected
145
125
  - Only the agent's own dedicated account is accessed — never the user's personal email
146
126
  - Email nodes have `scope: "admin"` — never visible to public agents
147
- - Inbound emails are classified by Haiku before storage prompt injection and phishing are flagged
148
-
149
- ## Auto-Respond
150
-
151
- When enabled, a public agent replies to incoming emails. The auto-respond binary lives at `email/mcp/dist/scripts/email-auto-respond.js` and, like the fetcher, is **not currently scheduled on any install** — see `maxy-code-prd.md` §Scheduled tasks for the canonical dispatch destination. Until that landing, auto-respond only runs when an operator invokes the script manually.
152
-
153
- ### Setup
154
-
155
- To enable auto-respond, call `email-auto-respond-config` with `enabled: true`. The tool requires an `agentSlug`. When called without a slug, the tool returns available public agents — present these as a numbered list in plain chat so the admin can choose which agent handles responses, then call the tool again with the selected slug.
156
-
157
- ### Configuration
158
-
159
- - `enabled` — `true` to enable, `false` to disable
160
- - `agentSlug` — slug of the public agent that responds (required when enabling)
161
- - `pollIntervalMinutes` — how often to check for new emails (default: 5, range: 1–60)
162
- - `hourlyLimit` — maximum auto-replies per clock hour UTC (default: 20, range: 1–1000)
163
- - `dailyLimit` — maximum auto-replies per calendar day UTC (default: 100, range: 1–10000)
164
-
165
- ### Behaviour
166
-
167
- - Once the dispatcher is wired (see above), each account's poll is skipped if the configured interval hasn't elapsed since the last poll. The interval gate is enforced inside `email-auto-respond.js`, so the same skip logic applies whether the script is fired by the dispatcher or manually by an operator.
168
- - Only emails addressed TO the agent's email address are processed (alias filtering applies).
169
- - Auto-replies, mailing list messages, and emails from the agent's own address are automatically skipped (RFC 3834 loop prevention).
170
- - Outgoing replies include `In-Reply-To` and `References` headers for correct threading, and `Auto-Submitted: auto-replied` to prevent loops with other auto-responders.
171
- - Every reply includes a deterministic AI disclosure footer ("This reply was generated by an AI assistant.") appended after the agent's response. This is a regulatory requirement (EU AI Act Article 50) and is not dependent on the LLM including disclosure in its generated text.
172
- - The subject line carries a single `Re:` prefix (no doubling).
173
-
174
- ### Rate Limiting
175
-
176
- Per-account send caps prevent runaway auto-replies from spam waves, mailing list explosions, or deliberate attacks. Two independent limits:
177
-
178
- - **Hourly limit** (default 20) — resets at each UTC clock-hour boundary
179
- - **Daily limit** (default 100) — resets at midnight UTC
180
-
181
- When either limit is reached, remaining emails in the poll cycle are skipped (not replied to). Auto-respond is **not** disabled — counters reset naturally at the next boundary. A medium-priority admin Task is created to notify the admin.
182
-
183
- Within a single poll cycle, only one auto-reply is sent per unique sender address. This prevents reply storms when an automated sender delivers multiple messages. Sender deduplication is case-insensitive.
184
-
185
- ### Circuit Breaker
186
-
187
- After 3 consecutive failures (IMAP errors, API failures, SMTP rejections), auto-respond is automatically disabled and a high-priority Task is created for the admin. The admin sees this task at the start of their next session and can re-enable auto-respond after resolving the issue.
188
-
189
- ### Disabling
190
-
191
- Call `email-auto-respond-config` with `enabled: false`. This clears the agent assignment and resets the failure counter.
127
+ - Inbound messages enter the graph only when the operator approves them by eye via `email-ingest`
192
128
 
193
129
  ## OTP Integration
194
130
 
@@ -0,0 +1,87 @@
1
+ ---
2
+ name: email-ingest
3
+ description: "Operator-initiated email ingestion. Activate when the operator asks to check, triage, or pull in new email ('check my emails', 'any new mail?', 'pull in the latest emails', 'what came in overnight'). Drives a list → summarise → ask → ingest loop using the email-fetch and email-ingest tools. Human-in-the-loop: nothing enters the graph without an explicit operator decision per message."
4
+ ---
5
+
6
+ # Email ingestion
7
+
8
+ Operator-initiated, human-in-the-loop ingestion of the agent's IMAP inbox into the graph. New messages enter the knowledge graph **only** when the operator says so, and only the ones they pick. There is no background poll, no automatic classifier, no silent writes.
9
+
10
+ ## When to activate
11
+
12
+ Activate when the operator wants to bring new email into the agent's memory. Typical phrasings:
13
+
14
+ - "Check my emails."
15
+ - "Any new mail?"
16
+ - "Pull in the latest emails."
17
+ - "What came in overnight?"
18
+
19
+ Do **not** activate for:
20
+
21
+ - Searching, reading, or recalling email already in the inbox or the graph — those are `email-search`, `email-read`, `email-graph-query`.
22
+ - Drafting or sending — that's `email-composition`.
23
+ - Setup, status, or OTP extraction — those are direct tool calls.
24
+
25
+ ## Flow
26
+
27
+ ### 1. List
28
+
29
+ Call `email-fetch`. It pulls new messages since the stored high-water mark (or a `since_uid` if the operator asked for a wider window) and stages them in-memory for the follow-up ingest. **It writes nothing to the graph.**
30
+
31
+ If `email-fetch` returns "No new messages", say that and stop. There is nothing to ingest.
32
+
33
+ ### 2. Summarise
34
+
35
+ Present the listed messages to the operator as a numbered or per-`Message-ID` summary. For each, surface:
36
+
37
+ - Sender (name + address).
38
+ - Subject.
39
+ - A one-line gist drawn from the body preview (not the full preview — keep it tight).
40
+ - A suggested disposition where the message is obviously one or the other (e.g., "newsletter — looks like discard", "thread reply from a known correspondent — looks like ingest"). The suggestion is a hint, never an action; the operator decides.
41
+
42
+ Do not classify suspicious vs clean — there is no screener. If a message looks like phishing, surface that observation in plain English so the operator can discard it by eye.
43
+
44
+ ### 3. Ask
45
+
46
+ Ask the operator to confirm a disposition for **every** message in the list. Either:
47
+
48
+ - A blanket call ("ingest all", "discard everything"), which you turn into the per-message map.
49
+ - An explicit per-message choice ("ingest 1, 2, 4; discard 3").
50
+
51
+ If the operator answers ambiguously ("the work ones"), restate the messages you think they mean and confirm before proceeding. Never guess.
52
+
53
+ ### 4. Ingest
54
+
55
+ Call `email-ingest` with a `decisions` array containing one entry per Message-ID returned by `email-fetch`. The tool refuses if any pending Message-ID is missing a decision — that's the safeguard against silent drops, not an error to retry around. If it refuses, go back to the operator and ask about the missing ones.
56
+
57
+ On success the tool returns a one-line summary (ingested / discarded / thread counts) and advances the inbox high-water mark.
58
+
59
+ ### 5. Confirm
60
+
61
+ Echo the tool's summary back to the operator in one sentence. If they want to draft a reply to anything that was just ingested, hand off to `email-composition`.
62
+
63
+ ## Edge cases
64
+
65
+ | Situation | Behaviour |
66
+ |-----------|-----------|
67
+ | `email-fetch` returns zero new messages | Tell the operator and stop. Do not call `email-ingest`. |
68
+ | A listed message has no `Message-ID` header | Surface it by UID and ask the operator how to handle it. `email-ingest` cannot apply a per-message decision to it, so either widen the search or skip it explicitly. |
69
+ | Operator wants to ingest some now and review the rest later | Refuse cleanly. The high-water mark advances on every successful ingest, so a partial decision would silently drop the rest. Ask them to commit one way or the other on every message, or to wait. |
70
+ | Operator abandons mid-flow | Do not call `email-ingest`. The staged batch stays in memory until the next `email-fetch` overwrites it; the high-water mark does not move. |
71
+ | `email-fetch` errors (IMAP down, auth failure) | Surface the error verbatim. Do not retry silently. |
72
+
73
+ ## Out of scope
74
+
75
+ - **Automatic re-screening or LLM classification.** The screener was removed; the operator is the screener now.
76
+ - **Scheduled or recurring ingestion.** There is no cron, no interval, no background trigger. The operator initiates every cycle.
77
+ - **Per-thread or per-sender allowlists.** Each message gets a fresh decision.
78
+ - **Other channels.** WhatsApp and the public web have their own ingestion paths.
79
+
80
+ ## Observability
81
+
82
+ Each tool emits a single tagged log line:
83
+
84
+ - `[email-fetch] tag=email-fetch listed=<n> sinceUid=<uid>` — one per list call.
85
+ - `[email-ingest] tag=email-ingest ingested=<n> discarded=<m>` — one per ingest call.
86
+
87
+ A complete cycle is greppable as the pair `email-fetch` → `email-ingest` for the same session.
@@ -160,7 +160,7 @@ Writes targeting `:Person`, `:UserProfile`, `:AdminUser`, `:Organization`, `:Loc
160
160
 
161
161
  - **Workflow path — `producedByTaskId`.** `memory-write` accepts an optional `producedByTaskId` parameter. When set, the platform composes an inbound `:PRODUCED` edge from that `:Task` node into the write's `relationships` array before the write runs. The Task and the new node must share the same `accountId`; mismatch is rejected loud. The typical pattern: call `work-create` at the start of an autonomous flow (onboarding skill, cloudflare tunnel-login) with `kind` and `raisedDuringConversationKey`; capture the returned `taskId`; pass it as `producedByTaskId` on every subsequent `memory-write` for one of the gated labels.
162
162
 
163
- - **Direct-ask path — `CONVERSATION_NODE_ID` env-stamp.** When `producedByTaskId` is not provided (typical of direct admin asks like "add Anneke as person"), `memory-write` falls back to the `CONVERSATION_NODE_ID` env var. The admin server stamps it at PTY spawn time on both admin sessions and on the specialist subagent spawns the admin dispatches (Task 382 — listing-curator, content-producer, database-operator and friends inherit the same anchor). The value is the `conversationId` UUID of the active `:AdminConversation`; the wrapper's `injectConversationProvenance` MATCHes `(c:Conversation {conversationId, accountId})` so account isolation is enforced inside the natural key — a cross-account stamp returns zero rows and never injects. Autonomous spawns with no parent conversation (cron, scheduled-task) legitimately have no env-stamp; those must thread `producedByTaskId` via `work-create` instead. The env-stamp is invisible to the agent (no schema field changes); the LLM never decides whether to use it.
163
+ - **Direct-ask path — `SESSION_NODE_ID` env-stamp.** When `producedByTaskId` is not provided (typical of direct admin asks like "add Anneke as person"), `memory-write` falls back to the `SESSION_NODE_ID` env var. The admin server stamps it at PTY spawn time on both admin sessions and on the specialist subagent spawns the admin dispatches (Task 382 — listing-curator, content-producer, database-operator and friends inherit the same anchor). The value is the `sessionId` UUID of the active `:AdminConversation`; the wrapper's `injectConversationProvenance` MATCHes `(c:Conversation {sessionId, accountId})` so account isolation is enforced inside the natural key — a cross-account stamp returns zero rows and never injects. Autonomous spawns with no parent conversation (cron, scheduled-task) legitimately have no env-stamp; those must thread `producedByTaskId` via `work-create` instead. The env-stamp is invisible to the agent (no schema field changes); the LLM never decides whether to use it.
164
164
 
165
165
  ## Graph Hygiene
166
166
 
@@ -676,7 +676,7 @@ if (!readOnly) {
676
676
  keywords,
677
677
  sourceWorkflow,
678
678
  occurredAt,
679
- conversationNodeId: process.env.CONVERSATION_NODE_ID,
679
+ conversationNodeId: process.env.SESSION_NODE_ID,
680
680
  });
681
681
  const status = result.created
682
682
  ? `Report created`
@@ -1211,7 +1211,7 @@ if (!readOnly) {
1211
1211
  "",
1212
1212
  ...result.items.map((i) => {
1213
1213
  const preview = i.firstUserMsgPreview ? ` userPreview=${JSON.stringify(i.firstUserMsgPreview)}` : "";
1214
- return `- elementId=${i.elementId} conversationId=${i.conversationId ?? "null"} assistantMsgs=${i.assistantMsgCount} realUserMsgs=${i.realUserMsgCount}${preview}`;
1214
+ return `- elementId=${i.elementId} sessionId=${i.sessionId ?? "null"} assistantMsgs=${i.assistantMsgCount} realUserMsgs=${i.realUserMsgCount}${preview}`;
1215
1215
  }),
1216
1216
  ];
1217
1217
  return { content: [{ type: "text", text: lines.join("\n") }] };
@@ -1473,7 +1473,7 @@ if (!readOnly) {
1473
1473
  }
1474
1474
  /** Format conversation header line with activity timestamps. Shared across metadata and inline modes. */
1475
1475
  function formatConversationHeader(opts) {
1476
- const label = opts.name ? `"${opts.name}"` : opts.conversationId.slice(0, 8) + "…";
1476
+ const label = opts.name ? `"${opts.name}"` : opts.sessionId.slice(0, 8) + "…";
1477
1477
  const agentInfo = opts.agentSlug ? `${opts.agentType}/${opts.agentSlug}` : opts.agentType;
1478
1478
  const createdStr = shortIso(opts.createdAt) || "(no timestamp)";
1479
1479
  const updatedStr = shortIso(opts.updatedAt);
@@ -1492,12 +1492,12 @@ if (!readOnly) {
1492
1492
  return `${label} [${agentInfo}] · created ${createdStr} · active ${updatedStr}${agoStr} — ${opts.messageCount} messages`;
1493
1493
  }
1494
1494
  server.tool("conversation-list", "List conversations or retrieve messages from a specific conversation. " +
1495
- "Without conversationId: lists all conversations with message counts, ordered by most recent activity (updatedAt DESC). " +
1495
+ "Without sessionId: lists all conversations with message counts, ordered by most recent activity (updatedAt DESC). " +
1496
1496
  "Headers show both creation time and last activity time; when they differ, the conversation was resumed. " +
1497
- "With conversationId: returns all messages in that conversation chronologically with per-message timestamps. " +
1497
+ "With sessionId: returns all messages in that conversation chronologically with per-message timestamps. " +
1498
1498
  "With includeMessages: returns conversations with their timestamped messages inline (useful for batch review). " +
1499
1499
  "The since filter matches against activity time (updatedAt), not creation time.", {
1500
- conversationId: z
1500
+ sessionId: z
1501
1501
  .string()
1502
1502
  .optional()
1503
1503
  .describe("If provided, returns messages for this conversation. If omitted, lists all conversations."),
@@ -1521,20 +1521,20 @@ if (!readOnly) {
1521
1521
  .number()
1522
1522
  .optional()
1523
1523
  .describe("Maximum results (default 50 for conversations, 200 for messages)"),
1524
- }, async ({ conversationId, agentType, agentSlug, since, includeMessages, limit }) => {
1524
+ }, async ({ sessionId, agentType, agentSlug, since, includeMessages, limit }) => {
1525
1525
  if (!accountId)
1526
1526
  return refuseNoAccount("conversation-list");
1527
1527
  const startTime = Date.now();
1528
1528
  const dbSession = getSession();
1529
1529
  try {
1530
- if (conversationId) {
1530
+ if (sessionId) {
1531
1531
  // Messages mode — chronological listing for a specific conversation
1532
1532
  const messageLimit = limit ?? 200;
1533
- const result = await dbSession.run(`MATCH (m:Message)-[:PART_OF]->(c:Conversation {conversationId: $conversationId, accountId: $accountId})
1533
+ const result = await dbSession.run(`MATCH (m:Message)-[:PART_OF]->(c:Conversation {sessionId: $sessionId, accountId: $accountId})
1534
1534
  WHERE ${notTrashed("m")} AND ${notTrashed("c")}
1535
1535
  RETURN m.role AS role, m.content AS content, m.createdAt AS createdAt
1536
1536
  ORDER BY m.createdAt ASC
1537
- LIMIT $limit`, { conversationId, accountId, limit: int(messageLimit) });
1537
+ LIMIT $limit`, { sessionId, accountId, limit: int(messageLimit) });
1538
1538
  if (result.records.length === 0) {
1539
1539
  return {
1540
1540
  content: [{ type: "text", text: "No messages found for this conversation." }],
@@ -1546,7 +1546,7 @@ if (!readOnly) {
1546
1546
  const ts = shortIso(String(r.get("createdAt") ?? ""));
1547
1547
  return ts ? `[${role} ${ts}]\n ${content}` : `[${role}]\n ${content}`;
1548
1548
  });
1549
- process.stderr.write(`[conversation-list] [${accountId}] mode=messages conversationId=${conversationId.slice(0, 8)}… count=${result.records.length} (${Date.now() - startTime}ms)\n`);
1549
+ process.stderr.write(`[conversation-list] [${accountId}] mode=messages sessionId=${sessionId.slice(0, 8)}… count=${result.records.length} (${Date.now() - startTime}ms)\n`);
1550
1550
  return {
1551
1551
  content: [{ type: "text", text: formatted.join("\n---\n") }],
1552
1552
  };
@@ -1579,7 +1579,7 @@ if (!readOnly) {
1579
1579
  OPTIONAL MATCH (m:Message)-[:PART_OF]->(c) WHERE ${trashedMsgFilter}
1580
1580
  WITH c, m ORDER BY m.createdAt ASC
1581
1581
  WITH c, collect({role: m.role, content: m.content, createdAt: m.createdAt})[0..${msgLimit}] AS messages
1582
- RETURN c.conversationId AS conversationId,
1582
+ RETURN c.sessionId AS sessionId,
1583
1583
  c.agentType AS agentType,
1584
1584
  c.agentSlug AS agentSlug,
1585
1585
  c.name AS name,
@@ -1594,11 +1594,11 @@ if (!readOnly) {
1594
1594
  };
1595
1595
  }
1596
1596
  const formatted = result.records.map((r) => {
1597
- const id = String(r.get("conversationId") ?? "");
1597
+ const id = String(r.get("sessionId") ?? "");
1598
1598
  const msgCount = Number(r.get("messageCount") ?? 0);
1599
1599
  const header = formatConversationHeader({
1600
1600
  name: r.get("name"),
1601
- conversationId: id,
1601
+ sessionId: id,
1602
1602
  agentType: String(r.get("agentType") ?? ""),
1603
1603
  agentSlug: r.get("agentSlug"),
1604
1604
  createdAt: String(r.get("createdAt") ?? ""),
@@ -1634,7 +1634,7 @@ if (!readOnly) {
1634
1634
  ${whereStr ? whereStr + " AND " : "WHERE "}${trashedConvFilter}
1635
1635
  WITH c ORDER BY c.updatedAt DESC LIMIT $limit
1636
1636
  OPTIONAL MATCH (m:Message)-[:PART_OF]->(c) WHERE ${trashedMsgFilter}
1637
- RETURN c.conversationId AS conversationId,
1637
+ RETURN c.sessionId AS sessionId,
1638
1638
  c.agentType AS agentType,
1639
1639
  c.agentSlug AS agentSlug,
1640
1640
  c.name AS name,
@@ -1648,13 +1648,13 @@ if (!readOnly) {
1648
1648
  };
1649
1649
  }
1650
1650
  const formatted = result.records.map((r) => {
1651
- const id = String(r.get("conversationId") ?? "");
1651
+ const id = String(r.get("sessionId") ?? "");
1652
1652
  const msgCount = typeof r.get("messageCount") === "number"
1653
1653
  ? r.get("messageCount")
1654
1654
  : Number(r.get("messageCount"));
1655
1655
  return formatConversationHeader({
1656
1656
  name: r.get("name"),
1657
- conversationId: id,
1657
+ sessionId: id,
1658
1658
  agentType: String(r.get("agentType") ?? ""),
1659
1659
  agentSlug: r.get("agentSlug"),
1660
1660
  createdAt: String(r.get("createdAt") ?? ""),
@@ -1691,7 +1691,7 @@ if (!readOnly) {
1691
1691
  .describe("How the preference was observed. Defaults to 'behavioural'."),
1692
1692
  mode: z.enum(["reinforce", "update", "contradict", "merge"]).optional()
1693
1693
  .describe("Update mode. Defaults to 'reinforce'."),
1694
- conversationId: z.string().optional()
1694
+ sessionId: z.string().optional()
1695
1695
  .describe("Conversation ID for evidence linking"),
1696
1696
  profileFields: z.record(z.string(), z.unknown()).optional()
1697
1697
  .describe("Top-level UserProfile fields to update (e.g. timezone, locale, role)"),
@@ -1702,7 +1702,7 @@ if (!readOnly) {
1702
1702
  .describe("Operator-identity fields written to the OWNS-bound Person. Use canonical `telephone` (NOT `phone` — that is the schema synonym, not the canonical name). Tool throws if the AdminUser-OWNS-Person edge is missing rather than silently no-op."),
1703
1703
  mergeSourceIds: z.array(z.string()).optional()
1704
1704
  .describe("For mode 'merge': preferenceIds of sources to combine into this preference"),
1705
- }, async ({ category, key, value, source, mode, conversationId, profileFields, personFields, mergeSourceIds }) => {
1705
+ }, async ({ category, key, value, source, mode, sessionId, profileFields, personFields, mergeSourceIds }) => {
1706
1706
  if (!accountId)
1707
1707
  return refuseNoAccount("profile-update");
1708
1708
  try {
@@ -1717,7 +1717,7 @@ if (!readOnly) {
1717
1717
  value,
1718
1718
  source,
1719
1719
  mode,
1720
- conversationId,
1720
+ sessionId,
1721
1721
  profileFields: profileFields,
1722
1722
  personFields,
1723
1723
  mergeSourceIds,
@@ -1901,15 +1901,15 @@ if (!readOnly) {
1901
1901
  "(Message nodes) is immutable history and is never modified — only the derived :Memory payload that " +
1902
1902
  "memory-search would otherwise re-surface. Use when a single conversation polluted memory with claims " +
1903
1903
  "that should not propagate (e.g. wrong-account hostnames, fabricated identifiers).", {
1904
- conversationId: z.string().min(1).describe("The Conversation node's conversationId to scope the expunge to."),
1904
+ sessionId: z.string().min(1).describe("The Conversation node's sessionId to scope the expunge to."),
1905
1905
  pattern: z.string().min(1).describe("The substring to scrub from string properties on linked :Memory nodes."),
1906
- }, async ({ conversationId, pattern }) => {
1906
+ }, async ({ sessionId, pattern }) => {
1907
1907
  if (!accountId)
1908
1908
  return refuseNoAccount("conversation-memory-expunge");
1909
1909
  try {
1910
- const result = await conversationMemoryExpunge({ accountId, conversationId, pattern });
1910
+ const result = await conversationMemoryExpunge({ accountId, sessionId, pattern });
1911
1911
  const lines = [
1912
- `Expunged "${result.pattern}" from conversation ${result.conversationId.slice(0, 8)}…`,
1912
+ `Expunged "${result.pattern}" from conversation ${result.sessionId.slice(0, 8)}…`,
1913
1913
  `:Memory nodes scanned: ${result.nodesScanned}`,
1914
1914
  `Properties nulled: ${result.propertiesNulled}`,
1915
1915
  ];
@@ -1967,7 +1967,7 @@ eagerTool(server, "conversation-search", "Search conversation history using sema
1967
1967
  try {
1968
1968
  const conversationSessionId = resolveSessionId();
1969
1969
  const sessionClause = conversationSessionId
1970
- ? "AND node.conversationId = $sessionId"
1970
+ ? "AND node.sessionId = $sessionId"
1971
1971
  : "";
1972
1972
  const result = await dbSession.run(`CALL db.index.vector.queryNodes('message_embedding', $limit, $embedding)
1973
1973
  YIELD node, score
@@ -1979,7 +1979,7 @@ eagerTool(server, "conversation-search", "Search conversation history using sema
1979
1979
  RETURN node.messageId AS messageId,
1980
1980
  node.role AS role,
1981
1981
  node.content AS content,
1982
- node.conversationId AS conversationId,
1982
+ node.sessionId AS sessionId,
1983
1983
  c.name AS sessionName,
1984
1984
  node.createdAt AS createdAt,
1985
1985
  score
@@ -2000,7 +2000,7 @@ eagerTool(server, "conversation-search", "Search conversation history using sema
2000
2000
  const content = r.get("content");
2001
2001
  const score = typeof r.get("score") === "number" ? r.get("score") : Number(r.get("score"));
2002
2002
  const createdAt = String(r.get("createdAt"));
2003
- const convId = r.get("conversationId");
2003
+ const convId = r.get("sessionId");
2004
2004
  const sessionName = r.get("sessionName");
2005
2005
  const convPrefix = convId ? convId.slice(0, 8) : "unknown";
2006
2006
  const convLabel = sessionName
@@ -2010,7 +2010,7 @@ eagerTool(server, "conversation-search", "Search conversation history using sema
2010
2010
  });
2011
2011
  // Diagnostic: log when admin search results span multiple conversations
2012
2012
  const distinctConvIds = new Set(result.records
2013
- .map((r) => r.get("conversationId"))
2013
+ .map((r) => r.get("sessionId"))
2014
2014
  .filter(Boolean));
2015
2015
  if (distinctConvIds.size > 1) {
2016
2016
  const prefixes = [...distinctConvIds].map((id) => id.slice(0, 8));
@@ -2082,7 +2082,7 @@ server.tool("image-fetch", [
2082
2082
  // bypassing this tool.
2083
2083
  server.tool("memory-typed-edge-pass", "Run the typed-edge auto-extraction pass over prose-bearing nodes this account wrote since sinceIso. Reads Message/Page/Meeting/Email/Idea/Note/Post/Report nodes, batches them, asks Haiku for typed-edge proposals against the closed allowlist (ATTENDED, WORKS_AT, INVESTED_IN, FOUNDED, ADVISES, MENTIONS, AUTHORED, ATTACHED_TO, REFERENCES), validates each proposal inline, and MERGEs accepted edges with createdBy provenance. Returns the counters (nodes, proposed, accepted, rejected, failed, ms) for the caller to hand back to admin's session-retrospective-mark-complete.", {
2084
2084
  sinceIso: z.string().describe("ISO timestamp lower bound. Prose nodes with updatedAt >= sinceIso are processed."),
2085
- conversationId: z.string().optional().describe("Conversation id stamped onto the createdBy provenance of MERGEd edges. Defaults to CONVERSATION_ID env if absent."),
2085
+ sessionId: z.string().optional().describe("Conversation id stamped onto the createdBy provenance of MERGEd edges. Defaults to SESSION_ID env if absent."),
2086
2086
  }, async (args) => {
2087
2087
  if (!accountId)
2088
2088
  return refuseNoAccount("memory-typed-edge-pass");