NYC Prototypes

Methodology

What our data actually says, what we chose to compute, and what we chose not to compute. Nothing here is presented without a source; nothing here is presented without a caveat.

Data as of 2026-10-13 08:28

Source inventory

Every source, its dataset ID, its license, its rate limit, its last successful ingest, and its coverage window. If a row is red, that source is failing. Alerts and portfolio counts continue to reflect the last-known-good snapshot for that source.

SourceDataset / endpointAccess / cadenceRows landedLast successStatus
acris_master
bnx9-e6tj
NYC Open Data Socrata JSON
Weekly
16,0972026-10-13 08:28Success
acris_legals
8h5j-fqxa
NYC Open Data Socrata JSON
Weekly
59,5842026-10-13 08:29Success
acris_parties
636b-3b5g
NYC Open Data Socrata JSON
Weekly
16,4562026-10-13 08:27Success
acris_pages
—
ACRIS GetImage (undocumented endpoint; DOF partnership sanctioned)
Weekly (new docs only)
—2026-07-15 22:37Success
ll44_projects
ucdy-byxd
NYC Open Data Socrata JSON
Weekly
1,0142026-10-13 08:33Success
housing_production
hg8x-zxpr
NYC Open Data Socrata JSON
Weekly
8,5552026-10-13 08:33Success
j51
y7az-s7wc
NYC Open Data Socrata JSON
Monthly
13,2682026-10-13 08:33Success
property_exemptions
muvi-b6kx
NYC Open Data Socrata JSON
Monthly
99,9272026-10-13 08:35Success
pluto_bbl_enrichment
geosearch_v2
NYC Open Data Socrata JSON
Quarterly
242026-10-13 08:33Success
coredata_snapshot
—
Manually-exported dated snapshot (offline)
Manual
02026-10-13 08:35Success
nhpd_snapshot
—
Manually-exported dated snapshot (offline)
Manual
02026-10-13 08:35Success
extraction_worker
—
Anthropic Claude (Sonnet vision)
Weekly (only new docs)
9322026-10-13 08:35Success
crosscheck_builder
—
Internal join (ACRIS extraction × LL44 × HP)
Weekly
1002026-10-13 08:36Success
alert_builder
—
Internal (SQL rules)
Weekly
4552026-10-13 08:36Success
document_link_resolver
—
Internal (heuristic on extracted references)
Weekly
10,6302026-10-13 08:36Success
orchestrator
—
Pipeline orchestration
Weekly
32026-10-13 08:33Success
replay_backfill
bnx9-e6tj
Internal replay test
Ad-hoc
62026-07-13 20:41Success
acris_references
pwkr-dpni
Unknown
Unknown
13,8242026-10-13 08:30Success
acris_remarks
9p4w-7npp
Unknown
Unknown
1,5982026-10-13 08:31Success

Ingest run history

Every ingest run, including failures, with duration, rows landed, and errors. This product does not paper over a failed refresh.

