@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
@@ -0,0 +1,361 @@
1
+ #!/usr/bin/env bash
2
+ # Task 440 — per-turn-graph-pass-gate Stop hook test suite.
3
+ #
4
+ # Mirrors session-end-retrospective.test.sh's listener-mock pattern. Local
5
+ # Python HTTP server stands in for /api/admin/log-ingest and records every
6
+ # POST so the assertions read every log line the hook emitted.
7
+ #
8
+ # Contract under test:
9
+ # - Role/specialist gates: exit 0, single trigger-skipped log line, no
10
+ # stderr.
11
+ # role-not-admin | is-specialist | empty-stdin | missing-transcript
12
+ # - No real-user record in transcript (e.g. SessionStart bootstrap, or
13
+ # only tool_result-shaped user records): exit 0, single
14
+ # `trigger-skipped reason=no-real-user` line, no stderr.
15
+ # - Block path — admin's turn since the latest real-user message contains
16
+ # no `Task(database-operator)` dispatch and no `pre-turn-graph-pass-skip`
17
+ # tool_use: exit 2, stderr carries the instruction block,
18
+ # `gate-blocked sessionId=<id> reason=sentinel-absent` emitted.
19
+ # - Release via dispatch — a `Task` tool_use with
20
+ # `input.subagent_type=database-operator` appears AFTER the latest
21
+ # real-user message: exit 0, `gate-released sessionId=<id> via=dispatch`.
22
+ # - Release via skip-sentinel — a `tool_use` named
23
+ # `mcp__admin__pre-turn-graph-pass-skip` appears AFTER the latest
24
+ # real-user message: exit 0,
25
+ # `gate-released sessionId=<id> via=skip-sentinel`.
26
+ # - Per-prompt scoping — a dispatch BEFORE the latest real-user message
27
+ # does NOT release the gate.
28
+ # - Re-entry — a second Stop fired after the release tool_use still
29
+ # releases (the JSONL grep is the re-entry guard, no loop).
30
+
31
+ set -u
32
+
33
+ HOOK="$(cd "$(dirname "$0")/.." && pwd)/per-turn-graph-pass-gate.sh"
34
+ if [[ ! -x "$HOOK" ]]; then
35
+ echo "FAIL: $HOOK not executable" >&2
36
+ exit 1
37
+ fi
38
+
39
+ OP_ID='aaaaaaaa-1111-2222-3333-bbbbbbbbbbbb'
40
+
41
+ TMPFILES=()
42
+ LISTENER_PIDS=()
43
+ cleanup_test_state() {
44
+ for pid in "${LISTENER_PIDS[@]:-}"; do
45
+ if [[ -n "$pid" ]]; then
46
+ kill "$pid" 2>/dev/null || true
47
+ wait "$pid" 2>/dev/null || true
48
+ fi
49
+ done
50
+ for f in "${TMPFILES[@]:-}"; do
51
+ [[ -n "$f" ]] && rm -f "$f" 2>/dev/null || true
52
+ done
53
+ }
54
+ trap cleanup_test_state EXIT
55
+
56
+ PASS=0
57
+ FAIL=0
58
+ pass() { echo "PASS: $1"; PASS=$((PASS + 1)); }
59
+ fail() { echo "FAIL: $1" >&2; FAIL=$((FAIL + 1)); }
60
+
61
+ start_listener() {
62
+ REQ_LOG=$(mktemp); TMPFILES+=("$REQ_LOG")
63
+ LISTENER_PORT=$((39800 + RANDOM % 100))
64
+ python3 - "$LISTENER_PORT" "$REQ_LOG" <<'PY' &
65
+ import sys, http.server, json
66
+ port = int(sys.argv[1])
67
+ log_path = sys.argv[2]
68
+ class H(http.server.BaseHTTPRequestHandler):
69
+ def log_message(self, *a, **k): pass
70
+ def do_POST(self):
71
+ n = int(self.headers.get('Content-Length','0') or 0)
72
+ body = self.rfile.read(n).decode('utf-8','replace')
73
+ with open(log_path, 'a', encoding='utf-8') as f:
74
+ f.write(self.path + '\t' + body + '\n')
75
+ self.send_response(200)
76
+ self.send_header('Content-Type','application/json')
77
+ self.end_headers()
78
+ self.wfile.write(json.dumps({"ok": True}).encode('utf-8'))
79
+ http.server.HTTPServer(('127.0.0.1', port), H).serve_forever()
80
+ PY
81
+ LISTENER_PIDS+=("$!")
82
+ for _ in $(seq 1 20); do
83
+ if curl -sS --max-time 1 -X POST "http://127.0.0.1:${LISTENER_PORT}/ping" -d '{}' >/dev/null 2>&1; then
84
+ break
85
+ fi
86
+ sleep 0.1
87
+ done
88
+ : > "$REQ_LOG"
89
+ }
90
+
91
+ run_hook() {
92
+ local role="$1"; local specialist="$2"; local stdin_json="$3"
93
+ local stderr_file; stderr_file=$(mktemp); TMPFILES+=("$stderr_file")
94
+ local stdout_file; stdout_file=$(mktemp); TMPFILES+=("$stdout_file")
95
+ printf '%s' "$stdin_json" | \
96
+ MAXY_SESSION_ROLE="$role" \
97
+ MAXY_SPECIALIST="$specialist" \
98
+ MAXY_UI_INTERNAL_PORT="$LISTENER_PORT" \
99
+ bash "$HOOK" >"$stdout_file" 2>"$stderr_file"
100
+ HOOK_RC=$?
101
+ HOOK_STDERR=$(cat "$stderr_file")
102
+ HOOK_STDOUT=$(cat "$stdout_file")
103
+ sleep 0.1
104
+ }
105
+
106
+ ingest_lines() {
107
+ grep -E '^/api/admin/log-ingest ' "$REQ_LOG" 2>/dev/null | python3 -c '
108
+ import sys, json
109
+ for raw in sys.stdin:
110
+ try:
111
+ _, body = raw.rstrip("\n").split("\t", 1)
112
+ d = json.loads(body)
113
+ if isinstance(d, dict) and isinstance(d.get("line"), str):
114
+ print(d["line"])
115
+ except Exception:
116
+ pass
117
+ ' || true
118
+ }
119
+
120
+ # write_transcript: builds JSONL from positional specs.
121
+ # Spec format: <role>|<text>|<extra>
122
+ # extra "" — plain text record
123
+ # extra "tool_result" — user record carrying only a tool_result block
124
+ # extra "tool_use:<NAME>" — assistant record with a tool_use block (no input)
125
+ # extra "task:<subagent_type>" — assistant record with a Task tool_use whose
126
+ # input.subagent_type equals <subagent_type>
127
+ write_transcript() {
128
+ local out="$1"; shift
129
+ python3 - "$out" "$@" <<'PY'
130
+ import sys, json
131
+ out = sys.argv[1]
132
+ spec = sys.argv[2:]
133
+ with open(out, "w", encoding="utf-8") as f:
134
+ for entry in spec:
135
+ role, text, extra = entry.split("|", 2)
136
+ rec = {"type": role, "timestamp": "2026-05-26T10:00:00.000Z"}
137
+ if role == "user":
138
+ if extra == "tool_result":
139
+ rec["message"] = {
140
+ "role": "user",
141
+ "content": [
142
+ {"type": "tool_result", "tool_use_id": "tu_x", "content": text or "ok"},
143
+ ],
144
+ }
145
+ else:
146
+ rec["message"] = {"role": "user", "content": text}
147
+ else:
148
+ content_blocks = []
149
+ if text:
150
+ content_blocks.append({"type": "text", "text": text})
151
+ if extra.startswith("tool_use:"):
152
+ tool_name = extra.split(":", 1)[1]
153
+ content_blocks.append({
154
+ "type": "tool_use",
155
+ "id": f"toolu_{tool_name}",
156
+ "name": tool_name,
157
+ "input": {},
158
+ })
159
+ elif extra.startswith("task:"):
160
+ subagent = extra.split(":", 1)[1]
161
+ content_blocks.append({
162
+ "type": "tool_use",
163
+ "id": f"toolu_task_{subagent}",
164
+ "name": "Task",
165
+ "input": {"subagent_type": subagent, "description": "test", "prompt": "test"},
166
+ })
167
+ rec["message"] = {
168
+ "id": f"msg_{role}_{hash(text) & 0xffff:04x}",
169
+ "role": "assistant",
170
+ "content": content_blocks,
171
+ }
172
+ f.write(json.dumps(rec) + "\n")
173
+ PY
174
+ }
175
+
176
+ envelope_for() {
177
+ python3 -c '
178
+ import json, sys
179
+ print(json.dumps({"session_id": sys.argv[1], "transcript_path": sys.argv[2]}))
180
+ ' "$1" "$2"
181
+ }
182
+
183
+ INSTRUCTION_TOKEN='Before this turn closes, do the per-turn graph pass'
184
+
185
+ # ---------------------------------------------------------------------------
186
+ # Case 1: role != admin → trigger-skipped reason=role-not-admin
187
+ # ---------------------------------------------------------------------------
188
+ start_listener
189
+ TR_BASIC=$(mktemp); TMPFILES+=("$TR_BASIC")
190
+ write_transcript "$TR_BASIC" "user|hello|" "assistant|hi|"
191
+ ENV_BASIC=$(envelope_for "$OP_ID" "$TR_BASIC")
192
+ : > "$REQ_LOG"
193
+ run_hook "public" "" "$ENV_BASIC"
194
+ [[ "$HOOK_RC" -eq 0 ]] || fail "case-1 rc=$HOOK_RC"
195
+ [[ -z "$HOOK_STDERR" ]] || fail "case-1 stderr must be empty"
196
+ if ingest_lines | grep -qE "^trigger-skipped sessionId=${OP_ID} reason=role-not-admin$"; then
197
+ pass "case-1 role=public → trigger-skipped reason=role-not-admin"
198
+ else
199
+ fail "case-1 expected role-not-admin, got: $(ingest_lines)"
200
+ fi
201
+
202
+ # ---------------------------------------------------------------------------
203
+ # Case 2: MAXY_SPECIALIST set → trigger-skipped reason=is-specialist
204
+ # ---------------------------------------------------------------------------
205
+ : > "$REQ_LOG"
206
+ run_hook "admin" "database-operator" "$ENV_BASIC"
207
+ [[ "$HOOK_RC" -eq 0 ]] || fail "case-2 rc=$HOOK_RC"
208
+ [[ -z "$HOOK_STDERR" ]] || fail "case-2 stderr must be empty"
209
+ if ingest_lines | grep -qE "^trigger-skipped sessionId=${OP_ID} reason=is-specialist specialist=database-operator$"; then
210
+ pass "case-2 specialist=database-operator → trigger-skipped is-specialist"
211
+ else
212
+ fail "case-2 expected is-specialist, got: $(ingest_lines)"
213
+ fi
214
+
215
+ # ---------------------------------------------------------------------------
216
+ # Case 3: empty stdin → trigger-skipped reason=empty-stdin
217
+ # ---------------------------------------------------------------------------
218
+ : > "$REQ_LOG"
219
+ run_hook "admin" "" ""
220
+ [[ "$HOOK_RC" -eq 0 ]] || fail "case-3 rc=$HOOK_RC"
221
+ if ingest_lines | grep -qE "^trigger-skipped sessionId=.* reason=empty-stdin$"; then
222
+ pass "case-3 empty stdin → trigger-skipped reason=empty-stdin"
223
+ else
224
+ fail "case-3 expected empty-stdin, got: $(ingest_lines)"
225
+ fi
226
+
227
+ # ---------------------------------------------------------------------------
228
+ # Case 4: missing transcript_path → trigger-skipped reason=missing-transcript
229
+ # ---------------------------------------------------------------------------
230
+ BAD_ENV=$(python3 -c 'import json,sys; print(json.dumps({"session_id": sys.argv[1]}))' "$OP_ID")
231
+ : > "$REQ_LOG"
232
+ run_hook "admin" "" "$BAD_ENV"
233
+ [[ "$HOOK_RC" -eq 0 ]] || fail "case-4 rc=$HOOK_RC"
234
+ if ingest_lines | grep -qE "^trigger-skipped sessionId=${OP_ID} reason=missing-transcript$"; then
235
+ pass "case-4 missing transcript → trigger-skipped reason=missing-transcript"
236
+ else
237
+ fail "case-4 expected missing-transcript, got: $(ingest_lines)"
238
+ fi
239
+
240
+ # ---------------------------------------------------------------------------
241
+ # Case 5: no real-user record in transcript → trigger-skipped no-real-user
242
+ # ---------------------------------------------------------------------------
243
+ TR_NO_USER=$(mktemp); TMPFILES+=("$TR_NO_USER")
244
+ # Only a tool_result-shaped user record + an assistant record. The hook should
245
+ # treat this as "no real user yet" and trigger-skip.
246
+ write_transcript "$TR_NO_USER" "user|ok|tool_result" "assistant|booting|"
247
+ ENV_NO_USER=$(envelope_for "$OP_ID" "$TR_NO_USER")
248
+ : > "$REQ_LOG"
249
+ run_hook "admin" "" "$ENV_NO_USER"
250
+ [[ "$HOOK_RC" -eq 0 ]] || fail "case-5 rc=$HOOK_RC"
251
+ [[ -z "$HOOK_STDERR" ]] || fail "case-5 stderr must be empty"
252
+ if ingest_lines | grep -qE "^trigger-skipped sessionId=${OP_ID} reason=no-real-user$"; then
253
+ pass "case-5 only tool_result-user records → trigger-skipped no-real-user"
254
+ else
255
+ fail "case-5 expected no-real-user, got: $(ingest_lines)"
256
+ fi
257
+
258
+ # ---------------------------------------------------------------------------
259
+ # Case 6: gate-blocked — admin replied to operator without dispatching or
260
+ # calling the skip sentinel.
261
+ # ---------------------------------------------------------------------------
262
+ TR_BLOCKED=$(mktemp); TMPFILES+=("$TR_BLOCKED")
263
+ write_transcript "$TR_BLOCKED" "user|hello|" "assistant|hi there|"
264
+ ENV_BLOCKED=$(envelope_for "$OP_ID" "$TR_BLOCKED")
265
+ : > "$REQ_LOG"
266
+ run_hook "admin" "" "$ENV_BLOCKED"
267
+ [[ "$HOOK_RC" -eq 2 ]] || fail "case-6 expected rc=2, got $HOOK_RC"
268
+ if ! printf '%s' "$HOOK_STDERR" | grep -qF "$INSTRUCTION_TOKEN"; then
269
+ fail "case-6 stderr must contain instruction token; got: $HOOK_STDERR"
270
+ fi
271
+ if ingest_lines | grep -qE "^gate-blocked sessionId=${OP_ID} reason=sentinel-absent$"; then
272
+ pass "case-6 admin replied without dispatch/skip → gate-blocked + stderr instruction + rc=2"
273
+ else
274
+ fail "case-6 expected gate-blocked, got: $(ingest_lines)"
275
+ fi
276
+
277
+ # ---------------------------------------------------------------------------
278
+ # Case 7: release via dispatch — admin issued Task(database-operator) AFTER
279
+ # the latest real-user message.
280
+ # ---------------------------------------------------------------------------
281
+ TR_DISPATCH=$(mktemp); TMPFILES+=("$TR_DISPATCH")
282
+ write_transcript "$TR_DISPATCH" \
283
+ "user|tell me about Alice|" \
284
+ "assistant|dispatching|task:database-operator" \
285
+ "assistant|done|"
286
+ ENV_DISPATCH=$(envelope_for "$OP_ID" "$TR_DISPATCH")
287
+ : > "$REQ_LOG"
288
+ run_hook "admin" "" "$ENV_DISPATCH"
289
+ [[ "$HOOK_RC" -eq 0 ]] || fail "case-7 expected rc=0, got $HOOK_RC"
290
+ [[ -z "$HOOK_STDERR" ]] || fail "case-7 stderr must be empty on release"
291
+ if ingest_lines | grep -qE "^gate-released sessionId=${OP_ID} via=dispatch$"; then
292
+ pass "case-7 Task(database-operator) after latest user → gate-released via=dispatch"
293
+ else
294
+ fail "case-7 expected gate-released via=dispatch, got: $(ingest_lines)"
295
+ fi
296
+
297
+ # ---------------------------------------------------------------------------
298
+ # Case 8: release via skip-sentinel — admin called the skip MCP tool AFTER
299
+ # the latest real-user message.
300
+ # ---------------------------------------------------------------------------
301
+ TR_SKIP=$(mktemp); TMPFILES+=("$TR_SKIP")
302
+ write_transcript "$TR_SKIP" \
303
+ "user|thanks|" \
304
+ "assistant|noted|tool_use:mcp__admin__pre-turn-graph-pass-skip" \
305
+ "assistant|you're welcome|"
306
+ ENV_SKIP=$(envelope_for "$OP_ID" "$TR_SKIP")
307
+ : > "$REQ_LOG"
308
+ run_hook "admin" "" "$ENV_SKIP"
309
+ [[ "$HOOK_RC" -eq 0 ]] || fail "case-8 expected rc=0, got $HOOK_RC"
310
+ [[ -z "$HOOK_STDERR" ]] || fail "case-8 stderr must be empty on release"
311
+ if ingest_lines | grep -qE "^gate-released sessionId=${OP_ID} via=skip-sentinel$"; then
312
+ pass "case-8 skip-sentinel after latest user → gate-released via=skip-sentinel"
313
+ else
314
+ fail "case-8 expected gate-released via=skip-sentinel, got: $(ingest_lines)"
315
+ fi
316
+
317
+ # ---------------------------------------------------------------------------
318
+ # Case 9: per-prompt scoping — a dispatch BEFORE the latest real-user
319
+ # message does NOT release the current turn's gate.
320
+ # ---------------------------------------------------------------------------
321
+ TR_PRIOR=$(mktemp); TMPFILES+=("$TR_PRIOR")
322
+ write_transcript "$TR_PRIOR" \
323
+ "user|first turn|" \
324
+ "assistant|dispatching|task:database-operator" \
325
+ "assistant|done|" \
326
+ "user|second turn|" \
327
+ "assistant|hello again|"
328
+ ENV_PRIOR=$(envelope_for "$OP_ID" "$TR_PRIOR")
329
+ : > "$REQ_LOG"
330
+ run_hook "admin" "" "$ENV_PRIOR"
331
+ [[ "$HOOK_RC" -eq 2 ]] || fail "case-9 expected rc=2, got $HOOK_RC"
332
+ if ingest_lines | grep -qE "^gate-blocked sessionId=${OP_ID} reason=sentinel-absent$"; then
333
+ pass "case-9 dispatch before latest user does NOT release current turn → gate-blocked"
334
+ else
335
+ fail "case-9 expected gate-blocked, got: $(ingest_lines)"
336
+ fi
337
+
338
+ # ---------------------------------------------------------------------------
339
+ # Case 10: re-entry — a release tool_use earlier in the same prompt window
340
+ # stays released on a second Stop fire (no loop).
341
+ # ---------------------------------------------------------------------------
342
+ TR_REENTRY=$(mktemp); TMPFILES+=("$TR_REENTRY")
343
+ write_transcript "$TR_REENTRY" \
344
+ "user|hi|" \
345
+ "assistant|dispatching|task:database-operator" \
346
+ "assistant|done|" \
347
+ "assistant|wrap-up reply|"
348
+ ENV_REENTRY=$(envelope_for "$OP_ID" "$TR_REENTRY")
349
+ : > "$REQ_LOG"
350
+ run_hook "admin" "" "$ENV_REENTRY"
351
+ [[ "$HOOK_RC" -eq 0 ]] || fail "case-10 expected rc=0, got $HOOK_RC"
352
+ if ingest_lines | grep -qE "^gate-released sessionId=${OP_ID} via=dispatch$"; then
353
+ pass "case-10 second Stop after dispatch still releases (no loop)"
354
+ else
355
+ fail "case-10 expected gate-released via=dispatch, got: $(ingest_lines)"
356
+ fi
357
+
358
+ # ---------------------------------------------------------------------------
359
+ echo
360
+ echo "per-turn-graph-pass-gate tests: $PASS passed, $FAIL failed"
361
+ [[ "$FAIL" -eq 0 ]]
@@ -26,13 +26,13 @@
26
26
  # "additionalContext":"..."}}` whose additionalContext begins with
