@rubytech/create-maxy-code 0.1.158 → 0.1.159

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (233) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/lib/admin-conversation-purge/dist/index.d.ts +1 -1
  3. package/payload/platform/lib/admin-conversation-purge/dist/index.d.ts.map +1 -1
  4. package/payload/platform/lib/admin-conversation-purge/dist/index.js +4 -4
  5. package/payload/platform/lib/admin-conversation-purge/dist/index.js.map +1 -1
  6. package/payload/platform/lib/admin-conversation-purge/src/index.ts +5 -5
  7. package/payload/platform/lib/graph-style/dist/index.js +2 -2
  8. package/payload/platform/lib/graph-style/dist/index.js.map +1 -1
  9. package/payload/platform/lib/graph-style/src/__tests__/parity.test.ts +1 -1
  10. package/payload/platform/lib/graph-style/src/index.ts +2 -2
  11. package/payload/platform/lib/graph-trash/dist/index.js +1 -1
  12. package/payload/platform/lib/graph-trash/dist/index.js.map +1 -1
  13. package/payload/platform/lib/graph-trash/src/index.ts +1 -1
  14. package/payload/platform/lib/graph-write/dist/__tests__/action-provenance-gate.test.js +1 -1
  15. package/payload/platform/lib/graph-write/dist/__tests__/action-provenance-gate.test.js.map +1 -1
  16. package/payload/platform/lib/graph-write/dist/conversation-provenance.d.ts +3 -3
  17. package/payload/platform/lib/graph-write/dist/conversation-provenance.js +5 -5
  18. package/payload/platform/lib/graph-write/dist/conversation-provenance.js.map +1 -1
  19. package/payload/platform/lib/graph-write/dist/index.js +1 -1
  20. package/payload/platform/lib/graph-write/dist/index.js.map +1 -1
  21. package/payload/platform/lib/graph-write/src/__tests__/action-provenance-gate.test.ts +1 -1
  22. package/payload/platform/lib/graph-write/src/conversation-provenance.ts +8 -8
  23. package/payload/platform/lib/graph-write/src/index.ts +1 -1
  24. package/payload/platform/neo4j/schema.cypher +30 -13
  25. package/payload/platform/plugins/admin/.claude-plugin/plugin.json +1 -1
  26. package/payload/platform/plugins/admin/PLUGIN.md +8 -4
  27. package/payload/platform/plugins/admin/hooks/__tests__/archive-ingest-surface-gate.test.sh +1 -1
  28. package/payload/platform/plugins/admin/hooks/__tests__/per-turn-graph-pass-gate.test.sh +361 -0
  29. package/payload/platform/plugins/admin/hooks/__tests__/pre-turn-graph-pass.test.sh +13 -13
  30. package/payload/platform/plugins/admin/hooks/__tests__/turn-completed-graph-write.test.sh +1 -1
  31. package/payload/platform/plugins/admin/hooks/lib/admin-graph-pass-common.sh +102 -0
  32. package/payload/platform/plugins/admin/hooks/per-turn-graph-pass-gate.sh +106 -0
  33. package/payload/platform/plugins/admin/hooks/pre-turn-graph-pass.sh +15 -8
  34. package/payload/platform/plugins/admin/hooks/turn-completed-graph-write.sh +4 -4
  35. package/payload/platform/plugins/admin/mcp/dist/index.js +65 -24
  36. package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
  37. package/payload/platform/plugins/admin/skills/session-management/SKILL.md +2 -2
  38. package/payload/platform/plugins/admin/skills/stream-log-review/SKILL.md +5 -5
  39. package/payload/platform/plugins/admin/skills/stream-log-review/references/analysis-patterns.md +6 -6
  40. package/payload/platform/plugins/business-assistant/references/profiling.md +1 -1
  41. package/payload/platform/plugins/contacts/PLUGIN.md +1 -1
  42. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-create.js +2 -2
  43. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-create.js.map +1 -1
  44. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-erase.js +3 -3
  45. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-export.d.ts +1 -1
  46. package/payload/platform/plugins/contacts/mcp/dist/tools/contact-export.js +2 -2
  47. package/payload/platform/plugins/contacts/mcp/dist/tools/group-create.d.ts +1 -1
  48. package/payload/platform/plugins/contacts/mcp/dist/tools/group-create.d.ts.map +1 -1
  49. package/payload/platform/plugins/contacts/mcp/dist/tools/group-create.js +4 -4
  50. package/payload/platform/plugins/contacts/mcp/dist/tools/group-create.js.map +1 -1
  51. package/payload/platform/plugins/contacts/mcp/dist/tools/group-manage.js +10 -10
  52. package/payload/platform/plugins/contacts/mcp/dist/tools/group-manage.js.map +1 -1
  53. package/payload/platform/plugins/docs/references/admin-session.md +6 -6
  54. package/payload/platform/plugins/docs/references/admin-ui.md +1 -1
  55. package/payload/platform/plugins/docs/references/internals.md +5 -5
  56. package/payload/platform/plugins/docs/references/plugins-guide.md +3 -3
  57. package/payload/platform/plugins/docs/references/troubleshooting.md +1 -1
  58. package/payload/platform/plugins/email/.claude-plugin/plugin.json +1 -1
  59. package/payload/platform/plugins/email/PLUGIN.md +15 -2
  60. package/payload/platform/plugins/email/mcp/dist/index.js +53 -0
  61. package/payload/platform/plugins/email/mcp/dist/index.js.map +1 -1
  62. package/payload/platform/plugins/email/mcp/dist/lib/embedding.js +2 -2
  63. package/payload/platform/plugins/email/mcp/dist/lib/embedding.js.map +1 -1
  64. package/payload/platform/plugins/email/mcp/dist/lib/graph.js +1 -1
  65. package/payload/platform/plugins/email/mcp/dist/lib/graph.js.map +1 -1
  66. package/payload/platform/plugins/email/mcp/dist/lib/imap.d.ts +1 -1
  67. package/payload/platform/plugins/email/mcp/dist/lib/ingest-batch.d.ts +23 -0
  68. package/payload/platform/plugins/email/mcp/dist/lib/ingest-batch.d.ts.map +1 -0
  69. package/payload/platform/plugins/email/mcp/dist/lib/ingest-batch.js +15 -0
  70. package/payload/platform/plugins/email/mcp/dist/lib/ingest-batch.js.map +1 -0
  71. package/payload/platform/plugins/email/mcp/dist/tools/email-fetch.d.ts +15 -0
  72. package/payload/platform/plugins/email/mcp/dist/tools/email-fetch.d.ts.map +1 -0
  73. package/payload/platform/plugins/email/mcp/dist/tools/email-fetch.js +49 -0
  74. package/payload/platform/plugins/email/mcp/dist/tools/email-fetch.js.map +1 -0
  75. package/payload/platform/plugins/email/mcp/dist/tools/email-ingest.d.ts +20 -0
  76. package/payload/platform/plugins/email/mcp/dist/tools/email-ingest.d.ts.map +1 -0
  77. package/payload/platform/plugins/email/mcp/dist/tools/email-ingest.js +86 -0
  78. package/payload/platform/plugins/email/mcp/dist/tools/email-ingest.js.map +1 -0
  79. package/payload/platform/plugins/email/mcp/dist/tools/email-setup.d.ts.map +1 -1
  80. package/payload/platform/plugins/email/mcp/dist/tools/email-setup.js +32 -52
  81. package/payload/platform/plugins/email/mcp/dist/tools/email-setup.js.map +1 -1
  82. package/payload/platform/plugins/email/references/email-reference.md +19 -83
  83. package/payload/platform/plugins/email/skills/email-ingest/SKILL.md +87 -0
  84. package/payload/platform/plugins/memory/PLUGIN.md +1 -1
  85. package/payload/platform/plugins/memory/mcp/dist/index.js +29 -29
  86. package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
  87. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/x-dm.js +2 -2
  88. package/payload/platform/plugins/memory/mcp/dist/lib/conversation-normalisers/x-dm.js.map +1 -1
  89. package/payload/platform/plugins/memory/mcp/dist/lib/graph-prune.d.ts +3 -3
  90. package/payload/platform/plugins/memory/mcp/dist/lib/graph-prune.d.ts.map +1 -1
  91. package/payload/platform/plugins/memory/mcp/dist/lib/graph-prune.js +6 -6
  92. package/payload/platform/plugins/memory/mcp/dist/lib/graph-prune.js.map +1 -1
  93. package/payload/platform/plugins/memory/mcp/dist/lib/log-ingest.js +1 -1
  94. package/payload/platform/plugins/memory/mcp/dist/lib/log-ingest.js.map +1 -1
  95. package/payload/platform/plugins/memory/mcp/dist/lib/neo4j.d.ts +2 -2
  96. package/payload/platform/plugins/memory/mcp/dist/lib/neo4j.js +2 -2
  97. package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-pass.d.ts +1 -1
  98. package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-pass.d.ts.map +1 -1
  99. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-memory-expunge-emit.test.js +3 -3
  100. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-memory-expunge-emit.test.js.map +1 -1
  101. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/log-ingest.test.js +2 -2
  102. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/log-ingest.test.js.map +1 -1
  103. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-empty-trash-admin-conversation.test.js +8 -8
  104. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-empty-trash-admin-conversation.test.js.map +1 -1
  105. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-report-tools.test.js +2 -2
  106. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-report-tools.test.js.map +1 -1
  107. package/payload/platform/plugins/memory/mcp/dist/tools/conversation-memory-expunge.d.ts +1 -1
  108. package/payload/platform/plugins/memory/mcp/dist/tools/conversation-memory-expunge.d.ts.map +1 -1
  109. package/payload/platform/plugins/memory/mcp/dist/tools/conversation-memory-expunge.js +2 -2
  110. package/payload/platform/plugins/memory/mcp/dist/tools/conversation-memory-expunge.js.map +1 -1
  111. package/payload/platform/plugins/memory/mcp/dist/tools/memory-brain-capture-recent.d.ts +2 -2
  112. package/payload/platform/plugins/memory/mcp/dist/tools/memory-brain-capture-recent.d.ts.map +1 -1
  113. package/payload/platform/plugins/memory/mcp/dist/tools/memory-brain-capture-recent.js +4 -4
  114. package/payload/platform/plugins/memory/mcp/dist/tools/memory-brain-capture-recent.js.map +1 -1
  115. package/payload/platform/plugins/memory/mcp/dist/tools/memory-empty-trash.d.ts +1 -1
  116. package/payload/platform/plugins/memory/mcp/dist/tools/memory-empty-trash.js +8 -8
  117. package/payload/platform/plugins/memory/mcp/dist/tools/memory-empty-trash.js.map +1 -1
  118. package/payload/platform/plugins/memory/mcp/dist/tools/memory-find-candidates.d.ts +1 -1
  119. package/payload/platform/plugins/memory/mcp/dist/tools/memory-find-candidates.d.ts.map +1 -1
  120. package/payload/platform/plugins/memory/mcp/dist/tools/memory-find-candidates.js +2 -2
  121. package/payload/platform/plugins/memory/mcp/dist/tools/memory-find-candidates.js.map +1 -1
  122. package/payload/platform/plugins/memory/mcp/dist/tools/memory-report-write.d.ts +1 -1
  123. package/payload/platform/plugins/memory/mcp/dist/tools/memory-report-write.js +1 -1
  124. package/payload/platform/plugins/memory/mcp/dist/tools/memory-typed-edge-pass.d.ts +1 -1
  125. package/payload/platform/plugins/memory/mcp/dist/tools/memory-typed-edge-pass.d.ts.map +1 -1
  126. package/payload/platform/plugins/memory/mcp/dist/tools/memory-typed-edge-pass.js +2 -2
  127. package/payload/platform/plugins/memory/mcp/dist/tools/memory-typed-edge-pass.js.map +1 -1
  128. package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.js +2 -2
  129. package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.js.map +1 -1
  130. package/payload/platform/plugins/memory/mcp/dist/tools/profile-update.d.ts +1 -1
  131. package/payload/platform/plugins/memory/mcp/dist/tools/profile-update.d.ts.map +1 -1
  132. package/payload/platform/plugins/memory/mcp/dist/tools/profile-update.js +11 -11
  133. package/payload/platform/plugins/memory/mcp/dist/tools/profile-update.js.map +1 -1
  134. package/payload/platform/plugins/memory/mcp/scripts/backfill-typed-edges.ts +1 -1
  135. package/payload/platform/plugins/memory/mcp/scripts/graph/fixture.cypher +1 -1
  136. package/payload/platform/plugins/memory/references/graph-primitives.md +1 -1
  137. package/payload/platform/plugins/memory/references/schema-base.md +4 -4
  138. package/payload/platform/plugins/memory/skills/conversational-memory/SKILL.md +1 -1
  139. package/payload/platform/plugins/whatsapp/PLUGIN.md +1 -1
  140. package/payload/platform/plugins/whatsapp/mcp/dist/index.js +2 -2
  141. package/payload/platform/plugins/whatsapp/mcp/dist/index.js.map +1 -1
  142. package/payload/platform/plugins/work/mcp/dist/index.js +2 -2
  143. package/payload/platform/plugins/work/mcp/dist/index.js.map +1 -1
  144. package/payload/platform/plugins/work/mcp/dist/tools/project-create.js +6 -6
  145. package/payload/platform/plugins/work/mcp/dist/tools/project-create.js.map +1 -1
  146. package/payload/platform/plugins/work/mcp/dist/tools/session-list.d.ts +1 -1
  147. package/payload/platform/plugins/work/mcp/dist/tools/session-list.d.ts.map +1 -1
  148. package/payload/platform/plugins/work/mcp/dist/tools/session-list.js +1 -1
  149. package/payload/platform/plugins/work/mcp/dist/tools/session-list.js.map +1 -1
  150. package/payload/platform/plugins/x-import/references/archive-shape.md +2 -2
  151. package/payload/platform/plugins/x-import/skills/x-import/SKILL.md +3 -3
  152. package/payload/platform/scripts/admin-persist-audit.ts +18 -18
  153. package/payload/platform/scripts/identity-forbidden-token-check.mjs +2 -0
  154. package/payload/platform/scripts/seed-neo4j.sh +1 -0
  155. package/payload/platform/services/claude-session-manager/dist/http-server.js +3 -3
  156. package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
  157. package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts +3 -3
  158. package/payload/platform/services/claude-session-manager/dist/pty-spawner.js +4 -4
  159. package/payload/platform/services/claude-session-manager/dist/pty-spawner.js.map +1 -1
  160. package/payload/platform/services/claude-session-manager/dist/system-prompt.d.ts.map +1 -1
  161. package/payload/platform/services/claude-session-manager/dist/system-prompt.js +2 -0
  162. package/payload/platform/services/claude-session-manager/dist/system-prompt.js.map +1 -1
  163. package/payload/platform/templates/specialists/agents/personal-assistant.md +1 -1
  164. package/payload/server/{chunk-AXOL2PPG.js → chunk-3TRIXQSJ.js} +101 -101
  165. package/payload/server/maxy-edge.js +1 -1
  166. package/payload/server/public/assets/{admin-3fLFD5h_.js → admin-Dal5FWaD.js} +2 -2
  167. package/payload/server/public/assets/{architectureDiagram-Q4EWVU46-Breg9-99.js → architectureDiagram-Q4EWVU46-Do2zYONG.js} +1 -1
  168. package/payload/server/public/assets/{blockDiagram-DXYQGD6D-DXf1_673.js → blockDiagram-DXYQGD6D-DpIX_bRu.js} +1 -1
  169. package/payload/server/public/assets/{c4Diagram-AHTNJAMY-CSZ36W4-.js → c4Diagram-AHTNJAMY-Cz335ZSY.js} +1 -1
  170. package/payload/server/public/assets/channel-PC4_IjI1.js +1 -0
  171. package/payload/server/public/assets/{chunk-336JU56O-DsrLk2eK.js → chunk-336JU56O-Dmknn3Wo.js} +2 -2
  172. package/payload/server/public/assets/{chunk-426QAEUC-JpNfNf81.js → chunk-426QAEUC-ClfGjizN.js} +1 -1
  173. package/payload/server/public/assets/{chunk-4TB4RGXK-DmClEAD0.js → chunk-4TB4RGXK-BPKctJ5c.js} +1 -1
  174. package/payload/server/public/assets/{chunk-5FUZZQ4R-BI9blW3N.js → chunk-5FUZZQ4R-BWDCO9zw.js} +1 -1
  175. package/payload/server/public/assets/{chunk-5PVQY5BW-BbgttEFO.js → chunk-5PVQY5BW-BE34_Db0.js} +1 -1
  176. package/payload/server/public/assets/{chunk-EDXVE4YY-BX_LCFOx.js → chunk-EDXVE4YY-BysA-_6v.js} +1 -1
  177. package/payload/server/public/assets/{chunk-ENJZ2VHE-Bb7EoD0w.js → chunk-ENJZ2VHE-BMVyMsqA.js} +1 -1
  178. package/payload/server/public/assets/{chunk-ICPOFSXX-DH8uQk-s.js → chunk-ICPOFSXX-C5KRdLV4.js} +1 -1
  179. package/payload/server/public/assets/{chunk-OYMX7WX6-FH5kgXsw.js → chunk-OYMX7WX6-DVZD-AVc.js} +1 -1
  180. package/payload/server/public/assets/{chunk-U2HBQHQK-D_ljlkHr.js → chunk-U2HBQHQK-DYmQdx8x.js} +1 -1
  181. package/payload/server/public/assets/{chunk-X2U36JSP-BX3EmZvm.js → chunk-X2U36JSP-DrZenIl3.js} +1 -1
  182. package/payload/server/public/assets/{chunk-YZCP3GAM-Vu7-E93h.js → chunk-YZCP3GAM-CDuGbvMq.js} +1 -1
  183. package/payload/server/public/assets/{chunk-ZZ45TVLE-CwjhNPX5.js → chunk-ZZ45TVLE-COztbiu5.js} +1 -1
  184. package/payload/server/public/assets/classDiagram-6PBFFD2Q-B_pMa-SX.js +1 -0
  185. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-BdBAgF20.js +1 -0
  186. package/payload/server/public/assets/clone-CkNt9L9r.js +1 -0
  187. package/payload/server/public/assets/{dagre-Ce6gsj0C.js → dagre-Cv9Ib2OM.js} +1 -1
  188. package/payload/server/public/assets/{dagre-KV5264BT-BaMGpsoy.js → dagre-KV5264BT-CoEd61KZ.js} +1 -1
  189. package/payload/server/public/assets/{data-BHASh0_Y.js → data-DbSORCl4.js} +1 -1
  190. package/payload/server/public/assets/{diagram-5BDNPKRD-CHEE9rjq.js → diagram-5BDNPKRD-WXNzw3uW.js} +1 -1
  191. package/payload/server/public/assets/{diagram-G4DWMVQ6-C98sZLW1.js → diagram-G4DWMVQ6-C6IuQ2VV.js} +1 -1
  192. package/payload/server/public/assets/{diagram-MMDJMWI5-DNvMGsTZ.js → diagram-MMDJMWI5-CdJdir5A.js} +1 -1
  193. package/payload/server/public/assets/{diagram-TYMM5635-Cdte4IBa.js → diagram-TYMM5635-DxWKQH5T.js} +1 -1
  194. package/payload/server/public/assets/{erDiagram-SMLLAGMA-C9VZsWXK.js → erDiagram-SMLLAGMA-C9fvs33K.js} +1 -1
  195. package/payload/server/public/assets/{flowDiagram-DWJPFMVM-tuP5fzzR.js → flowDiagram-DWJPFMVM-BO7Yrbqv.js} +1 -1
  196. package/payload/server/public/assets/{ganttDiagram-T4ZO3ILL-SJgRPUwx.js → ganttDiagram-T4ZO3ILL-CQJyWBZq.js} +1 -1
  197. package/payload/server/public/assets/{gitGraphDiagram-UUTBAWPF-DU_cI_50.js → gitGraphDiagram-UUTBAWPF-DZfQHrYw.js} +1 -1
  198. package/payload/server/public/assets/{graph-labels-DXlmm1og.js → graph-labels-BBB5jsZk.js} +1 -1
  199. package/payload/server/public/assets/{graph-BhEI09tF.js → graph-ys_joP2o.js} +1 -1
  200. package/payload/server/public/assets/{graphlib-D_nAsvmx.js → graphlib-C40H-Q5E.js} +1 -1
  201. package/payload/server/public/assets/{infoDiagram-42DDH7IO-Cj2Y19m6.js → infoDiagram-42DDH7IO-CakfV5f9.js} +1 -1
  202. package/payload/server/public/assets/{ishikawaDiagram-UXIWVN3A-DMc1xq1y.js → ishikawaDiagram-UXIWVN3A-CPuBPyfa.js} +1 -1
  203. package/payload/server/public/assets/{journeyDiagram-VCZTEJTY-C4CRAQma.js → journeyDiagram-VCZTEJTY-zpZm2Mmo.js} +1 -1
  204. package/payload/server/public/assets/{kanban-definition-6JOO6SKY-CTr4AldU.js → kanban-definition-6JOO6SKY-DfJduQCo.js} +1 -1
  205. package/payload/server/public/assets/{line-Btlm_IAl.js → line-BpYQqO5R.js} +1 -1
  206. package/payload/server/public/assets/{mermaid-parser.core-DXFdj_y1.js → mermaid-parser.core-C5Mwi14D.js} +1 -1
  207. package/payload/server/public/assets/{mermaid.core-DFBhoCr5.js → mermaid.core-D8qBtvvT.js} +3 -3
  208. package/payload/server/public/assets/{mindmap-definition-QFDTVHPH-r9gVQybo.js → mindmap-definition-QFDTVHPH-Bli9JhIN.js} +1 -1
  209. package/payload/server/public/assets/{page-CDWu1Aft.js → page--bl5Y7ZI.js} +2 -2
  210. package/payload/server/public/assets/page-CwmZ76U7.js +1 -0
  211. package/payload/server/public/assets/{pieDiagram-DEJITSTG-CHKZjSaH.js → pieDiagram-DEJITSTG-MsLXTSLg.js} +1 -1
  212. package/payload/server/public/assets/{public-DyGWgfaZ.js → public-DltgEfA9.js} +2 -2
  213. package/payload/server/public/assets/{quadrantDiagram-34T5L4WZ-CSGR1HJr.js → quadrantDiagram-34T5L4WZ-De1sh2K0.js} +1 -1
  214. package/payload/server/public/assets/{requirementDiagram-MS252O5E-DZ6hX9D6.js → requirementDiagram-MS252O5E-D5Sfg1t_.js} +1 -1
  215. package/payload/server/public/assets/{sankeyDiagram-XADWPNL6-DbZBKh0m.js → sankeyDiagram-XADWPNL6-DHA3LIbv.js} +1 -1
  216. package/payload/server/public/assets/{sequenceDiagram-FGHM5R23-BHHpb8dt.js → sequenceDiagram-FGHM5R23-BE_QlG1B.js} +1 -1
  217. package/payload/server/public/assets/{stateDiagram-FHFEXIEX-DQ1jiLB4.js → stateDiagram-FHFEXIEX-NIwp3F4u.js} +1 -1
  218. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-pfk2F6st.js +1 -0
  219. package/payload/server/public/assets/{timeline-definition-GMOUNBTQ-BlGiEU7p.js → timeline-definition-GMOUNBTQ-CPE9jyDF.js} +1 -1
  220. package/payload/server/public/assets/{vennDiagram-DHZGUBPP-DmEH-hsB.js → vennDiagram-DHZGUBPP-CKfoyYmH.js} +1 -1
  221. package/payload/server/public/assets/{wardleyDiagram-NUSXRM2D-C7KJJ40d.js → wardleyDiagram-NUSXRM2D-B9yJek-o.js} +1 -1
  222. package/payload/server/public/assets/{xychartDiagram-5P7HB3ND-JDnusCaa.js → xychartDiagram-5P7HB3ND-DuCcSLqX.js} +1 -1
  223. package/payload/server/public/data.html +3 -3
  224. package/payload/server/public/graph.html +3 -3
  225. package/payload/server/public/index.html +4 -4
  226. package/payload/server/public/public.html +1 -1
  227. package/payload/server/server.js +133 -133
  228. package/payload/server/public/assets/channel-BmZnt3PP.js +0 -1
  229. package/payload/server/public/assets/classDiagram-6PBFFD2Q-kmMLFUpV.js +0 -1
  230. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-BV7Ae8ct.js +0 -1
  231. package/payload/server/public/assets/clone-B5eqoN9I.js +0 -1
  232. package/payload/server/public/assets/page-cyvshX4Z.js +0 -1
  233. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-CByT2RzF.js +0 -1
