← 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
M src/lib/places.test.tsM src/lib/places.ts
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 →