@rubytech/create-maxy-code 0.1.295 → 0.1.297

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 (231) hide show
  1. package/package.json +1 -1
  2. package/payload/platform/lib/models/dist/index.d.ts +1 -0
  3. package/payload/platform/lib/models/dist/index.d.ts.map +1 -1
  4. package/payload/platform/lib/models/dist/index.js +4 -2
  5. package/payload/platform/lib/models/dist/index.js.map +1 -1
  6. package/payload/platform/lib/models/src/index.ts +3 -1
  7. package/payload/platform/neo4j/schema.cypher +10 -2
  8. package/payload/platform/plugins/admin/.claude-plugin/plugin.json +5 -1
  9. package/payload/platform/plugins/admin/hooks/__tests__/prompt-optimiser-compliance.test.sh +27 -0
  10. package/payload/platform/plugins/admin/hooks/prompt-optimiser-compliance.sh +24 -5
  11. package/payload/platform/plugins/admin/lib/mcp-spawn-tee/index.js +159 -0
  12. package/payload/platform/plugins/admin/lib/mcp-spawn-tee/package.json +3 -0
  13. package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +3 -13
  14. package/payload/platform/plugins/aeo/.claude-plugin/plugin.json +5 -1
  15. package/payload/platform/plugins/aeo/lib/mcp-spawn-tee/index.js +159 -0
  16. package/payload/platform/plugins/aeo/lib/mcp-spawn-tee/package.json +3 -0
  17. package/payload/platform/plugins/browser/.claude-plugin/plugin.json +5 -1
  18. package/payload/platform/plugins/browser/lib/mcp-spawn-tee/index.js +159 -0
  19. package/payload/platform/plugins/browser/lib/mcp-spawn-tee/package.json +3 -0
  20. package/payload/platform/plugins/contacts/.claude-plugin/plugin.json +5 -1
  21. package/payload/platform/plugins/contacts/lib/mcp-spawn-tee/index.js +159 -0
  22. package/payload/platform/plugins/contacts/lib/mcp-spawn-tee/package.json +3 -0
  23. package/payload/platform/plugins/docs/references/getting-started.md +1 -1
  24. package/payload/platform/plugins/docs/references/platform.md +1 -11
  25. package/payload/platform/plugins/email/.claude-plugin/plugin.json +6 -2
  26. package/payload/platform/plugins/email/PLUGIN.md +6 -2
  27. package/payload/platform/plugins/email/lib/mcp-spawn-tee/index.js +159 -0
  28. package/payload/platform/plugins/email/lib/mcp-spawn-tee/package.json +3 -0
  29. package/payload/platform/plugins/email/mcp/dist/__tests__/email-draft.test.d.ts +2 -0
  30. package/payload/platform/plugins/email/mcp/dist/__tests__/email-draft.test.d.ts.map +1 -0
  31. package/payload/platform/plugins/email/mcp/dist/__tests__/email-draft.test.js +75 -0
  32. package/payload/platform/plugins/email/mcp/dist/__tests__/email-draft.test.js.map +1 -0
  33. package/payload/platform/plugins/email/mcp/dist/__tests__/email-setup.test.js +58 -0
  34. package/payload/platform/plugins/email/mcp/dist/__tests__/email-setup.test.js.map +1 -1
  35. package/payload/platform/plugins/email/mcp/dist/__tests__/imap-drafts.test.d.ts +2 -0
  36. package/payload/platform/plugins/email/mcp/dist/__tests__/imap-drafts.test.d.ts.map +1 -0
  37. package/payload/platform/plugins/email/mcp/dist/__tests__/imap-drafts.test.js +74 -0
  38. package/payload/platform/plugins/email/mcp/dist/__tests__/imap-drafts.test.js.map +1 -0
  39. package/payload/platform/plugins/email/mcp/dist/__tests__/imap-probe.test.d.ts +2 -0
  40. package/payload/platform/plugins/email/mcp/dist/__tests__/imap-probe.test.d.ts.map +1 -0
  41. package/payload/platform/plugins/email/mcp/dist/__tests__/imap-probe.test.js +69 -0
  42. package/payload/platform/plugins/email/mcp/dist/__tests__/imap-probe.test.js.map +1 -0
  43. package/payload/platform/plugins/email/mcp/dist/__tests__/mail-options.test.d.ts +2 -0
  44. package/payload/platform/plugins/email/mcp/dist/__tests__/mail-options.test.d.ts.map +1 -0
  45. package/payload/platform/plugins/email/mcp/dist/__tests__/mail-options.test.js +46 -0
  46. package/payload/platform/plugins/email/mcp/dist/__tests__/mail-options.test.js.map +1 -0
  47. package/payload/platform/plugins/email/mcp/dist/__tests__/setup-probe.test.d.ts +2 -0
  48. package/payload/platform/plugins/email/mcp/dist/__tests__/setup-probe.test.d.ts.map +1 -0
  49. package/payload/platform/plugins/email/mcp/dist/__tests__/setup-probe.test.js +56 -0
  50. package/payload/platform/plugins/email/mcp/dist/__tests__/setup-probe.test.js.map +1 -0
  51. package/payload/platform/plugins/email/mcp/dist/__tests__/smtp-probe.test.d.ts +2 -0
  52. package/payload/platform/plugins/email/mcp/dist/__tests__/smtp-probe.test.d.ts.map +1 -0
  53. package/payload/platform/plugins/email/mcp/dist/__tests__/smtp-probe.test.js +46 -0
  54. package/payload/platform/plugins/email/mcp/dist/__tests__/smtp-probe.test.js.map +1 -0
  55. package/payload/platform/plugins/email/mcp/dist/index.js +44 -0
  56. package/payload/platform/plugins/email/mcp/dist/index.js.map +1 -1
  57. package/payload/platform/plugins/email/mcp/dist/lib/imap.d.ts +16 -3
  58. package/payload/platform/plugins/email/mcp/dist/lib/imap.d.ts.map +1 -1
  59. package/payload/platform/plugins/email/mcp/dist/lib/imap.js +62 -5
  60. package/payload/platform/plugins/email/mcp/dist/lib/imap.js.map +1 -1
  61. package/payload/platform/plugins/email/mcp/dist/lib/setup-probe.d.ts +42 -0
  62. package/payload/platform/plugins/email/mcp/dist/lib/setup-probe.d.ts.map +1 -0
  63. package/payload/platform/plugins/email/mcp/dist/lib/setup-probe.js +72 -0
  64. package/payload/platform/plugins/email/mcp/dist/lib/setup-probe.js.map +1 -0
  65. package/payload/platform/plugins/email/mcp/dist/lib/smtp.d.ts +16 -6
  66. package/payload/platform/plugins/email/mcp/dist/lib/smtp.d.ts.map +1 -1
  67. package/payload/platform/plugins/email/mcp/dist/lib/smtp.js +37 -20
  68. package/payload/platform/plugins/email/mcp/dist/lib/smtp.js.map +1 -1
  69. package/payload/platform/plugins/email/mcp/dist/scripts/send-transactional.js +1 -2
  70. package/payload/platform/plugins/email/mcp/dist/scripts/send-transactional.js.map +1 -1
  71. package/payload/platform/plugins/email/mcp/dist/tools/email-draft.d.ts +13 -0
  72. package/payload/platform/plugins/email/mcp/dist/tools/email-draft.d.ts.map +1 -0
  73. package/payload/platform/plugins/email/mcp/dist/tools/email-draft.js +45 -0
  74. package/payload/platform/plugins/email/mcp/dist/tools/email-draft.js.map +1 -0
  75. package/payload/platform/plugins/email/mcp/dist/tools/email-send.d.ts.map +1 -1
  76. package/payload/platform/plugins/email/mcp/dist/tools/email-send.js +2 -8
  77. package/payload/platform/plugins/email/mcp/dist/tools/email-send.js.map +1 -1
  78. package/payload/platform/plugins/email/mcp/dist/tools/email-setup.d.ts.map +1 -1
  79. package/payload/platform/plugins/email/mcp/dist/tools/email-setup.js +25 -3
  80. package/payload/platform/plugins/email/mcp/dist/tools/email-setup.js.map +1 -1
  81. package/payload/platform/plugins/email/references/email-reference.md +15 -0
  82. package/payload/platform/plugins/email/skills/email-composition/SKILL.md +15 -4
  83. package/payload/platform/plugins/memory/.claude-plugin/plugin.json +5 -1
  84. package/payload/platform/plugins/memory/lib/mcp-spawn-tee/index.js +159 -0
  85. package/payload/platform/plugins/memory/lib/mcp-spawn-tee/package.json +3 -0
  86. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-doc-contradictions.test.d.ts +2 -0
  87. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-doc-contradictions.test.d.ts.map +1 -0
  88. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-doc-contradictions.test.js +214 -0
  89. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-doc-contradictions.test.js.map +1 -0
  90. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-validator.test.js +1 -0
  91. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-validator.test.js.map +1 -1
  92. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-write-path-task802.test.d.ts +2 -0
  93. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-write-path-task802.test.d.ts.map +1 -0
  94. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-write-path-task802.test.js +113 -0
  95. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-write-path-task802.test.js.map +1 -0
  96. package/payload/platform/plugins/memory/mcp/dist/lib/schema-loader.d.ts +52 -2
  97. package/payload/platform/plugins/memory/mcp/dist/lib/schema-loader.d.ts.map +1 -1
  98. package/payload/platform/plugins/memory/mcp/dist/lib/schema-loader.js +90 -4
  99. package/payload/platform/plugins/memory/mcp/dist/lib/schema-loader.js.map +1 -1
  100. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/profile-update-personfields-open.test.js +1 -0
  101. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/profile-update-personfields-open.test.js.map +1 -1
  102. package/payload/platform/plugins/memory/mcp/vitest.config.ts +3 -0
  103. package/payload/platform/plugins/memory/references/schema-base.md +6 -2
  104. package/payload/platform/plugins/memory/references/schema-construction.md +8 -6
  105. package/payload/platform/plugins/memory/references/schema-estate-agent.md +1 -1
  106. package/payload/platform/plugins/outlook/.claude-plugin/plugin.json +5 -1
  107. package/payload/platform/plugins/outlook/lib/mcp-spawn-tee/index.js +159 -0
  108. package/payload/platform/plugins/outlook/lib/mcp-spawn-tee/package.json +3 -0
  109. package/payload/platform/plugins/replicate/.claude-plugin/plugin.json +5 -1
  110. package/payload/platform/plugins/replicate/lib/mcp-spawn-tee/index.js +159 -0
  111. package/payload/platform/plugins/replicate/lib/mcp-spawn-tee/package.json +3 -0
  112. package/payload/platform/plugins/scheduling/.claude-plugin/plugin.json +5 -1
  113. package/payload/platform/plugins/scheduling/lib/mcp-spawn-tee/index.js +159 -0
  114. package/payload/platform/plugins/scheduling/lib/mcp-spawn-tee/package.json +3 -0
  115. package/payload/platform/plugins/telegram/.claude-plugin/plugin.json +5 -1
  116. package/payload/platform/plugins/telegram/lib/mcp-spawn-tee/index.js +159 -0
  117. package/payload/platform/plugins/telegram/lib/mcp-spawn-tee/package.json +3 -0
  118. package/payload/platform/plugins/url-get/.claude-plugin/plugin.json +5 -1
  119. package/payload/platform/plugins/url-get/lib/mcp-spawn-tee/index.js +159 -0
  120. package/payload/platform/plugins/url-get/lib/mcp-spawn-tee/package.json +3 -0
  121. package/payload/platform/plugins/whatsapp/.claude-plugin/plugin.json +5 -1
  122. package/payload/platform/plugins/whatsapp/lib/mcp-spawn-tee/index.js +159 -0
  123. package/payload/platform/plugins/whatsapp/lib/mcp-spawn-tee/package.json +3 -0
  124. package/payload/platform/plugins/work/.claude-plugin/plugin.json +5 -1
  125. package/payload/platform/plugins/work/lib/mcp-spawn-tee/index.js +159 -0
  126. package/payload/platform/plugins/work/lib/mcp-spawn-tee/package.json +3 -0
  127. package/payload/platform/plugins/workflows/.claude-plugin/plugin.json +5 -1
  128. package/payload/platform/plugins/workflows/lib/mcp-spawn-tee/index.js +159 -0
  129. package/payload/platform/plugins/workflows/lib/mcp-spawn-tee/package.json +3 -0
  130. package/payload/platform/scripts/smoke-boot-services.sh +1 -1
  131. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.d.ts.map +1 -1
  132. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js +1 -0
  133. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js.map +1 -1
  134. package/payload/platform/services/whatsapp-channel/dist/jsonl-watch.d.ts +10 -0
  135. package/payload/platform/services/whatsapp-channel/dist/jsonl-watch.d.ts.map +1 -0
  136. package/payload/platform/services/whatsapp-channel/dist/jsonl-watch.js +70 -0
  137. package/payload/platform/services/whatsapp-channel/dist/jsonl-watch.js.map +1 -0
  138. package/payload/platform/services/whatsapp-channel/dist/notification.d.ts +10 -0
  139. package/payload/platform/services/whatsapp-channel/dist/notification.d.ts.map +1 -1
  140. package/payload/platform/services/whatsapp-channel/dist/notification.js +15 -0
  141. package/payload/platform/services/whatsapp-channel/dist/notification.js.map +1 -1
  142. package/payload/platform/services/whatsapp-channel/dist/server.d.ts +6 -1
  143. package/payload/platform/services/whatsapp-channel/dist/server.d.ts.map +1 -1
  144. package/payload/platform/services/whatsapp-channel/dist/server.js +38 -1
  145. package/payload/platform/services/whatsapp-channel/dist/server.js.map +1 -1
  146. package/payload/platform/templates/account.json +1 -1
  147. package/payload/platform/templates/specialists/agents/personal-assistant.md +1 -1
  148. package/payload/premium-plugins/writer-craft/.claude-plugin/plugin.json +5 -1
  149. package/payload/premium-plugins/writer-craft/lib/mcp-spawn-tee/index.js +159 -0
  150. package/payload/premium-plugins/writer-craft/lib/mcp-spawn-tee/package.json +3 -0
  151. package/payload/server/public/assets/AdminShell-DpjiG4KO.js +1 -0
  152. package/payload/server/public/assets/{Checkbox-DTrIyIFP.js → Checkbox-o5EbM1Sd.js} +1 -1
  153. package/payload/server/public/assets/{Transcript-C3aDVJ-n.js → Transcript-B-roO2vK.js} +1 -1
  154. package/payload/server/public/assets/{admin-DVdyV-Q6.js → admin-DmBG61gA.js} +1 -1
  155. package/payload/server/public/assets/{architectureDiagram-Q4EWVU46-DR9W0q1P.js → architectureDiagram-Q4EWVU46-DCLfcVZf.js} +1 -1
  156. package/payload/server/public/assets/{audio-attachment-mime-DGEfApkA.js → audio-attachment-mime-D_YMUIBb.js} +1 -1
  157. package/payload/server/public/assets/{blockDiagram-DXYQGD6D-C3uwaI7p.js → blockDiagram-DXYQGD6D-DtTb6oGR.js} +1 -1
  158. package/payload/server/public/assets/{browser-DrJReVEG.js → browser-DPqQnY8B.js} +1 -1
  159. package/payload/server/public/assets/{c4Diagram-AHTNJAMY-C8hmUDdd.js → c4Diagram-AHTNJAMY-DHMgkbse.js} +1 -1
  160. package/payload/server/public/assets/channel-BGB5Q-QM.js +1 -0
  161. package/payload/server/public/assets/chat-BpceL2qA.js +1 -0
  162. package/payload/server/public/assets/{chunk-336JU56O-BRCubMCb.js → chunk-336JU56O-DQja-fc4.js} +2 -2
  163. package/payload/server/public/assets/{chunk-426QAEUC-BNINkVsL.js → chunk-426QAEUC-uBZXKz4Z.js} +1 -1
  164. package/payload/server/public/assets/{chunk-4TB4RGXK-DSMj_AZh.js → chunk-4TB4RGXK-DViPFnGL.js} +1 -1
  165. package/payload/server/public/assets/{chunk-5FUZZQ4R-6DNGaUkf.js → chunk-5FUZZQ4R-CdKJ7vdW.js} +1 -1
  166. package/payload/server/public/assets/{chunk-5PVQY5BW-DPhkkS4p.js → chunk-5PVQY5BW-BIJiayBe.js} +1 -1
  167. package/payload/server/public/assets/{chunk-EDXVE4YY-BjWSqn7_.js → chunk-EDXVE4YY-CDDqx-TB.js} +1 -1
  168. package/payload/server/public/assets/{chunk-ENJZ2VHE-BX1ZnU4A.js → chunk-ENJZ2VHE-BVNFvue5.js} +1 -1
  169. package/payload/server/public/assets/{chunk-ICPOFSXX-DvYSWH7x.js → chunk-ICPOFSXX-DEZQolUW.js} +1 -1
  170. package/payload/server/public/assets/{chunk-OYMX7WX6-7_m3mEOK.js → chunk-OYMX7WX6-Dn0reHna.js} +1 -1
  171. package/payload/server/public/assets/{chunk-U2HBQHQK-Bl1a895I.js → chunk-U2HBQHQK-sqMpBHaS.js} +1 -1
  172. package/payload/server/public/assets/{chunk-X2U36JSP-WkSpBPYx.js → chunk-X2U36JSP-ByhTOa14.js} +1 -1
  173. package/payload/server/public/assets/{chunk-YZCP3GAM-DpWRmPUo.js → chunk-YZCP3GAM-CGo_et0d.js} +1 -1
  174. package/payload/server/public/assets/{chunk-ZZ45TVLE-D9Dgmeso.js → chunk-ZZ45TVLE-B9aPwq_o.js} +1 -1
  175. package/payload/server/public/assets/classDiagram-6PBFFD2Q-DdUR3hKH.js +1 -0
  176. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-B0ZE2WR0.js +1 -0
  177. package/payload/server/public/assets/clone-B5aO4uPo.js +1 -0
  178. package/payload/server/public/assets/{dagre-PrVfCcSt.js → dagre-DE88U4Vk.js} +1 -1
  179. package/payload/server/public/assets/{dagre-KV5264BT-DPq3dcLH.js → dagre-KV5264BT-oeoQWi1f.js} +1 -1
  180. package/payload/server/public/assets/data-6mvcS2_6.js +1 -0
  181. package/payload/server/public/assets/{diagram-5BDNPKRD-DoszElKb.js → diagram-5BDNPKRD-HmWmPhlY.js} +1 -1
  182. package/payload/server/public/assets/{diagram-G4DWMVQ6-BRuqosix.js → diagram-G4DWMVQ6-Bkao4d6n.js} +1 -1
  183. package/payload/server/public/assets/{diagram-MMDJMWI5-CpigG1d_.js → diagram-MMDJMWI5-Eh2fnSb-.js} +1 -1
  184. package/payload/server/public/assets/{diagram-TYMM5635-BS0eYiq9.js → diagram-TYMM5635-C8705_ZE.js} +1 -1
  185. package/payload/server/public/assets/{erDiagram-SMLLAGMA-VEQyXCFl.js → erDiagram-SMLLAGMA-Bkhe0ZPv.js} +1 -1
  186. package/payload/server/public/assets/{file-download-C3pBZjt9.js → file-download-DVUMxBgB.js} +1 -1
  187. package/payload/server/public/assets/{flowDiagram-DWJPFMVM-2NYMfqHX.js → flowDiagram-DWJPFMVM-rQKH0HF0.js} +1 -1
  188. package/payload/server/public/assets/{ganttDiagram-T4ZO3ILL-AAAa2sqE.js → ganttDiagram-T4ZO3ILL-C3oSBbAe.js} +1 -1
  189. package/payload/server/public/assets/{gitGraphDiagram-UUTBAWPF-d8NUAIz5.js → gitGraphDiagram-UUTBAWPF-28GEOzIR.js} +1 -1
  190. package/payload/server/public/assets/{graph-Bx9_2qbJ.js → graph-B5R9qDya.js} +1 -1
  191. package/payload/server/public/assets/{graph-labels-Cc1nU1_f.js → graph-labels-Bcq_R9X9.js} +1 -1
  192. package/payload/server/public/assets/{graphlib-DUlqr2mr.js → graphlib-DhAwTSya.js} +1 -1
  193. package/payload/server/public/assets/{infoDiagram-42DDH7IO-D4dh4-0g.js → infoDiagram-42DDH7IO-DnSzN29F.js} +1 -1
  194. package/payload/server/public/assets/{ishikawaDiagram-UXIWVN3A-DPTmm2IE.js → ishikawaDiagram-UXIWVN3A-B0mYhBS0.js} +1 -1
  195. package/payload/server/public/assets/{journeyDiagram-VCZTEJTY-B85vjqkE.js → journeyDiagram-VCZTEJTY-CIcZskca.js} +1 -1
  196. package/payload/server/public/assets/{jsx-runtime-D3PZpOAF.css → jsx-runtime-DqAwfhuD.css} +1 -1
  197. package/payload/server/public/assets/{kanban-definition-6JOO6SKY-C2Lfb5Xh.js → kanban-definition-6JOO6SKY-DWEpWX0D.js} +1 -1
  198. package/payload/server/public/assets/{line-CODKFpwO.js → line-D6evlE4c.js} +1 -1
  199. package/payload/server/public/assets/{mermaid-parser.core-DYdFZnXH.js → mermaid-parser.core-DyRhDebz.js} +1 -1
  200. package/payload/server/public/assets/{mermaid.core-Bamjzahu.js → mermaid.core-DaD391Xr.js} +3 -3
  201. package/payload/server/public/assets/{mindmap-definition-QFDTVHPH-CLK90bKJ.js → mindmap-definition-QFDTVHPH-D7IMib-k.js} +1 -1
  202. package/payload/server/public/assets/{pieDiagram-DEJITSTG-DEsnxhqP.js → pieDiagram-DEJITSTG-CyOSJozN.js} +1 -1
  203. package/payload/server/public/assets/{public-BFMu-jux.js → public-Cj7vjoG1.js} +5 -5
  204. package/payload/server/public/assets/{quadrantDiagram-34T5L4WZ-uIP9V2jZ.js → quadrantDiagram-34T5L4WZ-CHWWRW-7.js} +1 -1
  205. package/payload/server/public/assets/{requirementDiagram-MS252O5E-CVS6t5tv.js → requirementDiagram-MS252O5E-x4-mHKrQ.js} +1 -1
  206. package/payload/server/public/assets/{sankeyDiagram-XADWPNL6-BIsmtyZA.js → sankeyDiagram-XADWPNL6-DvKrAe78.js} +1 -1
  207. package/payload/server/public/assets/{sequenceDiagram-FGHM5R23-Cu8TfQiW.js → sequenceDiagram-FGHM5R23-DW778VnP.js} +1 -1
  208. package/payload/server/public/assets/{stateDiagram-FHFEXIEX-ax4vYGft.js → stateDiagram-FHFEXIEX-DVnPPuE8.js} +1 -1
  209. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-B3nWH_hq.js +1 -0
  210. package/payload/server/public/assets/{timeline-definition-GMOUNBTQ-3l7ojkMA.js → timeline-definition-GMOUNBTQ-CO4Sp85K.js} +1 -1
  211. package/payload/server/public/assets/{useSelectionMode-C_EBRd2k.js → useSelectionMode-BK4pznA6.js} +1 -1
  212. package/payload/server/public/assets/{vennDiagram-DHZGUBPP-C_sv0qMD.js → vennDiagram-DHZGUBPP-OCcztoT8.js} +1 -1
  213. package/payload/server/public/assets/{wardleyDiagram-NUSXRM2D-C7u4IHMB.js → wardleyDiagram-NUSXRM2D-C_1o3jux.js} +1 -1
  214. package/payload/server/public/assets/{xychartDiagram-5P7HB3ND-A-uLXr1a.js → xychartDiagram-5P7HB3ND-BPJxl9U1.js} +1 -1
  215. package/payload/server/public/browser.html +6 -6
  216. package/payload/server/public/chat.html +8 -8
  217. package/payload/server/public/data.html +5 -5
  218. package/payload/server/public/graph.html +8 -8
  219. package/payload/server/public/index.html +8 -8
  220. package/payload/server/public/public.html +6 -6
  221. package/payload/server/public/whatsapp-wallpaper.webp +0 -0
  222. package/payload/server/server.js +6 -2
  223. package/payload/server/public/assets/AdminShell-DDieHnzi.js +0 -1
  224. package/payload/server/public/assets/channel-drVqp11B.js +0 -1
  225. package/payload/server/public/assets/chat-DeEYwIKE.js +0 -1
  226. package/payload/server/public/assets/classDiagram-6PBFFD2Q-Dplkw_pj.js +0 -1
  227. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-sJXv1Ihp.js +0 -1
  228. package/payload/server/public/assets/clone-Q_B6oO0c.js +0 -1
  229. package/payload/server/public/assets/data-CYyR2m_B.js +0 -1
  230. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-BRv1By5g.js +0 -1
  231. /package/payload/server/public/assets/{jsx-runtime-5auA0FEj.js → jsx-runtime-CynkhuPm.js} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rubytech/create-maxy-code",