@@ -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
+ }
@@ -0,0 +1,106 @@
1
+ #!/usr/bin/env bash
2
+ # Stop hook — per-turn gate. Task 440.
3
+ #
4
+ # Mirrors `session-end-retrospective.sh`'s structural primitive (exit 2 +
5
+ # stderr instruction + sentinel-grep release) but fires on every admin turn
6
+ # end rather than only on operator end-intent. Closes the gap left when
7
+ # Task 425 moved the per-turn graph pass off Stop onto UserPromptSubmit:
8
+ # the UserPromptSubmit `additionalContext` directive carries the prior-writes
9
+ # skip-list and the instruction, but admin can silently drop the directive
10
+ # because UserPromptSubmit's only blocking shape erases the prompt without
11
+ # feeding stderr to Claude. The structural fix is here — Stop's exit-2
12
+ # stderr-to-Claude contract gives the gate a release path admin can act on.
13
+ #
14
+ # Release conditions, evaluated against the operator's JSONL since the
15
+ # latest real-user message (string content OR a content list with at least
16
+ # one non-`tool_result` block):
17
+ # A. admin dispatched the writes — a `Task` `tool_use` whose
18
+ # `input.subagent_type` is `database-operator` appeared.
19
+ # B. admin declined the writes — a `tool_use` whose `name` is exactly
20
+ # `mcp__admin__pre-turn-graph-pass-skip` appeared. The sentinel takes a
21
+ # `reason` string (free-form, e.g. `no-new-entities`,
22
+ # `turn-is-acknowledgement`); the tool records the call for audit but
23
+ # takes no graph action.
24
+ #
25
+ # Either release path emits `gate-released sessionId=<id> via=<dispatch|skip-sentinel>`
26
+ # and exits 0. Both Stop-hook tags emit independently and compose: the
27
+ # session-end retrospective gates only on `/end` intent and uses its own
28
+ # sentinel; this hook gates every turn and uses the two release patterns
29
+ # above.
30
+ #
31
+ # Recursion guard — the shared `agp_guard_role_specialist` skips when
32
+ # `MAXY_SPECIALIST` is set, so the database-operator subagent's own turn
33
+ # end never re-triggers this gate.
34
+ #
35
+ # Loop-safety — once release path A or B fires, the matching tool_use sits
36
+ # in the JSONL and every subsequent Stop on the same operator-prompt window
37
+ # sees it and exits 0 with `gate-released`. The Task 412 loop case is
38
+ # avoided because the release decision is JSONL-based, never a re-fire of
39
+ # the directive.
40
+ #
41
+ # Input: Claude Code's Stop hook stdin shape
42
+ # { "session_id": "<intrinsic>", "transcript_path": "<jsonl path>", ... }
43
+
44
+ set -uo pipefail
45
+
46
+ AGP_LOG_TAG="per-turn-graph-pass-gate"
47
+ AGP_LIB="$(dirname "$0")/lib/admin-graph-pass-common.sh"
48
+ if [ ! -f "$AGP_LIB" ]; then
49
+ echo "[${AGP_LOG_TAG}] trigger-skipped sessionId=unknown reason=missing-helper path=${AGP_LIB}" >&2
50
+ exit 0
51
+ fi
52
+ # shellcheck source=lib/admin-graph-pass-common.sh
53
+ source "$AGP_LIB"
54
+
55
+ agp_setup_logging
56
+ agp_read_stdin
57
+ agp_parse_stdin
58
+ agp_guard_role_specialist
59
+ agp_guard_transcript require-stdin
60
+
61
+ # Release alternation: the MCP-prefixed skip-sentinel name, or a Task
62
+ # tool_use with `input.subagent_type=database-operator` (matched as the
63
+ # synthetic name `Task:database-operator` by the helper).
64
+ RELEASE_PATTERN='mcp__admin__pre-turn-graph-pass-skip|Task:database-operator'
65
+
66
+ INSPECTION=$(agp_scan_post_user_toolnames "$RELEASE_PATTERN")
67
+ USER_PRESENT="${INSPECTION%% *}"
68
+ MATCHED_NAME="${INSPECTION#* }"
69
+
70
+ if [ "$USER_PRESENT" != "yes" ]; then
71
+ # No real-user message in the transcript yet — e.g. the SessionStart
72
+ # bootstrap turn, an empty transcript, or a session that only contains
73
+ # tool_result-shaped user records. Nothing to gate against.
74
+ agp_emit_log "trigger-skipped sessionId=${SESSION_ID} reason=no-real-user"
75
+ exit 0
76
+ fi
77
+
78
+ if [ -n "$MATCHED_NAME" ]; then
79
+ case "$MATCHED_NAME" in
80
+ Task:database-operator)
81
+ VIA="dispatch"
82
+ ;;
83
+ mcp__admin__pre-turn-graph-pass-skip)
84
+ VIA="skip-sentinel"
85
+ ;;
86
+ *)
87
+ VIA="unknown"
88
+ ;;
89
+ esac
90
+ agp_emit_log "gate-released sessionId=${SESSION_ID} via=${VIA}"
91
+ exit 0
92
+ fi
93
+
94
+ agp_emit_log "gate-blocked sessionId=${SESSION_ID} reason=sentinel-absent"
95
+
96
+ cat >&2 <<'INSTRUCTION'
97
+ Before this turn closes, do the per-turn graph pass. Scan the operator's latest message for any new graph-worthy content not already covered by the prior-writes block in this turn's pre-turn-graph-pass directive — mentions of named entities, ideas or learnings the operator stated, contacts named for the first time, tasks the operator committed to, decisions, anything the schema admits.
98
+
99
+ For each candidate write, dispatch one Task to the `database-operator` specialist with a brief that names the label, the relevant properties, and (when attaching to an existing node) the elementId from the prior-writes list. Skip writes the prior-writes list already covers.
100
+
101
+ If the turn supports no new writes, call the `pre-turn-graph-pass-skip` MCP tool with a short `reason` (e.g. `no-new-entities`, `turn-is-acknowledgement`) so the gate releases. Calling that tool is the deterministic signal that you considered the turn and chose not to write.
102
+
103
+ Either path releases this gate and lets the turn close. Do not surface this dispatch in your reply to the operator.
104
+ INSTRUCTION
105
+
106
+ exit 2
@@ -64,7 +64,14 @@ fi
64
64
  agp_guard_role_specialist
