Definitions & scoring reference
Reference

Definitions & scoring reference

Every number, tier, and label in Thunder Graph is computed by an explicit rule โ€” no black boxes. This page documents the exact math behind each score, the criteria behind every tier, and the verbatim AI prompts used to enrich data, so anyone new can understand precisely what a value means and why the machine made a decision.

Audience anyone using the platform Rule all scores are deterministic + inspectable AI role drafts & classifies; humans approve
Section 1

The data model

Thunder Graph tracks four kinds of records. Understanding the difference explains why some searches and scores apply to one but not another.

๐Ÿฆ

Firms (investors)

Investment firms โ€” VCs, PE funds, family offices, corporates. Each carries structured criteria (sectors, stages, check size, geography, thesis) that the matcher runs on. table: investors

๐Ÿข

Companies

Operating companies โ€” clients, targets, and portfolio companies. Firmographics (revenue, headcount, funding). table: companies

๐Ÿ‘ค

Contacts

People โ€” with a title, firm, location, personas, and a relationship warmth score. table: contacts

๐Ÿ”—

Organizations

The dedup layer that unifies firms and companies under one canonical name. Rebuilt nightly, so its ids are not stable โ€” durable records key on firm/contact identity instead. table: organizations

Why some contacts don't appear in "who do I know" searches. A natural-language network search is investor-anchored by default: a person surfaces only if they carry an investor persona or sit at a firm we track โ€” unless the search names a community (a curated tag like "PEF"), which lists all members regardless. "Who do I know" phrasing also adds a warmth floor (score โ‰ฅ 30). This keeps results signal-dense rather than dumping the whole contact list.

Section 2 ยท the one people ask about most

Warmth score

Warmth is a 0โ€“100 measure of how strong a relationship is, computed identically for every person and every firm from real interaction history (Gmail, Calendar, Fireflies meetings, HubSpot, WhatsApp, LinkedIn, Luma events). It is the sum of four components, each capturing a different dimension of a real relationship. graph/warmth.mjs ยท score-warmth.mjs

The four components (sum to 0โ€“100)

Recency0โ€“30
Frequency0โ€“30
Depth0โ€“25
Directionality0โ€“15

1 ยท Recency (0โ€“30) โ€” how recently did you last interact?

A straight-line decay over three years. A contact touched today scores the full 30; one last touched exactly three years ago scores 0. This deliberately long horizon lets genuinely strong but dormant relationships still surface across the team.

Formularecency = max(0, 30 ร— (1 โˆ’ days_since_last_touch / 1095))

e.g. last touch 6 months ago โ†’ 30 ร— (1 โˆ’ 182/1095) = 25.0. One year ago โ†’ 20.0. Two years ago โ†’ 10.0.

2 ยท Frequency (0โ€“30) โ€” how often, recently?

Counts interactions in the last 6 months (180 days), worth 6 points each, capped at 30. So five or more touches in six months maxes this component.

Formulafrequency = min(30, touches_in_last_180_days ร— 6)

3 ยท Depth (0โ€“25) โ€” was it substantive?

Not all contact is equal โ€” a meeting means far more than a one-line email. Depth is a weighted sum of interaction quality over the last 12 months, capped at 25.

Interaction typeDepth weightReading
Meeting (Fireflies / calendar)8the strongest signal of a real relationship
Luma event (checked in)5showed up to an event you hosted
Call ยท WhatsApp4direct, personal channel
LinkedIn message3light but intentional
Note ยท LinkedIn connect ยท event RSVP2weak signal of intent
Email1the baseline touch
Formuladepth = min(25, ฮฃ weight(each interaction in last 365 days))

4 ยท Directionality (0โ€“15) โ€” did they reach out to you?

An inbound message (them โ†’ you) is a much stronger signal than outbound alone. Reciprocity earns the most.

ConditionPoints
At least one inbound message+10
More than two inbound messages+3 more
At least one outbound message+2

Maximum 15. When warmth is derived from aggregate rollups (no per-message direction available), directionality is 0 โ€” the score is conservative rather than guessed.

The labels

The 0โ€“100 score maps to a label used everywhere in the UI:

LabelScore rangeMeaning
๐Ÿ”ฅ Hot80โ€“100active, deep, recent relationship
Warm55โ€“79a real relationship, maintained
Lukewarm30โ€“54some genuine history
Cold10โ€“29thin โ€” a touch or two
Dormant0โ€“9little or no interaction on record

Whose relationship? โ€” the warmth owner

A contact's warmth is the maximum over every Thunder teammate of that teammate's own interaction history with the person. The teammate who produces the max is the warmth owner โ€” the best intro path, shown as "best intro via โ€ฆ" on the record. So warmth answers two questions at once: how strong is this relationship and who on our team owns it.

Firm-level warmth

Firm warmthorg_warmth = max( strongest contact at the firm , strongest direct firm-level connection )

A firm is as warm as its warmest person โ€” or a direct firm-level relationship edge, whichever is stronger.

Two details that keep it honest

  • De-duplication. HubSpot auto-logs Gmail and Calendar, so one real email or meeting can appear 2โ€“3 times across sources. Before scoring, same-type events within a short window (email/call โ‰ค 3 min, meeting โ‰ค 30 min) are merged, so Frequency and Depth reflect real interactions, not double-counts.
  • Durable community bonuses. Some cohorts carry a manual boost that survives the nightly recompute, added on top of any interaction score: Post-Exit Founders (PEF) +20 ยท $100M Exits podcast guest +50. They stack โ€” warmth_bonus is the sum of a contact's community tags, so a guest who is also a PEF member gets +70. A no-touch member floors at their bonus value; a touched member gets score + bonus, capped at 100.
โšก Worked example
  • A founder you met twice in the last quarter (2 meetings), exchanged 4 emails with, who emailed you first, last touch 3 weeks ago:
  • Recency = 30 ร— (1 โˆ’ 21/1095) โ‰ˆ 29.4 ยท Frequency = min(30, 6 ร— 6) = 30 ยท Depth = min(25, 2ร—8 + 4ร—1) = 20 ยท Directionality = 10 (inbound) + 2 (outbound) = 12
  • Total โ‰ˆ 91 โ†’ ๐Ÿ”ฅ Hot.
Section 3

Relevance & compatibility

When you run Find intros, every candidate firm gets a relevance score (0โ€“100) measuring how well the firm's investment criteria fit the company โ€” a faithful re-implementation of Thunder's production matching model over our mirrored data. graph/compatibility.mjs

Two lanes, two weight tables

A capital raise and a company sale are scored by different weight tables, because the signals that predict a good investor are not the signals that predict a good acquirer. The mandate's intent picks the lane automatically โ€” you never choose it.

LaneUsed whenDominant signals
Raise defaultraise_capital mandates (venture, growth, buyout equity, debt) declared criteria fit โ€” sector + funding stage
Sell-side ma_sellbe_acquired mandates โ€” a full or partial sale demonstrated behaviour โ€” have they bought companies, can they afford this one, do they take this stake

Why they differ (2026-08-03): funding stage is a VC-round concept driven by a dropdown that sell-side clients leave blank, so on a sale the dominant component scored a flat 0 for everyone. The sell-side lane replaces it with evidence a banker would actually ask for.

Raise lane โ€” the eleven components (raw points)

Each criterion contributes raw points. Sector dominates; the rest refine. compatibility.mjs ยท W

Sector+40 / โˆ’40
Funding stage22
Acquisition alignment+20 / โˆ’20
Product stage15 / โˆ’3
Data confidenceโˆ’15
Geography+8 / โˆ’3
Business model5
Check size+5 / โˆ’2
Revenue range4
Tags3
Revenue streams2

Five of these can go negative: a thesis mismatch actively counts against a firm. Sector โˆ’40 (no thematic overlap at all), acquisition alignment โˆ’20 (disqualified type), data confidence โˆ’15 (a record with no web domain or no firm type โ€” usually not a firm at all), product stage โˆ’3, geography โˆ’3 (they list geographies and none match), check size โˆ’2. A profitable, non-growing company also loses a further 6 product-stage points against a pure VC. Product stage can reach 18 โ€” an advanced product paired with an early capital stage earns +3 ("further along than the round implies").