3
- "version": "0.1.295",
3
+ "version": "0.1.297",
4
4
  "description": "Install Maxy — AI for Productive People",
5
5
  "bin": {
6
6
  "create-maxy-code": "./dist/index.js"
@@ -1,3 +1,4 @@
1
+ export declare const FABLE_MODEL = "claude-fable-5[1m]";
1
2
  export declare const OPUS_MODEL = "claude-opus-4-8[1m]";
2
3
  export declare const SONNET_MODEL = "claude-sonnet-4-6";
3
4
  export declare const HAIKU_MODEL = "claude-haiku-4-5";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,UAAU,wBAAwB,CAAC;AAChD,eAAO,MAAM,YAAY,sBAAsB,CAAC;AAChD,eAAO,MAAM,WAAW,qBAAqB,CAAC;AAE9C,eAAO,MAAM,oBAAoB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAIvD,CAAC;AAEF,wEAAwE;AACxE,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEnD"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,WAAW,uBAAuB,CAAC;AAChD,eAAO,MAAM,UAAU,wBAAwB,CAAC;AAChD,eAAO,MAAM,YAAY,sBAAsB,CAAC;AAChD,eAAO,MAAM,WAAW,qBAAqB,CAAC;AAE9C,eAAO,MAAM,oBAAoB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAKvD,CAAC;AAEF,wEAAwE;AACxE,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEnD"}