StartedFinishedSourceKindRows landedDurationStatusError
2026-10-13 08:362026-10-13 08:36alert_builder—45525sSuccess
2026-10-13 08:362026-10-13 08:36crosscheck_builder—1001sSuccess
2026-10-13 08:352026-10-13 08:36document_link_resolver—10,63012sSuccess
2026-10-13 08:352026-10-13 08:35extraction_worker—9321sSuccess
2026-10-13 08:352026-10-13 08:35nhpd_snapshot—00sSuccess
2026-10-13 08:352026-10-13 08:35coredata_snapshot—00sSuccess
2026-10-13 08:332026-10-13 08:35property_exemptionsmuvi-b6kx99,9271m 58sSuccess
2026-10-13 08:332026-10-13 08:33j51y7az-s7wc13,26811sSuccess
2026-10-13 08:332026-10-13 08:33housing_productionhg8x-zxpr8,5559sSuccess
2026-10-13 08:332026-10-13 08:33ll44_projectsucdy-byxd1,0142sSuccess
2026-10-13 08:332026-10-13 08:33orchestrator—30sSuccess
2026-10-13 08:312026-10-13 08:33pluto_bbl_enrichmentgeosearch_v2241m 38sSuccess
2026-10-13 08:312026-10-13 08:31pluto_bbl_enrichment64uk-42ks7,09633sSuccess
2026-10-13 08:302026-10-13 08:31acris_remarks9p4w-7npp1,59835sSuccess
2026-10-13 08:292026-10-13 08:30acris_referencespwkr-dpni13,82455sSuccess
2026-10-13 08:282026-10-13 08:29acris_legals8h5j-fqxa59,58452sSuccess
2026-10-13 08:272026-10-13 08:28acris_masterbnx9-e6tj16,0971m 4sSuccess
2026-10-13 08:232026-10-13 08:27acris_parties636b-3b5g16,4564m 8sSuccess
2026-10-12 08:482026-10-12 08:49alert_builder—45537sSuccess
2026-10-12 08:482026-10-12 08:48crosscheck_builder—1001sSuccess
2026-10-12 08:482026-10-12 08:48document_link_resolver—10,63017sSuccess
2026-10-12 08:482026-10-12 08:48extraction_worker—9322sSuccess
2026-10-12 08:482026-10-12 08:48nhpd_snapshot—00sSuccess
2026-10-12 08:482026-10-12 08:48coredata_snapshot—00sSuccess
2026-10-12 08:462026-10-12 08:48property_exemptionsmuvi-b6kx99,9271m 39sSuccess
2026-10-12 08:462026-10-12 08:46j51y7az-s7wc13,26813sSuccess
2026-10-12 08:462026-10-12 08:46housing_productionhg8x-zxpr8,5556sSuccess
2026-10-12 08:462026-10-12 08:46ll44_projectsucdy-byxd1,0142sSuccess
2026-10-12 08:462026-10-12 08:46orchestrator—30sSuccess
2026-10-12 08:442026-10-12 08:46pluto_bbl_enrichmentgeosearch_v2241m 20sSuccess

Extraction pipeline

  1. ACRIS Master identifies HPD / HDC agreements by document type (AGMT, TERA) and party name normalization.
  2. ACRIS Legals resolves the recording to one or more BBLs (borough-block-lot).
  3. ACRIS Parties normalizes to canonical HPD/HDC entity variants (case, punctuation, LLC suffixes).
  4. GetImage fetches each page as a TIFF. Placeholder pages are flagged and skipped.
  5. Vision LLM (claude-opus-4-6 by default) reads the scan and returns field-level extractions with self-reported confidence, page number, source quote, and bounding box in normalized [0,1] page coordinates.
  6. Cross-check joins the extracted horizon fields to LL44 program-level publications and Housing Production building-level records.
  7. Horizon adjudication decides which value the header displays when sources disagree; the losing values remain visible on the building page.

Every field the model returns is stored with a source_run_id. Reruns append; they do not overwrite. Historical runs remain viewable.

Horizon methodology

A term is expressed one of four ways:

  1. Absolute date:“expires December 31, 2039.” Bucketed directly against today.
  2. Relative to observed event:“25 years after project completion (June 3, 2010).” Resolved into an absolute date.
  3. Relative to unobserved event:“25 years after project completion (project not yet observed).” Bucketed as needs base date and never silently invented.
  4. Perpetual / permanent: displayed as such, bucketed 10+ years.

Non-terminated terms only are considered for the header. Terminated terms remain in the timeline for auditability.

Cross-check

Three sources measure related but different things:

  • ACRIS is the text of the recorded regulatory agreement. It is the legal document.
  • LL44 (HPD) is an HPD publication of program-level data. Its unit of analysis is the project, not the building.
  • Housing Production is a building-level record of completed affordable units.

Discrepancies are surfaced as discrepancy_flag on the field. Neither value is silently discarded. The comparability matrix below documents which fields are and are not comparable across sources.

Adjudication policy

When ACRIS and LL44 disagree on a horizon-relevant field, the header shows the ACRIS extraction, because it's the legal document. The cross-check panel on the building page shows both values, side-by-side.

When ACRIS confidence is below 0.6 and LL44 has a matching value, we still show the ACRIS value in the header, but visibly de-emphasized with a lower-confidence pill. Both remain in cross-check.

Comparability matrix

