Sales Motion (Seller)

Status
in-flight
Owner
Ryan Colston
Started
2026-04-21
Target launch
2026-05-01

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.

Next 3 actions

  1. 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, the Customers/ tree, the FUB note, the journey step; trash the tree.
  2. Booking becomes a trigger (RYR-605 #3): route the FUB "Customer Booked" note → stamp booked_at + TPID, share Home Sale (dark flag first), park the kickoff draft.
  3. 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

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.

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.

3. Static + per-subscriber data (DONE for MVP)

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)

6. Decisions still open

7. ISA prep (parallel to Kit work)

📁 Edit the file in place: ~/platform/projects/recruiting-appointment-setter/onboarding/dial-cadence-runbook.md

8. Phase E paste-and-wire

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:

Cloud Run service extension tasks (target: existing pos-fub service):

Other FUB UI work (separate from sync wiring):

10. Landing page placeholder

11. End-to-end test

12. Launch day (May 1)

References

Phase F backlog (post-launch)

Don't worry about these before May 1. Full prioritized list at gap-analysis.md section 3.


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.