Sales Motion (Seller)
Linear: RYR-235 — FUB→Kit sync (2026-07-23 vault→Linear audit)
One-line description. End-to-end seller sales motion for personal production. Capri brand. Orchard Brokerage as legal label. ISA-driven outbound off cancelled and expired listings.
Why
I need my own production lane. Team-lead income alone is brittle. A working seller motion proves the playbook before I roll it out to the team.
The motion targets cancelled and expired listings. Setters call. I qualify. I run the consult. Capri is the brand on it. Orchard is the legal label on the agreement. May 1 is the MVP ship date.
Current state
All asset fills complete and all 7 email source files paste-ready as of 2026-05-02. Sequence restructured during paste-prep: consult-prep is now 3 emails (added pricing-strategy education email at Day 1), post-consult is 4 emails on Day 2/3/4/7 cadence (front-loaded value, then 3-day silent gap, then salvage). Two Kit sequence shells live (2730518 + 2730519). Remaining: Kit paste-and-wire + FUB workflow + landing placeholder + E2E test.
- Status: in-flight
- Last update: 2026-09-21 — deal spine wave 2: the FUB heal moved inside the send rail, the Meeting Game Plan email and the morning-of travel blocks went live (see §Deal spine)
- Rank-1 resolution: (b) system-bound — funnel runs E2E with at least one real subscriber + first Capri RE-branded email delivered by 5/31. Resolved 2026-05-02 in
Roadmap/plans/2026-05-may-priorities.md. - Blocked on: nothing — Ry can begin Kit paste-and-wire now
Next 3 actions
- Pond drill on Beverlei (RYR-605 #1): move her into
DFW Pond(id 50), Ry claims her in FUB → the real "Lead assigned" mail fires the whole deal spine on a fake seller. Read back the row, theCustomers/tree, the FUB note, the journey step; trash the tree. - Booking becomes a trigger (RYR-605 #3): route the FUB "Customer Booked" note → stamp
booked_at+ TPID, shareHome Sale(dark flag first), park the kickoff draft. - Nudge drainer to the claude@ Mini user (RYR-605 #4b-d) — still unbuilt. (Heal-before-send, the old item 2, SHIPPED 2026-09-21 as MR !3548.)
(The 2026-05 Kit sequence wiring items that sat here were superseded by the lifecycle-text rail; see
docs/RAILS.md§"FUB customer texting".)
Decisions log
- 2026-04-20 Capri brand — Capri is the brand on personal production
- 2026-04-26 Sell rycolston permanent — rycolston.com is permanent home for content and funnel
- 2026-04-26 Portfolio organization — vault README and Projects template (meta)
In-project decision log:
| Date | Decision |
|---|---|
| 2026-04-21 | MVP scope locked. 2 sequences. Text-only signature. Landing placeholder. |
| 2026-04-21 | ISA dial cadence runbook lives in appointment-setter-hiring (single source) |
| 2026-04-21 | post-consult objection buckets: silent disagreement / credibility gap / commission pushback |
| 2026-04-21 | Outcome-driven FUB→Kit cascade. I update FUB outcome. Tags follow. |
| 2026-04-21 | Option-period explainer email = educational, newsletter-style |
| 2026-04-22 | Tag stage:agreement-sent (19057984) live in Kit |
| 2026-04-22 | Sequence shells live: 2730518 (consult-prep) + 2730519 (post-consult-no-commit) |
| 2026-05-02 | Brand mark locked: Capri RE (not Capri). Every mention paired with powered by Orchard Brokerage. |
| 2026-05-02 | All asset fills complete: case-study-001 (Edwards), case-study-002 (Morgan), commission-defense (3 differentiators + math), static-fields (phone + signature), testimonial-001 (placeholder, currently unused). |
| 2026-05-02 | Consult-prep restructured to 3 emails (added pricing-strategy education email at Day 1). |
| 2026-05-02 | Post-consult restructured to Day 2/3/4/7 cadence (was Day 2/5/9/13). New order: proof → commission → three options → where-do-you-stand. Hard drop Day 8. |
| 2026-05-02 | Proof email reframed to Morgan family / 813 Goose Ct case study (lender pushback + short sale rescue). Edwards case retained for consult-prep morning-of email. |
| 2026-05-02 | Trigger architecture confirmed: stage:agreement-sent + 48hr wait for post-consult sequence. Day count is from agreement-sent moment. |
| 2026-05-02 | Writing rules tightened globally: Hormozi "talking to a friend" rule now explicitly excludes slang/swagger register in customer-facing copy. Documented in ~/.claude/CLAUDE.md. |
Open issues
Live launch checklist. Hit items in any order. They're grouped by type, not sequence.
1. Case studies (DONE)
Two case studies filled. Edwards used in consult-prep morning-of; Morgan used in post-consult proof email.
- Case study 1 — Edwards / Vista of Eldorado:
assets/case-studies/case-study-001.md. 77 DOM prior approach → 14 DOM under Ry → $440K close. ~$20K seller upside via guaranteed-proceeds bridge program. Used inconsult-prep-seller/03-morning-of.md. - Case study 2 — Morgan / 813 Goose Ct, Forney:
assets/case-studies/case-study-002.md. Short sale rescue. Family underwater + bank forced overpriced list + agent hospitalization. Ry negotiated the lender to a realistic price, drove the deal through. Closed 2026-03-26. Used inpost-consult-no-commit-seller/02-proof.md. - Optional Phase F: collect a signed testimonial from Edwards or Morgan to upgrade
testimonial-001.md(currently unused placeholder).
2. Commission defense (DONE)
commission-defense.md filled with three differentiators (P.R.E.P.A.R.E.D Framework / 3 Tier Pricing Strategy / Performance Guarantee) and the commission math example. Restructured 2026-05-02 from inline placeholders to bold-header + body format. Values now hardcoded in commission email source file.
- Three differentiators defined and locked
- Commission math values locked: $525K list / $5,250 savings / $26,250 price difference / $21,000 net difference
3. Static + per-subscriber data (DONE for MVP)
-
{{RYAN_PHONE}}= (214) 814-5052 — locked instatic-fields.md - Signature block locked:
Ry Colston, Broker Associate / Capri RE, powered by Orchard Brokerage / (214) 814-5052 | {{LANDING_PAGE_URL}} - MVP ships with manual fills for per-subscriber fields (
{{CONSULT_DAY}},{{CONSULT_TIME}},{{SELLER_PROPERTY_ADDRESS}},{{SELLER_NEIGHBORHOOD}}) - Phase F: FUB→Kit custom-field sync for per-subscriber automation
5. Option-period explainer email
The educational, newsletter-style template at sales-motion/email-templates/option-period-explainer.md. 7 placeholders to fill or leave as merge fields.
📁 Edit the file in place: ~/capri/personal-production/sales-motion/email-templates/option-period-explainer.md (this email is per-listing; merge-field syntax handles the per-listing variables)
- Read the draft and verify the tone reads as "teacher walking the seller through" not "transactional notice"
- Verify or replace the
{{STAT_INSPECTION_PCT}}stat - Confirm FUB merge-field syntax for the merge-field placeholders (FirstName, dates) before paste
6. Decisions still open
- FUB outcome mechanic: custom outcome values OR existing FUB outcomes + a "post-consult-decision" custom field. Pick one in FUB UI (~5 min)
- Capri brand visuals decision — confirm whether visuals will exist by 2026-04-29 (currently locked to option (b) text-only signature for May 1; can swap post-launch)
- Newsletter platform decision — Kit/Ghost split is fine for now; revisit when first close lands (Stage 12 motion)
7. ISA prep (parallel to Kit work)
📁 Edit the file in place: ~/platform/projects/recruiting-appointment-setter/onboarding/dial-cadence-runbook.md
- Fill in the dial cadence runbook TODOs at
~/platform/projects/recruiting-appointment-setter/onboarding/dial-cadence-runbook.md: - Cadence schedule (which attempts at which times of day across the 7-attempt minimum)
- Voicemail strategy (which attempts get voicemail, what the script says)
- SMS fallback (when fires, what it says)
- Time-of-day rules (best contact windows for cancelled/expired)
- "Mark dead" criteria (after 7 attempts no live contact, what happens?)
- Run NTREIS pull → Mojo import → skip-trace process at least once before the ISA starts (so they're not setting up the data flow on Day 1)
- Brief the ISA on
OPERATING-MODEL.mdso they understand the funnel they're plugging into (not just the dial mechanics)
8. Phase E paste-and-wire
- Override Kit sequence 2730518 (consult-prep) time zone NY → Chicago
- Override Kit sequence 2730519 (post-consult-no-commit) time zone NY → Chicago
- Paste 3 emails into shell 2730518 (consult-prep-seller) per the new structure:
- Email 1 (Day 0, fires immediately on enrollment):
01-confirmation-and-prep.md - Email 2 (Day 1, 24hr after Email 1):
02-pricing-strategy.md - Email 3 (morning-of consult):
03-morning-of.md— set delay per README cadence (MVP: ~24hr after Email 2) - Paste 4 emails into shell 2730519 (post-consult-no-commit-seller) per the new Day 2/3/4/7 cadence:
- Position 1 (Day 2, fires immediately on enrollment — upstream 48hr wait handles the delay):
02-proof.md - Position 2 (Day 3, 1 day after previous):
03-commission.md - Position 3 (Day 4, 1 day after previous):
04-three-option-close.md - Position 4 (Day 7, 3 days after previous):
01-where-are-you-at.md - Wire Kit automation:
stage:consult-settag added → enroll subscriber in 2730518 - Wire Kit automation:
stage:agreement-senttag added → wait 48 hours → enroll subscriber in 2730519 - Wire Kit automation: Day-8 hard-stop on 2730519 — subscriber finished sequence with no
stage:pre-listand no reply → applystage:do-not-contact - Set Kit account from-name to "Ry Colston"
- Set Kit signature template to the locked block in
assets/static-fields.md - Verify Kit automation rule:
stage:do-not-contacttag added → exit subscriber from all sequences
9. FUB → Kit sync wiring (Cloud Function build)
Decision 2026-05-02 (revised): Add a new route /fub-kit-sync to the existing pos-fub Cloud Run service. NOT a new function. Reuses the live FastAPI service. Architecture per ~/platform/projects/kit-mcp/FUB-SYNC-PLAN.md. Cost: $0/mo (rolls into existing pos-fub free-tier usage). Build estimate: 5-6 hours focused dev.
MVP tag mapping (3 rules):
| FUB signal | Kit tag (id) | Kit sequence enrollment |
|---|---|---|
| FUB tag "Consult Set" added | stage:consult-set (19049515) |
Enroll in 2730518 (consult-prep) |
| FUB tag "Agreement Sent" added | stage:agreement-sent (19057984) |
Enroll in 2730519 (post-consult) after Kit-side 48hr wait |
FUB tag "Do Not Contact" added OR unsubscribed = true |
stage:do-not-contact (19049531) |
Exit all sequences |
FUB-side prerequisite tasks:
- Create FUB tag "Consult Set" in FUB UI
- Create FUB tag "Agreement Sent" in FUB UI
- Create FUB tag "Do Not Contact" in FUB UI (or use existing if present)
- (Optional) FUB workflow: appointment outcome = "Consult Held - Agreement Sent" → auto-add "Agreement Sent" tag. Removes manual tag step.
- (Optional) FUB workflow: appointment-created with type = listing consult → auto-add "Consult Set" tag. Removes manual tag step.
Cloud Run service extension tasks (target: existing pos-fub service):
- Migrate Kit API key + secret from macOS Keychain to Google Secret Manager (
KIT_API_KEY,KIT_API_SECRET) - Add Kit secret env vars to
pos-fubTerraform module in~/platform/pos-fub/pos_fub.tf(alongside existingFUB_API_KEY) - Create new handler module
~/CCPJ/projects/pos-cloud-functions/functions/fub_kit_sync/__init__.py(or similar) with the sync logic - Build Kit API client helper:
apply_tag_by_email(email, tag_id)with subscriber lookup + create-if-missing + tag application - Build Kit API client helper:
remove_tag_by_email(email, tag_id) - Build tag-mapping logic for the 3 rules above
- Build snapshot-diff logic against
fub_data.fub_peopleand new state tablepos_raw.fub_kit_subscriber_state - Build audit log writes to new table
pos_raw.fub_kit_sync_log - Add
/fub-kit-syncroute to~/CCPJ/projects/pos-cloud-functions/services/fub/entrypoint.py(using existing_wrap()pattern) - Add scheduler job entry
fub-kit-syncto~/platform/pos-fub/pos_fub.tf(every 5 min recommended) - Local test: stub FUB tag change in BQ, run handler, verify Kit tag lands
- Deploy via existing pos-fub CI/CD pipeline
- Integration test: apply FUB tag "Consult Set" to
[email protected]record manually, watch Kit tag land within 5-min window, verify Kit sequence enrollment
Other FUB UI work (separate from sync wiring):
- Paste option-period explainer into FUB email templates
- Confirm repair-request template + offer-received template still live in Gmail/FUB
10. Landing page placeholder
- Decide: Ghost post on rycolston.com OR Kit landing page
- Build the placeholder (text, "video coming soon" if you want to hint at the future VSL, opt-in form)
- Confirm URL is shareable and lives somewhere your email CTAs can link to
11. End-to-end test
- Enroll
[email protected]as test subscriber inconsult-prep-seller(2730518) - Confirm Email 1 delivers at next send window
- Confirm from-name shows "Ry Colston"
- Confirm signature shows the text-only Capri/Orchard line
- Remove test subscriber from sequence post-confirmation
12. Launch day (May 1)
- First ISA starts and is briefed on the operating model
- FUB → Kit sync confirmed with a real subscriber
- First real consult-prep-seller subscriber enrolled
- Update
sales-motion/README.mdphase status to E complete
References
- Project home:
~/capri/personal-production/sales-motion/ - Single source of truth:
OPERATING-MODEL.md - Visual map: customer-journey.rycolston.com (source:
~/systems/sales-motion-map/, editstages.json) - Sequence email source files (separate repo):
~/platform/projects/kit-mcp/sequences/consult-prep-seller/and~/platform/projects/kit-mcp/sequences/post-consult-no-commit-seller/ - BUILD-LOG:
~/capri/personal-production/sales-motion/BUILD-LOG.md - Gap analysis:
~/capri/personal-production/sales-motion/gap-analysis.md - Live in Kit: tag
stage:agreement-sent(19057984), shells 2730518 + 2730519 - Asset convention reference:
~/capri/personal-production/sales-motion/assets/README.md - Asset file map:
- Case study 1 (Edwards) →
assets/case-studies/case-study-001.md— used in consult-prep03-morning-of.md - Case study 2 (Morgan) →
assets/case-studies/case-study-002.md— used in post-consult02-proof.md - Testimonial →
assets/testimonials/testimonial-001.md— currently unused placeholder - Commission defense →
assets/commission-defense.md— values hardcoded in03-commission.md; this file is documentation - Static fields →
assets/static-fields.md - Option-period email →
email-templates/option-period-explainer.md - ISA cadence →
~/platform/projects/recruiting-appointment-setter/onboarding/dial-cadence-runbook.md - FUB outcome workflow →
sales-motion/automations/fub-outcome-to-kit-tag.md - Related projects: Appointment Setter Hiring, Customer Journey Map, Phone Platform
Phase F backlog (post-launch)
Don't worry about these before May 1. Full prioritized list at gap-analysis.md section 3.
- Consult-prep Email 2 (pricing strategy) conditional skip-logic — when consult is < 48hr out from booking, skip Email 2 so it doesn't arrive after the meeting. Requires FUB → Kit sync to push consult datetime as a Kit custom field, plus a Kit Visual Automation rebuild that branches on the 48hr check. Full implementation path documented in
~/platform/projects/kit-mcp/sequences/consult-prep-seller/README.md"Phase F" section. - FUB → Kit per-subscriber custom field sync — current sync only passes tags. To support pricing-strategy skip-logic AND merge-field automation for
{{CONSULT_DAY}}/{{CONSULT_TIME}}/{{SELLER_PROPERTY_ADDRESS}}/{{SELLER_NEIGHBORHOOD}}, FUB must also push these values as Kit custom fields per subscriber. - Collect signed testimonial to upgrade
testimonial-001.mdfrom placeholder to live. Default upgrade path: text Edwards or Morgan, ask for 2-sentence quote. Once upgraded, slot into post-consult proof email or future seller-nurture content. - Pre-listing packet (design + print)
- VSL (script + film + edit + host)
- Closing-day workflow + closing gift + review/testimonial/referral asks
- Past-client annual nurture
- 9 remaining Kit sequences
- $299 FSBO-playbook downgrade product brainstorm
- Auto-generated weekly market + buyer-activity emails
- New Client Booking Intake template (v1 drafted 2026-04-26): https://docs.google.com/document/d/1tUdKkJRmrZBPYbKUfhFCkdNzdFdIHqliSj8Ua6hcW6Q/edit. Replaces
New Client Booking Audit | Template. Open review questions: (1) Form/Sheet vs Doc-per-client for queryability; (2) should "booking complete" in FUB be gated on this; (3) field add/cut after 2-3 live consults.
Homework cards — live 2026-09-16 (RYR-573, still In Progress)
The intake reply promises "I'm going to do some homework on your home and then give you a call." This is what keeps that promise. Cued automatically the moment that text is verified Sent.
All four cards build end to end, read back from Postgres this date: Dwan West (6218 Hightower St, Aubrey), Tierra Wallace (6108 Determine Ln, Heathridge), Jimmy Hoang (1409 Elderberry Dr, Anna), Srinivasa (2901 Bald Eagle Blvd, Krugerville). Each carries address, beds, baths, sqft, year built, the owner name from the county record, follow-up status from Follow Up Boss, listing history, showing demand and a pre-listing report — every value with its source, unknowns shown as unknown.
Dwan's is the one to read: listed at $396,000 with Keller Williams Rockwall on 03/17, cancelled 09/03 after 134 days, and she is now asking about a Cash Offer. Srinivasa's report correctly DECLINES — 0 comparable properties — which is the right answer, not a failure.
Both RYR-573 calls are closed (2026-09-21). Delivery: the card page at
homework.rycolston.com plus a nudge text and email (RYR-598, 2026-09-19), and
since RYR-604 the rendered .html is also filed into the deal's Internal
Drive folder and the FUB note carries Deal folder: <link>. The drill:
POST /deal-open on pos-pipeline runs the same three legs for an existing
person — a FUB self-reassign sends NO "Lead assigned" mail (proven 2026-09-19);
only a claim out of a pond does (DFW Pond, id 50), so that is the only way to
fire the real trigger synthetically.
Four bugs found by running it for real, all fixed and merged the same day: the research job could not import three cross-system modules and wrote empty findings while reporting COMPLETE; the county was asked for a tax year whose rates do not exist yet (this had silently cost every Cooke/Denton/Ellis/ Rockwall/Tarrant brief its tax section); a rate the county genuinely sets to 0.0 was read as missing, which refused any home in a PID or TIRZ; and three cards rebuilt in one second collided on a shared database connection, losing a card that had been assembled correctly while the log said "updated".
A local test run reached production. pytest data-platforms/gmail-push
published four real messages to the live homework-card topic and created four
junk cards for the fixtures' fake person ids. Nothing was texted — because the
SENDER is injected and the trigger was not. The trigger now goes through
SweepDeps.publish_homework like every other side effect, with a test that
fails on any direct call. The junk rows were read back and deleted.
The runner VM can now READ the seller ledger (SELECT only, on
seller_intake, v_latest_intake_per_person and homework_card). It had no
grant at all, so diagnosing a card from the box holding the failure meant using
the postgres admin password — withholding the grant raised break-glass use
rather than lowering exposure.
2026-09-17 — reliability rebuild (RYR-584/585/586, 12 MRs, all live).
Research no longer runs inside cma_runner; that pass is deleted. Since RYR-589 P1 (2026-09-18, another session) the worker only queues each job for ntreis-driver.service, which runs it. A Pub/Sub
worker plus a 5-minute sweep on the ntreis-runner VM now start it seconds after
the text is Sent, 24 hours a day. The research half is plain facts per source
(comps, showing demand, buyer pool) instead of the customer brief, so one
closed sale is shown rather than held. Each of the five parts retries on its
own at 60 s, 300 s and 900 s, four tries in all, and the card says "Retrying"
while it waits. The card rebuilds itself on every outcome. Scoring view
seller_market.v_homework_slo, a stuck-job alert and a heartbeat alert watch
it. A deploy now restarts the worker between jobs, never during one. The ZIP
bug (the house number read as the ZIP) is fixed. Declined by Ry: an hourly
canary and a ZIP-day demand cache. Parked on RYR-586: a bulk-roll CAD miss
burns all four attempts; there is no per-job clock; cma-runner's own queue sits
outside the worker's lock; the alert's page-on-error path is unproven. RYR-573's
two open calls (delivery channel, Beverlei drill) closed 2026-09-21 — see §Deal spine. Runbook:
docs/RUNBOOKS.md §Z.
Related: reference_showingtime_one_login — the demand half of every card goes through ShowingTime, which allows one live login per account.
Deal spine — live 2026-09-21 (RYR-604; RYR-605 wave 2 started)
One Postgres row per seller property — seller_ledger.public.deal, deal_id =
{person_id}:{normalized street} — opened the moment a lead is claimed. Every
rail hangs off that row: the Drive tree Customers/{Last} - {street}/ with
Internal/ (Ry-only: the homework card .html and the Quick CMA PDF are filed
here) and {street} - Home Sale/ (the only folder ever shared with a customer);
the FUB note "Deal folder: "; the journey step deal_folder_provisioned.
The trigger is the fast path; a 5-minute sweep (POST /deal-sweep) fills any
blank the trigger missed; every step claims before it acts, so running twice is
safe. One alarm ("a lead moved on without its Drive folder") pages Ry's phone;
a 7 AM readout text from claude@ says whether yesterday worked (a zero day still
texts — silence means broken). POST /deal-open back-fills a person who
predates the spine and is the by-hand drill. The NCS checklist is 3 human steps
now (the four the machine does were nested under "done automatically").
Canonical detail: ~/rylobasic/docs/RAILS.md §"Deal spine" and §"Deal
readout"; shape: docs/BUILD-PATTERNS.md §3e; spec: Linear RYR-604 document.
Wave 2 (RYR-605): heal-before-send SHIPPED 2026-09-21 (fub_session.py inside
reinquiry_send, claim namespace fub.reauth, MR !3548). Two more steps went
LIVE 22:03Z 2026-09-21 (MR !3570, Ry's call, no second dark morning): the
Meeting Game Plan email (#6 — agenda_email.py, template
meeting_game_plan_v1, scheduler pos-pipeline-agenda-email 07:30 CT, deal
columns agenda_email_at + agenda_message_id, claim deal.agenda,
AGENDA_EMAIL_SEND_ENABLED=1, FLAG_AGENDA_EMAIL=pilot) and the morning-of
travel blocks (#7 — travel_blocks.py + routes_client.py +
calendar_writer.py, two solo events on [email protected], scheduler
pos-pipeline-travel-blocks 07:30 CT, deal columns travel_blocks_at +
travel_out_event_id + travel_back_event_id, claim deal.travel,
FLAG_TRAVEL_BLOCKS=pilot, no send switch by design — nothing leaves the
building). Everything outward is scoped to FUB user 418 via
lib/acting_identity.py (MRs !3549/!3551). Ten dependency-review fixes landed
the same day (!3566 + !3568: switch read before the claim, is_deleted on both
consult queries, live FUB re-read before acting, heal timeout keeps the send
claim, once-per-day dark log). Still open: the pond drill (#1), the booking
trigger (#3), the nudge drainer (#4b-d), the RYR-604 definition-of-done walk
on a real lead. First real 07:30 run is the next morning with a consult.