11 KiB
PHASE 3.5 — Due Diligence Multi-Fuente
Estado: Phase 3.5.A en curso. Fundación lista, falta documento fetchers y PDF. Objetivo macro: dar al cliente DOS niveles de producto:
- Pre-screening ($15) — 2-3 min, ~1 Firecrawl credit. Decide GO / NO-GO rapido.
- Reporte completo ($150) — 5-15 min, ~2-5 creditos. PDF con TODOS los docs publicos.
Esto monetiza el trabajo que ya se hace gratis (clerks publicos + PA + court records) y agrega valor por la sintesis + la curaduria de documentos.
Tier system — que entrega cada producto
Pre-screening ($15) — los 3 BASICOS
| Documento | Fuente | Costo | Por que |
|---|---|---|---|
| Final Judgment / Clean Deed | Clerk records (CCIS / Acclaim / realauction docket) | Gratis | Confirma que hay caso real y el monto |
| Primary Lien (mortgage) | Recorder Official Records | Gratis | El monto que el plaintiff reclama |
| Photo exterior | PA (bcpa.net) o Zillow CDN fallback | 0-1 cred | Validacion visual basica |
Plus: Zestimate + comps (1 cred) + tax assessed + plaintiff classification + LienPositionAnalyzer verdict (GO/NO_GO/MAYBE/INSUFFICIENT_DATA).
Entregable: card en la app + "Pre-screening result" inline. NO PDF.
Reporte completo ($150) — TODO lo publico
Pre-screening +:
- IRS NFTL (Notice of Federal Tax Lien) check
- PACER bankruptcy check (chapters 7/11/13)
- Code enforcement violations
- Building permits / open permits
- Property tax delinquencies (tax collector)
- Sunbiz corporate filings (si owner es LLC)
- Sales history del deed (ultimos 10 anios)
- Comps detallados (5-10)
- HOA/condo docs (si aplica)
- Title chain summary
- PDF profesional (~15-25 paginas) con header del cliente + branding
Tiempo: 5-15 min. Costo Firecrawl: 2-5 cred (PA detail + comps + Sunbiz fallback).
Phase 3.5.A — Foundation (en curso, 70% done)
Hecho:
properties_store.py— carpetasproperties/{STATE}/{County}/{deal_type}/{id}/con subcategoriasdd_orchestrator.py— esqueleto run_pre_dd / run_full_dd / should_auto_trigger_dd- Pre-screening pipeline wired: court_records + tax_assessed + comps + price_validator + LienPositionAnalyzer
- Schema:
external_idseparado decase_number(migracion 280 deals movidos) - PA photos GRATIS (Broward backfill 36/37 hits, $0)
- Cards en app.py con foto + 5 botones + pre-screening inline
- 41 FL counties registrados en realforeclose.com + 7 CO + 3 AZ
Pendiente Phase 3.5.A:
- UI dedicada para "Reporte completo" — boton ya esta, falta el flujo real (hoy ejecuta heuristica)
- Categorias canonicas en
properties_store.pydefinidas pero no todos los fetchers escriben ahi dd_orchestrator.run_full_dd()hoy es placeholder — solo llama lo mismo que pre_dd
Done cuando: cliente puede hacer click "Reporte completo" y ver un PDF generado, aunque tenga 5 secciones.
Phase 3.5.B — Document fetchers (proximo bloque grande, ~2-3 semanas)
Fetchers free (Playwright) — multi-county adapters
Cada fetcher devuelve {found: bool, documents: [{category, filename, url, content}], data: {}} para que el orchestrator lo guarde en la carpeta correcta.
| Fetcher | Output | Counties priority |
|---|---|---|
data_fetchers/court_records.py |
Final judgment, lis pendens, case status | Duval (ya hecho), Broward, Miami-Dade, Palm Beach, Orange |
data_fetchers/recorder.py |
Deeds, mortgages, releases, assignments | Mismo set |
data_fetchers/code_enforcement.py |
Open violations, liens | County-by-county (cada uno tiene portal distinto) |
data_fetchers/building_dept.py |
Open permits, last inspection | Idem |
data_fetchers/tax_collector.py |
Tax delinquencies, tax certificates | Mismo set |
data_fetchers/property_appraiser.py |
Sales history, sketch, full record | Ya parcialmente (pa_photo_lookup.py) |
Arquitectura: cada data_fetchers/<topic>.py exporta fetch(county, state, identifier) -> dict. Internamente switch por county a la implementacion correcta (_fetch_broward, _fetch_miami_dade, etc.).
Fetchers federales / state-wide (gratis o Firecrawl bajo)
| Fetcher | Estado | Notas |
|---|---|---|
data_fetchers/irs_nftl.py |
Pendiente | Search por owner_name en IRS NFTL DB — gratis pero rate-limited |
data_fetchers/pacer.py |
Pendiente | Bankruptcy lookup — requiere cuenta PACER paga $0.10/page |
data_fetchers/sunbiz.py |
Pendiente | Si owner es LLC, traer corporate filing FL state — gratis |
data_fetchers/fl_dor.py |
Pendiente | FL Dept of Revenue — sales tax liens — gratis |
Fallback universal — Firecrawl /extract
Para counties FUERA de FL que aun no tienen scraper dedicado, usar data_fetchers/firecrawl_anywhere.py con schema generico (ver IDEAS_BACKLOG item #3). 4 cred per deal complete.
Done Phase 3.5.B cuando: pre-screening + full report consume datos REALES de los 5 counties FL priority (Broward, Miami-Dade, Palm Beach, Orange, Duval).
Phase 3.5.C — PDF report generator (~1 semana)
Stack tecnico
Opcion A (recomendado): WeasyPrint — HTML + CSS → PDF. Permite templates con Jinja2, CSS print rules, branding facil. Opcion B: ReportLab — codigo Python directo. Mas control, menos legible.
Decision: WeasyPrint.
Templates a crear
templates/reports/
pre_screening_summary.html # 2-3 paginas
full_report.html # 15-25 paginas
_header.html # branding cliente
_footer.html # disclaimer legal
_components/
plaintiff_box.html
comps_table.html
photo_grid.html
documents_index.html
Secciones del Full Report
- Executive Summary — verdict, top 3 risks, plaintiff, monto, address
- Property details — fotos, sketch, PA data, year built, sqft, lot size
- Owner — name, mailing address, LLC details (si Sunbiz aplica)
- Court status — case docket, final judgment date, judgment amount
- Liens — primary mortgage, secondary, IRS NFTL, HOA, code enforcement
- Title chain — last 3 deeds con fechas + amounts
- Tax position — assessed, market, taxes paid/owed, exemptions
- Comps — 5-10 sales recientes en .5 mile, $/sqft, days on market
- Investment math — bid suggestion, ARV estimate, repair budget ballpark
- Documents anexos — lista de PDFs descargados en
properties/.../con paths
Generador
# pdf_generator.py
def render_pre_screening_pdf(deal_id: int) -> Path: ...
def render_full_report_pdf(deal_id: int) -> Path: ...
Salida: properties/{state}/{county}/{type}/{id}/reports/report_{timestamp}.pdf
Done cuando: deal 349 (Broward) genera PDF de 10+ paginas con secciones 1-5 reales.
Phase 3.5.D — DueDiligenceAgent (synthesis layer, ~1 semana)
Hoy el LienPositionAnalyzer solo mira plaintiff. Para el reporte completo necesitamos un AGENTE que sintetice TODOS los outputs de los fetchers en un narrative.
Diseno
# dd_agent.py
def run_dd_agent(deal_id: int) -> dict:
"""
Llama a Ollama (modelo Coordinator: qwen2.5:32b) con un prompt que recibe:
- Court records output
- All liens (mortgage, IRS, HOA, code)
- PA data
- Comps
- Title chain
Y devuelve:
- executive_summary (3-4 oraciones)
- top_risks (lista de 3-5)
- investment_thesis (1 paragrafo)
- bid_suggestion (rango $)
- confidence_score (1-10)
"""
Modelfile
modelfiles/DueDiligenceCoordinator.modelfile — base qwen2.5:32b (19GB, mas reasoning power).
System prompt: "Eres un senior underwriter. Recibes data publica + extraida. Tu trabajo es escribir el executive summary y los risks que un investor experimentado escribiria."
Done cuando: deal con foreclosure + IRS NFTL detectado produce summary que MENCIONA el IRS lien como top risk.
Phase 3.5.E — Wave 1.5A v1.1 (Duval Acclaim Land Records)
Contexto: Duval Clerk tiene 2 sistemas:
- CCIS (court cases) — ya scrapeamos
- Acclaim Land Records (deeds + mortgages + lis pendens) — NO scrapeamos aun
Por que importa: lis pendens son LEADING INDICATOR — case que aun no llego a final judgment pero pre-foreclosure. Vale oro para outreach temprano.
Tareas
scrapers/duval_acclaim.py— Playwright scraper de Acclaim- Filtros: por document_type=lis_pendens, party_name, date_range
- Output: deals con
deal_type=pre_foreclosure(nuevo tipo) + 90 dias de runway - Registro en
scrapers/registry.pycomoduval_acclaim - UI: filtro nuevo en Search por deal_type=pre_foreclosure
Done cuando: Duval Acclaim devuelve >50 lis pendens del mes, todos con owner + property identificable.
Orden de ejecucion sugerido
Hoy: Phase 3.5.A close (UI Reporte completo functional aunque sea minimal)
Semana 1-2: Phase 3.5.B fetchers (los 5 county FL priority)
Semana 3: Phase 3.5.C PDF generator
Semana 4: Phase 3.5.D DD agent + integracion con PDF
Semana 5: Phase 3.5.E Duval Acclaim
Backlog (parallel): IDEAS_BACKLOG items P1/P2 segun bandwidth
Decisiones tecnicas que ya fueron tomadas (NO revisitar)
- case_number != external_id (Zillow zpid va a external_id). Migracion completada.
- realauction.com es multi-state multi-domain (realforeclose / realtaxdeed / treasurersdeedsale). Engine soporta
domainfield. - PA primero, Zillow fallback para fotos (PA es gratis Playwright, Zillow es 1 cred).
- 1 foto por deal (no 5) — cost-conscious.
- Pre-screening MANDATORY court_records para distressed deals (foreclosure/auction/tax_deed/reo).
- OWNER_VERIFIED cuenta como success en court_records (no es INSUFFICIENT_DATA).
- LienPositionAnalyzer soporta verdict INSUFFICIENT_DATA + PLAYERS section.
- CSS: 0 emojis user-facing, paleta corporate, Stop button NO se oculta.
- Folder structure
properties/{STATE}/{County}/{deal_type}/{identifier}/{category}/definida enproperties_store.py.
Como usar este plan
- Empezar sesion → leer este archivo +
IDEAS_BACKLOG.md - Si hay tarea en curso de Phase 3.5 → continuar en ese checkbox
- Si Phase 3.5 actual completada → mover al siguiente bloque
- Marcar [x] cuando done + agregar commit hash al lado
- Si discoveris algo nuevo que NO bloquea → va a
IDEAS_BACKLOG.md
Riesgos identificados
- Firecrawl budget (1000 cred/mes): con full report a 2-5 cred y 250 deals/mes = 500-1250 cred. Hay que monitorear y posiblemente bumpear plan.
- Multi-county fetchers son trabajo lineal — cada county tiene su portal con su captcha / su SPA. Estimado 2-4h por county-fetcher pair.
- PACER cuesta plata — si lo integramos, pasa de margen variable. Considerar omitirlo del basic full report y ofrecerlo como add-on $50.
- PDF generation puede ser lento (WeasyPrint con 20+ paginas y muchas imagenes) — preparar para 30-60s render time.
- Agent (qwen2.5:32b) requiere 19GB RAM/VRAM — confirmar que la maquina del cliente lo corre.