@@ -3,15 +3,17 @@
3
3
  // Templates, docs, and skills reference these values as strings;
4
4
  // all TypeScript consumers import from here.
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.MODEL_CONTEXT_WINDOW = exports.HAIKU_MODEL = exports.SONNET_MODEL = exports.OPUS_MODEL = void 0;
6
+ exports.MODEL_CONTEXT_WINDOW = exports.HAIKU_MODEL = exports.SONNET_MODEL = exports.OPUS_MODEL = exports.FABLE_MODEL = void 0;
7
7
  exports.contextWindow = contextWindow;
8
- // Opus defaults to the 1M-context variant ([1m] is Claude Code's
8
+ // Fable and Opus default to the 1M-context variant ([1m] is Claude Code's
9
9
  // context-extension suffix, valid in settings.json "model" and agent
10
10
  // frontmatter); Sonnet/Haiku stay on the standard 200k window.
11
+ exports.FABLE_MODEL = "claude-fable-5[1m]";
11
12
  exports.OPUS_MODEL = "claude-opus-4-8[1m]";
12
13
  exports.SONNET_MODEL = "claude-sonnet-4-6";
13
14
  exports.HAIKU_MODEL = "claude-haiku-4-5";
14
15
  exports.MODEL_CONTEXT_WINDOW = {
16
+ [exports.FABLE_MODEL]: 1_000_000,
15
17
  [exports.OPUS_MODEL]: 1_000_000,
16
18
  [exports.SONNET_MODEL]: 200_000,
17
19
  [exports.HAIKU_MODEL]: 200_000,
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA,0DAA0D;AAC1D,iEAAiE;AACjE,6CAA6C;;;AAgB7C,sCAEC;AAhBD,iEAAiE;AACjE,qEAAqE;AACrE,+DAA+D;AAClD,QAAA,UAAU,GAAG,qBAAqB,CAAC;AACnC,QAAA,YAAY,GAAG,mBAAmB,CAAC;AACnC,QAAA,WAAW,GAAG,kBAAkB,CAAC;AAEjC,QAAA,oBAAoB,GAA2B;IAC1D,CAAC,kBAAU,CAAC,EAAE,SAAS;IACvB,CAAC,oBAAY,CAAC,EAAE,OAAO;IACvB,CAAC,mBAAW,CAAC,EAAE,OAAO;CACvB,CAAC;AAEF,wEAAwE;AACxE,SAAgB,aAAa,CAAC,KAAa;IACzC,OAAO,4BAAoB,CAAC,KAAK,CAAC,IAAI,OAAO,CAAC;AAChD,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA,0DAA0D;AAC1D,iEAAiE;AACjE,6CAA6C;;;AAkB7C,sCAEC;AAlBD,0EAA0E;AAC1E,qEAAqE;AACrE,+DAA+D;AAClD,QAAA,WAAW,GAAG,oBAAoB,CAAC;AACnC,QAAA,UAAU,GAAG,qBAAqB,CAAC;AACnC,QAAA,YAAY,GAAG,mBAAmB,CAAC;AACnC,QAAA,WAAW,GAAG,kBAAkB,CAAC;AAEjC,QAAA,oBAAoB,GAA2B;IAC1D,CAAC,mBAAW,CAAC,EAAE,SAAS;IACxB,CAAC,kBAAU,CAAC,EAAE,SAAS;IACvB,CAAC,oBAAY,CAAC,EAAE,OAAO;IACvB,CAAC,mBAAW,CAAC,EAAE,OAAO;CACvB,CAAC;AAEF,wEAAwE;AACxE,SAAgB,aAAa,CAAC,KAAa;IACzC,OAAO,4BAAoB,CAAC,KAAK,CAAC,IAAI,OAAO,CAAC;AAChD,CAAC"}
@@ -2,14 +2,16 @@
2
2
  // Templates, docs, and skills reference these values as strings;
3
3
  // all TypeScript consumers import from here.
4
4
 
5
- // Opus defaults to the 1M-context variant ([1m] is Claude Code's
5
+ // Fable and Opus default to the 1M-context variant ([1m] is Claude Code's
6
6
  // context-extension suffix, valid in settings.json "model" and agent
7
7
  // frontmatter); Sonnet/Haiku stay on the standard 200k window.
8
+ export const FABLE_MODEL = "claude-fable-5[1m]";
8
9
  export const OPUS_MODEL = "claude-opus-4-8[1m]";
9
10
  export const SONNET_MODEL = "claude-sonnet-4-6";
10
11
  export const HAIKU_MODEL = "claude-haiku-4-5";
11
12
 
12
13
  export const MODEL_CONTEXT_WINDOW: Record<string, number> = {
14
+ [FABLE_MODEL]: 1_000_000,
13
15
  [OPUS_MODEL]: 1_000_000,
14
16
  [SONNET_MODEL]: 200_000,
15
17
  [HAIKU_MODEL]: 200_000,
@@ -1409,8 +1409,16 @@ OPTIONS {
1409
1409
  }
1410
1410
  };
1411
1411
 
1412
- CREATE CONSTRAINT inbound_invoice_account_supplier_num_unique IF NOT EXISTS
1413
- FOR (ii:InboundInvoice) REQUIRE (ii.accountId, ii.supplier, ii.invoiceNumber) IS UNIQUE;
1412
+ // Task 802 renamed the key property invoiceNumber -> confirmationNumber
1413
+ // (Schema.org canonical). The constraint gets a NEW name because
1414
+ // CREATE ... IF NOT EXISTS matches by constraint name: re-using the old
1415
+ // name would silently skip creation on databases seeded before the rename,
1416
+ // leaving the key unprotected. The old-name DROP retires the stale
1417
+ // invoiceNumber constraint on those databases; both statements are
1418
+ // idempotent on fresh installs.
1419
+ DROP CONSTRAINT inbound_invoice_account_supplier_num_unique IF EXISTS;
1420
+ CREATE CONSTRAINT inbound_invoice_account_supplier_confirmation_unique IF NOT EXISTS
1421
+ FOR (ii:InboundInvoice) REQUIRE (ii.accountId, ii.supplier, ii.confirmationNumber) IS UNIQUE;
1414
1422
 
1415
1423
  CREATE INDEX inbound_invoice_account IF NOT EXISTS
1416
1424
  FOR (ii:InboundInvoice) ON (ii.accountId);
@@ -10,8 +10,12 @@
10
10
  "type": "stdio",
11
11
  "command": "node",
12
12
  "args": [
13
+ "${CLAUDE_PLUGIN_ROOT}/lib/mcp-spawn-tee/index.js",
13
14
  "${CLAUDE_PLUGIN_ROOT}/mcp/dist/index.js"
14
- ]
15
+ ],
16
+ "env": {
17
+ "MCP_SPAWN_TEE_NAME": "admin"
18
+ }
15
19
  }