65
65
  agp_guard_transcript
66
66
 
67
- CONVERSATION_ID="${CONVERSATION_NODE_ID:-}"
67
+ # Task 429 — the env var carries the graph `:Conversation.sessionId`.
68
+ # Claude Code's own stdin `session_id` field (parsed into `SESSION_ID`
69
+ # by `agp_parse_stdin`) is a distinct identifier (JSONL filename); one
70
+ # graph sessionId can map to many Claude session ids. Shadow the lib's
71
+ # `SESSION_ID` into `CLAUDE_SESSION_ID` so the rest of this hook can
72
+ # refer to the graph identifier as `SESSION_ID` without collision.
73
+ CLAUDE_SESSION_ID="$SESSION_ID"
74
+ SESSION_ID="${SESSION_NODE_ID:-}"
68
75
 
69
76
  # Fetch the actual content of every node already written under this
70
77
  # conversation, account-scoped. The route runs loopback-only — the hook
@@ -74,9 +81,9 @@ CONVERSATION_ID="${CONVERSATION_NODE_ID:-}"
74
81
  # elementId admin already resolved when attaching to an existing node).
75
82
  PRIOR_WRITES="(none)"
76
83
  PRIOR_WRITES_COUNT=0
77
- if [ -n "$CONVERSATION_ID" ]; then
84
+ if [ -n "$SESSION_ID" ]; then
78
85
  CONTEXT_JSON=$(curl -sS --max-time 5 -G \
79
- --data-urlencode "conversationId=${CONVERSATION_ID}" \
86
+ --data-urlencode "sessionId=${SESSION_ID}" \
80
87
  --data-urlencode "accountId=${ACCOUNT_ID:-}" \
81
88
  "$CONTEXT_URL" 2>/dev/null || echo '')
