@rubytech/create-maxy-code 0.1.182 → 0.1.184

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 (170) hide show
  1. package/dist/__tests__/bundler-rewrite-platform-lib.test.js +68 -0
  2. package/dist/bundler-rewrite-platform-lib.js +29 -0
  3. package/package.json +1 -1
  4. package/payload/platform/lib/graph-search/dist/index.d.ts +10 -0
  5. package/payload/platform/lib/graph-search/dist/index.d.ts.map +1 -1
  6. package/payload/platform/lib/graph-search/dist/index.js +57 -30
  7. package/payload/platform/lib/graph-search/dist/index.js.map +1 -1
  8. package/payload/platform/lib/graph-search/src/__tests__/hybrid.test.ts +95 -2
  9. package/payload/platform/lib/graph-search/src/__tests__/vector-index-coverage.test.ts +198 -0
  10. package/payload/platform/lib/graph-search/src/index.ts +73 -29
  11. package/payload/platform/neo4j/schema.cypher +36 -0
  12. package/payload/platform/plugins/admin/PLUGIN.md +2 -0
  13. package/payload/platform/plugins/admin/hooks/admin-authoring-observer.sh +155 -0
  14. package/payload/platform/plugins/admin/skills/access-manager/SKILL.md +7 -5
  15. package/payload/platform/plugins/admin/skills/access-manager/references/operations.md +27 -55
  16. package/payload/platform/plugins/admin/skills/professional-document/SKILL.md +178 -0
  17. package/payload/platform/plugins/admin/skills/specialist-management/SKILL.md +3 -2
  18. package/payload/platform/plugins/aeo/mcp/dist/index.js +3 -0
  19. package/payload/platform/plugins/aeo/mcp/dist/index.js.map +1 -1
  20. package/payload/platform/plugins/contacts/PLUGIN.md +1 -0
  21. package/payload/platform/plugins/contacts/mcp/dist/index.js +3 -0
  22. package/payload/platform/plugins/contacts/mcp/dist/index.js.map +1 -1
  23. package/payload/platform/plugins/docs/references/access-control.md +29 -22
  24. package/payload/platform/plugins/email/mcp/dist/scripts/send-transactional.d.ts +2 -0
  25. package/payload/platform/plugins/email/mcp/dist/scripts/send-transactional.d.ts.map +1 -0
  26. package/payload/platform/plugins/email/mcp/dist/scripts/send-transactional.js +56 -0
  27. package/payload/platform/plugins/email/mcp/dist/scripts/send-transactional.js.map +1 -0
  28. package/payload/platform/plugins/memory/.claude-plugin/plugin.json +1 -1
  29. package/payload/platform/plugins/memory/PLUGIN.md +6 -1
  30. package/payload/platform/plugins/memory/mcp/dist/index.js +91 -7
  31. package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
  32. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/typed-edge-schema.test.js +30 -1
  33. package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/typed-edge-schema.test.js.map +1 -1
  34. package/payload/platform/plugins/memory/mcp/dist/lib/section-types.d.ts +15 -0
  35. package/payload/platform/plugins/memory/mcp/dist/lib/section-types.d.ts.map +1 -1
  36. package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-schema.d.ts +10 -0
  37. package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-schema.d.ts.map +1 -1
  38. package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-schema.js +35 -4
  39. package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-schema.js.map +1 -1
  40. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest.test.js +61 -0
  41. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-ingest.test.js.map +1 -1
  42. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-update-by-name.test.d.ts +2 -0
  43. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-update-by-name.test.d.ts.map +1 -0
  44. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-update-by-name.test.js +125 -0
  45. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-update-by-name.test.js.map +1 -0
  46. package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.d.ts.map +1 -1
  47. package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.js +65 -5
  48. package/payload/platform/plugins/memory/mcp/dist/tools/memory-ingest.js.map +1 -1
  49. package/payload/platform/plugins/memory/mcp/dist/tools/memory-update-by-name.d.ts +15 -0
  50. package/payload/platform/plugins/memory/mcp/dist/tools/memory-update-by-name.d.ts.map +1 -0
  51. package/payload/platform/plugins/memory/mcp/dist/tools/memory-update-by-name.js +45 -0
  52. package/payload/platform/plugins/memory/mcp/dist/tools/memory-update-by-name.js.map +1 -0
  53. package/payload/platform/plugins/memory/mcp/dist/tools/memory-update.js +24 -1
  54. package/payload/platform/plugins/memory/mcp/dist/tools/memory-update.js.map +1 -1
  55. package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.d.ts.map +1 -1
  56. package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.js +16 -0
  57. package/payload/platform/plugins/memory/mcp/dist/tools/memory-write.js.map +1 -1
  58. package/payload/platform/plugins/memory/references/graph-primitives.md +1 -0
  59. package/payload/platform/plugins/memory/references/schema-base.md +4 -2
  60. package/payload/platform/plugins/memory/skills/document-ingest/SKILL.md +24 -0
  61. package/payload/platform/plugins/scheduling/PLUGIN.md +1 -0
  62. package/payload/platform/plugins/scheduling/mcp/dist/index.js +3 -0
  63. package/payload/platform/plugins/scheduling/mcp/dist/index.js.map +1 -1
  64. package/payload/platform/plugins/work/PLUGIN.md +1 -0
  65. package/payload/platform/plugins/work/mcp/dist/index.js +4 -0
  66. package/payload/platform/plugins/work/mcp/dist/index.js.map +1 -1
  67. package/payload/platform/plugins/workflows/PLUGIN.md +1 -0
  68. package/payload/platform/plugins/workflows/mcp/dist/index.js +3 -0
  69. package/payload/platform/plugins/workflows/mcp/dist/index.js.map +1 -1
  70. package/payload/platform/scripts/__tests__/agents-md-bootstrap.test.sh +111 -0
  71. package/payload/platform/scripts/lib/agents-md-bootstrap.sh +49 -0
  72. package/payload/platform/scripts/setup-account.sh +18 -14
  73. package/payload/platform/services/claude-session-manager/dist/fs-watcher.d.ts +8 -0
  74. package/payload/platform/services/claude-session-manager/dist/fs-watcher.d.ts.map +1 -1
  75. package/payload/platform/services/claude-session-manager/dist/fs-watcher.js.map +1 -1
  76. package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -1
  77. package/payload/platform/services/claude-session-manager/dist/http-server.js +58 -0
  78. package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
  79. package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts +41 -4
  80. package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts.map +1 -1
  81. package/payload/platform/services/claude-session-manager/dist/pty-spawner.js +172 -53
  82. package/payload/platform/services/claude-session-manager/dist/pty-spawner.js.map +1 -1
  83. package/payload/platform/templates/agents/admin/AGENTS.md +18 -7
  84. package/payload/platform/templates/agents/admin/IDENTITY.md +2 -2
  85. package/payload/platform/templates/specialists/agents/archive-ingest-operator.md +1 -1
  86. package/payload/platform/templates/specialists/agents/citation-auditor.md +1 -1
  87. package/payload/platform/templates/specialists/agents/compiled-truth-rewriter.md +1 -1
  88. package/payload/platform/templates/specialists/agents/content-producer.md +3 -1
  89. package/payload/platform/templates/specialists/agents/database-operator.md +2 -2
  90. package/payload/platform/templates/specialists/agents/librarian.md +1 -1
  91. package/payload/platform/templates/specialists/agents/personal-assistant.md +1 -1
  92. package/payload/platform/templates/specialists/agents/project-manager.md +1 -1
  93. package/payload/platform/templates/specialists/agents/public-session-reviewer.md +40 -0
  94. package/payload/platform/templates/specialists/agents/research-assistant.md +1 -1
  95. package/payload/platform/templates/specialists/agents/typed-edge-classifier.md +1 -1
  96. package/payload/server/public/assets/ChatInput-DzacFNMk.css +1 -0
  97. package/payload/server/public/assets/{Checkbox-YrQovXpN.js → Checkbox-BJKNkUYu.js} +1 -1
  98. package/payload/server/public/assets/{admin-DH5jp-1u.js → admin-BNy4N2d6.js} +1 -1
  99. package/payload/server/public/assets/{architectureDiagram-Q4EWVU46-Do2zYONG.js → architectureDiagram-Q4EWVU46-DZoOzmjE.js} +1 -1
  100. package/payload/server/public/assets/{blockDiagram-DXYQGD6D-DpIX_bRu.js → blockDiagram-DXYQGD6D-DG3yufCR.js} +1 -1
  101. package/payload/server/public/assets/{c4Diagram-AHTNJAMY-Cz335ZSY.js → c4Diagram-AHTNJAMY-BBx5wXuZ.js} +1 -1
  102. package/payload/server/public/assets/channel-DdtUtt5g.js +1 -0
  103. package/payload/server/public/assets/{chunk-336JU56O-Dmknn3Wo.js → chunk-336JU56O-DwP7g5ns.js} +2 -2
  104. package/payload/server/public/assets/{chunk-426QAEUC-ClfGjizN.js → chunk-426QAEUC-DXzGdc22.js} +1 -1
  105. package/payload/server/public/assets/{chunk-4TB4RGXK-BPKctJ5c.js → chunk-4TB4RGXK-1LDRjk0E.js} +1 -1
  106. package/payload/server/public/assets/{chunk-5FUZZQ4R-BWDCO9zw.js → chunk-5FUZZQ4R-BHjWhwhn.js} +1 -1
  107. package/payload/server/public/assets/{chunk-5PVQY5BW-BE34_Db0.js → chunk-5PVQY5BW-CwPHRVN8.js} +1 -1
  108. package/payload/server/public/assets/{chunk-EDXVE4YY-BysA-_6v.js → chunk-EDXVE4YY-7443hrYZ.js} +1 -1
  109. package/payload/server/public/assets/{chunk-ENJZ2VHE-BMVyMsqA.js → chunk-ENJZ2VHE-BTnmmnmX.js} +1 -1
  110. package/payload/server/public/assets/{chunk-ICPOFSXX-C5KRdLV4.js → chunk-ICPOFSXX-CPnMJplL.js} +1 -1
  111. package/payload/server/public/assets/{chunk-OYMX7WX6-DVZD-AVc.js → chunk-OYMX7WX6-DCQ5Q4RS.js} +1 -1
  112. package/payload/server/public/assets/{chunk-U2HBQHQK-DYmQdx8x.js → chunk-U2HBQHQK-BmfZG8e4.js} +1 -1
  113. package/payload/server/public/assets/{chunk-X2U36JSP-DrZenIl3.js → chunk-X2U36JSP-Da2yJL2u.js} +1 -1
  114. package/payload/server/public/assets/{chunk-YZCP3GAM-CDuGbvMq.js → chunk-YZCP3GAM-BdUmMUJ6.js} +1 -1
  115. package/payload/server/public/assets/{chunk-ZZ45TVLE-COztbiu5.js → chunk-ZZ45TVLE-abkGirrZ.js} +1 -1
  116. package/payload/server/public/assets/classDiagram-6PBFFD2Q-CKk2DFZe.js +1 -0
  117. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E--YvfDQCh.js +1 -0
  118. package/payload/server/public/assets/clone-Cw6UfPGM.js +1 -0
  119. package/payload/server/public/assets/{dagre-Cv9Ib2OM.js → dagre-BVVuAEsU.js} +1 -1
  120. package/payload/server/public/assets/{dagre-KV5264BT-CoEd61KZ.js → dagre-KV5264BT-VG2kNj19.js} +1 -1
  121. package/payload/server/public/assets/data-uBpwaldK.js +1 -0
  122. package/payload/server/public/assets/{diagram-5BDNPKRD-WXNzw3uW.js → diagram-5BDNPKRD-DRiVy69K.js} +1 -1
  123. package/payload/server/public/assets/{diagram-G4DWMVQ6-C6IuQ2VV.js → diagram-G4DWMVQ6-DtpiRTYX.js} +1 -1
  124. package/payload/server/public/assets/{diagram-MMDJMWI5-CdJdir5A.js → diagram-MMDJMWI5-Da3t99fY.js} +1 -1
  125. package/payload/server/public/assets/{diagram-TYMM5635-DxWKQH5T.js → diagram-TYMM5635-BzQmLTJQ.js} +1 -1
  126. package/payload/server/public/assets/{erDiagram-SMLLAGMA-C9fvs33K.js → erDiagram-SMLLAGMA-D3Ll-GDw.js} +1 -1
  127. package/payload/server/public/assets/{flowDiagram-DWJPFMVM-BO7Yrbqv.js → flowDiagram-DWJPFMVM-D17bje6d.js} +1 -1
  128. package/payload/server/public/assets/{ganttDiagram-T4ZO3ILL-CQJyWBZq.js → ganttDiagram-T4ZO3ILL-BjeQ-Bun.js} +1 -1
  129. package/payload/server/public/assets/{gitGraphDiagram-UUTBAWPF-DZfQHrYw.js → gitGraphDiagram-UUTBAWPF-LtX4pvZS.js} +1 -1
  130. package/payload/server/public/assets/{graph-labels-BMU8LsOD.js → graph-labels-Cn9jAE6I.js} +1 -1
  131. package/payload/server/public/assets/graph-tvTPvBaz.js +1 -0
  132. package/payload/server/public/assets/{graphlib-C40H-Q5E.js → graphlib-CzwsfZOw.js} +1 -1
  133. package/payload/server/public/assets/{infoDiagram-42DDH7IO-CakfV5f9.js → infoDiagram-42DDH7IO-DOgH4i52.js} +1 -1
  134. package/payload/server/public/assets/{ishikawaDiagram-UXIWVN3A-CPuBPyfa.js → ishikawaDiagram-UXIWVN3A-DYqy5BFj.js} +1 -1
  135. package/payload/server/public/assets/{journeyDiagram-VCZTEJTY-zpZm2Mmo.js → journeyDiagram-VCZTEJTY-CsFpIULJ.js} +1 -1
  136. package/payload/server/public/assets/{kanban-definition-6JOO6SKY-DfJduQCo.js → kanban-definition-6JOO6SKY-5uZuArw7.js} +1 -1
  137. package/payload/server/public/assets/{lib-Bnh57com.js → lib-p4ylk2XS.js} +1 -1
  138. package/payload/server/public/assets/{line-BpYQqO5R.js → line-BY8PmCSW.js} +1 -1
  139. package/payload/server/public/assets/{mermaid-parser.core-C5Mwi14D.js → mermaid-parser.core-CJ_9xqwK.js} +1 -1
  140. package/payload/server/public/assets/{mermaid.core-D8qBtvvT.js → mermaid.core-CXznBkX7.js} +3 -3
  141. package/payload/server/public/assets/{mindmap-definition-QFDTVHPH-Bli9JhIN.js → mindmap-definition-QFDTVHPH-DZbHBud5.js} +1 -1
  142. package/payload/server/public/assets/{page-0lzgQWnS.js → page-B3VYaBcf.js} +1 -1
  143. package/payload/server/public/assets/{page-C29S3cBt.js → page-CfN7nw1J.js} +1 -1
  144. package/payload/server/public/assets/{pieDiagram-DEJITSTG-MsLXTSLg.js → pieDiagram-DEJITSTG-QmOi4DRG.js} +1 -1
  145. package/payload/server/public/assets/public-Bbew78md.js +7 -0
  146. package/payload/server/public/assets/{quadrantDiagram-34T5L4WZ-De1sh2K0.js → quadrantDiagram-34T5L4WZ-Cpidq6Xj.js} +1 -1
  147. package/payload/server/public/assets/{requirementDiagram-MS252O5E-D5Sfg1t_.js → requirementDiagram-MS252O5E-CBqtfbzR.js} +1 -1
  148. package/payload/server/public/assets/{sankeyDiagram-XADWPNL6-DHA3LIbv.js → sankeyDiagram-XADWPNL6-4BiY4dV9.js} +1 -1
  149. package/payload/server/public/assets/{sequenceDiagram-FGHM5R23-BE_QlG1B.js → sequenceDiagram-FGHM5R23-DVlL-l2u.js} +1 -1
  150. package/payload/server/public/assets/{stateDiagram-FHFEXIEX-NIwp3F4u.js → stateDiagram-FHFEXIEX-CAm9dW68.js} +1 -1
  151. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-B2EzXi50.js +1 -0
  152. package/payload/server/public/assets/{timeline-definition-GMOUNBTQ-CPE9jyDF.js → timeline-definition-GMOUNBTQ-CD-tZc4y.js} +1 -1
  153. package/payload/server/public/assets/{vennDiagram-DHZGUBPP-CKfoyYmH.js → vennDiagram-DHZGUBPP-Davcm0TF.js} +1 -1
  154. package/payload/server/public/assets/{wardleyDiagram-NUSXRM2D-B9yJek-o.js → wardleyDiagram-NUSXRM2D-40LBYw_Y.js} +1 -1
  155. package/payload/server/public/assets/{xychartDiagram-5P7HB3ND-DuCcSLqX.js → xychartDiagram-5P7HB3ND-DEPT-__v.js} +1 -1
  156. package/payload/server/public/data.html +5 -5
  157. package/payload/server/public/graph.html +6 -6
  158. package/payload/server/public/index.html +8 -8
  159. package/payload/server/public/public.html +5 -5
  160. package/payload/server/server.js +1254 -337
  161. package/payload/server/public/assets/ChatInput-CJ50oqWt.css +0 -1
  162. package/payload/server/public/assets/channel-PC4_IjI1.js +0 -1
  163. package/payload/server/public/assets/classDiagram-6PBFFD2Q-B_pMa-SX.js +0 -1
  164. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-BdBAgF20.js +0 -1
  165. package/payload/server/public/assets/clone-CkNt9L9r.js +0 -1
  166. package/payload/server/public/assets/data-CtanHhM2.js +0 -1
  167. package/payload/server/public/assets/graph-6DPD6be1.js +0 -1
  168. package/payload/server/public/assets/public-DltgEfA9.js +0 -7
  169. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-pfk2F6st.js +0 -1
  170. /package/payload/server/public/assets/{ChatInput-CJo_77bp.js → ChatInput-CvRaT05l.js} +0 -0
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Transactional email send — one-shot script invoked by the UI server
3
+ * for system emails (magic-link delivery, etc.) that must not carry the
4
+ * `email-send` tool's AI-generated disclosure footer.
5
+ *
6
+ * Stdin JSON payload: { accountId, to, subject, body, html? }
7
+ * Stdout on success: `ok messageId=<id>`
8
+ * Stderr on failure: error message
9
+ * Exit code: 0 on success, 1 on any failure.
10
+ *
11
+ * Spawned via `node dist/scripts/send-transactional.js` from a child
12
+ * process; reuses the email plugin's existing nodemailer + credentials
13
+ * loaders so no new dependency travels into the UI bundle.
14
+ */
15
+ import { readFileSync } from "node:fs";
16
+ import { loadCredentials } from "../lib/credentials.js";
17
+ import { sendEmail } from "../lib/smtp.js";
18
+ function readStdin() {
19
+ // Block until EOF on fd 0 — simpler than the async stream pattern for a
20
+ // one-shot script. Throws if no payload arrived.
21
+ try {
22
+ return readFileSync(0, "utf-8");
23
+ }
24
+ catch (err) {
25
+ throw new Error(`failed to read stdin: ${err instanceof Error ? err.message : String(err)}`);
26
+ }
27
+ }
28
+ async function main() {
29
+ const raw = readStdin();
30
+ if (!raw.trim()) {
31
+ throw new Error("empty stdin payload");
32
+ }
33
+ const payload = JSON.parse(raw);
34
+ for (const field of ["accountId", "to", "subject", "body"]) {
35
+ if (typeof payload[field] !== "string" || !payload[field].length) {
36
+ throw new Error(`missing required field: ${field}`);
37
+ }
38
+ }
39
+ const result = await loadCredentials(payload.accountId);
40
+ if ("error" in result)
41
+ throw new Error(result.error);
42
+ const { config, password } = result.credentials;
43
+ const { messageId } = await sendEmail(config, password, {
44
+ to: payload.to,
45
+ subject: payload.subject,
46
+ body: payload.body,
47
+ html: payload.html,
48
+ headers: payload.headers,
49
+ });
50
+ process.stdout.write(`ok messageId=${messageId}\n`);
51
+ }
52
+ main().catch((err) => {
53
+ process.stderr.write(`${err instanceof Error ? err.message : String(err)}\n`);
54
+ process.exit(1);
55
+ });
56
+ //# sourceMappingURL=send-transactional.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"send-transactional.js","sourceRoot":"","sources":["../../src/scripts/send-transactional.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAW3C,SAAS,SAAS;IAChB,wEAAwE;IACxE,iDAAiD;IACjD,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IAClC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,yBAAyB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC/F,CAAC;AACH,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,MAAM,GAAG,GAAG,SAAS,EAAE,CAAC;IACxB,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC;QAChB,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;IACzC,CAAC;IACD,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAY,CAAC;IAC3C,KAAK,MAAM,KAAK,IAAI,CAAC,WAAW,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,CAAU,EAAE,CAAC;QACpE,IAAI,OAAO,OAAO,CAAC,KAAK,CAAC,KAAK,QAAQ,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,MAAM,EAAE,CAAC;YACjE,MAAM,IAAI,KAAK,CAAC,2BAA2B,KAAK,EAAE,CAAC,CAAC;QACtD,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IACxD,IAAI,OAAO,IAAI,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACrD,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,CAAC,WAAW,CAAC;IAEhD,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,SAAS,CAAC,MAAM,EAAE,QAAQ,EAAE;QACtD,EAAE,EAAE,OAAO,CAAC,EAAE;QACd,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,OAAO,EAAE,OAAO,CAAC,OAAO;KACzB,CAAC,CAAC;IACH,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,gBAAgB,SAAS,IAAI,CAAC,CAAC;AACtD,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC9E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "memory",
3
- "description": "Graph memory plugin. Provides memory-search (with optional `fields` projection for known-shape lookups), memory-write, memory-update, and the :Report surface (memory-report-write / memory-report-read-latest / memory-report-list) for reading from, writing to, and updating the Neo4j knowledge graph. Includes conversational memory — organic preference learning, evidence-backed recall, and transparent 'what do you know about me?' responses. Document ingestion goes through memory-ingest; the dispatched specialist produces typed-section JSON in-turn from the loaded ontology. Operator-solicited reclassify of an already-stored thread-shaped KD (today: email-thread KDs) is exposed as `kd-classify <attachmentId>` — runs a body-growth gate (proceed iff body grew ≥25% since the last classify, or first-ever classify), stages the body to a temp file under `$ACCOUNT_DIR/tmp/`, and returns a dispatch envelope for the `librarian`; on success `memory-ingest` replaces the prior :Section children and stamps `lastClassifiedAt` + `lastClassifiedBodyLength` on the parent KD. Two modes: `document` (default) for unstructured PDF/web content → :KnowledgeDocument (keyed on `attachmentId`) + :Section, and `chat` for conversation transcripts → :ConversationArchive (keyed on `conversationIdentity`) + :Section chunks; two parent labels, two writer paths chosen by which identity property is set. Conversation-archive Phase 2 splits across two read-only tools (Task 433): `conversation-archive-list-chunks` pages chunk bodies for the dispatched specialist to read in-turn; `conversation-archive-derive-insights` converts the specialist's per-chunk claims into operator-facing proposals with per-kind cypher. `conversation-archive-enrich-rejection` records (or undoes) durable per-row rejections so already-triaged claims do not re-surface on re-runs. Ships five skills: `conversational-memory`, `document-ingest`, `conversation-archive` (source-agnostic transcript ingest for WhatsApp, Telegram, Signal, LinkedIn DMs, Zoom, meeting minutes, iMessage, Slack), `conversation-archive-mcp` (operator-initiated MCP-driven ingest for Granola, Otter, Circleback meetings — sibling of `conversation-archive` sharing the same writer surface and identity formula), and `conversation-archive-enrich` (per-row operator-gated insight derivation over a named archive's chunks).",
3
+ "description": "Graph memory plugin. Provides memory-search (with optional `fields` projection for known-shape lookups), memory-write, memory-update, memory-update-by-name (repair surface that resolves an elementId from a (label, name, accountId) tuple when search cannot return one), and the :Report surface (memory-report-write / memory-report-read-latest / memory-report-list) for reading from, writing to, and updating the Neo4j knowledge graph. Includes conversational memory — organic preference learning, evidence-backed recall, and transparent 'what do you know about me?' responses. Document ingestion goes through memory-ingest; the dispatched specialist produces typed-section JSON in-turn from the loaded ontology. Operator-solicited reclassify of an already-stored thread-shaped KD (today: email-thread KDs) is exposed as `kd-classify <attachmentId>` — runs a body-growth gate (proceed iff body grew ≥25% since the last classify, or first-ever classify), stages the body to a temp file under `$ACCOUNT_DIR/tmp/`, and returns a dispatch envelope for the `librarian`; on success `memory-ingest` replaces the prior :Section children and stamps `lastClassifiedAt` + `lastClassifiedBodyLength` on the parent KD. Two modes: `document` (default) for unstructured PDF/web content → :KnowledgeDocument (keyed on `attachmentId`) + :Section, and `chat` for conversation transcripts → :ConversationArchive (keyed on `conversationIdentity`) + :Section chunks; two parent labels, two writer paths chosen by which identity property is set. Conversation-archive Phase 2 splits across two read-only tools (Task 433): `conversation-archive-list-chunks` pages chunk bodies for the dispatched specialist to read in-turn; `conversation-archive-derive-insights` converts the specialist's per-chunk claims into operator-facing proposals with per-kind cypher. `conversation-archive-enrich-rejection` records (or undoes) durable per-row rejections so already-triaged claims do not re-surface on re-runs. Ships five skills: `conversational-memory`, `document-ingest`, `conversation-archive` (source-agnostic transcript ingest for WhatsApp, Telegram, Signal, LinkedIn DMs, Zoom, meeting minutes, iMessage, Slack), `conversation-archive-mcp` (operator-initiated MCP-driven ingest for Granola, Otter, Circleback meetings — sibling of `conversation-archive` sharing the same writer surface and identity formula), and `conversation-archive-enrich` (per-row operator-gated insight derivation over a named archive's chunks).",
4
4
  "version": "0.1.0",
