@rubytech/create-realagent 1.0.847 → 1.0.850

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 (121) hide show
  1. package/dist/__tests__/port-canonicalisation.test.js +1 -0
  2. package/dist/__tests__/snap-chromium.test.js +115 -0
  3. package/dist/index.js +201 -1
  4. package/dist/port-resolution.js +1 -1
  5. package/dist/snap-chromium.js +89 -0
  6. package/package.json +1 -1
  7. package/payload/platform/plugins/admin/skills/onboarding/SKILL.md +1 -1
  8. package/payload/platform/plugins/admin/skills/public-agent-manager/SKILL.md +2 -2
  9. package/payload/platform/plugins/cloudflare/PLUGIN.md +1 -1
  10. package/payload/platform/plugins/cloudflare/scripts/setup-tunnel.sh +25 -7
  11. package/payload/platform/plugins/cloudflare/skills/setup-tunnel/SKILL.md +1 -1
  12. package/payload/platform/plugins/docs/references/adherence.md +1 -1
  13. package/payload/platform/plugins/docs/references/deployment.md +8 -0
  14. package/payload/platform/plugins/docs/references/plugins-guide.md +4 -2
  15. package/payload/platform/plugins/docs/references/troubleshooting.md +33 -0
  16. package/payload/platform/plugins/linkedin-import/PLUGIN.md +2 -2
  17. package/payload/platform/plugins/linkedin-import/skills/linkedin-import/references/connections.md +2 -2
  18. package/payload/platform/plugins/memory/PLUGIN.md +1 -1
  19. package/payload/platform/plugins/memory/references/schema-base.md +1 -1
  20. package/payload/platform/scripts/test-laptop-vnc-boot.sh +81 -0
  21. package/payload/platform/scripts/vnc.sh +42 -2
  22. package/payload/platform/templates/agents/admin/AGENTS.md +6 -4
  23. package/payload/platform/templates/agents/admin/IDENTITY.md +6 -2
  24. package/payload/platform/templates/specialists/agents/content-producer.md +2 -2
  25. package/payload/premium-plugins/real-agency/BUNDLE.md +3 -3
  26. package/payload/premium-plugins/real-agency/agents/valuer.md +10 -0
  27. package/payload/premium-plugins/real-agency/plugins/buyers/skills/buyer-management/SKILL.md +42 -0
  28. package/payload/premium-plugins/real-agency/plugins/buyers/skills/buyer-management/references/buyer-qualification-questions.md +16 -0
  29. package/payload/premium-plugins/real-agency/plugins/buyers/skills/buyer-management/references/buyer-qualification.md +59 -0
  30. package/payload/premium-plugins/real-agency/plugins/buyers/skills/buyer-management/references/buyer-scripts.md +63 -0
  31. package/payload/premium-plugins/real-agency/plugins/buyers/skills/buyer-management/references/buyer-working-scripts.md +54 -0
  32. package/payload/premium-plugins/real-agency/plugins/buyers/skills/buyer-management/references/feedback-collection.md +42 -0
  33. package/payload/premium-plugins/real-agency/plugins/buyers/skills/buyer-management/references/offer-capture.md +38 -0
  34. package/payload/premium-plugins/real-agency/plugins/buyers/skills/buyer-management/references/viewing-booking.md +32 -0
  35. package/payload/premium-plugins/real-agency/plugins/buyers/skills/buyer-management/references/viewing-management.md +52 -0
  36. package/payload/premium-plugins/real-agency/plugins/estate-sales/skills/negotiation/SKILL.md +35 -0
  37. package/payload/premium-plugins/real-agency/plugins/estate-sales/skills/negotiation/references/deal-saving.md +47 -0
  38. package/payload/premium-plugins/real-agency/plugins/estate-sales/skills/negotiation/references/negotiation-deep-guide.md +64 -0
  39. package/payload/premium-plugins/real-agency/plugins/estate-sales/skills/negotiation/references/negotiation-prep-principles.md +29 -0
  40. package/payload/premium-plugins/real-agency/plugins/estate-sales/skills/negotiation/references/negotiation-techniques.md +42 -0
  41. package/payload/premium-plugins/real-agency/plugins/estate-sales/skills/negotiation/references/offer-presentation.md +43 -0
  42. package/payload/premium-plugins/real-agency/plugins/estate-sales/skills/sales-negotiation/SKILL.md +29 -0
  43. package/payload/premium-plugins/real-agency/plugins/estate-sales/skills/sales-negotiation/references/chris-voss-negotiation.md +70 -0
  44. package/payload/premium-plugins/real-agency/plugins/estate-sales/skills/sales-negotiation/references/phil-jones-price-words.md +40 -0
  45. package/payload/premium-plugins/real-agency/plugins/estate-sales/skills/sales-negotiation/references/serhant-negotiation-plus.md +55 -0
  46. package/payload/premium-plugins/real-agency/plugins/estate-sales/skills/sales-negotiation/references/tom-panos-commission-pricing.md +57 -0
  47. package/payload/premium-plugins/real-agency/plugins/estate-sales/skills/sales-negotiation/references/tony-morris-questioning.md +54 -0
  48. package/payload/premium-plugins/real-agency/plugins/loop/mcp/dist/lib/loop-api.d.ts +6 -4
  49. package/payload/premium-plugins/real-agency/plugins/loop/mcp/dist/lib/loop-api.d.ts.map +1 -1
  50. package/payload/premium-plugins/real-agency/plugins/loop/mcp/dist/lib/loop-api.js +82 -10
  51. package/payload/premium-plugins/real-agency/plugins/loop/mcp/dist/lib/loop-api.js.map +1 -1
  52. package/payload/premium-plugins/real-agency/plugins/loop/mcp/src/lib/loop-api.ts +111 -15
  53. package/payload/server/chunk-DIRNBH7F.js +1603 -0
  54. package/payload/server/chunk-GOO2J3X7.js +10561 -0
  55. package/payload/server/chunk-LCAFHNZR.js +10420 -0
  56. package/payload/server/chunk-X3LVMXI5.js +10578 -0
  57. package/payload/server/client-pool-7Z6YRUQT.js +34 -0
  58. package/payload/server/maxy-edge.js +2 -2
  59. package/payload/server/public/assets/{admin-DFUet1XM.js → admin-Dyl8uNxX.js} +1 -1
  60. package/payload/server/public/assets/{architectureDiagram-Q4EWVU46-Bs5MjIKf.js → architectureDiagram-Q4EWVU46-BePoi8XC.js} +1 -1
  61. package/payload/server/public/assets/{blockDiagram-DXYQGD6D-BVSXiX4T.js → blockDiagram-DXYQGD6D-BkiwLTtq.js} +1 -1
  62. package/payload/server/public/assets/{c4Diagram-AHTNJAMY-DBqsWCjl.js → c4Diagram-AHTNJAMY-bpjPj2Ln.js} +1 -1
  63. package/payload/server/public/assets/channel-D3U0_a1j.js +1 -0
  64. package/payload/server/public/assets/{chunk-336JU56O-COUTB2TN.js → chunk-336JU56O-BpATJiGl.js} +2 -2
  65. package/payload/server/public/assets/{chunk-426QAEUC-zKsTsXw6.js → chunk-426QAEUC-Wz6Bpsil.js} +1 -1
  66. package/payload/server/public/assets/{chunk-4TB4RGXK-CI9i2J5g.js → chunk-4TB4RGXK-CLXL19Wd.js} +1 -1
  67. package/payload/server/public/assets/{chunk-5FUZZQ4R-DfchzZ2Y.js → chunk-5FUZZQ4R-BoTfWHuW.js} +1 -1
  68. package/payload/server/public/assets/{chunk-5PVQY5BW-_iMyxz0C.js → chunk-5PVQY5BW-RhIfPCRB.js} +1 -1
  69. package/payload/server/public/assets/{chunk-EDXVE4YY-Ddtw_ZHk.js → chunk-EDXVE4YY-utELKGQK.js} +1 -1
  70. package/payload/server/public/assets/{chunk-ENJZ2VHE-BrGMkslM.js → chunk-ENJZ2VHE-CNHjq5xK.js} +1 -1
  71. package/payload/server/public/assets/{chunk-ICPOFSXX-DHInTpuR.js → chunk-ICPOFSXX-Di63NBur.js} +1 -1
  72. package/payload/server/public/assets/{chunk-OYMX7WX6-mOQ4KZ9j.js → chunk-OYMX7WX6-BSPzqyxs.js} +1 -1
  73. package/payload/server/public/assets/{chunk-U2HBQHQK-D5vGkUe9.js → chunk-U2HBQHQK-BZnA7c4T.js} +1 -1
  74. package/payload/server/public/assets/{chunk-X2U36JSP-CnNxZbqc.js → chunk-X2U36JSP-DpQ2OA_c.js} +1 -1
  75. package/payload/server/public/assets/{chunk-YZCP3GAM-Cb7OSc_r.js → chunk-YZCP3GAM-BAkNXu0G.js} +1 -1
  76. package/payload/server/public/assets/{chunk-ZZ45TVLE-BipxpzL8.js → chunk-ZZ45TVLE-DBSm41oP.js} +1 -1
  77. package/payload/server/public/assets/classDiagram-6PBFFD2Q-6EGGLDD_.js +1 -0
  78. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-DfAV4tgE.js +1 -0
  79. package/payload/server/public/assets/clone-BoV8noAi.js +1 -0
  80. package/payload/server/public/assets/{dagre-KV5264BT-B91sXKT2.js → dagre-KV5264BT-BkvWofSp.js} +1 -1
  81. package/payload/server/public/assets/{dagre-lObrgXUJ.js → dagre-nvPNAunb.js} +1 -1
  82. package/payload/server/public/assets/{diagram-5BDNPKRD-DB2Kcx9r.js → diagram-5BDNPKRD-CMEgyt4E.js} +1 -1
  83. package/payload/server/public/assets/{diagram-G4DWMVQ6-Cq1J05SW.js → diagram-G4DWMVQ6-ChorrAF0.js} +1 -1
  84. package/payload/server/public/assets/{diagram-MMDJMWI5-CwqXxUXd.js → diagram-MMDJMWI5-D_iD27po.js} +1 -1
  85. package/payload/server/public/assets/{diagram-TYMM5635-Nmk38u6a.js → diagram-TYMM5635-8qXI1ioG.js} +1 -1
  86. package/payload/server/public/assets/{erDiagram-SMLLAGMA-D2EfAdSD.js → erDiagram-SMLLAGMA-BFjtKDSB.js} +1 -1
  87. package/payload/server/public/assets/{flowDiagram-DWJPFMVM-CS98o6Jz.js → flowDiagram-DWJPFMVM-Bpd7IL9l.js} +1 -1
  88. package/payload/server/public/assets/{ganttDiagram-T4ZO3ILL-rWm6xQ8t.js → ganttDiagram-T4ZO3ILL-CwOozU85.js} +1 -1
  89. package/payload/server/public/assets/{gitGraphDiagram-UUTBAWPF-BuwECvwx.js → gitGraphDiagram-UUTBAWPF-CcPILiC9.js} +1 -1
  90. package/payload/server/public/assets/{graphlib-BXEED8qM.js → graphlib-B_mcXEVr.js} +1 -1
  91. package/payload/server/public/assets/{infoDiagram-42DDH7IO-CEmJMuVh.js → infoDiagram-42DDH7IO-T2sn--WJ.js} +1 -1
  92. package/payload/server/public/assets/{ishikawaDiagram-UXIWVN3A-CAQMMx-Y.js → ishikawaDiagram-UXIWVN3A-DOP9-Q8H.js} +1 -1
  93. package/payload/server/public/assets/{journeyDiagram-VCZTEJTY-toHrBGCq.js → journeyDiagram-VCZTEJTY-DGATg0WC.js} +1 -1
  94. package/payload/server/public/assets/{kanban-definition-6JOO6SKY-DwXLkenV.js → kanban-definition-6JOO6SKY-C5PigmKg.js} +1 -1
  95. package/payload/server/public/assets/{line-BkM2KuUb.js → line-DlKKhwkO.js} +1 -1
  96. package/payload/server/public/assets/{mermaid-parser.core-CsaDWYZC.js → mermaid-parser.core-C8xGCa9p.js} +1 -1
  97. package/payload/server/public/assets/{mermaid.core-CvICILSR.js → mermaid.core-CCUSwZB_.js} +3 -3
  98. package/payload/server/public/assets/{mindmap-definition-QFDTVHPH-DQyCWpKS.js → mindmap-definition-QFDTVHPH-75k-IVhC.js} +1 -1
  99. package/payload/server/public/assets/{pieDiagram-DEJITSTG-CVRIcK6b.js → pieDiagram-DEJITSTG-DN5RsDwZ.js} +1 -1
  100. package/payload/server/public/assets/preload-helper-qlgyTAkD.js +1 -0
  101. package/payload/server/public/assets/{public-CR_CX3K5.js → public-B_PNZUph.js} +1 -1
  102. package/payload/server/public/assets/{quadrantDiagram-34T5L4WZ-CnfXm2xw.js → quadrantDiagram-34T5L4WZ-Sd9x6pNe.js} +1 -1
  103. package/payload/server/public/assets/{requirementDiagram-MS252O5E-BntW6fnu.js → requirementDiagram-MS252O5E-BDgifYzj.js} +1 -1
  104. package/payload/server/public/assets/{sankeyDiagram-XADWPNL6-Bt6AfgXn.js → sankeyDiagram-XADWPNL6-BX9VULNJ.js} +1 -1
  105. package/payload/server/public/assets/{sequenceDiagram-FGHM5R23-D6s0kP6H.js → sequenceDiagram-FGHM5R23-z3vMxhgE.js} +1 -1
  106. package/payload/server/public/assets/{stateDiagram-FHFEXIEX-B9y9cOff.js → stateDiagram-FHFEXIEX-DlP0hBxF.js} +1 -1
  107. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-DSddQStC.js +1 -0
  108. package/payload/server/public/assets/{timeline-definition-GMOUNBTQ-DIFjQGfl.js → timeline-definition-GMOUNBTQ-DwQbhKCo.js} +1 -1
  109. package/payload/server/public/assets/{useVoiceRecorder-DWRtIHOw.js → useVoiceRecorder-fD0IWzJj.js} +3 -3
  110. package/payload/server/public/assets/{vennDiagram-DHZGUBPP-YRVHIBU9.js → vennDiagram-DHZGUBPP-WTqmZWWa.js} +1 -1
  111. package/payload/server/public/assets/{wardleyDiagram-NUSXRM2D-B20PPeAr.js → wardleyDiagram-NUSXRM2D-BUY50x5T.js} +1 -1
  112. package/payload/server/public/assets/{xychartDiagram-5P7HB3ND-BztKw58Q.js → xychartDiagram-5P7HB3ND-Btdq-fDj.js} +1 -1
  113. package/payload/server/public/index.html +3 -3
  114. package/payload/server/public/public.html +3 -3
  115. package/payload/server/server.js +6 -3
  116. package/payload/server/public/assets/channel-lEc18pSi.js +0 -1
  117. package/payload/server/public/assets/classDiagram-6PBFFD2Q-rkW6IED-.js +0 -1
  118. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-CRQJXpMG.js +0 -1
  119. package/payload/server/public/assets/clone-icRAjexu.js +0 -1
  120. package/payload/server/public/assets/preload-helper-bPV_ZjF3.js +0 -1
  121. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-DH4gbGCS.js +0 -1
