[object Object]

← back to Govarbitrage

agents: relevance-weighted ranking — surface stronger CRE matches first

c53b1f24896633f94414b0b0ea9356778cc7bf25 · 2026-07-27 21:19:24 -0700 · Steve Abrams

The commercial-RE finder ranked purely by rating*log(reviews), so a
weakly-commercial high-rated generic outranked a two-lens national
brokerage (CBRE surfaced by both buyer+leasing) with modest reviews.
Add bounded relevanceScore() (national brand +0.3, strong commercial
name +0.2, both-lens coverage +0.1) folded into the rank as a
multiplier + relevance tiebreak. Bounded so a 0-review brand still
weighs rating*log(1)=0 and cannot leapfrog a genuinely reviewed office.
Pure/offline/reversible; +7 tests (113/113), tsc clean, $0 no billing.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Files touched

Diff

commit c53b1f24896633f94414b0b0ea9356778cc7bf25
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Mon Jul 27 21:19:24 2026 -0700

    agents: relevance-weighted ranking — surface stronger CRE matches first
    
    The commercial-RE finder ranked purely by rating*log(reviews), so a
    weakly-commercial high-rated generic outranked a two-lens national
    brokerage (CBRE surfaced by both buyer+leasing) with modest reviews.
    Add bounded relevanceScore() (national brand +0.3, strong commercial
    name +0.2, both-lens coverage +0.1) folded into the rank as a
    multiplier + relevance tiebreak. Bounded so a 0-review brand still
    weighs rating*log(1)=0 and cannot leapfrog a genuinely reviewed office.
    Pure/offline/reversible; +7 tests (113/113), tsc clean, $0 no billing.
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
 src/lib/places.test.ts | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++
 src/lib/places.ts      | 42 ++++++++++++++++++++++++++++++---
 2 files changed, 102 insertions(+), 3 deletions(-)

diff --git a/src/lib/places.test.ts b/src/lib/places.test.ts
index 0de4078..abb9f35 100644
--- a/src/lib/places.test.ts
+++ b/src/lib/places.test.ts
@@ -4,6 +4,7 @@ import {
   dedupeByContact,
   normalizePhone,
   normalizeHost,
+  relevanceScore,
   type AgentResult,
   type RawPlace,
 } from "./places";
@@ -292,3 +293,65 @@ describe("dedupeByContact", () => {
     expect(out).toHaveLength(2);
   });
 });
+
+// relevanceScore() weights the RANKED list so a stronger CRE-broker match
+// (national brand / strong commercial name / surfaced by both lenses) surfaces
+// ahead of a weakly-commercial one at comparable rating-weight — without a
+// 0-review brand leapfrogging a genuinely reviewed office. Offline, no billing.
+describe("relevanceScore", () => {
+  it("returns the 1.0 baseline for a plain commercial listing", () => {
+    // No allowlisted brand, no strong COMMERCIAL_RE hit in the name, one lens.
+    expect(relevanceScore(agent({ id: "x", name: "Downtown Advisory" }))).toBeCloseTo(1.0);
+  });
+
+  it("adds weight for an allowlisted national brokerage brand", () => {
+    const s = relevanceScore(agent({ id: "x", name: "CBRE", kinds: ["buyer"] }));
+    expect(s).toBeGreaterThan(1.0);
+    // CBRE hits the brand bonus (+0.3) AND "commercial"? no — name is bare "CBRE"
+    // so only the brand bonus applies.
+    expect(s).toBeCloseTo(1.3);
+  });
+
+  it("adds weight for a strong commercial name signal", () => {
+    // "Industrial Property Group" hits COMMERCIAL_RE but is not an allowlist brand.
+    expect(relevanceScore(agent({ id: "x", name: "Industrial Property Group" }))).toBeCloseTo(1.2);
+  });
+
+  it("adds weight when surfaced by BOTH the buyer and leasing lenses", () => {
+    const both = relevanceScore(agent({ id: "x", name: "Anon Realty", kinds: ["buyer", "leasing"] }));
+    const one = relevanceScore(agent({ id: "x", name: "Anon Realty", kinds: ["buyer"] }));
+    expect(both - one).toBeCloseTo(0.1);
+  });
+
+  it("stacks signals (brand + commercial name + both lenses) up to the bound", () => {
+    const s = relevanceScore(
+      agent({ id: "x", name: "CBRE Commercial", kinds: ["buyer", "leasing"] }),
+    );
+    // +0.3 brand +0.2 commercial-name +0.1 both-lenses = 1.6 ceiling.
+    expect(s).toBeCloseTo(1.6);
+  });
+});
+
+// The ranking must PROMOTE a stronger commercial match at comparable
+// rating-weight, but a zero-review brand must NOT jump a genuinely reviewed
+// office. dedupeByContact is a pass-through here (distinct contacts), so we can
+// assert ordering behavior on the same sort comparator via a tiny local sort
+// mirroring searchCommercialAgents (kept in sync with places.ts).
+describe("relevance-weighted ranking behavior", () => {
+  const rankWeight = (r: AgentResult) =>
+    (r.rating ?? 0) * Math.log((r.reviews ?? 0) + 1) * relevanceScore(r);
+
+  it("promotes a stronger CRE match over a weakly-commercial one at equal rating/reviews", () => {
+    const brand = agent({ id: "1", name: "CBRE", rating: 4.5, reviews: 30, kinds: ["buyer", "leasing"] });
+    const weak = agent({ id: "2", name: "Anon Advisory", rating: 4.5, reviews: 30, kinds: ["buyer"] });
+    expect(rankWeight(brand)).toBeGreaterThan(rankWeight(weak));
+  });
+
+  it("does NOT let a zero-review brand leapfrog a well-reviewed office", () => {
+    const brandNoReviews = agent({ id: "1", name: "CBRE", rating: 5, reviews: 0, kinds: ["buyer", "leasing"] });
+    const reviewedOffice = agent({ id: "2", name: "Metro Advisory", rating: 4.2, reviews: 120, kinds: ["buyer"] });
+    // rating × log(1) = 0 for the brand regardless of relevance multiplier.
+    expect(rankWeight(brandNoReviews)).toBe(0);
+    expect(rankWeight(reviewedOffice)).toBeGreaterThan(rankWeight(brandNoReviews));
+  });
+});
diff --git a/src/lib/places.ts b/src/lib/places.ts
index dcf8797..962f3f6 100644
--- a/src/lib/places.ts
+++ b/src/lib/places.ts
@@ -168,6 +168,34 @@ function hasCommercialBrand(name: string): boolean {
   return COMMERCIAL_BRANDS.some((b) => n.includes(b));
 }
 
