← Back to brief

project froelich incident 2026-04-22

memory · project_froelich_incident_2026-04-22.md

What happened

On 2026-04-22 at 3:44 PM MDT, a HubSpot sequence (likely 303630905 or 303662164, both deleted later that day) sent a cold-intro email titled "Quick question about your Grand County property from Joseph Bowens" to froelich.john@gmail.com. The email used cold-outreach language ("I came across your place and wanted to introduce myself") and was delivered while John Froelich was already an active SkyRun customer (owner of R309421, 106 Preserve Way, Winter Park).

Sara Froelich (his wife, at sara.froelich@ccc-co.org on the same merged HS contact) saw the email and reached out to Rachel Scott directly to flag it.

Root causes (multiple compounding factors)

1. Inconsistent HS state on John's record:
- lifecyclestage = customer ✓ (correct — he IS a customer)
- Contact Type = Homeowner
- Relationship to Property = Current Owner - Primary Decision Maker
- BUT Lead Status = "New | Need to Contact" ❌ (wrong — inconsistent)
- The HS sequence filter keyed on Lead Status, missing the owner-state signals

2. HS sequence filter gap: the sequences (303630905, 303662164) enrolled by hs_lead_status = "New | Need to Contact" without lifecyclestage != customer as a required exclusion

3. Merge-time enrollment not cleaned: on Apr 14, John's two contact records were merged. The merge did not re-evaluate sequence eligibility on the resulting merged record.

4. Stale signature in sequence template: the email contained "SkyRun Vacation Rentals / Winter Park, Colorado and Vermont" — referencing Vermont despite VT being on hold. This is a separate issue (template not updated) that compounded the bad look.

5. No pre-send current-owner guardrail in our system: even though our own tasks (BV auto-load, live-ea, DQ check) could have caught this, none had a lifecyclestage=customer check before sending / drafting / enrolling.

Guardrails added 2026-04-22

1. is_current_owner(email) canonical check

At ~/Library/Application Support/SkyRun/current_owner_check.md. Single JS function that queries HS for email=X AND (lifecyclestage=customer OR contact_type=Homeowner OR relationship_to_the_property contains "Current Owner"). Called by every cold-outreach task.

2. daily-beenverified-enrichment Step 7b gate

Before pushing any BV-enriched lead to a SmartLead campaign, run the check. Skip current owners. Log skipped list in daily report.

3. daily-data-quality-check new Step 5G

Nightly audit: pull all SmartLead enrollees, run the check against each. Any current owner currently enrolled = RED flag + auto-remove attempt. Logged in daily DQ report.

4. live-ea new Step 4c

Before drafting any reply, run the check on the recipient. Current owners get routed to "warm operational" drafting or flagged for human review. Cold-intro language is FORBIDDEN for current owners with explicit pattern-match list.

Manual follow-ups Joseph should do

1. Update John's HS record: Lead Status should match lifecyclestage=customer. Current inconsistency ("Customer" + "New | Need to Contact") is what let the sequence fire.
2. Audit all current owners in HS for the same inconsistency: contacts where lifecyclestage=customer AND hs_lead_status != "Customer" — these are all potential future leak candidates.
3. Rachel has already heard about the Froelich case — no apology needed per Joseph (Sara reached out directly to Rachel).
4. Update sequence templates — all surviving sequence copy references "Winter Park, Colorado and Vermont" in signature. Need to either edit or delete. (HS sequences are deleted now, but this lesson applies to any future templating.)

Lessons for future outbound systems

Wiring status