@rubytech/create-realagent-code 0.1.316 → 0.1.320
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.
- package/dist/__tests__/base-toolchain-deps.test.js +67 -0
- package/dist/index.js +7 -1
- package/package.json +2 -2
- package/payload/platform/lib/graph-style/dist/index.d.ts.map +1 -1
- package/payload/platform/lib/graph-style/dist/index.js +15 -0
- package/payload/platform/lib/graph-style/dist/index.js.map +1 -1
- package/payload/platform/lib/graph-style/src/index.ts +16 -0
- package/payload/platform/lib/graph-write/dist/index.d.ts.map +1 -1
- package/payload/platform/lib/graph-write/dist/index.js +3 -0
- package/payload/platform/lib/graph-write/dist/index.js.map +1 -1
- package/payload/platform/lib/graph-write/src/index.ts +3 -0
- package/payload/platform/lib/mcp-eager/dist/index.d.ts +0 -20
- package/payload/platform/lib/mcp-eager/dist/index.d.ts.map +1 -1
- package/payload/platform/lib/mcp-eager/dist/index.js +2 -1
- package/payload/platform/lib/mcp-eager/dist/index.js.map +1 -1
- package/payload/platform/lib/mcp-eager/src/index.ts +3 -1
- package/payload/platform/lib/mcp-lifeline/dist/index.d.ts +8 -0
- package/payload/platform/lib/mcp-lifeline/dist/index.d.ts.map +1 -0
- package/payload/platform/lib/mcp-lifeline/dist/index.js +71 -0
- package/payload/platform/lib/mcp-lifeline/dist/index.js.map +1 -0
- package/payload/platform/lib/mcp-lifeline/package.json +7 -0
- package/payload/platform/lib/mcp-lifeline/src/__tests__/lifeline.test.ts +146 -0
- package/payload/platform/lib/mcp-lifeline/src/index.ts +78 -0
- package/payload/platform/lib/mcp-lifeline/tsconfig.json +9 -0
- package/payload/platform/lib/mcp-lifeline/vitest.config.ts +9 -0
- package/payload/platform/lib/models/dist/index.d.ts +16 -0
- package/payload/platform/lib/models/dist/index.d.ts.map +1 -1
- package/payload/platform/lib/models/dist/index.js +32 -1
- package/payload/platform/lib/models/dist/index.js.map +1 -1
- package/payload/platform/lib/models/src/index.ts +39 -0
- package/payload/platform/neo4j/schema.cypher +103 -0
- package/payload/platform/package.json +5 -2
- package/payload/platform/plugins/admin/mcp/dist/index.js +11 -10
- package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +50 -12
- package/payload/platform/plugins/docs/references/admin-ui.md +24 -2
- package/payload/platform/plugins/docs/references/internals.md +14 -7
- package/payload/platform/plugins/docs/references/neo4j.md +9 -0
- package/payload/platform/plugins/docs/references/plugins-guide.md +2 -2
- package/payload/platform/plugins/memory/mcp/dist/index.js +32 -31
- package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-loader.test.js +28 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-loader.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/typed-edge-schema.test.js +7 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/typed-edge-schema.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-schema.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-schema.js +19 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/typed-edge-schema.js.map +1 -1
- package/payload/platform/plugins/memory/references/schema-knowledge-work.md +80 -0
- package/payload/platform/plugins/outlook/mcp/dist/index.js +8 -7
- package/payload/platform/plugins/outlook/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/projects/PLUGIN.md +11 -0
- package/payload/platform/plugins/projects/references/meeting-to-tasks.md +34 -0
- package/payload/platform/plugins/projects/references/prioritization.md +43 -0
- package/payload/platform/plugins/projects/references/risk-premortem.md +34 -0
- package/payload/platform/plugins/projects/references/sprint.md +5 -1
- package/payload/platform/plugins/projects/references/stakeholder-map.md +43 -0
- package/payload/platform/plugins/quickbooks/mcp/dist/index.js +12 -11
- package/payload/platform/plugins/quickbooks/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/replicate/mcp/dist/index.js +4 -3
- package/payload/platform/plugins/replicate/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/whatsapp/mcp/dist/index.js +11 -10
- package/payload/platform/plugins/whatsapp/mcp/dist/index.js.map +1 -1
- package/payload/platform/scripts/__tests__/check-no-raw-mcp-registrations.test.sh +57 -0
- package/payload/platform/scripts/check-no-raw-mcp-registrations.mjs +70 -0
- package/payload/platform/scripts/installer-device-verify.sh +38 -0
- package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/http-server.js +57 -9
- package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/permission-mode-tail.d.ts +3 -1
- package/payload/platform/services/claude-session-manager/dist/permission-mode-tail.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/permission-mode-tail.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts +7 -1
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.js +9 -1
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/rc-daemon.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/rc-daemon.js +3 -12
- package/payload/platform/services/claude-session-manager/dist/rc-daemon.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/session-sidecar.d.ts +8 -0
- package/payload/platform/services/claude-session-manager/dist/session-sidecar.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/session-sidecar.js +9 -0
- package/payload/platform/services/claude-session-manager/dist/session-sidecar.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/system-prompt.d.ts +5 -0
- package/payload/platform/services/claude-session-manager/dist/system-prompt.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/system-prompt.js +15 -0
- package/payload/platform/services/claude-session-manager/dist/system-prompt.js.map +1 -1
- package/payload/premium-plugins/real-agent/lib/mcp-lifeline/dist/index.d.ts +8 -0
- package/payload/premium-plugins/real-agent/lib/mcp-lifeline/dist/index.d.ts.map +1 -0
- package/payload/premium-plugins/real-agent/lib/mcp-lifeline/dist/index.js +71 -0
- package/payload/premium-plugins/real-agent/lib/mcp-lifeline/dist/index.js.map +1 -0
- package/payload/premium-plugins/real-agent/lib/mcp-lifeline/package.json +7 -0
- package/payload/premium-plugins/real-agent/plugins/buyers/mcp/dist/index.js +9 -8
- package/payload/premium-plugins/real-agent/plugins/buyers/mcp/dist/index.js.map +1 -1
- package/payload/premium-plugins/real-agent/plugins/buyers/mcp/src/index.ts +9 -8
- package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/index.js +28 -27
- package/payload/premium-plugins/real-agent/plugins/loop/mcp/dist/index.js.map +1 -1
- package/payload/premium-plugins/real-agent/plugins/loop/mcp/src/index.ts +28 -27
- package/payload/premium-plugins/real-agent/plugins/property-data/mcp/dist/index.js +23 -22
- package/payload/premium-plugins/real-agent/plugins/property-data/mcp/dist/index.js.map +1 -1
- package/payload/premium-plugins/real-agent/plugins/property-data/mcp/src/index.ts +23 -22
- package/payload/server/{chunk-Q7EWROVN.js → chunk-GRKG3KNN.js} +0 -101
- package/payload/server/maxy-edge.js +1 -1
- package/payload/server/public/assets/AdminLoginScreens-D_e5PYXv.js +1 -0
- package/payload/server/public/assets/AdminShell-Dc23yALw.js +1 -0
- package/payload/server/public/assets/Checkbox-BHxSr_cA.js +1 -0
- package/payload/server/public/assets/OperatorConversations-BqNOXEu8.js +9 -0
- package/payload/server/public/assets/OperatorConversations-pu50BU11.css +1 -0
- package/payload/server/public/assets/admin-DE55chV9.js +1 -0
- package/payload/server/public/assets/{arc-J2g2u5Xv.js → arc-CxLB9WCE.js} +1 -1
- package/payload/server/public/assets/architecture-YZFGNWBL-DN-MYxff.js +1 -0
- package/payload/server/public/assets/{architectureDiagram-Q4EWVU46-CN0BXxpE.js → architectureDiagram-Q4EWVU46-D-EdJPSY.js} +1 -1
- package/payload/server/public/assets/{blockDiagram-DXYQGD6D-HX-8wF2p.js → blockDiagram-DXYQGD6D-CXx9RgCm.js} +1 -1
- package/payload/server/public/assets/browser-C1Dp1UxB.js +1 -0
- package/payload/server/public/assets/{c4Diagram-AHTNJAMY-wIuarKF5.js → c4Diagram-AHTNJAMY-RFBXEe0B.js} +1 -1
- package/payload/server/public/assets/channel-y27xl53N.js +1 -0
- package/payload/server/public/assets/chat-BLQDFyDL.js +1 -0
- package/payload/server/public/assets/{chunk-2KRD3SAO-Buz7egJZ.js → chunk-2KRD3SAO-DBqAFwK9.js} +1 -1
- package/payload/server/public/assets/{chunk-336JU56O-_JcFXJqc.js → chunk-336JU56O-DdnFEz6R.js} +2 -2
- package/payload/server/public/assets/chunk-426QAEUC-D8Iwaegm.js +1 -0
- package/payload/server/public/assets/{chunk-4BX2VUAB-DUR5Dg3M.js → chunk-4BX2VUAB-cnw-3Gbs.js} +1 -1
- package/payload/server/public/assets/{chunk-4TB4RGXK-BRIqQ9st.js → chunk-4TB4RGXK-BnqJ0bDc.js} +1 -1
- package/payload/server/public/assets/{chunk-55IACEB6-CezTHWXL.js → chunk-55IACEB6-BwyHvvzo.js} +1 -1
- package/payload/server/public/assets/{chunk-5FUZZQ4R-DHYUPzF1.js → chunk-5FUZZQ4R-DXA9U02I.js} +1 -1
- package/payload/server/public/assets/{chunk-5PVQY5BW-BVn4_fI5.js → chunk-5PVQY5BW-D78bZ_8D.js} +1 -1
- package/payload/server/public/assets/{chunk-67CJDMHE-BBLA8Mbi.js → chunk-67CJDMHE-CtE_Mgv7.js} +1 -1
- package/payload/server/public/assets/{chunk-7N4EOEYR-CdWfEI5c.js → chunk-7N4EOEYR-CUZDaySl.js} +1 -1
- package/payload/server/public/assets/{chunk-AA7GKIK3-tS11knCR.js → chunk-AA7GKIK3-CYQ3jO4X.js} +1 -1
- package/payload/server/public/assets/{chunk-BSJP7CBP-GEu1OOZ6.js → chunk-BSJP7CBP-BbA_HyTR.js} +1 -1
- package/payload/server/public/assets/{chunk-CIAEETIT-DKrNbbp_.js → chunk-CIAEETIT-D7_YqRhG.js} +1 -1
- package/payload/server/public/assets/{chunk-EDXVE4YY-B0InXNyr.js → chunk-EDXVE4YY-B23LrtSw.js} +1 -1
- package/payload/server/public/assets/{chunk-ENJZ2VHE-CO7lkHdm.js → chunk-ENJZ2VHE-D3fTHYKN.js} +1 -1
- package/payload/server/public/assets/{chunk-FMBD7UC4-CMj74lWo.js → chunk-FMBD7UC4-DFAA2tyh.js} +1 -1
- package/payload/server/public/assets/{chunk-FOC6F5B3-CLnKQoXw.js → chunk-FOC6F5B3-BF4IHvlI.js} +1 -1
- package/payload/server/public/assets/{chunk-ICPOFSXX-CdiEKIaz.js → chunk-ICPOFSXX-DBUGemHy.js} +2 -2
- package/payload/server/public/assets/{chunk-K5T4RW27-B6LA3fiv.js → chunk-K5T4RW27-rMMs08Eh.js} +1 -1
- package/payload/server/public/assets/{chunk-KGLVRYIC-DrhRrb8Q.js → chunk-KGLVRYIC-BD2r8R2G.js} +1 -1
- package/payload/server/public/assets/{chunk-LIHQZDEY-DVQukevB.js → chunk-LIHQZDEY-D4sYTTwM.js} +1 -1
- package/payload/server/public/assets/{chunk-ORNJ4GCN-ZMLkoDhP.js → chunk-ORNJ4GCN-CAs_uFzb.js} +1 -1
- package/payload/server/public/assets/{chunk-OYMX7WX6-C0dJkynG.js → chunk-OYMX7WX6-Fkp-2ORc.js} +1 -1
- package/payload/server/public/assets/chunk-QZHKN3VN-qHqDpwz3.js +1 -0
- package/payload/server/public/assets/{chunk-U2HBQHQK-BQ9BPIFZ.js → chunk-U2HBQHQK-D_pxZh25.js} +1 -1
- package/payload/server/public/assets/{chunk-X2U36JSP-CAonGMOd.js → chunk-X2U36JSP-CeVmvvRf.js} +1 -1
- package/payload/server/public/assets/{chunk-XPW4576I-D5C_WNlk.js → chunk-XPW4576I-iWP54fKp.js} +1 -1
- package/payload/server/public/assets/{chunk-YZCP3GAM-Ecdvzekb.js → chunk-YZCP3GAM-CNtbWJNN.js} +1 -1
- package/payload/server/public/assets/{chunk-ZZ45TVLE-BsFZd1cN.js → chunk-ZZ45TVLE-BmlFjU_9.js} +1 -1
- package/payload/server/public/assets/classDiagram-6PBFFD2Q-DgVoYWhO.js +1 -0
- package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-C0WNP3uN.js +1 -0
- package/payload/server/public/assets/clone-D50F_pvg.js +1 -0
- package/payload/server/public/assets/{cose-bilkent-S5V4N54A-DBWHaIwm.js → cose-bilkent-S5V4N54A-C7YmF1Pg.js} +1 -1
- package/payload/server/public/assets/{dagre-Dr7ZJYeS.js → dagre-BAmiDDtR.js} +1 -1
- package/payload/server/public/assets/{dagre-KV5264BT-oIJddk7m.js → dagre-KV5264BT-Ca3ESJhc.js} +1 -1
- package/payload/server/public/assets/data-D_L6g-L_.js +1 -0
- package/payload/server/public/assets/{diagram-5BDNPKRD-CEVxqOZ4.js → diagram-5BDNPKRD-BgT1ORf2.js} +1 -1
- package/payload/server/public/assets/{diagram-G4DWMVQ6-BovF7Rjx.js → diagram-G4DWMVQ6-BTaUIiem.js} +1 -1
- package/payload/server/public/assets/{diagram-MMDJMWI5-BhrF8zoF.js → diagram-MMDJMWI5-Bdb2g6Uo.js} +1 -1
- package/payload/server/public/assets/{diagram-TYMM5635-DCUYwxtR.js → diagram-TYMM5635-CkLGC0zZ.js} +1 -1
- package/payload/server/public/assets/{dist-DSsFp0Qd.js → dist-Bkbhs3jw.js} +1 -1
- package/payload/server/public/assets/{erDiagram-SMLLAGMA-BS2-HdCg.js → erDiagram-SMLLAGMA-D_sj4DMg.js} +1 -1
- package/payload/server/public/assets/{flatten-BZMXCpLh.js → flatten-E2Sr0FeD.js} +1 -1
- package/payload/server/public/assets/{flowDiagram-DWJPFMVM-BzSFLoea.js → flowDiagram-DWJPFMVM-iLERoZTe.js} +1 -1
- package/payload/server/public/assets/{ganttDiagram-T4ZO3ILL-1-3QU7mT.js → ganttDiagram-T4ZO3ILL-D60hjMBy.js} +1 -1
- package/payload/server/public/assets/gitGraph-7Q5UKJZL-D-L2yzYf.js +1 -0
- package/payload/server/public/assets/{gitGraphDiagram-UUTBAWPF-fTrJ35Wk.js → gitGraphDiagram-UUTBAWPF-Di0XM6fi.js} +1 -1
- package/payload/server/public/assets/graph-labels-C2r7zl8O.js +1 -0
- package/payload/server/public/assets/{graph-BZNc3EXa.js → graph-ticN9QbK.js} +3 -3
- package/payload/server/public/assets/{graphlib-rlEzI2qD.js → graphlib-C8fUP7uV.js} +1 -1
- package/payload/server/public/assets/info-OMHHGYJF-BQn6jndO.js +1 -0
- package/payload/server/public/assets/infoDiagram-42DDH7IO-BwMdbiXg.js +2 -0
- package/payload/server/public/assets/{isEmpty-DaYIrHay.js → isEmpty-CLz-UprQ.js} +1 -1
- package/payload/server/public/assets/{ishikawaDiagram-UXIWVN3A-0eU_UtlT.js → ishikawaDiagram-UXIWVN3A-CwgI4B5Z.js} +1 -1
- package/payload/server/public/assets/{journeyDiagram-VCZTEJTY-BKLeZohp.js → journeyDiagram-VCZTEJTY-CxBu-tze.js} +1 -1
- package/payload/server/public/assets/{kanban-definition-6JOO6SKY-Dq72xyaN.js → kanban-definition-6JOO6SKY-D2qlheA5.js} +1 -1
- package/payload/server/public/assets/{line-LQhmDT8k.js → line-Bdod7uzQ.js} +1 -1
- package/payload/server/public/assets/{linear-BGotDbGs.js → linear-BiVe6QzC.js} +1 -1
- package/payload/server/public/assets/{mermaid-parser.core-DoLdho1V.js → mermaid-parser.core-xZN7hC6M.js} +2 -2
- package/payload/server/public/assets/{mermaid.core-C1RRyHGm.js → mermaid.core-D0IylAac.js} +3 -3
- package/payload/server/public/assets/{mindmap-definition-QFDTVHPH-vUVVVyV1.js → mindmap-definition-QFDTVHPH-J_Szhwf1.js} +1 -1
- package/payload/server/public/assets/operator-COIYJFG7.js +1 -0
- package/payload/server/public/assets/{ordinal-BqEhkPyh.js → ordinal-5RtyPJVt.js} +1 -1
- package/payload/server/public/assets/packet-4T2RLAQJ-DmkQBx4h.js +1 -0
- package/payload/server/public/assets/page-CsOGSSSb.js +30 -0
- package/payload/server/public/assets/pie-ZZUOXDRM-DDnxYUBm.js +1 -0
- package/payload/server/public/assets/{pieDiagram-DEJITSTG-B9Pl6Qhc.js → pieDiagram-DEJITSTG-CV5DxUVx.js} +1 -1
- package/payload/server/public/assets/public-CjT_WNkz.js +1 -0
- package/payload/server/public/assets/{quadrantDiagram-34T5L4WZ-Drn9T81A.js → quadrantDiagram-34T5L4WZ-BsFMVizF.js} +1 -1
- package/payload/server/public/assets/radar-PYXPWWZC-7H4k0ChM.js +1 -0
- package/payload/server/public/assets/{reduce-T2IuntYP.js → reduce-B3Mw_0s1.js} +1 -1
- package/payload/server/public/assets/{requirementDiagram-MS252O5E-C0PAItJm.js → requirementDiagram-MS252O5E-C5eRRvGc.js} +1 -1
- package/payload/server/public/assets/{sankeyDiagram-XADWPNL6-BR42Mtwd.js → sankeyDiagram-XADWPNL6-CJYv5gpw.js} +1 -1
- package/payload/server/public/assets/{sequenceDiagram-FGHM5R23-c2lR9UOS.js → sequenceDiagram-FGHM5R23-B25563_2.js} +1 -1
- package/payload/server/public/assets/{src-DXUM2BJo.js → src-BKOAoFQc.js} +1 -1
- package/payload/server/public/assets/{stateDiagram-FHFEXIEX-BcHhtqsZ.js → stateDiagram-FHFEXIEX-BLyNJYOA.js} +1 -1
- package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-BSVuxZxz.js +1 -0
- package/payload/server/public/assets/{timeline-definition-GMOUNBTQ-Ax32c10H.js → timeline-definition-GMOUNBTQ-D-HgOM6Q.js} +1 -1
- package/payload/server/public/assets/treeView-SZITEDCU-BLXWTQtW.js +1 -0
- package/payload/server/public/assets/treemap-W4RFUUIX-DiePDF5d.js +1 -0
- package/payload/server/public/assets/{vennDiagram-DHZGUBPP-BxePewPq.js → vennDiagram-DHZGUBPP-Cw1JElYp.js} +1 -1
- package/payload/server/public/assets/wardley-RL74JXVD-OSUWK5LN.js +1 -0
- package/payload/server/public/assets/{wardleyDiagram-NUSXRM2D-DmJwZ2f5.js → wardleyDiagram-NUSXRM2D-BqMWzEko.js} +1 -1
- package/payload/server/public/assets/{xychartDiagram-5P7HB3ND-YjHomudv.js → xychartDiagram-5P7HB3ND-DBp71TLT.js} +1 -1
- package/payload/server/public/browser.html +5 -8
- package/payload/server/public/chat.html +8 -12
- package/payload/server/public/data.html +5 -7
- package/payload/server/public/graph.html +7 -10
- package/payload/server/public/index.html +8 -11
- package/payload/server/public/operator.html +10 -14
- package/payload/server/public/public.html +8 -10
- package/payload/server/server.js +330 -195
- package/payload/server/public/assets/AccessGate-bu988Xo-.js +0 -1
- package/payload/server/public/assets/AdminLoginScreens-BCYaOOuk.js +0 -1
- package/payload/server/public/assets/AdminShell-DSjJ4Biu.js +0 -1
- package/payload/server/public/assets/Checkbox-B4Dbvjls.js +0 -1
- package/payload/server/public/assets/OperatorConversations-XsXP7-P-.js +0 -1
- package/payload/server/public/assets/OperatorConversations-qc_xy7Az.css +0 -1
- package/payload/server/public/assets/admin-m0797WGA.js +0 -1
- package/payload/server/public/assets/architecture-YZFGNWBL-C6nkAxzW.js +0 -1
- package/payload/server/public/assets/audio-attachment-mime-Jm4KJ4YC.js +0 -30
- package/payload/server/public/assets/brand-D8LClgr_.js +0 -9
- package/payload/server/public/assets/brand-DvttVeGB.css +0 -1
- package/payload/server/public/assets/browser-CBjNMPsz.js +0 -1
- package/payload/server/public/assets/channel-Q39xIXyT.js +0 -1
- package/payload/server/public/assets/chat-Sg-RGuV6.js +0 -1
- package/payload/server/public/assets/chunk-426QAEUC-CCYjp9C2.js +0 -1
- package/payload/server/public/assets/chunk-QZHKN3VN-BNBxnHZh.js +0 -1
- package/payload/server/public/assets/classDiagram-6PBFFD2Q-BShusfby.js +0 -1
- package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-D4ivPLFF.js +0 -1
- package/payload/server/public/assets/clone-CjEM8LwB.js +0 -1
- package/payload/server/public/assets/data-CEqE4BDw.js +0 -1
- package/payload/server/public/assets/gitGraph-7Q5UKJZL-Btp3PwZh.js +0 -1
- package/payload/server/public/assets/graph-labels-Bj5yM9bI.js +0 -1
- package/payload/server/public/assets/info-OMHHGYJF-CPt2y6_L.js +0 -1
- package/payload/server/public/assets/infoDiagram-42DDH7IO-CpXNTMgd.js +0 -2
- package/payload/server/public/assets/inter-cyrillic-400-normal-HOLc17fK.woff +0 -0
- package/payload/server/public/assets/inter-cyrillic-400-normal-obahsSVq.woff2 +0 -0
- package/payload/server/public/assets/inter-cyrillic-500-normal-BasfLYem.woff2 +0 -0
- package/payload/server/public/assets/inter-cyrillic-500-normal-CxZf_p3X.woff +0 -0
- package/payload/server/public/assets/inter-cyrillic-ext-400-normal-BQZuk6qB.woff2 +0 -0
- package/payload/server/public/assets/inter-cyrillic-ext-400-normal-DQukG94-.woff +0 -0
- package/payload/server/public/assets/inter-cyrillic-ext-500-normal-B0yAr1jD.woff2 +0 -0
- package/payload/server/public/assets/inter-cyrillic-ext-500-normal-BmqWE9Dz.woff +0 -0
- package/payload/server/public/assets/inter-greek-400-normal-B4URO6DV.woff2 +0 -0
- package/payload/server/public/assets/inter-greek-400-normal-q2sYcFCs.woff +0 -0
- package/payload/server/public/assets/inter-greek-500-normal-BIZE56-Y.woff2 +0 -0
- package/payload/server/public/assets/inter-greek-500-normal-Xzm54t5V.woff +0 -0
- package/payload/server/public/assets/inter-greek-ext-400-normal-DGGRlc-M.woff2 +0 -0
- package/payload/server/public/assets/inter-greek-ext-400-normal-KugGGMne.woff +0 -0
- package/payload/server/public/assets/inter-greek-ext-500-normal-2j5mBUwD.woff +0 -0
- package/payload/server/public/assets/inter-greek-ext-500-normal-C4iEst2y.woff2 +0 -0
- package/payload/server/public/assets/inter-latin-400-normal-C38fXH4l.woff2 +0 -0
- package/payload/server/public/assets/inter-latin-400-normal-CyCys3Eg.woff +0 -0
- package/payload/server/public/assets/inter-latin-500-normal-BL9OpVg8.woff +0 -0
- package/payload/server/public/assets/inter-latin-500-normal-Cerq10X2.woff2 +0 -0
- package/payload/server/public/assets/inter-latin-ext-400-normal-77YHD8bZ.woff +0 -0
- package/payload/server/public/assets/inter-latin-ext-400-normal-C1nco2VV.woff2 +0 -0
- package/payload/server/public/assets/inter-latin-ext-500-normal-BxGbmqWO.woff +0 -0
- package/payload/server/public/assets/inter-latin-ext-500-normal-CV4jyFjo.woff2 +0 -0
- package/payload/server/public/assets/inter-vietnamese-400-normal-Bbgyi5SW.woff +0 -0
- package/payload/server/public/assets/inter-vietnamese-400-normal-DMkecbls.woff2 +0 -0
- package/payload/server/public/assets/inter-vietnamese-500-normal-DOriooB6.woff2 +0 -0
- package/payload/server/public/assets/inter-vietnamese-500-normal-mJboJaSs.woff +0 -0
- package/payload/server/public/assets/newsreader-latin-300-normal-AOSWdb_s.woff +0 -0
- package/payload/server/public/assets/newsreader-latin-300-normal-FGBQ0wlI.woff2 +0 -0
- package/payload/server/public/assets/newsreader-latin-400-normal-BFBkh4jY.woff2 +0 -0
- package/payload/server/public/assets/newsreader-latin-400-normal-gRTjlS2D.woff +0 -0
- package/payload/server/public/assets/newsreader-latin-500-normal-B66TYsaK.woff2 +0 -0
- package/payload/server/public/assets/newsreader-latin-500-normal-DFwuUcdu.woff +0 -0
- package/payload/server/public/assets/newsreader-latin-ext-300-normal-CFtw49Zd.woff +0 -0
- package/payload/server/public/assets/newsreader-latin-ext-300-normal-DRMzurxT.woff2 +0 -0
- package/payload/server/public/assets/newsreader-latin-ext-400-normal-DYA1XoQK.woff +0 -0
- package/payload/server/public/assets/newsreader-latin-ext-400-normal-svq1FPys.woff2 +0 -0
- package/payload/server/public/assets/newsreader-latin-ext-500-normal-BNHmvKvI.woff2 +0 -0
- package/payload/server/public/assets/newsreader-latin-ext-500-normal-CZruMFou.woff +0 -0
- package/payload/server/public/assets/newsreader-vietnamese-300-normal-CsrIkm-V.woff +0 -0
- package/payload/server/public/assets/newsreader-vietnamese-300-normal-D3VHEe81.woff2 +0 -0
- package/payload/server/public/assets/newsreader-vietnamese-400-normal-BekUZro8.woff +0 -0
- package/payload/server/public/assets/newsreader-vietnamese-400-normal-DdKr49mV.woff2 +0 -0
- package/payload/server/public/assets/newsreader-vietnamese-500-normal-BEAbKU8A.woff +0 -0
- package/payload/server/public/assets/newsreader-vietnamese-500-normal-CL6a8tp2.woff2 +0 -0
- package/payload/server/public/assets/operator-Bph7mx87.js +0 -1
- package/payload/server/public/assets/packet-4T2RLAQJ-Cwc-j_AI.js +0 -1
- package/payload/server/public/assets/page-CtWCeXdg.js +0 -1
- package/payload/server/public/assets/pie-ZZUOXDRM-BZ9fjD1_.js +0 -1
- package/payload/server/public/assets/public-gxHCJCs3.js +0 -6
- package/payload/server/public/assets/public-next-C3clISGQ.js +0 -1
- package/payload/server/public/assets/public-vnj7OhQj.css +0 -1
- package/payload/server/public/assets/radar-PYXPWWZC-BNz5Rt9V.js +0 -1
- package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-BUQ_F4eP.js +0 -1
- package/payload/server/public/assets/treeView-SZITEDCU-DcVCQgp1.js +0 -1
- package/payload/server/public/assets/treemap-W4RFUUIX-Bm12mwGd.js +0 -1
- package/payload/server/public/assets/useSelectionMode-BMn70cch.js +0 -5
- package/payload/server/public/assets/wardley-RL74JXVD-47Z3ymtK.js +0 -1
- package/payload/server/public/public-next.html +0 -25
- /package/payload/server/public/assets/{_baseFor-Y5mTRiRv.js → _baseFor-DVaNaTfF.js} +0 -0
- /package/payload/server/public/assets/{admin-types-D2qTXuCg.js → admin-types-CJrGd46U.js} +0 -0
- /package/payload/server/public/assets/{array-BwJyW1Dp.js → array-8_H1156C.js} +0 -0
- /package/payload/server/public/assets/{chunk-CAM3fms7.js → chunk-Pqm5yXtL.js} +0 -0
- /package/payload/server/public/assets/{cytoscape.esm-D95TtHqz.js → cytoscape.esm-h10p_6j-.js} +0 -0
- /package/payload/server/public/assets/{defaultLocale-kiwRz9Au.js → defaultLocale-pD7tFa1r.js} +0 -0
- /package/payload/server/public/assets/{init-CKZirZ49.js → init-CwJ4b81e.js} +0 -0
- /package/payload/server/public/assets/{katex-8mXVa4k3.js → katex-DJPjIBAI.js} +0 -0
- /package/payload/server/public/assets/{path-B0d9ncVi.js → path-CK8wrAxY.js} +0 -0
- /package/payload/server/public/assets/{preload-helper-C5gCWwwF.js → preload-helper-Bf_JiD2A.js} +0 -0
- /package/payload/server/public/assets/{rough.esm-BWqoIFNR.js → rough.esm-Dwml_la6.js} +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: platform-architecture
|
|
3
3
|
description: Use when grounding any documented-surface claim about what Real Agent 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:
|
|
4
|
+
content-hash: sha256:843389dda91c1a02b58a1506c04e3b5d8406dae18b74215c9468981b6918c4be
|
|
5
5
|
brand: realagent-code
|
|
6
6
|
product-name: Real Agent
|
|
7
7
|
---
|
|
@@ -360,7 +360,7 @@ These are enabled during onboarding and can be added or removed at any time. Som
|
|
|
360
360
|
| `business-assistant` | Customer enquiries, scheduling, quoting, invoicing, daily briefings | Personal assistant |
|
|
361
361
|
| `sales` | Buying signal detection, closing techniques, objection handling | Personal assistant |
|
|
362
362
|
| `deep-research` | Structured multi-source research — query decomposition, source evaluation, citations | Research assistant |
|
|
363
|
-
| `projects` | Structured project execution — phased sprints, investigations, reviews, retrospectives | Project manager |
|
|
363
|
+
| `projects` | Structured project execution — phased sprints, investigations, reviews, retrospectives, plus method references for stakeholder mapping, risk pre-mortems, task prioritization, and meeting-to-tasks | Project manager |
|
|
364
364
|
| `telegram` | Telegram bot — BotFather setup, messaging, channels | Personal assistant |
|
|
365
365
|
| `whatsapp` | WhatsApp messaging, pairing, and conversation browsing | Personal assistant |
|
|
366
366
|
| `replicate` | Image generation — three models for photorealistic, design, and fast draft images | Content producer, Research assistant |
|
|
@@ -411,7 +411,7 @@ There is no per-account purchase record; the brand decides the shipping set.
|
|
|
411
411
|
| `teaching` | Skills | Interactive tutoring, lesson planning, and study pack generation from your knowledge base | Yes — all 3 skills serve students and parents |
|
|
412
412
|
| `real-agent` | Bundle (13 sub-plugins) | UK estate agency skills — sales, listings, vendor management, buyer management, lead generation, coaching, business operations, teaching, Loop CRM (five value pillars: auto-respond, viewing lifecycle, pipeline mining, listings prospecting, maintenance & preferences), PropertyData market analytics (valuation, sold prices, £/sqft baselines, £/sqft growth, demand-rent, area risk, planning precedent, UPRN matching, property-type distribution), gov.uk EPC floor-area lookup, property brochures, social-share image cards, A4 market reports, and single-address preval packs (full UK address → 4-page A4 PDF covering valuation, area, and demand). 3 specialist roles (negotiator, valuer, compliance) | 4 sub-plugins (estate-sales, buyers, estate-coaching, estate-teaching) |
|
|
413
413
|
| `writer-craft` | Skills + Agent | Manuscript review and writing craft — story architecture, reader engagement, prose craft, editorial practice, and multi-level review | No — writing craft serves the author |
|
|
414
|
-
| `venture-studio` | Skills + Agent | Founding-a-business workflow — office-hours discovery, brand pack, zero-to-prototype validation,
|
|
414
|
+
| `venture-studio` | Skills + Agent | Founding-a-business workflow — office-hours discovery, brand pack, zero-to-prototype validation, the full investor data room (business plan, prospectus, term sheet, deck blueprint, A4 print pipeline), and a `legal-essentials` skill that drafts an NDA and a UK-GDPR/PECR privacy policy. Carries citation-routed method references for market sizing (TAM/SAM/SOM), pricing, monetization, competitor analysis, battlecards, strategy frameworks (SWOT/PESTLE/Porter's/Ansoff), and a pre-fundraise strategy red-team. Pre-seeds a `Project` with one `Task` per artefact so nothing gets forgotten. | No — founder-facing only |
|
|
415
415
|
| `management-consulting` | Skills | 21 MBB-style strategy skills for client engagements — situation assessment, growth-barrier and assumption diagnosis, market mapping, competitive intel, segmentation, profit-pool analysis, strategic options, pricing, business cases, portfolio review, operating-model design, initiative prioritization, transformation roadmaps, war-gaming, risk registers, KPI design, value realization, stakeholder alignment, executive narrative, and decision memos. No MCP server. | No — consultant-facing only |
|
|
416
416
|
|
|
417
417
|
**How it works:** Every boot Real Agent delivers the brand's premium plugins from staging into `platform/plugins/` and stamps `enabledPlugins` against what is actually on disk. No conversation needed — the brand's full set is active from the first turn after install. Updates and reinstalls re-deliver from staging.
|
|
@@ -2320,10 +2320,12 @@ either is a regression.
|
|
|
2320
2320
|
|
|
2321
2321
|
**`/chat` empty-state greeting panel.** While the admin webchat has no conversation JSONL yet (`GET /api/webchat/session` → `projectDir:null`), `app/chat/page.tsx` renders a "What's up next, {givenName}?" greeting (given name = first whitespace token of the admin session's `userName`) above two read-only lists from `GET /api/webchat/greeting` (`server/routes/webchat-greeting.ts`, `requireAdminSession`-gated, `accountId`-scoped): the next 5 upcoming `:Event` rows (`eventStatus IN ['scheduled','due']`, future `COALESCE(nextRun, startDate)`, soonest first) and the outstanding `:Task` rows (`status IN ['pending','active','running']`, 5 shown + `+N more`). Read failure returns HTTP 200 `{ ok: false }` and the page shows the headline alone — the panel never blocks the composer. A third section, **Your specialists**, shows the account's installed roster — every `*.md` under `data/accounts/<accountId>/specialists/agents/`, core and `--`-prefixed premium files alike — shown by frontmatter `name` + `summary` (fallback `description`), empty dir → "No specialists installed". The roster read (`app/lib/claude-agent/specialist-roster.ts`) is isolated from the graph fallback: malformed files are skipped (`op=specialist-skipped file=<name> reason=<…>`), a whole-roster failure degrades to `specialists: []` inside the `ok: true` payload (`op=specialists-read-failed`). Logs: `[webchat:greeting] op=read account=<id8> events=<n> tasks=<n> specialists=<n> ms=<n>` / `op=read-failed reason=…`; client warns `[admin-ui] greeting-unavailable …`. The full webchat architecture lives in `.docs/admin-webchat-native-channel.md`.
|
|
2322
2322
|
|
|
2323
|
-
**`/chat` Claude-desktop transcript presentation.** The admin webchat keeps the shared `Transcript` shell (stream, follow-tail) but injects a /chat-only item renderer via the component's optional `renderItems` prop: `renderChatTimeline` in `app/chat/transcript-render.tsx`. Presentation: operator turns render as a right-aligned grey bubble showing the message text and, beneath it, a subtle always-visible time-of-day stamp (no label); delivered agent replies render as plain prose with the same time-of-day stamp beneath (the reply-document filename line stays, as prose); the stamp is HH:MM from the turn's `ts` (locale-formatted, right-aligned inside the operator bubble, left-aligned under agent prose), and a turn whose `ts` is null/unparseable shows no stamp, never an empty line — so only delivered operator and agent-reply turns are stamped, while tool runs, the collapsed "Thinking" block, and the agent-error banner stay time-free; a maximal consecutive run of `tool-call`/`tool-result` turns renders as one collapsed grey one-liner ("Used N tools ›") whose expansion shows every call and result payload — a lone call still gets the one-liner, and prose or a directive row ends a run. The WhatsApp reader (`/whatsapp`) omits the prop and keeps the default `renderTimeline`, so its rendering is unchanged; both presentations are test-pinned (`app/whatsapp/__tests__/Transcript-*.test.tsx
|
|
2323
|
+
**`/chat` Claude-desktop transcript presentation.** The admin webchat keeps the shared `Transcript` shell (stream, follow-tail) but injects a /chat-only item renderer via the component's optional `renderItems` prop: `renderChatTimeline` in `app/chat/transcript-render.tsx`. Presentation: operator turns render as a right-aligned grey bubble showing the message text and, beneath it, a subtle always-visible time-of-day stamp (no label); delivered agent replies render as plain prose with the same time-of-day stamp beneath (the reply-document filename line stays, as prose); the stamp is HH:MM from the turn's `ts` (locale-formatted, right-aligned inside the operator bubble, left-aligned under agent prose), and a turn whose `ts` is null/unparseable shows no stamp, never an empty line — so only delivered operator and agent-reply turns are stamped, while tool runs, the collapsed "Thinking" block, and the agent-error banner stay time-free; a maximal consecutive run of `tool-call`/`tool-result` turns renders as one collapsed grey one-liner ("Used N tools ›") whose expansion shows every call and result payload — a lone call still gets the one-liner, and prose or a directive row ends a run. The WhatsApp reader (`/whatsapp`) omits the prop and keeps the default `renderTimeline`, so its rendering is unchanged; both presentations are test-pinned (`app/whatsapp/__tests__/Transcript-*.test.tsx`, `app/chat/__tests__/transcript-render.test.tsx`). **Day-divider:** both renderers insert a centered `.day-divider` row between two consecutive timeline items on different local calendar days (label `Today`/`Yesterday`, else `Sat 14 Jun 2026`), so a thread spanning midnight is never an ambiguous run of HH:MM; the first dated item gets a leading divider, a null/unparseable `ts` marks no boundary, dividers are computed over the filtered `visibleItems`, and in `/chat` a day crossover flushes any open tool/think run first so a collapsed run never spans it. Per-bubble HH:MM stamps are unchanged. Shared helpers `dayKey`/`dayLabel`/`itemTs`/`DayDivider` live in `app/whatsapp/Transcript.tsx`.
|
|
2324
2324
|
|
|
2325
2325
|
**maxy title for public sessions.** A `role=public` webchat spawn never produces a useful Claude Code `ai-title` (an anonymous one-line visitor turn), so every public row would otherwise read identically. The webchat route (`chat.ts`) composes a deterministic title — `Web · <senderId[:8]>[ · <personId>] · <UTC YYYY-MM-DD HH:mm>` (personId present only for gated visitors) — and threads it through the native webchat gateway's public spawn (`handleInbound` → `buildPublicWebchatSpawnRequest` → `managerSpawn`) to the manager `POST /public-spawn` body as `name`. `/spawn` validates it with `validateUserTitle` and, for `role=public` only, writes it into `UserTitleStore` so it occupies the operator-rename tier and wins over `ai-title`. Admin (`/rc-spawn`) and WhatsApp titling are unchanged. Observability: every public spawn logs `[spawn] role=public … title="…"` (or `title=missing`); the manager's row builder emits `[public-title] sessionId=… unexpected titleSource=<ai|null>` on the next list read for any public row that did not resolve from the user tier.
|
|
2326
2326
|
|
|
2327
|
+
**Public visitor surface.** The public-host root (`GET /`), the `/:slug` agent routes, and the admin-host `/public` / `/public-chat` previews all serve one shell, `public.html` → [`app/public-entry.tsx`](../../../ui/app/public-entry.tsx) → `PublicChat`. `PublicChat` reuses `useSession` purely as the magic-link gatekeeper — it drives `AccessGate`, resolves the agent slug from the path, and handles `?token=` verification; once the grant is satisfied it mounts `ChatSurface variant="public"`, whose transcript reads the visitor-scoped, **delivered-only** stream `GET /api/public-reader/stream` ([`server/routes/public-reader.ts`](../../../ui/server/routes/public-reader.ts)) — the visitor sees the agent's delivered prose, never the tool/tool-result/directive bytes the legacy `/api/chat` SSE render exposed. The human visitor's branding is resolved client-side by `useSession`. For the head only, the server injects per-agent link-preview meta — `<title>`, `og:title`/`og:description`/`og:image`, `theme-color`, and a per-agent favicon, resolved from the same branding cache `useSession` reads — into the served shell, so a link-preview crawler (which never runs the client bundle) gets a branded card per agent instead of one generic shell; an agent with no branding cache gets the clean brand-default shell with no empty meta tags. There is exactly one public client surface and it is 1:1 visitor↔agent: the earlier `?surface=next` A/B handle is retired, group messaging is retired (not a supported product surface), and a former `/g/<slug>` group URL now serves the same 1:1 shell — a stale bookmark gets the 1:1 chat, never a broken render.
|
|
2328
|
+
|
|
2327
2329
|
### Graph
|
|
2328
2330
|
|
|
2329
2331
|
| Mount | Purpose |
|
|
@@ -2407,6 +2409,26 @@ the Web Share API and is disabled where unavailable. Signals:
|
|
|
2407
2409
|
`[data-ui] op=mount header=operator home=absent`, `op=select-enter`,
|
|
2408
2410
|
`op=select-exit reason=<cancel|action>`, `op=share supported=<bool> count=<n>`.
|
|
2409
2411
|
|
|
2412
|
+
**`/data` list ↔ grid view + image thumbnails.** A toolbar toggle switches the
|
|
2413
|
+
file browser between the two-line list and a **grid**. In grid view, image
|
|
2414
|
+
files render an inline thumbnail; folders render a folder tile (still navigate
|
|
2415
|
+
on tap); every other file renders a labelled tile (name + size) that downloads
|
|
2416
|
+
on tap. Tapping a thumbnail opens a full-size overlay (reusing the chat
|
|
2417
|
+
attachment overlay), not a download — download stays reachable via long-press →
|
|
2418
|
+
select → Download. The chosen view persists across reload and `/data` ↔ `/`
|
|
2419
|
+
navigation (`localStorage['maxy-data-view']`). A file counts as an image only
|
|
2420
|
+
when its **extension** is one the inline-serve route can serve
|
|
2421
|
+
(`png/jpg/jpeg/gif/webp/svg`, the server's `detectMimeType` image set) — the
|
|
2422
|
+
sidecar `mimeType` is not consulted, so the grid never promises a thumbnail the
|
|
2423
|
+
serve route would refuse. Thumbnails load from the same `/api/admin/files/download`
|
|
2424
|
+
route with `disposition=inline` (`inlineImageUrl`), which for an `image/*` file
|
|
2425
|
+
returns the bytes with **no** `Content-Disposition` and a cacheable header so the
|
|
2426
|
+
browser renders them in an `<img>`; a non-image inline request is refused `400`,
|
|
2427
|
+
and the account-scope guard is identical to the attachment path. Signals:
|
|
2428
|
+
`[data] op=view-mode mode=<grid|list>`, `[data] op=thumb-serve path=… mime=… size=… status=200`,
|
|
2429
|
+
`[data] op=thumb-refused path=… reason=not-image`, and client `[data] op=thumb-error path=…`
|
|
2430
|
+
from a thumbnail that fails to load.
|
|
2431
|
+
|
|
2410
2432
|
**`/data` search — locate-in-files link and clear button.** Every
|
|
2411
2433
|
search hit is a `:FileArtifact` backed by a physical file, so each result card
|
|
2412
2434
|
whose `relativePath` is a non-empty string carries a **locate link** (folder
|
|
@@ -2569,7 +2591,7 @@ authoritative. This section names the surfaces and what backs each.
|
|
|
2569
2591
|
| Nav rows (Chat / People / Agents / Projects / Tasks / Artefacts) | People, Agents, Tasks open the artefact-pane Graph filtered to the matching label. Chat selects the active conversation. Artefacts swaps the list to editable documents. | `graph-search.ts`, `graph-subgraph.ts`, `sidebar-artefacts.ts` |
|
|
2570
2592
|
| Sessions list (Active / Archived / All) | Live row store driven by SSE; manual reconcile button on the segmented control re-fetches the full id set. Every listed row carries two launch actions: the claude.ai/code resume (`ExternalLink`) and a chat-launch (`MessageSquare`) that opens `/chat?session=<full sessionId>` — the admin webchat pointed at that exact session; sending there resumes a stopped session with the webchat channel bound to that id (see `admin-webchat-native-channel.md`, "Session-targeted mode"). At the ≤720 px drawer breakpoint each row stacks into two lines — dot + title + id/stamp, then the action icons — with a divider between rows and actions at full opacity (the desktop hover-gated 0.5 opacity never resolves on touch). Below a 400 px list width each row's action icons collapse to a single `MoreHorizontal` ellipsis trigger; its popover menu lists the same actions as the inline icons but labels them with concise verbs (`Resume in claude.ai/code`, `Open in webchat`, `Stop`, `Archive` / `Unarchive`, `Rename`, `Delete`, `Re-seat`) rather than the inline icon buttons' verbose per-session aria-labels — the inline buttons keep those verbose labels because an icon-only control needs the full descriptive accessible name. **Re-seat:** Re-seat is a member action of the one `SessionRowActions` cluster, not a separate sibling control — wide it is the sliders icon inline with the other icons (sharing the cluster geometry and alignment); collapsed it is the `Re-seat` menu item, which expands the model/mode/effort form inline inside the overflow menu. The form (`SessionReseatControl`) forks the session via `/api/admin/session-reseat` and navigates to the fork (the same fork mechanism `/chat`'s pickers drive); its model picker defaults to the row's current model (a `model` field on each row, read from the JSONL tail), and mode and effort each carry a "Keep" option that omits the field. The overflow menu and the Re-seat form render through a `document.body` portal, fixed-positioned from the trigger's rect (right-aligned, flipped above the trigger when there is no room below), so neither is clipped by `.side-list`'s `overflow-y:auto`; Escape, a pointerdown outside the trigger/popover, and any scroll or resize dismiss them. | `/claude-sessions/events`, `/claude-sessions`, `/session-reseat` |
|
|
2571
2593
|
| Channel reader nav rows (WhatsApp / Telegram) | One conditional nav row **per interactive channel that has ≥1 admin session**. Each row carries its brand glyph (WhatsApp `#25D366`, Telegram `#229ED9`); a channel with no admin session shows no row, and no install ever shows an always-empty "No conversations" row. The channel list loads **once on sidebar mount** (the per-channel counts must be known before the nav renders), so a failed load shows one muted, non-clickable line instead of channel rows. Clicking a channel row lists that channel's admin conversations; each conversation row shows a **display name** resolved by precedence `operatorName ?? whatsappName ?? senderId ?? title`: the bound `Person givenName familyName` when a `senderId`→`userId` binding exists, else the persisted WhatsApp display name (`pushName`, read from the latest `:Message:WhatsAppMessage.senderName`), else the raw `senderId`, else the agent title; the agent session title is the hover tooltip only. Under the name each row shows a **last-message-time breadcrumb** (`conv-timestamp`, same markup as the Sessions rows) formatted from the row's `lastMessageAt` (the last parseable turn's `ts`); a session with no parseable turn shows no time, never "Invalid Date". **Re-seat:** each channel conversation row carries a `SessionRowActions` cluster whose sole action is Re-seat (the row is a `conv-with-actions` shell whose open click moved onto an inner button so the cluster can sit beside it), so a WhatsApp/Telegram session's model/mode/effort is re-seatable from the dashboard exactly like a webchat row — wide it is the inline sliders icon, and below the 400 px width it folds into the `…` overflow menu identically to the Sessions rows; the channel reader row carries the same `model` field for the picker default. A click on a conversation **opens its transcript on the home surface**: on `/` it selects in place, and from any other route (`/graph`, `/data`, `/browser`) it navigates to `/?wa=<sessionId>&projectDir=<dir>`, which the root shell hydrates on mount (then strips the query so a later refresh does not re-pin a closed conversation). Server logs `[wa-reader] op=operator-name-fallback senderId=… source=whatsapp-pushname` when the pushName fallback fires and `[wa-reader] op=conversations count=<n> withTimestamp=<m>` per list build; the client logs `[admin-ui] wa-open route=… via=<in-place\|navigate> …` and `[admin-ui] wa-hydrate route=/ …`. | `/whatsapp-reader/conversations` |
|
|
2572
|
-
| Channel transcript (`<Transcript>`) | Reads one session's JSONL over SSE (`/whatsapp-reader/stream`) and renders both sides plus tool calls — the turns claude.ai/code hides because channel inbound is stamped `isMeta`. Every turn shows its time-of-day (HH:MM from the turn's `ts`; a null/unparseable `ts` shows no time, never "Invalid Date"). `tool-call`/`tool-result` turns render as **collapsed cards** (chevron + label + time, default collapsed, expandable per card; one card's state never affects another) so the human↔agent text is not buried in JSON; the three conversation kinds always render in full. The thread **follows the tail**: it opens at the newest turn and pins to the bottom on each live append **only while the operator is already within 32 px of the bottom** — a scroll up suppresses the jump so reading history is never yanked. While the operator is scrolled up a **jump-to-bottom control** (`.wa-jump`, bottom-right of the viewport) appears; clicking it scrolls to the newest turn and re-arms follow-tail, and it hides again at the bottom. The thread scrolls inside its grid cell (header/sidebar/footer fixed). The stream sends a 20 s heartbeat so an idle Cloudflare tunnel does not idle-drop, tags each frame with a byte-offset `id:`, and resumes from the client's `Last-Event-ID` on reconnect (no duplicate backlog); the client clears the "Stream disconnected" banner on reopen and latches it only on a terminal CLOSED state. The thread also interleaves a collapsed `⚙ directive injected (N B)` row per turn, sorted by timestamp just before the turn it informed; expanding one fetches the exact stored `prompt-optimiser-directive` bytes for that turn. The entries are listed by `GET /whatsapp-reader/directives?sessionId=` and the bytes served by `GET /whatsapp-reader/directive?sessionId=&name=`, both admin-gated and account-scoped; a missing store degrades to no rows. | `/whatsapp-reader/stream`, `/whatsapp-reader/directives`, `/whatsapp-reader/directive` |
|
|
2594
|
+
| Channel transcript (`<Transcript>`) | Reads one session's JSONL over SSE (`/whatsapp-reader/stream`) and renders both sides plus tool calls — the turns claude.ai/code hides because channel inbound is stamped `isMeta`. Every turn shows its time-of-day (HH:MM from the turn's `ts`; a null/unparseable `ts` shows no time, never "Invalid Date"). `tool-call`/`tool-result` turns render as **collapsed cards** (chevron + label + time, default collapsed, expandable per card; one card's state never affects another) so the human↔agent text is not buried in JSON; the three conversation kinds always render in full. The thread **follows the tail**: it opens at the newest turn and pins to the bottom on each live append **only while the operator is already within 32 px of the bottom** — a scroll up suppresses the jump so reading history is never yanked. While the operator is scrolled up a **jump-to-bottom control** (`.wa-jump`, bottom-right of the viewport) appears; clicking it scrolls to the newest turn and re-arms follow-tail, and it hides again at the bottom. The thread scrolls inside its grid cell (header/sidebar/footer fixed). The stream sends a 20 s heartbeat so an idle Cloudflare tunnel does not idle-drop, tags each frame with a byte-offset `id:`, and resumes from the client's `Last-Event-ID` on reconnect (no duplicate backlog); the client clears the "Stream disconnected" banner on reopen and latches it only on a terminal CLOSED state. The thread also interleaves a collapsed `⚙ directive injected (N B)` row per turn, sorted by timestamp just before the turn it informed; expanding one fetches the exact stored `prompt-optimiser-directive` bytes for that turn. The entries are listed by `GET /whatsapp-reader/directives?sessionId=` and the bytes served by `GET /whatsapp-reader/directive?sessionId=&name=`, both admin-gated and account-scoped; a missing store degrades to no rows. A centered day-divider row (`.day-divider`) marks each local calendar-day crossover between consecutive turns so a thread spanning midnight is unambiguous. | `/whatsapp-reader/stream`, `/whatsapp-reader/directives`, `/whatsapp-reader/directive` |
|
|
2573
2595
|
| Conversations row hover actions | Inline rename, archive, delete, JSONL view / download per row. The historical `.conversations-modal` CSS block exists in `globals.css` but is no longer mounted from any TSX — Sidebar.tsx now owns every per-row affordance directly. | `claude-sessions.ts` |
|
|
2574
2596
|
| Artefacts list | Lists every `:FileArtifact` under this account's tree (`relativePath STARTS WITH 'accounts/'`, all file types, excluding the `uploads/<id>/` subtree) plus this account's IDENTITY / SOUL / KNOWLEDGE / specialist templates. Click downloads the row's backing file (`downloadPath` → `GET /api/admin/files/download`) so the operator opens it in their local app; rows whose file is outside `DATA_ROOT` (bundled-fallback templates) show a "can't be downloaded" pill. The in-app artefact pane is dead pending removal. | `sidebar-artefacts.ts`, `files.ts` |
|
|
2575
2597
|
| System-stats widget | CPU / RAM widget at the foot of the sidebar. | `system-stats.ts` (see above) |
|
|
@@ -2841,6 +2863,8 @@ If a session never runs an insight pass, its prose nodes are not lost — the ne
|
|
|
2841
2863
|
| Meeting | MENTIONS | Organization |
|
|
2842
2864
|
| KnowledgeDocument | MENTIONS | Person |
|
|
2843
2865
|
| KnowledgeDocument | MENTIONS | Organization |
|
|
2866
|
+
| ConversationArchive | MENTIONS | Person |
|
|
2867
|
+
| ConversationArchive | MENTIONS | Organization |
|
|
2844
2868
|
| Note | MENTIONS | Person |
|
|
2845
2869
|
| Note | MENTIONS | Organization |
|
|
2846
2870
|
| Idea | MENTIONS | Person |
|
|
@@ -2859,6 +2883,13 @@ If a session never runs an insight pass, its prose nodes are not lost — the ne
|
|
|
2859
2883
|
| Page | REFERENCES | Page |
|
|
2860
2884
|
| Report | REFERENCES | Report |
|
|
2861
2885
|
| Report | REFERENCES | Page |
|
|
2886
|
+
| Person | REPORTS_TO | Person |
|
|
2887
|
+
| Source | AUTHORED_BY | Person |
|
|
2888
|
+
| Project | ADVANCES | Objective |
|
|
2889
|
+
| Project | ADVANCES | KeyResult |
|
|
2890
|
+
| Task | ADVANCES | Objective |
|
|
2891
|
+
| Task | ADVANCES | KeyResult |
|
|
2892
|
+
| Task | DEPENDS_ON | Task |
|
|
2862
2893
|
|
|
2863
2894
|
<!-- TYPED-EDGE-TABLE:END -->
|
|
2864
2895
|
|
|
@@ -3241,15 +3272,22 @@ The admin agent runs via Claude Code CLI, which manages its own system prompt as
|
|
|
3241
3272
|
|
|
3242
3273
|
This is assembled as a `<previous-context>` block in the system prompt on each admin turn.
|
|
3243
3274
|
|
|
3244
|
-
### Public-agent memory context
|
|
3275
|
+
### Public-agent memory context
|
|
3245
3276
|
|
|
3246
3277
|
Public agents historically had their memory context injected by a server-side bridge
|
|
3247
3278
|
(`fetchMemoryContext`) that spawned the memory MCP server with `ALLOWED_SCOPES=public,shared`
|
|
3248
|
-
and ran a `memory-search` on the agent's behalf. That bridge
|
|
3249
|
-
are
|
|
3250
|
-
server-side proxy runs a public-scope memory
|
|
3251
|
-
path ranked against was retired alongside it.
|
|
3252
|
-
|
|
3279
|
+
and ran a `memory-search` on the agent's behalf. That bridge was removed: public agents
|
|
3280
|
+
are toolless (`buildPublicDeny` denies `mcp__memory__*`), so neither the agent nor a
|
|
3281
|
+
server-side proxy runs a public-scope memory search, and the public-scope fulltext index that
|
|
3282
|
+
path ranked against was retired alongside it.
|
|
3283
|
+
|
|
3284
|
+
A gated visitor's per-visitor memory still reaches their next conversation, without any tool
|
|
3285
|
+
and without reopening the ringfence. The session-end reviewer writes per-visitor slice nodes
|
|
3286
|
+
(`{sliceToken, scope:'user'}`); at the next gated spawn the UI process fetches that visitor's
|
|
3287
|
+
own `scope:'user'` slice nodes (a slice-pinned read, not a public-scope search), renders them
|
|
3288
|
+
to a `<previous-context>` block, and threads it through the public spawn body so the manager
|
|
3289
|
+
appends it to the agent's system prompt. Only the visitor's own slice is read; open-mode
|
|
3290
|
+
visitors, admins, and first visits inject nothing.
|
|
3253
3291
|
|
|
3254
3292
|
---
|
|
3255
3293
|
|
|
@@ -3317,7 +3355,7 @@ The Claude Code SDK marks every MCP tool as **deferred** by default. The model c
|
|
|
3317
3355
|
|
|
3318
3356
|
The SDK's per-tool override is `_meta["anthropic/alwaysLoad"]: true` on each MCP tool's `tools/list` entry. Two surfaces apply it:
|
|
3319
3357
|
|
|
3320
|
-
1. **In-process plugins.** Every admin-eager tool is registered via `eagerTool(server, name, description, inputSchema, handler)` from `platform/lib/mcp-eager/` instead of `server.tool(...)`. The helper calls `server.registerTool` with the `_meta` flag set.
|
|
3358
|
+
1. **In-process plugins.** Every admin-eager tool is registered via `eagerTool(server, name, description, inputSchema, handler)` from `platform/lib/mcp-eager/` instead of `server.tool(...)`. The helper calls `server.registerTool` with the `_meta` flag set. Both `eagerTool` and the non-eager `lifelineTool` (from `platform/lib/mcp-lifeline/`) wrap the handler with `wrapWithLifeline`, which emits a structured `op=request`/`op=result` log pair per call including a holdings census — see `.docs/mcp-helper-observability.md` "Tool-call lifeline".
|
|
3321
3359
|
2. **Upstream graph proxy.** The upstream Python `mcp-neo4j-cypher` server has no `_meta` channel, so `platform/lib/graph-mcp/src/index.ts` intercepts every `tools/list` response on the wire and injects `_meta["anthropic/alwaysLoad"]: true` into each tool entry. The `[graph-mcp] tools/list eager-flagged count=<N>` stderr line confirms the injection fired.
|
|
3322
3360
|
|
|
3323
3361
|
**Curation rule.** Every MCP tool the admin agent calls routinely should be eager — registered via `eagerTool` (or arriving through the graph-mcp interceptor). Whether a tool is eager is decided at its registration site in the plugin's MCP `index.ts` (`eagerTool` vs `server.tool`); there is no separate allow-list constant. Admin-skill / specialist / public-agent tools that stay on `server.tool()` pay the ToolSearch tax only when their caller invokes them. The admin tool surface (`toolSurface.admin`, the `adminAllowlist: true` set) is the intended eager set; a routinely-called admin tool left on `server.tool()` is a gap to fix at the registration site.
|
|
@@ -55,10 +55,12 @@ either is a regression.
|
|
|
55
55
|
|
|
56
56
|
**`/chat` empty-state greeting panel.** While the admin webchat has no conversation JSONL yet (`GET /api/webchat/session` → `projectDir:null`), `app/chat/page.tsx` renders a "What's up next, {givenName}?" greeting (given name = first whitespace token of the admin session's `userName`) above two read-only lists from `GET /api/webchat/greeting` (`server/routes/webchat-greeting.ts`, `requireAdminSession`-gated, `accountId`-scoped): the next 5 upcoming `:Event` rows (`eventStatus IN ['scheduled','due']`, future `COALESCE(nextRun, startDate)`, soonest first) and the outstanding `:Task` rows (`status IN ['pending','active','running']`, 5 shown + `+N more`). Read failure returns HTTP 200 `{ ok: false }` and the page shows the headline alone — the panel never blocks the composer. A third section, **Your specialists**, shows the account's installed roster — every `*.md` under `data/accounts/<accountId>/specialists/agents/`, core and `--`-prefixed premium files alike — shown by frontmatter `name` + `summary` (fallback `description`), empty dir → "No specialists installed". The roster read (`app/lib/claude-agent/specialist-roster.ts`) is isolated from the graph fallback: malformed files are skipped (`op=specialist-skipped file=<name> reason=<…>`), a whole-roster failure degrades to `specialists: []` inside the `ok: true` payload (`op=specialists-read-failed`). Logs: `[webchat:greeting] op=read account=<id8> events=<n> tasks=<n> specialists=<n> ms=<n>` / `op=read-failed reason=…`; client warns `[admin-ui] greeting-unavailable …`. The full webchat architecture lives in `.docs/admin-webchat-native-channel.md`.
|
|
57
57
|
|
|
58
|
-
**`/chat` Claude-desktop transcript presentation.** The admin webchat keeps the shared `Transcript` shell (stream, follow-tail) but injects a /chat-only item renderer via the component's optional `renderItems` prop: `renderChatTimeline` in `app/chat/transcript-render.tsx`. Presentation: operator turns render as a right-aligned grey bubble showing the message text and, beneath it, a subtle always-visible time-of-day stamp (no label); delivered agent replies render as plain prose with the same time-of-day stamp beneath (the reply-document filename line stays, as prose); the stamp is HH:MM from the turn's `ts` (locale-formatted, right-aligned inside the operator bubble, left-aligned under agent prose), and a turn whose `ts` is null/unparseable shows no stamp, never an empty line — so only delivered operator and agent-reply turns are stamped, while tool runs, the collapsed "Thinking" block, and the agent-error banner stay time-free; a maximal consecutive run of `tool-call`/`tool-result` turns renders as one collapsed grey one-liner ("Used N tools ›") whose expansion shows every call and result payload — a lone call still gets the one-liner, and prose or a directive row ends a run. The WhatsApp reader (`/whatsapp`) omits the prop and keeps the default `renderTimeline`, so its rendering is unchanged; both presentations are test-pinned (`app/whatsapp/__tests__/Transcript-*.test.tsx
|
|
58
|
+
**`/chat` Claude-desktop transcript presentation.** The admin webchat keeps the shared `Transcript` shell (stream, follow-tail) but injects a /chat-only item renderer via the component's optional `renderItems` prop: `renderChatTimeline` in `app/chat/transcript-render.tsx`. Presentation: operator turns render as a right-aligned grey bubble showing the message text and, beneath it, a subtle always-visible time-of-day stamp (no label); delivered agent replies render as plain prose with the same time-of-day stamp beneath (the reply-document filename line stays, as prose); the stamp is HH:MM from the turn's `ts` (locale-formatted, right-aligned inside the operator bubble, left-aligned under agent prose), and a turn whose `ts` is null/unparseable shows no stamp, never an empty line — so only delivered operator and agent-reply turns are stamped, while tool runs, the collapsed "Thinking" block, and the agent-error banner stay time-free; a maximal consecutive run of `tool-call`/`tool-result` turns renders as one collapsed grey one-liner ("Used N tools ›") whose expansion shows every call and result payload — a lone call still gets the one-liner, and prose or a directive row ends a run. The WhatsApp reader (`/whatsapp`) omits the prop and keeps the default `renderTimeline`, so its rendering is unchanged; both presentations are test-pinned (`app/whatsapp/__tests__/Transcript-*.test.tsx`, `app/chat/__tests__/transcript-render.test.tsx`). **Day-divider:** both renderers insert a centered `.day-divider` row between two consecutive timeline items on different local calendar days (label `Today`/`Yesterday`, else `Sat 14 Jun 2026`), so a thread spanning midnight is never an ambiguous run of HH:MM; the first dated item gets a leading divider, a null/unparseable `ts` marks no boundary, dividers are computed over the filtered `visibleItems`, and in `/chat` a day crossover flushes any open tool/think run first so a collapsed run never spans it. Per-bubble HH:MM stamps are unchanged. Shared helpers `dayKey`/`dayLabel`/`itemTs`/`DayDivider` live in `app/whatsapp/Transcript.tsx`.
|
|
59
59
|
|
|
60
60
|
**maxy title for public sessions.** A `role=public` webchat spawn never produces a useful Claude Code `ai-title` (an anonymous one-line visitor turn), so every public row would otherwise read identically. The webchat route (`chat.ts`) composes a deterministic title — `Web · <senderId[:8]>[ · <personId>] · <UTC YYYY-MM-DD HH:mm>` (personId present only for gated visitors) — and threads it through the native webchat gateway's public spawn (`handleInbound` → `buildPublicWebchatSpawnRequest` → `managerSpawn`) to the manager `POST /public-spawn` body as `name`. `/spawn` validates it with `validateUserTitle` and, for `role=public` only, writes it into `UserTitleStore` so it occupies the operator-rename tier and wins over `ai-title`. Admin (`/rc-spawn`) and WhatsApp titling are unchanged. Observability: every public spawn logs `[spawn] role=public … title="…"` (or `title=missing`); the manager's row builder emits `[public-title] sessionId=… unexpected titleSource=<ai|null>` on the next list read for any public row that did not resolve from the user tier.
|
|
61
61
|
|
|
62
|
+
**Public visitor surface.** The public-host root (`GET /`), the `/:slug` agent routes, and the admin-host `/public` / `/public-chat` previews all serve one shell, `public.html` → [`app/public-entry.tsx`](../../../ui/app/public-entry.tsx) → `PublicChat`. `PublicChat` reuses `useSession` purely as the magic-link gatekeeper — it drives `AccessGate`, resolves the agent slug from the path, and handles `?token=` verification; once the grant is satisfied it mounts `ChatSurface variant="public"`, whose transcript reads the visitor-scoped, **delivered-only** stream `GET /api/public-reader/stream` ([`server/routes/public-reader.ts`](../../../ui/server/routes/public-reader.ts)) — the visitor sees the agent's delivered prose, never the tool/tool-result/directive bytes the legacy `/api/chat` SSE render exposed. The human visitor's branding is resolved client-side by `useSession`. For the head only, the server injects per-agent link-preview meta — `<title>`, `og:title`/`og:description`/`og:image`, `theme-color`, and a per-agent favicon, resolved from the same branding cache `useSession` reads — into the served shell, so a link-preview crawler (which never runs the client bundle) gets a branded card per agent instead of one generic shell; an agent with no branding cache gets the clean brand-default shell with no empty meta tags. There is exactly one public client surface and it is 1:1 visitor↔agent: the earlier `?surface=next` A/B handle is retired, group messaging is retired (not a supported product surface), and a former `/g/<slug>` group URL now serves the same 1:1 shell — a stale bookmark gets the 1:1 chat, never a broken render.
|
|
63
|
+
|
|
62
64
|
### Graph
|
|
63
65
|
|
|
64
66
|
| Mount | Purpose |
|
|
@@ -142,6 +144,26 @@ the Web Share API and is disabled where unavailable. Signals:
|
|
|
142
144
|
`[data-ui] op=mount header=operator home=absent`, `op=select-enter`,
|
|
143
145
|
`op=select-exit reason=<cancel|action>`, `op=share supported=<bool> count=<n>`.
|
|
144
146
|
|
|
147
|
+
**`/data` list ↔ grid view + image thumbnails.** A toolbar toggle switches the
|
|
148
|
+
file browser between the two-line list and a **grid**. In grid view, image
|
|
149
|
+
files render an inline thumbnail; folders render a folder tile (still navigate
|
|
150
|
+
on tap); every other file renders a labelled tile (name + size) that downloads
|
|
151
|
+
on tap. Tapping a thumbnail opens a full-size overlay (reusing the chat
|
|
152
|
+
attachment overlay), not a download — download stays reachable via long-press →
|
|
153
|
+
select → Download. The chosen view persists across reload and `/data` ↔ `/`
|
|
154
|
+
navigation (`localStorage['maxy-data-view']`). A file counts as an image only
|
|
155
|
+
when its **extension** is one the inline-serve route can serve
|
|
156
|
+
(`png/jpg/jpeg/gif/webp/svg`, the server's `detectMimeType` image set) — the
|
|
157
|
+
sidecar `mimeType` is not consulted, so the grid never promises a thumbnail the
|
|
158
|
+
serve route would refuse. Thumbnails load from the same `/api/admin/files/download`
|
|
159
|
+
route with `disposition=inline` (`inlineImageUrl`), which for an `image/*` file
|
|
160
|
+
returns the bytes with **no** `Content-Disposition` and a cacheable header so the
|
|
161
|
+
browser renders them in an `<img>`; a non-image inline request is refused `400`,
|
|
162
|
+
and the account-scope guard is identical to the attachment path. Signals:
|
|
163
|
+
`[data] op=view-mode mode=<grid|list>`, `[data] op=thumb-serve path=… mime=… size=… status=200`,
|
|
164
|
+
`[data] op=thumb-refused path=… reason=not-image`, and client `[data] op=thumb-error path=…`
|
|
165
|
+
from a thumbnail that fails to load.
|
|
166
|
+
|
|
145
167
|
**`/data` search — locate-in-files link and clear button.** Every
|
|
146
168
|
search hit is a `:FileArtifact` backed by a physical file, so each result card
|
|
147
169
|
whose `relativePath` is a non-empty string carries a **locate link** (folder
|
|
@@ -304,7 +326,7 @@ authoritative. This section names the surfaces and what backs each.
|
|
|
304
326
|
| Nav rows (Chat / People / Agents / Projects / Tasks / Artefacts) | People, Agents, Tasks open the artefact-pane Graph filtered to the matching label. Chat selects the active conversation. Artefacts swaps the list to editable documents. | `graph-search.ts`, `graph-subgraph.ts`, `sidebar-artefacts.ts` |
|
|
305
327
|
| Sessions list (Active / Archived / All) | Live row store driven by SSE; manual reconcile button on the segmented control re-fetches the full id set. Every listed row carries two launch actions: the claude.ai/code resume (`ExternalLink`) and a chat-launch (`MessageSquare`) that opens `/chat?session=<full sessionId>` — the admin webchat pointed at that exact session; sending there resumes a stopped session with the webchat channel bound to that id (see `admin-webchat-native-channel.md`, "Session-targeted mode"). At the ≤720 px drawer breakpoint each row stacks into two lines — dot + title + id/stamp, then the action icons — with a divider between rows and actions at full opacity (the desktop hover-gated 0.5 opacity never resolves on touch). Below a 400 px list width each row's action icons collapse to a single `MoreHorizontal` ellipsis trigger; its popover menu lists the same actions as the inline icons but labels them with concise verbs (`Resume in claude.ai/code`, `Open in webchat`, `Stop`, `Archive` / `Unarchive`, `Rename`, `Delete`, `Re-seat`) rather than the inline icon buttons' verbose per-session aria-labels — the inline buttons keep those verbose labels because an icon-only control needs the full descriptive accessible name. **Re-seat:** Re-seat is a member action of the one `SessionRowActions` cluster, not a separate sibling control — wide it is the sliders icon inline with the other icons (sharing the cluster geometry and alignment); collapsed it is the `Re-seat` menu item, which expands the model/mode/effort form inline inside the overflow menu. The form (`SessionReseatControl`) forks the session via `/api/admin/session-reseat` and navigates to the fork (the same fork mechanism `/chat`'s pickers drive); its model picker defaults to the row's current model (a `model` field on each row, read from the JSONL tail), and mode and effort each carry a "Keep" option that omits the field. The overflow menu and the Re-seat form render through a `document.body` portal, fixed-positioned from the trigger's rect (right-aligned, flipped above the trigger when there is no room below), so neither is clipped by `.side-list`'s `overflow-y:auto`; Escape, a pointerdown outside the trigger/popover, and any scroll or resize dismiss them. | `/claude-sessions/events`, `/claude-sessions`, `/session-reseat` |
|
|
306
328
|
| Channel reader nav rows (WhatsApp / Telegram) | One conditional nav row **per interactive channel that has ≥1 admin session**. Each row carries its brand glyph (WhatsApp `#25D366`, Telegram `#229ED9`); a channel with no admin session shows no row, and no install ever shows an always-empty "No conversations" row. The channel list loads **once on sidebar mount** (the per-channel counts must be known before the nav renders), so a failed load shows one muted, non-clickable line instead of channel rows. Clicking a channel row lists that channel's admin conversations; each conversation row shows a **display name** resolved by precedence `operatorName ?? whatsappName ?? senderId ?? title`: the bound `Person givenName familyName` when a `senderId`→`userId` binding exists, else the persisted WhatsApp display name (`pushName`, read from the latest `:Message:WhatsAppMessage.senderName`), else the raw `senderId`, else the agent title; the agent session title is the hover tooltip only. Under the name each row shows a **last-message-time breadcrumb** (`conv-timestamp`, same markup as the Sessions rows) formatted from the row's `lastMessageAt` (the last parseable turn's `ts`); a session with no parseable turn shows no time, never "Invalid Date". **Re-seat:** each channel conversation row carries a `SessionRowActions` cluster whose sole action is Re-seat (the row is a `conv-with-actions` shell whose open click moved onto an inner button so the cluster can sit beside it), so a WhatsApp/Telegram session's model/mode/effort is re-seatable from the dashboard exactly like a webchat row — wide it is the inline sliders icon, and below the 400 px width it folds into the `…` overflow menu identically to the Sessions rows; the channel reader row carries the same `model` field for the picker default. A click on a conversation **opens its transcript on the home surface**: on `/` it selects in place, and from any other route (`/graph`, `/data`, `/browser`) it navigates to `/?wa=<sessionId>&projectDir=<dir>`, which the root shell hydrates on mount (then strips the query so a later refresh does not re-pin a closed conversation). Server logs `[wa-reader] op=operator-name-fallback senderId=… source=whatsapp-pushname` when the pushName fallback fires and `[wa-reader] op=conversations count=<n> withTimestamp=<m>` per list build; the client logs `[admin-ui] wa-open route=… via=<in-place\|navigate> …` and `[admin-ui] wa-hydrate route=/ …`. | `/whatsapp-reader/conversations` |
|
|
307
|
-
| Channel transcript (`<Transcript>`) | Reads one session's JSONL over SSE (`/whatsapp-reader/stream`) and renders both sides plus tool calls — the turns claude.ai/code hides because channel inbound is stamped `isMeta`. Every turn shows its time-of-day (HH:MM from the turn's `ts`; a null/unparseable `ts` shows no time, never "Invalid Date"). `tool-call`/`tool-result` turns render as **collapsed cards** (chevron + label + time, default collapsed, expandable per card; one card's state never affects another) so the human↔agent text is not buried in JSON; the three conversation kinds always render in full. The thread **follows the tail**: it opens at the newest turn and pins to the bottom on each live append **only while the operator is already within 32 px of the bottom** — a scroll up suppresses the jump so reading history is never yanked. While the operator is scrolled up a **jump-to-bottom control** (`.wa-jump`, bottom-right of the viewport) appears; clicking it scrolls to the newest turn and re-arms follow-tail, and it hides again at the bottom. The thread scrolls inside its grid cell (header/sidebar/footer fixed). The stream sends a 20 s heartbeat so an idle Cloudflare tunnel does not idle-drop, tags each frame with a byte-offset `id:`, and resumes from the client's `Last-Event-ID` on reconnect (no duplicate backlog); the client clears the "Stream disconnected" banner on reopen and latches it only on a terminal CLOSED state. The thread also interleaves a collapsed `⚙ directive injected (N B)` row per turn, sorted by timestamp just before the turn it informed; expanding one fetches the exact stored `prompt-optimiser-directive` bytes for that turn. The entries are listed by `GET /whatsapp-reader/directives?sessionId=` and the bytes served by `GET /whatsapp-reader/directive?sessionId=&name=`, both admin-gated and account-scoped; a missing store degrades to no rows. | `/whatsapp-reader/stream`, `/whatsapp-reader/directives`, `/whatsapp-reader/directive` |
|
|
329
|
+
| Channel transcript (`<Transcript>`) | Reads one session's JSONL over SSE (`/whatsapp-reader/stream`) and renders both sides plus tool calls — the turns claude.ai/code hides because channel inbound is stamped `isMeta`. Every turn shows its time-of-day (HH:MM from the turn's `ts`; a null/unparseable `ts` shows no time, never "Invalid Date"). `tool-call`/`tool-result` turns render as **collapsed cards** (chevron + label + time, default collapsed, expandable per card; one card's state never affects another) so the human↔agent text is not buried in JSON; the three conversation kinds always render in full. The thread **follows the tail**: it opens at the newest turn and pins to the bottom on each live append **only while the operator is already within 32 px of the bottom** — a scroll up suppresses the jump so reading history is never yanked. While the operator is scrolled up a **jump-to-bottom control** (`.wa-jump`, bottom-right of the viewport) appears; clicking it scrolls to the newest turn and re-arms follow-tail, and it hides again at the bottom. The thread scrolls inside its grid cell (header/sidebar/footer fixed). The stream sends a 20 s heartbeat so an idle Cloudflare tunnel does not idle-drop, tags each frame with a byte-offset `id:`, and resumes from the client's `Last-Event-ID` on reconnect (no duplicate backlog); the client clears the "Stream disconnected" banner on reopen and latches it only on a terminal CLOSED state. The thread also interleaves a collapsed `⚙ directive injected (N B)` row per turn, sorted by timestamp just before the turn it informed; expanding one fetches the exact stored `prompt-optimiser-directive` bytes for that turn. The entries are listed by `GET /whatsapp-reader/directives?sessionId=` and the bytes served by `GET /whatsapp-reader/directive?sessionId=&name=`, both admin-gated and account-scoped; a missing store degrades to no rows. A centered day-divider row (`.day-divider`) marks each local calendar-day crossover between consecutive turns so a thread spanning midnight is unambiguous. | `/whatsapp-reader/stream`, `/whatsapp-reader/directives`, `/whatsapp-reader/directive` |
|
|
308
330
|
| Conversations row hover actions | Inline rename, archive, delete, JSONL view / download per row. The historical `.conversations-modal` CSS block exists in `globals.css` but is no longer mounted from any TSX — Sidebar.tsx now owns every per-row affordance directly. | `claude-sessions.ts` |
|
|
309
331
|
| Artefacts list | Lists every `:FileArtifact` under this account's tree (`relativePath STARTS WITH 'accounts/'`, all file types, excluding the `uploads/<id>/` subtree) plus this account's IDENTITY / SOUL / KNOWLEDGE / specialist templates. Click downloads the row's backing file (`downloadPath` → `GET /api/admin/files/download`) so the operator opens it in their local app; rows whose file is outside `DATA_ROOT` (bundled-fallback templates) show a "can't be downloaded" pill. The in-app artefact pane is dead pending removal. | `sidebar-artefacts.ts`, `files.ts` |
|
|
310
332
|
| System-stats widget | CPU / RAM widget at the foot of the sidebar. | `system-stats.ts` (see above) |
|
|
@@ -373,15 +373,22 @@ The admin agent runs via Claude Code CLI, which manages its own system prompt as
|
|
|
373
373
|
|
|
374
374
|
This is assembled as a `<previous-context>` block in the system prompt on each admin turn.
|
|
375
375
|
|
|
376
|
-
### Public-agent memory context
|
|
376
|
+
### Public-agent memory context
|
|
377
377
|
|
|
378
378
|
Public agents historically had their memory context injected by a server-side bridge
|
|
379
379
|
(`fetchMemoryContext`) that spawned the memory MCP server with `ALLOWED_SCOPES=public,shared`
|
|
380
|
-
and ran a `memory-search` on the agent's behalf. That bridge
|
|
381
|
-
are
|
|
382
|
-
server-side proxy runs a public-scope memory
|
|
383
|
-
path ranked against was retired alongside it.
|
|
384
|
-
|
|
380
|
+
and ran a `memory-search` on the agent's behalf. That bridge was removed: public agents
|
|
381
|
+
are toolless (`buildPublicDeny` denies `mcp__memory__*`), so neither the agent nor a
|
|
382
|
+
server-side proxy runs a public-scope memory search, and the public-scope fulltext index that
|
|
383
|
+
path ranked against was retired alongside it.
|
|
384
|
+
|
|
385
|
+
A gated visitor's per-visitor memory still reaches their next conversation, without any tool
|
|
386
|
+
and without reopening the ringfence. The session-end reviewer writes per-visitor slice nodes
|
|
387
|
+
(`{sliceToken, scope:'user'}`); at the next gated spawn the UI process fetches that visitor's
|
|
388
|
+
own `scope:'user'` slice nodes (a slice-pinned read, not a public-scope search), renders them
|
|
389
|
+
to a `<previous-context>` block, and threads it through the public spawn body so the manager
|
|
390
|
+
appends it to the agent's system prompt. Only the visitor's own slice is read; open-mode
|
|
391
|
+
visitors, admins, and first visits inject nothing.
|
|
385
392
|
|
|
386
393
|
---
|
|
387
394
|
|
|
@@ -449,7 +456,7 @@ The Claude Code SDK marks every MCP tool as **deferred** by default. The model c
|
|
|
449
456
|
|
|
450
457
|
The SDK's per-tool override is `_meta["anthropic/alwaysLoad"]: true` on each MCP tool's `tools/list` entry. Two surfaces apply it:
|
|
451
458
|
|
|
452
|
-
1. **In-process plugins.** Every admin-eager tool is registered via `eagerTool(server, name, description, inputSchema, handler)` from `platform/lib/mcp-eager/` instead of `server.tool(...)`. The helper calls `server.registerTool` with the `_meta` flag set.
|
|
459
|
+
1. **In-process plugins.** Every admin-eager tool is registered via `eagerTool(server, name, description, inputSchema, handler)` from `platform/lib/mcp-eager/` instead of `server.tool(...)`. The helper calls `server.registerTool` with the `_meta` flag set. Both `eagerTool` and the non-eager `lifelineTool` (from `platform/lib/mcp-lifeline/`) wrap the handler with `wrapWithLifeline`, which emits a structured `op=request`/`op=result` log pair per call including a holdings census — see `.docs/mcp-helper-observability.md` "Tool-call lifeline".
|
|
453
460
|
2. **Upstream graph proxy.** The upstream Python `mcp-neo4j-cypher` server has no `_meta` channel, so `platform/lib/graph-mcp/src/index.ts` intercepts every `tools/list` response on the wire and injects `_meta["anthropic/alwaysLoad"]: true` into each tool entry. The `[graph-mcp] tools/list eager-flagged count=<N>` stderr line confirms the injection fired.
|
|
454
461
|
|
|
455
462
|
**Curation rule.** Every MCP tool the admin agent calls routinely should be eager — registered via `eagerTool` (or arriving through the graph-mcp interceptor). Whether a tool is eager is decided at its registration site in the plugin's MCP `index.ts` (`eagerTool` vs `server.tool`); there is no separate allow-list constant. Admin-skill / specialist / public-agent tools that stay on `server.tool()` pay the ToolSearch tax only when their caller invokes them. The admin tool surface (`toolSurface.admin`, the `adminAllowlist: true` set) is the intended eager set; a routinely-called admin tool left on `server.tool()` is a gap to fix at the registration site.
|
|
@@ -41,6 +41,8 @@ If a session never runs an insight pass, its prose nodes are not lost — the ne
|
|
|
41
41
|
| Meeting | MENTIONS | Organization |
|
|
42
42
|
| KnowledgeDocument | MENTIONS | Person |
|
|
43
43
|
| KnowledgeDocument | MENTIONS | Organization |
|
|
44
|
+
| ConversationArchive | MENTIONS | Person |
|
|
45
|
+
| ConversationArchive | MENTIONS | Organization |
|
|
44
46
|
| Note | MENTIONS | Person |
|
|
45
47
|
| Note | MENTIONS | Organization |
|
|
46
48
|
| Idea | MENTIONS | Person |
|
|
@@ -59,5 +61,12 @@ If a session never runs an insight pass, its prose nodes are not lost — the ne
|
|
|
59
61
|
| Page | REFERENCES | Page |
|
|
60
62
|
| Report | REFERENCES | Report |
|
|
61
63
|
| Report | REFERENCES | Page |
|
|
64
|
+
| Person | REPORTS_TO | Person |
|
|
65
|
+
| Source | AUTHORED_BY | Person |
|
|
66
|
+
| Project | ADVANCES | Objective |
|
|
67
|
+
| Project | ADVANCES | KeyResult |
|
|
68
|
+
| Task | ADVANCES | Objective |
|
|
69
|
+
| Task | ADVANCES | KeyResult |
|
|
70
|
+
| Task | DEPENDS_ON | Task |
|
|
62
71
|
|
|
63
72
|
<!-- TYPED-EDGE-TABLE:END -->
|
|
@@ -38,7 +38,7 @@ These are enabled during onboarding and can be added or removed at any time. Som
|
|
|
38
38
|
| `business-assistant` | Customer enquiries, scheduling, quoting, invoicing, daily briefings | Personal assistant |
|
|
39
39
|
| `sales` | Buying signal detection, closing techniques, objection handling | Personal assistant |
|
|
40
40
|
| `deep-research` | Structured multi-source research — query decomposition, source evaluation, citations | Research assistant |
|
|
41
|
-
| `projects` | Structured project execution — phased sprints, investigations, reviews, retrospectives | Project manager |
|
|
41
|
+
| `projects` | Structured project execution — phased sprints, investigations, reviews, retrospectives, plus method references for stakeholder mapping, risk pre-mortems, task prioritization, and meeting-to-tasks | Project manager |
|
|
42
42
|
| `telegram` | Telegram bot — BotFather setup, messaging, channels | Personal assistant |
|
|
43
43
|
| `whatsapp` | WhatsApp messaging, pairing, and conversation browsing | Personal assistant |
|
|
44
44
|
| `replicate` | Image generation — three models for photorealistic, design, and fast draft images | Content producer, Research assistant |
|
|
@@ -89,7 +89,7 @@ There is no per-account purchase record; the brand decides the shipping set.
|
|
|
89
89
|
| `teaching` | Skills | Interactive tutoring, lesson planning, and study pack generation from your knowledge base | Yes — all 3 skills serve students and parents |
|
|
90
90
|
| `real-agent` | Bundle (13 sub-plugins) | UK estate agency skills — sales, listings, vendor management, buyer management, lead generation, coaching, business operations, teaching, Loop CRM (five value pillars: auto-respond, viewing lifecycle, pipeline mining, listings prospecting, maintenance & preferences), PropertyData market analytics (valuation, sold prices, £/sqft baselines, £/sqft growth, demand-rent, area risk, planning precedent, UPRN matching, property-type distribution), gov.uk EPC floor-area lookup, property brochures, social-share image cards, A4 market reports, and single-address preval packs (full UK address → 4-page A4 PDF covering valuation, area, and demand). 3 specialist roles (negotiator, valuer, compliance) | 4 sub-plugins (estate-sales, buyers, estate-coaching, estate-teaching) |
|
|
91
91
|
| `writer-craft` | Skills + Agent | Manuscript review and writing craft — story architecture, reader engagement, prose craft, editorial practice, and multi-level review | No — writing craft serves the author |
|
|
92
|
-
| `venture-studio` | Skills + Agent | Founding-a-business workflow — office-hours discovery, brand pack, zero-to-prototype validation,
|
|
92
|
+
| `venture-studio` | Skills + Agent | Founding-a-business workflow — office-hours discovery, brand pack, zero-to-prototype validation, the full investor data room (business plan, prospectus, term sheet, deck blueprint, A4 print pipeline), and a `legal-essentials` skill that drafts an NDA and a UK-GDPR/PECR privacy policy. Carries citation-routed method references for market sizing (TAM/SAM/SOM), pricing, monetization, competitor analysis, battlecards, strategy frameworks (SWOT/PESTLE/Porter's/Ansoff), and a pre-fundraise strategy red-team. Pre-seeds a `Project` with one `Task` per artefact so nothing gets forgotten. | No — founder-facing only |
|
|
93
93
|
| `management-consulting` | Skills | 21 MBB-style strategy skills for client engagements — situation assessment, growth-barrier and assumption diagnosis, market mapping, competitive intel, segmentation, profit-pool analysis, strategic options, pricing, business cases, portfolio review, operating-model design, initiative prioritization, transformation roadmaps, war-gaming, risk registers, KPI design, value realization, stakeholder alignment, executive narrative, and decision memos. No MCP server. | No — consultant-facing only |
|
|
94
94
|
|
|
95
95
|
**How it works:** Every boot {{productName}} delivers the brand's premium plugins from staging into `platform/plugins/` and stamps `enabledPlugins` against what is actually on disk. No conversation needed — the brand's full set is active from the first turn after install. Updates and reinstalls re-deliver from staging.
|