+// --- Commercial-relevance ranking weight ----------------------------------
+// Every result in the ranked list has ALREADY passed isCommercial() (precision
+// gate), but they're not equally strong CRE-broker matches. A listing that is
+// an allowlisted national brokerage AND was surfaced by BOTH the buyer- and
+// leasing-lenses is a far more confident "commercial broker near this property"
+// answer than a lone generic result that only just cleared the commercial name
+// gate. The old ranking (pure rating × log(reviews)) ignored this entirely, so
+// a highly-rated but weakly-commercial listing outranked a two-lens national
+// brokerage with modest reviews.
+//
+// relevanceScore() returns a small multiplier (1.0 baseline → up to ~1.6) that
+// nudges stronger CRE matches upward. It's deliberately BOUNDED and multiplied
+// into the existing rating-weight so it re-orders near-comparable results and
+// breaks near-ties in favor of the better commercial match — WITHOUT letting a
+// zero-review brand leapfrog a genuinely well-reviewed office (a 0-review brand
+// still scores rating×log(1)=0 and stays below any reviewed listing). Pure +
+// deterministic; unit-tested offline with zero live Places billing.
+export function relevanceScore(r: AgentResult): number {
+  let s = 1;
+  // Allowlisted national/regional brokerage brand → the most confident signal.
+  if (hasCommercialBrand(r.name)) s += 0.3;
+  // Strong commercial name evidence (CRE/industrial/office/investment sales…).
+  if (COMMERCIAL_RE.test(r.name)) s += 0.2;
+  // Surfaced by BOTH the buyer- and leasing-lens → broader CRE relevance.
+  if (r.kinds.includes("buyer") && r.kinds.includes("leasing")) s += 0.1;
+  return s;
+}
+
 // --- Contact-based dedupe -------------------------------------------------
 // Google Places returns the SAME physical brokerage office under several of our
 // query lenses as DIFFERENT place ids (e.g. "CBRE" from the buyer lens and
@@ -397,11 +425,19 @@ export async function searchCommercialAgents(
   // same website when phones don't contradict) BEFORE ranking.
   const deduped = dedupeByContact([...byId.values()]);
 
-  // Rank by rating weighted by review volume, then rating, then review count.
+  // Rank by rating weighted by review volume AND commercial-relevance, then by
+  // relevance alone (surfaces a strong CRE match ahead of a weakly-commercial
+  // one at equal rating-weight), then rating, then review count. The relevance
+  // multiplier is bounded (≤~1.6) so it re-orders near-comparable results and
+  // breaks near-ties toward the better commercial match, but a 0-review listing
+  // still weighs rating×log(1)=0 and cannot leapfrog a genuinely reviewed office.
   const results = deduped.sort((a, b) => {
-    const sa = (a.rating ?? 0) * Math.log((a.reviews ?? 0) + 1);
-    const sb = (b.rating ?? 0) * Math.log((b.reviews ?? 0) + 1);
+    const sa = (a.rating ?? 0) * Math.log((a.reviews ?? 0) + 1) * relevanceScore(a);
+    const sb = (b.rating ?? 0) * Math.log((b.reviews ?? 0) + 1) * relevanceScore(b);
     if (sb !== sa) return sb - sa;
+    const ra = relevanceScore(a);
+    const rb = relevanceScore(b);
+    if (rb !== ra) return rb - ra;
     if ((b.rating ?? 0) !== (a.rating ?? 0)) return (b.rating ?? 0) - (a.rating ?? 0);
     return (b.reviews ?? 0) - (a.reviews ?? 0);
   });

← c173473 auto-save: 2026-07-27T20:24:23 (1 files) — tsconfig.tsbuildi  ·  back to Govarbitrage  ·  agents: drop financial-advisory/wealth firms from CRE finder 2d44193 →