@rubytech/create-realagent 1.0.847 → 1.0.849

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 (111) 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/cloudflare/PLUGIN.md +1 -1
  8. package/payload/platform/plugins/cloudflare/scripts/setup-tunnel.sh +25 -7
  9. package/payload/platform/plugins/cloudflare/skills/setup-tunnel/SKILL.md +1 -1
  10. package/payload/platform/plugins/docs/references/deployment.md +8 -0
  11. package/payload/platform/plugins/docs/references/plugins-guide.md +4 -2
  12. package/payload/platform/plugins/docs/references/troubleshooting.md +33 -0
  13. package/payload/platform/scripts/test-laptop-vnc-boot.sh +81 -0
  14. package/payload/platform/scripts/vnc.sh +42 -2
  15. package/payload/platform/templates/agents/admin/AGENTS.md +6 -4
  16. package/payload/platform/templates/agents/admin/IDENTITY.md +2 -2
  17. package/payload/platform/templates/specialists/agents/content-producer.md +2 -2
  18. package/payload/premium-plugins/real-agency/BUNDLE.md +3 -3
  19. package/payload/premium-plugins/real-agency/agents/valuer.md +10 -0
  20. package/payload/premium-plugins/real-agency/plugins/buyers/skills/buyer-management/SKILL.md +42 -0
  21. package/payload/premium-plugins/real-agency/plugins/buyers/skills/buyer-management/references/buyer-qualification-questions.md +16 -0
  22. package/payload/premium-plugins/real-agency/plugins/buyers/skills/buyer-management/references/buyer-qualification.md +59 -0
  23. package/payload/premium-plugins/real-agency/plugins/buyers/skills/buyer-management/references/buyer-scripts.md +63 -0
  24. package/payload/premium-plugins/real-agency/plugins/buyers/skills/buyer-management/references/buyer-working-scripts.md +54 -0
  25. package/payload/premium-plugins/real-agency/plugins/buyers/skills/buyer-management/references/feedback-collection.md +42 -0
  26. package/payload/premium-plugins/real-agency/plugins/buyers/skills/buyer-management/references/offer-capture.md +38 -0
  27. package/payload/premium-plugins/real-agency/plugins/buyers/skills/buyer-management/references/viewing-booking.md +32 -0
  28. package/payload/premium-plugins/real-agency/plugins/buyers/skills/buyer-management/references/viewing-management.md +52 -0
  29. package/payload/premium-plugins/real-agency/plugins/estate-sales/skills/negotiation/SKILL.md +35 -0
  30. package/payload/premium-plugins/real-agency/plugins/estate-sales/skills/negotiation/references/deal-saving.md +47 -0
  31. package/payload/premium-plugins/real-agency/plugins/estate-sales/skills/negotiation/references/negotiation-deep-guide.md +64 -0
  32. package/payload/premium-plugins/real-agency/plugins/estate-sales/skills/negotiation/references/negotiation-prep-principles.md +29 -0
  33. package/payload/premium-plugins/real-agency/plugins/estate-sales/skills/negotiation/references/negotiation-techniques.md +42 -0
  34. package/payload/premium-plugins/real-agency/plugins/estate-sales/skills/negotiation/references/offer-presentation.md +43 -0
  35. package/payload/premium-plugins/real-agency/plugins/estate-sales/skills/sales-negotiation/SKILL.md +29 -0
  36. package/payload/premium-plugins/real-agency/plugins/estate-sales/skills/sales-negotiation/references/chris-voss-negotiation.md +70 -0
  37. package/payload/premium-plugins/real-agency/plugins/estate-sales/skills/sales-negotiation/references/phil-jones-price-words.md +40 -0
  38. package/payload/premium-plugins/real-agency/plugins/estate-sales/skills/sales-negotiation/references/serhant-negotiation-plus.md +55 -0
  39. package/payload/premium-plugins/real-agency/plugins/estate-sales/skills/sales-negotiation/references/tom-panos-commission-pricing.md +57 -0
  40. package/payload/premium-plugins/real-agency/plugins/estate-sales/skills/sales-negotiation/references/tony-morris-questioning.md +54 -0
  41. package/payload/premium-plugins/real-agency/plugins/loop/mcp/dist/lib/loop-api.d.ts +6 -4
  42. package/payload/premium-plugins/real-agency/plugins/loop/mcp/dist/lib/loop-api.d.ts.map +1 -1
  43. package/payload/premium-plugins/real-agency/plugins/loop/mcp/dist/lib/loop-api.js +82 -10
  44. package/payload/premium-plugins/real-agency/plugins/loop/mcp/dist/lib/loop-api.js.map +1 -1
  45. package/payload/premium-plugins/real-agency/plugins/loop/mcp/src/lib/loop-api.ts +111 -15
  46. package/payload/server/chunk-GOO2J3X7.js +10561 -0
  47. package/payload/server/chunk-LCAFHNZR.js +10420 -0
  48. package/payload/server/maxy-edge.js +1 -1
  49. package/payload/server/public/assets/{admin-DFUet1XM.js → admin-Dyl8uNxX.js} +1 -1
  50. package/payload/server/public/assets/{architectureDiagram-Q4EWVU46-Bs5MjIKf.js → architectureDiagram-Q4EWVU46-BePoi8XC.js} +1 -1
  51. package/payload/server/public/assets/{blockDiagram-DXYQGD6D-BVSXiX4T.js → blockDiagram-DXYQGD6D-BkiwLTtq.js} +1 -1
  52. package/payload/server/public/assets/{c4Diagram-AHTNJAMY-DBqsWCjl.js → c4Diagram-AHTNJAMY-bpjPj2Ln.js} +1 -1
  53. package/payload/server/public/assets/channel-D3U0_a1j.js +1 -0
  54. package/payload/server/public/assets/{chunk-336JU56O-COUTB2TN.js → chunk-336JU56O-BpATJiGl.js} +2 -2
  55. package/payload/server/public/assets/{chunk-426QAEUC-zKsTsXw6.js → chunk-426QAEUC-Wz6Bpsil.js} +1 -1
  56. package/payload/server/public/assets/{chunk-4TB4RGXK-CI9i2J5g.js → chunk-4TB4RGXK-CLXL19Wd.js} +1 -1
  57. package/payload/server/public/assets/{chunk-5FUZZQ4R-DfchzZ2Y.js → chunk-5FUZZQ4R-BoTfWHuW.js} +1 -1
  58. package/payload/server/public/assets/{chunk-5PVQY5BW-_iMyxz0C.js → chunk-5PVQY5BW-RhIfPCRB.js} +1 -1
  59. package/payload/server/public/assets/{chunk-EDXVE4YY-Ddtw_ZHk.js → chunk-EDXVE4YY-utELKGQK.js} +1 -1
  60. package/payload/server/public/assets/{chunk-ENJZ2VHE-BrGMkslM.js → chunk-ENJZ2VHE-CNHjq5xK.js} +1 -1
  61. package/payload/server/public/assets/{chunk-ICPOFSXX-DHInTpuR.js → chunk-ICPOFSXX-Di63NBur.js} +1 -1
  62. package/payload/server/public/assets/{chunk-OYMX7WX6-mOQ4KZ9j.js → chunk-OYMX7WX6-BSPzqyxs.js} +1 -1
  63. package/payload/server/public/assets/{chunk-U2HBQHQK-D5vGkUe9.js → chunk-U2HBQHQK-BZnA7c4T.js} +1 -1
  64. package/payload/server/public/assets/{chunk-X2U36JSP-CnNxZbqc.js → chunk-X2U36JSP-DpQ2OA_c.js} +1 -1
  65. package/payload/server/public/assets/{chunk-YZCP3GAM-Cb7OSc_r.js → chunk-YZCP3GAM-BAkNXu0G.js} +1 -1
  66. package/payload/server/public/assets/{chunk-ZZ45TVLE-BipxpzL8.js → chunk-ZZ45TVLE-DBSm41oP.js} +1 -1
  67. package/payload/server/public/assets/classDiagram-6PBFFD2Q-6EGGLDD_.js +1 -0
  68. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-DfAV4tgE.js +1 -0
  69. package/payload/server/public/assets/clone-BoV8noAi.js +1 -0
  70. package/payload/server/public/assets/{dagre-KV5264BT-B91sXKT2.js → dagre-KV5264BT-BkvWofSp.js} +1 -1
  71. package/payload/server/public/assets/{dagre-lObrgXUJ.js → dagre-nvPNAunb.js} +1 -1
  72. package/payload/server/public/assets/{diagram-5BDNPKRD-DB2Kcx9r.js → diagram-5BDNPKRD-CMEgyt4E.js} +1 -1
  73. package/payload/server/public/assets/{diagram-G4DWMVQ6-Cq1J05SW.js → diagram-G4DWMVQ6-ChorrAF0.js} +1 -1
  74. package/payload/server/public/assets/{diagram-MMDJMWI5-CwqXxUXd.js → diagram-MMDJMWI5-D_iD27po.js} +1 -1
  75. package/payload/server/public/assets/{diagram-TYMM5635-Nmk38u6a.js → diagram-TYMM5635-8qXI1ioG.js} +1 -1
  76. package/payload/server/public/assets/{erDiagram-SMLLAGMA-D2EfAdSD.js → erDiagram-SMLLAGMA-BFjtKDSB.js} +1 -1
  77. package/payload/server/public/assets/{flowDiagram-DWJPFMVM-CS98o6Jz.js → flowDiagram-DWJPFMVM-Bpd7IL9l.js} +1 -1
  78. package/payload/server/public/assets/{ganttDiagram-T4ZO3ILL-rWm6xQ8t.js → ganttDiagram-T4ZO3ILL-CwOozU85.js} +1 -1
  79. package/payload/server/public/assets/{gitGraphDiagram-UUTBAWPF-BuwECvwx.js → gitGraphDiagram-UUTBAWPF-CcPILiC9.js} +1 -1
  80. package/payload/server/public/assets/{graphlib-BXEED8qM.js → graphlib-B_mcXEVr.js} +1 -1
  81. package/payload/server/public/assets/{infoDiagram-42DDH7IO-CEmJMuVh.js → infoDiagram-42DDH7IO-T2sn--WJ.js} +1 -1
  82. package/payload/server/public/assets/{ishikawaDiagram-UXIWVN3A-CAQMMx-Y.js → ishikawaDiagram-UXIWVN3A-DOP9-Q8H.js} +1 -1
  83. package/payload/server/public/assets/{journeyDiagram-VCZTEJTY-toHrBGCq.js → journeyDiagram-VCZTEJTY-DGATg0WC.js} +1 -1
  84. package/payload/server/public/assets/{kanban-definition-6JOO6SKY-DwXLkenV.js → kanban-definition-6JOO6SKY-C5PigmKg.js} +1 -1
  85. package/payload/server/public/assets/{line-BkM2KuUb.js → line-DlKKhwkO.js} +1 -1
  86. package/payload/server/public/assets/{mermaid-parser.core-CsaDWYZC.js → mermaid-parser.core-C8xGCa9p.js} +1 -1
  87. package/payload/server/public/assets/{mermaid.core-CvICILSR.js → mermaid.core-CCUSwZB_.js} +3 -3
  88. package/payload/server/public/assets/{mindmap-definition-QFDTVHPH-DQyCWpKS.js → mindmap-definition-QFDTVHPH-75k-IVhC.js} +1 -1
  89. package/payload/server/public/assets/{pieDiagram-DEJITSTG-CVRIcK6b.js → pieDiagram-DEJITSTG-DN5RsDwZ.js} +1 -1
  90. package/payload/server/public/assets/preload-helper-qlgyTAkD.js +1 -0
  91. package/payload/server/public/assets/{public-CR_CX3K5.js → public-B_PNZUph.js} +1 -1
  92. package/payload/server/public/assets/{quadrantDiagram-34T5L4WZ-CnfXm2xw.js → quadrantDiagram-34T5L4WZ-Sd9x6pNe.js} +1 -1
  93. package/payload/server/public/assets/{requirementDiagram-MS252O5E-BntW6fnu.js → requirementDiagram-MS252O5E-BDgifYzj.js} +1 -1
  94. package/payload/server/public/assets/{sankeyDiagram-XADWPNL6-Bt6AfgXn.js → sankeyDiagram-XADWPNL6-BX9VULNJ.js} +1 -1
  95. package/payload/server/public/assets/{sequenceDiagram-FGHM5R23-D6s0kP6H.js → sequenceDiagram-FGHM5R23-z3vMxhgE.js} +1 -1
  96. package/payload/server/public/assets/{stateDiagram-FHFEXIEX-B9y9cOff.js → stateDiagram-FHFEXIEX-DlP0hBxF.js} +1 -1
  97. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-DSddQStC.js +1 -0
  98. package/payload/server/public/assets/{timeline-definition-GMOUNBTQ-DIFjQGfl.js → timeline-definition-GMOUNBTQ-DwQbhKCo.js} +1 -1
  99. package/payload/server/public/assets/{useVoiceRecorder-DWRtIHOw.js → useVoiceRecorder-fD0IWzJj.js} +3 -3
  100. package/payload/server/public/assets/{vennDiagram-DHZGUBPP-YRVHIBU9.js → vennDiagram-DHZGUBPP-WTqmZWWa.js} +1 -1
  101. package/payload/server/public/assets/{wardleyDiagram-NUSXRM2D-B20PPeAr.js → wardleyDiagram-NUSXRM2D-BUY50x5T.js} +1 -1
  102. package/payload/server/public/assets/{xychartDiagram-5P7HB3ND-BztKw58Q.js → xychartDiagram-5P7HB3ND-Btdq-fDj.js} +1 -1
  103. package/payload/server/public/index.html +3 -3
  104. package/payload/server/public/public.html +3 -3
  105. package/payload/server/server.js +4 -1
  106. package/payload/server/public/assets/channel-lEc18pSi.js +0 -1
  107. package/payload/server/public/assets/classDiagram-6PBFFD2Q-rkW6IED-.js +0 -1
  108. package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-CRQJXpMG.js +0 -1
  109. package/payload/server/public/assets/clone-icRAjexu.js +0 -1
  110. package/payload/server/public/assets/preload-helper-bPV_ZjF3.js +0 -1
  111. package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-DH4gbGCS.js +0 -1
