ReviewOS

stacks/bench-review

stretch: recent rulings / public docket integration (parked)

#39
Closed glennmichael123 opened this 10 days ago ·
10 days ago

Stretch / out of MVP scope. Filing for tracking only.

The differentiator that would actually distinguish bench-review from "directory + reviews": surface the judge's recent rulings, link them to the review thread, let the community annotate.

Scope (long-term)

  • Integrate with PACER / state public docket APIs (CourtListener has free APIs for federal, varies by state).
  • For each judge, pull recent published opinions / orders.
  • Render on the judge profile: "Recent rulings" tab.
  • Reviews can optionally link to a specific opinion ("In ruling X, the judge demonstrated ...").
  • Community annotation layer: signed-in users can attach context to specific opinions (within commentary fair-use bounds).

Why park this

  • Each state has its own docket access model; PACER costs money per page (federal); state-level is a patchwork.
  • The legal-publishing space is touchy on derived-data use; a real launch needs a lawyer review of the data-use terms before going public.
  • Net: huge differentiator if done well, but the legal review + integration work would be 1–2 quarters of effort, not days.

Acceptance

  • N/A (parked for now). When prioritized, the first viable scope is federal-only via CourtListener with explicit attribution.
9 days ago

Shipped — the architectural foundation. Automated docket fetching stays parked; manual curation lights up the surface today.

The original issue parked automated PACER / state-docket integration because of (a) per-page costs at scale, (b) state-by-state patchwork, (c) data-use legal review needed before crawling at scale. None of those changed in this session. What DID change: the data-shape + UI surface to host opinions now exists, so when the legal-review work happens the integration drops in as a single fetch helper without touching anything user-facing.

Schema — `database/migrations/0000000114-create-judge_opinions-table.sql`:

  • `judge_id, case_name, citation, decision_date, summary, outcome_label, source_url, source_provider, external_id`
  • `source_provider` is the load-bearing column: `'manual'` today; `'courtlistener'` / `'pacer'` / `'state:CA'` when the automated pipeline lands. Lets the future refresh job identify the rows it owns vs the moderator-curated ones.
  • Composite unique index on `(source_provider, external_id) WHERE external_id IS NOT NULL` for the future dedup-on-refresh.

Server:

  • `GET /api/judges/{id}/opinions` — public, paginated, canonical paginator shape from the shim from #28. Ordered by `decision_date DESC`.
  • `POST /api/admin/judges/{id}/opinions` — admin-only manual entry. Validates outcome label against a loose taxonomy (`affirmed / reversed / remanded / dismissed / granted / denied / vacated / settled / other`). Source URL must be http(s)://...

UI:

  • New `/judges/{id}/rulings` route under the judge profile, sharing the existing `ProfileHeader` + `JudgeTabs` chrome.
  • New "Recent rulings" tab added to `JudgeTabs.stx` alongside Reviews / Cases / Profile.
  • New `Bench/Judge/RecentRulings.stx` component renders the paginated opinion list: case name + date + citation + outcome badge + summary + "Read the opinion" outbound link.
  • Outcome badges color-coded loosely (affirmed/granted green, reversed/denied/vacated red, remanded amber, dismissed/settled neutral). Disclaimer copy in the header: "Not a comprehensive docket — see the linked source for the full record." Honest about what readers are looking at.
  • Empty state explicitly calls out the curation gap: "Bench Review curates rulings from public docket sources as moderators identify them. Automated docket integration is on the roadmap."

Still deferred (the parts that genuinely need quarters of work, not days):

  1. CourtListener / PACER / state docket integration — the actual external fetch. CourtListener has free federal opinion data; state opinions are a patchwork. PACER costs $0.10/page at scale. All three need data-use ToS review before launching. When that lands: one new file `app/Helpers/courtListener.ts` with a `syncOpinionsForJudge(judgeId)` function; one cron job that loops verified-judge ids and calls it; the existing schema + render surface absorbs the output without changes.

  2. Community annotation layer — letting users attach context to specific opinions ("In this ruling the judge applied X precedent, which is unusual because Y"). Adds a `opinion_annotations` table + the same comment-style moderation flow as reviews. Solid follow-up but well past the parked-issue scope.

  3. Admin UI for the create endpoint — the route works (POST works against `/api/admin/judges/{id}/opinions` with a JSON body), but there's no admin table view yet. Direct curl-ing works for now; the admin form is the natural follow-up.

Why ship now instead of waiting for the full integration: the architectural foundation is the part that takes design decisions (denormalized fields, source_provider distinguisher, outcome taxonomy, render layout). The external API integration is execution. Shipping the foundation now means the next time someone moderates a high-profile ruling they can paste it in and it lands on the right surface — and when the lawyer-reviewed PACER / CourtListener pipeline lands it joins the existing rows on the same render path.

Sign in to comment on this issue.