Skip to content

fix(tokenizers): relax whitespace at full-cite template boundaries - #339

Open
jaysoma wants to merge 2 commits into
freelawproject:mainfrom
jaysoma:glued-citation-boundaries
Open

fix(tokenizers): relax whitespace at full-cite template boundaries#339
jaysoma wants to merge 2 commits into
freelawproject:mainfrom
jaysoma:glued-citation-boundaries

Conversation

@jaysoma

@jaysoma jaysoma commented Aug 13, 2026

Copy link
Copy Markdown

Fixes

Fixes: #338

Summary

Glued citations (846F.2d746) currently extract as nothing: the full-cite
template requires exactly one literal space at the volume-reporter and
reporter-page boundaries. This extends #305's whitespace relaxation to those
two boundaries:

  • full_cite template becomes r"$volume\s*$reporter,?\s*$page"
  • _relax_ws now trims its trailing \s* so the reporter group cannot
    capture boundary whitespace (reporter='U.S. ') once the mandatory
    template space is gone.

Measured on the 7,740 glued-citation opinions from the bulk scan (details in
#338): 7,737 recovered citations across 4,141 documents, no losses of
previously-extracted citations, existing test suite unchanged. New regression
tests cover glued full/short cites, composition with #305, group cleanliness,
and a non-citation negative.

AI Disclosure

  • No AI tools were used to create the content of this PR.
  • Parts of this PR were created with the help of an AI tool, and I have carefully reviewed all of its content and take full responsibility for it.

Glued citations (846F.2d746, 410U.S.113) extract as nothing because the
full-cite template requires exactly one literal space at the
volume-reporter and reporter-page boundaries. Relax both to \s*,
extending the freelawproject#305 within-reporter relaxation, and trim the trailing
\s* from _relax_ws output so the reporter group cannot capture boundary
whitespace once the mandatory template space is gone.

Fixes freelawproject#338

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Claude Code Review

This pull request is from a fork — automated review is disabled. A repository maintainer can comment @claude review to run a one-time review.

@CLAassistant

CLAassistant commented Aug 13, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

The nonalphanum boundary wrappers consume one character on each side of a
match, so under finditer semantics a separator consumed as one citation's
trailing boundary was unavailable as the next citation's leading boundary,
and the second of two adjacent citations was silently skipped:
"347 U.S. 483,349 U.S. 294" lost "349 U.S. 294". The swallow predates the
glued-citation relaxation and exists on main for unglued text; glued OCR
text simply produces more adjacent pairs.

TokenExtractor.get_matches now resumes scanning at the end of the token
content (group 1) rather than the end of the boundary-consuming match, so
the separator stays available. HyperscanTokenizer reports overlapping
matches and never had this blind spot; this aligns the pure-Python
tokenizers with it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@jaysoma

jaysoma commented Aug 13, 2026

Copy link
Copy Markdown
Author

I ran this patch against real-world data to validate it beyond the unit tests:
a bulk scan of the CourtListener opinion dump (10.8M rows) found 7,740 opinions
containing glued citations, and I replayed both pristine main and this branch
over the stored context windows of every one of them (11,748 unique windows
across 7,489 documents after deduplication).

Recovery: 7,416 windows in 4,141 documents gained citations that main
extracts nothing from — 6,568 FullCaseCitation, 1,166 ShortCaseCitation,
3 SupraCitation. Known specimens (846F.2d746, 443U.S.307,
42U.S.C.§1983) all extract with correct volume/reporter/page groups.

Regressions: the diff initially showed 14 windows where the branch lost a
citation main had found. On inspection:

  • 9 are a bare SupraCitation("supra,") replaced by the short citation it
    pointed at (Attaway, supra, 757F.2d at 1241-42 — main only saw the
    supra; the branch recovers 757 F.2d at 1241 and the overlap filter
    absorbs the supra, preserving the referent as antecedent_guess). Net
    information gain.
  • 3 are garbage UnknownCitation blobs (e.g.
    544(2007);28U.S.C.§1915.Dismissal…) replaced by real citations.
  • 1 was a true regression, now fixed by the second commit: in
    347U.S. 483,349 U.S. 294 the first citation's consuming trailing
    boundary swallowed the comma, starving the second citation's leading
    boundary. Notably this swallow exists on main for unglued text
    get_citations("347 U.S. 483,349 U.S. 294") returns only the first
    citation — and only the pure-Python tokenizers are affected;
    HyperscanTokenizer reports overlapping matches and never had the blind
    spot. TokenExtractor.get_matches now resumes scanning at the end of the
    token content rather than the end of the boundary-consuming match, which
    aligns the tokenizers and fixes both the glued and unglued cases.

Over-capture, documented honestly: when OCR glues a preceding number
onto the volume, the digits are inherently ambiguous: …U.S. 137, 8 S. Ct. 38… glued to 1378S. Ct. 38 extracts volume 1378. About 285 of the ~7.7k
newly matched instances (≈4%) are in this class (recognizable here by
impossible S. Ct. volumes). Two things worth noting: (1) main already
extracts volume 1378 from the properly-spaced string — eyecite has no
volume-plausibility gating anywhere, so this is pre-existing behavior that
glued input merely produces more of; (2) a fabricated-looking volume still
fails any downstream lookup, whereas main extracts nothing from these
windows at all. A volume-plausibility check against reporters-db ranges
would be a natural follow-up if there's interest.

Also observed: the overlap filter now sees pairings it has no rule for
(Supra followed by adjacent ShortCase, parallel ShortCase pairs) and
logs "Unknown overlap case" warnings; outcomes are reasonable but
order-dependent (the supra is absorbed in one processing order, kept
alongside in the other). Happy to file that separately.

Replay harness and full per-window diffs are available if useful.

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.

Glued citations (846F.2d746): relax whitespace at the full-cite template boundaries -- completes #305

2 participants