@rubytech/create-maxy-code 0.1.49 → 0.1.57

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 (317) hide show
  1. package/dist/__tests__/platform-port-stamp.test.js +24 -0
  2. package/dist/index.js +5 -2
  3. package/dist/port-resolution.js +2 -0
  4. package/package.json +1 -1
  5. package/payload/platform/lib/require-port-env/dist/index.d.ts +31 -0
  6. package/payload/platform/lib/require-port-env/dist/index.d.ts.map +1 -0
  7. package/payload/platform/lib/require-port-env/dist/index.js +52 -0
  8. package/payload/platform/lib/require-port-env/dist/index.js.map +1 -0
  9. package/payload/platform/lib/require-port-env/src/index.ts +56 -0
  10. package/payload/platform/lib/require-port-env/tsconfig.json +8 -0
  11. package/payload/platform/package-lock.json +0 -1
  12. package/payload/platform/package.json +2 -3
  13. package/payload/platform/plugins/admin/PLUGIN.md +16 -3
  14. package/payload/platform/plugins/admin/hooks/__tests__/turn-completed-graph-write.test.sh +184 -146
  15. package/payload/platform/plugins/admin/hooks/turn-completed-graph-write.sh +186 -112
  16. package/payload/platform/plugins/admin/mcp/dist/index.js +20 -12
  17. package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
  18. package/payload/platform/plugins/brochures/PLUGIN.md +2 -0
  19. package/payload/platform/plugins/brochures/skills/property-market-report/SKILL.md +100 -0
  20. package/payload/platform/plugins/brochures/skills/property-market-report/references/render.py +267 -0
  21. package/payload/platform/plugins/brochures/skills/property-market-report/references/template.html +266 -0
  22. package/payload/platform/plugins/brochures/skills/property-socials/SKILL.md +141 -0
  23. package/payload/platform/plugins/cloudflare/mcp/dist/lib/setup-orchestrator.d.ts.map +1 -1
  24. package/payload/platform/plugins/cloudflare/mcp/dist/lib/setup-orchestrator.js +2 -1
  25. package/payload/platform/plugins/cloudflare/mcp/dist/lib/setup-orchestrator.js.map +1 -1
  26. package/payload/platform/plugins/docs/PLUGIN.md +3 -1
  27. package/payload/platform/plugins/docs/references/admin-session.md +40 -0
  28. package/payload/platform/plugins/docs/references/deployment.md +25 -0
  29. package/payload/platform/plugins/docs/references/internals.md +30 -0
  30. package/payload/platform/plugins/docs/references/platform.md +3 -1
  31. package/payload/platform/plugins/docs/references/plugins-guide.md +1 -1
  32. package/payload/platform/plugins/docs/references/troubleshooting.md +1 -1
  33. package/payload/platform/plugins/email/mcp/dist/lib/claude-bridge.d.ts.map +1 -1
  34. package/payload/platform/plugins/email/mcp/dist/lib/claude-bridge.js +2 -1
  35. package/payload/platform/plugins/email/mcp/dist/lib/claude-bridge.js.map +1 -1
  36. package/payload/platform/plugins/loop/PLUGIN.md +24 -0
  37. package/payload/platform/plugins/loop/mcp/src/__tests__/plugin-md-time-doctrine.test.ts +132 -0
  38. package/payload/platform/plugins/memory/.claude-plugin/plugin.json +1 -1
  39. package/payload/platform/plugins/memory/PLUGIN.md +1 -1
  40. package/payload/platform/plugins/memory/mcp/dist/index.js +6 -1
  41. package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
  42. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-search-fields.test.d.ts +2 -0
  43. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-search-fields.test.d.ts.map +1 -0
  44. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-search-fields.test.js +107 -0
  45. package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-search-fields.test.js.map +1 -0
  46. package/payload/platform/plugins/memory/mcp/dist/tools/memory-search.d.ts +4 -2
  47. package/payload/platform/plugins/memory/mcp/dist/tools/memory-search.d.ts.map +1 -1
  48. package/payload/platform/plugins/memory/mcp/dist/tools/memory-search.js +22 -13
  49. package/payload/platform/plugins/memory/mcp/dist/tools/memory-search.js.map +1 -1
  50. package/payload/platform/plugins/memory/references/graph-primitives.md +42 -0
  51. package/payload/platform/plugins/memory/skills/concept-synthesis/SKILL.md +1 -1
  52. package/payload/platform/plugins/memory/skills/conversation-archive-enrich/SKILL.md +2 -2
  53. package/payload/platform/plugins/memory/skills/document-ingest/SKILL.md +1 -1
  54. package/payload/platform/plugins/property-data/.claude-plugin/plugin.json +17 -0
  55. package/payload/platform/plugins/property-data/PLUGIN.md +100 -0
  56. package/payload/platform/plugins/property-data/mcp/dist/index.d.ts +2 -0
  57. package/payload/platform/plugins/property-data/mcp/dist/index.d.ts.map +1 -0
  58. package/payload/platform/plugins/property-data/mcp/dist/index.js +153 -0
  59. package/payload/platform/plugins/property-data/mcp/dist/index.js.map +1 -0
  60. package/payload/platform/plugins/property-data/mcp/dist/lib/crypto.d.ts +3 -0
  61. package/payload/platform/plugins/property-data/mcp/dist/lib/crypto.d.ts.map +1 -0
  62. package/payload/platform/plugins/property-data/mcp/dist/lib/crypto.js +72 -0
  63. package/payload/platform/plugins/property-data/mcp/dist/lib/crypto.js.map +1 -0
  64. package/payload/platform/plugins/property-data/mcp/dist/lib/neo4j.d.ts +5 -0
  65. package/payload/platform/plugins/property-data/mcp/dist/lib/neo4j.d.ts.map +1 -0
  66. package/payload/platform/plugins/property-data/mcp/dist/lib/neo4j.js +38 -0
  67. package/payload/platform/plugins/property-data/mcp/dist/lib/neo4j.js.map +1 -0
  68. package/payload/platform/plugins/property-data/mcp/dist/lib/propertydata-api.d.ts +29 -0
  69. package/payload/platform/plugins/property-data/mcp/dist/lib/propertydata-api.d.ts.map +1 -0
  70. package/payload/platform/plugins/property-data/mcp/dist/lib/propertydata-api.js +112 -0
  71. package/payload/platform/plugins/property-data/mcp/dist/lib/propertydata-api.js.map +1 -0
  72. package/payload/platform/plugins/property-data/mcp/dist/tools/endpoints.d.ts +14 -0
  73. package/payload/platform/plugins/property-data/mcp/dist/tools/endpoints.d.ts.map +1 -0
  74. package/payload/platform/plugins/property-data/mcp/dist/tools/endpoints.js +20 -0
  75. package/payload/platform/plugins/property-data/mcp/dist/tools/endpoints.js.map +1 -0
  76. package/payload/platform/plugins/property-data/mcp/dist/tools/key-deregister.d.ts +4 -0
  77. package/payload/platform/plugins/property-data/mcp/dist/tools/key-deregister.d.ts.map +1 -0
  78. package/payload/platform/plugins/property-data/mcp/dist/tools/key-deregister.js +19 -0
  79. package/payload/platform/plugins/property-data/mcp/dist/tools/key-deregister.js.map +1 -0
  80. package/payload/platform/plugins/property-data/mcp/dist/tools/key-list.d.ts +4 -0
  81. package/payload/platform/plugins/property-data/mcp/dist/tools/key-list.d.ts.map +1 -0
  82. package/payload/platform/plugins/property-data/mcp/dist/tools/key-list.js +10 -0
  83. package/payload/platform/plugins/property-data/mcp/dist/tools/key-list.js.map +1 -0
  84. package/payload/platform/plugins/property-data/mcp/dist/tools/key-register.d.ts +5 -0
  85. package/payload/platform/plugins/property-data/mcp/dist/tools/key-register.d.ts.map +1 -0
  86. package/payload/platform/plugins/property-data/mcp/dist/tools/key-register.js +43 -0
  87. package/payload/platform/plugins/property-data/mcp/dist/tools/key-register.js.map +1 -0
  88. package/payload/platform/plugins/property-data/mcp/package-lock.json +2566 -0
  89. package/payload/platform/plugins/property-data/mcp/package.json +21 -0
  90. package/payload/platform/plugins/property-data/mcp/src/__tests__/key-roundtrip.test.ts +107 -0
  91. package/payload/platform/plugins/property-data/mcp/src/__tests__/propertydata-api.test.ts +184 -0
  92. package/payload/platform/plugins/property-data/mcp/src/__tests__/schema-parity.test.ts +48 -0
  93. package/payload/platform/plugins/property-data/mcp/src/index.ts +249 -0
  94. package/payload/platform/plugins/property-data/mcp/src/lib/crypto.ts +79 -0
  95. package/payload/platform/plugins/property-data/mcp/src/lib/neo4j.ts +47 -0
  96. package/payload/platform/plugins/property-data/mcp/src/lib/propertydata-api.ts +135 -0
  97. package/payload/platform/plugins/property-data/mcp/src/tools/endpoints.ts +27 -0
  98. package/payload/platform/plugins/property-data/mcp/src/tools/key-deregister.ts +21 -0
  99. package/payload/platform/plugins/property-data/mcp/src/tools/key-list.ts +10 -0
  100. package/payload/platform/plugins/property-data/mcp/src/tools/key-register.ts +58 -0
  101. package/payload/platform/plugins/property-data/mcp/tsconfig.json +20 -0
  102. package/payload/platform/plugins/property-data/mcp/vitest.config.ts +8 -0
  103. package/payload/platform/plugins/property-data/skills/property-data/SKILL.md +58 -0
  104. package/payload/platform/plugins/tasks/mcp/dist/index.js +1 -2
  105. package/payload/platform/plugins/tasks/mcp/dist/index.js.map +1 -1
  106. package/payload/platform/plugins/tasks/mcp/dist/tools/session-name.d.ts.map +1 -1
  107. package/payload/platform/plugins/tasks/mcp/dist/tools/session-name.js +3 -2
  108. package/payload/platform/plugins/tasks/mcp/dist/tools/session-name.js.map +1 -1
  109. package/payload/platform/plugins/waitlist/PLUGIN.md +6 -8
  110. package/payload/platform/plugins/waitlist/mcp/dist/index.js +33 -0
  111. package/payload/platform/plugins/waitlist/mcp/dist/index.js.map +1 -1
  112. package/payload/platform/plugins/waitlist/mcp/dist/lib/admin-model.d.ts +16 -0
  113. package/payload/platform/plugins/waitlist/mcp/dist/lib/admin-model.d.ts.map +1 -0
  114. package/payload/platform/plugins/waitlist/mcp/dist/lib/admin-model.js +58 -0
  115. package/payload/platform/plugins/waitlist/mcp/dist/lib/admin-model.js.map +1 -0
  116. package/payload/platform/plugins/waitlist/mcp/dist/tools/waitlist-extract.d.ts +34 -0
  117. package/payload/platform/plugins/waitlist/mcp/dist/tools/waitlist-extract.d.ts.map +1 -0
  118. package/payload/platform/plugins/waitlist/mcp/dist/tools/waitlist-extract.js +129 -0
  119. package/payload/platform/plugins/waitlist/mcp/dist/tools/waitlist-extract.js.map +1 -0
  120. package/payload/platform/plugins/waitlist/mcp/dist/tools/waitlist-heal.d.ts +12 -18
  121. package/payload/platform/plugins/waitlist/mcp/dist/tools/waitlist-heal.d.ts.map +1 -1
  122. package/payload/platform/plugins/waitlist/mcp/dist/tools/waitlist-heal.js +89 -86
  123. package/payload/platform/plugins/waitlist/mcp/dist/tools/waitlist-heal.js.map +1 -1
  124. package/payload/platform/plugins/waitlist/mcp/dist/tools/waitlist-setup.d.ts.map +1 -1
  125. package/payload/platform/plugins/waitlist/mcp/dist/tools/waitlist-setup.js +15 -53
  126. package/payload/platform/plugins/waitlist/mcp/dist/tools/waitlist-setup.js.map +1 -1
  127. package/payload/platform/plugins/whatsapp/PLUGIN.md +1 -0
  128. package/payload/platform/plugins/whatsapp/mcp/dist/index.js +5 -5
  129. package/payload/platform/plugins/whatsapp/mcp/dist/index.js.map +1 -1
  130. package/payload/platform/plugins/workflows/PLUGIN.md +10 -176
  131. package/payload/platform/plugins/workflows/mcp/dist/index.js +14 -142
  132. package/payload/platform/plugins/workflows/mcp/dist/index.js.map +1 -1
  133. package/payload/platform/plugins/workflows/mcp/dist/lib/step-resolver.d.ts +1 -88
  134. package/payload/platform/plugins/workflows/mcp/dist/lib/step-resolver.d.ts.map +1 -1
  135. package/payload/platform/plugins/workflows/mcp/dist/lib/step-resolver.js +0 -86
  136. package/payload/platform/plugins/workflows/mcp/dist/lib/step-resolver.js.map +1 -1
  137. package/payload/platform/plugins/workflows/mcp/dist/lib/validate-capabilities.d.ts +5 -12
  138. package/payload/platform/plugins/workflows/mcp/dist/lib/validate-capabilities.d.ts.map +1 -1
  139. package/payload/platform/plugins/workflows/mcp/dist/lib/validate-capabilities.js +5 -46
  140. package/payload/platform/plugins/workflows/mcp/dist/lib/validate-capabilities.js.map +1 -1
  141. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-create.d.ts +1 -16
  142. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-create.d.ts.map +1 -1
  143. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-create.js +39 -75
  144. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-create.js.map +1 -1
  145. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-execute.d.ts +8 -21
  146. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-execute.d.ts.map +1 -1
  147. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-execute.js +39 -266
  148. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-execute.js.map +1 -1
  149. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-get.d.ts +3 -8
  150. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-get.d.ts.map +1 -1
  151. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-get.js +3 -10
  152. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-get.js.map +1 -1
  153. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-update.d.ts.map +1 -1
  154. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-update.js +38 -86
  155. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-update.js.map +1 -1
  156. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-validate.d.ts.map +1 -1
  157. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-validate.js +8 -26
  158. package/payload/platform/plugins/workflows/mcp/dist/tools/workflow-validate.js.map +1 -1
  159. package/payload/platform/services/claude-session-manager/dist/fs-watcher.d.ts.map +1 -1
  160. package/payload/platform/services/claude-session-manager/dist/fs-watcher.js +1 -2
  161. package/payload/platform/services/claude-session-manager/dist/fs-watcher.js.map +1 -1
  162. package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -1
  163. package/payload/platform/services/claude-session-manager/dist/http-server.js +221 -25
  164. package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
  165. package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts +39 -1
  166. package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts.map +1 -1
  167. package/payload/platform/services/claude-session-manager/dist/pty-spawner.js +109 -10
  168. package/payload/platform/services/claude-session-manager/dist/pty-spawner.js.map +1 -1
  169. package/payload/platform/services/claude-session-manager/dist/reaper.d.ts.map +1 -1
  170. package/payload/platform/services/claude-session-manager/dist/reaper.js +11 -0
  171. package/payload/platform/services/claude-session-manager/dist/reaper.js.map +1 -1
  172. package/payload/platform/services/claude-session-manager/dist/session-store.d.ts +21 -0
  173. package/payload/platform/services/claude-session-manager/dist/session-store.d.ts.map +1 -1
  174. package/payload/platform/services/claude-session-manager/dist/session-store.js.map +1 -1
  175. package/payload/platform/services/claude-session-manager/vitest.config.ts +14 -0
  176. package/payload/platform/templates/agents/admin/IDENTITY.md +2 -0
  177. package/payload/platform/templates/agents/admin/SOUL.md +3 -1
  178. package/payload/premium-plugins/real-agent/BUNDLE.md +5 -3
  179. package/payload/premium-plugins/real-agent/agents/negotiator.md +1 -1
  180. package/payload/premium-plugins/real-agent/agents/valuer.md +1 -1
  181. package/payload/premium-plugins/real-agent/plugins/.claude-plugin/marketplace.json +5 -0
  182. package/payload/premium-plugins/real-agent/plugins/brochures/PLUGIN.md +2 -0
  183. package/payload/premium-plugins/real-agent/plugins/brochures/skills/property-market-report/SKILL.md +100 -0
  184. package/payload/premium-plugins/real-agent/plugins/brochures/skills/property-market-report/references/render.py +267 -0
  185. package/payload/premium-plugins/real-agent/plugins/brochures/skills/property-market-report/references/template.html +266 -0
  186. package/payload/premium-plugins/real-agent/plugins/brochures/skills/property-socials/SKILL.md +141 -0
  187. package/payload/premium-plugins/real-agent/plugins/loop/PLUGIN.md +24 -0
  188. package/payload/premium-plugins/real-agent/plugins/loop/mcp/src/__tests__/plugin-md-time-doctrine.test.ts +132 -0
  189. package/payload/premium-plugins/real-agent/plugins/property-data/.claude-plugin/plugin.json +17 -0
  190. package/payload/premium-plugins/real-agent/plugins/property-data/PLUGIN.md +100 -0
  191. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/dist/index.d.ts +2 -0
  192. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/dist/index.d.ts.map +1 -0
  193. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/dist/index.js +153 -0
  194. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/dist/index.js.map +1 -0
  195. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/dist/lib/crypto.d.ts +3 -0
  196. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/dist/lib/crypto.d.ts.map +1 -0
  197. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/dist/lib/crypto.js +72 -0
  198. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/dist/lib/crypto.js.map +1 -0
  199. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/dist/lib/neo4j.d.ts +5 -0
  200. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/dist/lib/neo4j.d.ts.map +1 -0
  201. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/dist/lib/neo4j.js +38 -0
  202. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/dist/lib/neo4j.js.map +1 -0
  203. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/dist/lib/propertydata-api.d.ts +29 -0
  204. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/dist/lib/propertydata-api.d.ts.map +1 -0
  205. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/dist/lib/propertydata-api.js +112 -0
  206. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/dist/lib/propertydata-api.js.map +1 -0
  207. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/dist/tools/endpoints.d.ts +14 -0
  208. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/dist/tools/endpoints.d.ts.map +1 -0
  209. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/dist/tools/endpoints.js +20 -0
  210. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/dist/tools/endpoints.js.map +1 -0
  211. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/dist/tools/key-deregister.d.ts +4 -0
  212. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/dist/tools/key-deregister.d.ts.map +1 -0
  213. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/dist/tools/key-deregister.js +19 -0
  214. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/dist/tools/key-deregister.js.map +1 -0
  215. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/dist/tools/key-list.d.ts +4 -0
  216. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/dist/tools/key-list.d.ts.map +1 -0
  217. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/dist/tools/key-list.js +10 -0
  218. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/dist/tools/key-list.js.map +1 -0
  219. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/dist/tools/key-register.d.ts +5 -0
  220. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/dist/tools/key-register.d.ts.map +1 -0
  221. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/dist/tools/key-register.js +43 -0
  222. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/dist/tools/key-register.js.map +1 -0
  223. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/package-lock.json +2566 -0
  224. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/package.json +21 -0
  225. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/src/__tests__/key-roundtrip.test.ts +107 -0
  226. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/src/__tests__/propertydata-api.test.ts +184 -0
  227. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/src/__tests__/schema-parity.test.ts +48 -0
  228. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/src/index.ts +249 -0
  229. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/src/lib/crypto.ts +79 -0
  230. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/src/lib/neo4j.ts +47 -0
  231. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/src/lib/propertydata-api.ts +135 -0
  232. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/src/tools/endpoints.ts +27 -0
  233. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/src/tools/key-deregister.ts +21 -0
  234. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/src/tools/key-list.ts +10 -0
  235. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/src/tools/key-register.ts +58 -0
  236. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/tsconfig.json +20 -0
  237. package/payload/premium-plugins/real-agent/plugins/property-data/mcp/vitest.config.ts +8 -0
  238. package/payload/premium-plugins/real-agent/plugins/property-data/skills/property-data/SKILL.md +58 -0
  239. package/payload/server/{chunk-MEGIQYUD.js → chunk-2IKQERHN.js} +33 -5
  240. package/payload/server/{chunk-XJVJ2B2Q.js → chunk-NPZKH5EC.js} +1 -1
  241. package/payload/server/{chunk-4P2MPERV.js → chunk-X3Y6ENKA.js} +0 -90
  242. package/payload/server/{cloudflare-task-tracker-R6MMORFU.js → cloudflare-task-tracker-TL6R364J.js} +2 -2
  243. package/payload/server/maxy-edge.js +54 -26
  244. package/payload/server/public/assets/admin-2ZJmzJ_g.js +216 -0
  245. package/payload/server/public/assets/{architectureDiagram-Q4EWVU46-Ch-JZ1Q0.js → architectureDiagram-Q4EWVU46-DgfgldJT.js} +1 -1
  246. package/payload/server/public/assets/{blockDiagram-DXYQGD6D-C08tkD4C.js → blockDiagram-DXYQGD6D-agu8GDzA.js} +1 -1
  247. package/payload/server/public/assets/{brand-DCdOhh-I.css → brand-BDASZqMG.css} +1 -1
  248. package/payload/server/public/assets/{c4Diagram-AHTNJAMY-IceRdWw3.js → c4Diagram-AHTNJAMY-CmNsUmAe.js} +1 -1
  249. package/payload/server/public/assets/channel-DXGOX55q.js +1 -0
  250. package/payload/server/public/assets/{chunk-336JU56O-Cey0rxmH.js → chunk-336JU56O-D9Uts7k9.js} +2 -2
  251. package/payload/server/public/assets/{chunk-426QAEUC-Dzk8s0or.js → chunk-426QAEUC-D4ABqXMn.js} +1 -1
  252. package/payload/server/public/assets/{chunk-4TB4RGXK-C10nuKc8.js → chunk-4TB4RGXK-D1KE4OAX.js} +1 -1
  253. package/payload/server/public/assets/{chunk-5FUZZQ4R-B1B8871D.js → chunk-5FUZZQ4R-CAh0GXe2.js} +1 -1
  254. package/payload/server/public/assets/{chunk-5PVQY5BW-jvHIkgqP.js → chunk-5PVQY5BW-DBHa6HOv.js} +1 -1
  255. package/payload/server/public/assets/{chunk-EDXVE4YY-7nDxvXHS.js → chunk-EDXVE4YY-BDC-6mL3.js} +1 -1
  256. package/payload/server/public/assets/{chunk-ENJZ2VHE-C8lJ1YYn.js → chunk-ENJZ2VHE-CH3uROkW.js} +1 -1
  257. package/payload/server/public/assets/{chunk-ICPOFSXX-CT1d7veI.js → chunk-ICPOFSXX-BzZf0nAw.js} +1 -1
  258. package/payload/server/public/assets/{chunk-OYMX7WX6-LTAfwxv0.js → chunk-OYMX7WX6-BrLHrI6O.js} +1 -1
  259. package/payload/server/public/assets/{chunk-U2HBQHQK-RoGrqrH0.js → chunk-U2HBQHQK-Bw4UkLe_.js} +1 -1
  260. package/payload/server/public/assets/{chunk-X2U36JSP-D89ZBg3z.js → chunk-X2U36JSP-23xgdk05.js} +1 -1
  261. package/payload/server/public/assets/{chunk-YZCP3GAM-Cyg122Hf.js → chunk-YZCP3GAM-BA8iGgRa.js} +1 -1
  262. package/payload/server/public/assets/{chunk-ZZ45TVLE-Dg59YYuG.js → chunk-ZZ45TVLE-B-ol4EgR.js} +1 -1
  263. package/payload/server/public/assets/classDiagram-6PBFFD2Q-DTuuDxpK.js +1 -0
  264. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-CIw8RU0q.js +1 -0
  265. package/payload/server/public/assets/clone-O4ZyuvYl.js +1 -0
  266. package/payload/server/public/assets/{dagre-BPzUsxie.js → dagre--kXszEIb.js} +1 -1
  267. package/payload/server/public/assets/{dagre-KV5264BT-CjDNXqPy.js → dagre-KV5264BT-amN1uU2d.js} +1 -1
  268. package/payload/server/public/assets/data-DlmoKxmN.js +1 -0
  269. package/payload/server/public/assets/{device-url-actions-B588ZlnE.js → device-url-actions-CPoz5fqz.js} +1 -1
  270. package/payload/server/public/assets/{diagram-5BDNPKRD-Bqq0vqWM.js → diagram-5BDNPKRD-Cwizs9tP.js} +1 -1
  271. package/payload/server/public/assets/{diagram-G4DWMVQ6-DSqocDhm.js → diagram-G4DWMVQ6-BpSu5Uao.js} +1 -1
  272. package/payload/server/public/assets/{diagram-MMDJMWI5-DZRWgKRL.js → diagram-MMDJMWI5-DiArtkto.js} +1 -1
  273. package/payload/server/public/assets/{diagram-TYMM5635-DXRm-FXu.js → diagram-TYMM5635-_tygK58Y.js} +1 -1
  274. package/payload/server/public/assets/{erDiagram-SMLLAGMA-CFVgkUCo.js → erDiagram-SMLLAGMA-CBV6LWYA.js} +1 -1
  275. package/payload/server/public/assets/{flowDiagram-DWJPFMVM-C82XCt9-.js → flowDiagram-DWJPFMVM-CHZFrtOU.js} +1 -1
  276. package/payload/server/public/assets/{ganttDiagram-T4ZO3ILL-C4tnImlS.js → ganttDiagram-T4ZO3ILL-B3vKq5ov.js} +1 -1
  277. package/payload/server/public/assets/{gitGraphDiagram-UUTBAWPF-DXHutP-a.js → gitGraphDiagram-UUTBAWPF-dnJPjbtj.js} +1 -1
  278. package/payload/server/public/assets/graph-BVvcFSEQ.js +1 -0
  279. package/payload/server/public/assets/graph-labels-cCvgu38Y.js +1 -0
  280. package/payload/server/public/assets/{graphlib-BvR5tL62.js → graphlib-CNXtnega.js} +1 -1
  281. package/payload/server/public/assets/{infoDiagram-42DDH7IO-DgFMqgZy.js → infoDiagram-42DDH7IO-D8DYwVAF.js} +1 -1
  282. package/payload/server/public/assets/{ishikawaDiagram-UXIWVN3A-_5gmh1-V.js → ishikawaDiagram-UXIWVN3A-CfEVY2Ud.js} +1 -1
  283. package/payload/server/public/assets/{journeyDiagram-VCZTEJTY-CNfDVgwI.js → journeyDiagram-VCZTEJTY-FmoBq7Kh.js} +1 -1
  284. package/payload/server/public/assets/{kanban-definition-6JOO6SKY-Djifb_Z6.js → kanban-definition-6JOO6SKY-B-Q9qk99.js} +1 -1
  285. package/payload/server/public/assets/{line-0fRVrNiw.js → line-DZwbJENP.js} +1 -1
  286. package/payload/server/public/assets/{mermaid-parser.core-DXA7LKDt.js → mermaid-parser.core-C3ahKykw.js} +1 -1
  287. package/payload/server/public/assets/{mermaid.core-BCfYtdMJ.js → mermaid.core-B8OFZIE8.js} +3 -3
  288. package/payload/server/public/assets/{mindmap-definition-QFDTVHPH-sTRvikWi.js → mindmap-definition-QFDTVHPH-CqhkfbWa.js} +1 -1
  289. package/payload/server/public/assets/{page-nAY64ID7.js → page-BnAxPkmg.js} +1 -1
  290. package/payload/server/public/assets/{page-DDyny08O.js → page-BnaN3u86.js} +1 -1
  291. package/payload/server/public/assets/{pieDiagram-DEJITSTG-QLTieded.js → pieDiagram-DEJITSTG-CJqQ6u3-.js} +1 -1
  292. package/payload/server/public/assets/{public-rUUducAl.js → public-rWe9ADCS.js} +3 -3
  293. package/payload/server/public/assets/{quadrantDiagram-34T5L4WZ-DOKCcqAZ.js → quadrantDiagram-34T5L4WZ-BtEqOXQM.js} +1 -1
  294. package/payload/server/public/assets/{requirementDiagram-MS252O5E-BX6Zpq1X.js → requirementDiagram-MS252O5E-DPHWUtE6.js} +1 -1
  295. package/payload/server/public/assets/{sankeyDiagram-XADWPNL6-B05NdgZX.js → sankeyDiagram-XADWPNL6-FBmc3wHT.js} +1 -1
  296. package/payload/server/public/assets/{sequenceDiagram-FGHM5R23-CHF8ZdUb.js → sequenceDiagram-FGHM5R23-BMSd2-1M.js} +1 -1
  297. package/payload/server/public/assets/{stateDiagram-FHFEXIEX-DTAt7Ytz.js → stateDiagram-FHFEXIEX-DqFbU-LT.js} +1 -1
  298. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-CXTnsHGq.js +1 -0
  299. package/payload/server/public/assets/{timeline-definition-GMOUNBTQ-Dzd6X_ei.js → timeline-definition-GMOUNBTQ-DsfvHVK8.js} +1 -1
  300. package/payload/server/public/assets/{vennDiagram-DHZGUBPP-BAbM4QlQ.js → vennDiagram-DHZGUBPP-kHU05mqC.js} +1 -1
  301. package/payload/server/public/assets/{wardleyDiagram-NUSXRM2D-CIOXXKJd.js → wardleyDiagram-NUSXRM2D-C696Mez_.js} +1 -1
  302. package/payload/server/public/assets/{xychartDiagram-5P7HB3ND-oF9sZesS.js → xychartDiagram-5P7HB3ND-yht-JyXJ.js} +1 -1
  303. package/payload/server/public/data.html +5 -5
  304. package/payload/server/public/graph.html +5 -5
  305. package/payload/server/public/index.html +7 -7
  306. package/payload/server/public/public.html +4 -4
  307. package/payload/server/server.js +261 -207
  308. package/payload/server/public/assets/admin-DBuCWSPS.js +0 -216
  309. package/payload/server/public/assets/channel-8QQB2Zoe.js +0 -1
  310. package/payload/server/public/assets/classDiagram-6PBFFD2Q-CViZOOjI.js +0 -1
  311. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-Dm7eGBqB.js +0 -1
  312. package/payload/server/public/assets/clone-BC8oes11.js +0 -1
  313. package/payload/server/public/assets/data-BeblX4m4.js +0 -1
  314. package/payload/server/public/assets/graph-ZuBiYril.js +0 -1
  315. package/payload/server/public/assets/graph-labels-CnbJR6cp.js +0 -1
  316. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-2bJIW7wn.js +0 -1
  317. /package/payload/server/public/assets/{brand-Dln107gD.js → brand-BWCtpG7_.js} +0 -0