16
20
  }
17
21
  }
@@ -45,6 +45,17 @@ ASSISTANT_REPLY='{"type":"assistant","message":{"role":"assistant","content":[{"
45
45
  ASSISTANT_REPLYDOC='{"type":"assistant","message":{"role":"assistant","content":[{"type":"tool_use","name":"mcp__whatsapp-channel__reply-document","input":{}}]}}'
46
46
  ASSISTANT_SKILLLOAD='{"type":"assistant","message":{"role":"assistant","content":[{"type":"tool_use","name":"mcp__admin__skill-load","input":{}}]}}'
47
47
  ASSISTANT_TASK='{"type":"assistant","message":{"role":"assistant","content":[{"type":"tool_use","name":"Task","input":{}}]}}'
48
+ ASSISTANT_BASH='{"type":"assistant","message":{"role":"assistant","content":[{"type":"tool_use","name":"Bash","input":{}}]}}'
49
+ ASSISTANT_WRITE='{"type":"assistant","message":{"role":"assistant","content":[{"type":"tool_use","name":"Write","input":{}}]}}'
50
+ # Task 805 — a production-shape reframe turn: channel-wrapped, isMeta, carrying
51
+ # the composeAdminContent ## Context / ## Instruction sections. No directive
52
+ # marker row accompanies it (the directive hook suppresses itself on channel
53
+ # turns, Task 753), so the reframe itself must count as directive-equivalent.
54
+ CHANNEL_REFRAME='{"type":"user","isMeta":true,"message":{"role":"user","content":"<channel source=\"whatsapp-channel\">## Context\nplease draft the works order PDF for order 926\n\n## Instruction\nChoose the installed specialist that owns this request and dispatch it with the Agent tool.</channel>"}}'
55
+ # Same shape, one-word Context payload — the trivial filter must read the
56
+ # payload, not the wrapper (the always-present instruction text would otherwise
57
+ # make every reframed turn look non-trivial).
58
+ CHANNEL_REFRAME_TRIVIAL='{"type":"user","isMeta":true,"message":{"role":"user","content":"<channel source=\"whatsapp-channel\">## Context\nyes\n\n## Instruction\nChoose the installed specialist that owns this request and dispatch it with the Agent tool.</channel>"}}'
48
59
 
