Skip to content

Add structured court selector per jurisdiction - #219

Merged
nonprofittechy merged 3 commits into
mainfrom
120-better-court-selectors-per-jurisdiction
Sep 5, 2026
Merged

Add structured court selector per jurisdiction#219
nonprofittechy merged 3 commits into
mainfrom
120-better-court-selectors-per-jurisdiction

Conversation

@nonprofittechy

@nonprofittechy nonprofittechy commented Sep 5, 2026

Copy link
Copy Markdown
Member

Summary

Replaces the flat court dropdown with a multi-step, jurisdiction-aware court selector. Instead of scrolling through 200+ courts in one list, a filer answers a small number of progressive questions whose answers narrow the list to exactly the court they need.

Each state's court_selector block in its YAML config file drives the entire flow — no new per-state Python or JS is needed to add a new one.


What changed

New services

File Purpose
efile/services/court_selection.py YAML-driven selector engine: parses the court_selector block, evaluates when: conditions, filters courts by name_pattern/exclude_name_pattern, and computes step defaults
efile/services/court_location.py Location-to-court matchers for Massachusetts (MACourts) and Vermont (VTCourts), plus parse_place() for free-text address input

New API endpoint

GET /dropdowns/court-selector/ — serialises the current selector state (steps, filtered court lists, active answers) for the active jurisdiction.

New frontend

File Purpose
efile/static/js/court-selector.js Progressive-disclosure UI: each step renders only when its when: conditions are met; location steps fire the court-lookup API and show matched courts alongside the full list
efile/static/css/components/court-selector.css Scoped styles for the selector component

Per-state routing logic

Illinois — routes by county. A regex groups the Tyler court list by county, and only counties with sub-courts (Cook above all) show a second division/courthouse selector. Appeals are identified by appellate district.

Massachusetts — routes by department, then by place. MACourts translates a typed town or address into the courts that serve it; the full department list is always shown beside the lookup as a fallback.

Vermont — routes by Superior Court division. VTCourts looks up the unit from a town, county, or ZIP; the dropdown remains for filers who know their unit already.


Other changes

  • is_non_filing_court() extracted from dropdown_views into court_selection so the same filter applies to both the flat list and the new selector.
  • EXTRACTION_KEY_ALIASES + _normalized_key() added to extraction_fields so LLM variants of party-name labels ("plaintiff name", "petitioner names" …) resolve to the canonical key.
  • State YAML files (Illinois, Massachusetts, Vermont) now include the court_selector block documented in jurisdiction-config.md.
  • Playwright test utilities updated with a selectCourt() helper that drives the new selector UI; existing E2E tests updated to use it.

Testing

  • New unit tests in efile/tests/test_court_selection.py cover the selector engine and is_non_filing_court().
  • Existing Playwright E2E suite updated to use the new selector helper.
  • Extensive manual testing + iteration

Closes #120

Replace the flat court dropdown with a multi-step court selector that
walks a filer through the right questions for each jurisdiction:

- Illinois routes by county using a regex group on the Tyler court list,
  then optionally by division (Cook County gets sub-grouped by district).
- Massachusetts asks for department first, then uses MACourts to match a
  typed town/address to the courts that serve it; the full list is always
  shown alongside as a fallback.
- Vermont asks for Superior Court division, then uses VTCourts to look up
  the unit from a town, county, or ZIP; the dropdown stays for those who
  know their unit.

New services and files:
- efile/services/court_selection.py -- YAML-driven selector engine; parses
  the court_selector block, evaluates when: conditions, filters courts by
  name_pattern/exclude_name_pattern, and computes defaults.
- efile/services/court_location.py -- location-to-court matchers for MA
  (MACourts) and VT (VTCourts), plus parse_place() for free-text input.
- efile/api/court_selector_views.py -- /dropdowns/court-selector/ endpoint
  that serialises the selector state for the active jurisdiction.
- efile/static/js/court-selector.js + css/components/court-selector.css --
  progressive-disclosure UI; each step appears only when its when: conditions
  are met, and location steps fire the court-lookup API.

Supporting changes:
- is_non_filing_court() extracted from dropdown_views into court_selection
  so the same filter applies to both the flat list and the selector.
- EXTRACTION_KEY_ALIASES + _normalized_key() added to extraction_fields so
  LLM variants of party-name labels ("plaintiff name", "petitioner names" …)
  all resolve to the canonical key.
- State YAML files (illinois, massachusetts, vermont) gain the court_selector
  block documented in jurisdiction-config.md.
- Playwright test utilities updated with a selectCourt() helper that drives
  the new selector UI; existing tests updated to use it.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The new Playwright guided-court helper can be flaky due to insufficient waiting/step-type handling, and the new git deps are pinned to a moving branch in pyproject, risking non-reproducible installs.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR introduces a YAML-driven, jurisdiction-aware “guided court selector” that replaces the single flat court dropdown with a progressive question flow (including optional place-based matching for MA/VT), adds a dedicated API endpoint to power the selector, and updates E2E/unit tests and partner documentation accordingly.

