[object Object]

← back to Rentv 2026

harden(deals): Cody gate — lower SF/unit plausibility threshold 100→50 so it stops false-dropping legit self-storage SF (~60-90 sf/unit) while still catching the <11 sf/unit residential body leaks

f6e330bb674750489f58d90f3ede42adccbef8bd · 2026-08-06 08:03:10 -0700 · Steve

Files touched

Diff

commit f6e330bb674750489f58d90f3ede42adccbef8bd
Author: Steve <steve@designerwallcoverings.com>
Date:   Thu Aug 6 08:03:10 2026 -0700

    harden(deals): Cody gate — lower SF/unit plausibility threshold 100→50 so it stops false-dropping legit self-storage SF (~60-90 sf/unit) while still catching the <11 sf/unit residential body leaks
---
 scripts/lib/deal-parse.mjs | 10 ++++++----
 test/deals/parse.test.mjs  |  3 +++
 2 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/scripts/lib/deal-parse.mjs b/scripts/lib/deal-parse.mjs
index a4e8e952..27bb1c14 100644
--- a/scripts/lib/deal-parse.mjs
+++ b/scripts/lib/deal-parse.mjs
@@ -74,10 +74,12 @@ export function parseSize(text) {
   let sqft = cands.length ? cands[0].val : null;
   const unitsNum = units ? +units[1].replace(/,/g, '') : null;
   // Plausibility guard: a multifamily asset is measured in UNITS, not SF, so a small "N sf" next to a
-  // unit count is a body leak — a per-unit average or an amenity/clubhouse size, NOT the total. No
-  // residential building runs under ~100 sf/unit (micro-units start ~250), and real data shows a clean
-  // gap (leaks < 11 sf/unit, legit > 790), so this drops "406 units · 669 SF" → "406 units" safely.
-  if (unitsNum && sqft && sqft < unitsNum * 100) sqft = null;
+  // unit count is a body leak — a per-unit average or an amenity/clubhouse size, NOT the total. The
+  // threshold is 50 sf/unit: the actual leaks run 1.6–11 sf/unit (well under 50) while the tightest LEGIT
+  // per-unit density is self-storage at ~60–90 sf/unit (a "unit" there is a locker) — 50 sits in the gap,
+  // so it drops "406 units · 669 SF" → "406 units" but keeps a real "100-unit self-storage, 8,000 SF".
+  // (This is deliberately type-blind; a type-aware guard is a logged follow-on.)
+  if (unitsNum && sqft && sqft < unitsNum * 50) sqft = null;
   const parts = [];
   if (units) parts.push(`${units[1]} units`);
   if (sqft) parts.push(`${sqft.toLocaleString()} SF`);
diff --git a/test/deals/parse.test.mjs b/test/deals/parse.test.mjs
index 0410f722..77f58493 100644
--- a/test/deals/parse.test.mjs
+++ b/test/deals/parse.test.mjs
@@ -108,6 +108,9 @@ test('parseSize: an implausibly small SF next to a unit count is dropped (multif
   // a plausible large SF next to units is KEPT (not dropped)
   assert.deepEqual(parseSize('Meta Housing 300-Unit Community spanning 238,000 sf'),
     { size_label: '300 units · 238,000 SF', units: 300, sqft: 238000 });
+  // self-storage runs ~60-90 sf/unit (a "unit" is a locker) — threshold is 50 sf/unit so this SURVIVES
+  assert.deepEqual(parseSize('Buyer acquires 100-unit self-storage facility spanning 8,000 sf'),
+    { size_label: '100 units · 8,000 SF', units: 100, sqft: 8000 });
 });
 
 // ── parseOccupancy / parseYearBuilt ───────────────────────────────────────────

← 72561ee4 fix(deals): drop an implausibly small SF (<100 sf/unit) next  ·  back to Rentv 2026  ·  Add rentv.com region+category tab panel + /region/:slug land ba45532d →