[object Object]

← back to Rentv 2026

harden(deals): Cody gate — scope parseOccupancy 'pre-' to 'leased' only so '90% preoccupied' isn't read as occupancy (my pre- addition had extended the occup root); \bbuilt ships as-is (Cody's 'custom built' critique was a misfire — that IS the build year)

f3b16410819d3ec52d190601bc41b501f152e8b9 · 2026-08-06 09:17:16 -0700 · Steve

Files touched

Diff

commit f3b16410819d3ec52d190601bc41b501f152e8b9
Author: Steve <steve@designerwallcoverings.com>
Date:   Thu Aug 6 09:17:16 2026 -0700

    harden(deals): Cody gate — scope parseOccupancy 'pre-' to 'leased' only so '90% preoccupied' isn't read as occupancy (my pre- addition had extended the occup root); \bbuilt ships as-is (Cody's 'custom built' critique was a misfire — that IS the build year)
---
 scripts/lib/deal-parse.mjs | 9 ++++++---
 test/deals/parse.test.mjs  | 1 +
 2 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/scripts/lib/deal-parse.mjs b/scripts/lib/deal-parse.mjs
index 9d503008..fa870839 100644
--- a/scripts/lib/deal-parse.mjs
+++ b/scripts/lib/deal-parse.mjs
@@ -110,9 +110,12 @@ export function parseAddress(body) {
   const m = body.match(/(?:located at|situated at|address is|\bat)\s+(\d{2,6}\s[A-Z][A-Za-z0-9.\- ]+?(?:Rd|Road|St|Street|Ave|Avenue|Blvd|Boulevard|Dr|Drive|Way|Ln|Lane|Pl|Place|Ct|Court|Pkwy|Parkway|Hwy|Highway)\b)/);
   return m ? m[1].trim() : null;
 }
-// "85% pre-leased" (common for new developments) counts as occupancy too, not just "leased"/"occupied".
-export function parseOccupancy(body) { const m = body.match(/(\d{1,3})%\s?(?:pre-?)?(?:leased|occup)/i); return m ? +m[1] : null; }
-// \bbuilt so "rebuilt/prebuilt in YYYY" (a RENOVATION year) isn't recorded as the original construction year.
+// "85% pre-leased" (common for new developments) counts as occupancy. The pre- qualifier is scoped to
+// "leased" only — NOT "occup" — so "90% preoccupied" (distracted, not a leasing metric) doesn't match.
+export function parseOccupancy(body) { const m = body.match(/(\d{1,3})%\s?(?:(?:pre-?)?leased|occup)/i); return m ? +m[1] : null; }
+// \bbuilt so "rebuilt in YYYY" (a renovation year, the only renovation phrase containing "built") isn't
+// recorded as the original construction year. Space-separated qualifiers ("newly/custom built in YYYY")
+// correctly stay — those ARE the original build year.
 export function parseYearBuilt(body) { const m = body.match(/\bbuilt in (\d{4})/i); return m ? +m[1] : null; }
 
 // two-sentence summary from the body (drop the leading title echo + date stamp)
diff --git a/test/deals/parse.test.mjs b/test/deals/parse.test.mjs
index ef0e2c44..2342b130 100644
--- a/test/deals/parse.test.mjs
+++ b/test/deals/parse.test.mjs
@@ -137,6 +137,7 @@ test('parseOccupancy + parseYearBuilt', () => {
   assert.equal(parseOccupancy('the asset is 95% leased'), 95);
   assert.equal(parseOccupancy('100% occupied at closing'), 100);
   assert.equal(parseOccupancy('85% pre-leased at delivery'), 85); // new-development pre-leasing counts
+  assert.equal(parseOccupancy('the team was 90% preoccupied with it'), null); // "preoccupied" ≠ occupancy
   assert.equal(parseOccupancy('no occupancy figure'), null);
   assert.equal(parseYearBuilt('the property was built in 1998'), 1998);
   assert.equal(parseYearBuilt('the tower was rebuilt in 2019'), null); // a renovation year is not the build year

← f0ce5eb3 PR intel: tenant-scope core entity reads + 2nd-tenant safety  ·  back to Rentv 2026  ·  fix(logo): keep header brand centered — .rentv-logo's positi ee669c0a →