How the distress score, priority score, portfolio linkage, and Watchlist comparison are computed, and how every source we use has been ingested. The tables on this page read the live database at request time; no dates are hardcoded.
The distress score is a 0-100 rollup of six public signals. Each component is capped so that no single source dominates a building's score.
adax-9mitdataset (~800 rows, quarterly cadence) from dominating an otherwise low-distress building's score.Score version v1-2026-07-15. Every score row and export CSV carries this version stamp.
A distress score between 1-9 is honest evidence that the building has minimal public signal. This is not an error - it is what a low-signal, healthy-enough building looks like inside the product. When a visitor lands on a building detail with a very low score, the page renders that number and calls it out explicitly rather than hiding the building.
Buildings are linked into portfolios via Union-Find over an edge graph derived from HPD registration contacts. Two edges exist between buildings if they share either:
Business addresses that appear on more than 50 distinct contact names are excluded before linking. Confidence is min(1.0, edge_density * sqrt(building_count) / sqrt(3))per cluster. Standard confidence ≥ 0.60; low confidence < 0.60. Two-building clusters need corroborating edges to reach standard confidence.
Known false-merge patterns: LLC shells sharing a management-company address; N/A / unknown owner names collapsing unrelated portfolios. Known false-split patterns: same landlord using different registration contact aliases across neighborhoods; portfolios recently changing management.
Any cluster with more than 1,000 buildings is treated as a supercluster and excluded from ranked outreach queues. The 50-contact high-frequency address exclusion prevents most spurious merges; the ceiling is a hard safety net for the residual over-merges. Supercluster member buildings still appear individually in the intake view with their own distress score.
Ranked queues use a priority score, not raw distress. Priority is distress_score × unit_exposure_multiplier × stabilization_multiplier. Unit exposure scales with total residential unit count so that a 220-unit distressed building is prioritized over a 6-unit distressed building. Stabilization multiplier weights buildings whose rent-stabilized unit count is at risk.
Only the complaint types below are counted from 311 (dataset erm2-nwe9) toward complaint velocity. Version v1-2026-07-15 effective Jul 15, 2026.
Baseline set from REQUIREMENTS.md; expanded with heat/water/pest/safety variants observed in the 2023-present erm2-nwe9 window as agency='HPD' or location_type='RESIDENTIAL BUILDING'. Change-control rule: any addition/removal creates a new version_label (never edits an existing row).
The product compares its top-100 portfolio ranking to the Public Advocate's most recent Watchlist edition. Overlap must be at least 50% for the comparison to pass. Each row where ranks differ is tagged with one of four difference categories:
Overlap threshold >= 50% is honored per REQUIREMENTS.md done-when #5. When overlap falls below threshold, the validation view calls it out honestly and directs the reader to the categorized breakdown.
An independent building sample is scored by hand and compared with the product's score. Per-BBL heuristic tier, product score, agreement, and disagreement reasons live in nyc.tenant_outreach_score_validation_sample.
| BBL | Heuristic tier | Product score | Agreement | Disagreement reason |
|---|---|---|---|---|
| 2039377501 | High | 90.0 | agree | - |
| 2026187501 | High | 90.0 | agree | - |
| 2039447501 | High | 90.0 | agree | - |
| 2039387501 | High | 89.0 | agree | - |
| 2039437501 | High | 89.0 | agree | - |
| 1010907502 | High | 87.0 | agree | - |
| 1020350001 | High | 87.0 | agree | - |
| 3049670040 | High | 86.0 | agree | - |
| 4091870018 | Medium | 10.0 | agree | - |
| 1018710052 | Medium | 9.9 | agree | - |
| 1017560005 | Medium | 9.9 | agree | - |
| 3064400042 | Medium | 9.9 | agree | - |
| 3031680001 | Medium | 9.9 | agree | - |
| 4088640031 | Medium | 9.9 | agree | - |
| 3069240065 | Medium | 9.9 | agree | - |
| 4028850055 | Medium | 9.9 | agree | - |
REQUIREMENTS.md requires a Jaccard similarity >=0.70 for at least 8 of 10 fixed BBLs when comparing product portfolio boundaries with the Housing Data Coalition's Who Owns What (WOW) portfolios.
Cluster boundaries can legitimately differ because (1) this product links via Union-Find on HPD registration contact names and business addresses while WOW additionally uses ACRIS buyer/seller deed chains and HPD manager-contact networks (not publicly available as an API); and (2) this product's high-frequency address exclusion (business addresses shared by more than 50 distinct contact names) is an operationalization of WOW's qualitative heuristic, not an exact replica. Mismatches are documented, explainable differences, not errors requiring resolution.
| BBL | WOW size | Product size | Jaccard | Status |
|---|---|---|---|---|
| 1001630001 | 3 | 3 | 1.00 | match |
| 5000480024 | 17 | 17 | 1.00 | match |
| 5033250040 | 233 | 236 | 0.97 | match |
| 1010500029 | 18 | 17 | 0.94 | match |
| 5012540165 | 2 | 10 | 0.20 | mismatch |
| 1018840001 | 3 | 78 | 0.01 | mismatch |
| 2033000013 | 134 | 1 | 0.01 | mismatch |
| 1013920070 | 1 | 190 | 0.00 | no wow portfolio |
| 5001650024 | 1 | 1 | 0.00 | no wow portfolio |
| 5007810028 | 1 | 1 | 0.00 | no wow portfolio |
The product accepts a CSV drop-in of aggregated PEU helpline records. The fixture-run aggregate panel on /tenant-outreach/helpline-drop-in shows the latest batch's matched / ambiguous / unmatched / rejected counts and quality status. Thresholds: PASS at >= 85% matched, WARN at >= 75%, FAIL below 75%. No tenant PII enters the product; only aggregate counts and quality metrics are stored.
Live status from nyc.tenant_outreach_source_registry joined to the latest nyc.tenant_outreach_ingest_runs row per source. Rows carry stable anchor IDs so the freshness chips on every other page deep-link here.
| Source | Agency | Access | Cadence | Stale after | Last success | Rows loaded | Status |
|---|---|---|---|---|---|---|---|
311 (filtered by allowlist) 311_tenant_relevanterm2-nwe9 | DoITT / 311 | socrata | every 1d | 10d | Jul 15, 2026, 07:32 PM 29 days ago | 1,500,000 | Stale |
Building distress + priority scores | (derived) | derived | every 7d | 21d | Jul 20, 2026, 11:03 PM 24 days ago | 181,735 | Stale |
Buildings roll-up | (derived) | derived | every 7d | 21d | Jul 15, 2026, 09:36 PM 29 days ago | 181,735 | Stale |
HPD Complaints and Problems hpd_complaints_problemsygpa-z7cr | HPD | socrata | every 1d | 10d | Jul 15, 2026, 08:50 PM 29 days ago | 499,993 | Stale |
HPD Housing Litigations hpd_litigations59kj-x8nc | HPD | socrata | every 7d | 21d | Jul 15, 2026, 06:44 PM 29 days ago | 239,434 | Stale |
HPD Housing Maintenance Code Violations hpd_violationswvxf-dwi5 | HPD | socrata | every 1d | 10d | Jul 15, 2026, 08:31 PM 29 days ago | 412,502 | Stale |
HPD Multiple Dwelling Registrations hpd_registrationstesw-yqqr | HPD | socrata | every 1d | 10d | Jul 15, 2026, 06:42 PM 29 days ago | 193,567 | Stale |
HPD Registration Contacts hpd_registration_contactsfeu5-w2e2 | HPD | socrata | every 1d | 10d | Jul 15, 2026, 06:49 PM 29 days ago | 730,660 | Stale |
Marshal-Executed Evictions marshal_evictions6z8x-wfk4 | DOI | socrata | every 30d | 45d | Jul 15, 2026, 06:44 PM 29 days ago | 119,276 | Fresh |
Portfolio clusters + members | (derived) | derived | every 7d | 21d | Jul 20, 2026, 11:02 PM 24 days ago | 87,964 | Stale |
Public Advocate Worst Landlord Watchlist | Public Advocate | html-scrape | every 365d | 400d | Jul 15, 2026, 06:52 PM 29 days ago | 99 | Fresh |
Rent-stabilized building lists (annual) | DHCR + community sources | html-scrape | every 365d | 400d | Jul 15, 2026, 06:54 PM 29 days ago | 430,103 | Fresh |
Speculation Watch List (LL7/2018) speculation_watchadax-9mit | DOF/Public Advocate | socrata | every 90d | 120d | Jul 15, 2026, 06:38 PM 29 days ago | 795 | Fresh |
Watchlist overlap and mismatch categories | (derived) | derived | every 365d | 400d | Jul 20, 2026, 11:04 PM 24 days ago | 175 | Fresh |