Changed 2026-08-13 โ€” funding stage cut 40 โ†’ 22, and a stage miss now costs nothing. Two independent reviews of the same screening data reached this from opposite directions, and it was then measured against 430 human shortlist/dismiss decisions. Stage was the heaviest weight and bought almost no ordering: across the seven scored raise lists it was identical for every firm in four of them. Where it did vary, it pointed backwards โ€” on the only fully reviewed list, 27 of the 28 firms the team shortlisted were carrying the old โˆ’6 stage penalty. Sector is now the sole dominant signal, and the VC-vs-PE-vs-debt separation is handled where it belongs: the firm-type multiplier below, which zeroes an off-instrument firm outright rather than docking it 6 points.

Sell-side lane โ€” the fifteen components

The sell-side lane keeps every raise component (re-weighted) and adds five that only make sense when someone is buying the company. compatibility.mjs ยท W_MA

Sector+34 / โˆ’34
Acquisition capability+30 / โˆ’12
Control fit+22 / โˆ’13
EV capacityยฑ20
Acquisition alignment+18 / โˆ’18
Strategic overlap14
Deal contextยฑ10
Geography+8 / โˆ’3
Funding stage6
Product stage6
Check size ยท Business model5 each
Revenue range5
Tags ยท Revenue streams3 / 2
Sell-side-only componentWhat it measures
Acquisition capability 30Have they actually bought companies, and recently? 5+ deals in 36 months earns full marks, 1โ€“2 earns 65%, a firm that transacts but has never acquired earns 35%, and a firm with a record showing zero acquisitions is penalised. A deal closed within 12 months adds 3; nothing for 36 months subtracts 3.
Control fit 22Does the stake they take match the stake being sold? The minority-vs-majority separator: a growth fund that has only ever taken 20% is a poor fit for a full exit however well its sectors line up. Measured stake behaviour wins; declared stages, thesis focus tags, then firm type corroborate when we have no measured behaviour.
EV capacity ยฑ20Jason's 4ร— rule โ€” can they afford it? Capacity โ‰ฅ 4ร— the deal earns full marks, 1โ€“2ร— earns 15%, below half the deal is a full penalty. Capacity comes from market cap or enterprise value first, then the largest cheque they have actually written, and only last from a revenue proxy. Unknown capacity is neutral, never an exclusion.
Strategic overlap 14The bolt-on story: adjacent sectors, shared business model, shared revenue streams, shared geography. Deliberately double-counts signals that also score elsewhere โ€” for a sale, "sells the same way to the same customers" is the synergy thesis.
Deal context ยฑ10What the banker typed into the Context box. A buyer the client named gets the full +10 and is flagged a dream buyer; a name on the exclusion list gets โˆ’10. Otherwise: profitable + debt-free paired with a control buyer, no customer concentration paired with a proven acquirer, and price expectation matched against a distressed posture.

Sector is the gate