49
60
  assert_flagged() {
50
61
  local name="$1" t="$2" out
@@ -147,6 +158,22 @@ assert_not_flagged "route then isMeta injections -> not flagged (slice not trunc
147
158
  assert_not_flagged "slash prompt then isMeta skill body -> not flagged" \
148
159
  "$(mk_transcript '{"type":"user","message":{"role":"user","content":"/insight"}}' "$DIRECTIVE_ATTACH" "$ASSISTANT_TEXT" "$META_SKILL")"
149
160
 
161
+ # 16. Task 805 — reframed channel turn, no marker row, inline authoring tools
162
+ # (the e48c2a5e freestyle shape) -> flagged. The reframe IS the directive.
163
+ assert_flagged "reframe turn + inline authoring, no marker -> flagged" \
164
+ "$(mk_transcript "$CHANNEL_REFRAME" "$ASSISTANT_REPLY" "$ASSISTANT_BASH" "$ASSISTANT_WRITE")"
165
+ # 17. Same reframed turn with an Agent dispatch -> not flagged.
166
+ assert_not_flagged "reframe turn + Agent dispatch -> not flagged" \
167
+ "$(mk_transcript "$CHANNEL_REFRAME" "$ASSISTANT_REPLY" "$ASSISTANT_AGENT")"
168
+ # 18. Reframed turn whose Context payload is one word -> trivial, not flagged,
169
+ # even though the wrapper text is long.
170
+ assert_not_flagged "reframe turn with one-word Context payload -> not flagged (trivial)" \
171
+ "$(mk_transcript "$CHANNEL_REFRAME_TRIVIAL" "$ASSISTANT_TEXT")"
172
+ # 19. Channel-wrapped NON-reframe turn (no ## Instruction section — webchat
173
+ # today, Task 776) with no marker -> not directive-equivalent, not flagged.
174
+ assert_not_flagged "channel-wrapped non-reframe turn, no marker -> not flagged" \
175
+ "$(mk_transcript "$CHANNEL_PROMPT" "$ASSISTANT_TEXT")"
176
+
150
177
  # 11. Fail-open: missing transcript_path -> exit 0, no output.
151
178
  fo_out=$(printf '{"session_id":"x"}' | bash "$HOOK" 2>&1); fo_exit=$?
152
179
  if [[ "$fo_exit" -eq 0 && -z "$fo_out" ]]; then
@@ -11,7 +11,10 @@
11
11
  # slice (robust to CC-version differences in how the
12
12
  # UserPromptSubmit additionalContext is recorded: a
13
13
  # type:"attachment"/hook_success on 2.1.x, a
14
- # type:"hook_additional_context" on the Pi).
14
+ # type:"hook_additional_context" on the Pi), OR the prompt is
15
+ # a <channel>-wrapped reframe turn (## Context/## Instruction
16
+ # sections, Task 805) — the directive hook suppresses itself
17
+ # on channel turns, so the reframe is directive-equivalent.
15
18
  # route taken = the turn contains a tool_use that is a genuine route:
16
19
  # Agent/Task dispatch, native Skill, or a *__skill-load MCP
17
20
  # tool. ToolSearch (a schema load) and the channel transport
@@ -126,23 +129,39 @@ if boundary is None:
126
129
 
127
130
  slice_rows = rows[boundary:]
128
131
 
129
- # Strip a leading <channel ...>...</channel> wrapper to reach the inner prompt for
130
- # the trivial check (WhatsApp/native-channel prompts arrive wrapped).
132
+ # Strip a leading <channel ...>...</channel> wrapper to reach the inner prompt
133
+ # (WhatsApp/native-channel prompts arrive wrapped).
131
134
  inner = prompt_text
135
+ is_channel = False
132
136
  if inner.startswith("<channel"):
133
137
  end = inner.find(">")
134
138
  close = inner.rfind("</channel>")
135
139
  if end != -1 and close != -1 and close > end:
136
140
  inner = inner[end + 1:close].strip()
141
+ is_channel = True
142
+
143
+ # Task 805 — a channel-wrapped reframe turn (the ## Context / ## Instruction
144
+ # sections of composeAdminContent) is directive-equivalent: the directive hook suppresses
145
+ # itself on channel turns (Task 753), so the reframe is the only routing
146
+ # instruction the turn carries, and the marker check alone left every channel
147
+ # turn unevaluated. A channel-wrapped turn WITHOUT the reframe (webchat today,
148
+ # Task 776) is not directive-equivalent. For the trivial check the prompt is the
149
+ # Context payload, not the wrapper — the always-present instruction text would
150
+ # otherwise make a one-word confirmation look non-trivial.
151
+ is_reframe = is_channel and inner.startswith("## Context\n") and "\n## Instruction\n" in inner
152
+ if is_reframe:
153
+ head, _, _rest = inner.partition("\n## Instruction\n")
154
+ inner = head[len("## Context"):].strip()
137
155
 
138
156
  # Trivial-turn filter.
139
157
  is_slash = inner.startswith("/")
140
158
  tokens = inner.split()
141
159
  is_one_word = len(tokens) <= 1
142
160
 
143
- # Directive fired = marker present anywhere in the slice (any record shape).
161
+ # Directive fired = marker present anywhere in the slice (any record shape) OR
162
+ # the prompt is a channel-wrapped reframe turn (Task 805).
144
163
  marker = "PROMPT-OPTIMISER DIRECTIVE"
145
- directive_fired = any(marker in json.dumps(r, ensure_ascii=False) for r in slice_rows)
164
+ directive_fired = is_reframe or any(marker in json.dumps(r, ensure_ascii=False) for r in slice_rows)
146
165
 
147
166
  # Route taken = an assistant tool_use that is a genuine route: specialist
148
167
  # dispatch (Agent/Task) or skill load (native Skill, or the *__skill-load MCP
@@ -0,0 +1,159 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ /**
4
+ * MCP spawn-tee — parent-side stderr capture + lifecycle observability.
5
+ *
6
+ * Claude Code spawns each MCP server itself; the platform never holds a
7
+ * ChildProcess handle. This wrapper sits between Claude Code and the real
8
+ * MCP server: Claude Code runs `node <this> <real-entry>`, and the wrapper
9
+ * spawns the real entry with `stdio:['inherit','inherit','pipe']` so stdin
10
+ * and stdout (the JSON-RPC channel) pass through byte-identical. Only stderr
11
+ * is intercepted, and only for logging.
12
+ *
13
+ * Because the wrapper IS the helper's parent, it observes the helper's true
14
+ * exit code, signal, and lifetime for every death mode — including a SIGKILL
15
+ * or a transport-layer crash that an in-process handler would miss.
16
+ *
17
+ * Claude Code CLI → wrapper (this file) → child = node <real-entry>
18
+ * child stdin/stdout : inherited (Claude Code pipe, untouched)
19
+ * child stderr : piped → per-date log + per-session log + passthrough
20
+ *
21
+ * Destinations (Task 706):
22
+ * - `${LOG_DIR}/mcp-<name>-stderr-<date>.log` — per-date raw (back-compat;
23
+ * the in-process mcp-stderr-tee and the [mcp-init-error] probe read it).
24
+ * - `${LOG_DIR}/mcp-<name>-<SESSION_ID>.log` — per-session raw + lifecycle
25
+ * lines; wrapper-only, so it never mixes the enumeration copy with the
26
+ * live copy. Authoritative sink. Absent when SESSION_ID is unset
27
+ * (enumeration spawn) — then the per-date file is the fallback.
28
+ * - `server.log` via the loopback log-ingest route — best-effort mirror of
29
+ * the [mcp-helper] lifecycle lines. A dropped POST loses nothing because
30
+ * the per-session file already holds the line (written synchronously).
31
+ *
32
+ * Lifecycle lines, correlation key `session=<id8> server=<name>`:
33
+ * [mcp-helper] op=spawn ... pid= entry=
34
+ * [mcp-helper] op=boot ... head=<first stderr bytes>
35
+ * [mcp-helper] op=exit ... code= signal= lifetimeMs= stderr-tail= (always)
36
+ *
37
+ * The wrapper never writes to fd 1 (stdout) — that is the JSON-RPC channel.
38
+ * SIGTERM/SIGINT are forwarded to the child so a Claude Code shutdown does
39
+ * not orphan it; the child exit code/signal is propagated verbatim.
40
+ */
41
+ Object.defineProperty(exports, "__esModule", { value: true });
42
+ const node_child_process_1 = require("node:child_process");
43
+ const node_fs_1 = require("node:fs");
44
+ const node_path_1 = require("node:path");
45
+ const SERVER_NAME = process.env.MCP_SPAWN_TEE_NAME ?? "unknown";
46
+ const LOG_DIR = process.env.LOG_DIR;
47
+ const SESSION_ID = process.env.SESSION_ID;
48
+ const PLATFORM_PORT = process.env.PLATFORM_PORT;
49
+ const ENTRY = process.argv[2];
50
+ const SESSION_ID8 = SESSION_ID ? SESSION_ID.slice(0, 8) : "—";
51
+ const spawnStamp = Date.now();
52
+ // Per-session raw + lifecycle log (Task 706). Wrapper-only. Empty SESSION_ID
53
+ // (enumeration spawn) → undefined, and the per-date file is the fallback.
54
+ const perSessionPath = LOG_DIR && SESSION_ID
55
+ ? (0, node_path_1.resolve)(LOG_DIR, `mcp-${SERVER_NAME}-${SESSION_ID}.log`)
56
+ : undefined;
57
+ const perDatePath = LOG_DIR
58
+ ? (0, node_path_1.resolve)(LOG_DIR, `mcp-${SERVER_NAME}-stderr-${new Date(spawnStamp).toISOString().slice(0, 10)}.log`)
59
+ : undefined;
60
+ // Rolling tail of child stderr for op=exit. Capped so a chatty child cannot
61
+ // grow the buffer without bound.
62
+ const TAIL_CAP = 2048;
63
+ let stderrTail = "";
64
+ let bootEmitted = false;
65
+ function appendSafe(path, data) {
66
+ if (!path || !LOG_DIR)
67
+ return;
68
+ try {
69
+ (0, node_fs_1.mkdirSync)(LOG_DIR, { recursive: true });
70
+ (0, node_fs_1.appendFileSync)(path, data);
71
+ }
72
+ catch {
73
+ /* unwritable destination — never mask primary output */
74
+ }
75
+ }
76
+ // Best-effort mirror of a lifecycle line to server.log via the loopback
77
+ // log-ingest route. Fire-and-forget: the per-session file is authoritative,
78
+ // so a dropped POST (unreachable port, process exiting) loses nothing.
79
+ function postToServerLog(suffix, level) {
80
+ if (!PLATFORM_PORT)
81
+ return;
82
+ try {
83
+ const ctrl = new AbortController();
84
+ const t = setTimeout(() => ctrl.abort(), 500);
85
+ t.unref?.(); // never let the abort timer keep the wrapper's event loop alive
86
+ void fetch(`http://127.0.0.1:${PLATFORM_PORT}/api/admin/log-ingest`, {
87
+ method: "POST",
88
+ headers: { "content-type": "application/json" },
89
+ body: JSON.stringify({ tag: "mcp-helper", level, line: suffix }),
90
+ signal: ctrl.signal,
91
+ }).then(() => clearTimeout(t)).catch(() => clearTimeout(t));
92
+ }
93
+ catch {
94
+ /* fetch threw synchronously — best-effort only */
95
+ }
96
+ }
97
+ // Emit one [mcp-helper] lifecycle line: authoritative per-session file (sync,
98
+ // survives process.exit), the wrapper's own stderr (journald / Claude Code
99
+ // visibility), and a best-effort server.log mirror. `suffix` is the line body
100
+ // after the tag and carries no newline (the log-ingest route rejects newlines).
101
+ function emitLifecycle(suffix, level) {
102
+ const line = `[mcp-helper] ${suffix}\n`;
103
+ appendSafe(perSessionPath, line);
104
+ try {
105
+ process.stderr.write(line);
106
+ }
107
+ catch { /* stderr closed */ }
108
+ postToServerLog(suffix, level);
109
+ }
110
+ if (!ENTRY) {
111
+ emitLifecycle(`op=error session=${SESSION_ID8} server=${SERVER_NAME} reason="no entry given (argv[2] missing)"`, "error");
112
+ process.exit(2);
113
+ }
114
+ const child = (0, node_child_process_1.spawn)(process.execPath, [ENTRY], {
115
+ stdio: ["inherit", "inherit", "pipe"],
116
+ env: process.env,
117
+ });
118
+ emitLifecycle(`op=spawn session=${SESSION_ID8} server=${SERVER_NAME} pid=${child.pid ?? -1} entry=${ENTRY}`, "info");
119
+ child.on("error", (err) => {
120
+ const msg = err instanceof Error ? err.message : String(err);
121
+ emitLifecycle(`op=error session=${SESSION_ID8} server=${SERVER_NAME} reason=${JSON.stringify(`spawn error: ${msg}`)}`, "error");
122
+ process.exit(127);
123
+ });
124
+ if (child.stderr) {
125
+ child.stderr.on("data", (chunk) => {
126
+ appendSafe(perDatePath, chunk); // per-date raw (back-compat)
127
+ appendSafe(perSessionPath, chunk); // per-session raw (Task 706)
128
+ try {
129
+ process.stderr.write(chunk);
130
+ }
131
+ catch { /* stderr closed */ } // passthrough
132
+ stderrTail = (stderrTail + chunk.toString("utf8")).slice(-TAIL_CAP);
133
+ if (!bootEmitted) {
134
+ bootEmitted = true;
135
+ const head = chunk.toString("utf8").split("\n")[0].slice(0, 200);
136
+ emitLifecycle(`op=boot session=${SESSION_ID8} server=${SERVER_NAME} head=${JSON.stringify(head)}`, "info");
137
+ }
138
+ });
139
+ }
140
+ const forward = (signal) => { if (!child.killed)
141
+ child.kill(signal); };
142
+ process.on("SIGTERM", () => forward("SIGTERM"));
143
+ process.on("SIGINT", () => forward("SIGINT"));
144
+ // Signal → number, so a signal-killed child propagates as 128+signum (the
145
+ // shell convention). `code` is null on a signal exit, so `128 + (code ?? 0)`
146
+ // would collapse every signal to 128 and lose the signal identity in the
147
+ // wrapper's own exit status.
148
+ const SIGNUM = { SIGHUP: 1, SIGINT: 2, SIGQUIT: 3, SIGKILL: 9, SIGTERM: 15 };
149
+ child.on("exit", (code, signal) => {
150
+ const lifetimeMs = Date.now() - spawnStamp;
151
+ const tail = stderrTail.slice(-200);
152
+ const level = signal || (code ?? 0) !== 0 ? "error" : "info";
153
+ emitLifecycle(`op=exit session=${SESSION_ID8} server=${SERVER_NAME} pid=${child.pid ?? -1} ` +
154
+ `code=${code ?? "—"} signal=${signal ?? "—"} lifetimeMs=${lifetimeMs} stderr-tail=${JSON.stringify(tail)}`, level);
155
+ if (signal)
156
+ process.exit(128 + (SIGNUM[signal] ?? 0));
157
+ process.exit(code ?? 0);
158
+ });
159
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,3 @@
1
+ {
2
+ "type": "commonjs"
3
+ }
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: platform-architecture
3
3
  description: Use when grounding any documented-surface claim about what Maxy ships — plugins, skills, specialists, install/deploy flows, internals. This is the install catalogue, not evidence of what is enabled on the current account. For install state on this account, call `capabilities-here`; for documented surface, cite the `Source:` URL inline.
4
- content-hash: sha256:c39a9e28304fa49a4afee3aabc0507872065d868994c9ab14d56b2576f4ce636
4
+ content-hash: sha256:e5c0c490243571baf0b7414b4e9a9f4806d3730b7f12829e9c7ed16c9445ed43
5
5
  brand: maxy-code
6
6
  product-name: Maxy
7
7
  ---
@@ -87,7 +87,7 @@ When the text field is empty, a microphone button appears in place of the send b
87
87
 
88
88
  Voice recording requires a secure connection (HTTPS). When accessing Maxy over the local network via HTTP, use the tunnel URL for voice notes.
89
89
 
90
- You can also drop, paste, or pick an audio file (`.opus`, `.ogg`, `.m4a`, `.mp3`, `.wav`, `.webm`) into the chat composer — for example a voice note forwarded from WhatsApp. The file is transcribed the same way the in-browser recording is, and only the transcript reaches Maxy; the audio itself is discarded after transcription.
90
+ You can also drop, paste, or pick an audio file (`.opus`, `.ogg`, `.m4a`, `.mp3`, `.wav`, `.webm`) into the chat composer — for example a voice note forwarded from WhatsApp. The file is transcribed the same way the in-browser recording is, and only the transcript reaches Maxy; the audio itself is discarded after transcription. If you type a message and attach an audio file on the same send, both arrive — the transcript follows your typed text.
91
91
 
92
92
  ## What Maxy Remembers
93
93
 
@@ -145,7 +145,7 @@ Everything Maxy can do is provided by a plugin. Each plugin is a self-contained
145
145
 
146
146
  **How tools and roles reach the session.** Each `claude` PTY spawn registers every plugin's MCP server and every bundled subagent directory before the operator's first turn — a per-spawn `mcp-config.json` written by the session manager and passed as `--mcp-config` on the PTY argv, plus one `--add-dir` per agents directory. Admin sessions see every plugin and every role; public sessions see only plugins with at least one public-allowlisted tool. The manager refuses to start when a plugin's `PLUGIN.md` declares tools without a matching `mcp:` block (forensic signal: `boot-failed reason=mcp-allowlist-without-server …`). See `internals.md` "Spawn-time MCP and subagent registration" for the full mechanism and `internals.md` "Tool Eagerness" for the separate ToolSearch-vs-eager registration concern.
147
147
 
148
- **MCP helper death observability (Task 706).** `claude` spawns each plugin MCP helper as its own child, so the manager cannot see a helper die. Every spawn-capable plugin therefore wraps its `mcp:` command with `lib/mcp-spawn-tee`, a parent-side node wrapper that is the helper's real parent and observes its true exit code, signal, and lifetime (including SIGKILL / transport crashes). The wrapper tees the helper's stderr to a wrapper-only per-session file `~/.{brand}/logs/mcp-<server>-<sessionId>.log` — never mixed with the admin-server enumeration copy — and emits lifecycle lines keyed `session=<id8> server=<name>`: `[mcp-helper] op=spawn … pid= entry=`, `[mcp-helper] op=boot … head=<first stderr bytes>`, and `[mcp-helper] op=exit … code= signal= lifetimeMs= stderr-tail=` on every exit (including a clean one). Lines are written synchronously to the per-session file and best-effort mirrored to `server.log` via the loopback log-ingest route. Diagnose a dead helper by `grep '\[mcp-helper\]' ~/.{brand}/logs/server.log` filtered by `session=<id8>`, then read the per-session file for its last output. Full contract and diagnostic path in [`.docs/mcp-helper-observability.md`](../../../.docs/mcp-helper-observability.md). The alive-but-wedged case (no process exit) is the deferred `[mcp-helper-census]` reconciler (Task 710).
148
+ **MCP helper death observability (Task 706).** `claude` spawns each plugin MCP helper as its own child, so the manager cannot see a helper die. Every spawn-capable plugin therefore wraps its `mcp:` command with `lib/mcp-spawn-tee`, a parent-side node wrapper that is the helper's real parent and observes its true exit code, signal, and lifetime (including SIGKILL / transport crashes). The wrapper tees the helper's stderr to a wrapper-only per-session file `~/.{brand}/logs/mcp-<server>-<sessionId>.log` — never mixed with the admin-server enumeration copy — and emits lifecycle lines keyed `session=<id8> server=<name>`: `[mcp-helper] op=spawn … pid= entry=`, `[mcp-helper] op=boot … head=<first stderr bytes>`, and `[mcp-helper] op=exit … code= signal= lifetimeMs= stderr-tail=` on every exit (including a clean one). Lines are written synchronously to the per-session file and best-effort mirrored to `server.log` via the loopback log-ingest route. Diagnose a dead helper by `grep '\[mcp-helper\]' ~/.{brand}/logs/server.log` filtered by `session=<id8>`, then read the per-session file for its last output. Both spawn paths are wrapped: the manager's per-spawn `.mcp.json` (Task 706) and the generated `.claude-plugin/plugin.json` manifests that channel sessions take helpers from (Task 807) — the manifest generator copies the tee into each `mcp-manifest: auto` plugin at `lib/mcp-spawn-tee/index.js`, because the plugin-install cache snapshot severs `${PLATFORM_ROOT}`-relative paths, and a missing tee dist at generation time is FATAL. Full contract and diagnostic path in [`.docs/mcp-helper-observability.md`](../../../.docs/mcp-helper-observability.md). The alive-but-wedged case (no process exit) is the deferred `[mcp-helper-census]` reconciler (Task 710).
149
149
 
150
150
  **Where premium bundle subs live.** Bundle subs (`loop`, `property-data`, `brochures`, etc. inside `real-agent`) live exclusively at `premium-plugins/<bundle>/plugins/<sub>/` and are registered via the resolver's bundle-descent walk. Standalone premiums (no `BUNDLE.md`, e.g. `writer-craft`, `teaching`, `venture-studio`) live exclusively at `premium-plugins/<name>/` and are registered via the resolver's dual-root scan (`platform/plugins/` and `premium-plugins/` are both `pluginsRoots`). Neither shape is flat-copied into `platform/plugins/<name>/`. A divergent flat copy of a bundle sub is treated as an operator override: the resolver refuses to boot with `boot-failed reason=mcp-plugin-duplicate <plugin> declared by more than one plugins root: <pathA> (sha=…) vs <pathB> (sha=…)` so the operator can `sha256sum` both paths and remove the stale one. Byte-identical bundle-sub flat copies left over from installer versions that flat-copied bundle subs are reaped on the first post-upgrade boot (`[premium-auto-deliver] reaped sub=<name> reason=duplicate-of-premium-tree`). Standalone flat copies (leaked by the pre-fix `autoDeliverPremiumPlugins` standalone branch) are reaped unconditionally — there is no documented override path for standalones at `platform/plugins/<name>/` — and the reaper logs `[premium-auto-deliver] reaped standalone=<name> matches-source=<true|false>` so divergent reaps leave a forensic trail.
151
151
 
@@ -285,16 +285,6 @@ Both flows run on the native Claude Code PTY surface in admin chat (Task 287). T
285
285
 
286
286
  **Authorisation** is inherited from the same `canAccessAdmin()` gate that wraps every `/api/admin/*` route.
287
287
 
288
- ## AI Content Provenance
289
-
290
- When your public agent sends a message to someone — via email, WhatsApp, Telegram, or SMS — the platform automatically includes a brief disclosure that the content was generated by AI. This is transparent and cannot be turned off.
291
-
292
- - **Email:** an `X-AI-Generated` header and a footer line are added to every outbound email
293
- - **WhatsApp and Telegram:** a short line is appended to the message body
294
- - **SMS:** a brief suffix is appended when the message is AI-composed
295
-
296
- Messages you write yourself (e.g. typing directly in WhatsApp) are not marked — the disclosure applies only to content composed by the AI agent.
297
-
298
288
  ## Session Slot Safeguards
299
289
 
300
290
  Maxy runs each chat — yours and every visitor's — as a separate `claude` process on your Pi. Three safeguards keep these processes from piling up:
@@ -10,8 +10,12 @@
10
10
  "type": "stdio",
11
11
  "command": "node",
12
12
  "args": [
13
+ "${CLAUDE_PLUGIN_ROOT}/lib/mcp-spawn-tee/index.js",
13
14
  "${CLAUDE_PLUGIN_ROOT}/mcp/dist/index.js"
14
- ]
15
+ ],
16
+ "env": {
17
+ "MCP_SPAWN_TEE_NAME": "aeo"
18
+ }
15
19
  }
