[object Object]

← back to Homesonspec

feat(specs): pulte specs capture — discount-off-list, monthly payment, basement, active-adult, tour

1fd7b60a48dd52498fe831e11938041237eaae4c · 2026-08-03 07:03:48 -0700 · Steve Abrams

Verified vs a real qmiplans snapshot: audit's community-level candidates
(apr/adjustableRate) are NOT on the home object; the real home-level extras are
priceDiscount ($ off list), mortgagePayment, hasBasement, isActiveAdult,
discountExpiration, virtualTour, planDescription. Pruned null+false. tsc clean.

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

Files touched

Diff

commit 1fd7b60a48dd52498fe831e11938041237eaae4c
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Mon Aug 3 07:03:48 2026 -0700

    feat(specs): pulte specs capture — discount-off-list, monthly payment, basement, active-adult, tour
    
    Verified vs a real qmiplans snapshot: audit's community-level candidates
    (apr/adjustableRate) are NOT on the home object; the real home-level extras are
    priceDiscount ($ off list), mortgagePayment, hasBasement, isActiveAdult,
    discountExpiration, virtualTour, planDescription. Pruned null+false. tsc clean.
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
 collectors/pulte/src/index.ts | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/collectors/pulte/src/index.ts b/collectors/pulte/src/index.ts
index 36586cf0..ad9137c4 100644
--- a/collectors/pulte/src/index.ts
+++ b/collectors/pulte/src/index.ts
@@ -149,6 +149,22 @@ export const pulteAdapter: SourceAdapter = {
         const img = images.map((im) => (typeof im === "string" ? im : str((im as Record<string, unknown>)?.url) ?? str((im as Record<string, unknown>)?.src) ?? str((im as Record<string, unknown>)?.path)))
           .filter((u): u is string => !!u).map((u) => (u.startsWith("http") ? u : API + u));
         const invId = str(h.inventoryHomeID) ?? str(h.lotBlock);
+
+        // Long-tail specs Pulte exposes on the qmiplans home object (verified vs a real
+        // snapshot). Core price/beds/baths/sqft stay as columns; these are the extras.
+        const bool = (v: unknown): boolean | null =>
+          typeof v === "boolean" ? v : v === "true" ? true : v === "false" ? false : null;
+        const specs: Record<string, unknown> = {
+          priceDiscount: num(h.priceDiscount),      // $ off list (finalPrice = price − this)
+          mortgagePayment: num(h.mortgagePayment),  // est. monthly payment
+          hasBasement: bool(h.hasBasement),
+          isActiveAdult: bool(h.isActiveAdult),     // 55+ / active-adult community
+          discountExpiration: str(h.discountExpirationDate),
+          virtualTour: str(h.virtualTour) ?? str(h.threeDTour) ?? str(h.selfGuidedTourURL),
+          planDescription: str(h.planDescription),
+        };
+        for (const k of Object.keys(specs)) if (specs[k] == null || specs[k] === false) delete specs[k];
+
         records.push({
           entityType: "inventory_home",
           canonicalHints: {
@@ -181,6 +197,12 @@ export const pulteAdapter: SourceAdapter = {
             lat: fv(lat, null, page.url),
             lon: fv(lon, null, page.url),
             images: fv<string[]>(img.slice(0, 6), null, page.url, img.length ? "builder listing photo" : null),
+            specs: fv(
+              Object.keys(specs).length ? specs : null,
+              null,
+              page.url,
+              "pulte extra specs (discount off list, monthly payment, basement, active-adult, tour)",
+            ),
           },
         });
       }

← 7c3609cc feat(specs): dr-horton capture proving slice — extract->vali  ·  back to Homesonspec  ·  feat(specs): meritage specs capture — monthly payment, was-p 41335772 →