Changes:

  • Added a selector engine (court_selection) + location matcher layer (court_location) and exposed it via GET /api/dropdowns/court-selector/.
  • Integrated the new selector UI into the extraction review + case lookup pages (new JS/CSS, template hooks), while keeping the underlying <select> as the submitted value.
  • Updated jurisdiction YAML configs + partner docs, plus expanded unit/E2E test coverage and adjusted Playwright execution to avoid shared-draft conflicts.
File summaries
File Description
efile_app/uv.lock Locks new git-based court-lookup dependencies and transitive packages (e.g., shapely).
efile_app/pyproject.toml Adds MACourts/VTCourts dependencies for MA/VT location-based court matching.
Dockerfile Installs git to support git-based Python dependencies during image builds.
efile_app/playwright.config.js Forces serial Playwright execution to prevent shared test account/draft collisions.
efile_app/tests/test-utils.js Adds E2E helpers for guided court selection and conditional step continuation.
efile_app/tests/test-optional-services-e2e.spec.js Updates E2E flow to use the guided selector and new continuation helpers.
efile_app/tests/reorganized-filing-matrix.spec.js Updates filing-matrix E2E flows to use guided court selection and new helpers.
efile_app/tests/document-classification-sentinel.spec.js Updates extraction review assertions to match updated UI/field behavior.
efile_app/efile/tests/test_document_extractions.py Adds tests ensuring party-name key normalization canonicalizes common variants.
efile_app/efile/tests/test_court_selection.py Adds comprehensive unit tests for selector engine, endpoint behavior, and matchers.
efile_app/efile/templates/efile/workflow_base.html Adds global inclusion of the court selector component stylesheet.
efile_app/efile/templates/efile/extraction_review.html Adds selector mount point and loads the selector JS on extraction review.
efile_app/efile/templates/efile/case_lookup.html Adds selector mount point, improves labeling, and loads selector JS on case lookup.
efile_app/efile/static/js/extraction-review.js Mounts guided selector when available; improves handling of non-filing courts.
efile_app/efile/static/js/case-lookup.js Mounts guided selector when available; adds explicit “court required” submit validation.
efile_app/efile/static/js/court-selector.js Implements the progressive guided selector UI driven entirely by the API payload.
efile_app/efile/static/css/reorganized-flow.css Adjusts extraction review layout when the selector is present.
efile_app/efile/static/css/components/court-selector.css Adds component-scoped styles for the guided selector UI.
efile_app/efile/static/config/states/illinois.yaml Adds Illinois court_selector config (county/division/appellate routing).
efile_app/efile/static/config/states/massachusetts.yaml Adds Massachusetts court_selector config + court renaming rules + place matcher.
efile_app/efile/static/config/states/vermont.yaml Adds Vermont court_selector config + unit selection and optional place matcher.
efile_app/efile/services/extraction_fields.py Adds extraction key aliases to normalize party-name label variants consistently.
efile_app/efile/services/court_selection.py New YAML-driven selector engine; includes shared “non-filing court” filtering.
efile_app/efile/services/court_location.py New MA/VT location-to-court matching layer and place parsing utilities.
efile_app/efile/prompts/document_evidence_extraction.yaml Strengthens prompt instructions to always extract party names from case captions.
efile_app/efile/api/urls.py Registers the new /api/dropdowns/court-selector/ endpoint.
efile_app/efile/api/dropdown_views.py Reuses is_non_filing_court() from the shared selector service.
efile_app/efile/api/court_selector_views.py New endpoint implementation for guided selector state serialization.
docs/docs/partners-courts/jurisdiction-config.md Documents court_selector configuration format and matcher behavior for partners.
Review details
  • Files reviewed: 28/29 changed files
  • Comments generated: 2
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread efile_app/pyproject.toml
Comment on lines +28 to +30
"suffolklitlab-macourts @ git+https://github.com/SuffolkLITLab/MACourts@main",
# Vermont Superior Court unit lookup by town, county, or ZIP.
"suffolklitlab-vtcourts @ git+https://github.com/SuffolkLITLab/VTCourts@main",

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is fine for now, also we control both repos. will move to PyPI later

Comment thread efile_app/tests/test-utils.js
nonprofittechy and others added 2 commits September 5, 2026 16:08
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@nonprofittechy
nonprofittechy merged commit ef31822 into main Sep 5, 2026
7 checks passed
@nonprofittechy
nonprofittechy deleted the 120-better-court-selectors-per-jurisdiction branch September 5, 2026 20:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Make courts hierarchical based on county/equivalent when in dev?

2 participants