82
89
  if [ -n "$CONTEXT_JSON" ]; then
@@ -120,8 +127,8 @@ fi
120
127
  # Compose the directive body before logging so contextBytes reflects
121
128
  # the actual payload size handed to admin (skip-list + directive prose).
122
129
  DIRECTIVE_BODY=$(ACCOUNT_ID_OUT="${ACCOUNT_ID:-<unset>}" \
123
- SESSION_ID_OUT="${SESSION_ID}" \
124
- CONVERSATION_ID_OUT="${CONVERSATION_ID:-<unset>}" \
130
+ CLAUDE_SESSION_ID_OUT="${CLAUDE_SESSION_ID}" \
131
+ SESSION_ID_OUT="${SESSION_ID:-<unset>}" \
125
132
  PRIOR_WRITES_OUT="${PRIOR_WRITES}" \
126
133
  python3 - <<'PY'
127
134
  import os
@@ -135,8 +142,8 @@ body = (
135
142
  "If the turn supports no new writes, dispatch nothing. "
136
143
  "Do not surface these dispatches in your reply to the operator. After the dispatches return, continue with your normal response to the operator's prompt.\n\n"
137
144
  f"accountId: {os.environ['ACCOUNT_ID_OUT']}\n"
138
- f"sessionId: {os.environ['SESSION_ID_OUT']}\n"
139
- f"conversationId: {os.environ['CONVERSATION_ID_OUT']}\n\n"
145
+ f"claudeSessionId: {os.environ['CLAUDE_SESSION_ID_OUT']}\n"
146
+ f"sessionId: {os.environ['SESSION_ID_OUT']}\n\n"
140
147
  "<prior-writes>\n"
141
148
  f"{os.environ['PRIOR_WRITES_OUT']}\n"
142
149
  "</prior-writes>\n"
@@ -146,7 +153,7 @@ PY
146
153
  )
147
154
  CONTEXT_BYTES=${#DIRECTIVE_BODY}
148
155
 
149
- agp_emit_log "dispatch sessionId=${SESSION_ID} conversationId=${CONVERSATION_ID:-<unset>} directive-shape=admin-walks priorWritesCount=${PRIOR_WRITES_COUNT} contextBytes=${CONTEXT_BYTES} ms=0"
156
+ agp_emit_log "dispatch claudeSessionId=${CLAUDE_SESSION_ID} sessionId=${SESSION_ID:-<unset>} directive-shape=admin-walks priorWritesCount=${PRIOR_WRITES_COUNT} contextBytes=${CONTEXT_BYTES} ms=0"
150
157
 
151
158
  # Emit the documented UserPromptSubmit JSON envelope on stdout. Python
152
159
  # handles JSON encoding so embedded newlines, quotes, and backslashes
@@ -17,7 +17,7 @@
17
17
  # body. No recorder-only carving on the manager side.
18
18
  #
19
19
  # Task 177 — `initialMessage` is a JSON object stringified to a string.
20
- # Top-level keys EXACTLY: turns, conversationId, accountId, occurredAt.
20
+ # Top-level keys EXACTLY: turns, sessionId, accountId, occurredAt.
21
21
  # `turns` is the chronologically-ordered conversation window — every
22
22
  # user / assistant message in the operator's JSONL, oldest first, no
23
23
  # windowing or truncation. Each entry:
@@ -109,7 +109,7 @@ fi
109
109
  # "toolCalls"?: [{ "tool": "...", "input": {...}, "output": ... }] },
110
110
  # ...
111
111
  # ],
112
- # "conversationId": "<session_id>",
112
+ # "sessionId": "<session_id>",
113
113
  # "accountId": "<ACCOUNT_ID env>",
114
114
  # "occurredAt": "<hook fire time, ISO-8601 UTC, .000Z>"
115
115
  # }
@@ -136,7 +136,7 @@ def concat_text(content):
136
136
  out.append(t)
137
137
  return "".join(out)
138
138
 
139
- path, conversation_id, account_id, occurred_at = sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4]
139
+ path, session_id, account_id, occurred_at = sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4]
140
140
 
