@rubytech/create-maxy-code 0.1.158 → 0.1.161

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 (359) 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-search/src/__tests__/fulltext-coverage.test.ts +48 -17
  8. package/payload/platform/lib/graph-style/dist/index.js +2 -2
  9. package/payload/platform/lib/graph-style/dist/index.js.map +1 -1
  10. package/payload/platform/lib/graph-style/src/__tests__/parity.test.ts +1 -1
  11. package/payload/platform/lib/graph-style/src/index.ts +2 -2
  12. package/payload/platform/lib/graph-trash/dist/index.js +1 -1
  13. package/payload/platform/lib/graph-trash/dist/index.js.map +1 -1
  14. package/payload/platform/lib/graph-trash/src/index.ts +1 -1
  15. package/payload/platform/lib/graph-write/dist/__tests__/action-provenance-gate.test.js +1 -1
  16. package/payload/platform/lib/graph-write/dist/__tests__/action-provenance-gate.test.js.map +1 -1
  17. package/payload/platform/lib/graph-write/dist/conversation-provenance.d.ts +3 -3
  18. package/payload/platform/lib/graph-write/dist/conversation-provenance.js +5 -5
  19. package/payload/platform/lib/graph-write/dist/conversation-provenance.js.map +1 -1
  20. package/payload/platform/lib/graph-write/dist/index.js +1 -1
  21. package/payload/platform/lib/graph-write/dist/index.js.map +1 -1
  22. package/payload/platform/lib/graph-write/src/__tests__/action-provenance-gate.test.ts +1 -1
  23. package/payload/platform/lib/graph-write/src/conversation-provenance.ts +8 -8
  24. package/payload/platform/lib/graph-write/src/index.ts +1 -1
  25. package/payload/platform/neo4j/schema.cypher +86 -46
  26. package/payload/platform/plugins/.claude-plugin/marketplace.json +5 -0
  27. package/payload/platform/plugins/admin/.claude-plugin/plugin.json +1 -1
  28. package/payload/platform/plugins/admin/PLUGIN.md +8 -4
  29. package/payload/platform/plugins/admin/hooks/__tests__/archive-ingest-surface-gate.test.sh +1 -1
  30. package/payload/platform/plugins/admin/hooks/__tests__/per-turn-graph-pass-gate.test.sh +361 -0
  31. package/payload/platform/plugins/admin/hooks/__tests__/pre-turn-graph-pass.test.sh +13 -13
  32. package/payload/platform/plugins/admin/hooks/__tests__/turn-completed-graph-write.test.sh +1 -1
  33. package/payload/platform/plugins/admin/hooks/archive-ingest-surface-gate.sh +2 -2
  34. package/payload/platform/plugins/admin/hooks/lib/admin-graph-pass-common.sh +102 -0
  35. package/payload/platform/plugins/admin/hooks/per-turn-graph-pass-gate.sh +106 -0
  36. package/payload/platform/plugins/admin/hooks/pre-turn-graph-pass.sh +15 -8
  37. package/payload/platform/plugins/admin/hooks/turn-completed-graph-write.sh +4 -4
  38. package/payload/platform/plugins/admin/mcp/dist/index.js +65 -24
  39. package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
  40. package/payload/platform/plugins/admin/skills/business-profile/SKILL.md +1 -1
  41. package/payload/platform/plugins/admin/skills/session-management/SKILL.md +2 -2
  42. package/payload/platform/plugins/admin/skills/stream-log-review/SKILL.md +5 -5
  43. package/payload/platform/plugins/admin/skills/stream-log-review/references/analysis-patterns.md +6 -6
  44. package/payload/platform/plugins/business-assistant/references/profiling.md +1 -1
  45. package/payload/platform/plugins/contacts/PLUGIN.md +1 -1
  46. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-create.js +2 -2
  47. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-create.js.map +1 -1
  48. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-erase.js +3 -3
  49. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-export.d.ts +1 -1
  50. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-export.js +2 -2
  51. package/payload/platform/plugins/contacts/mcp/dist/tools/group-create.d.ts +1 -1
  52. package/payload/platform/plugins/contacts/mcp/dist/tools/group-create.d.ts.map +1 -1
  53. package/payload/platform/plugins/contacts/mcp/dist/tools/group-create.js +4 -4
  54. package/payload/platform/plugins/contacts/mcp/dist/tools/group-create.js.map +1 -1
  55. package/payload/platform/plugins/contacts/mcp/dist/tools/group-manage.js +10 -10
  56. package/payload/platform/plugins/contacts/mcp/dist/tools/group-manage.js.map +1 -1
  57. package/payload/platform/plugins/docs/references/admin-session.md +6 -6
  58. package/payload/platform/plugins/docs/references/admin-ui.md +1 -1
  59. package/payload/platform/plugins/docs/references/internals.md +5 -5
  60. package/payload/platform/plugins/docs/references/plugins-guide.md +6 -5
  61. package/payload/platform/plugins/docs/references/troubleshooting.md +1 -1
  62. package/payload/platform/plugins/email/.claude-plugin/plugin.json +1 -1
  63. package/payload/platform/plugins/email/PLUGIN.md +19 -2
  64. package/payload/platform/plugins/email/mcp/dist/index.js +78 -0
  65. package/payload/platform/plugins/email/mcp/dist/index.js.map +1 -1
  66. package/payload/platform/plugins/email/mcp/dist/lib/conversation-archive-dispatch.d.ts +8 -0
  67. package/payload/platform/plugins/email/mcp/dist/lib/conversation-archive-dispatch.d.ts.map +1 -0
  68. package/payload/platform/plugins/email/mcp/dist/lib/conversation-archive-dispatch.js +177 -0
  69. package/payload/platform/plugins/email/mcp/dist/lib/conversation-archive-dispatch.js.map +1 -0
  70. package/payload/platform/plugins/email/mcp/dist/lib/embedding.js +2 -2
  71. package/payload/platform/plugins/email/mcp/dist/lib/embedding.js.map +1 -1
  72. package/payload/platform/plugins/email/mcp/dist/lib/graph.d.ts +6 -54
  73. package/payload/platform/plugins/email/mcp/dist/lib/graph.d.ts.map +1 -1
  74. package/payload/platform/plugins/email/mcp/dist/lib/graph.js +12 -300
  75. package/payload/platform/plugins/email/mcp/dist/lib/graph.js.map +1 -1
  76. package/payload/platform/plugins/email/mcp/dist/lib/imap.d.ts +1 -1
  77. package/payload/platform/plugins/email/mcp/dist/lib/ingest-batch.d.ts +23 -0
  78. package/payload/platform/plugins/email/mcp/dist/lib/ingest-batch.d.ts.map +1 -0
  79. package/payload/platform/plugins/email/mcp/dist/lib/ingest-batch.js +15 -0
  80. package/payload/platform/plugins/email/mcp/dist/lib/ingest-batch.js.map +1 -0
  81. package/payload/platform/plugins/email/mcp/dist/tools/email-classify.d.ts +6 -0
  82. package/payload/platform/plugins/email/mcp/dist/tools/email-classify.d.ts.map +1 -0
  83. package/payload/platform/plugins/email/mcp/dist/tools/email-classify.js +89 -0
  84. package/payload/platform/plugins/email/mcp/dist/tools/email-classify.js.map +1 -0
  85. package/payload/platform/plugins/email/mcp/dist/tools/email-fetch.d.ts +15 -0
  86. package/payload/platform/plugins/email/mcp/dist/tools/email-fetch.d.ts.map +1 -0
  87. package/payload/platform/plugins/email/mcp/dist/tools/email-fetch.js +49 -0
  88. package/payload/platform/plugins/email/mcp/dist/tools/email-fetch.js.map +1 -0
  89. package/payload/platform/plugins/email/mcp/dist/tools/email-ingest.d.ts +20 -0
  90. package/payload/platform/plugins/email/mcp/dist/tools/email-ingest.d.ts.map +1 -0
  91. package/payload/platform/plugins/email/mcp/dist/tools/email-ingest.js +91 -0
  92. package/payload/platform/plugins/email/mcp/dist/tools/email-ingest.js.map +1 -0
  93. package/payload/platform/plugins/email/mcp/dist/tools/email-setup.d.ts.map +1 -1
  94. package/payload/platform/plugins/email/mcp/dist/tools/email-setup.js +32 -52
  95. package/payload/platform/plugins/email/mcp/dist/tools/email-setup.js.map +1 -1
  96. package/payload/platform/plugins/email/references/email-reference.md +19 -83
  97. package/payload/platform/plugins/email/skills/email-ingest/SKILL.md +87 -0
  98. package/payload/platform/plugins/linkedin-import/skills/linkedin-import/SKILL.md +10 -37
  99. package/payload/platform/plugins/linkedin-import/skills/linkedin-import/references/connections.md +1 -0
  100. package/payload/platform/plugins/memory/.claude-plugin/plugin.json +1 -1
  101. package/payload/platform/plugins/memory/PLUGIN.md +11 -2
  102. package/payload/platform/plugins/memory/bin/conversation-archive-ingest.mjs +139 -439
  103. package/payload/platform/plugins/memory/bin/conversation-archive-ingest.sh +15 -47
  104. package/payload/platform/plugins/memory/mcp/dist/index.js +197 -58
  105. package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
  106. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/compiled-truth-revision.test.js +43 -27
  107. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/compiled-truth-revision.test.js.map +1 -1
  108. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/label-delete-gate.test.d.ts +2 -0
  109. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/label-delete-gate.test.d.ts.map +1 -0
  110. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/label-delete-gate.test.js +62 -0
  111. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/label-delete-gate.test.js.map +1 -0
  112. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-cypher-drift.test.js +5 -0
  113. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-cypher-drift.test.js.map +1 -1
  114. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/typed-edge-schema.test.js +1 -1
  115. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/typed-edge-schema.test.js.map +1 -1
  116. package/payload/platform/plugins/memory/mcp/dist/lib/compiled-truth-revision.d.ts +42 -25
  117. package/payload/platform/plugins/memory/mcp/dist/lib/compiled-truth-revision.d.ts.map +1 -1
  118. package/payload/platform/plugins/memory/mcp/dist/lib/compiled-truth-revision.js +23 -17
  119. package/payload/platform/plugins/memory/mcp/dist/lib/compiled-truth-revision.js.map +1 -1
  120. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/email.d.ts +3 -0
  121. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/email.d.ts.map +1 -0
  122. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/email.js +61 -0
  123. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/email.js.map +1 -0
  124. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/index.d.ts +1 -0
  125. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/index.d.ts.map +1 -1
  126. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/index.js +3 -0
  127. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/index.js.map +1 -1
  128. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/types.d.ts +1 -1
  129. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/types.d.ts.map +1 -1
  130. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/types.js +1 -0
  131. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/types.js.map +1 -1
  132. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/x-dm.js +2 -2
  133. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/x-dm.js.map +1 -1
  134. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/derive-keys.d.ts +2 -0
  135. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/derive-keys.d.ts.map +1 -1
  136. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/derive-keys.js +9 -3
  137. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-pipeline/derive-keys.js.map +1 -1
  138. package/payload/platform/plugins/memory/mcp/dist/lib/graph-prune.d.ts +3 -3
  139. package/payload/platform/plugins/memory/mcp/dist/lib/graph-prune.d.ts.map +1 -1
  140. package/payload/platform/plugins/memory/mcp/dist/lib/graph-prune.js +6 -6
  141. package/payload/platform/plugins/memory/mcp/dist/lib/graph-prune.js.map +1 -1
  142. package/payload/platform/plugins/memory/mcp/dist/lib/kd-classify-gate.d.ts +41 -0
  143. package/payload/platform/plugins/memory/mcp/dist/lib/kd-classify-gate.d.ts.map +1 -0
  144. package/payload/platform/plugins/memory/mcp/dist/lib/kd-classify-gate.js +71 -0
  145. package/payload/platform/plugins/memory/mcp/dist/lib/kd-classify-gate.js.map +1 -0
  146. package/payload/platform/plugins/memory/mcp/dist/lib/label-delete-gate.d.ts +18 -0
  147. package/payload/platform/plugins/memory/mcp/dist/lib/label-delete-gate.d.ts.map +1 -0
  148. package/payload/platform/plugins/memory/mcp/dist/lib/label-delete-gate.js +31 -0
  149. package/payload/platform/plugins/memory/mcp/dist/lib/label-delete-gate.js.map +1 -0
  150. package/payload/platform/plugins/memory/mcp/dist/lib/log-ingest.js +1 -1
  151. package/payload/platform/plugins/memory/mcp/dist/lib/log-ingest.js.map +1 -1
  152. package/payload/platform/plugins/memory/mcp/dist/lib/neo4j.d.ts +2 -2
  153. package/payload/platform/plugins/memory/mcp/dist/lib/neo4j.js +2 -2
  154. package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-pass.d.ts +1 -1
  155. package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-pass.d.ts.map +1 -1
  156. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-archive-derive-insights.test.d.ts +5 -0
  157. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-archive-derive-insights.test.d.ts.map +1 -1
  158. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-archive-derive-insights.test.js +162 -78
  159. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-archive-derive-insights.test.js.map +1 -1
  160. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-archive-enrich-rejection.test.js +1 -1
  161. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-archive-enrich-rejection.test.js.map +1 -1
  162. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-memory-expunge-emit.test.js +3 -3
  163. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-memory-expunge-emit.test.js.map +1 -1
  164. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-normalisers-source-agnosticism.test.js +2 -0
  165. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-normalisers-source-agnosticism.test.js.map +1 -1
  166. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/log-ingest.test.js +2 -2
  167. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/log-ingest.test.js.map +1 -1
  168. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-compiled-truth-history.test.js +2 -0
  169. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-compiled-truth-history.test.js.map +1 -1
  170. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-delete-emit.test.js +6 -0
  171. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-delete-emit.test.js.map +1 -1
  172. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-delete-reserved-label.test.d.ts +2 -0
  173. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-delete-reserved-label.test.d.ts.map +1 -0
  174. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-delete-reserved-label.test.js +141 -0
  175. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-delete-reserved-label.test.js.map +1 -0
  176. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-empty-trash-admin-conversation.test.js +8 -8
  177. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-empty-trash-admin-conversation.test.js.map +1 -1
  178. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-empty-trash-reserved-label.test.d.ts +2 -0
  179. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-empty-trash-reserved-label.test.d.ts.map +1 -0
  180. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-empty-trash-reserved-label.test.js +86 -0
  181. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-empty-trash-reserved-label.test.js.map +1 -0
  182. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-report-tools.test.js +2 -2
  183. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-report-tools.test.js.map +1 -1
  184. package/payload/platform/plugins/memory/mcp/dist/tools/conversation-archive-derive-insights.d.ts +33 -34
  185. package/payload/platform/plugins/memory/mcp/dist/tools/conversation-archive-derive-insights.d.ts.map +1 -1
  186. package/payload/platform/plugins/memory/mcp/dist/tools/conversation-archive-derive-insights.js +94 -273
  187. package/payload/platform/plugins/memory/mcp/dist/tools/conversation-archive-derive-insights.js.map +1 -1
  188. package/payload/platform/plugins/memory/mcp/dist/tools/conversation-archive-list-chunks.d.ts +43 -0
  189. package/payload/platform/plugins/memory/mcp/dist/tools/conversation-archive-list-chunks.d.ts.map +1 -0
  190. package/payload/platform/plugins/memory/mcp/dist/tools/conversation-archive-list-chunks.js +96 -0
  191. package/payload/platform/plugins/memory/mcp/dist/tools/conversation-archive-list-chunks.js.map +1 -0
  192. package/payload/platform/plugins/memory/mcp/dist/tools/conversation-memory-expunge.d.ts +1 -1
  193. package/payload/platform/plugins/memory/mcp/dist/tools/conversation-memory-expunge.d.ts.map +1 -1
  194. package/payload/platform/plugins/memory/mcp/dist/tools/conversation-memory-expunge.js +2 -2
  195. package/payload/platform/plugins/memory/mcp/dist/tools/conversation-memory-expunge.js.map +1 -1
  196. package/payload/platform/plugins/memory/mcp/dist/tools/kd-classify.d.ts +6 -0
  197. package/payload/platform/plugins/memory/mcp/dist/tools/kd-classify.d.ts.map +1 -0
  198. package/payload/platform/plugins/memory/mcp/dist/tools/kd-classify.js +73 -0
  199. package/payload/platform/plugins/memory/mcp/dist/tools/kd-classify.js.map +1 -0
  200. package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.d.ts.map +1 -1
  201. package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.js +0 -1
  202. package/payload/platform/plugins/memory/mcp/dist/tools/memory-archive-write.js.map +1 -1
  203. package/payload/platform/plugins/memory/mcp/dist/tools/memory-brain-capture-recent.d.ts +2 -2
  204. package/payload/platform/plugins/memory/mcp/dist/tools/memory-brain-capture-recent.d.ts.map +1 -1
  205. package/payload/platform/plugins/memory/mcp/dist/tools/memory-brain-capture-recent.js +4 -4
  206. package/payload/platform/plugins/memory/mcp/dist/tools/memory-brain-capture-recent.js.map +1 -1
  207. package/payload/platform/plugins/memory/mcp/dist/tools/memory-compiled-truth-history.d.ts +6 -0
  208. package/payload/platform/plugins/memory/mcp/dist/tools/memory-compiled-truth-history.d.ts.map +1 -1
  209. package/payload/platform/plugins/memory/mcp/dist/tools/memory-compiled-truth-history.js +2 -0
  210. package/payload/platform/plugins/memory/mcp/dist/tools/memory-compiled-truth-history.js.map +1 -1
  211. package/payload/platform/plugins/memory/mcp/dist/tools/memory-delete.d.ts +8 -0
  212. package/payload/platform/plugins/memory/mcp/dist/tools/memory-delete.d.ts.map +1 -1
  213. package/payload/platform/plugins/memory/mcp/dist/tools/memory-delete.js +40 -5
  214. package/payload/platform/plugins/memory/mcp/dist/tools/memory-delete.js.map +1 -1
  215. package/payload/platform/plugins/memory/mcp/dist/tools/memory-empty-trash.d.ts +8 -1
  216. package/payload/platform/plugins/memory/mcp/dist/tools/memory-empty-trash.d.ts.map +1 -1
  217. package/payload/platform/plugins/memory/mcp/dist/tools/memory-empty-trash.js +25 -9
  218. package/payload/platform/plugins/memory/mcp/dist/tools/memory-empty-trash.js.map +1 -1
  219. package/payload/platform/plugins/memory/mcp/dist/tools/memory-find-candidates.d.ts +1 -1
  220. package/payload/platform/plugins/memory/mcp/dist/tools/memory-find-candidates.d.ts.map +1 -1
  221. package/payload/platform/plugins/memory/mcp/dist/tools/memory-find-candidates.js +2 -2
  222. package/payload/platform/plugins/memory/mcp/dist/tools/memory-find-candidates.js.map +1 -1
  223. package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.js +11 -0
  224. package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.js.map +1 -1
  225. package/payload/platform/plugins/memory/mcp/dist/tools/memory-node-exists.d.ts +28 -0
  226. package/payload/platform/plugins/memory/mcp/dist/tools/memory-node-exists.d.ts.map +1 -0
  227. package/payload/platform/plugins/memory/mcp/dist/tools/memory-node-exists.js +46 -0
  228. package/payload/platform/plugins/memory/mcp/dist/tools/memory-node-exists.js.map +1 -0
  229. package/payload/platform/plugins/memory/mcp/dist/tools/memory-report-write.d.ts +1 -1
  230. package/payload/platform/plugins/memory/mcp/dist/tools/memory-report-write.js +1 -1
  231. package/payload/platform/plugins/memory/mcp/dist/tools/memory-typed-edge-pass.d.ts +1 -1
  232. package/payload/platform/plugins/memory/mcp/dist/tools/memory-typed-edge-pass.d.ts.map +1 -1
  233. package/payload/platform/plugins/memory/mcp/dist/tools/memory-typed-edge-pass.js +2 -2
  234. package/payload/platform/plugins/memory/mcp/dist/tools/memory-typed-edge-pass.js.map +1 -1
  235. package/payload/platform/plugins/memory/mcp/dist/tools/memory-update.d.ts.map +1 -1
  236. package/payload/platform/plugins/memory/mcp/dist/tools/memory-update.js +26 -0
  237. package/payload/platform/plugins/memory/mcp/dist/tools/memory-update.js.map +1 -1
  238. package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.js +2 -2
  239. package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.js.map +1 -1
  240. package/payload/platform/plugins/memory/mcp/dist/tools/profile-update.d.ts +1 -1
  241. package/payload/platform/plugins/memory/mcp/dist/tools/profile-update.d.ts.map +1 -1
  242. package/payload/platform/plugins/memory/mcp/dist/tools/profile-update.js +11 -11
  243. package/payload/platform/plugins/memory/mcp/dist/tools/profile-update.js.map +1 -1
  244. package/payload/platform/plugins/memory/mcp/scripts/backfill-typed-edges.ts +1 -1
  245. package/payload/platform/plugins/memory/mcp/scripts/graph/fixture.cypher +1 -1
  246. package/payload/platform/plugins/memory/mcp/vitest.config.ts +5 -4
  247. package/payload/platform/plugins/memory/references/graph-primitives.md +1 -1
  248. package/payload/platform/plugins/memory/references/schema-base.md +8 -10
  249. package/payload/platform/plugins/memory/skills/conversation-archive/SKILL.md +100 -116
  250. package/payload/platform/plugins/memory/skills/conversation-archive-enrich/SKILL.md +74 -24
  251. package/payload/platform/plugins/memory/skills/conversational-memory/SKILL.md +1 -1
  252. package/payload/platform/plugins/notion-import/skills/notion-import/SKILL.md +1 -1
  253. package/payload/platform/plugins/obsidian-import/skills/obsidian-import/SKILL.md +1 -1
  254. package/payload/platform/plugins/substack-import/.claude-plugin/plugin.json +8 -0
  255. package/payload/platform/plugins/substack-import/PLUGIN.md +34 -0
  256. package/payload/platform/plugins/substack-import/skills/substack-import/SKILL.md +182 -0
  257. package/payload/platform/plugins/substack-import/skills/substack-import/references/archive-shape.md +68 -0
  258. package/payload/platform/plugins/substack-import/skills/substack-import/references/attachments.md +72 -0
  259. package/payload/platform/plugins/substack-import/skills/substack-import/references/engagement.md +61 -0
  260. package/payload/platform/plugins/substack-import/skills/substack-import/references/posts.md +80 -0
  261. package/payload/platform/plugins/substack-import/skills/substack-import/references/subscribers.md +74 -0
  262. package/payload/platform/plugins/whatsapp/PLUGIN.md +1 -1
  263. package/payload/platform/plugins/whatsapp/mcp/dist/index.js +2 -2
  264. package/payload/platform/plugins/whatsapp/mcp/dist/index.js.map +1 -1
  265. package/payload/platform/plugins/work/mcp/dist/index.js +2 -2
  266. package/payload/platform/plugins/work/mcp/dist/index.js.map +1 -1
  267. package/payload/platform/plugins/work/mcp/dist/tools/project-create.js +6 -6
  268. package/payload/platform/plugins/work/mcp/dist/tools/project-create.js.map +1 -1
  269. package/payload/platform/plugins/work/mcp/dist/tools/session-list.d.ts +1 -1
  270. package/payload/platform/plugins/work/mcp/dist/tools/session-list.d.ts.map +1 -1
  271. package/payload/platform/plugins/work/mcp/dist/tools/session-list.js +1 -1
  272. package/payload/platform/plugins/work/mcp/dist/tools/session-list.js.map +1 -1
  273. package/payload/platform/plugins/x-import/references/archive-shape.md +2 -2
  274. package/payload/platform/plugins/x-import/skills/x-import/SKILL.md +4 -4
  275. package/payload/platform/scripts/admin-persist-audit.ts +18 -18
  276. package/payload/platform/scripts/identity-forbidden-token-check.mjs +2 -0
  277. package/payload/platform/scripts/seed-neo4j.sh +1 -0
  278. package/payload/platform/services/claude-session-manager/dist/http-server.js +3 -3
  279. package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
  280. package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts +3 -3
  281. package/payload/platform/services/claude-session-manager/dist/pty-spawner.js +4 -4
  282. package/payload/platform/services/claude-session-manager/dist/pty-spawner.js.map +1 -1
  283. package/payload/platform/services/claude-session-manager/dist/system-prompt.d.ts.map +1 -1
  284. package/payload/platform/services/claude-session-manager/dist/system-prompt.js +2 -0
  285. package/payload/platform/services/claude-session-manager/dist/system-prompt.js.map +1 -1
  286. package/payload/platform/templates/specialists/agents/archive-ingest-operator.md +45 -0
  287. package/payload/platform/templates/specialists/agents/database-operator.md +5 -17
  288. package/payload/platform/templates/specialists/agents/librarian.md +1 -1
  289. package/payload/platform/templates/specialists/agents/personal-assistant.md +1 -1
  290. package/payload/server/{chunk-AXOL2PPG.js → chunk-3TRIXQSJ.js} +101 -101
  291. package/payload/server/maxy-edge.js +1 -1
  292. package/payload/server/public/assets/{admin-3fLFD5h_.js → admin-Dal5FWaD.js} +2 -2
  293. package/payload/server/public/assets/{architectureDiagram-Q4EWVU46-Breg9-99.js → architectureDiagram-Q4EWVU46-Do2zYONG.js} +1 -1
  294. package/payload/server/public/assets/{blockDiagram-DXYQGD6D-DXf1_673.js → blockDiagram-DXYQGD6D-DpIX_bRu.js} +1 -1
  295. package/payload/server/public/assets/{c4Diagram-AHTNJAMY-CSZ36W4-.js → c4Diagram-AHTNJAMY-Cz335ZSY.js} +1 -1
  296. package/payload/server/public/assets/channel-PC4_IjI1.js +1 -0
  297. package/payload/server/public/assets/{chunk-336JU56O-DsrLk2eK.js → chunk-336JU56O-Dmknn3Wo.js} +2 -2
  298. package/payload/server/public/assets/{chunk-426QAEUC-JpNfNf81.js → chunk-426QAEUC-ClfGjizN.js} +1 -1
  299. package/payload/server/public/assets/{chunk-4TB4RGXK-DmClEAD0.js → chunk-4TB4RGXK-BPKctJ5c.js} +1 -1
  300. package/payload/server/public/assets/{chunk-5FUZZQ4R-BI9blW3N.js → chunk-5FUZZQ4R-BWDCO9zw.js} +1 -1
  301. package/payload/server/public/assets/{chunk-5PVQY5BW-BbgttEFO.js → chunk-5PVQY5BW-BE34_Db0.js} +1 -1
  302. package/payload/server/public/assets/{chunk-EDXVE4YY-BX_LCFOx.js → chunk-EDXVE4YY-BysA-_6v.js} +1 -1
  303. package/payload/server/public/assets/{chunk-ENJZ2VHE-Bb7EoD0w.js → chunk-ENJZ2VHE-BMVyMsqA.js} +1 -1
  304. package/payload/server/public/assets/{chunk-ICPOFSXX-DH8uQk-s.js → chunk-ICPOFSXX-C5KRdLV4.js} +1 -1
  305. package/payload/server/public/assets/{chunk-OYMX7WX6-FH5kgXsw.js → chunk-OYMX7WX6-DVZD-AVc.js} +1 -1
  306. package/payload/server/public/assets/{chunk-U2HBQHQK-D_ljlkHr.js → chunk-U2HBQHQK-DYmQdx8x.js} +1 -1
  307. package/payload/server/public/assets/{chunk-X2U36JSP-BX3EmZvm.js → chunk-X2U36JSP-DrZenIl3.js} +1 -1
  308. package/payload/server/public/assets/{chunk-YZCP3GAM-Vu7-E93h.js → chunk-YZCP3GAM-CDuGbvMq.js} +1 -1
  309. package/payload/server/public/assets/{chunk-ZZ45TVLE-CwjhNPX5.js → chunk-ZZ45TVLE-COztbiu5.js} +1 -1
  310. package/payload/server/public/assets/classDiagram-6PBFFD2Q-B_pMa-SX.js +1 -0
  311. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-BdBAgF20.js +1 -0
  312. package/payload/server/public/assets/clone-CkNt9L9r.js +1 -0
  313. package/payload/server/public/assets/{dagre-Ce6gsj0C.js → dagre-Cv9Ib2OM.js} +1 -1
  314. package/payload/server/public/assets/{dagre-KV5264BT-BaMGpsoy.js → dagre-KV5264BT-CoEd61KZ.js} +1 -1
  315. package/payload/server/public/assets/{data-BHASh0_Y.js → data-DbSORCl4.js} +1 -1
  316. package/payload/server/public/assets/{diagram-5BDNPKRD-CHEE9rjq.js → diagram-5BDNPKRD-WXNzw3uW.js} +1 -1
  317. package/payload/server/public/assets/{diagram-G4DWMVQ6-C98sZLW1.js → diagram-G4DWMVQ6-C6IuQ2VV.js} +1 -1
  318. package/payload/server/public/assets/{diagram-MMDJMWI5-DNvMGsTZ.js → diagram-MMDJMWI5-CdJdir5A.js} +1 -1
  319. package/payload/server/public/assets/{diagram-TYMM5635-Cdte4IBa.js → diagram-TYMM5635-DxWKQH5T.js} +1 -1
  320. package/payload/server/public/assets/{erDiagram-SMLLAGMA-C9VZsWXK.js → erDiagram-SMLLAGMA-C9fvs33K.js} +1 -1
  321. package/payload/server/public/assets/{flowDiagram-DWJPFMVM-tuP5fzzR.js → flowDiagram-DWJPFMVM-BO7Yrbqv.js} +1 -1
  322. package/payload/server/public/assets/{ganttDiagram-T4ZO3ILL-SJgRPUwx.js → ganttDiagram-T4ZO3ILL-CQJyWBZq.js} +1 -1
  323. package/payload/server/public/assets/{gitGraphDiagram-UUTBAWPF-DU_cI_50.js → gitGraphDiagram-UUTBAWPF-DZfQHrYw.js} +1 -1
  324. package/payload/server/public/assets/{graph-labels-DXlmm1og.js → graph-labels-BBB5jsZk.js} +1 -1
  325. package/payload/server/public/assets/{graph-BhEI09tF.js → graph-ys_joP2o.js} +1 -1
  326. package/payload/server/public/assets/{graphlib-D_nAsvmx.js → graphlib-C40H-Q5E.js} +1 -1
  327. package/payload/server/public/assets/{infoDiagram-42DDH7IO-Cj2Y19m6.js → infoDiagram-42DDH7IO-CakfV5f9.js} +1 -1
  328. package/payload/server/public/assets/{ishikawaDiagram-UXIWVN3A-DMc1xq1y.js → ishikawaDiagram-UXIWVN3A-CPuBPyfa.js} +1 -1
  329. package/payload/server/public/assets/{journeyDiagram-VCZTEJTY-C4CRAQma.js → journeyDiagram-VCZTEJTY-zpZm2Mmo.js} +1 -1
  330. package/payload/server/public/assets/{kanban-definition-6JOO6SKY-CTr4AldU.js → kanban-definition-6JOO6SKY-DfJduQCo.js} +1 -1
  331. package/payload/server/public/assets/{line-Btlm_IAl.js → line-BpYQqO5R.js} +1 -1
  332. package/payload/server/public/assets/{mermaid-parser.core-DXFdj_y1.js → mermaid-parser.core-C5Mwi14D.js} +1 -1
  333. package/payload/server/public/assets/{mermaid.core-DFBhoCr5.js → mermaid.core-D8qBtvvT.js} +3 -3
  334. package/payload/server/public/assets/{mindmap-definition-QFDTVHPH-r9gVQybo.js → mindmap-definition-QFDTVHPH-Bli9JhIN.js} +1 -1
  335. package/payload/server/public/assets/{page-CDWu1Aft.js → page--bl5Y7ZI.js} +2 -2
  336. package/payload/server/public/assets/page-CwmZ76U7.js +1 -0
  337. package/payload/server/public/assets/{pieDiagram-DEJITSTG-CHKZjSaH.js → pieDiagram-DEJITSTG-MsLXTSLg.js} +1 -1
  338. package/payload/server/public/assets/{public-DyGWgfaZ.js → public-DltgEfA9.js} +2 -2
  339. package/payload/server/public/assets/{quadrantDiagram-34T5L4WZ-CSGR1HJr.js → quadrantDiagram-34T5L4WZ-De1sh2K0.js} +1 -1
  340. package/payload/server/public/assets/{requirementDiagram-MS252O5E-DZ6hX9D6.js → requirementDiagram-MS252O5E-D5Sfg1t_.js} +1 -1
  341. package/payload/server/public/assets/{sankeyDiagram-XADWPNL6-DbZBKh0m.js → sankeyDiagram-XADWPNL6-DHA3LIbv.js} +1 -1
  342. package/payload/server/public/assets/{sequenceDiagram-FGHM5R23-BHHpb8dt.js → sequenceDiagram-FGHM5R23-BE_QlG1B.js} +1 -1
  343. package/payload/server/public/assets/{stateDiagram-FHFEXIEX-DQ1jiLB4.js → stateDiagram-FHFEXIEX-NIwp3F4u.js} +1 -1
  344. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-pfk2F6st.js +1 -0
  345. package/payload/server/public/assets/{timeline-definition-GMOUNBTQ-BlGiEU7p.js → timeline-definition-GMOUNBTQ-CPE9jyDF.js} +1 -1
  346. package/payload/server/public/assets/{vennDiagram-DHZGUBPP-DmEH-hsB.js → vennDiagram-DHZGUBPP-CKfoyYmH.js} +1 -1
  347. package/payload/server/public/assets/{wardleyDiagram-NUSXRM2D-C7KJJ40d.js → wardleyDiagram-NUSXRM2D-B9yJek-o.js} +1 -1
  348. package/payload/server/public/assets/{xychartDiagram-5P7HB3ND-JDnusCaa.js → xychartDiagram-5P7HB3ND-DuCcSLqX.js} +1 -1
  349. package/payload/server/public/data.html +3 -3
  350. package/payload/server/public/graph.html +3 -3
  351. package/payload/server/public/index.html +4 -4
  352. package/payload/server/public/public.html +1 -1
  353. package/payload/server/server.js +133 -133
  354. package/payload/server/public/assets/channel-BmZnt3PP.js +0 -1
  355. package/payload/server/public/assets/classDiagram-6PBFFD2Q-kmMLFUpV.js +0 -1
  356. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-BV7Ae8ct.js +0 -1
  357. package/payload/server/public/assets/clone-B5eqoN9I.js +0 -1
  358. package/payload/server/public/assets/page-cyvshX4Z.js +0 -1
  359. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-CByT2RzF.js +0 -1