Sector is treated as the imperative signal, co-equal with funding stage. Any core (primary) sector overlap earns near-full credit; no thematic overlap at all is a โˆ’40 penalty (โˆ’34 on the sell-side lane, keeping the gate proportional to that lane's sector weight). Firms listing more than 12 sectors are treated as generalists and dampened โ€” down to half credit โ€” so a match has to be a specific theme, not a firm that "invests in everything." Secondary/adjacent sectors expand recall but count at 40% weight, never as a core match.

From raw points to a 0โ€“100 score

The summed raw points are squashed through a logistic (sigmoid) curve โ€” this compresses the extremes the way the production model does, so scores cluster meaningfully instead of spreading linearly. Each lane has its own midpoint, because the sell-side lane has a higher positive ceiling (~173 raw points vs ~147); reusing the raise midpoint saturated every decent buyer into the high 90s.

Sigmoidrelevance = 100 / (1 + e^(โˆ’0.05 ร— (raw_points โˆ’ midpoint))) // midpoint 35 on a raise ยท 85 on a sale ยท raw = midpoint โ†’ 50/100

The raise midpoint moved 45 โ†’ 35 on 2026-08-13, alongside the funding-stage cut. It is not a free parameter: it re-centres the squash so that removing 18 points of stage weight does not shift every client-visible score downward. Measured across the 1,446 firms on the seven scored raise lists, the median relevance is unchanged at 71.

The sell-side midpoint of 85 was calibrated by sweep, not guessed: at 85 a demonstrated control buyer with capacity lands ~97, a minority-only fund on a full-exit mandate ~61, a sub-scale strategic ~50, a firm with zero recorded acquisitions ~38, a disqualified VC ~15. It is a function of the weight table โ€” any weight change requires re-running the sweep. graph/compat-test.mjs

Firm-type weighting

The score is then multiplied by a firm-type weight (0โ€“1) set by the deal's intent. A firm that is the wrong type for the deal ("off-type", weight 0) is floored at 0.05 โ€” deep-demoted and sorted to the bottom, flagged, but never deleted (it may still be a useful sounding board). An unknown firm type is neutral: 0.5 on a raise, 0.2โ€“0.3 elsewhere. recommend.mjs ยท FIRMTYPE_WEIGHTS

On a raise, the weight is not set by intent alone โ€” it is set by the instrument the company selected at intake (venture equity, buyout equity, or debt). This is the real VC-vs-PE-vs-lender separator: a venture fund is not a weaker fit for a debt raise, it is no fit, so it scores 0 and is demoted out of the list rather than docked a few points.

Firm typeRaise ยท venture equityRaise ยท buyout equityRaise ยท debtBe acquiredAcquirePartner
Venture Capital Fund1.000000
Corporate VC1.00.600.801.0
Private Equity01.00.31.000
Family Office1.01.00.40.800.5
Syndicate1.000000
Accelerator1.000000.25
Private Credit00.31.000.80
Commercial Bank000.800.90
Incubator0.2500000.25

The debt column was retuned on 2026-08-13 from the curation record: family offices 0.7 โ†’ 0.4 and commercial banks 1.0 โ†’ 0.8. On the two debt mandates in the data, family offices were a third of the list and the reviewer dismissed 66 of the 67 they looked at. A family office does occasionally write private debt, so this is a demotion below the credit funds that do it routinely โ€” not a zero.

What relevance is NOT. The company's own quality/reputation score was deliberately removed from this engine โ€” fit drives relevance, not how "good" the company looks. And relevance is pure criteria fit: it contains zero relationship warmth (that's a separate signal, see next section).

Section 4

How results are ranked

The score is relevance and nothing else. Warmth and the owner path are computed for every firm and shown on each card, but they are never folded into the number.

Relevance scorescore = 1.0 ร— relevance + 0 ร— relationship + 0 ร— owner

This is a deliberate decision (2026-06-29): an earlier version blended in relationship warmth and the owner path, which buried genuinely relevant firms behind whoever we happened to know. Now the number answers one question โ€” "is this firm a fit for the deal?" โ€” and you sort or filter by warmth separately when you want to prioritize who's easiest to reach. graph/recommend.mjs

The list order is not just the score

Sorting purely by score put a well-documented generic buyer above a partner the client actually asked for, because the partner is privately held and loses on data richness. So the list applies four deterministic keys before the score โ€” a rule, not another round of weight tuning (2026-08-04):

#Sort keyWhy
1On-type before off-typewrong-type firms sink to the bottom whatever they score
2Fit tier โ€” ๐ŸŽฏ slam dunks, then possible fits, then everything elsemulti-dimensional confirmation outranks a high score on thin data
3Existing relationship โ€” a dream buyer the client named, then an ecosystem partner the seller is built on"a direct integration is more relevant, there is already a relationship"
4Relevance score, then warmth, then confidencethe tie-breakers within a tier

Keys 3 and 4 are the only place relationship data touches ordering, and only as a tie-break inside a tier โ€” it never changes the score itself.

Section 5

Fit tiers

Because a raw relevance score can look high on thin data, candidates are also sorted into fit tiers that require multi-dimensional confirmation โ€” a tier is never a single threshold. This is what the ๐ŸŽฏ / tier-2 badges on target-list cards mean.

TierEvery one of these must hold
๐ŸŽฏ Slam dunk (tier 1) firm-type weight โ‰ฅ 0.8 (clearly the right type) ยท a core sector match (not just an adjacent one; if the company has 3+ core themes, at least 2 must match) ยท multi-component criteria confirmation โ€” raw points clear the lane's sigmoid midpoint (35 on a raise, 85 on a sale) ยท plus one lane-specific condition:
  • Raise: no funding-stage mismatch penalty.
  • Sale: positive acquisition alignment and non-negative EV capacity and non-negative control fit โ€” are they a real acquirer, can they afford it, do they take this stake? Stage is meaningless here: sellers leave the dropdown blank and corporate acquirers have no stage tags at all, so gating on it made tier 1 a function of a field nobody fills.