16
20
  }
17
21
  }
@@ -0,0 +1,159 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ /**
4
+ * MCP spawn-tee — parent-side stderr capture + lifecycle observability.
5
+ *
6
+ * Claude Code spawns each MCP server itself; the platform never holds a
7
+ * ChildProcess handle. This wrapper sits between Claude Code and the real
8
+ * MCP server: Claude Code runs `node <this> <real-entry>`, and the wrapper
9
+ * spawns the real entry with `stdio:['inherit','inherit','pipe']` so stdin
10
+ * and stdout (the JSON-RPC channel) pass through byte-identical. Only stderr
11
+ * is intercepted, and only for logging.
12
+ *
13
+ * Because the wrapper IS the helper's parent, it observes the helper's true
14
+ * exit code, signal, and lifetime for every death mode — including a SIGKILL
15
+ * or a transport-layer crash that an in-process handler would miss.
16
+ *
17
+ * Claude Code CLI → wrapper (this file) → child = node <real-entry>
18
+ * child stdin/stdout : inherited (Claude Code pipe, untouched)
19
+ * child stderr : piped → per-date log + per-session log + passthrough
20
+ *
21
+ * Destinations (Task 706):
22
+ * - `${LOG_DIR}/mcp-<name>-stderr-<date>.log` — per-date raw (back-compat;
23
+ * the in-process mcp-stderr-tee and the [mcp-init-error] probe read it).
24
+ * - `${LOG_DIR}/mcp-<name>-<SESSION_ID>.log` — per-session raw + lifecycle
25
+ * lines; wrapper-only, so it never mixes the enumeration copy with the
26
+ * live copy. Authoritative sink. Absent when SESSION_ID is unset
27
+ * (enumeration spawn) — then the per-date file is the fallback.
28
+ * - `server.log` via the loopback log-ingest route — best-effort mirror of
29
+ * the [mcp-helper] lifecycle lines. A dropped POST loses nothing because
30
+ * the per-session file already holds the line (written synchronously).
31
+ *
32
+ * Lifecycle lines, correlation key `session=<id8> server=<name>`:
33
+ * [mcp-helper] op=spawn ... pid= entry=
34
+ * [mcp-helper] op=boot ... head=<first stderr bytes>
35
+ * [mcp-helper] op=exit ... code= signal= lifetimeMs= stderr-tail= (always)
36
+ *
37
+ * The wrapper never writes to fd 1 (stdout) — that is the JSON-RPC channel.
38
+ * SIGTERM/SIGINT are forwarded to the child so a Claude Code shutdown does
39
+ * not orphan it; the child exit code/signal is propagated verbatim.
40
+ */
41
+ Object.defineProperty(exports, "__esModule", { value: true });
42
+ const node_child_process_1 = require("node:child_process");
43
+ const node_fs_1 = require("node:fs");
44
+ const node_path_1 = require("node:path");
45
+ const SERVER_NAME = process.env.MCP_SPAWN_TEE_NAME ?? "unknown";
46
+ const LOG_DIR = process.env.LOG_DIR;
47
+ const SESSION_ID = process.env.SESSION_ID;
48
+ const PLATFORM_PORT = process.env.PLATFORM_PORT;
49
+ const ENTRY = process.argv[2];
50
+ const SESSION_ID8 = SESSION_ID ? SESSION_ID.slice(0, 8) : "—";
51
+ const spawnStamp = Date.now();
52
+ // Per-session raw + lifecycle log (Task 706). Wrapper-only. Empty SESSION_ID
53
+ // (enumeration spawn) → undefined, and the per-date file is the fallback.
54
+ const perSessionPath = LOG_DIR && SESSION_ID
55
+ ? (0, node_path_1.resolve)(LOG_DIR, `mcp-${SERVER_NAME}-${SESSION_ID}.log`)
56
+ : undefined;
57
+ const perDatePath = LOG_DIR
58
+ ? (0, node_path_1.resolve)(LOG_DIR, `mcp-${SERVER_NAME}-stderr-${new Date(spawnStamp).toISOString().slice(0, 10)}.log`)
59
+ : undefined;
60
+ // Rolling tail of child stderr for op=exit. Capped so a chatty child cannot
61
+ // grow the buffer without bound.
62
+ const TAIL_CAP = 2048;
63
+ let stderrTail = "";
64
+ let bootEmitted = false;
65
+ function appendSafe(path, data) {
66
+ if (!path || !LOG_DIR)
67
+ return;
68
+ try {
69
+ (0, node_fs_1.mkdirSync)(LOG_DIR, { recursive: true });
70
+ (0, node_fs_1.appendFileSync)(path, data);
71
+ }
72
+ catch {
73
+ /* unwritable destination — never mask primary output */
74
+ }
75
+ }
76
+ // Best-effort mirror of a lifecycle line to server.log via the loopback
77
+ // log-ingest route. Fire-and-forget: the per-session file is authoritative,
78
+ // so a dropped POST (unreachable port, process exiting) loses nothing.
79
+ function postToServerLog(suffix, level) {
80
+ if (!PLATFORM_PORT)
81
+ return;
82
+ try {
83
+ const ctrl = new AbortController();
84
+ const t = setTimeout(() => ctrl.abort(), 500);
85
+ t.unref?.(); // never let the abort timer keep the wrapper's event loop alive
86
+ void fetch(`http://127.0.0.1:${PLATFORM_PORT}/api/admin/log-ingest`, {
87
+ method: "POST",
88
+ headers: { "content-type": "application/json" },
89
+ body: JSON.stringify({ tag: "mcp-helper", level, line: suffix }),
90
+ signal: ctrl.signal,
91
+ }).then(() => clearTimeout(t)).catch(() => clearTimeout(t));
92
+ }
93
+ catch {
94
+ /* fetch threw synchronously — best-effort only */
95
+ }
96
+ }
97
+ // Emit one [mcp-helper] lifecycle line: authoritative per-session file (sync,
98
+ // survives process.exit), the wrapper's own stderr (journald / Claude Code
99
+ // visibility), and a best-effort server.log mirror. `suffix` is the line body
100
+ // after the tag and carries no newline (the log-ingest route rejects newlines).
101
+ function emitLifecycle(suffix, level) {
102
+ const line = `[mcp-helper] ${suffix}\n`;
103
+ appendSafe(perSessionPath, line);
104
+ try {
105
+ process.stderr.write(line);
106
+ }
107
+ catch { /* stderr closed */ }
108
+ postToServerLog(suffix, level);
109
+ }
110
+ if (!ENTRY) {
111
+ emitLifecycle(`op=error session=${SESSION_ID8} server=${SERVER_NAME} reason="no entry given (argv[2] missing)"`, "error");
112
+ process.exit(2);
113
+ }
114
+ const child = (0, node_child_process_1.spawn)(process.execPath, [ENTRY], {
115
+ stdio: ["inherit", "inherit", "pipe"],
116
+ env: process.env,
117
+ });
118
+ emitLifecycle(`op=spawn session=${SESSION_ID8} server=${SERVER_NAME} pid=${child.pid ?? -1} entry=${ENTRY}`, "info");
119
+ child.on("error", (err) => {
120
+ const msg = err instanceof Error ? err.message : String(err);
121
+ emitLifecycle(`op=error session=${SESSION_ID8} server=${SERVER_NAME} reason=${JSON.stringify(`spawn error: ${msg}`)}`, "error");
122
+ process.exit(127);
123
+ });
124
+ if (child.stderr) {
125
+ child.stderr.on("data", (chunk) => {
126
+ appendSafe(perDatePath, chunk); // per-date raw (back-compat)
127
+ appendSafe(perSessionPath, chunk); // per-session raw (Task 706)
128
+ try {
129
+ process.stderr.write(chunk);
130
+ }
131
+ catch { /* stderr closed */ } // passthrough
132
+ stderrTail = (stderrTail + chunk.toString("utf8")).slice(-TAIL_CAP);
133
+ if (!bootEmitted) {
134
+ bootEmitted = true;
135
+ const head = chunk.toString("utf8").split("\n")[0].slice(0, 200);
136
+ emitLifecycle(`op=boot session=${SESSION_ID8} server=${SERVER_NAME} head=${JSON.stringify(head)}`, "info");
137
+ }
138
+ });
139
+ }
140
+ const forward = (signal) => { if (!child.killed)
141
+ child.kill(signal); };
142
+ process.on("SIGTERM", () => forward("SIGTERM"));
143
+ process.on("SIGINT", () => forward("SIGINT"));
144
+ // Signal → number, so a signal-killed child propagates as 128+signum (the
145
+ // shell convention). `code` is null on a signal exit, so `128 + (code ?? 0)`
146
+ // would collapse every signal to 128 and lose the signal identity in the
147
+ // wrapper's own exit status.
148
+ const SIGNUM = { SIGHUP: 1, SIGINT: 2, SIGQUIT: 3, SIGKILL: 9, SIGTERM: 15 };
149
+ child.on("exit", (code, signal) => {
150
+ const lifetimeMs = Date.now() - spawnStamp;
151
+ const tail = stderrTail.slice(-200);
152
+ const level = signal || (code ?? 0) !== 0 ? "error" : "info";
153
+ emitLifecycle(`op=exit session=${SESSION_ID8} server=${SERVER_NAME} pid=${child.pid ?? -1} ` +
154
+ `code=${code ?? "—"} signal=${signal ?? "—"} lifetimeMs=${lifetimeMs} stderr-tail=${JSON.stringify(tail)}`, level);
155
+ if (signal)
156
+ process.exit(128 + (SIGNUM[signal] ?? 0));
157
+ process.exit(code ?? 0);
158
+ });
159
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,3 @@
1
+ {
2
+ "type": "commonjs"
3
+ }
@@ -10,8 +10,12 @@
10
10
  "type": "stdio",
11
11
  "command": "node",
12
12
  "args": [
13
+ "${CLAUDE_PLUGIN_ROOT}/lib/mcp-spawn-tee/index.js",
13
14
  "${CLAUDE_PLUGIN_ROOT}/mcp/dist/index.js"
14
- ]
15
+ ],
16
+ "env": {
17
+ "MCP_SPAWN_TEE_NAME": "browser"
18
+ }
15
19
  }
16
20
  }
17
21
  }