5
5
  "author": {
6
6
  "name": "Rubytech LLC"
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: memory
3
- description: "Graph memory plugin. Provides memory-search (with optional `fields` projection for known-shape lookups), memory-write, memory-update, and the :Report surface (memory-report-write / memory-report-read-latest / memory-report-list) for reading from, writing to, and updating the Neo4j knowledge graph. Includes conversational memory — organic preference learning, evidence-backed recall, and transparent 'what do you know about me?' responses. Document ingestion goes through memory-ingest; the dispatched specialist produces typed-section JSON in-turn from the loaded ontology. Operator-solicited reclassify of an already-stored thread-shaped KD (today: email-thread KDs) is exposed as `kd-classify <attachmentId>` — runs a body-growth gate (proceed iff body grew ≥25% since the last classify, or first-ever classify), stages the body to a temp file under `$ACCOUNT_DIR/tmp/`, and returns a dispatch envelope for the `librarian`; on success `memory-ingest` replaces the prior :Section children and stamps `lastClassifiedAt` + `lastClassifiedBodyLength` on the parent KD. Two modes: `document` (default) for unstructured PDF/web content → :KnowledgeDocument (keyed on `attachmentId`) + :Section, and `chat` for conversation transcripts → :ConversationArchive (keyed on `conversationIdentity`) + :Section chunks; two parent labels, two writer paths chosen by which identity property is set. Conversation-archive Phase 2 splits across two read-only tools (Task 433): `conversation-archive-list-chunks` pages chunk bodies for the dispatched specialist to read in-turn; `conversation-archive-derive-insights` converts the specialist's per-chunk claims into operator-facing proposals with per-kind cypher. `conversation-archive-enrich-rejection` records (or undoes) durable per-row rejections so already-triaged claims do not re-surface on re-runs. Ships five skills: `conversational-memory`, `document-ingest`, `conversation-archive` (source-agnostic transcript ingest for WhatsApp, Telegram, Signal, LinkedIn DMs, Zoom, meeting minutes, iMessage, Slack), `conversation-archive-mcp` (operator-initiated MCP-driven ingest for Granola, Otter, Circleback meetings — sibling of `conversation-archive` sharing the same writer surface and identity formula), and `conversation-archive-enrich` (per-row operator-gated insight derivation over a named archive's chunks)."
3
+ description: "Graph memory plugin. Provides memory-search (with optional `fields` projection for known-shape lookups), memory-write, memory-update, memory-update-by-name (repair surface that resolves an elementId from a (label, name, accountId) tuple when search cannot return one), and the :Report surface (memory-report-write / memory-report-read-latest / memory-report-list) for reading from, writing to, and updating the Neo4j knowledge graph. Includes conversational memory — organic preference learning, evidence-backed recall, and transparent 'what do you know about me?' responses. Document ingestion goes through memory-ingest; the dispatched specialist produces typed-section JSON in-turn from the loaded ontology. Operator-solicited reclassify of an already-stored thread-shaped KD (today: email-thread KDs) is exposed as `kd-classify <attachmentId>` — runs a body-growth gate (proceed iff body grew ≥25% since the last classify, or first-ever classify), stages the body to a temp file under `$ACCOUNT_DIR/tmp/`, and returns a dispatch envelope for the `librarian`; on success `memory-ingest` replaces the prior :Section children and stamps `lastClassifiedAt` + `lastClassifiedBodyLength` on the parent KD. Two modes: `document` (default) for unstructured PDF/web content → :KnowledgeDocument (keyed on `attachmentId`) + :Section, and `chat` for conversation transcripts → :ConversationArchive (keyed on `conversationIdentity`) + :Section chunks; two parent labels, two writer paths chosen by which identity property is set. Conversation-archive Phase 2 splits across two read-only tools (Task 433): `conversation-archive-list-chunks` pages chunk bodies for the dispatched specialist to read in-turn; `conversation-archive-derive-insights` converts the specialist's per-chunk claims into operator-facing proposals with per-kind cypher. `conversation-archive-enrich-rejection` records (or undoes) durable per-row rejections so already-triaged claims do not re-surface on re-runs. Ships five skills: `conversational-memory`, `document-ingest`, `conversation-archive` (source-agnostic transcript ingest for WhatsApp, Telegram, Signal, LinkedIn DMs, Zoom, meeting minutes, iMessage, Slack), `conversation-archive-mcp` (operator-initiated MCP-driven ingest for Granola, Otter, Circleback meetings — sibling of `conversation-archive` sharing the same writer surface and identity formula), and `conversation-archive-enrich` (per-row operator-gated insight derivation over a named archive's chunks)."
4
4
  tools:
5
5
  - name: memory-search
6
6
  publicAllowlist: true
@@ -11,6 +11,9 @@ tools:
11
11
  - name: memory-update
12
12
  publicAllowlist: false
13
13
  adminAllowlist: true
14
+ - name: memory-update-by-name
15
+ publicAllowlist: false
16
+ adminAllowlist: true
14
17
  - name: memory-reindex
15
18
  publicAllowlist: false
16
19
  adminAllowlist: false
@@ -140,6 +143,8 @@ mcp:
140
143
  PLATFORM_ROOT: ${PLATFORM_ROOT}
141
144
  ACCOUNT_ID: ${ACCOUNT_ID}
142
145
  SESSION_ID: ${SESSION_ID}
146
+ AGENT_SLUG: ${AGENT_SLUG}
147
+ AGENT_SLUG_SCOPE: ${AGENT_SLUG_SCOPE}
143
148
  mcp-manifest: auto
144
149
  ---
145
150
 
@@ -25,6 +25,7 @@ import { obsidianVaultImport, } from "./tools/obsidian-vault-import.js";
25
25
  // whatsapp-export-insight-pass deleted (Phase 2 deferred).
26
26
  import { memoryIngestWeb } from "./tools/memory-ingest-web.js";
27
27
  import { memoryUpdate } from "./tools/memory-update.js";
28
+ import { memoryUpdateByName } from "./tools/memory-update-by-name.js";
28
29
  import { memoryDelete } from "./tools/memory-delete.js";
29
30
  import { memoryFindCandidates } from "./tools/memory-find-candidates.js";
30
31
  import { memoryNodeExists, ALLOWED_LABELS as MEMORY_NODE_EXISTS_LABELS } from "./tools/memory-node-exists.js";
@@ -66,7 +67,12 @@ const readOnly = process.env.READ_ONLY === "true";
66
67
  // Module-init must never throw; plugin-system spawn enumerates tools/list
67
68
  // before ACCOUNT_ID is set. Per-call refusal preserves account isolation.
68
69
  const accountId = process.env.ACCOUNT_ID ?? null;
69
- process.stderr.write(`[memory] boot accountId=${accountId ?? "null"}\n`);
70
+ // Task 476/487 — extended boot signal: sessionId, agentSlug (provenance),
71
+ // and agentScope (read-scope) land here so a stale spawn-env contract is
72
+ // visible at the first byte of stderr. Regression shapes: `sessionId ===
73
+ // accountId`; `agentSlug` empty on a specialist spawn (provenance lost);
74
+ // `agentScope` non-empty on the admin operator spawn (search wrongly scoped).
75
+ process.stderr.write(`[memory] boot accountId=${accountId ?? "null"} sessionId=${process.env.SESSION_ID || "-"} agentSlug=${process.env.AGENT_SLUG || "-"} agentScope=${process.env.AGENT_SLUG_SCOPE || "-"}\n`);
70
76
  function refuseNoAccount(toolName) {
71
77
  process.stderr.write(`[memory] tool=${toolName} refuse reason=no-account-context\n`);
72
78
  return {
@@ -139,6 +145,15 @@ const userId = process.env.USER_ID; // Optional — present for admin sessions w
139
145
  const allowedScopes = process.env.ALLOWED_SCOPES
140
146
  ? process.env.ALLOWED_SCOPES.split(",").map((s) => s.trim()).filter(Boolean)
141
147
  : undefined;
148
+ // Task 485 — per-visitor slice ringfence. Stamped by pty-spawner on
149
+ // gated public-agent spawns. When present, every memory-search WHERE
150
+ // composes `(n.sliceToken = $sliceToken OR n.scope IN $allowedScopes)`
151
+ // so the agent sees its visitor's user-scoped nodes alongside public-scope
152
+ // rows. When absent (admin path + open-mode public), behaviour is
153
+ // unchanged.
154
+ const accessSliceToken = typeof process.env.ACCESS_SLICE_TOKEN === "string" && process.env.ACCESS_SLICE_TOKEN.length > 0
155
+ ? process.env.ACCESS_SLICE_TOKEN
156
+ : undefined;
142
157
  // Per-handler session resolution. Module-load env capture was
143
158
  // wrong: when the admin agent didn't set SESSION_ID on MCP spawn, `sessionId`
144
159
  // was undefined for the entire process lifetime — every subsequent
@@ -151,10 +166,17 @@ function resolveSessionId(override) {
151
166
  const fromEnv = process.env.SESSION_ID;
152
167
  return fromEnv && fromEnv.trim() ? fromEnv.trim() : undefined;
153
168
  }
154
- // Per-agent knowledge scoping: when set, memory-search only returns nodes whose
155
- // `agents` array contains this slug. For public agents, set via env var (server-level
156
- // enforcement). For admin queries, passed as an optional tool param.
169
+ // Provenance stamp: AGENT_SLUG is the agent identity recorded as
170
+ // `createdByAgent` on every write. The admin operator gets the 'admin'
171
+ // sentinel (Task 487); specialists/public get their slug.
157
172
  const envAgentSlug = process.env.AGENT_SLUG || undefined;
173
+ // Per-agent knowledge scoping (Task 487 split this off AGENT_SLUG): when set,
174
+ // memory-search only returns nodes whose `agents` array contains this slug.
175
+ // Specialists/public get their slug here (server-level enforcement); the admin
176
+ // operator gets EMPTY so search stays wide-open. For admin, an optional tool
177
+ // param can still scope a single query. Read-scope and provenance are now
178
+ // independent — admin writes stamp 'admin' while admin reads stay unscoped.
179
+ const envAgentScopeSlug = process.env.AGENT_SLUG_SCOPE || undefined;
158
180
  // Keyword subscriptions: comma-separated list of keywords for BM25-based reactive
159
181
  // knowledge inclusion. When set, memory-search runs a BM25 query per keyword and
160
182
  // unions results with directly-tagged nodes. Capped at 5 for Pi performance.
@@ -225,8 +247,10 @@ eagerTool(server, "memory-search", "Search the knowledge graph using semantic ve
225
247
  }, async ({ query, labels, limit, expandHops, keywords, keywordMatch, agentSlug: toolAgentSlug, fields, retrievalClass }) => {
226
248
  if (!accountId)
227
249
  return refuseNoAccount("memory-search");
228
- // Env var takes precedence over tool param (security: public agent server-level enforcement)
229
- const effectiveAgentSlug = envAgentSlug ?? toolAgentSlug;
250
+ // AGENT_SLUG_SCOPE takes precedence over the tool param (security: public
251
+ // agent server-level enforcement). Empty for the admin operator, so admin
252
+ // falls through to the optional tool param (default: unscoped).
253
+ const effectiveAgentSlug = envAgentScopeSlug ?? toolAgentSlug;
230
254
  try {
231
255
  const results = await memorySearch({
232
256
  query,
@@ -235,6 +259,7 @@ eagerTool(server, "memory-search", "Search the knowledge graph using semantic ve
235
259
  limit,
236
260
  expandHops,
237
261
  allowedScopes,
262
+ sliceToken: accessSliceToken,
238
263
  keywords,
239
264
  keywordMatch,
240
265
  agentSlug: effectiveAgentSlug,
@@ -242,6 +267,23 @@ eagerTool(server, "memory-search", "Search the knowledge graph using semantic ve
242
267
  fields,
243
268
  retrievalClass,
244
269
  });
270
+ // Task 485 — per-call slice/public/user breakdown so the
271
+ // `[memory-search] sliceFilter=…|none publicCount=… userCount=…` grep
272
+ // proves the gated filter fired on the right turn. Inspects results
273
+ // after hybrid() applied the WHERE, so the counts reflect what the
274
+ // agent actually saw, not the unscoped corpus.
275
+ let publicCount = 0;
276
+ let userCount = 0;
277
+ for (const r of results) {
278
+ const scope = r.properties.scope;
279
+ const sliceTokenRow = r.properties.sliceToken;
280
+ if (scope === "public")
281
+ publicCount += 1;
282
+ if (typeof sliceTokenRow === "string" && sliceTokenRow.length > 0)
283
+ userCount += 1;
284
+ }
285
+ process.stderr.write(`[memory-search] sliceFilter=${accessSliceToken ? accessSliceToken.slice(0, 8) : "none"} ` +
286
+ `resultCount=${results.length} publicCount=${publicCount} userCount=${userCount}\n`);
245
287
  if (results.length === 0) {
246
288
  return {
247
289
  content: [
@@ -779,7 +821,49 @@ if (!readOnly) {
779
821
  };
780
822
  }
781
823
  });
782
- server.tool("memory-update", "Update properties on an existing node in the knowledge graph. Finds the node by element ID, verifies account ownership, sets the provided properties, and recomputes the embedding. To refresh `compiledTruth` / `compiledTruthPublic` on :Person / :Organization / :Concept / :Project / :LocalBusiness, dispatch the `compiled-truth-rewriter` specialist via the Task tool admin sends the nodeId plus any `operatorHint` / `publicOperatorHint`; the specialist reads the node + 90-day timeline, computes the new summary, and writes it back via memory-update. Direct writes to compiled-truth properties via this tool are refused unless the caller is the compiled-truth-rewriter specialist (gated by MAXY_SPECIALIST env).", {
824
+ server.tool("memory-update-by-name", "Update an existing node addressed by (label, name, accountId) instead of elementId. Use this as a repair surface when memory-search cannot return an elementId for a node you know exists by name typically an ingest-created :Organization the search route is failing to surface. Resolves the unique node matching the tuple, then delegates to memory-update (embedding refresh, write gates, compiled-truth refusal, and provenance stamping all carry over). Rejects loudly on zero matches (the row does not exist) and on two-or-more matches (ambiguous the rejection lists candidate elementIds so you can pick one and call memory-update directly). Trashed nodes are excluded from the lookup. For one-off updates where you already have the elementId from a successful memory-search, prefer memory-update this tool is the fallback when search hides the node.", {
825
+ label: z.string().describe("The single label to MATCH on (e.g. 'Organization', 'Person', 'Project'). Must be exactly the label carried by the target node — the tool does not iterate label variants."),
826
+ name: z.string().describe("The exact `name` property of the target node (case-sensitive). Forbidden-property rules still apply downstream — if the label rejects `name`, use memory-update with the correct identifier instead."),
827
+ properties: z
828
+ .record(z.string(), z.unknown())
829
+ .describe("Properties to set or overwrite. Same restrictions as memory-update — embedding/accountId/createdAt are silently stripped; compiled-truth fields are refused unless the caller is the compiled-truth-rewriter specialist."),
830
+ }, async ({ label, name, properties }) => {
831
+ if (!accountId)
832
+ return refuseNoAccount("memory-update-by-name");
833
+ try {
834
+ const result = await memoryUpdateByName({
835
+ label,
836
+ name,
837
+ accountId,
838
+ properties: properties,
839
+ createdBy: {
840
+ agent: envAgentSlug,
841
+ session: resolveSessionId(),
842
+ tool: "memory-update-by-name",
843
+ },
844
+ });
845
+ return {
846
+ content: [
847
+ {
848
+ type: "text",
849
+ text: `Node updated: [${result.labels.join(", ")}] (ID: ${result.nodeId})`,
850
+ },
851
+ ],
852
+ };
853
+ }
854
+ catch (err) {
855
+ return {
856
+ content: [
857
+ {
858
+ type: "text",
859
+ text: `Update failed: ${err instanceof Error ? err.message : String(err)}`,
860
+ },
861
+ ],
862
+ isError: true,
863
+ };
864
+ }
865
+ });
866
+ server.tool("memory-update", "Update properties on an existing node in the knowledge graph. Finds the node by element ID, verifies account ownership, sets the provided properties, and recomputes the embedding. To refresh `compiledTruth` / `compiledTruthPublic` on :Person / :Organization / :Concept / :Project / :LocalBusiness, dispatch the `compiled-truth-rewriter` specialist via the Task tool — admin sends the nodeId plus any `operatorHint` / `publicOperatorHint`; the specialist reads the node + 90-day timeline, computes the new summary, and writes it back via memory-update. Direct writes to compiled-truth properties via this tool are refused unless the caller is the compiled-truth-rewriter specialist (gated by MAXY_SPECIALIST env). When you only have the node's name (typically because memory-search couldn't return it), use memory-update-by-name instead.", {
783
867
  nodeId: z.string().describe("Element ID of the node to update (from memory-search results)"),
784
868
  properties: z
785
869
  .record(z.string(), z.unknown())