Two overrides promote straight to tier 1: a team ๐Ÿ‘ upvote (the team said so), and a dream buyer โ€” a firm the client named in the deal context is a slam dunk by definition.
Possible fit (tier 2) plausible firm type (weight โ‰ฅ 0.5) ยท any sector overlap ยท relevance โ‰ฅ 45. A real fit that's missing one slam-dunk condition.
Othereverything else, including off-type firms and โ€” on a sale โ€” any firm with a negative acquisition alignment. Collapsed behind a toggle, never mixed into the main list.

Tier 1 is criteria-driven, not score-threshold-driven: sparse firm tag data caps scores, so a hard relevance bar would make the top tier depend on data density instead of actual fit. The production match-score prior (which tends to make everything look 82โ€“100) can never mint a slam dunk by itself. graph/recommend.mjs

Section 6

Mandate verification

After matching, each top candidate is screened against the firm's own written thesis plus reality data (real ticket window, 36-month activity, true investor type from Inven) to answer: would this firm actually do this deal? Screening runs per lane, derived from the mandate's intent + financing type + structure. graph/verify-mandate.mjs

LaneMandate
ma_sellsell-side M&A โ€” full control sale
ma_sell_minorsell-side โ€” minority / partial stake
raise_ventureventure / growth equity raise
raise_buyoutbuyout / control equity raise
raise_debtdebt / credit financing

Hard reality checks run first with no LLM (e.g. a firm whose minimum ticket is $193M is excluded from a $60M deal instantly, for free). What survives goes to a Sonnet screen. Each firm gets a verdict:

โœ“ covers the firm's thesis + reality credibly cover this mandate   โœ— excludes a concrete reason it won't (auto-demoted to Other)   ? unclear not enough signal to decide

Verdicts cache for 60 days (invalidated when fresher reality data lands), keyed by firm + lane + deal-size bucket, so the same firm isn't re-screened across deals of the same shape.

Section 7

Origination score

The Origination engine surfaces companies that look like they're about to need a banker. Each prospect's score is an additive sum of independent signals โ€” the higher the score, the more reasons to reach out now. graph/originate.mjs

SignalPointsWhat it means
Warm path+30a warm contact (warmth โ‰ฅ 55) at the company โ€” we can actually reach them
Lukewarm path+18a lukewarm contact (warmth โ‰ฅ 30)
SEC Form D filed+25recently filed a raise โ†’ re-raise clock + M&A appetite
Pulse intent+20recent news mentioning raising / acquisition / sale exploration
Raise window+20seed/A/B stage + company 2โ€“8 years old โ†’ re-raise clock
$100M Exits podcast guest+15a pre-qualified founder with a warm hook
Scale fit+15revenue in the millions โ†’ transaction-sized
Form D officer in our network+10a named filer is already a contact
Scale fit (growth/profitable stage)+10later product stage, if revenue unknown

Every prospect card lists exactly which signals fired and why, so the score is always explainable โ€” never just a number.

Section 8

Learned ranker

The matcher improves over time by learning from real outcomes. Every recommendation stores the exact per-component scores that produced it (the "why-breakdown"), so when a firm later progresses down the funnel โ€” or passes โ€” we can measure which components actually separate winners from losers. graph/learn.mjs

Outcomes are weighted by depth

A closed deal tells us far more about a good match than a bare reply; an informed pass tells us more than silence. Each outcome is weighted by how far it got:

OutcomeWeightOutcomeWeight
Committed1.5Meeting0.7
Term sheet1.1NDA0.5
IOI1.0Responded0.3
Diligence0.9Passed (informed)โˆ’1.0
Materials sent0.8Passed (no response)โˆ’0.6
Dismissed before outreachโˆ’0.4

A dismissal during curation is the weakest negative in the set โ€” the market never saw the firm, so it reflects our judgment rather than theirs.