@@ -57,12 +57,12 @@ Premium plugins are one-off purchases that grant permanent ownership. They are n
57
57
  | Plugin | Type | What it does | Public agent |
58
58
  |--------|------|-------------|-------------|
59
59
  | `teaching` | Skills | Interactive tutoring, lesson planning, and study pack generation from your knowledge base | Yes — all 3 skills serve students and parents |
60
- | `real-agency` | Bundle (10 sub-plugins) | UK estate agency skills — sales, listings, vendor management, buyer management, lead generation, coaching, business operations, onboarding, teaching, and Loop CRM. 2 specialist roles (negotiator, valuer) | 4 sub-plugins (estate-sales, buyers, estate-coaching, estate-onboarding) |
60
+ | `real-agency` | Bundle (10 sub-plugins) | UK estate agency skills — sales, listings, vendor management, buyer management, lead generation, coaching, business operations, onboarding, teaching, and Loop CRM. 3 specialist roles (negotiator, valuer, compliance) | 5 sub-plugins (estate-sales, buyers, estate-coaching, estate-teaching, estate-onboarding) |
61
61
  | `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 |
62
62
 
63
63
  **How it works:** When you purchase a premium plugin, it's delivered to your {{productName}} via conversation. Tell {{productName}} "Enable the teaching plugin" and it handles the rest. Premium plugins are yours permanently — they survive updates and reinstalls.
64
64
 
65
- Some premium plugins are **bundles** — a single purchase that delivers multiple sub-plugins, each independently activatable. For example, Real Agency delivers 11 sub-plugins covering different aspects of estate agency work. You can enable all of them or just the ones you need (e.g., "Enable estate-sales" for just the sales skills). Enabling or disabling individual sub-plugins does not affect the others.
65
+ Some premium plugins are **bundles** — a single purchase that delivers multiple sub-plugins, each independently activatable. For example, Real Agency delivers 10 sub-plugins covering different aspects of estate agency work. You can enable all of them or just the ones you need (e.g., "Enable estate-sales" for just the sales skills). Enabling or disabling individual sub-plugins does not affect the others.
66
66
 
67
67
  **Public agent embedding:** Premium plugins marked as public-eligible have their full content (skills and reference knowledge) embedded in public agent prompts. This means a public agent for a Real Agency member can handle buyer enquiries, book viewings, deliver coaching content, and onboard new applicants — all powered by the premium plugin's domain knowledge. Plugins marked admin-only (listings, vendors, leads, business) are only available to the account owner's admin agent.
68
68
 
@@ -72,6 +72,8 @@ Some premium plugins include pre-built public agent templates — ready-made con
72
72
 
73
73
  Some premium plugins ship pre-built workflows that are created when the plugin is enabled. These workflows are fully yours — you can inspect, edit, run, and manage them through conversation, exactly like workflows you create yourself. The plugin provides the starting point; you own the result.
74
74
 
75
+ **If a premium plugin ever stops working** — `documents`, `teaching`, anything else you've paid for — and {{productName}} responds as if it doesn't have those tools, the platform's health check (`/api/health.missingPlugins`) will name the affected plugin. Tell {{productName}} "deliver the {{plugin}} plugin" — it re-runs the same delivery step that fires automatically at session start. If the plugin isn't in the device's staging area, re-run the installer for this brand.
76
+
75
77
  ## Choosing Plugins
76
78
 
77
79
  During first-time setup, {{productName}} presents a plugin selection screen where you choose which plugins to activate. Core plugins are pre-selected and locked. Recommended plugins are pre-selected but optional. You can change your mind later.
@@ -420,6 +420,39 @@ The installer's resolver will then see `dpkg -s chromium-browser` exit 0 for the
420
420
 
421
421
  ---
422
422
 
423
+ ## VNC browser will not start on Linux laptop — `Permission denied (13)` on SingletonLock
424
+
425
+ **Symptom:** Boot log `~/.{brand}/logs/vnc-boot.log` shows:
426
+
427
+ ```
428
+ Starting Chromium on :<vncDisplay> (vnc) profile=/home/<user>/.{brand}/chromium-profile CDP=:<cdpPort>
429
+ ERROR:chrome/browser/process_singleton_posix.cc:345] Failed to create
430
+ /home/<user>/.{brand}/chromium-profile/SingletonLock: Permission denied (13)
431
+ ERROR: Chromium failed to start on :<vncDisplay> (vnc) — CDP port <cdpPort> not listening (browser-specialist degraded)
432
+ ```
433
+
434
+ `dmesg` (or `journalctl -k`) shows AppArmor `DENIED` lines naming `profile="snap.chromium.chromium"` and the `~/.{brand}/chromium-profile/` path. The brand admin chat reports the public-agent VNC browser as unavailable.
435
+
436
+ **What it means:** Your `/usr/bin/chromium` is a snap symlink. Snap's AppArmor profile excludes hidden top-level paths under `$HOME` from its `home` interface, so writes to per-brand Chromium profile dirs at `~/.maxy/chromium-profile/` and `~/.realagent/chromium-profile/` are denied — Chromium cannot create its `SingletonLock` and never starts the CDP listener. This is exclusively a Linux-laptop problem (Ubuntu Noble); Raspberry Pi OS Bookworm ships `chromium` as a real `.deb` and is unaffected.
437
+
438
+ **Fix:** Re-run the installer at version 1.0.849 or later. The installer detects the snap-confined chromium during system-dependency setup and replaces it with Google Chrome stable from Google's signed apt repo:
439
+
440
+ ```bash
441
+ npx -y @rubytech/create-maxy@latest
442
+ ```
443
+
444
+ The resolved non-snap binary path is recorded at `<INSTALL_DIR>/platform/config/chromium-binary.path` (single line) and read by every Chromium call site (VNC service, in-page wrapper, Cloudflare OAuth spawn, Playwright server). After re-running, verify with the bundled acceptance script:
445
+
446
+ ```bash
447
+ MAXY_PLATFORM_ROOT=$HOME/<install-dir>/platform $HOME/<install-dir>/platform/scripts/test-laptop-vnc-boot.sh
448
+ ```
449
+
450
+ The script exits 0 only when (1) the configured Chromium realpath is non-snap, (2) the path is absolute and executable, (3) the per-brand CDP port returns Chromium version JSON, and (4) `vnc-boot.log` since the last `[vnc.sh] start` ends with `VNC + browser stack running` and contains no `Chromium failed to start` line.
451
+
452
+ **Deeper diagnostic:** `vnc.sh` and the in-page wrapper now refuse to start (and exit with a snap-Chromium reference in the boot log) when `chromium-binary.path` is absent or its realpath lands under `/snap/`. If you see those messages, the install completed before the fix shipped — re-run `npx -y @rubytech/create-maxy@latest`. Manual workaround for an emergency (not a fix): `sudo apt-get install -y google-chrome-stable` and confirm `which google-chrome-stable` is non-snap, then re-run the installer to write `chromium-binary.path`.
453
+
454
+ ---
455
+
423
456
  ## Terminal iframe renders black and cursor vanishes over the canvas
424
457
 
425
458
  **Symptom:** Header-menu Terminal click appears to succeed — no error toast, overlay opens — but the iframe renders uniformly black, keystrokes do not reach any shell, and the mouse cursor disappears the moment it enters the iframe (visible elsewhere in the page).
@@ -10,11 +10,11 @@ metadata: {"platform":{"optional":true,"pluginKey":"linkedin-import"}}
10
10
 
11
11
  # LinkedIn Import
12
12
 
13
- Ingests a LinkedIn Basic Data Export (unzipped directory of CSVs + subdirectories) into the Maxy Neo4j graph. Skill-only plugin — no MCP server, no admin tools added. The skill runs under the `database-operator` specialist, which owns external-archive ingestion and ad-hoc graph operations.
13
+ Ingests a LinkedIn Basic Data Export (unzipped directory of CSVs + subdirectories) into the Maxy Neo4j graph. Skill-only plugin — no MCP server, no admin tools added. The skill runs under the `specialists:database-operator` specialist, which owns external-archive ingestion and ad-hoc graph operations.
14
14
 
15
15
  ## When this applies
16
16
 
17
- The admin agent delegates to `database-operator` when the operator drops a `Basic_LinkedInDataExport_*` directory (or references one by path) into chat. The specialist runs the skill's archive-owner confirmation flow before any CSV is read, then ingests the CSVs the skill has references for.
17
+ The admin agent delegates to `specialists:database-operator` when the operator drops a `Basic_LinkedInDataExport_*` directory (or references one by path) into chat. The specialist runs the skill's archive-owner confirmation flow before any CSV is read, then ingests the CSVs the skill has references for.
18
18
 
19
19
  ## Intra-plugin growth
20
20
 
@@ -110,7 +110,7 @@ Rows missing a position but present with a company produce a `WORKS_FOR` edge wi
110
110
 
111
111
  ## Post-import verification (operator-side, not agent-side)
112
112
 
113
- After ingest, the operator can verify counts via the `database-operator` specialist's read tools — `mcp__memory__memory-search` with `labels: ["Person"]` plus a filter, or a direct read query through `mcp__graph__maxy-graph-read_neo4j_cypher`:
113
+ After ingest, the operator can verify counts via the `specialists:database-operator` specialist's read tools — `mcp__memory__memory-search` with `labels: ["Person"]` plus a filter, or a direct read query through `mcp__graph__maxy-graph-read_neo4j_cypher`:
114
114
 
115
115
  ```cypher
