Onboarding Decision Tree — the routing brain

The three walkthroughs, collapsed into one branching logic: from "someone arrives" down to the exact next question and close. Two things at once — a tree the team reads, and the programmable backbone for the technical mapping.

Perch · CRO cockpit · Jun 25 2026 · synthesizes Squires · CVE · journey-map · violet = signal source (a swarm agent)

The rule that makes it smart: every gate consumes a signal the research swarm already resolved, so we only ever ask what enrichment couldn't infer. Each branch narrows the path; nothing is a dead or dumb step; every gate has a graceful fallback when confidence is low. Ask → confirm → never re-ask.

The shape — four routes (cold/warm × self-serve/white-glove)

⚡ Self-serve  (<$10M · agent closes)
🤝 White-glove  (M/L · human closes)
❄ Cold
we know nothing
Stranger, small
Email is the trigger → enrich → confirm → agent runs the wow → trial→card. ~2 asks.
→ Squires (cold) ↗
Stranger, big — outbound
Agents build the battle pack → SDR reaches out armed → AE insight call → MEDDPICC.
→ CVE ↗
🔥 Warm
PLG · we know them
Known, small
Enrichment pre-ran. Zero asks (maybe 1 role tap) → straight to the board → agent closes.
→ Squires (warm) ↗
Known, big — inbound / expand
Agents pre-armed before contact; AE walks in fully briefed. Often a seat expanding to a dept.
→ CVE (warm variant) ↗

The tree — gates from arrival to close

Do we already know them?reads: entry payload · src: PLG capture / channel
🔥 Warm
Have email + name (maybe role). No email ask; enrichment pre-ran before arrival.
❄ Cold
Anonymous. Email is the one ask; enrichment fires after, on the critical path.
Fallback: "warm" but identity stale/unverified → soft-confirm instead of assuming.
sets identity.known · identity.{email,name,role?}
Enrich — resolve the profilereads: email domain + public web · src: 6-agent swarm
The swarm
Domain→site · Classifier · Size · Role · Project-finder · Network-seeder → one profile.
Confidence-scored
Each field carries a confidence. High → assert (confirm). Low → ask that one field.
Fallback (the smart bit): thin data → don't guess; ask only the unresolved fields. ~100% bar — a wrong pre-fill is worse than a blank.
sets profile.{company,type,size,role,trade,pursuits[],network[],confidence}
What kind of account?reads: profile.type · src: Business classifier
GC (contractor)
Picks sectors. Pipeline/portfolio surfaces.
Sub (sub_contractor)
Picks a trade → routes through G5.
Homeowner (consumer)
Different product (marketplace / milestones). Out of this funnel's scope.
Fallback: ambiguous → one tap "GC / Sub / Homeowner" (the only structural question we ever force).
sets profile.type ∈ {gc, sub, ho}
Which track? (size / ACV)reads: profile.size + modeled ACV · src: Size estimator
⚡ Self-serve
<$10M. Agent is the salesperson — closes trial→card in-flow.
🤝 White-glove · mid
$10–100M sub / $10–500M GC. Land a seat, expand to the dept.
🤝 White-glove · enterprise
$100M+ sub / $500M+ GC. Outbound, exec buyer, full MEDDPICC.
Fallback: revenue vs ACV disagree → ACV wins (open Q). Borderline → start self-serve, flag for sales.
sets route.track ∈ {self_serve, wg_mid, wg_enterprise}
Who landed? → the wow + surfacereads: profile.role · src: Role resolver
Estimator
Takeoff wow (Sarah) · Jobs. "What are you bidding this week?"
Owner / Exec
Portfolio + margin (Tom · Analytics). "Where did you lose your last 5 bids?"
PM / PE
Board + RFIs (Carlos · Network). "Your open RFIs + at-risk dates."
Foreman / Field
Route OUT of chat → Field Ops / mobile. Different door entirely.
Fallback: role unknown → the one allowed ask (warm = a tap; cold = captured at confirm).
sets route.persona ∈ {estimator, owner_exec, pm, field} · route.surface
Which trade? (subs only)reads: profile.trade · src: Classifier · 34 canonical
Counts — e.g. Electrical
/electrical · device/gear counts + lead-time flag.
Volume — e.g. Concrete
/concrete · CY + formwork SF + rebar tons.
Area — e.g. Drywall
/drywall · wall area by type + LF of track.
Fallback: trade unclear → generic sub lander, ask trade. (GC skips this gate.)
sets trade.{lander, takeoff_recipe, value_framing}
Compose the next questionderived: persona × size × trade
The conversion lever
One motivating ask that reveals $ AND pulls real data in. This is the line the team signs off on per cell.
Note: not a branch — a template filled from the gates above. The single highest-leverage string in the whole flow.
sets next_question (string template)
How do we close?reads: route.track
⚡ In-flow
Self-serve → agent closes: trial auto-starts → card after the wow. One session.
🤝 AE + MEDDPICC
White-glove → agents arm the AE → MEDDPICC → annual enterprise contract + migration.
Fallback: self-serve stalls or expands past threshold → hand off to white-glove (assisted).
sets close.motion ∈ {in_flow_card, ae_meddpicc}

Four routes traced through the gates

❄ Cold · Self-serve — Squires (cold)
G0 Cold G1 enrich after email G2 GC G3 <$10M · self-serve G4 owner G6 "which is worth winning?" G7 trial→card
open walkthrough (toggle cold) ↗
🔥 Warm · Self-serve — Squires (warm)
G0 Warm (have email+name) G1 pre-enriched G2 GC G3 self-serve G4 owner (role known → 0 asks) G7 agent closes
open walkthrough (toggle warm) ↗
❄ Cold · White-glove — CVE (outbound)
G0 Cold (target account) G1 deep swarm → battle pack G2 Sub G3 $100M+ · enterprise G4 VP Precon G5 Electrical G7 AE + MEDDPICC
open walkthrough ↗
🔥 Warm · White-glove — CVE (inbound / expand)
G0 Warm (a seat already in) G1 pre-armed G3 expand: seat → dept G4 estimator → champion G7 AE + MEDDPICC
open walkthrough ↗

The same tree, as a spec — for the technical mapping

Each gate as a programmable unit. This is the backbone Brock asked for — wire a state machine + events onto these, and the data model is the union of the variables set.

GateDecisionReadsSourceSetsFallback
G0Known already?entry payloadPLG capture / channelidentity.knownstale → soft-confirm
G1Enrich profileemail domain + web6-agent swarmprofile{…} + confidencelow conf → ask that field only
G2Account typeprofile.typeClassifiertype∈{gc,sub,ho}ambiguous → 1 tap
G3Tracksize + ACVSize estimatortrack∈{self_serve,wg_mid,wg_ent}conflict → ACV wins
G4Persona / surfaceprofile.roleRole resolverpersona, surfaceunknown → 1 ask; field → Field Ops
G5Trade (sub)profile.tradeClassifiertrade{lander,recipe,framing}unclear → generic + ask
G6Next questionpersona×size×tradederivednext_question
G7Close motionroute.trackderivedclose∈{in_flow_card,ae_meddpicc}stall/expand → hand to WG

Next for the technical mapping: a state machine over G0–G7 (states + transitions + events per gate), the data model (= union of the sets column), and the swarm as real services behind G1. This page is the control flow; those are the implementation.