For each compatibility sub-weight it computes a magnitude-weighted lift โ€” how much higher that component scores among firms that progressed versus firms that passed โ€” and writes a proposal to nudge the weight. Nothing is applied automatically. A human reviews each proposal on the Portfolio tab and clicks Adopt or Reject; adopting applies a bounded step (at most ยฑ20% per adoption). The 100%-relevance ranking decision is never touched โ€” only the compatibility sub-weights inside relevance.

Section 9 ยท AI transparency

Personas & the AI prompts behind them

Every contact can carry one or more personas โ€” their professional role(s). A person can be several (a post-exit founder who now angel-invests is Founder + Angel). The canonical taxonomy:

Founder Operator Angel VC LP PE/Buyout Corporate/Strategic Advisor Banker Recruiter Service Provider Board Member

Personas are set in priority order: a human edit always wins; then a HubSpot self-selection ("What best describes you"); then AI inference. Provenance and a confidence value are stored on every contact so you can see where a label came from. graph/enrich.mjs

Prompt A โ€” normalize a HubSpot self-selection confidence 0.95

When a contact answered HubSpot's "What best describes you", the AI just maps their words to our taxonomy.

๐Ÿค– System prompt ยท Sonnet
You are a data normalizer. Map HubSpot "What best describes you"
selections to this canonical taxonomy:
Founder, Operator, Angel, VC, LP, PE/Buyout, Corporate/Strategic,
Advisor, Banker, Recruiter, Service Provider, Board Member.

Input may be: comma-separated, pipe-separated, JSON array, or free
text. Output ONLY a JSON array of canonical labels (exact
case-sensitive match). If empty or unmappable, return [].

Prompt B โ€” post-exit founder (PEF community) confidence 0.80

PEF members come with a rich roster profile (exit company/title/year, current status, industry). Because they founded and exited a company by definition, "Founder" always applies; the AI adds today's roles from their current-status text.

๐Ÿค– System prompt ยท Sonnet
You classify a post-exit founder's professional personas from their
community-roster profile. This person is a member of the "Post-Exit
Founders" (PEF) community โ€” they founded and exited (sold or took
public) a company, so "Founder" ALWAYS applies. Add any ADDITIONAL
personas their CURRENT activity clearly supports.
Canonical taxonomy (use exact labels): Founder, Operator, Angel, VC,
LP, PE/Buyout, Corporate/Strategic, Advisor, Banker, Recruiter,
Service Provider, Board Member.
Mapping guidance for the "current status" text:
- "VC", "investor", "fund", "general partner" => VC ; "angel",
  "angel investing" => Angel ; "LP", "limited partner" => LP.
- "advisor", "consultant", "consulting", "coaching", "fractional"
  => Advisor ; "board", "board member", "director" => Board Member.
- "operator", "CxO at", "operating", "running/building a company",
  "founded a new company" => Operator (and Founder already applies).
- "PE", "private equity", "buyout", "search fund", "acquisition
  entrepreneur" => PE/Buyout.
Only add a persona the text actually supports. Return ONLY a JSON
array of 1-4 canonical labels, ALWAYS including "Founder".
๐Ÿ“ฅ User message (example)
Exited: Parallel Markets Inc as CEO (2025)
Current status: Founded a New Company, VC / Investor
Industry: B2B SaaS, Fintech
Functional expertise: Product, GTM
Current title: (none)

โ†’ result: Founder Operator VC. "Founder" is guaranteed even if the model omits it.

Prompt C โ€” infer from minimal signals confidence 0.60

For everyone else, the AI infers conservatively from title + email domain + firm โ€” and returns nothing rather than guess when signals are too weak.

๐Ÿค– System prompt ยท Sonnet
You are a data analyst inferring professional roles from minimal
signals. Be conservative; only include personas you are reasonably
confident about.
๐Ÿ“ฅ User message
Infer role personas for this person.
Title: {title}
Email domain: {domain}
Firm: {firm}

Choose from: Founder, Operator, Angel, VC, LP, PE/Buyout,
Corporate/Strategic, Advisor, Banker, Recruiter, Service Provider,
Board Member.
Return a JSON array of 1-3 likely personas. If signals are too weak,
return [].
No wasted retries. If a classification fails or a contact has no usable signal (no title, firm, self-selection, or roster data), the attempt is recorded so the nightly job backs off (retries at most a few times, weeks apart) instead of re-trying a lost cause every night. Contacts with genuinely nothing to go on are routed out of the AI loop entirely and flagged for human tagging or a directory lookup.
Section 10