@@ -0,0 +1,141 @@
1
+ ---
2
+ name: property-socials
3
+ description: Use when generating Open Graph / social-share images for a property page built by the real-estate brochure pipeline (estate-agents/<agent>/properties/<slug>/output/web/page.html). Produces landscape, square, and portrait JPGs that match the brochure's brand palette and typography, pulling copy from property.json and hero images already curated for that property. Triggers include "og images for <property>", "social collateral for <listing>", "Instagram tiles for that brochure", or any request to create share-card imagery for a published realagent.chat property page.
4
+ ---
5
+
6
+ # Property OG / Social Images
7
+
8
+ The brochure pipeline already produces a styled property page at
9
+ `estate-agents/<agent>/properties/<slug>/output/web/page.html` with curated hero
10
+ images under `images/`, branding tokens in `:root` of the page CSS, and
11
+ structured metadata in the property's `property.json`. This skill renders
12
+ share-ready images by overlaying brand-consistent typography on those hero
13
+ shots — it does not re-design anything.
14
+
15
+ ## Inputs the skill consumes (never invents)
16
+
17
+ - **Palette and fonts** — read from `:root` in `output/web/page.html`. Use the
18
+ exact `--paper / --ink / --gold` tokens and Google Font imports already on
19
+ that page. Do not pick new colours.
20
+ - **Copy** — `property.json` is canonical for address, price, qualifier,
21
+ bedrooms/baths/receptions, agent name + phone. The page's
22
+ `<meta name="description">` is the sub-headline. The brochure folder's
23
+ display name (e.g. *Sparrows Farm*) is the headline.
24
+ - **Hero images** — `images/<slug>-hero-1-main.webp`, `hero-2-kitchen.webp`,
25
+ `hero-3-garden.webp` are the curated set. Use them by name; do not pick
26
+ numbered shots from the raw set unless the curated heroes are missing.
27
+
28
+ ## Output contract
29
+
30
+ Two deliverables every time: image files and the captions that go with them.
31
+
32
+ **Image files** are written next to `page.html` so they share the same public
33
+ URL prefix:
34
+
35
+ | File | Dimensions | Use |
36
+ |------|------------|-----|
37
+ | `og-landscape-<hero>.jpg` | 1200×628 | Twitter / LinkedIn / Facebook / OG |
38
+ | `og-square-<hero>.jpg` | 1200×1200 | Instagram feed |
39
+ | `og-portrait-<hero>.jpg` | 1080×1350 | Instagram portrait, mobile |
40
+
41
+ `<hero>` is `main`, `kitchen`, or `garden`. At minimum produce
42
+ `og-landscape-main.jpg`; offer the full five-variant set (landscape + square +
43
+ three portraits) when the user wants social collateral, not just a meta image.
44
+
45
+ **Captions** are written into `output/web/social-posts.md`, one section per
46
+ image, ready to paste. Every caption is generated through the `plainly` skill's
47
+ register: no em-dashes, no inflation vocabulary (*discover*, *unlock*,
48
+ *nestled*, *stunning*, *boasts*, *bespoke* where it isn't literally bespoke),
49
+ no antithetical "it's not X, it's Y", no rhetorical openers (*Imagine…*,
50
+ *Picture this…*). Read each draft aloud; if it sounds like an estate-agent
51
+ blurb-bot rather than a person, rewrite it.
52
+
53
+ Per-platform shape (these are caps, not minimums):
54
+
55
+ - **Landscape post (Twitter / X)**: under 280 characters. One sentence of
56
+ scene, one of specs, one of agent + phone. Link as last token.
57
+ - **Landscape post (LinkedIn / Facebook)**: three short paragraphs. Opening
58
+ line that names the property and locality. A middle paragraph of concrete
59
+ features taken from `property.json`'s `key_features`. A closing paragraph
60
+ with price, agent name, phone, listing URL.
61
+ - **Square (Instagram feed)**: property name + locality on line one, two or
62
+ three lines of concrete features, price, agent + phone, "link in bio", four
63
+ to six hashtags drawn from locality + property type + agency.
64
+ - **Portrait (Instagram portrait / Reels cover)**: lead with what is visible
65
+ in *that specific hero* (exterior, kitchen, or garden), not the generic
66
+ property summary. Three lines maximum. Price + agent line at the bottom.
67
+
68
+ Copy sources, in order: `property.json` for facts (address, price, beds, baths,
69
+ acreage, key features); the page's `<meta name="description">` for tone of the
70
+ hero sub-line; the brochure folder display name for the headline. Do not invent
71
+ features that are not in those sources.
72
+
73
+ ## How rendering works
74
+
75
+ A single `og.html` template lives at `output/web/og.html` alongside `page.html`
76
+ so it can use relative `images/` paths. It accepts `?format=landscape|square|
77
+ portrait` and `?hero=main|kitchen|garden`, applies the matching CSS class with
78
+ explicit min/max width and height (no relative units), and sets the background
79
+ hero image from the param. Playwright screenshots the URL at exactly the
80
+ container's pixel size.
81
+
82
+ Critical layout rules:
83
+
84
+ - The stage div fixes its own width and height with `width / minWidth / maxWidth`
85
+ (and the height triple). Without max constraints the viewport bleeds.
86
+ - Hero fills the stage with `background-size: cover; background-position: center`
87
+ so the same template works across all three aspect ratios.
88
+ - A vertical gradient scrim (transparent → ink 0.85) sits between hero and copy.
89
+ On bright daytime shots the scrim's bottom stop must reach ≥ 0.85 or the
90
+ eyebrow/sub copy loses contrast.
91
+ - Copy block sits in the bottom-left: eyebrow (locality, gold), headline
92
+ (display serif), sub (italic body serif), thin rule, specs row, footer line
93
+ with `realagent.chat / <agent>` left and `<agent name> · <phone>` right.
94
+
95
+ ## Generation flow
96
+
97
+ 1. Confirm `output/web/og.html` is in sync with the page's `:root` palette and
98
+ `property.json` copy. If the property page has been re-themed since the last
99
+ render, update the template before screenshotting.
100
+ 2. Start a static server in `output/web/` on any free port:
101
+ `python3 -m http.server <port> &`. Hold the PID so it can be killed at the
102
+ end. Relative `images/` paths require a real HTTP origin; `file://` won't
103
+ render webfonts either.
104
+ 3. On a fresh machine, `npx -y playwright install chromium` once. The first
105
+ `playwright screenshot` invocation otherwise fails with "Executable doesn't
106
+ exist".
107
+ 4. Screenshot each variant. Pass `--wait-for-timeout=2500` so Google Fonts
108
+ land before capture. Always quote URLs that contain `&`.
109
+ 5. Stop the server. Verify each JPG with `Read` so the user sees the rendered
110
+ collateral inline — file sizes alone aren't proof of a good render.
111
+
112
+ ## Failure modes seen on first use
113
+
114
+ - **Filename mangling.** A bash loop using `for v in "landscape main" …; set --
115
+ $v` collapses to filenames like `og-landscape main-.jpg` (space, then dash).
116
+ Use an explicit per-variant call or an array; never rely on positional
117
+ splitting for two-word tuples.
118
+ - **6 KB screenshots.** A screenshot under ~20 KB is a blank page. Common
119
+ causes: server not running, wrong port, Chromium not installed, or `og.html`
120
+ threw a JS error. Open the URL in a browser to confirm before re-running.
121
+ - **Eyebrow on a light surface.** The garden / pool hero washes the eyebrow
122
+ out. Either deepen the scrim's bottom stop or move the eyebrow above the
123
+ hero crop on that variant. Don't ship a low-contrast tile.
124
+ - **Treating this as a Next.js task.** The brochure site is static HTML. The
125
+ upstream `og-images` skill assumes `app/og/page.tsx`; ignore that scaffold
126
+ and render against the static page directly.
127
+ - **Captions that sound like AI marketing.** "Discover this stunning home
128
+ nestled in the heart of Essex" is the failure mode. Strip *discover*,
129
+ *unlock*, *nestled*, *stunning*, *boasts*, *exquisite*, *charming*, every
130
+ em-dash, every exclamation mark used to fake enthusiasm. The aloud test from
131
+ the `plainly` skill applies: read the caption out; if you would not say it
132
+ in conversation to a buyer, rewrite it.
133
+
134
+ ## Out of scope
135
+
136
+ - The brochure page itself (owned by `real-estate-brochure:property-brochure`).
137
+ - Property metadata extraction (owned by
138
+ `real-estate-brochure:property-extract`).
139
+ - Wiring `<meta property="og:image">` into `page.html`. Surface the snippet for
140
+ the operator; the page is regenerated by a separate skill and edits there
141
+ belong in that pipeline, not this one.
@@ -174,6 +174,30 @@ Loop covers five value pillars with API surface. Each pillar has both read and w
174
174
  - `loop-customer-preferences` (action=write)
175
175
  - `loop-supplier` (action=maintenance-complete, board-complete, maintenance-submit-quote)
176
176
 
177
+ ## Time presentation
178
+
179
+ **Every datetime field in a Loop response is UTC, returned without a timezone marker.** The Loop V2 API stores and returns instants as bare `YYYY-MM-DDTHH:MM:SS` strings whose true zone is UTC. Presenting them verbatim is silent misrepresentation: a viewing whose `dateOfAppointment` is `12:00:00` is `12:00Z`, which is `13:00 BST` between late March and late October in the UK. Off-by-one-hour viewing times have already misled an operator (Task 126).
180
+
181
+ **Convert before any datetime appears in agent output.** The operator's zone comes from the `Person.timezone` property on the operator's `Person` node; Real Agent UK accounts default to `Europe/London` when that property is absent. The conversion is non-negotiable — there is no case where a Loop datetime is presented to the operator in its raw UTC form. State the converted local time, and where ambiguous (cross-DST scheduling, calendar invites), name the zone explicitly (`13:00 BST`, `09:30 GMT`).
182
+
183
+ The tools whose responses carry one or more datetime fields — and therefore require this conversion before any field value reaches the operator — are exhaustive:
184
+
185
+ - `loop-viewing-search` — `dateOfAppointment`, `dateOfAppointmentEnd`
186
+ - `loop-viewing-detail` — `dateCreated`, `dateOfAppointment`, `dateOfAppointmentEnd`, `dateBuyerFeedbackGiven`, `dateSellerFeedbackGiven`, `dateDone`
187
+ - `loop-feedback-get` — `viewingDateOfAppointment`
188
+ - `loop-people-search` — renters list: `dateRequired`
189
+ - `loop-people-detail` — `dateCreated`; nested `viewings[].dateOfAppointment(+End)`, `offers[].dateReceived`, `applications[].dateReceived`, `applications[].proposedStartDate`, `property.dateCreated` (sellers/landlords), `dateRequired` (renters)
190
+ - `loop-property-search` — `dateCreated`
191
+ - `loop-property-detail` — `dateCreated`, `dateInstructed`, `dateUnderOffer`, `dateLaunched`, `dateExchanged`, `dateCompleted`, `dateWithdrawn`, `dateFirstAvailable`, `leaseExpiryDate`
192
+ - `loop-property-listed` — `dateLaunched`, `dateFirstAvailable`, `leaseExpiryDate`
193
+ - `loop-property-sold` — `dateLaunched`, `leaseExpiryDate`, `images[].dateUpdated`
194
+ - `loop-marketing-match` — `dateCreated`, `dateInstructed`, `dateUnderOffer`, `dateLaunched`, `dateExchanged`, `dateCompleted`, `dateWithdrawn`, `dateFirstAvailable`, `viewings[].dateOfAppointment(+End)`, `applications[].dateReceived`, `applications[].proposedStartDate`, `marketListings[].dateListed`, `images[].dateUpdated`
195
+ - `loop-auto-responder` — `enquiry.dateMoving`
196
+ - `loop-team-availability` — `start`, `end`
197
+ - `loop-supplier` — `dateCreated`, `dateDone`, `dateReported`, `dateQuoteBy`, `dateCompleted`, `dateApproved`
198
+
199
+ Tools not listed (`loop-key-*`, `loop-team-info`, `loop-customer-preferences`, `loop-marketing-enquiry`, `loop-marketing-match-batch`, `loop-marketing-match-request`, `loop-viewing-create`, `loop-viewing-update`, `loop-feedback-submit`, `loop-property-viewing`, `loop-property-callback`, `loop-property-information`) either have no datetime in response or are write-only acknowledgements. The enumeration is grounded in the vendored swagger snapshot at `mcp/src/__tests__/loop-swagger.snapshot.json`; the pinning test at `mcp/src/__tests__/plugin-md-time-doctrine.test.ts` blocks silent drift.
200
+
177
201
  ### Team-key prerequisite
178
202
 
179
203
  Every Loop tool routes through one or more team keys. If `loop-key-list` returns nothing for the account, surface the registration prompt before attempting any other Loop call — every downstream tool will fail otherwise. If a call returns `Team "X" does not have <group> permission`, the key was scoped to fewer than 8 endpoint groups; re-register with the full permissions array (`["properties","people","viewings","feedback","team","marketing","customer","supplier"]`).
@@ -0,0 +1,132 @@
1
+ /**
2
+ * Anti-regression: PLUGIN.md must carry the "Time presentation" doctrine
3
+ * paragraph and enumerate every Loop tool whose response contains a
4
+ * datetime field. The doctrine is the agent's only signal that Loop
5
+ * returns bare UTC strings without a zone marker — silent drop of this
6
+ * section recurs the off-by-one-hour viewing-time failure (Task 126).
7
+ *
8
+ * The expected tool list is derived live from the vendored swagger
9
+ * snapshot, so if Loop adds a new datetime-bearing endpoint and we miss
10
+ * mapping it in PLUGIN.md, the test fails and names the orphan.
11
+ */
12
+
13
+ import { describe, expect, it } from 'vitest';
14
+ import { readFileSync } from 'node:fs';
15
+ import { resolve, dirname } from 'node:path';
16
+ import { fileURLToPath } from 'node:url';
17
+
18
+ const __dirname = dirname(fileURLToPath(import.meta.url));
19
+ const PLUGIN_MD = resolve(__dirname, '../../../PLUGIN.md');
20
+ const SWAGGER_PATH = resolve(__dirname, 'loop-swagger.snapshot.json');
21
+
22
+ interface SwaggerDoc {
23
+ paths: Record<string, Record<string, { responses?: Record<string, { content?: Record<string, { schema?: unknown }> }> }>>;
24
+ components?: { schemas?: Record<string, unknown> };
25
+ }
26
+
27
+ const swagger = JSON.parse(readFileSync(SWAGGER_PATH, 'utf-8')) as SwaggerDoc;
28
+ const plugin = readFileSync(PLUGIN_MD, 'utf-8');
29
+
30
+ // Swagger path → tool name. Every response-bearing GET path that surfaces
31
+ // a datetime field must map to exactly one tool here. Add a row when Loop
32
+ // publishes a new datetime endpoint that we expose.
33
+ const PATH_TO_TOOL: Record<string, string> = {
34
+ '/residential/sales/viewings': 'loop-viewing-search',
35
+ '/residential/lettings/viewings': 'loop-viewing-search',
36
+ '/residential/sales/viewings/{id}': 'loop-viewing-detail',
37
+ '/residential/lettings/viewings/{id}': 'loop-viewing-detail',
38
+ '/feedback/residential/sales/viewings/{id}': 'loop-feedback-get',
39
+ '/feedback/residential/lettings/viewings/{id}': 'loop-feedback-get',
40
+ '/people/renters': 'loop-people-search',
41
+ '/people/{id}': 'loop-people-detail',
42
+ '/people/buyers/{id}': 'loop-people-detail',
43
+ '/people/sellers/{id}': 'loop-people-detail',
44
+ '/people/landlords/{id}': 'loop-people-detail',
45
+ '/people/renters/{id}': 'loop-people-detail',
46
+ '/property/residential/sales/{id}': 'loop-property-detail',
47
+ '/property/residential/lettings/{id}': 'loop-property-detail',
48
+ '/property/residential/sales': 'loop-property-search',
49
+ '/property/residential/lettings': 'loop-property-search',
50
+ '/property/residential/sales/listed/{channel}': 'loop-property-listed',
51
+ '/property/residential/lettings/listed/{channel}': 'loop-property-listed',
52
+ '/property/residential/sales/{id}/preview/{previewHash}': 'loop-property-detail',
53
+ '/property/residential/lettings/{id}/preview/{previewHash}': 'loop-property-detail',
54
+ '/property/residential/sold/{channel}': 'loop-property-sold',
55
+ '/marketing/matching/{id}': 'loop-marketing-match',
56
+ '/marketing/rentals/matching/{id}': 'loop-marketing-match',
57
+ '/marketing/enquiries/auto-responder/{id}/{key}': 'loop-auto-responder',
58
+ '/team/{agentId}/availability/{searchDate}': 'loop-team-availability',
59
+ '/supplier/board-contractor/{code}/{jobid}/job-list': 'loop-supplier',
60
+ '/supplier/maintenance/{quoteCode}/{jobid}/job-list': 'loop-supplier',
61
+ '/supplier/maintenance/{quoteCode}/{jobId}/quote-list': 'loop-supplier',
62
+ };
63
+
64
+ function resolveRef(ref: string): unknown {
65
+ const parts = ref.replace('#/', '').split('/');
66
+ let cur: unknown = swagger;
67
+ for (const p of parts) cur = cur && typeof cur === 'object' ? (cur as Record<string, unknown>)[p] : null;
68
+ return cur;
69
+ }
70
+
71
+ function hasDateField(node: unknown, depth = 0, visited = new WeakSet<object>()): boolean {
72
+ if (!node || typeof node !== 'object' || depth > 12) return false;
73
+ if (visited.has(node as object)) return false;
74
+ visited.add(node as object);
75
+ const n = node as Record<string, unknown>;
76
+ if (typeof n.$ref === 'string') return hasDateField(resolveRef(n.$ref), depth + 1, visited);
77
+ if (n.format === 'date-time' || n.format === 'date') return true;
78
+ if (n.properties && typeof n.properties === 'object') {
79
+ for (const v of Object.values(n.properties as Record<string, unknown>)) {
80
+ if (hasDateField(v, depth + 1, visited)) return true;
81
+ }
82
+ }
83
+ if (n.items && hasDateField(n.items, depth + 1, visited)) return true;
84
+ if (Array.isArray(n.allOf)) {
85
+ for (const v of n.allOf) if (hasDateField(v, depth + 1, visited)) return true;
86
+ }
87
+ return false;
88
+ }
89
+
90
+ function toolsRequiringDoctrine(): Set<string> {
91
+ const tools = new Set<string>();
92
+ for (const [path, methods] of Object.entries(swagger.paths)) {
93
+ const op = methods.get;
94
+ if (!op || !op.responses) continue;
95
+ const anyDate = Object.values(op.responses).some(r =>
96
+ Object.values(r.content || {}).some(sw => hasDateField(sw.schema)),
97
+ );
98
+ if (!anyDate) continue;
99
+ const tool = PATH_TO_TOOL[path];
100
+ if (tool) tools.add(tool);
101
+ else throw new Error(`Swagger GET ${path} returns a datetime but has no PATH_TO_TOOL mapping — add it and list the tool in PLUGIN.md "Time presentation".`);
102
+ }
103
+ return tools;
104
+ }
105
+
106
+ describe('PLUGIN.md time-presentation doctrine', () => {
107
+ it('contains the Time presentation section', () => {
108
+ expect(plugin).toMatch(/^## Time presentation$/m);
109
+ });
110
+
111
+ it('names UTC, Person.timezone, and the Europe/London default', () => {
112
+ expect(plugin).toMatch(/UTC/);
113
+ expect(plugin).toMatch(/Person\.timezone/);
114
+ expect(plugin).toMatch(/Europe\/London/);
115
+ });
116
+
117
+ it('forbids raw UTC presentation', () => {
118
+ // Must state conversion is required before any datetime appears in output.
119
+ expect(plugin).toMatch(/Convert before any datetime appears in agent output/);
120
+ });
121
+
122
+ it('enumerates every tool whose Loop response carries a datetime field', () => {
123
+ const required = toolsRequiringDoctrine();
124
+ const missing: string[] = [];
125
+ for (const tool of required) {
126
+ // Each tool must appear in the doctrine section as a bullet item.
127
+ const re = new RegExp(`^- \`${tool.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&')}\``, 'm');
128
+ if (!re.test(plugin)) missing.push(tool);
129
+ }
130
+ expect(missing, `PLUGIN.md "Time presentation" must list: ${missing.join(', ')}`).toEqual([]);
131
+ });
132
+ });
@@ -0,0 +1,17 @@
1
+ {
2
+ "name": "real-agent-property-data",
3
+ "description": "PropertyData UK market analytics — postcode-keyed valuation, asking prices, sold prices, demand, yields, growth, national HPI. One encrypted API key per account.",
4
+ "version": "0.1.0",
5
+ "author": {
6
+ "name": "Rubytech LLC"
7
+ },
8
+ "mcpServers": {
9
+ "real-agent-property-data": {
10
+ "type": "stdio",
11
+ "command": "node",
12
+ "args": [
13
+ "${CLAUDE_PLUGIN_ROOT}/mcp/dist/index.js"
14
+ ]
15
+ }
16
+ }
17
+ }
@@ -0,0 +1,100 @@
1
+ ---
2
+ name: real-agent-property-data
3
+ description: "PropertyData UK market analytics — postcode-keyed valuation, asking prices, sold prices, demand, yields, growth, national HPI. One encrypted API key per account."
4
+ tools:
5
+ - name: property-data-key-register
6
+ publicAllowlist: false
7
+ - name: property-data-key-deregister
8
+ publicAllowlist: false
9
+ - name: property-data-key-list
10
+ publicAllowlist: false
11
+ - name: property-data-valuation-sale
12
+ publicAllowlist: false
13
+ - name: property-data-valuation-rent
14
+ publicAllowlist: false
15
+ - name: property-data-prices
16
+ publicAllowlist: false
17
+ - name: property-data-prices-rent
18
+ publicAllowlist: false
19
+ - name: property-data-sold-prices
20
+ publicAllowlist: false
21
+ - name: property-data-demand
22
+ publicAllowlist: false
23
+ - name: property-data-yields
24
+ publicAllowlist: false
25
+ - name: property-data-growth
26
+ publicAllowlist: false
27
+ - name: property-data-national-hpi
28
+ publicAllowlist: false
29
+ skills:
30
+ - skills/property-data/SKILL.md
31
+ always: false
32
+ metadata: {"platform":{"optional":true,"embed":["admin"]}}
33
+ mcp:
34
+ command: node
35
+ args:
36
+ - ${PLATFORM_ROOT}/lib/mcp-spawn-tee/dist/index.js
37
+ - ${PREMIUM_PLUGINS_ROOT}/real-agent/plugins/property-data/mcp/dist/index.js
38
+ env:
39
+ MCP_SPAWN_TEE_NAME: property-data
40
+ LOG_DIR: ${LOG_DIR}
41
+ PLATFORM_ROOT: ${PLATFORM_ROOT}
42
+ ACCOUNT_ID: ${ACCOUNT_ID}
43
+ SESSION_ID: ${SESSION_ID}
44
+ ---
45
+
46
+ # Real Agent — PropertyData
47
+
48
+ Local stdio MCP that proxies the PropertyData UK market-analytics HTTP API (propertydata.co.uk). Postcode-keyed analytics powering valuer + negotiator workflows: comparable evidence, asking-price baselines, sold-price history, demand index, rental yield, growth signals, and the national house-price index.
49
+
50
+ ## Capabilities
51
+
52
+ - **Key management** — register, deregister, and list a single PropertyData API key per account. AES-256-GCM encrypted at rest in Neo4j under the `PropertyDataKey` label.
53
+ - **Valuation** — point-estimate sale and rent valuations from postcode + property attributes (`valuation-sale`, `valuation-rent`).
54
+ - **Asking-price baselines** — live mean / median / 80th-percentile asking prices for sale and rent in a postcode (`prices`, `prices-rent`).
55
+ - **Sold-price history** — Land Registry sold transactions filtered by postcode, property type, and age (`sold-prices`).
56
+ - **Demand index** — number of properties currently for sale vs. average days to sell-STC for a postcode (`demand`).
57
+ - **Rental yield** — gross yield estimates by postcode and bedroom count (`yields`).
58
+ - **Growth signals** — short and long-term price growth by postcode (`growth`).
59
+ - **National house-price index** — UK-wide HPI series (`national-hpi`).
60
+
61
+ ## Security
62
+
63
+ The PropertyData API key is encrypted at rest with AES-256-GCM. Encryption key lives at `~/<configDir>/.property-data-encryption-key` with mode `0600`. Never include the key value in responses; identify the key by registration timestamp only. If the operator asks for the key value, explain that keys are encrypted and cannot be retrieved — they must be re-registered from the PropertyData dashboard.
64
+
65
+ ## When to use these tools
66
+
67
+ ### Pillar 1 — Comparable evidence for valuation
68
+
69
+ **Triggers** — operator says "comps for", "sold prices around", "what's gone for", "comparable evidence":
70
+ - `property-data-sold-prices` — Land Registry sold prices for the postcode
71
+
72
+ ### Pillar 2 — Asking-price baselines and point valuations
73
+
74
+ **Triggers** — operator says "what's it worth", "asking prices in", "point estimate", "ballpark":
75
+ - `property-data-valuation-sale` — point sale estimate for postcode + attributes
76
+ - `property-data-valuation-rent` — point rent estimate
77
+ - `property-data-prices` — distribution of asking prices for sale
78
+ - `property-data-prices-rent` — distribution of asking prices for rent
79
+
80
+ ### Pillar 3 — Demand + yield + growth (negotiation signals)
81
+
82
+ **Triggers** — operator says "demand in", "yield on", "growth", "is the market moving":
83
+ - `property-data-demand` — supply count + average days to sell-STC
84
+ - `property-data-yields` — gross rental yield by bedroom count
85
+ - `property-data-growth` — short and long-term price growth
86
+ - `property-data-national-hpi` — national HPI context
87
+
88
+ ### Key prerequisite
89
+
90
+ Every PropertyData tool requires a registered key. If `property-data-key-list` returns nothing for the account, surface the registration prompt before attempting any other call — every downstream tool will return `status=key-missing` otherwise.
91
+
92
+ ## Tool error envelope
93
+
94
+ Every tool returns either the PropertyData `data` payload as JSON text or an `isError: true` envelope with deterministic text shape:
95
+
96
+ - `Error: key-not-registered. Register a PropertyData API key with property-data-key-register before calling this tool.`
97
+ - `Error: http-<status> from PropertyData. <message>`
98
+ - `Error: bad-response from PropertyData (non-JSON, length=<n>).`
99
+
100
+ Operators see the reason directly; downstream skills branch on the prefix.
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
@@ -0,0 +1,153 @@
1
+ import { initStderrTee } from "../../../../lib/mcp-stderr-tee/dist/index.js";
2
+ initStderrTee("property-data");
3
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
4
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
5
+ import { z } from "zod";
6
+ import { keyRegister } from "./tools/key-register.js";
7
+ import { keyDeregister } from "./tools/key-deregister.js";
8
+ import { keyList } from "./tools/key-list.js";
9
+ import { valuationSale, valuationRent, prices, pricesRent, soldPrices, demand, yields, growth, nationalHpi, } from "./tools/endpoints.js";
10
+ import { closeDriver } from "./lib/neo4j.js";
11
+ import { KeyNotRegisteredError, PropertyDataError, BadResponseError, } from "./lib/propertydata-api.js";
12
+ const accountId = process.env.ACCOUNT_ID;
13
+ if (!accountId) {
14
+ throw new Error("ACCOUNT_ID environment variable is required");
15
+ }
16
+ const server = new McpServer({
17
+ name: "maxy-property-data",
18
+ version: "0.1.0",
19
+ });
20
+ console.error(`[property-data] server started, account=${accountId}`);
21
+ function errorEnvelope(err) {
22
+ let text;
23
+ if (err instanceof KeyNotRegisteredError) {
24
+ text =
25
+ "Error: key-not-registered. Register a PropertyData API key with property-data-key-register before calling this tool.";
26
+ }
27
+ else if (err instanceof PropertyDataError) {
28
+ text = `Error: http-${err.status} from PropertyData. ${err.upstreamMessage}`;
29
+ }
30
+ else if (err instanceof BadResponseError) {
31
+ text = `Error: bad-response from PropertyData (non-JSON, length=${err.length}).`;
32
+ }
33
+ else {
34
+ text = `Error: ${err instanceof Error ? err.message : String(err)}`;
35
+ }
36
+ return { content: [{ type: "text", text }], isError: true };
37
+ }
38
+ function endpointHandler(fn) {
39
+ return async (params) => {
40
+ try {
41
+ const text = await fn({ ...params, accountId: accountId });
42
+ return { content: [{ type: "text", text }] };
43
+ }
44
+ catch (err) {
45
+ return errorEnvelope(err);
46
+ }
47
+ };
48
+ }
49
+ // ─────────────────────────────────────────────────────────────────
50
+ // Key Management
51
+ // ─────────────────────────────────────────────────────────────────
52
+ server.tool("property-data-key-register", "Register the account's PropertyData API key. Validates the key against PropertyData's /national-hpi endpoint, encrypts it with AES-256-GCM, and stores it in Neo4j. One key per account; re-registering overwrites the existing key.", {
53
+ apiKey: z.string().min(8).describe("PropertyData API key from propertydata.co.uk dashboard"),
54
+ }, async ({ apiKey }) => {
55
+ try {
56
+ await keyRegister({ apiKey, accountId: accountId });
57
+ return {
58
+ content: [
59
+ {
60
+ type: "text",
61
+ text: "PropertyData API key registered successfully.",
62
+ },
63
+ ],
64
+ };
65
+ }
66
+ catch (err) {
67
+ return errorEnvelope(err);
68
+ }
69
+ });
70
+ server.tool("property-data-key-deregister", "Remove the account's PropertyData API key. The encrypted key is permanently deleted from Neo4j.", {}, async () => {
71
+ try {
72
+ await keyDeregister({ accountId: accountId });
73
+ return {
74
+ content: [{ type: "text", text: "PropertyData API key deregistered." }],
75
+ };
76
+ }
77
+ catch (err) {
78
+ return errorEnvelope(err);
79
+ }
80
+ });
81
+ server.tool("property-data-key-list", "Show whether a PropertyData API key is registered for this account. Never reveals the key value.", {}, async () => {
82
+ try {
83
+ const text = await keyList({ accountId: accountId });
84
+ return { content: [{ type: "text", text }] };
85
+ }
86
+ catch (err) {
87
+ return errorEnvelope(err);
88
+ }
89
+ });
90
+ // ─────────────────────────────────────────────────────────────────
91
+ // Valuation endpoints
92
+ // ─────────────────────────────────────────────────────────────────
93
+ const valuationSchema = {
94
+ postcode: z.string().min(2).describe("UK postcode (outcode or full)"),
95
+ type: z
96
+ .enum(["detached", "semi-detached", "terraced", "flat"])
97
+ .describe("Property type"),
98
+ bedrooms: z.number().int().min(0).describe("Bedroom count"),
99
+ bathrooms: z.number().int().min(0).optional().describe("Bathroom count"),
100
+ internal_area: z.number().optional().describe("Internal area (sq ft)"),
101
+ construction_date: z.string().optional().describe("Construction date band (e.g. 'pre1900', '1900-1929')"),
102
+ finish_quality: z
103
+ .enum(["luxury", "above_average", "average", "below_average", "needs_modernisation"])
104
+ .optional()
105
+ .describe("Finish quality"),
106
+ };
107
+ server.tool("property-data-valuation-sale", "Point sale-price estimate for a property given postcode + attributes. Returns point estimate plus comparables.", valuationSchema, endpointHandler(valuationSale));
108
+ server.tool("property-data-valuation-rent", "Point rent estimate (PCM) for a property given postcode + attributes. Returns point estimate plus comparables.", valuationSchema, endpointHandler(valuationRent));
109
+ // ─────────────────────────────────────────────────────────────────
110
+ // Asking-price distributions
111
+ // ─────────────────────────────────────────────────────────────────
112
+ const pricesSchema = {
113
+ postcode: z.string().min(2).describe("UK postcode (outcode or full)"),
114
+ type: z
115
+ .enum(["detached", "semi-detached", "terraced", "flat"])
116
+ .optional()
117
+ .describe("Filter by property type"),
118
+ bedrooms: z.number().int().min(0).optional().describe("Filter by bedroom count"),
119
+ };
120
+ server.tool("property-data-prices", "Asking-price distribution for sale listings in a postcode — mean, median, 80th percentile.", pricesSchema, endpointHandler(prices));
121
+ server.tool("property-data-prices-rent", "Asking-price distribution for rental listings in a postcode — mean, median, 80th percentile (PCM).", pricesSchema, endpointHandler(pricesRent));
122
+ // ─────────────────────────────────────────────────────────────────
123
+ // Sold prices (Land Registry)
124
+ // ─────────────────────────────────────────────────────────────────
125
+ server.tool("property-data-sold-prices", "Land Registry sold transactions for a postcode, optionally filtered by age, type, and bedrooms.", {
126
+ postcode: z.string().min(2).describe("UK postcode (outcode or full)"),
127
+ max_age: z.number().int().min(1).optional().describe("Max transaction age in months"),
128
+ type: z
129
+ .enum(["detached", "semi-detached", "terraced", "flat"])
130
+ .optional()
131
+ .describe("Filter by property type"),
132
+ bedrooms: z.number().int().min(0).optional().describe("Filter by bedroom count"),
133
+ }, endpointHandler(soldPrices));
134
+ // ─────────────────────────────────────────────────────────────────
135
+ // Demand / yields / growth / national HPI
136
+ // ─────────────────────────────────────────────────────────────────
137
+ server.tool("property-data-demand", "Demand signals for a postcode — count of properties for sale and average days to sell-STC.", { postcode: z.string().min(2).describe("UK postcode (outcode or full)") }, endpointHandler(demand));
138
+ server.tool("property-data-yields", "Gross rental yield for a postcode and bedroom count.", {
139
+ postcode: z.string().min(2).describe("UK postcode (outcode or full)"),
140
+ bedrooms: z.number().int().min(0).describe("Bedroom count"),
141
+ }, endpointHandler(yields));
142
+ server.tool("property-data-growth", "Short-term and long-term price growth signals for a postcode.", { postcode: z.string().min(2).describe("UK postcode (outcode or full)") }, endpointHandler(growth));
143
+ server.tool("property-data-national-hpi", "UK national house-price index series. No postcode required.", {}, endpointHandler(nationalHpi));
144
+ // ─────────────────────────────────────────────────────────────────
145
+ // Lifecycle
146
+ // ─────────────────────────────────────────────────────────────────
147
+ process.on("SIGINT", async () => {
148
+ await closeDriver();
149
+ process.exit(0);
150
+ });
151
+ const transport = new StdioServerTransport();
152
+ await server.connect(transport);
153
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export declare function encrypt(plaintext: string): string;
2
+ export declare function decrypt(encryptedValue: string): string;
3
+ //# sourceMappingURL=crypto.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../../src/lib/crypto.ts"],"names":[],"mappings":"AAgDA,wBAAgB,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAQjD;AAED,wBAAgB,OAAO,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,CAoBtD"}