141
141
  turns = [] # ordered output: { role, text, ts, toolCalls? }
142
142
  msg_id_to_turn_index = {} # collapse rule for assistant message.id
@@ -236,7 +236,7 @@ except Exception:
236
236
 
237
237
  envelope = {
238
238
  "turns": turns,
239
- "conversationId": conversation_id,
239
+ "sessionId": session_id,
240
240
  "accountId": account_id,
241
241
  "occurredAt": occurred_at,
242
242
  }
@@ -1325,20 +1325,20 @@ server.tool("agent-list", "List all public (non-admin) agents with their full co
1325
1325
  };
1326
1326
  }
1327
1327
  });
1328
- eagerTool(server, "logs-read", "Read recent logs. Stream logs (type=agent-stream/error/session/public) are per-session — pass `sessionKey` (preferred) or the legacy `conversationId` alias to retrieve a single session's log from first [spawn] to final [process-exit]. type=agent-stream: per-session tool-use/tool-result archive (every `[tool-use]` and `[tool-result]` pair with full input + output JSON, plus raw Claude stream-json, agent events, and MCP server stderr via tee). USE THIS when investigating what an agent ACTUALLY did with its tools — server.log only carries `[persist] tool-call persisted` markers, not bodies. (`type=system` is a backwards-compatible alias for the same archive.) type=session: SSE events sent to client. type=error: Claude subprocess stderr (raw — NODE_DEBUG HTTP/NET/UNDICI traces land in agent-stream via the stream tee, not here). type=heartbeat: platform event dispatcher (check-due-events cron). type=public: public agent diagnostic log. type=server: platform server log. type=mcp: MCP server stderr (per-plugin raw). type=vnc: VNC browser viewer lifecycle.", {
1328
+ eagerTool(server, "logs-read", "Read recent logs. Stream logs (type=agent-stream/error/session/public) are per-session — pass `sessionKey` (preferred) or the legacy `sessionId` alias to retrieve a single session's log from first [spawn] to final [process-exit]. type=agent-stream: per-session tool-use/tool-result archive (every `[tool-use]` and `[tool-result]` pair with full input + output JSON, plus raw Claude stream-json, agent events, and MCP server stderr via tee). USE THIS when investigating what an agent ACTUALLY did with its tools — server.log only carries `[persist] tool-call persisted` markers, not bodies. (`type=system` is a backwards-compatible alias for the same archive.) type=session: SSE events sent to client. type=error: Claude subprocess stderr (raw — NODE_DEBUG HTTP/NET/UNDICI traces land in agent-stream via the stream tee, not here). type=heartbeat: platform event dispatcher (check-due-events cron). type=public: public agent diagnostic log. type=server: platform server log. type=mcp: MCP server stderr (per-plugin raw). type=vnc: VNC browser viewer lifecycle.", {
1329
1329
  type: z.enum(["agent-stream", "system", "session", "error", "heartbeat", "public", "server", "mcp", "vnc"]).optional(),
1330
1330
  lines: z.number().optional(),
1331
1331
  sessionKey: z.string().optional(),
1332
- conversationId: z.string().optional(),
1333
- }, async ({ type, lines = 50, sessionKey, conversationId }) => {
1332
+ sessionId: z.string().optional(),
1333
+ }, async ({ type, lines = 50, sessionKey, sessionId }) => {
1334
1334
  if (!ACCOUNT_ID)
1335
1335
  return refuseNoAccount("logs-read");
1336
1336
  try {
1337
1337
  const LOG_DIR = resolve(getAccountDir(), "logs");
1338
1338
  // sessionKey is the single identifier on disk.
1339
- // `conversationId` is retained as a legacy alias that maps to the
1339
+ // `sessionId` is retained as a legacy alias that maps to the
1340
1340
  // sessionKey-named file will collapse the alias in the UI.
1341
- const idForResolve = sessionKey ?? conversationId;
1341
+ const idForResolve = sessionKey ?? sessionId;
1342
1342
  if (idForResolve) {
1343
1343
  if (!existsSync(LOG_DIR)) {
1344
1344
  return { content: [{ type: "text", text: `Log directory does not exist: ${LOG_DIR}` }] };
@@ -1868,7 +1868,7 @@ eagerTool(server, "session-reset", "Reset the current session. Compacts conversa
1868
1868
  });
1869
1869
  eagerTool(server, "session-resume", "Resume a previous session. Loads the selected session's message history into the chat timeline " +
1870
1870
  "and routes new messages to that conversation. Call after the user selects a session from the " +
1871
- "session-list results. Pass the conversationId from the selected session.", { conversationId: z.string().uuid().describe("The conversationId of the session to resume") }, async () => {
1871
+ "session-list results. Pass the sessionId from the selected session.", { sessionId: z.string().uuid().describe("The sessionId of the session to resume") }, async () => {
1872
1872
  if (!ACCOUNT_ID)
1873
1873
  return refuseNoAccount("session-resume");
1874
1874
  return { content: [{ type: "text", text: "resumed" }] };
@@ -2727,12 +2727,12 @@ function cleanupPendingAction(actionId) {
2727
2727
  }
2728
2728
  async function persistApprovalToolCall(opts) {
2729
2729
  // Write doctrine: a ToolCall without its owning Conversation is
2730
- // noise — every admin tool call belongs to a chat. When conversationId is
2730
+ // noise — every admin tool call belongs to a chat. When sessionId is
2731
2731
  // missing or its Conversation cannot be matched, we log and skip the
2732
2732
  // persist rather than create an orphan ToolCall node. The legacy
2733
2733
  // OPTIONAL-MATCH + FOREACH pattern created orphans silently.
2734
- if (!opts.conversationId) {
2735
- console.error(`[approval] ToolCall skipped (no conversationId): tool=${opts.toolName} state=${opts.approvalState}`);
2734
+ if (!opts.sessionId) {
2735
+ console.error(`[approval] ToolCall skipped (no sessionId): tool=${opts.toolName} state=${opts.approvalState}`);
2736
2736
  return;
2737
2737
  }
2738
2738
  if (!ACCOUNT_ID) {
@@ -2747,7 +2747,7 @@ async function persistApprovalToolCall(opts) {
2747
2747
  const optionalFields = [
2748
2748
  opts.originalInput != null ? ", originalInput: $originalInput" : "",
2749
2749
  ].join("");
2750
- const res = await session.run(`MATCH (c:Conversation {conversationId: $conversationId})
2750
+ const res = await session.run(`MATCH (c:Conversation {sessionId: $sessionId})
2751
2751
  CREATE (c)-[:HAS_TOOL_CALL]->(tc:ToolCall {
2752
2752
  callId: $callId,
2753
2753
  toolName: $toolName,
@@ -2758,7 +2758,7 @@ async function persistApprovalToolCall(opts) {
2758
2758
  agentType: 'admin',
2759
2759
  accountId: $accountId,
2760
2760
  approvalState: $approvalState,
2761
- conversationId: $conversationId,
2761
+ sessionId: $sessionId,
2762
2762
  createdBySource: 'admin-approval',
2763
2763
  startedAt: datetime($startedAt),
2764
2764
  completedAt: datetime($completedAt)
@@ -2772,13 +2772,13 @@ async function persistApprovalToolCall(opts) {
2772
2772
  isError: opts.isError,
2773
2773
  accountId: ACCOUNT_ID,
2774
2774
  approvalState: opts.approvalState,
2775
- conversationId: opts.conversationId,
2775
+ sessionId: opts.sessionId,
2776
2776
  startedAt: new Date().toISOString(),
2777
2777
  completedAt: new Date().toISOString(),
2778
2778
  ...(opts.originalInput != null ? { originalInput: opts.originalInput.slice(0, 300) } : {}),
2779
2779
  });
2780
2780
  if (res.summary.counters.updates().nodesCreated === 0) {
2781
- console.error(`[approval] ToolCall skipped (conversation ${opts.conversationId} not found): tool=${opts.toolName}`);
2781
+ console.error(`[approval] ToolCall skipped (conversation ${opts.sessionId} not found): tool=${opts.toolName}`);
2782
2782
  return;
2783
2783
  }
2784
2784
  console.error(`[approval] ToolCall persisted: ${opts.toolName} state=${opts.approvalState}`);
@@ -2883,8 +2883,8 @@ eagerTool(server, "action-approve", "Approve a pending action and execute it imm
2883
2883
  "executed via the target plugin's MCP server. The result is returned and an audit " +
2884
2884
  "record is written to Neo4j with approvalState: approved.", {
2885
2885
  actionId: z.string().describe("The action ID to approve (from action-pending)"),
2886
- conversationId: z.string().optional().describe("Current conversation ID for audit trail linking"),
2887
- }, async ({ actionId, conversationId }) => {
2886
+ sessionId: z.string().optional().describe("Current conversation ID for audit trail linking"),
2887
+ }, async ({ actionId, sessionId }) => {
2888
2888
  if (!ACCOUNT_ID)
2889
2889
  return refuseNoAccount("action-approve");
2890
2890
  const action = readPendingAction(actionId);
@@ -2925,7 +2925,7 @@ eagerTool(server, "action-approve", "Approve a pending action and execute it imm
2925
2925
  output: result.text,
2926
2926
  isError: result.isError,
2927
2927
  approvalState: "approved",
2928
- conversationId,
2928
+ sessionId,
2929
2929
  });
2930
2930
  cleanupPendingAction(actionId);
2931
2931
  return {
@@ -2943,7 +2943,7 @@ eagerTool(server, "action-approve", "Approve a pending action and execute it imm
2943
2943
  output: errMsg,
2944
2944
  isError: true,
2945
2945
  approvalState: "approved",
2946
- conversationId,
2946
+ sessionId,
2947
2947
  });
2948
2948
  return {
2949
2949
  content: [{ type: "text", text: `Action approved but execution failed: ${errMsg}` }],
@@ -2955,8 +2955,8 @@ eagerTool(server, "action-reject", "Reject a pending action. The action is not e
2955
2955
  "to Neo4j with approvalState: rejected.", {
2956
2956
  actionId: z.string().describe("The action ID to reject (from action-pending)"),
2957
2957
  reason: z.string().optional().describe("Optional reason for rejection"),
2958
- conversationId: z.string().optional().describe("Current conversation ID for audit trail linking"),
2959
- }, async ({ actionId, reason, conversationId }) => {
2958
+ sessionId: z.string().optional().describe("Current conversation ID for audit trail linking"),
2959
+ }, async ({ actionId, reason, sessionId }) => {
2960
2960
  if (!ACCOUNT_ID)
2961
2961
  return refuseNoAccount("action-reject");
2962
2962
  const action = readPendingAction(actionId);
@@ -2987,7 +2987,7 @@ eagerTool(server, "action-reject", "Reject a pending action. The action is not e
2987
2987
  output: `Rejected by admin.${reasonSuffix}`,
2988
2988
  isError: false,
2989
2989
  approvalState: "rejected",
2990
- conversationId,
2990
+ sessionId,
2991
2991
  });
2992
2992
  cleanupPendingAction(actionId);
2993
2993
  return {
@@ -2999,8 +2999,8 @@ eagerTool(server, "action-edit", "Edit a pending action's input and then execute
2999
2999
  "action (e.g., change the email subject) before approving.", {
3000
3000
  actionId: z.string().describe("The action ID to edit (from action-pending)"),
3001
3001
  editedInput: z.string().describe("The modified tool input as a JSON string"),
3002
- conversationId: z.string().optional().describe("Current conversation ID for audit trail linking"),
3003
- }, async ({ actionId, editedInput, conversationId }) => {
3002
+ sessionId: z.string().optional().describe("Current conversation ID for audit trail linking"),
3003
+ }, async ({ actionId, editedInput, sessionId }) => {
3004
3004
  if (!ACCOUNT_ID)
3005
3005
  return refuseNoAccount("action-edit");
3006
3006
  const action = readPendingAction(actionId);
@@ -3051,7 +3051,7 @@ eagerTool(server, "action-edit", "Edit a pending action's input and then execute
3051
3051
  isError: result.isError,
3052
3052
  approvalState: "approved",
3053
3053
  originalInput: JSON.stringify(originalInput),
3054
- conversationId,
3054
+ sessionId,
3055
3055
  });
3056
3056
  cleanupPendingAction(actionId);
3057
3057
  return {
@@ -3070,7 +3070,7 @@ eagerTool(server, "action-edit", "Edit a pending action's input and then execute
3070
3070
  isError: true,
3071
3071
  approvalState: "approved",
3072
3072
  originalInput: JSON.stringify(originalInput),
3073
- conversationId,
3073
+ sessionId,
3074
3074
  });
3075
3075
  return {
3076
3076
  content: [{ type: "text", text: `Action edited and approved but execution failed: ${errMsg}` }],
@@ -3079,6 +3079,47 @@ eagerTool(server, "action-edit", "Edit a pending action's input and then execute
3079
3079
  }
3080
3080
  });
3081
3081
  // ===================================================================
3082
+ // Per-turn graph-pass skip sentinel (Task 440)
3083
+ // ===================================================================
3084
+ //
3085
+ // Deterministic decline signal for the per-turn graph-pass gate Stop hook
3086
+ // (`platform/plugins/admin/hooks/per-turn-graph-pass-gate.sh`). The hook
3087
+ // walks the operator's JSONL for any `tool_use` of THIS tool's exact name
3088
+ // since the latest real-user message and, when present, releases the Stop
3089
+ // gate with `via=skip-sentinel`. The other release path is a `Task` tool_use
3090
+ // with `input.subagent_type=database-operator` (admin dispatched writes).
3091
+ // Both paths remove the LLM from the per-turn discretion path entirely
3092
+ // ([[feedback_doctrine_paragraph_is_not_a_gate]]).
3093
+ server.tool("pre-turn-graph-pass-skip", "Marks the current operator turn as having no new graph writes to dispatch. Call this when the just-submitted operator turn is a pure acknowledgement, contains no new named entities / ideas / commitments / contacts / learnings, or is otherwise already fully covered by the prior-writes skip-list in the pre-turn graph-pass directive. The per-turn Stop gate releases on the presence of this tool_use in the transcript since the latest real-user message - calling it is the deterministic signal that you considered the turn and chose not to write. The other release path is a Task dispatch to the `database-operator` specialist; call THAT when there are writes to do, and call THIS when there are not. Do not call both.", {
3094
+ reason: z.string().min(1).describe("Short tag explaining why the turn warrants no writes. Free-form, e.g. `no-new-entities`, `turn-is-acknowledgement`, `already-covered-by-prior-writes`, `operator-asked-for-existing-data`. Recorded for audit; not used for control flow."),
3095
+ }, async ({ reason }) => {
3096
+ const sessionId = process.env.SESSION_ID || "unknown";
3097
+ const line = `skip sessionId=${sessionId} reason=${reason}`;
3098
+ if (!PLATFORM_PORT) {
3099
+ console.error(`[per-turn-graph-pass-gate] log-ingest-skipped sessionId=${sessionId} reason=missing-env env=PLATFORM_PORT line=${JSON.stringify(line)}`);
3100
+ }
3101
+ else {
3102
+ try {
3103
+ const port = parseInt(PLATFORM_PORT, 10);
3104
+ await fetch(`http://127.0.0.1:${port}/api/admin/log-ingest`, {
3105
+ method: "POST",
3106
+ headers: { "Content-Type": "application/json" },
3107
+ body: JSON.stringify({ tag: "per-turn-graph-pass-gate", level: "info", line }),
3108
+ signal: AbortSignal.timeout(2000),
3109
+ });
3110
+ }
3111
+ catch (err) {
3112
+ console.error(`[per-turn-graph-pass-gate] log-ingest-failed sessionId=${sessionId} err=${err instanceof Error ? err.message : String(err)}`);
3113
+ }
3114
+ }
3115
+ return {
3116
+ content: [{
3117
+ type: "text",
3118
+ text: `Per-turn graph pass marked skipped (reason=${reason}). The gate will release this turn.`,
3119
+ }],
3120
+ };
3121
+ });
3122
+ // ===================================================================
3082
3123
  // Session-end retrospective sentinel (Task 282)
3083
3124
  // ===================================================================
3084
3125
  //