27
27
  # `[system: pre-turn-graph-pass-hook]`, names `database-operator` as
28
28
  # the dispatch target, carries a `<prior-writes>` block with the
29
- # fetched node, interpolates conversationId from CONVERSATION_NODE_ID,
29
+ # fetched node, interpolates sessionId from SESSION_NODE_ID,
30
30
  # and carries NO `<conversation>` block (admin has the turn already).
31
31
  # Dispatch log line carries `directive-shape=admin-walks`.
32
32
  # - Prior-writes fetch fails (context endpoint 500): exit 0, dispatch
33
33
  # still fires, `<prior-writes>` block resolves to `(none)`.
34
- # - CONVERSATION_NODE_ID unset: exit 0, additionalContext names
35
- # `conversationId: <unset>`, and no GET to /api/admin/post-turn-context
34
+ # - SESSION_NODE_ID unset: exit 0, additionalContext names
35
+ # `sessionId: <unset>`, and no GET to /api/admin/post-turn-context
36
36
  # is attempted.
37
37
  # - UserPromptSubmit stdin-shape regression: a synthetic UserPromptSubmit
38
38
  # payload produces the documented stdout envelope; a stale Stop-shaped
@@ -125,7 +125,7 @@ PY
125
125
  }
126
126
 
127
127
  run_hook() {
128
- # Args: role, specialist, ui_port, conversation_node_id, stdin_json
128
+ # Args: role, specialist, ui_port, session_node_id, stdin_json
129
129
  local role="$1"; local specialist="$2"; local ui_port="$3"
130
130
  local conv="$4"; local stdin_json="$5"
131
131
  local stderr_file; stderr_file=$(mktemp); TMPFILES+=("$stderr_file")
@@ -137,7 +137,7 @@ run_hook() {
137
137
  env_cmd+=("MAXY_UI_INTERNAL_PORT=${ui_port}")
138
138
  fi
139
139
  if [[ -n "$conv" ]]; then
140
- env_cmd+=("CONVERSATION_NODE_ID=${conv}")
140
+ env_cmd+=("SESSION_NODE_ID=${conv}")
141
141
  fi
142
142
  env_cmd+=("ACCOUNT_ID=acct-test-0001")
143
143
  printf '%s' "$stdin_json" | "${env_cmd[@]}" bash "$HOOK" >"$stdout_file" 2>"$stderr_file"
@@ -328,14 +328,14 @@ fi
328
328
  if ! printf '%s' "$CTX_BODY" | grep -q 'database-operator'; then
329
329
  fail "case-5 additionalContext must name the database-operator dispatch target"
330
330
  fi
331
- if ! printf '%s' "$CTX_BODY" | grep -q "conversationId: ${CONV_ID}"; then
332
- fail "case-5 additionalContext must interpolate conversationId=${CONV_ID}"
331
+ if ! printf '%s' "$CTX_BODY" | grep -q "sessionId: ${CONV_ID}"; then
332
+ fail "case-5 additionalContext must interpolate sessionId=${CONV_ID}"
333
333
  fi
334
334
  if ! printf '%s' "$CTX_BODY" | grep -q 'KnowledgeDocument'; then
335
335
  fail "case-5 additionalContext <prior-writes> must include fetched labels"
336
336
  fi
337
- if ingest_lines | grep -qE "^dispatch sessionId=${OP_ID} conversationId=${CONV_ID} directive-shape=admin-walks "; then
338
- pass "case-5 dispatch path → exit 0 + JSON envelope with prior-writes, conversationId, admin-walks shape"
337
+ if ingest_lines | grep -qE "^dispatch claudeSessionId=${OP_ID} sessionId=${CONV_ID} directive-shape=admin-walks "; then
338
+ pass "case-5 dispatch path → exit 0 + JSON envelope with prior-writes, sessionId, admin-walks shape"
339
339
  else
340
340
  fail "case-5 expected dispatch log line with directive-shape=admin-walks, got: $(ingest_lines)"
341
341
  fi
@@ -356,7 +356,7 @@ else
356
356
  fi
357
357
 
358
358
  # ---------------------------------------------------------------------------
359
- # Case 7: CONVERSATION_NODE_ID unset → conversationId:<unset>, no context GET.
359
+ # Case 7: SESSION_NODE_ID unset → sessionId:<unset>, no context GET.
360
360
  # ---------------------------------------------------------------------------
361
361
  cat > "$CTX_FILE" <<'JSON'
362
362
  {"writes":[]}
@@ -365,12 +365,12 @@ JSON
365
365
  run_hook "admin" "" "$LISTENER_PORT" "" "$ENV_BASIC"
366
366
  [[ "$HOOK_RC" -eq 0 ]] || fail "case-7 expected rc=0, got $HOOK_RC"
367
367
  CTX_BODY=$(additional_context)
368
- if ! printf '%s' "$CTX_BODY" | grep -q 'conversationId: <unset>'; then
369
- fail "case-7 additionalContext must contain 'conversationId: <unset>'"
368
+ if ! printf '%s' "$CTX_BODY" | grep -q 'sessionId: <unset>'; then
369
+ fail "case-7 additionalContext must contain 'sessionId: <unset>'"
370
370
  fi
371
371
  GET_COUNT=$(context_get_count)
372
372
  if [[ "$GET_COUNT" == "0" ]]; then
373
- pass "case-7 CONVERSATION_NODE_ID unset → no GET /api/admin/post-turn-context attempted"
373
+ pass "case-7 SESSION_NODE_ID unset → no GET /api/admin/post-turn-context attempted"
374
374
  else
375
375
  fail "case-7 expected zero context GETs, got: $GET_COUNT"
376
376
  fi
@@ -194,7 +194,7 @@ fi
194
194
  # --- Case 5 (Task 177): ordered-turns happy path -----------------------
195
195
  # Transcript with four turns: user-A, asst-A-reply, user-B, asst-B-reply.
196
196
  # Envelope `turns` array must carry exactly that order, oldest first.
197
- # Envelope shape: { turns, conversationId, accountId, occurredAt } — no
197
+ # Envelope shape: { turns, sessionId, accountId, occurredAt } — no
198
198
  # top-level operatorMessage / assistantReply.
199
199
  ORDERED_TRANSCRIPT=$(mktemp); TMPFILES+=("$ORDERED_TRANSCRIPT")
200
200
  {
@@ -154,7 +154,7 @@ fi
154
154
  case "$TOOL_NAME" in
155
155
  mcp__memory__whatsapp-export-parse|mcp__memory__whatsapp-export-insight-write|mcp__memory__whatsapp-export-insight-pass|mcp__memory__whatsapp-export-preview)
156
156
  emit_decision "block" "denied-mcp-legacy" \
157
- "Blocked: ${TOOL_NAME} is a retired path. generalised conversation-archive ingestinvoke 'bash platform/plugins/memory/bin/conversation-archive-ingest.sh <archive> --source whatsapp --owner-element-id <id> --participant-person-ids <csv> --scope <admin|public>' once. Normalise, sessionize, classify (mode=chat), and memory-ingest (writes :ConversationArchive keyed on conversationIdentity, source=<enum>) all run in-process."
157
+ "Blocked: ${TOOL_NAME} is a retired path. Invoke the generalised conversation-archive skill — 'bash platform/plugins/memory/bin/conversation-archive-ingest.sh <archive> --source whatsapp --participant-person-ids <csv> --scope <admin|public>' (owner derived from ACCOUNT_ID + USER_ID env). The script normalises, sessionizes, and emits prepared sessions; the dispatched specialist classifies each session in-turn and calls memory-ingest with conversationIdentity set (writes :ConversationArchive)."
158
158
  ;;
159
159
  esac
160
160
 
@@ -186,7 +186,7 @@ if [ "$TOOL_NAME" = "mcp__memory__memory-archive-write" ]; then
186
186
  ARCHIVE_TYPE=$(extract_tool_input_field archiveType)
187
187
  if [ "$ARCHIVE_TYPE" = "whatsapp-export" ]; then
188
188
  emit_decision "block" "denied-mcp-legacy archiveType=whatsapp-export" \
189
- "Blocked: memory-archive-write with archiveType='whatsapp-export' is a retired path. routes conversation transcripts through 'bash platform/plugins/memory/bin/conversation-archive-ingest.sh <archive> --source whatsapp --owner-element-id <id> --participant-person-ids <csv> --scope <admin|public>'. Flat-dataset archiveTypes (linkedin-connections, …) flow through memory-archive-write unchanged."
189
+ "Blocked: memory-archive-write with archiveType='whatsapp-export' is a retired path. Routes conversation transcripts through 'bash platform/plugins/memory/bin/conversation-archive-ingest.sh <archive> --source whatsapp --participant-person-ids <csv> --scope <admin|public>' (owner derived from ACCOUNT_ID + USER_ID env). Flat-dataset archiveTypes (linkedin-connections, …) flow through memory-archive-write unchanged."
190
190
  fi
191
191
  fi
192
192
 
@@ -138,3 +138,105 @@ agp_guard_transcript() {
138
138
  exit 0
139
139
  fi
140
140
  }
141
+
142
+ # Walks $TRANSCRIPT_PATH and reports, in one line on stdout:
143
+ # <real-user-present:yes|no>\t<matched-tool-name-or-empty>
144
+ # A "real user" record matches `session-end-retrospective.sh`'s `is_real_user`
145
+ # — `type=user, message.role=user`, content is a string OR a list with at
146
+ # least one non-`tool_result` block. `tool_result`-only user records are tool
147
+ # replies, never turn starts.
148
+ #
149
+ # Every assistant `tool_use` block that appears AFTER the latest real-user
150
+ # record is matched against the alternation passed as `$1` (an extended-regex
151
+ # alternation of literal `tool_use.name` values). The synthetic name
152
+ # `Task:<subagent_type>` is also matched, so callers can release on a
153
+ # `Task` tool_use with `input.subagent_type=<name>` by including
154
+ # `Task:<name>` in the alternation. Returns the first match encountered after
155
+ # the latest real-user record (oldest-first) so the release log carries the
156
+ # matched tool's actual name. Empty match means none of the release patterns
157
+ # appeared since the operator's last turn.
158
+ agp_scan_post_user_toolnames() {
159
+ local pattern="$1"
160
+ TRANSCRIPT_PATH="$TRANSCRIPT_PATH" AGP_PATTERN="$pattern" python3 - <<'PY'
161
+ import os, json, re
162
+
163
+ pattern = re.compile(os.environ["AGP_PATTERN"])
164
+ path = os.environ["TRANSCRIPT_PATH"]
165
+
166
+ def is_real_user(rec):
167
+ if not isinstance(rec, dict) or rec.get("type") != "user":
168
+ return False
169
+ msg = rec.get("message")
170
+ if not isinstance(msg, dict) or msg.get("role") != "user":
171
+ return False
172
+ content = msg.get("content")
173
+ if isinstance(content, str):
174
+ return True
175
+ if isinstance(content, list):
176
+ for b in content:
177
+ if isinstance(b, dict) and b.get("type") != "tool_result":
178
+ return True
179
+ return False
180
+ return True
181
+
182
+ def assistant_tool_use_names(rec):
183
+ if not isinstance(rec, dict) or rec.get("type") != "assistant":
184
+ return []
185
+ msg = rec.get("message", {}) or {}
186
+ if msg.get("role") != "assistant":
187
+ return []
188
+ content = msg.get("content")
189
+ if not isinstance(content, list):
190
+ return []
191
+ names = []
192
+ for b in content:
193
+ if isinstance(b, dict) and b.get("type") == "tool_use":
194
+ n = b.get("name")
195
+ if not isinstance(n, str):
196
+ continue
197
+ names.append(n)
198
+ if n == "Task":
199
+ inp = b.get("input")
200
+ if isinstance(inp, dict):
201
+ st = inp.get("subagent_type")
202
+ if isinstance(st, str) and st:
203
+ names.append(f"Task:{st}")
204
+ return names
205
+
206
+ records = []
207
+ try:
208
+ with open(path, "r", encoding="utf-8") as f:
209
+ for raw in f:
210
+ raw = raw.strip()
211
+ if not raw:
212
+ continue
213
+ try:
214
+ records.append(json.loads(raw))
215
+ except Exception:
216
+ continue
217
+ except Exception:
218
+ print("no\t")
219
+ raise SystemExit(0)
220
+
221
+ latest_user_idx = -1
222
+ for i in range(len(records) - 1, -1, -1):
223
+ if is_real_user(records[i]):
224
+ latest_user_idx = i
225
+ break
226
+
227
+ if latest_user_idx == -1:
228
+ print("no\t")
229
+ raise SystemExit(0)
230
+
231
+ matched = ""
232
+ for r in records[latest_user_idx + 1:]:
233
+ for n in assistant_tool_use_names(r):
234
+ if pattern.fullmatch(n):
235
+ matched = n
236
+ break
237
+ if matched:
238
+ break
239
+
240
+ print(f"yes\t{matched}")
241
+ PY
242
+ }