Changelog¶
Unreleased¶
Added¶
Changed¶
Fixed¶
Deprecated¶
Contracts¶
Security¶
1.0.3 - 2026-04-21¶
Docs-only patch. Ships everything that landed on main after v1.0.2 (PR #23's
llms.txt + doc refresh) plus a cross-reference surfacing
nyc_geo_toolkit.centroids_from_boundaries from nyc311.spatial (closes
#24). No consumer code needs to change.
Added — machine-readable agent guide¶
docs/llms.txt— canonical llmstxt.org-style summary consumed by Cursor, Codex, Copilot, Claude Code, Aider, Zed, Windsurf, Gemini CLI, ChatGPT. Covers the public surface, typical workflows, contracts, install paths, examples, version ranges, ecosystem siblings. Added to mkdocs nav as "For LLMs / agents";AGENTS.mdgains a pointer at it.
Docs¶
nyc311.spatialmodule +load_boundaries_geodataframedocstring now cross-reference upstreamnyc_geo_toolkit.centroids_from_boundaries(v0.4+) for polygon-centroid extraction (addresses #24 via the doc-only path — nyc311 deliberately doesn't ship a centroid helper innyc311.spatialbecause the upstream helper is the one-stop shop).docs/integration.md— new "Upstream helpers worth knowing" section with the fullcentroids_from_boundaries → build_distance_weightscomposition recipe inline, including the(lat, lon)vs(lon, lat)GeoJSON axis-flip.docs/migration-v0-to-v1.md— new "v1.0.1 + v1.0.2 addenda" subsection with before / after snippets for theclosed_dateSDK / Socrata-bypass migration and the shapely-backed-centroid upgrade.docs/sdk.md—!!! tipblock in the spatial-weights section pointing at upstream's shapely-backed helper with the complete(lat, lon)adapter snippet forbuild_distance_weights.docs/integration.mdpin row refreshed to the v1.0.2 state (nyc-geo-toolkit>=0.3.0,<0.5).README.md— new v1.0.1closed_dateand v1.0.2 pin-widening subsections under the existing factor-factory integration block.AGENTS.md— new "Current release line" roll-up for v1.0.0 / v1.0.1 / v1.0.2 / v1.0.3.examples/factor-factory-quickstart/— extended to demonstrate bothoutcome="complaint_count"andoutcome="median_resolution_days"DiD fits against the same panel (the v1.0.1closed_datepivot workflow). Same panel, singleoutcome=swap, two ATT recoveries. README gains a "What's also in the panel" table documenting every numeric column the adapter exposes.
Ecosystem convergence¶
Not code changes in this release, but worth tracking:
nyc-geo-toolkitv0.4.1 (2026-04-21) — patch aligning the upstream showcase withjellycell.tearsheetsv1.4.0's native API. No public-surface change. Our>=0.3.0,<0.5pin accepts it automatically.- Jellycell v1.4.0 — landed upstream with the native
jellycell.tearsheetsAPI (#24) and deps-comma lint fix (#25). All six issues we filed from v1.0.0 dogfooding (J1 through J6) are closed. Ourjellycell>=1.3.5,<2pin accepts v1.4.0 via semver when it hits PyPI. A targeted alignment pass — droppingfactor_factory.jellycell.cells.setup()workarounds in favour of the native API — is a future concern gated on factor-factory's own update cycle. - Three downstream follow-ups filed: nyc311#24 (this release), subway-access#19 comment, blaise-website#20 (resolution-equity centroid swap).
1.0.2 - 2026-04-20¶
Patch release. Widens the nyc-geo-toolkit pin so consumers can pick up
upstream v0.4.0 (shapely-backed centroids_from_boundaries) alongside nyc311.
Changed¶
- Widen the
nyc-geo-toolkitpin from>=0.3.0,<0.4to>=0.3.0,<0.5so consumers can pick up the just-shipped nyc-geo-toolkit v0.4.0 alongside nyc311. The upstream v0.4.0 release adds a shapely-backed :func:nyc_geo_toolkit.centroids_from_boundarieshelper (closing random-walks/nyc-geo-toolkit#12). nyc311's own homegrownnyc311.temporal.centroids_from_boundariesis the shapely-free path and stays as-is with a new.. note::cross-reference in its docstring explaining when to use which — the two return different shapes (dict vs BoundaryCollection) on purpose.
1.0.1 - 2026-04-20¶
Patch release. Fixes #20 — resolution-time / SLA analyses no longer have to bypass the SDK.
Added¶
ServiceRequestRecord.closed_date(date | None, defaultNone) — carries the per-complaint resolution-date column through the full ingest / export / dataframe / Socrata pipeline. Fixes #20:bulk_fetch's Socrata$selectnow requestsclosed_datealongsidecreated_date, the CSV reader and writer both preserve the column, andrecords_to_dataframesurfaces it as adatetime64-typed column (with pandasNaT↔ PythonNoneround-trip). Consumers doing resolution-time / SLA analysis can computerecord.closed_date - record.created_datedirectly instead of bypassing the SDK.
Schema change is additive: existing call sites that instantiate
ServiceRequestRecord without closed_date keep working; the default None
models the unresolved-complaint case exactly as Socrata returns it. CSV
snapshots written by pre-v1.0.1 SDKs load without closed_date too — the CSV
column is optional.
1.0.0 - 2026-04-19¶
First major release. The headline is integration with
factor-factory — every
PanelDataset can now feed factor-factory's 17 causal-inference engine families
without leaving the nyc311 API.
Changed¶
- Drop Python 3.10 and 3.11 support. Minimum is now 3.12, to match upstream
factor-factory. Existing
nyc3110.3.x consumers on Python 3.10/3.11 should either stay on 0.3 or upgrade Python first. See migration-v0-to-v1.md. - Bump
nyc-geo-toolkitminimum to>=0.3.0,<0.4(from>=0.1.7,<0.2.0), to pick up the v0.3.0 modernization pass (Claude Code infra parity, factor-factory/jellycell showcase example, pin bumps). Existing nyc311 consumers ofnyc311.geographiesand the haversine helpers see no API changes — the upstream bump is additive. - CI: bump
actions/checkouttov6,setup-uvtov8.1.0(exact — no moving tag),upload-artifacttov7, keepdownload-artifact@v8. Add macOS and Windows runners to thetestsjob matrix.
Added — factor-factory integration¶
PanelDataset.to_factor_factory_panel()— additive adapter returning afactor_factory.tidy.Panelwith full treatment-event and spatial-weights round-trip.Pipeline.as_factor_factory_estimate()— thin bridge that dispatches intofactor_factory.engines.<family>.estimateon a converted Panel. Supports every factor-factory engine family (did, sdid, rdd, scm, mediation, changepoint, stl, panel_reg, inequality, spatial, reporting_bias, hawkes, survival, event_study, het_te, dml, climate, diffusion).nyc311.temporal.panel_dataset_to_factor_factoryandspatial_weights_from_panelas the function-style equivalents.nyc311.factors.dispatch_factor_factory_enginefor direct engine dispatch independently of thePipelineAPI.
Added — jellycell tearsheets¶
- New
tearsheetsoptional extra:pip install nyc311[tearsheets]pullsjellycell>=1.3.5,<2. - Both production case studies (
examples/case_studies/rat_containerization/,examples/case_studies/resolution_equity/) gained a new tearsheet-generation step that emitsmanuscripts/{METHODOLOGY,DIAGNOSTICS_CHECKLIST,FINDINGS,MANUSCRIPT,AUDIT}.mdalongside the authoritativeFINDINGS.md. Numbers are unchanged — the tearsheet is a parallel deliverable.
Added — new case studies¶
examples/sdid-multi-borough-policy/— self-contained showcase forfactor_factory.engines.sdidover a synthetic 5-borough 311 rollout. Runs offline in seconds.examples/mediation-cascade-resolution/— self-contained showcase forfactor_factory.engines.mediation.four_wayover a synthetic pilot → triage-time → resolution-rate cascade.
Added — Claude Code infrastructure¶
.claude/agents/release-auditor.mdand.claude/agents/factor-compat-auditor.md— read-only auditors for release preflight and factor-factory-bridge drift..claude/commands/{bump,release-check,run-case-study}.md..claude/skills/{factor-compat,stats-module-discipline,release-bump}.md..claude/settings.local.jsonpermissions allowlist,.claude/launch.jsondev-server configs.- Top-level
AGENTS.md(canonical cross-agent-vendor guide — Cursor / Codex / Copilot / Aider / Zed / Windsurf read this),CLAUDE.md(Claude-specific overlay),CONTRIBUTING.md,.github/PULL_REQUEST_TEMPLATE.md,CITATION.cff.
Added — examples showcases¶
examples/factor-factory-quickstart/— minimal no-jellycell showcase that exercisesPanelDataset.to_factor_factory_panel()→factor_factory.engines.did.estimate→ pandas in ~50 lines. Starting point for consumers who want the adapter without the reporting machinery.
Added — docs¶
docs/integration.md— crosswalk betweennyc311andfactor_factory(Panel schema, stats-module map, engine families).docs/migration-v0-to-v1.md— before/after snippets for consumer upgrades.- README — new "factor-factory integration" section + links to all four new engine-showcase examples.
docs/sdk.md,docs/architecture.md,docs/index.md,docs/releasing.md,docs/getting-started.md,docs/cli.md,docs/contributing.md,docs/examples.md— refreshed to v1.x framing;docs/architecture.mdmermaid now shows the two new bridges and the jellycell branch.
Added — previously-unreleased content¶
The causal-inference, spatial-econometrics, equity, reporting-bias, Bayesian,
and point-process statistical methods listed under ## 0.3.0 below shipped in
source on main under that tag, but additional polish, docstring
cross-references to factor-factory, and case-study wiring land together under
v1.0.0.
Changed — examples isolation¶
examples/*/uv.lockandexamples/*/.venv/are gitignored repo-wide. Example reproducibility comes from pinned version ranges in eachpyproject.toml, not from committed lockfiles. Four previously-committeduv.lockfiles (~5,000 lines) were dropped.- Hygiene-hook scope aligned with subway-access v0.5 conventions:
- prettier narrowed to
exclude: ^examples/.*\.md$(markdown-only; example yaml / json / pyproject still get prettier). - blacken-docs gained
exclude: ^examples/so showcase-authored Python code blocks in READMEs aren't rewritten to root-project style. - Top-level pre-commit
exclude:widened to^(\.cruft\.json|\.copier-answers\.yml|cache/.*|examples/.*/cache/.*|examples/.*/(manuscripts|artifacts)/.*|seeds/enhanced/research/.*)$— covers runtime caches (including symlinked ones), committed tearsheets/artifacts, and a reservedseeds/slot for future research notes. - Ruff
per-file-ignoresforexamples/**/*.pybroadened to the showcase-friendly set (unicode ambiguity, cross-platform shebang, print progress) — protects future examples from surprise lint failures. - Per-example
.gitignores strip trailing slashes from dir patterns (cache/→cache,artifacts/→artifacts, etc.). Trailing slash matches real dirs but not symlinks-to-dirs — the subway-access v0.5 engine-audit work surfaced this when a 631 MB cache was symlinked to shared storage and git started tracking it. No-trailing-slash matches both.
Changed — jellycell tearsheet reproducibility¶
- The four case studies commit their
manuscripts/*.mdtearsheets andartifacts/*.jsonresult files so the jellycell site is reproducible from a fresh clone without running the pipeline.factor_factory.jellycell.tearsheets.*is called withtemplate_overridespinningprojectto a stable display name andgenerated_atto a fixed string — committed output is byte-identical across machines. examples/case_studies/resolution_equity/figures/(3 PNG plots + 4 derived-research CSVs) is now committed rather than gitignored. The resolution-equity study can't be re-run without live Socrata access, so keeping the figures in git means a reviewer can inspect the study's visual output from a fresh clone.
Added — data provenance sidecars¶
Both production case studies now ship a data/demographics.csv.meta.json
sidecar describing the upstream Census ACS tables used (B01003_001E, B02001,
B19013_001E, B25003), the vintage year, the exact derivation formulas for
the two ratio columns (pct_nonwhite, pct_renter), the log transform on
log_median_income, and a how_to_regenerate note for future updates. Matches
subway-access v0.5's per-station data.json + research.md provenance
convention.
Removed — legacy cruft¶
examples/case_studies/rat_containerization/FINDINGS copy.md(duplicate ofFINDINGS.md, byte-identical, leaked into main in an earlier commit).
Known issues¶
Two upstream factor-factory bugs that the adapter test suite catches and
xfails with clear remediation notes. Neither affects the nyc311 adapter path
itself — the PanelDataset → Panel conversion is correct in both cases.
factor_factory.engines.panel_reg.pyfixestreferences a'Coefficient'column thatpyfixest>=0.50no longer emits. Workaround upstream is a column-name update.factor_factory.engines.stl.sktime_stlreads freq from the DataFrame MultiIndex, but pandas doesn't preserveDatetimeIndex.freqon MultiIndex levels afterset_index/sort_index. Workaround upstream is to fall back onpanel.metadata.freq.
Contracts¶
v1.0.0 introduces three new public contracts. All are additive and any change to
them after this release requires the
factor-compat-auditor
ceremony:
PanelDataset.to_factor_factory_panel(*, outcome_col, provenance, spatial_weights) -> factor_factory.tidy.PanelPipeline.as_factor_factory_estimate(panel, *, family, method, outcome, **engine_kwargs)Pipeline ↔ factor_factory.engines.*supported-family list (_SUPPORTED_FAMILIESinsrc/nyc311/factors/_factor_factory.py).
Each of the 11 nyc311.stats modules with a factor-factory equivalent gained a
.. note:: block cross-referencing the upstream engine as the preferred
backend. The homegrown functions continue to work for backwards compatibility.
0.3.0¶
- add composable factor pipeline (
nyc311.factors) with seven built-in domain factors (ComplaintVolumeFactor,ResolutionTimeFactor,TopicConcentrationFactor,SeasonalityFactor,AnomalyScoreFactor,ResponseRateFactor,RecurrenceFactor) and an immutablePipelinebuilder - add temporal panel module (
nyc311.temporal) with balanced panel construction, treatment-event modeling, and inverse-distance spatial weights - add statistical modeling module (
nyc311.stats) with interrupted time series, PELT changepoint detection, STL seasonal decomposition, global and local Moran's I (LISA) spatial autocorrelation, and panel fixed/random-effects regression wrappers - add
nyc311.pipeline.bulk_fetch()for full-city per-borough downloads with.meta.jsonintegrity sidecars - add the resolution-equity case study under
examples/case_studies/resolution_equity/, exercising the full v0.3.0 surface against ~1M real records - upgrade all model dataclasses to
frozen=True, slots=True - add the
statsoptional dependency group (ruptures,linearmodels,esda,libpysal,statsmodels) - add mypy overrides for the new optional dependencies
- align ruff per-file ignores with the example slugs convention so the resolution-equity case study scripts lint cleanly
- standardize public docstrings on Google-style
Args:/Returns:/Raises:so the mkdocstrings-rendered API reference is uniform across the package
0.2.6¶
- align the published changelog with the docs refresh that already shipped in
0.2.5 - keep the public docs, release notes, and package history in sync after the docs-only follow-up patch
0.2.5¶
- sharpen the README and core docs around the stable
0.2.xpackage surface - document the
nyc311andnyc-geo-toolkitrelationship more clearly across user-facing and maintainer docs - refresh install, contributor, and release guidance to match the current workflow
0.2.4¶
- delegate duplicated geography conversion and boundary-loading helpers back to
nyc-geo-toolkit - add CI coverage against
nyc-geo-toolkitonmainso downstream breakage is caught before release - stabilize compatibility and version checks across local CI, release builds, and the toolkit-main validation path
0.2.3¶
- refresh public authorship metadata to credit Blaise Albis-Burdige directly
- add
blaiseab.comas the portfolio link on package and docs surfaces - align README, docs, and site metadata with the same attribution model
0.2.2¶
- migrate reusable geography ownership to
nyc-geo-toolkit - preserve the public
nyc311.geographiesAPI through compatibility adapters - remove duplicated bundled boundary assets from
nyc311and depend on the published toolkit package instead
0.2.1¶
- polish the README and package metadata for a cleaner PyPI project page
- align docs wording with the shipped stable
0.2.xline - keep the release workflow current with the validated TestPyPI then PyPI path
0.2.0¶
- ship the first public stable release in the
0.2line - include topic coverage, resolution gaps, anomaly detection, report-card
export, dataframe helpers, and the refreshed
uvextras/groups and CI setup
Earlier History¶
0.2.0a1: internal milestone that retired the olderv0.1framing in favor of an explicit0.2release line
Release history¶
nyc311 tracks release history through GitHub Releases and tags.
-
0.1.0: original foundation release from the earlier narrow project phase - View tags
GitHub Releases remains the authoritative public record of shipped artifacts.