116
116
  // Owner → connections count
@@ -132,4 +132,4 @@ These are **read queries**, not writes. Cypher writes from the agent are forbidd
132
132
  | Tool error "row connectedOn is not ISO 8601" | Parser left `Connected On` in `"23 Apr 2026"` form | Convert to `YYYY-MM-DD` before passing to the tool |
133
133
  | Tool error "ownerNodeId not found" | Owner-confirmation flow not run, or operator typed the wrong id | Re-run owner confirmation; pass the resulting `elementId` as `ownerNodeId` |
134
134
  | `WORKS_FOR` count « connection count | Many rows have blank company | Expected — LinkedIn doesn't force connections to list a current employer |
135
- | Tool not present in `init` frame | `database-operator` spawned without the `mcp__memory__memory-archive-write` token | Loud-fail per database-operator's prerogatives. Do not improvise via Bash. Operator must remediate (re-seed specialist templates) |
135
+ | Tool not present in `init` frame | `specialists:database-operator` spawned without the `mcp__memory__memory-archive-write` token | Loud-fail per database-operator's prerogatives. Do not improvise via Bash. Operator must remediate (re-seed specialist templates) |
@@ -109,7 +109,7 @@ Before any structured write, load `references/schema-base.md` via `plugin-read`.
109
109
 