@@ -219,9 +219,9 @@ OPTIONS {
219
219
  // shared label — a WhatsApp export is a transcript, not a knowledge
220
220
  // document. Task 397 split the conversation path off into its own
221
221
  // `:ConversationArchive` parent; `:KnowledgeDocument` continues to mean
222
- // narrative documents only (PDF/web/Obsidian/Notion/contract attachment +
223
- // Gmail thread under the legacy `source:'email'` shape until Task 397's
224
- // email follow-up retargets it).
222
+ // narrative documents only (PDF/web/Obsidian/Notion/contract attachment).
223
+ // Email threads moved onto `:ConversationArchive {source:'email'}` in
224
+ // Task 426.
225
225
  //
226
226
  // KnowledgeDocument -[HAS_SECTION]-> Section
227
227
  // KnowledgeDocument -[PARTY]-> (Person|Organization) (contracts only)
@@ -233,9 +233,9 @@ OPTIONS {
233
233
  //
234
234
  // Two writer paths (see platform/plugins/memory/mcp/src/tools/memory-ingest.ts):
235
235
  // - Document path — MERGE :KnowledgeDocument keyed on `attachmentId`
236
- // (URL, file path, obsidian page, contract attachment, Gmail thread,
237
- // etc.). First-ingest re-writes sections per run; anchor edges to
238
- // subject nodes; orphan-candidate related entities.
236
+ // (URL, file path, obsidian page, contract attachment, etc.).
237
+ // First-ingest re-writes sections per run; anchor edges to subject
238
+ // nodes; orphan-candidate related entities.
239
239
  // - Conversation path — MERGE :ConversationArchive keyed on
240
240
  // `conversationIdentity` (= sha256(accountId + ":" +
241
241
  // sortedParticipantElementIds)). Source-agnostic across WhatsApp,
@@ -365,17 +365,32 @@ OPTIONS {
365
365
  //
366
366
  // Label union — every operator-meaningful label:
367
367
  // - Business identity: LocalBusiness, Service, PriceSpecification, OpeningHoursSpecification, Organization
368
+ // - Estate-agent ontology (Task 358): Listing, Property, Viewing, Offer, PostalAddress
368
369
  // - People: Person, UserProfile, Preference, AdminUser, AccessGrant
369
370
  // - Knowledge: KnowledgeDocument, ConversationArchive (Task 397), Section, Chunk (legacy),
370
371
  // DigitalDocument, CreativeWork, Question, FAQPage, DefinedTerm, Review, ImageObject
371
372
  // - Conversational: Conversation, AdminConversation, PublicConversation, Message,
372
373
  // UserMessage, AssistantMessage, ToolCall
373
- // - Tasks/projects/events: Task, Project, Event
374
+ // - Tasks/projects/events: Task, Project, Event, Meeting, Attachment
374
375
  // - Workflows: Workflow, WorkflowStep, WorkflowRun, StepResult
375
376
  // - Email: EmailAccount (config node only — email threads land on
376
- // :KnowledgeDocument {source:'email'} since Task 321)
377
+ // :ConversationArchive {source:'email'} since Task 426)
377
378
  // - CV/career sublabels: Position, Credential
378
379
  // - Public agents: Agent (projection of file-based public agents)
380
+ // - Ideas + concepts: Idea, Concept (admin-twin compiledTruth subjects)
381
+ // - Voice mirror (Task 356): VoiceProfile, VoiceEdit
382
+ // - Authored content / audit: SocialPost, AEOAudit, Page
383
+ // - Compiled truth (Task 306/391/392): TimelineEvent, CompiledTruthRevision,
384
+ // Report, OrphanCandidate, CitationProposal
385
+ //
386
+ // Excluded by design (carry no operator-meaningful free text, asserted by
387
+ // the doctrine test's EXCLUDED_FROM_INDEX set):
388
+ // - Trashed, GraphPreference — system flags / UI metadata
389
+ // - Email (legacy, retired Task 321; further retired Task 426) — replaced by :ConversationArchive {source:'email'}
390
+ // - Session, AnonVisitor, PageView, Click,
391
+ // ScrollMilestone, Recommendation — visitor analytics (Task 357)
392
+ // - Component — admin-resume rehydration JSON
393
+ // - CloudflareTunnel, CloudflareHostname — legacy projection (Task 288)
379
394
  //
380
395
  // Property union — every textual property the schema's writers assign:
381
396
  // - Generic: name, title, summary, body, content, text, description, headline, abstract,
@@ -417,13 +432,16 @@ DROP INDEX entity_search_public IF EXISTS;
417
432
 
418
433
  CREATE FULLTEXT INDEX entity_search_admin IF NOT EXISTS
419
434
  FOR (n:LocalBusiness|Service|PriceSpecification|OpeningHoursSpecification|Organization
435
+ |Listing|Property|Viewing|Offer|PostalAddress
420
436
  |Person|UserProfile|Preference|AdminUser|AccessGrant
421
437
  |KnowledgeDocument|ConversationArchive|Section|Chunk|DigitalDocument|CreativeWork|Question|FAQPage|DefinedTerm|Review|ImageObject
422
438
  |Conversation|AdminConversation|PublicConversation|Message|UserMessage|AssistantMessage|ToolCall
423
- |Task|Project|Event
439
+ |Task|Project|Event|Meeting|Attachment
424
440
  |Workflow|WorkflowStep|WorkflowRun|StepResult
425
441
  |EmailAccount
426
- |Position|Credential|Agent|Idea)
442
+ |Position|Credential|Agent|Idea|Concept
443
+ |VoiceProfile|VoiceEdit|SocialPost|AEOAudit|Page
444
+ |TimelineEvent|CompiledTruthRevision|Report|OrphanCandidate|CitationProposal)
427
445
  ON EACH [n.name, n.firstName, n.lastName, n.givenName, n.familyName,
428
446
  n.title, n.currentTitle, n.summary, n.body, n.content, n.text, n.description, n.headline, n.abstract,
429
447
  n.email, n.note, n.label, n.value, n.message, n.preview, n.tagline,
@@ -434,13 +452,16 @@ ON EACH [n.name, n.firstName, n.lastName, n.givenName, n.familyName,
434
452
 
435
453
  CREATE FULLTEXT INDEX entity_search_public IF NOT EXISTS
436
454
  FOR (n:LocalBusiness|Service|PriceSpecification|OpeningHoursSpecification|Organization
455
+ |Listing|Property|Viewing|Offer|PostalAddress
437
456
  |Person|UserProfile|Preference|AdminUser|AccessGrant
438
457
  |KnowledgeDocument|ConversationArchive|Section|Chunk|DigitalDocument|CreativeWork|Question|FAQPage|DefinedTerm|Review|ImageObject
439
458
  |Conversation|AdminConversation|PublicConversation|Message|UserMessage|AssistantMessage|ToolCall
440
- |Task|Project|Event
459
+ |Task|Project|Event|Meeting|Attachment
441
460
  |Workflow|WorkflowStep|WorkflowRun|StepResult
442
461
  |EmailAccount
443
- |Position|Credential|Agent|Idea)
462
+ |Position|Credential|Agent|Idea|Concept
463
+ |VoiceProfile|VoiceEdit|SocialPost|AEOAudit|Page
464
+ |TimelineEvent|CompiledTruthRevision|Report|OrphanCandidate|CitationProposal)
444
465
  ON EACH [n.name, n.firstName, n.lastName, n.givenName, n.familyName,
445
466
  n.title, n.currentTitle, n.summary, n.body, n.content, n.text, n.description, n.headline, n.abstract,
446
467
  n.email, n.note, n.label, n.value, n.message, n.preview, n.tagline,
@@ -516,15 +537,31 @@ OPTIONS {
516
537
  // Neo4j labels are set-semantic; the sublabel is added at ON CREATE SET
517
538
  // time in `ensureConversation` so the node carries both `:Conversation`
518
539
  // and the sublabel. No new constraints — the existing
519
- // conversation_id_unique constraint applies to Conversations regardless
520
- // of sublabel. The sublabel drives /graph canvas colour resolution and
521
- // filter popover chips per agentType without schema fragmentation.
540
+ // conversation_session_id_unique constraint applies to Conversations
541
+ // regardless of sublabel. The sublabel drives /graph canvas colour
542
+ // resolution and filter popover chips per agentType without schema
543
+ // fragmentation.
522
544
  // Pre-Task-633 Conversations stay unlabelled and render in the base
523
545
  // :Conversation colour (sublabel backfill is a separate task).
546
+ //
547
+ // Task 429 — kill `conversationId`; `sessionId` is canonical. One-shot
548
+ // migration: copy any legacy `conversationId` property onto `sessionId`
549
+ // and remove the legacy property. Idempotent via WHERE guard: re-runs
550
+ // against already-migrated rows are no-ops. The legacy
551
+ // `conversation_id_unique` constraint is dropped by name; the new
552
+ // uniqueness constraint is `conversation_session_id_unique` on
553
+ // `:Conversation.sessionId` (disambiguated from the :Session
554
+ // constraint that legitimately owns `session_id_unique`).
524
555
  // ----------------------------------------------------------
525
556
 
526
- CREATE CONSTRAINT conversation_id_unique IF NOT EXISTS
527
- FOR (c:Conversation) REQUIRE c.conversationId IS UNIQUE;
557
+ DROP CONSTRAINT conversation_id_unique IF EXISTS;
558
+
559
+ MATCH (c:Conversation) WHERE c.conversationId IS NOT NULL
560
+ SET c.sessionId = coalesce(c.sessionId, c.conversationId)
561
+ REMOVE c.conversationId;
562
+
563
+ CREATE CONSTRAINT conversation_session_id_unique IF NOT EXISTS
564
+ FOR (c:Conversation) REQUIRE c.sessionId IS UNIQUE;
528
565
 
529
566
  CREATE CONSTRAINT conversation_session_key_unique IF NOT EXISTS
530
567
  FOR (c:Conversation) REQUIRE c.sessionKey IS UNIQUE;
@@ -574,7 +611,7 @@ OPTIONS {
574
611
  //
575
612
  // Chain-fork invariant: the write path in
576
613
  // platform/ui/app/lib/neo4j-store.ts#persistMessage holds a
577
- // per-conversationId async mutex around the Cypher that observes
614
+ // per-sessionId async mutex around the Cypher that observes
578
615
  // the tail and CREATEs the new [:NEXT] edge. Without this, two
579
616
  // concurrent writes under READ_COMMITTED both see the same tail
580
617
  // and each CREATE an outgoing NEXT → two edges from one node.
@@ -590,10 +627,10 @@ CREATE CONSTRAINT message_id_unique IF NOT EXISTS
590
627
  FOR (m:Message) REQUIRE m.messageId IS UNIQUE;
591
628
 
592
629
  // Message.sessionKey is the canonical conversation pointer.
593
- // The legacy m.conversationId index stays until the final cutover, after the
594
- // full code-rename slice lands and no path reads m.conversationId.
630
+ // The legacy m.sessionId index stays until the final cutover, after the
631
+ // full code-rename slice lands and no path reads m.sessionId.
595
632
  CREATE INDEX message_conversation IF NOT EXISTS
596
- FOR (m:Message) ON (m.conversationId);
633
+ FOR (m:Message) ON (m.sessionId);
597
634
 
598
635
  CREATE INDEX message_session_key IF NOT EXISTS
599
636
  FOR (m:Message) ON (m.sessionKey);
@@ -798,24 +835,19 @@ OPTIONS {
798
835
  // ----------------------------------------------------------
799
836
 
800
837
  // ----------------------------------------------------------
801
- // Email threads — :KnowledgeDocument {source:'email'}
838
+ // Email threads — :ConversationArchive {source:'email'}
802
839
  //
803
- // Task 321 retired the legacy :Email label. Every inbound (and outbound)
804
- // email lands as one :KnowledgeDocument per thread, keyed on
805
- // attachmentId = sha256("email:<accountId>:<rootMessageId>"). The body
806
- // is the verbatim chronological transcript; per-message envelopes live
807
- // in a JSON-serialised `messages` property; address parties hang off
808
- // the document as :Person edges (FROM/TO/CC). The email-fetch script
809
- // writes them via storeEmailMessage in plugins/email/mcp/src/lib/graph.ts.
840
+ // Task 426 retargeted email threads off :KnowledgeDocument onto the
841
+ // conversation-archive pipeline. The email plugin's email-ingest tool
842
+ // dispatches `conversation-archive-ingest.sh --source email` once per
843
+ // thread; each invocation MERGEs one :ConversationArchive
844
+ // (conversationIdentity-keyed, source-scoped) and writes :Section
845
+ // chunks via :HAS_SECTION + :NEXT.
810
846
  //
811
- // No :Email constraints or indexes are declared. The general
812
- // KnowledgeDocument constraints + indexes (above) already cover
813
- // uniqueness, accountId lookup, and embedding search. Email-specific
847
+ // No email-specific constraints or indexes are declared. The general
848
+ // ConversationArchive constraints + indexes (above) cover uniqueness,
849
+ // accountId lookup, and Section embedding search. Email-specific
814
850
  // filtering (source='email') uses the generic accountId + source path.
815
- //
816
- // Relationships:
817
- // (KnowledgeDocument {source:'email'})-[:RECEIVED_BY]->(EmailAccount)
818
- // (KnowledgeDocument {source:'email'})-[:FROM|:TO|:CC]->(Person)
819
851
  // ----------------------------------------------------------
820
852
 
821
853
  // ----------------------------------------------------------
@@ -992,7 +1024,7 @@ FOR (tc:ToolCall) ON (tc.accountId, tc.startedAt);
992
1024
  //
993
1025
  // Properties:
994
1026
  // componentId — UUID, primary key
995
- // conversationId / accountId / messageId — denormalised for
1027
+ // sessionId / accountId / messageId — denormalised for
996
1028
  // account-scoped reads and cross-account isolation audits
997
1029
  // name — component name (document-editor, action-buttons,
998
1030
  // single-select, etc.)
@@ -1033,7 +1065,7 @@ FOR (c:Component) ON (c.accountId);
1033
1065
  // Properties:
1034
1066
  // attachmentId — UUID assigned at storeAttachment time; matches
1035
1067
  // the on-disk directory + Neo4j node id.
1036
- // conversationId — denormalised for filtered scans + cascade delete.
1068
+ // sessionId — denormalised for filtered scans + cascade delete.
1037
1069
  // accountId — account-isolation. Reads MUST scope by this.
1038
1070
  // messageId — back-pointer to parent :Message.
1039
1071
  // filename — original upload name (kept for chip render).
@@ -1258,9 +1290,9 @@ FOR (a:PostalAddress) ON (a.postalCode);
1258
1290
  // the next distillation.
1259
1291
  //
1260
1292
  // `authorshipMode` is an enum property on content-bearing labels
1261
- // (`:KnowledgeDocument` (includes email threads under the legacy
1262
- // `source:'email'` shape), `:ConversationArchive` (Task 397 — every chat
1263
- // transcript), `:Message`, `:SocialPost`) with
1293
+ // (`:KnowledgeDocument`, `:ConversationArchive` (Task 397 every chat
1294
+ // transcript, including email threads under `source:'email'` post-Task-426),
1295
+ // `:Message`, `:SocialPost`) with
1264
1296
  // values `human-only | human-led-agent-assisted | agent-led-human-reviewed
1265
1297
  // | agent-only | unknown`. Legacy nodes default to `unknown` until
1266
1298
  // reviewed via the voice-mirror backfill flow. The index lets the
@@ -1534,9 +1566,10 @@ CREATE INDEX local_business_compiled_truth_public_updated_at IF NOT EXISTS
1534
1566
  FOR (b:LocalBusiness) ON (b.compiledTruthPublicUpdatedAt);
1535
1567
 
1536
1568
  // ----------------------------------------------------------
1537
- // :CompiledTruthRevision (Task 391) audit history of every
1538
- // `compiledTruth` value an entity has ever held. Captured in the
1539
- // same transaction as the rewriter SET so revision history can
1569
+ // :CompiledTruthRevision (Task 391, twin discriminator added in
1570
+ // Task 436) audit history of every `compiledTruth` /
1571
+ // `compiledTruthPublic` value an entity has ever held. Captured in
1572
+ // the same transaction as the writer's SET so revision history can
1540
1573
  // never desync from the live property. Pruned by dream-cycle
1541
1574
  // phase 5 (keep newest 20 per entity) — never written-and-pruned
1542
1575
  // in the same TX as the main rewrite.
@@ -1551,9 +1584,13 @@ FOR (b:LocalBusiness) ON (b.compiledTruthPublicUpdatedAt);
1551
1584
  // MERGE (e)-[:HAS_REVISION]->(r:CompiledTruthRevision {revisionId: $id})
1552
1585
  // Never label-only MERGE on :CompiledTruthRevision.
1553
1586
  //
1587
+ // `twin` enum: 'compiledTruth' (private/admin twin) or
1588
+ // 'compiledTruthPublic' (public twin). One revision row per twin
1589
+ // per write; the specialist calls `memory-update` once per twin.
1590
+ //
1554
1591
  // `source` enum (exact, no catch-all):
1555
- // 'rewriter' — compiled-truth-rewriter library wrote the truth.
1556
- // 'operator' — operator overrode via a sanctioned write route.
1592
+ // 'rewriter' — compiled-truth-rewriter specialist wrote the truth.
1593
+ // 'operator' — operator hint overrode the rewriter for this twin.
1557
1594
  // ----------------------------------------------------------
1558
1595
 
1559
1596
  CREATE CONSTRAINT compiled_truth_revision_id_unique IF NOT EXISTS
@@ -1565,6 +1602,9 @@ FOR (r:CompiledTruthRevision) ON (r.accountId);
1565
1602
  CREATE INDEX compiled_truth_revision_written_at IF NOT EXISTS
1566
1603
  FOR (r:CompiledTruthRevision) ON (r.writtenAt);
1567
1604
 
1605
+ CREATE INDEX compiled_truth_revision_twin IF NOT EXISTS
1606
+ FOR (r:CompiledTruthRevision) ON (r.twin);
1607
+
1568
1608
  // ----------------------------------------------------------
1569
1609
  // :Report node — durable, keyword-routed output of admin
1570
1610
  // workflows (daily briefing, dream cycle, ad-hoc analyses).
@@ -99,6 +99,11 @@
99
99
  "source": "./scheduling",
100
100
  "version": "0.1.0"
101
101
  },
102
+ {
103
+ "name": "substack-import",
104
+ "source": "./substack-import",
105
+ "version": "0.1.0"
106
+ },
102
107
  {
103
108
  "name": "telegram",
104
109
  "source": "./telegram",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "admin",
3
- "description": "Platform administration plugin. Provides system-status, public-hostname (deterministic Cloudflare public-URL resolver, single call returning the operator's canonical hostname so agents never guess property names on :CloudflareHostname nodes), publish-site (move an extracted static-site tree under <accountDir>/sites/<slug>/, emit one canonical path slug, and refresh llms.txt at the site root — typed refusal taxonomy replaces the prior skill-prose contract), brand-settings, account-manage, account-update, admin-add, admin-remove, admin-list, admin-update-pin, agent-list, agent-config-read, logs-read, plugin-read, skill-load (one-call resolve+read for SKILL.md by skill name, the canonical primitive for loading a named skill; plugin-read remains the reader for references/* and PLUGIN.md), store-skill (deterministic write counterpart to plugin-read; persists operator-authored skills as plugin files under the active account), session-reset, session-resume, file-attach, wifi, action-approval tools (action-pending, action-approve, action-reject, action-edit), and session-retrospective-mark-complete (the deterministic sentinel the session-end Stop hook reads via JSONL grep to release the retrospective gate; admin calls it once per session after running the three-pass retrospective) for managing the Maxy platform.",
3
+ "description": "Platform administration plugin. Provides system-status, public-hostname (deterministic Cloudflare public-URL resolver, single call returning the operator's canonical hostname so agents never guess property names on :CloudflareHostname nodes), publish-site (move an extracted static-site tree under <accountDir>/sites/<slug>/, emit one canonical path slug, and refresh llms.txt at the site root — typed refusal taxonomy replaces the prior skill-prose contract), brand-settings, account-manage, account-update, admin-add, admin-remove, admin-list, admin-update-pin, agent-list, agent-config-read, logs-read, plugin-read, skill-load (one-call resolve+read for SKILL.md by skill name, the canonical primitive for loading a named skill; plugin-read remains the reader for references/* and PLUGIN.md), store-skill (deterministic write counterpart to plugin-read; persists operator-authored skills as plugin files under the active account), session-reset, session-resume, file-attach, wifi, action-approval tools (action-pending, action-approve, action-reject, action-edit), session-retrospective-mark-complete (the deterministic sentinel the session-end Stop hook reads via JSONL grep to release the retrospective gate; admin calls it once per session after running the three-pass retrospective), and pre-turn-graph-pass-skip (the deterministic decline sentinel the per-turn graph-pass Stop hook reads via JSONL grep to release the per-turn gate when the operator turn has no new writes; admin calls it instead of dispatching to database-operator) for managing the Maxy platform.",
4
4
  "version": "0.1.0",
5
5
  "author": {
6
6
  "name": "Rubytech LLC"
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: admin
3
3
  surface: platform
4
- description: "Platform administration plugin. Provides system-status, public-hostname (deterministic Cloudflare public-URL resolver, single call returning the operator's canonical hostname so agents never guess property names on :CloudflareHostname nodes), publish-site (move an extracted static-site tree under <accountDir>/sites/<slug>/, emit one canonical path slug, and refresh llms.txt at the site root — typed refusal taxonomy replaces the prior skill-prose contract), brand-settings, account-manage, account-update, admin-add, admin-remove, admin-list, admin-update-pin, agent-list, agent-config-read, logs-read, plugin-read, skill-load (one-call resolve+read for SKILL.md by skill name, the canonical primitive for loading a named skill; plugin-read remains the reader for references/* and PLUGIN.md), store-skill (deterministic write counterpart to plugin-read; persists operator-authored skills as plugin files under the active account), session-reset, session-resume, file-attach, wifi, action-approval tools (action-pending, action-approve, action-reject, action-edit), and session-retrospective-mark-complete (the deterministic sentinel the session-end Stop hook reads via JSONL grep to release the retrospective gate; admin calls it once per session after running the three-pass retrospective) for managing the Maxy platform."
4
+ description: "Platform administration plugin. Provides system-status, public-hostname (deterministic Cloudflare public-URL resolver, single call returning the operator's canonical hostname so agents never guess property names on :CloudflareHostname nodes), publish-site (move an extracted static-site tree under <accountDir>/sites/<slug>/, emit one canonical path slug, and refresh llms.txt at the site root — typed refusal taxonomy replaces the prior skill-prose contract), brand-settings, account-manage, account-update, admin-add, admin-remove, admin-list, admin-update-pin, agent-list, agent-config-read, logs-read, plugin-read, skill-load (one-call resolve+read for SKILL.md by skill name, the canonical primitive for loading a named skill; plugin-read remains the reader for references/* and PLUGIN.md), store-skill (deterministic write counterpart to plugin-read; persists operator-authored skills as plugin files under the active account), session-reset, session-resume, file-attach, wifi, action-approval tools (action-pending, action-approve, action-reject, action-edit), session-retrospective-mark-complete (the deterministic sentinel the session-end Stop hook reads via JSONL grep to release the retrospective gate; admin calls it once per session after running the three-pass retrospective), and pre-turn-graph-pass-skip (the deterministic decline sentinel the per-turn graph-pass Stop hook reads via JSONL grep to release the per-turn gate when the operator turn has no new writes; admin calls it instead of dispatching to database-operator) for managing the Maxy platform."
5
5
  tools:
6
6
  - name: system-status
7
7
  publicAllowlist: false
@@ -75,6 +75,9 @@ tools:
75
75
  - name: session-retrospective-mark-complete
76
76
  publicAllowlist: false
77
77
  adminAllowlist: true
78
+ - name: pre-turn-graph-pass-skip
79
+ publicAllowlist: false
80
+ adminAllowlist: true
78
81
  hidden:
79
82
  - remote-auth-status
80
83
  - remote-auth-set-password
@@ -110,7 +113,7 @@ Tools are available via the `admin` MCP server.
110
113
 
111
114
  `logs-read { type: "agent-stream" }` is the canonical name for the per-conversation tool-use/tool-result archive previously called `system`; both names work and the legacy alias is preserved.
112
115
 
113
- **Stream log is the primary diagnostic surface for an in-progress session.** Every stream log is named by sessionKey and the stream-log file exists from the first token. The single-writer mandate (2026-05-14) mechanically enforces this contract: the single writer module at [`platform/ui/app/lib/claude-agent/stream-log-writer.ts`](../../ui/app/lib/claude-agent/stream-log-writer.ts) owns every open of `claude-agent-stream-*.log`, opens the file lazily on the first SDK token byte (via `streamLog.writeToken`), and buffers pre-token markers in memory while duplicating them to `server.log` via `console.error` so zero-token sessions retain observability. The build gate `platform/ui/scripts/check-stream-log-writer.mjs` rejects any external `appendFileSync`/`createWriteStream` against the `claude-agent-stream-*` pattern outside the writer module, plus any `claude-agent-stream-${conversationId}` literal (the pre-1013 wrong-identifier signature that produced two files for one session on the Beacons Pi 2026-05-14). The first-token invariant is bound by `platform/scripts/__tests__/first-token-creates-stream-log.test.sh`: one operator turn, one token, `claude-agent-stream-<sessionKey>.log` exists and contains the token bytes after the byte returns to the operator. The parent-process console fan-out tee in [`platform/ui/app/lib/claude-agent/logging.ts`](../../ui/app/lib/claude-agent/logging.ts) appends every `[<tag>]`-prefixed `console.error` / `console.log` line to every active session's stream log alongside `server.log`. For diagnosing an in-session issue (WhatsApp inbound, Cloudflare action, persist write, baileys error), call `logs-read { sessionKey: "<…>" }` first — the stream log carries both the agent lifecycle AND the parent-process events that occurred during the session window. The `conversationId` parameter remains a legacy alias resolving to the same sessionKey-named file. `logs-read { type: "server" }` is the cross-session escape hatch for events outside any single session window.
116
+ **Stream log is the primary diagnostic surface for an in-progress session.** Every stream log is named by sessionKey and the stream-log file exists from the first token. The single-writer mandate (2026-05-14) mechanically enforces this contract: the single writer module at [`platform/ui/app/lib/claude-agent/stream-log-writer.ts`](../../ui/app/lib/claude-agent/stream-log-writer.ts) owns every open of `claude-agent-stream-*.log`, opens the file lazily on the first SDK token byte (via `streamLog.writeToken`), and buffers pre-token markers in memory while duplicating them to `server.log` via `console.error` so zero-token sessions retain observability. The build gate `platform/ui/scripts/check-stream-log-writer.mjs` rejects any external `appendFileSync`/`createWriteStream` against the `claude-agent-stream-*` pattern outside the writer module, plus any `claude-agent-stream-${sessionId}` literal (the pre-1013 wrong-identifier signature that produced two files for one session on the Beacons Pi 2026-05-14). The first-token invariant is bound by `platform/scripts/__tests__/first-token-creates-stream-log.test.sh`: one operator turn, one token, `claude-agent-stream-<sessionKey>.log` exists and contains the token bytes after the byte returns to the operator. The parent-process console fan-out tee in [`platform/ui/app/lib/claude-agent/logging.ts`](../../ui/app/lib/claude-agent/logging.ts) appends every `[<tag>]`-prefixed `console.error` / `console.log` line to every active session's stream log alongside `server.log`. For diagnosing an in-session issue (WhatsApp inbound, Cloudflare action, persist write, baileys error), call `logs-read { sessionKey: "<…>" }` first — the stream log carries both the agent lifecycle AND the parent-process events that occurred during the session window. The `sessionId` parameter remains a legacy alias resolving to the same sessionKey-named file. `logs-read { type: "server" }` is the cross-session escape hatch for events outside any single session window.
114
117
 
115
118
  ## Skills
116
119
 
@@ -139,8 +142,9 @@ Tools are available via the `admin` MCP server.
139
142
  - `hooks/webfetch-preflight.mjs` — short-circuits WebFetch on JS-SPA shells with a structured `WEBFETCH_CANNOT_READ_JS_SPA` error so the agent surfaces a loud failure to the owner instead of paying the 60s extraction timeout. Fail-open on any internal error.
140
143
  - `hooks/askuserquestion-investigate-gate.sh` — PreToolUse matcher=`AskUserQuestion`. Blocks the question (exit 2) when no read-only investigation tool has fired since the latest real user turn in the session JSONL. The structural fix for the failure class where the agent fabricates a menu before evidence-gathering (session `c085ec2c-46fb-4b73-8865-68cf85866ea8` 2026-05-22 — "change remote access password" → invented options "Admin PIN / Cloudflare tunnel / WiFi password" with zero prior tool_use; post-correction the agent immediately fired `remote-auth-status` → `ToolSearch` → `remote-auth-set-password`, proving it knew the moves). **Allowlist** (exact, with trailing `__<tool>` suffix-match for namespaced `mcp__plugin_<plugin>_<server>__<tool>` aliases): `ToolSearch`, `Grep`, `Glob`, `Read`, `LS`, `NotebookRead`, `Bash`, `WebFetch`, `WebSearch`, plus the read-only admin / memory MCP tools (`*-status`, `*-list`, `*-read`, `skill-find`, `memory-find-candidates`, `profile-read`, `conversation-list`, `memory-list-attachments`, `memory-read-attachment`). **Block message:** `Blocked: AskUserQuestion requires at least one investigation tool (ToolSearch, Grep, Read, *-list, *-status, *-read, skill-find, ...) earlier in this turn. Search the operator's literal phrase first.` **Log line** (stderr, one per call): `[ask-gate] decision=<allow|block> sessionId=<id8> seen=<csv|-> reason=<allowlist-hit|no-investigation|fail-open-no-transcript|fail-open-parse-error>`. **Fail-open** on missing transcript or parse error — nudges, never bricks the UI.
141
144
  - `hooks/session-end-retrospective.sh` — **Stop hook.** Fires on every assistant end_turn but exits 0 with `trigger-skipped reason=<role-not-admin|is-specialist|empty-stdin|missing-transcript|no-intent-match>` on every path EXCEPT when the operator's latest real-user message carries an end-intent token (`/end`, `/archive`, `end session`, `archive this session`, case-insensitive, must match the whole message or a standalone line — not embedded in prose). On that path the hook blocks (exit 2 + structured retrospective instruction on stderr per Stop-hook contract) and emits `[session-retrospective] gate-blocked sessionId=<id> reason=sentinel-absent` until the admin agent calls the `session-retrospective-mark-complete` MCP sentinel tool. Completion is recognised by greping the operator's own JSONL (`transcript_path` on the Stop envelope) for a `tool_use` block whose `name` equals that exact string — never by parsing prose ([[feedback_no_stdout_parsing_for_control_flow]], [[feedback_doctrine_paragraph_is_not_a_gate]]). The sentinel-grep doubles as the re-entry guard: every Stop after the sentinel call sees it and exits 0 with `gate-released sessionId=<id>`. Recursion guard: any session whose `MAXY_SPECIALIST` env is set (specialist subagent dispatched via Task tool) skips the gate. The Sidebar archive button POSTs `/:sessionId/archive` directly to the manager which kills the PTY — no Stop fires after that, so clicking archive is the operator's current escape hatch (opt-out remains deferred per the task spec). All emits go through `POST /api/admin/log-ingest`; the only stderr writer is the gate-blocked path (the instruction block the agent reads). The retrospective itself runs as one or more additional turns inside the operator's existing admin session — Task-tool delegation to `database-operator` is the existing IDENTITY.md "Recording" route, not a parallel admin session ([[feedback_deterministic_means_remove_llm]]).
142
- - `hooks/pre-turn-graph-pass.sh` — **UserPromptSubmit hook.** Tasks 425, 430 supersedes Task 412's Stop-hook registration of the same logic. Task 412 fired on every admin-agent `end_turn`, including the agent's own ack after the dispatch, producing an unbounded loop until context exhaustion. Firing on `UserPromptSubmit` fires once per operator prompt and removes the loop primitive entirely. **Task 430 reshaped the orchestration:** admin is the session-walker. The hook no longer packages the conversation into the specialist's prompt that collapsed the data channel and instruction channel into one context, so operator prose pattern-matching as a writer-binding instruction ("memory-update is denied this session") was treated as binding and the pass self-denied (session `d7070b66-1759-41ca-a771-d7559b8a1967` retrospective wrote 3 graph rows on the same session where the pre-turn pass returned `writes=0`). The Task 425 Task 430 shape change brings the per-turn pass into line with the session-end retrospective, which never had this defect: admin walks, admin dispatches per-write briefs to `database-operator`. The hook now `GET /api/admin/post-turn-context?conversationId&accountId` to fetch every node already written under this conversationId, then emits the documented UserPromptSubmit stdout JSON envelope `{"hookSpecificOutput":{"hookEventName":"UserPromptSubmit","additionalContext":"<directive>"}}` with `exit 0`. The directive body begins with the literal token `[system: pre-turn-graph-pass-hook]` and carries one interpolated `<prior-writes>` block (the skip-list); the IDENTITY.md UserPromptSubmit-directive section routes the agent into scanning the just-submitted operator turn (already in admin's context) and dispatching one `Task → database-operator` per candidate write before composing its reply. Coverage trade: the assistant response to the most recent operator prompt is not covered by a per-turn pass until the next operator turn (or never, if no next turn arrives); end-of-session coverage is provided by `session-end-retrospective.sh` which walks the full transcript at `/end`. Duplicate writes between per-turn dispatches and the admin agent's discretionary inline `database-operator` dispatch are accepted at write time; cleanup is delegated to the dream-cycle / hygiene sweeps (Tasks 410, 411). Early exits: `reason=role-not-admin` (the hook fires only on admin-agent prompt submissions by doctrine), `reason=is-specialist` (`MAXY_SPECIALIST` env-stamped on every subagent PTY blocks the hook from firing inside a specialist's own session), `reason=missing-transcript` (safety exit), `reason=wrong-hook-event event=<…>` (stale Stop-shaped fire), `reason=missing-env env=MAXY_UI_INTERNAL_PORT` (UI port unset). All emits go through `POST /api/admin/log-ingest` under tag `pre-turn-graph-pass`. The canonical fire line is `dispatch sessionId=<id> conversationId=<id> directive-shape=admin-walks priorWritesCount=<n> contextBytes=<n> ms=<n>`; the `directive-shape=admin-walks` field distinguishes the Task 430 shape from any cached device still running the Task 425 shape. Success: one or more `db-op: writes=<n>` lines in the admin session transcript reflecting per-write dispatches admin actually emitted (zero candidate writes ⇒ zero dispatches, no `db-op` line). Failure: a `db-op: error reason=<…>` line, or a turn that named new entities / commitments where admin emitted no dispatch — the latter is the regression signal for self-denial.
143
- - `hooks/turn-completed-graph-write.sh` — **Dormant since Task 214**the Stop-hook registration is no longer written to account settings.json; admin delegates graph writes to `database-operator` via the Task tool. The script, envelope walker, loopback `/api/admin/claude-sessions` 127.0.0.1 bypass, `[turn-recorder]` emitters, recorder-auto-archive subscriber, and `initialMessage` envelope spec are preserved as reusable infrastructure for any future autonomous post-turn flow. Historical contract (still describes the dormant path): Stop hook fired once per completed admin-agent turn. Gates on `MAXY_SESSION_ROLE=admin` + `MAXY_SPECIALIST!=database-operator` so it never recurses into the recorder PTY or fires on public sessions. **Task 147** the recorder is spawned via the same route Sidebar uses. ONE POST to `POST /api/admin/claude-sessions`, body carries `{specialist:'database-operator', model:'haiku', initialMessage:<json-envelope>, adminSessionId:<op>}` no synthetic `senderId: 'turn-recorder'` marker. The Hono wrapper bypasses cookie auth on this exact method+path when the request originates from `127.0.0.1` (same trust boundary the claude-session-manager itself relies on), looks up the operator's senderId from the manager's `/<adminSessionId>/meta`, and forwards a Sidebar-shape spawn body. The `/recorder-spawn` sibling route is gone. The hook reads its UI port from `MAXY_UI_INTERNAL_PORT` (stamped on the manager systemd unit) no fallback; absence emits `[turn-recorder] spawn-failed reason=missing-env env=MAXY_UI_INTERNAL_PORT` to stderr instead of silently 19199-ing. **Task 177** `initialMessage` is a JSON-stringified envelope; the schema lives in [`platform/plugins/docs/references/admin-session.md`](../docs/references/admin-session.md) under "`initialMessage` JSON envelope (Task 177)". Top-level keys exactly: `turns`, `conversationId`, `accountId`, `occurredAt`. `turns` is the full conversation transcript, oldest first, newest last, with each entry `{ role: "user"|"assistant", text, ts, toolCalls? }`. No windowing, no truncation. Multi-record assistant messages collapse on `message.id`. `tool_use` and matching `tool_result` blocks attach as a single `toolCalls` entry on the owning assistant turn; the user record carrying only the `tool_result` does not create a separate user turn. No leading instruction prose. `toolCalls[].input` and `toolCalls[].output` are native JSON values, never re-stringified. (Replaces Task 175's `(operatorMessage, assistantReply)` pair, which asserted a temporal Q→A relationship the walker never enforced.) One observability line `[turn-recorder] envelope sessionId=<op> turnsCount=<n> userTurns=<n> assistantTurns=<n> toolCallTurns=<n>` precedes `spawn-request`. The envelope rides on the `/spawn` body as a trailing positional argv to `claude`, so the database-operator session's JSONL first `role=user` line is the JSON object verbatim. No separate `POST /:id/input` call, no bracketed-paste, no keystroke injection. The recorder-auto-archive subscriber stops the recorder PTY as soon as its JSONL contains an assistant message with `stop_reason === "end_turn"`. **Task 129** every emit goes through `POST /api/admin/log-ingest` so the lines land in `server.log` keyed by the operator session id. The chain is `trigger` `spawn-request` `spawn-success` `input-delivered` `tool-call` × N → `tool-result` × N `write-complete` `auto-archive`; each gated-off path emits one `trigger-skipped reason=<role-not-admin|is-recorder|empty-stdin|missing-transcript|conversation-empty>` line. Failure modes `spawn-failed`, `tool-surface-missing`, `input-failed`, `write-empty`, `auto-archive reason=stale-recorder` each emit one named line; absence is itself a defect.
145
+ - `hooks/per-turn-graph-pass-gate.sh` — **Stop hook.** Task 440. Per-turn blocking gate that closes the gap left when Task 425 moved the per-turn graph pass off Stop onto `UserPromptSubmit`. `pre-turn-graph-pass.sh` delivers the directive (with prior-writes skip-list) as `additionalContext` and exits 0 that channel can't carry a release path because UserPromptSubmit's only blocking shape erases the prompt without feeding stderr to Claude ([[feedback_doctrine_paragraph_is_not_a_gate]]). This Stop hook is the enforcement primitive: walks the operator's JSONL since the latest real-user message, releases on either a `Task` `tool_use` whose `input.subagent_type` is `database-operator` (admin dispatched the writes) or a `tool_use` whose `name` is `mcp__admin__pre-turn-graph-pass-skip` (admin declined via the deterministic skip sentinel). Both releases emit `gate-released sessionId=<id> via=<dispatch|skip-sentinel>` and exit 0. Absent both, exits 2 with a stderr instruction naming the two release paths admin reads the instruction (Stop's exit-2 stderr-to-Claude contract) and acts. Recursion guard: any session with `MAXY_SPECIALIST` set (specialist subagent dispatched via Task) skips. Loop-safety: once either release tool_use sits in the JSONL, every subsequent Stop on the same operator-prompt window sees it and exits 0 the Task 412 loop is avoided because the release decision is JSONL-based, never a re-fire of the directive. Composes with `session-end-retrospective.sh` (the other Stop-array entry): the session-end hook gates only on operator end-intent, this one gates every turn. Early exits: `reason=role-not-admin`, `reason=is-specialist`, `reason=empty-stdin`, `reason=missing-transcript`, `reason=no-real-user` (transcript has no real-user record yet — e.g. SessionStart bootstrap, or only `tool_result`-shaped user records). All emits go through `POST /api/admin/log-ingest` under tag `per-turn-graph-pass-gate`.
146
+ - `hooks/pre-turn-graph-pass.sh` — **UserPromptSubmit hook.** Tasks 425, 430 supersedes Task 412's Stop-hook registration of the same logic. Task 412 fired on every admin-agent `end_turn`, including the agent's own ack after the dispatch, producing an unbounded loop until context exhaustion. Firing on `UserPromptSubmit` fires once per operator prompt and removes the loop primitive entirely. **Task 430 reshaped the orchestration:** admin is the session-walker. The hook no longer packages the conversation into the specialist's prompt that collapsed the data channel and instruction channel into one context, so operator prose pattern-matching as a writer-binding instruction ("memory-update is denied this session") was treated as binding and the pass self-denied (session `d7070b66-1759-41ca-a771-d7559b8a1967` retrospective wrote 3 graph rows on the same session where the pre-turn pass returned `writes=0`). The Task 425 Task 430 shape change brings the per-turn pass into line with the session-end retrospective, which never had this defect: admin walks, admin dispatches per-write briefs to `database-operator`. The hook now `GET /api/admin/post-turn-context?sessionId&accountId` to fetch every node already written under this sessionId, then emits the documented UserPromptSubmit stdout JSON envelope `{"hookSpecificOutput":{"hookEventName":"UserPromptSubmit","additionalContext":"<directive>"}}` with `exit 0`. The directive body begins with the literal token `[system: pre-turn-graph-pass-hook]` and carries one interpolated `<prior-writes>` block (the skip-list); the IDENTITY.md UserPromptSubmit-directive section routes the agent into scanning the just-submitted operator turn (already in admin's context) and dispatching one `Task database-operator` per candidate write before composing its reply. Enforcement is the Stop-array sibling `per-turn-graph-pass-gate.sh` (Task 440): every admin turn end blocks until admin either dispatched the writes (`Task` `tool_use` with `input.subagent_type=database-operator`) or called the skip sentinel (`pre-turn-graph-pass-skip` MCP tool with a `reason` arg) since the latest real-user message. Duplicate writes between per-turn dispatches and the admin agent's discretionary inline `database-operator` dispatch are accepted at write time; cleanup is delegated to the dream-cycle / hygiene sweeps (Tasks 410, 411). Early exits: `reason=role-not-admin` (the hook fires only on admin-agent prompt submissions by doctrine), `reason=is-specialist` (`MAXY_SPECIALIST` env-stamped on every subagent PTY blocks the hook from firing inside a specialist's own session), `reason=missing-transcript` (safety exit), `reason=wrong-hook-event event=<…>` (stale Stop-shaped fire), `reason=missing-env env=MAXY_UI_INTERNAL_PORT` (UI port unset). All emits go through `POST /api/admin/log-ingest` under tag `pre-turn-graph-pass`. The canonical fire line is `dispatch sessionId=<id> sessionId=<id> directive-shape=admin-walks priorWritesCount=<n> contextBytes=<n> ms=<n>`; the `directive-shape=admin-walks` field distinguishes the Task 430 shape from any cached device still running the Task 425 shape. Success: one or more `db-op: writes=<n>` lines in the admin session transcript reflecting per-write dispatches admin actually emitted (zero candidate writes zero dispatches, no `db-op` line). Failure: a `db-op: error reason=<…>` line, or a turn that named new entities / commitments where admin emitted no dispatchthe latter is the regression signal for self-denial.
147
+ - `hooks/turn-completed-graph-write.sh` — **Dormant since Task 214** — the Stop-hook registration is no longer written to account settings.json; admin delegates graph writes to `database-operator` via the Task tool. The script, envelope walker, loopback `/api/admin/claude-sessions` 127.0.0.1 bypass, `[turn-recorder]` emitters, recorder-auto-archive subscriber, and `initialMessage` envelope spec are preserved as reusable infrastructure for any future autonomous post-turn flow. Historical contract (still describes the dormant path): Stop hook fired once per completed admin-agent turn. Gates on `MAXY_SESSION_ROLE=admin` + `MAXY_SPECIALIST!=database-operator` so it never recurses into the recorder PTY or fires on public sessions. **Task 147** — the recorder is spawned via the same route Sidebar uses. ONE POST to `POST /api/admin/claude-sessions`, body carries `{specialist:'database-operator', model:'haiku', initialMessage:<json-envelope>, adminSessionId:<op>}` — no synthetic `senderId: 'turn-recorder'` marker. The Hono wrapper bypasses cookie auth on this exact method+path when the request originates from `127.0.0.1` (same trust boundary the claude-session-manager itself relies on), looks up the operator's senderId from the manager's `/<adminSessionId>/meta`, and forwards a Sidebar-shape spawn body. The `/recorder-spawn` sibling route is gone. The hook reads its UI port from `MAXY_UI_INTERNAL_PORT` (stamped on the manager systemd unit) — no fallback; absence emits `[turn-recorder] spawn-failed reason=missing-env env=MAXY_UI_INTERNAL_PORT` to stderr instead of silently 19199-ing. **Task 177** — `initialMessage` is a JSON-stringified envelope; the schema lives in [`platform/plugins/docs/references/admin-session.md`](../docs/references/admin-session.md) under "`initialMessage` JSON envelope (Task 177)". Top-level keys exactly: `turns`, `sessionId`, `accountId`, `occurredAt`. `turns` is the full conversation transcript, oldest first, newest last, with each entry `{ role: "user"|"assistant", text, ts, toolCalls? }`. No windowing, no truncation. Multi-record assistant messages collapse on `message.id`. `tool_use` and matching `tool_result` blocks attach as a single `toolCalls` entry on the owning assistant turn; the user record carrying only the `tool_result` does not create a separate user turn. No leading instruction prose. `toolCalls[].input` and `toolCalls[].output` are native JSON values, never re-stringified. (Replaces Task 175's `(operatorMessage, assistantReply)` pair, which asserted a temporal Q→A relationship the walker never enforced.) One observability line `[turn-recorder] envelope sessionId=<op> turnsCount=<n> userTurns=<n> assistantTurns=<n> toolCallTurns=<n>` precedes `spawn-request`. The envelope rides on the `/spawn` body as a trailing positional argv to `claude`, so the database-operator session's JSONL first `role=user` line is the JSON object verbatim. No separate `POST /:id/input` call, no bracketed-paste, no keystroke injection. The recorder-auto-archive subscriber stops the recorder PTY as soon as its JSONL contains an assistant message with `stop_reason === "end_turn"`. **Task 129** — every emit goes through `POST /api/admin/log-ingest` so the lines land in `server.log` keyed by the operator session id. The chain is `trigger` → `spawn-request` → `spawn-success` → `input-delivered` → `tool-call` × N → `tool-result` × N → `write-complete` → `auto-archive`; each gated-off path emits one `trigger-skipped reason=<role-not-admin|is-recorder|empty-stdin|missing-transcript|conversation-empty>` line. Failure modes — `spawn-failed`, `tool-surface-missing`, `input-failed`, `write-empty`, `auto-archive reason=stale-recorder` — each emit one named line; absence is itself a defect.
144
148
 
145
149
  ## Session identifiers (Task 135)
146
150
 
@@ -103,7 +103,7 @@ run_case "BYPASS: nested rows[0].archiveType=linkedin + top-level archiveType=wh
103
103
  2
104
104
 
105
105
  run_case "BYPASS: conversation.archiveType=linkedin + top-level archiveType=whatsapp-export → BLOCKED" \
106
- '{"hook_event_name":"PreToolUse","tool_name":"mcp__memory__memory-archive-write","tool_input":{"conversation":{"archiveType":"linkedin-connections","conversationId":"x"},"archiveType":"whatsapp-export","ownerNodeId":"x","accountId":"a","rows":[]}}' \
106
+ '{"hook_event_name":"PreToolUse","tool_name":"mcp__memory__memory-archive-write","tool_input":{"conversation":{"archiveType":"linkedin-connections","sessionId":"x"},"archiveType":"whatsapp-export","ownerNodeId":"x","accountId":"a","rows":[]}}' \
107
107
  2
108
108
 
109
109
  # Plugin-source-edit path block must read tool_input.file_path top-level,