@elitedcs/ghl-mcp 3.83.9 → 3.84.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/guide/guide.html CHANGED
@@ -4,7 +4,7 @@
4
4
  <meta charset="utf-8">
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1">
6
6
  <title>GHL Command — User Guide</title>
7
- <!-- guides-hash: b3c8d8eb3b079a5b -->
7
+ <!-- guides-hash: 6b9469902fc22be2 -->
8
8
  <style>
9
9
  /* Deliberately light in every environment, including a dark-mode OS. This is a
10
10
  reference document people read at length, print, and save to PDF, and a page
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elitedcs/ghl-mcp",
3
- "version": "3.83.9",
3
+ "version": "3.84.1",
4
4
  "mcpName": "io.github.drjerryrelth/ghl-command",
5
5
  "description": "GoHighLevel MCP Server for Claude. 250 tools — full CRM, automation, marketing control, account-wide workflow audit, live funnel-capture verification, and the only programmatic GHL workflow builder, now multi-tenant across client accounts.",
6
6
  "main": "dist/index.js",
@@ -1,6 +1,6 @@
1
1
  # Preset: Clinic / Practice
2
2
 
3
- **File:** `clinic.preset.json` · **id:** `clinic` · **version:** 2.0.0 · **default:** no
3
+ **File:** `clinic.preset.json` · **id:** `clinic` · **version:** 2.1.0 · **default:** no
4
4
  **Source:** Generalized from proven clinic builds with the intake industry pack "clinic" (insurance_or_cash, new_patient_offer, compliance_notes); v2 depth per the owner review of 2026-08-26.
5
5
 
6
6
  ## When it is selected
@@ -28,6 +28,8 @@ Routes from the "Clinic / practice" business type and the `clinic` / `practice`
28
28
  | Lead Nurture (30 days) | contact_tag (tag.nurture_start) | 28 | 11 | 31 days | yes |
29
29
  | Replied - Stop & Route | customer_reply | 9 | 0 | instant | no |
30
30
  | Win-back (30 days) | contact_tag (tag.winback_start) | 13 | 5 | 31 days | yes |
31
+ | Care plan Follow-up | contact_tag (tag.quote_sent) | 14 | 4 + a call task | 10 days | yes |
32
+ | Review Requests | contact_tag (tag.review_ask) | 8 | 3 | 7 days | yes |
31
33
  | Visit Booked - Confirm & Move | appointment (confirmed) | 8 | 2 | instant | no |
32
34
  | Visit Reminders | appointment (confirmed) | 5 | 3 | instant | no |
33
35
  | No-Show Rescue | appointment (noshow) | 14 | 4 | 7 days | yes |
@@ -39,6 +41,13 @@ Routes from the "Clinic / practice" business type and the `clinic` / `practice`
39
41
  - **Missed Call Text-Back**: `call_status` trigger scoped to no-answer / busy / voicemail, inbound. Text within seconds, tag, alert, call-back task, one more text an hour later.
40
42
  - **New Patient Visit → Confirm & Move, Reminders, No-Show Rescue**: booking stops every sequence and moves (or creates) the opportunity; reminders at 24 h and 2 h; a no-show gets a same-day call task, text and email, two more touches, then hands off to Win-back and moves the card back to Contacted.
41
43
 
44
+ ### Added in v2.1.0 (2026-09-06): the two features the Assessment prices
45
+
46
+ - **Care plan Follow-up** (feature `quote_followup`): starts from the `quote-sent` tag the operator applies when a care plan goes out (by hand, from a quoting tool, or from a stage). Text on day 1, email on day 3, text on day 6 plus a call task, last email on day 10; any reply stops it; ends by tagging `quote-no-reply`. Hand-off `handoff.quote_tag` explains the tag.
47
+ - **Review Requests** (feature `review_requests`): starts from the `review-ask` tag applied when the work is done. Text two hours later with the Google link from the `review_link` custom value, email on day 3, last text on day 7; any reply stops it (a complaint reaches a person, not a second nudge); ends by tagging `review-asked`. Hand-off `handoff.review_link` collects the link.
48
+
49
+ Every workflow now belongs to a feature (`src/intake-to-build/features.ts`) so a client's Blueprint builds what they bought; the reply router is the foundation every messaging feature stands on.
50
+
42
51
  ### Why sequences hand off with a tag, not add_to_workflow
43
52
  Every hand-off is `add_contact_tag` + a `contact_tag` trigger. Both halves are live-proven shapes captured from working GHL workflows (`templates/action-schemas.json`). `add_to_workflow` has no captured native shape there and has not been proven at runtime, so a preset may not use it. Each sequence removes its own trigger tag as its first action so a later hand-off can start it again.
44
53
 
@@ -58,3 +67,7 @@ The templates say "your visit", "what brought you in", "what you came in for". T
58
67
 
59
68
  ## Copy notes
60
69
  Compliance first: no message names a condition, diagnosis, treatment or medication, and the intake pack's compliance_notes are honored on rewrite. The through-line is "the first visit is mostly listening": what happens minute by minute, how insurance and cash pricing work in plain words, no surprise bills, and why the easy-to-fix stage is the cheap stage. Texts ask one-word questions (new / ongoing / check-up; mornings / afternoons; YES / later).
70
+
71
+ ## v2.1.0 (2026-09-15)
72
+
73
+ Two workflows the Assessment prices and no preset built: **Quote Follow-up** (starts from the `quote-sent` tag; text next day, email day 3, last text day 5, then a call task for the owner and the `quote-stale` tag) and **Review Request** (starts when a booked visit is marked showed; text at two hours with the `review_link` custom value, email three days later). Held DRAFT behind the A2P and phone-number handoffs like every other text-bearing workflow (Quote Follow-up also behind staff, for its call task); their emails wait on the sending-domain handoff.
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "presetId": "clinic",
3
- "presetVersion": "2.0.0",
3
+ "presetVersion": "2.1.0",
4
4
  "schemaVersion": "0.1",
5
5
  "title": "Clinic / Practice",
6
- "description": "A clinic / practice new-patient system at v2 depth (chiropractic, physical therapy, dental, functional medicine, primary care and similar). Patient pipeline, lead-source / interest / insurance fields, source + lifecycle + interest tags, a round-robin New Patient Visit calendar, an A2P-compliant new-patient form, 15 email + 17 SMS send-ready templates written to be compliance-safe (no condition, diagnosis or treatment is ever named in a message), and 8 workflows: Speed to Lead (15 actions, 5 touches in 24 h, then a hand-off), Missed Call Text-Back, Lead Nurture (31 days, 11 touches), Replied - Stop & Route, Win-back (31 days, 5 touches), Visit Booked - Confirm & Move, Visit Reminders, No-Show Rescue.",
6
+ "description": "A clinic / practice new-patient system at v2 depth (chiropractic, physical therapy, dental, functional medicine, primary care and similar). Patient pipeline, lead-source / interest / insurance fields, source + lifecycle + interest tags, a round-robin New Patient Visit calendar, an A2P-compliant new-patient form, 15 email + 17 SMS send-ready templates written to be compliance-safe (no condition, diagnosis or treatment is ever named in a message), and 10 workflows: Speed to Lead (15 actions, 5 touches in 24 h, then a hand-off), Missed Call Text-Back, Lead Nurture (31 days, 11 touches), Replied - Stop & Route, Win-back (31 days, 5 touches), Visit Booked - Confirm & Move, Visit Reminders, No-Show Rescue, plus Quote Follow-up and Review Request (v2.1.0).",
7
7
  "default": false,
8
8
  "selectors": {
9
9
  "businessTypes": [
@@ -251,6 +251,22 @@
251
251
  {
252
252
  "ref": "tag.interest_second_opinion",
253
253
  "name": "interest-second-opinion"
254
+ },
255
+ {
256
+ "ref": "tag.quote_sent",
257
+ "name": "quote-sent",
258
+ "_note": "Added when a treatment plan goes out. Starts Quote Follow-up; removed by it so a later treatment plan can start it again."
259
+ },
260
+ {
261
+ "ref": "tag.quote_stale",
262
+ "name": "quote-stale",
263
+ "_note": "A treatment plan that got no answer through the whole follow-up."
264
+ },
265
+ {
266
+ "ref": "tag.review_requested",
267
+ "name": "review-requested",
268
+ "_note": "A review was asked for after a completed visit.",
269
+ "conditionalOn": "goal.bookingNeeded == true"
254
270
  }
255
271
  ],
256
272
  "_tagNote": "Interest tags mirror the What Brings You In options and are intentionally non-clinical. The skill may add service tags from offer.summary only if compliance_notes allow it.",
@@ -280,6 +296,14 @@
280
296
  "value": "",
281
297
  "filledBy": "handoff.calendar_oauth",
282
298
  "conditionalOn": "goal.bookingNeeded == true"
299
+ },
300
+ {
301
+ "ref": "cv.review_link",
302
+ "name": "review_link",
303
+ "value": "",
304
+ "filledBy": "handoff.review_link",
305
+ "conditionalOn": "goal.bookingNeeded == true",
306
+ "_fill": "the Google review link; blank until the operator pastes it"
283
307
  }
284
308
  ],
285
309
  "calendars": [
@@ -288,7 +312,7 @@
288
312
  "conditionalOn": "goal.bookingNeeded == true",
289
313
  "name": "{{business.name}} New Patient Visit || New Patient Visit",
290
314
  "calendarType": "round_robin",
291
- "_slotDuration": "Carry the appointment length from the brief (brief.calendars[].durationMinutes, or the words in the calendar answer: \"15 minutes\" \u2192 15) onto slotDuration (minutes, slotDurationUnit \"mins\"). This preset value applies ONLY when the brief gives no length; without any slotDuration GoHighLevel builds 30-minute slots (finding 25).",
315
+ "_slotDuration": "Carry the appointment length from the brief (brief.calendars[].durationMinutes, or the words in the calendar answer: \"15 minutes\" → 15) onto slotDuration (minutes, slotDurationUnit \"mins\"). This preset value applies ONLY when the brief gives no length; without any slotDuration GoHighLevel builds 30-minute slots (finding 25).",
292
316
  "slotDuration": 45,
293
317
  "slotDurationUnit": "mins",
294
318
  "teamMemberRefs": [
@@ -314,7 +338,6 @@
314
338
  }
315
339
  ],
316
340
  "availabilityType": 0,
317
- "slotDuration": 45,
318
341
  "slotBuffer": 15,
319
342
  "requiresStaff": true,
320
343
  "notes": "Default Mon-Fri 8-5, 45-minute new-patient slots from business.hours; operator edits after build. teamMemberRefs points at the providers in the plan users list."
@@ -450,6 +473,19 @@
450
473
  "name": "No-Show 2 - Still Want This?",
451
474
  "subject": "Still want to come in?",
452
475
  "html": "<div style=\"font-family:Arial,Helvetica,sans-serif;font-size:16px;line-height:1.5;color:#1f2937;max-width:600px;\"><p style=\"margin:0 0 14px;\">Hi {{contact.first_name}},</p><p style=\"margin:0 0 14px;\">Quick and honest: if the timing is wrong, say so and I'll check back in a few months. If you still want to come in, the calendar is open and the visit is the same as before.</p><p style=\"margin:0 0 14px;\"><a href=\"{{custom_values.booking_link}}\" style=\"display:inline-block;background:#1a56db;color:#ffffff;padding:12px 20px;border-radius:6px;text-decoration:none;font-weight:600;\">Pick a new time</a></p><p style=\"margin:0 0 14px;\">Either way, thanks for considering {{custom_values.business_name}}.</p><p style=\"margin:0;\">{{custom_values.owner_first_name}}<br>{{custom_values.business_name}} · {{custom_values.business_phone}}</p></div>"
476
+ },
477
+ {
478
+ "ref": "email_template.quote_email_1",
479
+ "name": "Quote Follow-up - Day 3 Email",
480
+ "subject": "Any questions on your treatment plan, {{contact.first_name}}?",
481
+ "html": "<div style=\"font-family:Arial,Helvetica,sans-serif;font-size:16px;line-height:1.5;color:#1f2937;max-width:600px;\"><p style=\"margin:0 0 14px;\">Hi {{contact.first_name}},</p><p style=\"margin:0 0 14px;\">You have had the treatment plan from {{custom_values.business_name}} for a few days, so this is a short check-in rather than a push.</p><p style=\"margin:0 0 14px;\">Three things people usually ask at this point: what is included, what can wait, and how payment works. Reply with any of those and I will answer plainly.</p><p style=\"margin:0 0 14px;\">If you would rather talk it through, pick a time here:</p><p style=\"margin:0 0 14px;\"><a href=\"{{custom_values.booking_link}}\" style=\"display:inline-block;background:#1a56db;color:#ffffff;padding:12px 20px;border-radius:6px;text-decoration:none;font-weight:600;\">Book a quick call</a></p><p style=\"margin:0 0 14px;\">No pressure either way. The numbers stand for 30 days.</p><p style=\"margin:0;\">{{custom_values.owner_first_name}}<br>{{custom_values.business_name}} · {{custom_values.business_phone}}</p></div>"
482
+ },
483
+ {
484
+ "ref": "email_template.review_email_1",
485
+ "name": "Review Request - Day 3 Email",
486
+ "subject": "One minute for a review, {{contact.first_name}}?",
487
+ "html": "<div style=\"font-family:Arial,Helvetica,sans-serif;font-size:16px;line-height:1.5;color:#1f2937;max-width:600px;\"><p style=\"margin:0 0 14px;\">Hi {{contact.first_name}},</p><p style=\"margin:0 0 14px;\">Thank you again for your visit with {{custom_values.business_name}} this week.</p><p style=\"margin:0 0 14px;\">If it went well, a short review is the most useful thing you could do for us. It takes about a minute and it is how the next person decides to trust us.</p><p style=\"margin:0 0 14px;\"><a href=\"{{custom_values.review_link}}\" style=\"display:inline-block;background:#1a56db;color:#ffffff;padding:12px 20px;border-radius:6px;text-decoration:none;font-weight:600;\">Leave a review</a></p><p style=\"margin:0 0 14px;\">If anything was not right, reply to this email instead and I will fix it personally.</p><p style=\"margin:0;\">{{custom_values.owner_first_name}}<br>{{custom_values.business_name}} · {{custom_values.business_phone}}</p></div>",
488
+ "conditionalOn": "goal.bookingNeeded == true"
453
489
  }
454
490
  ],
455
491
  "sms": [
@@ -537,6 +573,22 @@
537
573
  "ref": "sms_template.ns_sms_2",
538
574
  "name": "No-Show Text 2",
539
575
  "body": "{{contact.first_name}}, {{custom_values.owner_first_name}} here. I kept a couple of new-patient times open for you this week. Want one? Reply with a day that works."
576
+ },
577
+ {
578
+ "ref": "sms_template.quote_sms_1",
579
+ "name": "Quote Follow-up - Next Day Text",
580
+ "body": "Hi {{contact.first_name}}, {{custom_values.owner_first_name}} at {{custom_values.business_name}}. Did the treatment plan make sense? Happy to walk through any part of it. Reply here or call {{custom_values.business_phone}}. Reply STOP to opt out."
581
+ },
582
+ {
583
+ "ref": "sms_template.quote_sms_2",
584
+ "name": "Quote Follow-up - Last Text",
585
+ "body": "Hi {{contact.first_name}}, last note from {{custom_values.business_name}} about your treatment plan. If the timing is off, one word back and I will check in when it suits you. Reply STOP to opt out."
586
+ },
587
+ {
588
+ "ref": "sms_template.review_sms_1",
589
+ "name": "Review Request - Same Day Text",
590
+ "body": "Thank you for coming in today, {{contact.first_name}}. If we did right by you, a quick review helps the next person find us: {{custom_values.review_link}} Reply STOP to opt out.",
591
+ "conditionalOn": "goal.bookingNeeded == true"
540
592
  }
541
593
  ]
542
594
  },
@@ -751,6 +803,35 @@
751
803
  "custom_values.owner_first_name",
752
804
  "custom_values.business_phone"
753
805
  ]
806
+ },
807
+ {
808
+ "ref": "email.quote_email_1",
809
+ "name": "Quote Follow-up - Day 3 Email",
810
+ "subject": "Any questions on your treatment plan, {{contact.first_name}}?",
811
+ "templateRef": "email_template.quote_email_1",
812
+ "copyDirection": "Day three after the treatment plan. Check-in, not a push. Name the three questions people ask (what is included, what can wait, how payment works), invite a reply, booking CTA for a quick call. Tone: brief.voice.threeWords.",
813
+ "mergeTags": [
814
+ "contact.first_name",
815
+ "custom_values.business_name",
816
+ "custom_values.booking_link",
817
+ "custom_values.owner_first_name",
818
+ "custom_values.business_phone"
819
+ ]
820
+ },
821
+ {
822
+ "ref": "email.review_email_1",
823
+ "name": "Review Request - Day 3 Email",
824
+ "subject": "One minute for a review, {{contact.first_name}}?",
825
+ "templateRef": "email_template.review_email_1",
826
+ "copyDirection": "Three days after a completed visit with no review yet. Thank them, why it matters, the review button, and an honest line: if anything was not right, reply instead. Tone: brief.voice.threeWords.",
827
+ "mergeTags": [
828
+ "contact.first_name",
829
+ "custom_values.business_name",
830
+ "custom_values.review_link",
831
+ "custom_values.owner_first_name",
832
+ "custom_values.business_phone"
833
+ ],
834
+ "conditionalOn": "goal.bookingNeeded == true"
754
835
  }
755
836
  ],
756
837
  "sms": [
@@ -944,6 +1025,41 @@
944
1025
  "custom_values.owner_first_name"
945
1026
  ],
946
1027
  "conditionalOn": "channels.sms == true"
1028
+ },
1029
+ {
1030
+ "ref": "sms.quote_sms_1",
1031
+ "name": "Quote Follow-up - Next Day Text",
1032
+ "templateRef": "sms_template.quote_sms_1",
1033
+ "copyDirection": "One day after the treatment plan went out. Owner's first name and business, one question: did it make sense. Offer to walk through it, reply or call. STOP line.",
1034
+ "mergeTags": [
1035
+ "contact.first_name",
1036
+ "custom_values.owner_first_name",
1037
+ "custom_values.business_name",
1038
+ "custom_values.business_phone"
1039
+ ],
1040
+ "conditionalOn": "channels.sms == true"
1041
+ },
1042
+ {
1043
+ "ref": "sms.quote_sms_2",
1044
+ "name": "Quote Follow-up - Last Text",
1045
+ "templateRef": "sms_template.quote_sms_2",
1046
+ "copyDirection": "Last text of the follow-up, five days in. No guilt: if the timing is off, one word back and we check in later. STOP line.",
1047
+ "mergeTags": [
1048
+ "contact.first_name",
1049
+ "custom_values.business_name"
1050
+ ],
1051
+ "conditionalOn": "channels.sms == true"
1052
+ },
1053
+ {
1054
+ "ref": "sms.review_sms_1",
1055
+ "name": "Review Request - Same Day Text",
1056
+ "templateRef": "sms_template.review_sms_1",
1057
+ "copyDirection": "Two hours after a completed visit. Thank them, one sentence on why a review helps, the review link. STOP line.",
1058
+ "mergeTags": [
1059
+ "contact.first_name",
1060
+ "custom_values.review_link"
1061
+ ],
1062
+ "conditionalOn": "channels.sms == true && goal.bookingNeeded == true"
947
1063
  }
948
1064
  ],
949
1065
  "workflows": [
@@ -1541,6 +1657,104 @@
1541
1657
  }
1542
1658
  ],
1543
1659
  "conditionalOn": "goal.bookingNeeded == true"
1660
+ },
1661
+ {
1662
+ "ref": "workflow.quote_follow_up",
1663
+ "name": "Quote Follow-up",
1664
+ "trigger": {
1665
+ "type": "contact_tag",
1666
+ "tagRef": "tag.quote_sent"
1667
+ },
1668
+ "stopOnResponse": true,
1669
+ "_design": "Starts when the quote-sent tag is added (by hand, or by the estimate workflow the operator builds in the UI). Removes its own trigger tag first so the next treatment plan can start it again. Text next day, email on day 3, last text on day 5, then a call task for the owner and the quote-stale tag. Any reply stops it (stopOnResponse) and Replied - Stop & Route takes over. Closes the Layer 4 gap named on the hub: the assessment measured quote follow-up and nothing built it (2026-09-14).",
1670
+ "actions": [
1671
+ {
1672
+ "type": "remove_contact_tag",
1673
+ "tagRef": "tag.quote_sent"
1674
+ },
1675
+ {
1676
+ "type": "wait",
1677
+ "value": 1,
1678
+ "unit": "days"
1679
+ },
1680
+ {
1681
+ "type": "send_sms",
1682
+ "smsRef": "sms.quote_sms_1",
1683
+ "conditionalOn": "channels.sms == true"
1684
+ },
1685
+ {
1686
+ "type": "wait",
1687
+ "value": 2,
1688
+ "unit": "days"
1689
+ },
1690
+ {
1691
+ "type": "send_email",
1692
+ "emailRef": "email.quote_email_1"
1693
+ },
1694
+ {
1695
+ "type": "wait",
1696
+ "value": 2,
1697
+ "unit": "days"
1698
+ },
1699
+ {
1700
+ "type": "send_sms",
1701
+ "smsRef": "sms.quote_sms_2",
1702
+ "conditionalOn": "channels.sms == true"
1703
+ },
1704
+ {
1705
+ "type": "wait",
1706
+ "value": 2,
1707
+ "unit": "days"
1708
+ },
1709
+ {
1710
+ "type": "task_notification",
1711
+ "userRef": "user.owner",
1712
+ "title": "Call {{contact.first_name}} about their treatment plan",
1713
+ "body": "No reply to the treatment plan in a week. One call, no pressure: what would make this a yes, or when should we check back.",
1714
+ "dueDate": "1"
1715
+ },
1716
+ {
1717
+ "type": "add_contact_tag",
1718
+ "tagRef": "tag.quote_stale"
1719
+ }
1720
+ ]
1721
+ },
1722
+ {
1723
+ "ref": "workflow.review_request",
1724
+ "name": "Review Request",
1725
+ "trigger": {
1726
+ "type": "appointment",
1727
+ "appointmentStatus": "showed",
1728
+ "calendarRef": "calendar.new_patient"
1729
+ },
1730
+ "stopOnResponse": true,
1731
+ "conditionalOn": "goal.bookingNeeded == true",
1732
+ "_design": "On a completed visit (status showed): tag, wait two hours, text the review link, then an email three days later if nothing came back. Any reply stops it. The review link is a custom value the operator pastes once (handoff.review_link). Closes the Layer 4 gap named on the hub: review requests had no build feature (2026-09-14).",
1733
+ "actions": [
1734
+ {
1735
+ "type": "add_contact_tag",
1736
+ "tagRef": "tag.review_requested"
1737
+ },
1738
+ {
1739
+ "type": "wait",
1740
+ "value": 2,
1741
+ "unit": "hours"
1742
+ },
1743
+ {
1744
+ "type": "send_sms",
1745
+ "smsRef": "sms.review_sms_1",
1746
+ "conditionalOn": "channels.sms == true"
1747
+ },
1748
+ {
1749
+ "type": "wait",
1750
+ "value": 3,
1751
+ "unit": "days"
1752
+ },
1753
+ {
1754
+ "type": "send_email",
1755
+ "emailRef": "email.review_email_1"
1756
+ }
1757
+ ]
1544
1758
  }
1545
1759
  ],
1546
1760
  "handoffs": [
@@ -1558,7 +1772,8 @@
1558
1772
  "workflow.reply_route",
1559
1773
  "workflow.appointment_booked",
1560
1774
  "workflow.no_show",
1561
- "workflow.missed_call"
1775
+ "workflow.missed_call",
1776
+ "workflow.quote_follow_up"
1562
1777
  ],
1563
1778
  "_blocksNote": "Workflows with a notification or task pointed at user.__pending__ stay DRAFT until a real user is assigned. Prune entries whose workflow was dropped by conditional pruning."
1564
1779
  },
@@ -1578,7 +1793,9 @@
1578
1793
  "workflow.win_back",
1579
1794
  "workflow.appointment_booked",
1580
1795
  "workflow.appointment_reminders",
1581
- "workflow.no_show"
1796
+ "workflow.no_show",
1797
+ "workflow.quote_follow_up",
1798
+ "workflow.review_request"
1582
1799
  ]
1583
1800
  },
1584
1801
  {
@@ -1652,7 +1869,9 @@
1652
1869
  "sms.appt_24h_sms",
1653
1870
  "sms.appt_2h_sms",
1654
1871
  "sms.ns_sms_1",
1655
- "sms.ns_sms_2"
1872
+ "sms.ns_sms_2",
1873
+ "workflow.quote_follow_up",
1874
+ "workflow.review_request"
1656
1875
  ],
1657
1876
  "_blocksNote": "Lists every SMS-bearing WORKFLOW ref (so they stay DRAFT) plus the sms.* asset refs. After conditional pruning, drop any entry whose workflow/asset was removed."
1658
1877
  },
@@ -1705,8 +1924,31 @@
1705
1924
  "email.appt_confirm_email",
1706
1925
  "email.appt_prep_email",
1707
1926
  "email.ns_email_1",
1708
- "email.ns_email_2"
1927
+ "email.ns_email_2",
1928
+ "email.quote_email_1",
1929
+ "email.review_email_1"
1709
1930
  ]
1931
+ },
1932
+ {
1933
+ "ref": "handoff.review_link",
1934
+ "conditionalOn": "goal.bookingNeeded == true",
1935
+ "owner": "OPERATOR-UI",
1936
+ "title": "Paste the Google review link so review requests point somewhere",
1937
+ "trigger": "always (2 minutes)",
1938
+ "instruction": "In Google Business Profile, open the profile, choose Ask for reviews and copy the short link. Then in the sub-account: Settings > Custom Values: set review_link to that link. Until it is set, the Review Request workflow sends a text with no link, so do this before the first visit is marked showed.",
1939
+ "produces": "cv.review_link",
1940
+ "successCheck": "review_link shows a real https link, not a blank",
1941
+ "blocks": [
1942
+ "cv.review_link"
1943
+ ]
1944
+ },
1945
+ {
1946
+ "ref": "handoff.quote_tag",
1947
+ "owner": "OPERATOR-UI",
1948
+ "title": "Start Quote Follow-up by tagging quote-sent when a treatment plan goes out",
1949
+ "trigger": "always (1 minute to read)",
1950
+ "instruction": "Quote Follow-up starts from the tag quote-sent. Add that tag to the contact whenever a treatment plan goes out: by hand on the contact, or, if the treatment plans are sent as GoHighLevel estimates, build one workflow in the UI with the Estimate trigger (status sent) whose only step adds the tag quote-sent. The follow-up removes the tag itself, so the next treatment plan starts it again.",
1951
+ "successCheck": "A contact tagged quote-sent receives the next-day text"
1710
1952
  }
1711
1953
  ]
1712
1954
  }
@@ -1,6 +1,6 @@
1
1
  # Preset: Coach / Consultant
2
2
 
3
- **File:** `coach.preset.json` · **id:** `coach` · **version:** 2.0.0 · **default:** no
3
+ **File:** `coach.preset.json` · **id:** `coach` · **version:** 2.1.0 · **default:** no
4
4
  **Source:** Built from the intake industry pack "coach" (delivery_format, call_booking_flow) and the discovery-call sales pattern; v2 depth per the owner review of 2026-08-26.
5
5
 
6
6
  ## When it is selected
@@ -28,6 +28,8 @@ Routes from the "Coach / consultant" business type (coaching, consulting, course
28
28
  | Lead Nurture (30 days) | contact_tag (tag.nurture_start) | 28 | 11 | 31 days | yes |
29
29
  | Replied - Stop & Route | customer_reply | 9 | 0 | instant | no |
30
30
  | Win-back (30 days) | contact_tag (tag.winback_start) | 13 | 5 | 31 days | yes |
31
+ | Proposal Follow-up | contact_tag (tag.quote_sent) | 14 | 4 + a call task | 10 days | yes |
32
+ | Review Requests | contact_tag (tag.review_ask) | 8 | 3 | 7 days | yes |
31
33
  | Call Booked - Confirm & Move | appointment (confirmed) | 8 | 2 | instant | no |
32
34
  | Call Reminders | appointment (confirmed) | 5 | 3 | instant | no |
33
35
  | No-Show Rescue | appointment (noshow) | 14 | 4 | 7 days | yes |
@@ -39,6 +41,13 @@ Routes from the "Coach / consultant" business type (coaching, consulting, course
39
41
  - **Missed Call Text-Back**: `call_status` trigger scoped to no-answer / busy / voicemail, inbound. Text within seconds, tag, alert, call-back task, one more text an hour later.
40
42
  - **Discovery Call → Confirm & Move, Reminders, No-Show Rescue**: booking stops every sequence and moves (or creates) the opportunity; reminders at 24 h and 2 h; a no-show gets a same-day call task, text and email, two more touches, then hands off to Win-back and moves the card back to Contacted.
41
43
 
44
+ ### Added in v2.1.0 (2026-09-06): the two features the Assessment prices
45
+
46
+ - **Proposal Follow-up** (feature `quote_followup`): starts from the `quote-sent` tag the operator applies when a proposal goes out (by hand, from a quoting tool, or from a stage). Text on day 1, email on day 3, text on day 6 plus a call task, last email on day 10; any reply stops it; ends by tagging `quote-no-reply`. Hand-off `handoff.quote_tag` explains the tag.
47
+ - **Review Requests** (feature `review_requests`): starts from the `review-ask` tag applied when the work is done. Text two hours later with the Google link from the `review_link` custom value, email on day 3, last text on day 7; any reply stops it (a complaint reaches a person, not a second nudge); ends by tagging `review-asked`. Hand-off `handoff.review_link` collects the link.
48
+
49
+ Every workflow now belongs to a feature (`src/intake-to-build/features.ts`) so a client's Blueprint builds what they bought; the reply router is the foundation every messaging feature stands on.
50
+
42
51
  ### Why sequences hand off with a tag, not add_to_workflow
43
52
  Every hand-off is `add_contact_tag` + a `contact_tag` trigger. Both halves are live-proven shapes captured from working GHL workflows (`templates/action-schemas.json`). `add_to_workflow` has no captured native shape there and has not been proven at runtime, so a preset may not use it. Each sequence removes its own trigger tag as its first action so a later hand-off can start it again.
44
53
 
@@ -56,3 +65,7 @@ Every hand-off is `add_contact_tag` + a `contact_tag` trigger. Both halves are l
56
65
 
57
66
  ## Copy notes
58
67
  Built on belief shifts, not hype: you do not need more information, you need a decision; the reason "tried before" did not stick was structure, not willpower; the call is a diagnosis, not a pitch; the cost of staying where you are. Time and money objections are handled head-on on days 14 and 20. Every text is a one-word question. No income, result or transformation claims are made; the build stage adds real client results only if the brief supplies them.
68
+
69
+ ## v2.1.0 (2026-09-15)
70
+
71
+ Two workflows the Assessment prices and no preset built: **Quote Follow-up** (starts from the `quote-sent` tag; text next day, email day 3, last text day 5, then a call task for the owner and the `quote-stale` tag) and **Review Request** (starts from the `service-complete` tag, never from a consult or estimate; text at two hours with the `review_link` custom value, email three days later). Held DRAFT behind the A2P and phone-number handoffs like every other text-bearing workflow (Quote Follow-up also behind staff, for its call task); their emails wait on the sending-domain handoff.