Skip to content

Why Reverse Transitions Need Reasons

When a lead moves backwards in the pipeline — COMMITTED → QUALIFIED because a buyer’s agreement fell apart, IN_CONTRACT → QUALIFIED because a contract got voided, NEW → TRASHED because the contact data turned out to be junk — the system requires you to pick a reason code at the moment of the transition. You can’t move the card without it.

This is intentional. Forward transitions are cheap to interpret (“they signed the buyer’s agreement, of course they’re now COMMITTED”). Reverse transitions carry information that disappears if you don’t capture it at the moment it’s true.

This page is the argument for why the reason-code requirement is the right design.

From → ToRequired reason codeWhat it represents
COMMITTED → QUALIFIEDdeal_collapsedBuyer’s agreement signed, then fell apart before contract.
IN_CONTRACT → QUALIFIEDcontract_voidedContract executed, then voided — financing failed, inspection killed it, mutual release, cold feet.
NEW → TRASHEDbogus_contact_detectedThe contact data turned out to be junk.
CONTACTING → TRASHEDbogus_contact_detectedDiscovered mid-outreach that the contact data is bad.

The state machine itself enforces this — the transition will fail if you try to do it without a reason code. There’s no opt-out, no silent demotion, no “I’ll add the note later.”

In a CRM without the requirement, here’s what happens in practice. A deal collapses. The agent feels bad about it. They move the card back to a search column. They don’t write anything down because they don’t want to dwell on it. A week later, nobody can remember whether the deal fell apart because of financing, an inspection issue, the buyer changing their mind, or something with the listing side.

Three months later, the broker is reviewing the quarter. They notice that ten deals went COMMITTED → QUALIFIED. They want to know whether to invest in a financing partnership, retrain on inspection negotiation, or improve buyer qualification.

They have nothing to go on. The cards moved; the reasons didn’t. The data that would have answered the question is gone — not because nobody knew it at the time, but because nobody wrote it down at the moment they knew it.

The reason-code requirement is the system putting its foot down: you don’t get to move the card without saying why. It’s enforcement of the rule that the moment of transition is the only moment the reason is reliably knowable.

The instinct that deal collapse is a failure to be hidden is the wrong instinct. Deal collapse is a fact about the market, about the lead, about your process — and depending on the pattern, about something the brokerage can change.

Consider three months of COMMITTED → QUALIFIED reasons:

  • 60% deal_collapsed: buyer_financing_fell_through
  • 20% deal_collapsed: buyer_cold_feet
  • 15% deal_collapsed: listing_pulled_or_other_party_backed_out
  • 5% deal_collapsed: other

That’s a story. The story says: most of your buyer collapses are financing. The intervention that moves the needle isn’t more aggressive qualification or faster offer turnaround — it’s getting buyers to a lender earlier, or partnering with a lender who handles edge cases better.

Without reason codes, you’d have ten collapsed deals and no diagnosis. With reason codes, you have a directed-improvement opportunity.

The same logic applies to IN_CONTRACT → QUALIFIED voids. If 70% are inspection-driven, that’s different intelligence than if 70% are appraisal-driven.

The actor and reason code are different things

Section titled “The actor and reason code are different things”

The actor on a reverse transition is you — humans make the call on whether a deal collapsed, not Scribe. The reason code is the categorization of why.

That separation matters because:

  • The actor is who. The reason code is what.
  • The actor is one of a small set (each agent, plus admins). The reason code is one of a controlled set (financing, inspection, mutual release, etc.).
  • Aggregations work on reason codes; accountability works on actors. Both surfaces exist.

When you add a free-text reason on top of the reason code (“buyer’s job offer fell through during underwriting”), that’s the third layer — the narrative. The reason code makes it filterable; the narrative makes it readable. You can have one without the other, but both is better.

NEW → TRASHED and CONTACTING → TRASHED aren’t demotions in the deal-collapse sense — they’re disposition decisions. So why the same requirement?

Because future-you may need to undo the trash. If a teammate trashed a lead two months ago and you’re now talking to that person on the phone (their number was fine, the original agent misdialed), you’d like to know why they ended up in TRASHED. bogus_contact_detected plus a free-text note (“phone rang to wrong person, never tried email”) tells you exactly what to verify before reactivating.

The reason isn’t accusatory. It’s the breadcrumb that makes recovery possible.

What “deal collapse as signal” looks like in practice

Section titled “What “deal collapse as signal” looks like in practice”

A few patterns the reason-code data surfaces over time, if the team uses the system honestly:

PatternWhat it suggests
Financing collapses cluster around a specific lenderStop steering buyers there, or have a conversation with the lender.
Inspection collapses cluster around a specific neighborhood or price pointOlder inventory; pre-emptively recommend inspections earlier in the offer process.
Cold-feet collapses cluster around first-time buyersAdd a “what to expect during escrow” conversation before the buyer’s agreement.
Mutual-release rate is climbingThe market shifted; buyers have more leverage to walk. Adjust offer strategy.
One agent has 3× the average collapse rateConversation with the agent about qualification practices.

None of those are visible without the reason codes. All of them are actionable when the reason codes are there.

The flip side: agents shouldn’t game the reasons

Section titled “The flip side: agents shouldn’t game the reasons”

The reason code list is short on purpose. It’s not a place to put a wall of free-text excuses or to invent categories that hide what really happened. If the deal collapsed because the buyer ghosted, that’s deal_collapsed: buyer_ghosted (or whatever the controlled list of reasons is at the time), with the free-text reason filling in specifics.

Two things to avoid:

  • Picking the most flattering reason instead of the most accurate. “Deal collapsed due to market conditions” when the actual cause was a failed inspection negotiation degrades the dataset for everyone.
  • Reaching for other when one of the named reasons fits. other should mean the categorization is genuinely outside the current list, not I didn’t want to think about which one to pick. If you find yourself picking other often, that’s feedback that the reason list needs to expand.

The reason code matters more than the immediate emotional comfort of softening the entry.

What the system does NOT do with the reason

Section titled “What the system does NOT do with the reason”

Reason codes are stored on the event row, surfaced in the timeline, and queryable for reports. They are not used to:

  • Penalize agents algorithmically.
  • Auto-route the recovered lead differently based on the reason.
  • Block future state transitions.

The reason exists to be read — by you, by your broker, by future-you trying to figure out what happened. It’s data for humans to interpret, not a control surface.

Reverse transitions are the most analytically valuable events in the pipeline. They’re the moments where the system would otherwise lose information — agents are emotionally inclined to move past them, the cards involved come with embarrassment, and “I’ll write it down later” is a promise that gets broken.

Requiring the reason code at the moment of the transition is the system saying: this information is too valuable to trust to “later.” Capture it now, when you know it, in a controlled form that aggregates to insight.

The reason isn’t punishment. It’s the most useful thing about the move.