@@ -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).
@@ -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
 
@@ -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."
@@ -0,0 +1,42 @@
1
+ # Feedback Collection
2
+
3
+ ## Purpose
4
+
5
+ Capture honest post-viewing feedback to relay to the vendor and inform the agent's strategy. Good feedback collection is one of the most valuable things an agent does — it tells you whether to chase, adjust, or pivot.
6
+
7
+ ## Timing
8
+
9
+ Reach out within 24 hours of the viewing. Sooner is better — impressions fade.
10
+
11
+ ## Questions
12
+
13
+ Ask conversationally, not as a checklist:
14
+
15
+ 1. **Overall impression** — "How did you find the viewing? What were your first impressions?"
16
+ 2. **Positives** — "What stood out to you? What did you like most?"
17
+ 3. **Concerns** — "Were there any reservations or things that gave you pause?"
18
+ 4. **Comparison** — "How does it compare to others you've seen?" (if applicable)
19
+ 5. **Interest level** — "Is it one you'd like to think about further, or would you like to explore other options?"
20
+ 6. **Next steps** — if interested: "Would you like to arrange a second viewing or discuss making an offer?" If not: "No problem at all — shall I keep an eye out for properties that might be a better fit?"
21
+
22
+ ## Reading Between the Lines
23
+
24
+ - **"It was nice but..."** usually means no. Gently probe the "but"
25
+ - **"We need to think about it"** — ask what specifically they're weighing up
26
+ - **"We loved it"** — ask what specifically they loved (the agent uses this when presenting offers)
27
+ - **Silence / no response** — follow up once more after 48 hours, then note as unresponsive
28
+
29
+ ## Recording Feedback
30
+
31
+ Save to `memory/users/{phone}/viewings/YYYY-MM-DD-address-slug.md`:
32
+ - Date of viewing
33
+ - Property address
34
+ - Overall reaction (positive / mixed / negative)
35
+ - Key positives mentioned
36
+ - Concerns raised
37
+ - Interest level (keen / considering / not interested)
38
+ - Next action (second viewing / offer / no further action)
39
+
40
+ ## Escalation
41
+
42
+ If a buyer expresses strong interest or wants to discuss an offer, transition to offer capture immediately. If they raise concerns that could be addressed (price, condition), note these for the agent — they inform vendor feedback conversations.
@@ -0,0 +1,38 @@
1
+ # Offer Capture
2
+
3
+ ## Purpose
4
+
5
+ Gather all the information the agent needs to present an offer to the vendor professionally. You capture — the agent negotiates.
6
+
7
+ ## Information to Gather
8
+
9
+ 1. **The offer amount** — "What figure would you like to offer?"
10
+ 2. **How they arrived at it** — "How did you come to that figure?" (This helps the agent understand their thinking and position)
11
+ 3. **Their buying position:**
12
+ - Cash or mortgage?
13
+ - If mortgage: AIP confirmed? Lender? Deposit amount?
14
+ - Property to sell? Status? (Under offer, exchanged, no property)
15
+ - Chain length?
16
+ - Solicitor instructed?
17
+ 4. **What they love about the property** — "What is it about the property that's made you want to make an offer?" (the agent uses this when presenting to the vendor — emotional connection matters)
18
+ 5. **Timeline** — when would they ideally like to complete?
19
+ 6. **Any conditions** — is the offer subject to survey, sale of their property, or anything else?
20
+
21
+ ## Critical Rules
22
+
23
+ - **Never counter-offer** — you do not negotiate on behalf of the vendor
24
+ - **Never disclose other offers** — not the number, not the amount, not whether any exist
25
+ - **Never hint at what might be acceptable** — no "I think the vendor would want more" or "that's quite low"
26
+ - **Never disclose the vendor's circumstances** — their timeline, motivation, or financial position is confidential
27
+ - **Stay neutral and professional** — "I'll make sure the agent presents this to the seller and they'll be in touch to discuss"
28
+
29
+ ## After Capture
30
+
31
+ 1. Save the offer to `memory/users/{phone}/offers/YYYY-MM-DD-address-slug.md`
32
+ 2. Include all gathered details
33
+ 3. **Escalate to the agent immediately** — offers are time-sensitive
34
+ 4. Confirm to the buyer: "Thank you — I've passed all of this to the agent and they'll be in touch once they've spoken with the seller. Is there anything else you'd like me to include?"
35
+
36
+ ## Multiple Offers
37
+
38
+ If another buyer also wants to offer on the same property, capture their details separately. Never mention the other offer. The agent manages the best-and-final process if needed.
@@ -0,0 +1,32 @@
1
+ # Viewing Booking
2
+
3
+ ## Purpose
4
+
5
+ Convert a qualified buyer into a confirmed viewing. Make it easy, organised, and professional.
6
+
7
+ ## Booking Flow
8
+
9
+ 1. **Confirm the property** — make sure you're both talking about the same one
10
+ 2. **Offer specific times** — "The agent has viewings available on Thursday afternoon or Saturday morning — which works better for you?" Two options, not open-ended
11
+ 3. **Confirm attendees** — will it be just them, or partner/family too? This helps the agent prepare
12
+ 4. **Set expectations** — the agent conducts all viewings personally. They'll walk them through the property and answer any questions on the day
13
+ 5. **Confirm details** — repeat the time, date, property address, and their name
14
+
15
+ ## Important
16
+
17
+ - Viewings are arranged on set days where possible to be respectful of the seller's time
18
+ - If the buyer's preferred time clashes, offer the next available slot — don't leave it hanging
19
+ - If the property has high interest, mention this factually ("there's been good interest this week") but never fabricate urgency
20
+ - Always confirm the buyer has been qualified before booking — if not, qualify first
21
+
22
+ ## After Booking
23
+
24
+ - Save the viewing to `memory/users/{phone}/viewings/YYYY-MM-DD-address-slug.md`
25
+ - Include: date, time, property address, buyer name, their position, any notes
26
+ - If shared calendar is available, create the event there too
27
+
28
+ ## Cancellations and Rescheduling
29
+
30
+ - Be understanding — things come up
31
+ - Offer an alternative promptly
32
+ - If a buyer cancels twice without rescheduling, note it in their profile — they may be going cold