Buyer Blast Process Hub
This hub covers the engine-level mechanics of the 4-channel buyer blast system. It is the technical deep-dive companion to dispo-lifecycle, which covers the lifecycle orchestration. Read this hub when you need to understand per-channel scripts, InvestorBase scoring details, dedup logic, or failure recovery for the blast system. Skill wrapper: dispo-blast.
⚠️ NEVER bypass —dry-run
All blast commands MUST include --dry-run unless Henry has given explicit blast authorization for that deal in this session. Live blasts are irreversible.
Quick reference
| Field | Value |
|---|---|
| Stages | Pre-blast preview → 4 history checks → Channel coordination → Per-channel send → Post-blast audit |
| Primary agent | _summary |
| Supporting agents | _summary (IB scoring), _summary (reply routing) |
| Agent handoff chain | dispo (blast coordinator) → atlas (IB score) → dispo-send.js → SalesMsg/OpenPhone → aurora (inbound replies) |
| Compliance gates list | defer to compliance-gates |
| Skills invoked | dispo-blast |
| Success metrics | Blast delivery rate; reply rate per channel; IB score distribution; days-to-offer |
| Cost per stage | Preview: ~0.01 × count; Channel 2 CRMLS: same; Channel 4 PropStream: same |
| Throughput | Up to 200 recipients per channel per blast; w4-broadcast hits all active deals weekly |
| Last run result | Query: SELECT * FROM ib_blast_history ORDER BY created_at DESC LIMIT 20 |
| Failure modes | 0 matched (threshold), 429 from carrier, CRMLS auth fail, PropStream quota, suppression miss |
Architecture
HubSpot dispo deal (status: dispositioning) OR scheduled showing
│
▼
[blast-preview.js] — estimated count, cost, dedup hits (always run first)
│
▼
[dispo-blast-engine.js] — unified 4-channel coordinator
│
├─ Channel 1: Showing-day blast
│ └─ [showing-blast-generic.js] / [showing-blast-compiled.js]
│ └─ Cohort: ALL prior buyers + watchlist tagged 'buyer' in HubSpot
│
├─ Channel 2: CRMLS agents
│ └─ [dispo-crmls-agent-blast.js]
│ └─ Targets: agents who sold in same zip + price band recently
│
├─ Channel 3: InvestorBase end-buyers
│ └─ [dispo-investorbase-blast.js]
│ └─ [ib-blast-scorer.js] — fit score per buyer (threshold ≥60)
│ └─ [ib-blast-history.js] — 4-check dedup
│ └─ [ib-blast-message.js] — channel-specific message builder
│
├─ Channel 4: PropStream flippers (cold)
│ └─ [dispo-propstream-blast.js]
│ └─ Targets: flippers in market with ≥3 recent purchases
│
▼
[dispo-send.js] — shared send chokepoint (same as acquisitions-outreach)
│
▼
SalesMsg (port 18793) / OpenPhone (port 18792)
Channel details
Channel 1 — Showing-day blast
Cohort: all HubSpot contacts tagged 'buyer' + watchlist.
Dedup: 24h window before showing date.
# Single deal showing announcement
node /home/opsadmin/.openclaw/workspace/scripts/showing-blast-generic.js --deal-id=X --dry-run
# Multi-deal weekly compiled blast
node /home/opsadmin/.openclaw/workspace/scripts/showing-blast-compiled.js --week=2026-W17 --dry-runChannel 2 — CRMLS agents
Cohort: LA-area agents with recent sales in same zip + price band.
Dedup: 30d per agent.
Auth: CRMLS API token → op://Aurora/crmls/api-token
node /home/opsadmin/.openclaw/workspace/scripts/dispo-crmls-agent-blast.js \
--deal-id=X --dry-runFailure mode: CRMLS API auth fail → refresh token from 1Password, check master.env CRMLS section.
Channel 3 — InvestorBase end-buyers
Cohort: InvestorBase platform buyers with fit score ≥60. Dedup: 7d per (deal, buyer) pair.
node /home/opsadmin/.openclaw/workspace/scripts/dispo-investorbase-blast.js \
--deal-id=X --min-score=60 --dry-runIB fit scoring — ib-blast-scorer.js {#IB-scoring}
| Factor | Weight | Threshold |
|---|---|---|
| Zip match | 25% | exact zip OR adjacent zip |
| Bed count | 15% | ±1 bed |
| Price band | 20% | within ±20% of asking |
| Condition pref | 20% | matches buyer’s stated rehab tolerance |
| Recent activity | 10% | bought in last 90d |
| Deal velocity | 10% | hot deal (views > 100 in 24h) |
Score ≥60 → blast. Below threshold → logged, skipped.
Default --min-score=60. Lower to 50 if 0 buyers matched and deal characteristics are broad.
Channel 4 — PropStream flippers (cold)
Cohort: cold flippers in market with ≥3 recent purchases. Dedup: 90d per flipper.
node /home/opsadmin/.openclaw/workspace/scripts/dispo-propstream-blast.js \
--deal-id=X --zip=90210 --dry-runFailure mode: PropStream rate limit → daily quota hit; retry next day. Check quota in master.env PropStream section.
Pre-blast history checks (4 checks per buyer)
All 4 checks run via ib-blast-history.js before every send:
- Already-blasted — sent this exact (deal, buyer) in last 7d?
- Recent-engagement — buyer replied to ANY blast in last 14d?
- Saturation — ≥3 blasts to this buyer in last 7d?
- Suppression — buyer in
messaging_suppressiontable?
Any check fails → blast skipped, reason written to ib_blast_history.
Weekly w4 broadcast
Every Wednesday AM: all active dispo deals → all buyer cohorts.
node /home/opsadmin/.openclaw/workspace/scripts/w4-broadcast-blast.js --dry-runPre-blast preview (always run first)
node -e "
const p = require('/home/opsadmin/.openclaw/workspace/scripts/lib/blast-preview.js');
p.preview({ dealId: 'DEAL_ID', channels: [1,2,3,4] }).then(r => console.log(JSON.stringify(r, null, 2)));
"Returns: estimated recipient count, projected cost, dedup hit count per channel.
Post-blast audit
node /home/opsadmin/.openclaw/workspace/scripts/audit-blast-responses.js --deal-id=XReturns: buyer replies, A-G classification per reply, HubSpot stage transitions triggered.
Failure modes
| Symptom | Cause | Recovery |
|---|---|---|
0 buyers matched for Channel 3 | IB score threshold too high | Lower --min-score; check IB buyer database freshness |
429 from SalesMsg/OpenPhone | Line saturation | Lower --limit-per-channel; rotate lines |
CRMLS API auth fail | Token rotated | Refresh from 1Password; check master.env CRMLS section |
PropStream rate limit | Daily quota hit | Retry tomorrow; monitor quota |
| Blast sent to suppressed buyer | messaging_suppression check missed | Audit messaging_suppression table; surface for manual review |
| Inbound replies not routing | Webhook handler down | Check acquisitions-followup; systemctl --user status openphone-webhook salesmsg-webhook |
| Channel 1 showing blast duplicate | Dedup window too short | Verify 24h dedup in ib_blast_history; check showing date proximity |
Components
workspace/scripts/dispo-blast-engine.js— unified 4-channel coordinatorworkspace/scripts/dispo-crmls-agent-blast.js— Channel 2 (CRMLS)workspace/scripts/dispo-investorbase-blast.js— Channel 3 (IB)workspace/scripts/dispo-propstream-blast.js— Channel 4 (PropStream)workspace/scripts/showing-blast-generic.js— Channel 1 (single showing)workspace/scripts/showing-blast-compiled.js— Channel 1 (weekly compiled)workspace/scripts/w4-broadcast-blast.js— weekly inventory broadcastworkspace/scripts/audit-blast-responses.js— post-blast auditworkspace/scripts/lib/investorbase/ib-blast-scorer.js— fit scoringworkspace/scripts/lib/investorbase/ib-blast-history.js— 4-check dedupworkspace/scripts/lib/investorbase/ib-blast-message.js— message builderworkspace/scripts/lib/blast-preview.js— pre-blast statsworkspace/scripts/dispo-send.js— shared send chokepoint
Cross-links
Agents that touch this
- _summary — blast coordinator
- _summary — IB scoring enrichment
- _summary — inbound buyer reply routing
Skills that invoke this
- dispo-blast — canonical skill wrapper for all blast commands
Plans that govern this
- openclaw-fragmentation-fix-2026-05-01 — governance + G-FAILED-SERVICE-MTTR
Feedback rules
- feedback_dispo_scorer_rules — IB scoring weight rules
- feedback_blast_inbox_required — blast must land in inbox not spam
- feedback_sms_160_char_at_scale — 160-char SMS limit at scale
- feedback_no_em_dash — no em-dashes in outbound
- feedback_salesmsg_mention_syntax — SalesMsg @mention syntax
- feedback_never_send_without_auth — live blast requires explicit Henry auth
KB / source docs
System maps
- vm-dispo-blast-flow — blast data flow diagram
Related cluster
- dispo-lifecycle — lifecycle orchestration (reads this hub for mechanics)
- compliance-gates — pre-send compliance gates
- acquisitions-lifecycle — upstream (Category F hand-off triggers blast)
- salesmsg — SMS transport layer
- openphone-quo — SMS transport (alt)
- investorlift — deal source + IB platform connection
Open issues / TODOs
- 10DLC A2P repeat-denial is BLOCKING all SMS blast channels. See osil-twilio-10dlc-resubmission-2026-05-03 B14.
- Channel 4 PropStream daily quota not tracked in monitoring. Add to cost-tracking open issues.
- CRMLS agent blast result rate needs baseline measurement (no historical data in
ib_blast_history).
Recent activity
- 2026-05-03: hub created by W1-S9
- 2026-05-03: 4-channel blast mechanics, IB scoring, pre-blast checks, all commands documented