110
110
  ## Document Ingestion
111
111
 
112
- Document ingestion of any kind — PDFs, text, transcripts, web pages, single files — routes to the `database-operator` specialist, which loads the universal `document-ingest` skill at `skills/document-ingest/SKILL.md`. The admin agent never calls `memory-ingest` directly; it dispatches with the document path, the document subject (the anchor node), and the visibility scope.
112
+ Document ingestion of any kind — PDFs, text, transcripts, web pages, single files — routes to the `specialists:database-operator` specialist, which loads the universal `document-ingest` skill at `skills/document-ingest/SKILL.md`. The admin agent never calls `memory-ingest` directly; it dispatches with the document path, the document subject (the anchor node), and the visibility scope.
113
113
 
114
114
  ### Pipeline
115
115
 
@@ -206,7 +206,7 @@ The classifier returns `kind` strings from the closed enumeration above. `kind`
206
206
  | `TO` | `KnowledgeDocument` → `Person` or `Organization` | Email direct recipient — written from `documentEdges` per recipient. |
207
207
  | `CC` | `KnowledgeDocument` → `Person` or `Organization` | Email cc'd recipient — written from `documentEdges` per cc. |
208
208
  | `SPEAKER` | `KnowledgeDocument` → `Person` | Voice-note / single-speaker transcript speaker — written from `documentEdges`. |
209
- | `MENTIONS` | `KnowledgeDocument` → `Person`, `Organization`, `Service`, `Task`, `Event`, `KnowledgeDocument`, `BrandingData` | Catch-all for entities the dispatch brief named that the document references but for which no document-shape-specific edge applies — written by `database-operator` in the `wire-brief-entities` pipeline step. |
209
+ | `MENTIONS` | `KnowledgeDocument` → `Person`, `Organization`, `Service`, `Task`, `Event`, `KnowledgeDocument`, `BrandingData` | Catch-all for entities the dispatch brief named that the document references but for which no document-shape-specific edge applies — written by `specialists:database-operator` in the `wire-brief-entities` pipeline step. |
210
210
  | `DEFINES` | `Section:Definitions` → `DefinedTerm` | Contract definitions — written from per-section `related`. |
211
211
 
212
212
  **Ontology-growth review query.** When a document accumulates several `:Section:Other` nodes, the operator (or admin agent) can run the following Cypher to surface candidate ontology additions:
@@ -0,0 +1,81 @@
1
+ #!/usr/bin/env bash
2
+ # Task 929 — laptop VNC + Chromium boot acceptance test.
3
+ #
4
+ # Asserts the four green conditions from .tasks/929 §Verification:
5
+ # 1. The configured Chromium binary's realpath does NOT contain `/snap/`.
6
+ # 2. The configured binary is on PATH and executable.
7
+ # 3. http://127.0.0.1:${cdpPort}/json/version returns the Chromium version JSON.
8
+ # 4. ~/.{configDir}/logs/vnc-boot.log ends with `VNC + browser stack running`
9
+ # with no preceding `Chromium failed to start` line.
10
+ #
11
+ # Exits non-zero on any assertion failure so this script is wired into the
12
+ # create-maxy post-install gate — any package bump that re-introduces
13
+ # snap-confined Chromium fails before publish (`feedback_no_admin_upgrade_path.md`).
14
+ #
15
+ # Usage (production / post-install): test-laptop-vnc-boot.sh
16
+ # Usage (CI / dev shell): MAXY_PLATFORM_ROOT=/path/to/maxy/platform test-laptop-vnc-boot.sh
17
+
18
+ set -uo pipefail
19
+
20
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
21
+ PLATFORM_ROOT="${MAXY_PLATFORM_ROOT:-$(dirname "$SCRIPT_DIR")}"
22
+ BRAND_JSON="${PLATFORM_ROOT}/config/brand.json"
23
+ CHROMIUM_BIN_FILE="${PLATFORM_ROOT}/config/chromium-binary.path"
24
+
25
+ fail() { echo "FAIL: $*" >&2; exit 1; }
26
+ pass() { echo "OK: $*"; }
27
+
28
+ # --- Resolve config: brand persistDir + cdpPort. brand.json is mandatory.
29
+ [ -r "$BRAND_JSON" ] || fail "${BRAND_JSON} unreadable"
30
+ command -v jq >/dev/null 2>&1 || fail "jq not on PATH (apt install jq)"
31
+ CONFIG_DIR=$(jq -r '.configDir // ".maxy"' "$BRAND_JSON")
32
+ CDP_PORT=$(jq -r '.cdpPort // 9222' "$BRAND_JSON")
33
+ PERSIST_DIR="${HOME}/${CONFIG_DIR}"
34
+ VNC_LOG="${PERSIST_DIR}/logs/vnc-boot.log"
35
+
36
+ # --- Assertion 1: chromium-binary.path realpath is non-snap.
37
+ [ -r "$CHROMIUM_BIN_FILE" ] || fail "${CHROMIUM_BIN_FILE} missing — installer did not write it"
38
+ CHROMIUM_BIN="$(head -n1 "$CHROMIUM_BIN_FILE" | tr -d '[:space:]')"
39
+ [ -n "$CHROMIUM_BIN" ] || fail "${CHROMIUM_BIN_FILE} is empty"
40
+ [ -x "$CHROMIUM_BIN" ] || fail "configured Chromium ${CHROMIUM_BIN} is not executable"
41
+ CHROMIUM_REALPATH="$(readlink -f "$CHROMIUM_BIN" 2>/dev/null || echo "$CHROMIUM_BIN")"
42
+ case ":$(echo "$CHROMIUM_REALPATH" | tr '/' ':'):" in
43
+ *:snap:*) fail "${CHROMIUM_BIN} resolves to ${CHROMIUM_REALPATH} (snap-confined — AppArmor will deny SingletonLock writes)" ;;
44
+ esac
45
+ pass "[1/4] Chromium binary ${CHROMIUM_BIN} → realpath=${CHROMIUM_REALPATH} (non-snap)"
46
+
47
+ # --- Assertion 2: configured binary is the same as `which chromium` resolves
48
+ # to OR an absolute path bypassing PATH. Skipped if the
49
+ # configured path is absolute and executable (the only thing
50
+ # callers actually require). The PATH check is informational.
51
+ if [ "${CHROMIUM_BIN#/}" = "$CHROMIUM_BIN" ]; then
52
+ fail "${CHROMIUM_BIN_FILE} contains a relative path — must be absolute"
53
+ fi
54
+ pass "[2/4] ${CHROMIUM_BIN} is an absolute, executable path"
55
+
56
+ # --- Assertion 3: CDP endpoint responds with version JSON.
57
+ CDP_URL="http://127.0.0.1:${CDP_PORT}/json/version"
58
+ CDP_RESP="$(curl -fsS -m 5 "$CDP_URL" 2>&1 || true)"
59
+ if ! echo "$CDP_RESP" | jq -e '.Browser // empty' >/dev/null 2>&1; then
60
+ fail "[3/4] ${CDP_URL} did not return Chromium version JSON. Response: ${CDP_RESP:0:500}"
61
+ fi
62
+ pass "[3/4] ${CDP_URL} returns Chromium version JSON"
63
+
64
+ # --- Assertion 4: vnc-boot.log ends with the success line and never
65
+ # emitted `Chromium failed to start` after the most recent
66
+ # `[vnc.sh] start` marker.
67
+ [ -r "$VNC_LOG" ] || fail "[4/4] ${VNC_LOG} unreadable"
68
+ LAST_START_LINE=$(grep -n "\[vnc.sh\] start " "$VNC_LOG" | tail -n1 | cut -d: -f1)
69
+ if [ -z "$LAST_START_LINE" ]; then
70
+ fail "[4/4] ${VNC_LOG} contains no [vnc.sh] start marker — vnc.sh has not been invoked yet"
71
+ fi
72
+ TAIL_AFTER_START=$(tail -n +"$LAST_START_LINE" "$VNC_LOG")
73
+ if echo "$TAIL_AFTER_START" | grep -q "Chromium failed to start"; then
74
+ fail "[4/4] ${VNC_LOG} since last start contains 'Chromium failed to start' (boot regression)"
75
+ fi
76
+ if ! echo "$TAIL_AFTER_START" | grep -q "VNC + browser stack running"; then
77
+ fail "[4/4] ${VNC_LOG} since last start has no 'VNC + browser stack running' line — VNC boot incomplete"
78
+ fi
79
+ pass "[4/4] ${VNC_LOG} reports VNC + browser stack running with no Chromium failed-to-start"
80
+
81
+ echo "Task 929 acceptance: PASS (4/4)"
@@ -82,6 +82,46 @@ mkdir -p "$LOG_DIR"
82
82
 
83
83
  log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" >> "$LOG_FILE"; }
84
84
 
