As of April 2026, the
council_decisions, zoning_variances, and environmental_reviews tables are now actively populated. Legistar-sourced records can use an HTML collection path for cities where the JSON API is no longer accessible, and California environmental reviews are sourced from the CEQANet registry. EPA EIS records are not yet available — see known limitations for details.record_id, chunk_id, bitemporal fields, confidence_score, provenance) and carries the join keys documented below.
Dataset-specific fields
Document types
Entities
Theentities_extracted field contains an array of entities mentioned in the record. Each entity includes:
councilmember, mayor, planning_commissioner, zoning_board_member, developer, resident, attorney, city_agency_staff, state_agency_staff, nonprofit_representative, business_owner, expert_witness, other.
Sentiment values: supportive, favorable, neutral, concerned, opposed, hostile.
entity_urn is populated by the entity resolution pipeline. Records where resolution has not yet run will have null URNs.Blockers
Ordered array of blocker tags identified by the LLM as standing between a proceeding and final approval:Contingency DAG
Thecontingency_dag field represents conditional approval chains as a directed acyclic graph:
pending, approved, denied, withdrawn, deferred.
Scores
Upzoning probability
Classifier-estimated probability that the proceeding results in zoning changes allowing greater density or use intensity. Built with DistilBERT fine-tuned on council minutes with labeled upzoning outcomes. Features includelanguage_signals, entity sentiment distribution, document_type, and historical base rate by jurisdiction.
>= 0.600— flagged as “likely”>= 0.850— flagged as “highly likely”
Hostility index
Aggregate of hostile-sentiment entity mentions and opposition-coded language signals, normalized to document length. Predicts procedural delay, not outcome.Litigation risk score
Probability of a formal legal challenge (lawsuit, appeal to state board) within 24 months. Built with a gradient boosted classifier trained on historic filings matched to upstream proceedings. Features includehostility_index, presence of attorney role in entities, litigation_threat blocker tag, and jurisdiction base rate.
>= 0.700— flagged as “high risk”
Join keys
Example query
Find high litigation-risk zoning votes in Philadelphia:HTML collection mode
Legistar provides a JSON API for accessing council matters, but many cities have restricted API access behind authentication tokens. When the JSON API is unavailable for a jurisdiction, the collector can switch to an HTML collection mode that scrapes the same data from Legistar’s public web pages.How it works
The HTML collector follows the same three-page navigation path a user would on a Legistar site:- Calendar page — the collector reads the meeting calendar to find upcoming and recent meetings for zoning-related bodies.
- Meeting detail page — for each relevant meeting, the collector retrieves linked legislation items.
- Legislation detail page — each legislation item is scraped for matter ID, file number, title, type, status, and key dates (introduced, on agenda, final action).
Zoning variance filtering
The zoning variance collector uses keyword-based filtering to identify relevant records from the full stream of council matters. Records are included if any of the following match: Body keywords — checked against the legislative body or committee name:zoningboard of appealsboard of adjustmentplanning commissionland use
varianceconditional usespecial permitspecial usecup
These filters differ from the ones used by the council monitor, which targets broader development-related activity (rezoning, demolition, TIF districts, etc.). The zoning variance collector is narrower and focused specifically on variance and conditional-use proceedings.
Date handling
Records collected via the HTML path may include dates inm/d/YYYY format (for example, 3/15/2026) rather than the ISO format returned by the JSON API (2026-03-15T00:00:00). The collector normalizes all date formats before storage, so occurred_at and other date fields are always stored as ISO dates regardless of the collection path.
Identifying HTML-sourced records
Records collected via the HTML path havesource set to legistar_html. You can use this to distinguish them from JSON API records (source = 'legistar') in queries:
Signal extraction backend
LLM-based signal extraction (used to populateentities_extracted, language_signals, blockers, and item-level fields like outcome, units, and dollar_amount) runs on a configurable backend. Schema-constrained classification work defaults to a local model; the hosted Anthropic backend is opt-in.
Backend selection
The Granicus extractor selects a backend based on theCIVIC_EXTRACTOR environment variable:
When
CIVIC_EXTRACTOR is unset or set to ollama, the extractor calls the local runtime only — there is no silent fallback to Anthropic. If the local runtime returns a non-200 response or invalid JSON, the record is skipped and extracted_signals remains null. Re-run the extractor after the local runtime is restored to populate skipped records.
Configuration
Output schema
Both backends are prompted with the same schema, so downstream consumers — including thecivic_decision_signals materialized view — observe identical field shapes regardless of which backend produced a record. Each item carries item_type, outcome, units, sqft, dollar_amount, h3_signal, development_sentiment, and high_signal.
Example
Run a one-off backfill against the hosted Anthropic backend:Known limitations
- Jurisdictional coverage is uneven — dense for San Francisco, Philadelphia, and Boston; sparse for sunbelt growth markets.
- CivicPlus ingestion has been retired. The upstream
/AgendaCenter/ViewFile/...URL pattern the scraper depended on is no longer served by the tracked city domains, so no new records withsource = 'civicplus'are being landed. Historical CivicPlus rows remain valid and queryable, and thecivicplusvalue stays in thesourceenum for backward compatibility. Coverage will resume once a rebuilt scraper ships. language_signalsvocabulary is English-only. Bilingual meetings may underperform on signal extraction.- Transcripts lag real-time by 24–72 hours. Use
occurred_atfor event-time analysis, notingested_at. - The legacy
document_datefield is retained for backward compatibility. Useoccurred_atinstead. - Legistar HTML-sourced records (
source = 'legistar_html') may have null date fields when the source page uses non-standard labels. Most major cities — including New York City, Seattle, San Francisco, and Chicago — now resolve titles, sponsoring bodies, and dates through multiple fallback labels, but some jurisdictions may still return nulls. Filter onoccurred_at IS NOT NULLif your query requires dates. - EPA EIS environmental reviews are not yet available. The
environmental_reviewdocument type currently covers California CEQA filings (via CEQANet) only. Federal NEPA coverage is planned. - Records collected while the local extraction backend was unreachable have null
extracted_signalsand may also have emptyraw_textif the upstream Granicus transcript fetch did not complete. These records require both the upstream fetch and the extractor to be re-run before signals appear. See signal extraction backend for backend configuration.