Focus tags

Some investment strategies aren't in the sector tree (a "search fund" isn't a sector). Focus tags capture those thesis concepts. An AI reads each firm's own written thesis and assigns tags from a fixed vocabulary โ€” only what the firm itself focuses on backing, not words that merely appear in the text. These power niche searches like "firms that back search funds". graph/enrich.mjs ยท search.mjs

๐Ÿค– System prompt ยท Sonnet
You tag investment firms with strategy/focus tags from this EXACT
vocabulary (never invent tags): search_funds,
entrepreneurship_through_acquisition, micro_pe, rollups,
buyouts_smb, b2b_saas, vertical_saas, marketplaces, deep_tech,
climate, defense, ai_native, cybersecurity, โ€ฆ (40+ tags).
Read each firm's own thesis text. Tag only what the FIRM ITSELF
focuses on investing in โ€” e.g. tag search_funds only if they BACK
search funds / searchers, not if the text merely mentions the words.
0-6 tags per firm; [] when nothing clearly applies.
Section 11 ยท AI transparency

Where AI is used โ€” and where it isn't

AI is used for language and classification tasks; all scoring math above is deterministic code, not an LLM. Models run on AWS Bedrock, tiered by task for cost and quality.

TierModelUsed for
DraftingClaude Opus 4.6client-facing intro emails, reply drafts, client reports (quality-critical, low volume)
MidClaude Sonnet 4.6profile extraction, persona & focus-tag classification, mandate screening, reply triage, natural-language search parsing
FastClaude Haiku 4.5bulk pulse / news summaries (simple, high volume)

The golden rule holds everywhere AI touches outbound: the machine drafts, a human clicks send. No email, stage change on a judgment call, or weight adjustment is ever applied without explicit human approval. Every AI-written value is stored with its source label ("ai" vs "human" vs "hubspot") and a confidence, and a human edit always wins and is never overwritten.

Section 12

Funnel stages

Once a firm is contacted for a live mandate, it moves through the investor process ladder. Every stage change writes an activity-log row โ€” that's the compliance audit trail.

StageMeaning
research โ†’ approved โ†’ queuedcuration: identified, shortlisted, queued for a wave
contacted โ†’ respondedoutreach sent; a reply came back
nda โ†’ meeting โ†’ materials_sentengaged: NDA, first meeting, deck/data sent
diligence โ†’ ioi โ†’ term_sheetprogressing: diligence, indication of interest, term sheet
committed ยท passed ยท dormantterminal: won, declined (with a reason), or gone quiet

A passed outcome records a reason from a fixed taxonomy (too early/late, sector fit, geo fit, check size, valuation, portfolio conflict, no capacity, process timing, no response) โ€” which feeds the learned ranker and the conversion analytics.

Section 13

Glossary

TermDefinition
Warmth ownerthe Thunder teammate with the strongest relationship to a contact โ€” the best intro path.
Off-typea firm of the wrong type for the deal's intent (e.g. a VC on a control-buyout mandate); deep-demoted to ~5% and sorted last.
Core vs expanded sectora core sector is one the user actually named; expanded sectors are synonym matches used for recall only, at reduced weight.
Scoring lanewhich weight table a mandate is scored with โ€” default (raise) or ma_sell (sale). Set by the mandate's intent, not chosen by hand.
Dream buyera firm the client named in the deal context. Scores the full deal-context weight and is promoted straight to tier 1 โ€” they asked for it.
Ecosystem partnera platform or integration the seller is built on. Not a score bonus: it sorts ahead of unrelated firms inside the same tier.
Acquisition capabilitysell-side only: evidence the firm has actually bought companies (deal count over 36 months, recency of the last close).
Control fitsell-side only: whether the stake the firm typically takes (majority vs minority) matches the stake being sold.
Data confidencea โˆ’15 demotion for a record we don't trust enough to rank: no web domain, or no firm type. Usually a sign the row is an operating company or a person filed as a firm. The fix is the Data review queue; this only stops such rows ranking meanwhile.
EV capacitysell-side only: what the buyer could plausibly pay โ€” market cap or enterprise value, else the largest cheque they've written, else a revenue proxy. Unknown is neutral.
Sweet spot / check sizea firm's typical single-investment size; the "range" is the set of check-size bands it invests across.
Mandatea signed client engagement with economics (retainer, success fee, exclusivity, target size).
Pulserecent public news about a firm or company, fetched live and summarized.
Community / list (contact tag)a curated people group (e.g. "PEF") โ€” a searchable dimension independent of investor status.
Firmographicsa company's structured facts (revenue, headcount, funding raised, founded year, ownership), sourced from Inven.
IOI / LOI / term sheetindication of interest โ†’ letter of intent โ†’ term sheet: escalating stages of buyer/investor commitment.