FieldACRISLL44Housing Prod.Comparable?
Unit countLegal units at recordingProject totalBuilding-levelYes when BBL is 1:1 with project
Expiration dateAbsolute or relativePublication-year plus termNot availableApproximate; expect ±90 days
Program nameFree-textEnumeratedNot presentFuzzy match only
Affordable unit mixAMI + bedroom countsNot always publishedNot availablePartial

Scan corpus scope

We do not have the disk budget or the render throughput to hold every ACRIS scan for every HPD / HDC record ever recorded. We hold: (a) every HPD/HDC recording in the selected full-scan neighborhoods and (b) every alert-triggered recording. Everything else is metadata-only until requested, and a Scan not yet in corpus badge makes that visible.

ACRIS GetImage caveat

ACRIS GetImage returns a placeholder TIFF for a small number of officially-recorded instruments (misfiles, redactions, or scans held under privacy holds). The extractor flags these pages and the document's scan status becomes undocumented. The metadata (party, doc type, date) still contributes to portfolio counts, but no horizon or unit-count field is emitted.

Unreadable scans

A scan is marked unreadablewhen OCR quality confidence falls below the retry threshold across at least three consecutive pages. Unreadable scans surface as a portfolio alert; the corresponding building card offers a “Rerun extraction” action but does not silently guess.

Needs base date

“35 years after project completion” is not a date until we observe the completion date. Records with unobserved base events are bucketed needs base date and cross-checked against Housing Production and DOB completions. If a match is found on later ingest, the record moves out of this bucket automatically; the original relative expression is retained in the audit log.

HPD internal firewall

Some HPD program-level fields (recapture triggers, subordination priorities, exact AMI mix by bedroom) live behind HPD's internal firewall and are not published to open data. This product does not scrape internal systems. When a field is known to exist internally but not on open data, we mark it hpd-internal rather than guess or blank it.

Offline snapshots

When an upstream source is unavailable at ingest time we retain the last-known-good snapshot rather than dropping rows. Every table view stamps the snapshot date; every stale banner names the source that failed. The ingest run history above is the audit log for what fell over and when.

Pre-1966 records

ACRIS coverage begins in 1966; older recordings live in reel-and-page microfilm at the City Register. We display a “chain runs off the edge of ACRIS coverage” marker rather than pretend the chain started with the earliest ACRIS record.

Staten Island

Staten Island (Richmond County) records live at the Richmond County Clerk, not at ACRIS. This product does not attempt to combine those sources. Staten Island BBLs return an in-scope-not-in-scope empty state.

Alerts

Alerts fire only on ingest deltas. If a BBL matches your rule but was already matching before the last ingest, no alert. This means alerts are cheap on a static snapshot and loud when the world actually changes.

Suppression: per-alert, either one ingest cycle or 30 days. Suppression is per-user, and per-rule.

Confidence & ranges

Confidence is self-reported by the extraction model, bucketed into low (<0.6), medium (0.6-0.85), and high (0.85+). Confidence is a signal about the model, not about the document. A high-confidence extraction of a garbled scan is still a high-confidence extraction of a garbled scan.

Party-name dictionary

HPD and HDC entities appear in ACRIS as free-text party names. We normalize variants (case, punctuation, LLC suffixes, historical name changes) against a published dictionary. If a variant is unknown, the record is stored but excluded from portfolio counts until an operator adds the mapping.

Adjudication history

The table below shows the last 200 adjudicated cross-check decisions with the extracted and reference values side-by-side and the operator's reason. Every decision persists; nothing is silently discarded.

No adjudication cross-checks have been recorded in this environment yet. Run the cross-check script against a snapshot to populate this table.

LLM security

The Ask endpoint is scoped to a single document: model context is populated only with page text and metadata for the document you are viewing. External URLs are not followed; user prompts cannot exfiltrate other documents. All Ask traffic is rate limited per session and the endpoint responds 401 when the environment is token-gated. Model output is stripped of HTML before rendering.

Notification channels

Alert deliveries currently support in-app queue only. Email and Slack channels are planned but disabled in this build. When they land, delivery routing and per-user digest windows will appear on the alert rule editor; nothing is emailed today regardless of what a rule is configured to do.

Changelog

Substantive changes to the methodology are logged in the git history of this application. Because this product is a public interface to a public dataset, the methodology is subject to change without notice as source datasets change; the ingest history above is your best guide to what actually changed and when.