85
+ # Task 929 — resolve the absolute Chromium binary path from the install-time
86
+ # config file. The installer (packages/create-maxy/src/index.ts
87
+ # ensureNonSnapChromium + writeChromiumBinaryPathFile) writes this file with
88
+ # the non-snap binary chosen for this device — `/usr/bin/chromium` on Pi
89
+ # Bookworm (real .deb) or `/usr/bin/google-chrome-stable` on Ubuntu Noble
90
+ # laptop where the system `/usr/bin/chromium` realpaths to the snap launcher.
91
+ # Hard-fail when the file is absent or the resolved path is snap-confined:
92
+ # the AppArmor `home` profile denies writes to ~/.{brand}/chromium-profile/
93
+ # and Chromium will never start the CDP listener. Loud fail beats silent
94
+ # fallback (silent-fallback-masks-root-cause).
95
+ CHROMIUM_BIN_FILE="${PLATFORM_ROOT}/config/chromium-binary.path"
96
+ if [ ! -r "$CHROMIUM_BIN_FILE" ]; then
97
+ log "[vnc.sh:chromium] FATAL: ${CHROMIUM_BIN_FILE} missing or unreadable"
98
+ echo "ERROR: ${CHROMIUM_BIN_FILE} missing or unreadable." >&2
99
+ echo " Re-run the installer to provision a non-snap Chromium (Task 929)." >&2
100
+ exit 1
101
+ fi
102
+ CHROMIUM_BIN="$(head -n1 "$CHROMIUM_BIN_FILE" | tr -d '[:space:]')"
103
+ if [ -z "$CHROMIUM_BIN" ]; then
104
+ log "[vnc.sh:chromium] FATAL: ${CHROMIUM_BIN_FILE} is empty"
105
+ echo "ERROR: ${CHROMIUM_BIN_FILE} is empty — re-run installer (Task 929)." >&2
106
+ exit 1
107
+ fi
108
+ if [ ! -x "$CHROMIUM_BIN" ]; then
109
+ log "[vnc.sh:chromium] FATAL: configured CHROMIUM_BIN=${CHROMIUM_BIN} is not executable"
110
+ echo "ERROR: configured Chromium binary ${CHROMIUM_BIN} is not executable — re-run installer (Task 929)." >&2
111
+ exit 1
112
+ fi
113
+ CHROMIUM_REALPATH="$(readlink -f "$CHROMIUM_BIN" 2>/dev/null || echo "$CHROMIUM_BIN")"
114
+ case ":$(echo "$CHROMIUM_REALPATH" | tr '/' ':'):" in
115
+ *:snap:*)
116
+ log "[vnc.sh:chromium] FATAL: CHROMIUM_BIN=${CHROMIUM_BIN} resolves to ${CHROMIUM_REALPATH} (snap-confined)"
117
+ echo "ERROR: configured Chromium ${CHROMIUM_BIN} resolves to ${CHROMIUM_REALPATH} which is snap-confined." >&2
118
+ echo " Snap AppArmor denies writes to ~/.{brand}/chromium-profile/. Re-run installer to install Google Chrome (Task 929)." >&2
119
+ exit 1
120
+ ;;
121
+ esac
122
+ CHROMIUM_CONFINEMENT="non-snap"
123
+ log "[vnc.sh:chromium] bin=${CHROMIUM_BIN} realpath=${CHROMIUM_REALPATH} confinement=${CHROMIUM_CONFINEMENT}"
124
+
85
125
  kill_stale() {
86
126
  # Brand-scoped matchers (Task 553): pkill on --user-data-dir narrows the
87
127
  # Chromium kill to this brand's profile only, so two brands on the same
@@ -229,7 +269,7 @@ start_chrome_on() {
229
269
  mkdir -p "${CHROMIUM_PROFILE_DIR}"
230
270
  log "Starting Chromium on ${target_display} (${label}) profile=${CHROMIUM_PROFILE_DIR} CDP=:${CDP_PORT}"
231
271
 
232
- DISPLAY="${target_display}" /usr/bin/chromium \
272
+ DISPLAY="${target_display}" "$CHROMIUM_BIN" \
233
273
  --user-data-dir="${CHROMIUM_PROFILE_DIR}" \
234
274
  --ozone-platform=x11 \
235
275
  --no-sandbox \
@@ -306,7 +346,7 @@ start_chrome_native() {
306
346
  env_vars+=("WAYLAND_DISPLAY=${NATIVE_WAYLAND_DISPLAY}")
307
347
  fi
308
348
 
309
- env "${env_vars[@]}" /usr/bin/chromium \
349
+ env "${env_vars[@]}" "$CHROMIUM_BIN" \
310
350
  --user-data-dir="${CHROMIUM_PROFILE_DIR}" \
311
351
  "$ozone_flag" \
312
352
  --no-sandbox \
@@ -1,10 +1,12 @@
1
1
  # Installed Roles
2
2
 
3
3
  <!-- Entries written by admin agent when roles are installed. One line per role.
4
- Format: - **{name}**: {one-line rule — when to delegate to this role}
5
- This exact format is required for reliable Edit-based removal.
4
+ Format: - **specialists:{name}**: {one-line rule — when to delegate to this role}
5
+ The `specialists:` prefix is the canonical dispatch ID registered by the SDK;
6
+ bare names are rejected by the runtime registry. This exact format is also
7
+ required for reliable Edit-based removal.
6
8
 
7
9
  Example (populated):
8
- - **personal-assistant**: Scheduling, platform administration, messaging channels, and browser automation — delegate when a task involves operational work.
9
- - **research-assistant**: Deep research, knowledge management, and visual production — delegate when a task requires web research or graph reorganisation.
10
+ - **specialists:personal-assistant**: Scheduling, platform administration, messaging channels, and browser automation — delegate when a task involves operational work.
11
+ - **specialists:research-assistant**: Deep research, knowledge management, and visual production — delegate when a task requires web research or graph reorganisation.
10
12
  -->
@@ -165,8 +165,8 @@ When the user asks what you can do, answer from the specialist domains, admin-ow
165
165
  - Think strategically. Surface problems before they become urgent. Recommend actions based on what you know.
166
166
  - Never state a future commitment ("I'll flag", "I'll check", "I'll remind") without immediately creating the mechanism to fulfil it — a scheduled event, a task, or a workflow trigger. A commitment without a backing mechanism is a broken promise.
167
167
  - Store everything you learn about the business in the graph — not in files.
168
- - For document ingestion of any kind — PDFs, text, transcripts, web pages, audio, video, single files, archives — delegate to the `database-operator` specialist. Include the document path, the document subject (account owner, the business, a third party, etc. — ask if not obvious from context), and the scope (admin/shared/public — ask if not obvious). **Not** content-producer. content-producer produces documents from the populated graph; it does not ingest. The two are opposite movements through the graph and must never be conflated.
169
- - For ad-hoc graph operations — pruning orphan nodes, deduplicating entities, adding edges, normalising labels, tidying schema drift — delegate to the `database-operator` specialist. Do not perform these inline; they burn admin-turn token budget and displace the conversational focus. **Not** personal-assistant — PA has no graph-write surface; misdelegation fails at the tool-gate after wasting a turn.
168
+ - For document ingestion of any kind — PDFs, text, transcripts, web pages, audio, video, single files, archives — delegate to the `specialists:database-operator` specialist. Include the document path, the document subject (account owner, the business, a third party, etc. — ask if not obvious from context), and the scope (admin/shared/public — ask if not obvious). **Not** `specialists:content-producer`. content-producer produces documents from the populated graph; it does not ingest. The two are opposite movements through the graph and must never be conflated.
169
+ - For ad-hoc graph operations — pruning orphan nodes, deduplicating entities, adding edges, normalising labels, tidying schema drift — delegate to the `specialists:database-operator` specialist. Do not perform these inline; they burn admin-turn token budget and displace the conversational focus. **Not** `specialists:personal-assistant` — PA has no graph-write surface; misdelegation fails at the tool-gate after wasting a turn.
170
170
 
171
171
  ## Proactive Commitment Detection
172
172
 
@@ -255,6 +255,10 @@ The platform also operates an api-wait-ping liveness gate: a heartbeat-driven st
255
255
 
256
256
  In managed context mode, conversation history is provided within `<conversation-history>` tags. Use `session-compact-status` to retrieve older archived context if needed.
257
257
 
258
+ ## Thread resumption after a sub-flow
259
+
260
+ A "sub-flow" is a self-contained run of tool calls — identity repair, LEARNINGS edit, schema audit, attachment unzip — whose subject is not the operator's last stated intent. After the sub-flow returns, the conversation history still holds the operator's earlier request in full. Resume that thread yourself: name what they were asking, then pick it back up. Do not ask the operator to restate, remind, or repeat the intent. Phrases like "What were you originally asking …", "What did you want me to …", or "Remind me what …" delegate the work of holding the thread to the operator and signal that you have treated the prior turn as if it were wiped — when it was not. The exhibit for this rule is the L:2611 turn in stream-4683bd3f, where an OWNS-edge repair returned successfully and the next sentence asked the operator to restate the calendar question they had been pursuing for a thousand prior lines. The platform emits a `[thread-resumption] kind=restate-request` log line when the post-tool assistant text matches one of those phrases, so this regression class is now visible in operations logs even when the operator does not flag it.
261
+
258
262
  ## Tasks
259
263
 
260
264
  Tasks live in the graph — not in files. The tasks plugin manages them.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: content-producer
3
- description: "Visual production — reads from the populated graph to produce visual artifacts: image generation, PDF rendering, and component delivery. Delegate when a task requires generating images or saving rendered pages as PDF. **Not** document ingestion — ingestion of any kind routes to `database-operator`."
3
+ description: "Visual production — reads from the populated graph to produce visual artifacts: image generation, PDF rendering, and component delivery. Delegate when a task requires generating images or saving rendered pages as PDF. **Not** document ingestion — ingestion of any kind routes to `specialists:database-operator`."
4
4
  summary: "Produces visual output from your graph — generates images and renders pages to PDF. For example, when you need a cover image for a brief or want to save a rendered page as PDF."
5
5
  model: claude-sonnet-4-6
6
6
  tools: mcp__memory__memory-search, mcp__replicate__image-generate, mcp__plugin_playwright_playwright__browser_navigate, mcp__plugin_playwright_playwright__browser_snapshot, mcp__plugin_playwright_playwright__browser_take_screenshot, mcp__plugin_playwright_playwright__browser_pdf_save, mcp__admin__render-component, mcp__admin__file-attach
@@ -12,7 +12,7 @@ You produce visual artifacts and PDF output by reading from the already-populate
12
12
 
13
13
  ## Out of scope: ingestion of any kind
14
14
 
15
- content-producer reads from the graph to produce; it does not write external input into the graph. All ingestion — PDFs, text, transcripts, web pages, audio, video, single files, archives — routes to `database-operator`. Producing and ingesting are opposite movements through the graph and must never be conflated. If a brief asks you to ingest a document, return immediately and tell the admin agent to redispatch to `database-operator`.
15
+ content-producer reads from the graph to produce; it does not write external input into the graph. All ingestion — PDFs, text, transcripts, web pages, audio, video, single files, archives — routes to `specialists:database-operator`. Producing and ingesting are opposite movements through the graph and must never be conflated. If a brief asks you to ingest a document, return immediately and tell the admin agent to redispatch to `specialists:database-operator`.
16
16
 
17
17
  ## Prerogatives
18
18
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: real-agency
3
- description: "UK estate agency skills + Loop CRM integration — 10 sub-plugins covering sales, listings, vendor management, buyer management, lead generation, coaching, business operations, onboarding, teaching, and Loop CRM. 3 specialist roles (negotiator, valuer, compliance). 21 skills + 22 MCP tools."
3
+ description: "UK estate agency skills + Loop CRM integration — 10 sub-plugins covering sales, listings, vendor management, buyer management, lead generation, coaching, business operations, onboarding, teaching, and Loop CRM. 3 specialist roles (negotiator, valuer, compliance). 27 skills + 22 MCP tools."
4
4
  plugins:
5
5
  - estate-sales
6
6
  - listings
@@ -30,10 +30,10 @@ Premium plugin bundle for UK estate agency professionals. Purchasing this bundle
30
30
 
31
31
  | Sub-Plugin | Skills | MCP Tools | Focus |
32
32
  |---|---|---|---|
33
- | `estate-sales` | 3 | — | Sales cycle — discovery, closing, progression |
33
+ | `estate-sales` | 5 | — | Sales cycle — discovery, closing, progression, negotiation, sales-negotiation |
34
34
  | `listings` | 3 | — | Pre-listing through marketing — presentations, campaigns, staging |
35
35
  | `vendors` | 2 | — | Active vendor lifecycle — communication, updates |
36
- | `buyers` | 4 | — | Buyer lifecycle — enquiry, viewing feedback, educational guides |
36
+ | `buyers` | 5 | — | Buyer lifecycle — enquiry, viewing feedback, educational guides, buyer management |
37
37
  | `leads` | 2 | — | Pipeline building — nurturing and prospecting |
38
38
  | `estate-coaching` | 4 | — | People development — coaching, training, performance |
39
39
  | `estate-business` | 4 | — | Business owner skills — growth, operations, brand, partnerships |
@@ -33,6 +33,16 @@ Return to the admin agent:
33
33
  **People search (sellers):**
34
34
  - `loop-people-search` (role: seller) finds vendor records — useful for identifying the property owner and their circumstances
35
35
 
36
+ ### Recovering from a `loop-property-search` HTTP 400
37
+
38
+ When `loop-property-search` returns "All teams failed" with `HTTP 400` for every team, the Loop API has rejected the query — most often because `searchTerm` is too long, contains unsupported punctuation, or mixes multiple address lines. Do not retry the same `searchTerm` verbatim; that has been observed to fail identically a second time. Simplify in this order, retrying after each step, and stop as soon as a step returns results:
39
+
40
+ 1. **Drop the postcode.** A full address with postcode is often longer than the API accepts. Try the same query without the postcode segment.
41
+ 2. **Drop punctuation.** Apostrophes (e.g. `Bishop's Stortford`) and other non-alphanumeric characters can break the query. Strip them and retry.
42
+ 3. **Narrow to house name + town.** If steps 1 and 2 still return 400, reduce to the most distinctive elements — a property name (or street number + street) plus the town.
43
+
44
+ If all three rungs return 400 or empty, fall back to `loop-property-detail` with a known property ID, or surface "no comparable evidence found" with the simplified queries you tried, so the agent has a record of what was attempted.
45
+
36
46
  ## Market appraisal preparation
37
47
 
38
48
  When preparing for a valuation, assemble this structure:
@@ -0,0 +1,42 @@
1
+ ---
2
+ name: buyer-management
3
+ description: "Handle buyer enquiries — qualification, viewing booking, feedback collection, offer capture, and ongoing buyer relationship management."
4
+ publicEmbed: false
5
+ ---
6
+
7
+ # Buyer Management
8
+
9
+ Guides the full buyer lifecycle — from initial enquiry through qualification, viewing management, feedback collection, and offer capture.
10
+
11
+ ## When to Activate
12
+
13
+ Someone asks about a property, registers interest, requests a viewing, gives post-viewing feedback, wants to make an offer, or needs rescheduling/cancelling a viewing.
14
+
15
+ ## Reference Table
16
+
17
+ | Task | When | Reference |
18
+ |------|------|-----------|
19
+ | Quick qualification (5 questions) | Early in conversation to gauge seriousness fast | `references/buyer-qualification-questions.md` |
20
+ | Qualification (full) | New buyer enquiry or property interest | `references/buyer-qualification.md` |
21
+ | Viewing booking | Qualified buyer ready for a viewing | `references/viewing-booking.md` |
22
+ | Feedback collection | After a viewing has taken place | `references/feedback-collection.md` |
23
+ | Offer capture | Buyer wants to make an offer | `references/offer-capture.md` |
24
+ | Buyer scripts & dialogue | Qualifying, encouraging offers, overcoming hesitation | `references/buyer-scripts.md` |
25
+ | Working with buyers (Serhant) | Shoppers vs buyers, elimination process, getting off the fence | `references/buyer-working-scripts.md` |
26
+ | Viewing management | Rescheduling, cancellations, reminders, schedule summaries | `references/viewing-management.md` |
27
+
28
+ ## Key Rules
29
+
30
+ - Always qualify before booking a viewing — understand their position first
31
+ - One question at a time — don't overwhelm with a qualification form
32
+ - Never disclose vendor circumstances, other offers, or pricing flexibility
33
+ - Never negotiate — gather information and pass to the agent
34
+ - Update the buyer's profile in memory after every interaction
35
+ - Frame everything around helping them, not extracting information
36
+ - Distinguish shoppers from buyers — qualify early, invest time wisely
37
+ - "Buying a home is a process of elimination, not selection" — guide them through narrowing down
38
+ - Post-viewing follow-up within 2 hours — never leave a viewing without a next step
39
+ - An offer is "just a conversation starter" — help hesitant buyers understand nothing is final until exchange
40
+ - Never double-book a property or team member at the same time
41
+ - Access instructions (lockbox codes, keys) are confidential — only share with the conducting agent
42
+ - Two no-shows = flag to agent before booking further viewings
@@ -0,0 +1,16 @@
1
+ # Buyer qualification — 5 non‑negotiable questions (Tom Panos)
2
+
3
+ Use these to quickly learn whether a buyer is serious and where their friction is.
4
+
5
+ 1) **How long have you been looking?**
6
+ 2) **Have you made any offers on anything?**
7
+ 3) **What is the best home you've seen so far?**
8
+ 4) **Why didn't you buy that one?**
9
+ 5) **If I had a home that was suitable, will you be looking at making an offer?**
10
+
11
+ ## Notes for Max
12
+ - Ask in a friendly, curious tone.
13
+ - Capture the answers verbatim.
14
+ - If #5 is not a clear "yes", they're browsing. Keep warm, don't over-invest.
15
+
16
+ Source: *Tom Panos — Dialogue to Get More Listings* (Estate Agency Mastermind summary)
@@ -0,0 +1,59 @@
1
+ # Buyer Qualification
2
+
3
+ ## Purpose
4
+
5
+ Understand the buyer's situation so the agent can prioritise and serve them effectively. Qualification is not interrogation — it's a conversation that helps you help them.
6
+
7
+ ## The MAN Framework
8
+
9
+ Gather these three dimensions naturally through conversation:
10
+
11
+ ### Motivation
12
+ - Why are they looking to move?
13
+ - What's their timeline — urgent, browsing, planning ahead?
14
+ - What drew them to this particular property or area?
15
+ - Are they relocating? Upsizing? Downsizing? First-time buyers?
16
+
17
+ ### Ability
18
+ - Do they have a property to sell? If so, what's its status?
19
+ - Not yet on market → early stage, may need longer
20
+ - On market → check how long, any interest
21
+ - Sold STC → stronger position
22
+ - No property to sell → chain-free (cash or FTB)
23
+ - Are they buying with cash or mortgage?
24
+ - If mortgage, do they have an Agreement in Principle (AIP)?
25
+ - If no AIP, suggest speaking with a mortgage adviser before viewings
26
+
27
+ ### Need
28
+ - What type of property are they looking for? (beds, type, garden, parking)
29
+ - Must-haves vs nice-to-haves
30
+ - Any dealbreakers? (location, condition, budget ceiling)
31
+ - How far along are they in their search — just started or seen several?
32
+
33
+ ## Conversational Flow
34
+
35
+ Don't ask all of this in one message. Weave it naturally:
36
+
37
+ 1. **Start warm** — thank them for their enquiry, show enthusiasm about the property they've asked about
38
+ 2. **Open with motivation** — "What's prompted your move?" or "Are you local to the area or looking to relocate?"
39
+ 3. **Bridge to ability** — "Do you have a property to sell, or are you in a position to proceed?"
40
+ 4. **Understand need** — "What's on your wish list for your next home?"
41
+
42
+ ## After Qualification
43
+
44
+ - **Proceedable** (chain-free, mortgage agreed, or sold STC) → book viewing promptly
45
+ - **Needs steps** (no AIP, property not on market) → suggest next steps gently, keep them warm
46
+ - **Browsing/long-term** → register their requirements, offer to send matching properties
47
+
48
+ ## Memory
49
+
50
+ Save qualification status to `memory/users/{phone}/profile.md`:
51
+ - Position (FTB, selling, sold STC, cash, renting)
52
+ - Mortgage status (AIP yes/no, cash)
53
+ - Requirements (beds, type, area, budget range)
54
+ - Timeline (urgent, 3-6 months, browsing)
55
+ - Properties of interest
56
+
57
+ ## Tone
58
+
59
+ Curious and helpful, never clinical. You're having a chat, not filling in a form. If someone volunteers information, don't re-ask it. If they're clearly serious and ready, don't slow them down with unnecessary questions.
@@ -0,0 +1,63 @@
1
+ # Buyer Scripts & Qualification Dialogue
2
+ *Sources: Tom Panos (Real Estate Gym), Team LANC (Matt Lancashire), Serhant Agent Training Guide*
3
+
4
+ ## Qualifying Questions (Natural Conversation)
5
+
6
+ Use these naturally — not as a checklist. Weave them into conversation.
7
+
8
+ **Understanding motivation:**
9
+ - "When buying a home, what's most important for you?"
10
+ - "What's the best home you've seen so far?"
11
+ - "What prevented you from making an offer on that one?"
12
+ - "If there were 3 things you absolutely wouldn't compromise on, what would they be?"
13
+
14
+ **Getting to an offer:**
15
+ - "At what price on a contract represents great value for you?"
16
+ - "If you could move into the right home next month, would that work for your timing?"
17
+
18
+ **When a buyer is waiting for the market to bottom:**
19
+ > "The only way to know you've bought at the bottom of the market is when the market goes up. But by then it's too late. Because the only way to know the market was at the bottom is when prices have already gone up. Do you want to make a decision based on the market, or based on your life?"
20
+
21
+ ## Post-Viewing Follow-Up Process
22
+
23
+ **Within 2 hours of viewing:**
24
+ 1. Send warm check-in message (reference specific property, use first name)
25
+ 2. Capture overall impression, interest level, positives, concerns
26
+ 3. If interested — offer second viewing or next steps
27
+ 4. If not interested — ask what they ARE looking for (refine criteria)
28
+
29
+ **10-Day Follow-Up (if no response or "thinking about it"):**
30
+ - Brief, value-led message — share new comparable that just listed, or market insight
31
+ - Never "just checking in" — always lead with something useful
32
+
33
+ **Hot Buyer Management:**
34
+ - Maintain a hot buyer list with key criteria
35
+ - When new properties come to market, check against hot buyer criteria within 24 hours
36
+ - Call (don't just text) for strong matches — "I've just seen something that ticks every box you mentioned"
37
+
38
+ ## Encouraging Offers
39
+
40
+ **When a buyer is hesitant:**
41
+ - "What would need to change for you to feel comfortable making an offer?"
42
+ - "Is it the property itself, or the timing?"
43
+ - "If this property sells to someone else this weekend, would you regret not having put an offer forward?"
44
+
45
+ **When a buyer lowballs:**
46
+ - Use comparable evidence: "Let me show you what similar properties have actually sold for recently"
47
+ - Frame as collaboration: "Let's find a number that the seller will take seriously, so we don't lose the opportunity to negotiate"
48
+
49
+ ## Getting Buyers Off the Fence (Serhant)
50
+
51
+ - Show them what they think they want (validates their criteria)
52
+ - Show them the WOW listing (exceeds expectations, creates excitement)
53
+ - Show them the consolation prize (makes the WOW listing feel essential)
54
+ - This is about understanding their emotional journey, not manipulation
55
+
56
+ ## The Flip: Turning Negatives Into Positives
57
+
58
+ When a buyer raises an objection about a property:
59
+ 1. **List the common objections** you expect (small garden, busy road, dated kitchen)
60
+ 2. **Find the silver lining** ("A contained garden is easy to maintain and beautify — you'll spend time enjoying it, not mowing")
61
+ 3. **Offer a solution** (share photos of beautiful small gardens, connect with a landscaper)
62
+
63
+ Always acknowledge the concern genuinely before flipping it. Never dismiss a buyer's objection.
@@ -0,0 +1,54 @@
1
+ # Working With Buyers — Scripts & Scenarios
2
+ *Adapted from Serhant Team Agent Training Guide*
3
+
4
+ ## Phase 1: Selling Is ASKING
5
+
6
+ ### Qualify First — Shoppers vs Buyers
7
+ You don't work with shoppers, you work with BUYERS. Determine if they're real:
8
+
9
+ **Qualifying Questions:**
10
+ 1. "Where do you work?" (financial picture)
11
+ 2. "Do you currently own or rent?" (experience level + chain status)
12
+ 3. "When are you looking to move by? Is there a specific reason?" (urgency + motivation)
13
+ 4. "How long have you been looking? Seen anything you liked?" (stage in journey)
14
+ 5. "Have you already been pre-approved / spoken to a mortgage adviser?" (readiness)
15
+
16
+ ### Never Meet a Buyer for the First Time at a Listing
17
+ Meet them first — in the office, for coffee, on a call. Understand their needs before showing properties.
18
+
19
+ ### Set Expectations
20
+ List the steps to successfully purchasing a home. Buyers who understand the process make better decisions and don't panic at each stage.
21
+
22
+ ## Phase 2: Selling Is GUIDING
23
+
24
+ ### Elimination, Not Selection
25
+ "Buying a home isn't a process of selection — it's a process of elimination. We'll narrow down what works and what doesn't until we find the right one."
26
+
27
+ ### Ask for Feedback After Every Viewing
28
+ Don't assume silence means disinterest. Start the conversation, get them in the game.
29
+
30
+ ### Make Offers — Get Off the Fence
31
+ Buyers can look forever without a push. Address the hesitation:
32
+
33
+ "It's never a 'bad' time to buy. As long as you're comfortable with the purchase and don't overstretch yourself, you'll be in good shape."
34
+
35
+ "I've never had a client who, at completion, said 'I got exactly what I wanted under budget!' — there's always a stretch."
36
+
37
+ ### Encouraging Offers
38
+ "An offer is JUST a conversation starter. Nothing is final until contracts are exchanged."
39
+
40
+ "What do you think the property is worth? What would you pay? ...[X]? Great — why don't we just see how the vendor responds?"
41
+
42
+ ### Make Them Fall in Love with the PROPERTY, Not the Discount
43
+ Focus on lifestyle, not savings. "Can you see yourself here?" beats "You're getting £10k off."
44
+
45
+ ## Getting Buyers Off the Fence
46
+
47
+ **Longer-Term Outlook:**
48
+ "Will you be there for 5-10 years? If so, waiting for the 'perfect' property is like not taking a holiday because it might rain."
49
+
50
+ **The Historical Perspective:**
51
+ "Every buyer thinks it's SO expensive at the time. Then they look back and think they got the best deal ever."
52
+
53
+ **The iPhone Analogy (for price objections):**
54
+ If a buyer won't pay because the vendor only paid £X before — "How much did you pay for your iPhone? It costs £84 to make."