Thunder Graph โ€” every score on this page is produced by explicit, inspectable code. If a number ever looks wrong, it can be traced to the exact rule that produced it.

See also: Getting started ยท Release notes

Section 14

GTM events

Go-To-Market โ†’ Events productizes Thunder's private-event motion โ€” dinners (the founding case), breakfasts, roundtables, receptions (dinners.event_type; the invitation copy follows the type). Each event is a host engagement (engagements.intent = host_dinner, excluded from every deal list) plus a dinners row carrying date, city, metro (the hard location gate โ€” a London dinner only considers London people), venue, theme, the ideal-attendee description, an optional Luma link, and priority clients (linked client engagements whose matched investors get a boost on the invite list).

Invite-list score (0โ€“100), four components โ€” computed by graph/dinner-recommend.mjs, breakdown stored per row in recommendations.score_breakdown. The only LLM call in the pipeline parses the ideal-attendee text into targeting (prompt dinner-targeting-parse); the ranking itself is deterministic. Location is a hard gate, not a score: a candidate must match the dinner's metro (contact-level first; firm-HQ fallback is flagged on the row).

ComponentMaxWhat earns it
profile_fit35persona matches targeting (15) ยท firm type matches (10) ยท targeted seniority (5) ยท sector/keyword hit in title/thesis/tags (5)
client_association25the person's firm on a linked priority client: live funnel row (10) ยท shortlisted/upvoted recommendation (8) ยท positive match feedback (4) โ€” each ร— the link's weight, summed, capped
warmth30warmth_score/100 ร— 20 ยท Swarm 2nd-degree connection (strong 6 / medium 4 / any 2) ยท prior dinner/event attendance (checked-in 8, RSVP'd 4, +2 per extra event, cap 10)
reachability10verified email 4 (unverified 2) ยท LinkedIn URL 3 ยท touched in the last 90 days 3
Warm vs cold. A candidate lists as warm when any of: warmth_score โ‰ฅ 30 (the lukewarm floor), a Swarm connection to their firm, prior Luma attendance/RSVP, or their firm is live on a linked client engagement. Everything else is cold. Unlike the deal engine (which ranks on 100% relevance by explicit decision), warmth is IN the dinner rank โ€” who accepts a dinner invitation is mostly a warmth question. Votes and shortlist decisions survive re-runs (capture-and-replay, same contract as deal scans); imported and Inven-added rows are never wiped by a re-run.

The dinner funnel (v.65). Committing the shortlist creates one funnel row per guest (investor_process, source dinner, no mandate) and the 4-touch plan dinner_invite: email 1 โ†’ email 2 (+4 business days) โ†’ LinkedIn invite-or-DM by connection state (+3bd) โ†’ final email (+5bd), every draft approval-gated and sent by the same windowed scheduler as deal campaigns. The dinner stage ladder ends rsvp_yes | declined โ†’ attended; those stages sit outside the scheduler's arming gate, so an RSVP/decline/check-in automatically freezes the guest's remaining touches. RSVP state flows from the Luma guest CSV (luma_attendees) nightly, on every fresh import, and on demand; guests registering under an unknown email are linked by a human on the RSVPs tab. The capacity projection (guests ร— touches vs mailboxes ~40/day, a 0.5 share of the LinkedIn budgets, +12 business-day cadence span) is recomputed live and warns when the projected last touch lands within 3 days of the dinner.