Skip to content

fix: derive L2 fullmap keys through one shared Unicode-aware filter - #252

Merged
SkyeAv merged 1 commit into
mainfrom
fix/l2-nonascii-parity
Nov 9, 2026
Merged

SkyeAv merged 1 commit into
mainfrom
fix/l2-nonascii-parity

Conversation

@SkyeAv

@SkyeAv SkyeAv commented Nov 5, 2026

Copy link
Copy Markdown
Owner

Level-two fullmap keys were derived by an ASCII-only filter at build time but by a Unicode-aware polars regex at query time, so non-ASCII terms could never match at level two while level one stayed unaffected. Both sides now share one implementation, mirroring the single-source-of-truth contract level one already has.

Shared Filter

  • Rust key definition: fullmap::level_two now keeps Unicode alphanumeric characters plus underscore (c.is_alphanumeric() || c == '_') instead of stripping every non-ASCII byte, and is pub(crate) so the normalizer module can route through it.
  • Python batch surface: a new normalize_terms_l2 pyfunction in rust/src/nlp.rs exposes that exact filter (GIL released via py.detach, rayon fan-out, index-aligned, same shape as normalize_terms), registered in rust/src/lib.rs and declared in src/tablassert/rs.pyi.
  • Query path: nlp.level_two's default pattern routes through rs.normalize_terms_l2 via the same map_batches whole-column shape level_one uses (nulls never reach Rust, one GIL-released call per column); a custom regex keeps the vectorized polars path and is documented as a generic cleaner with no build-side key contract.

Golden Regeneration

  • Rust build_golden: loses the three ASCII-stripped level-two twins of non-ASCII names (caf, nave, t; each level-two form now equals its level-one form and stores no extra key) and gains β-catenin / βcatenin from a new Greek-letter fixture name in rust/tests/common/mod.rs.
  • Python mirror: tests/test_fullmap_golden.py updates in lockstep (54 golden rows / 51 probes) and gains the issue's reproduction table as tests/test_nlp.py parity tests against rs.normalize_terms_l2.

Docs

  • docs/api/fullmap.md, docs/api/lib.md: the level_two sections now describe the shared compiled Rust filter instead of the \W+ polars regex.
  • docs/fullmap.md: notes that fullmaps built before this change must be rebuilt (build-fullmap) for non-ASCII level-two lookups; the on-disk schema tag is unchanged.

Testing

  • Issue reproduction on the fixed tree: level_two(level_one(...)) and rs.normalize_terms_l2 both return aucafélait / βcatenin for Café au lait / β-catenin.
  • make check -> ruff clean, pyright 0 errors, pytest 1355 passed, 1 skipped (the env-gated config-corpus sweep), cargo test 129 + 11 + 17 + 1 pass across lib/integration suites, clippy -D warnings clean.
  • uv run mkdocs build --strict -> built; markdownlint-cli2 -> 0 issues.

Fixes #251

…nd query

Level-two fullmap keys were derived by an ASCII-only filter at build time
(rust/src/fullmap.rs level_two) but by a Unicode-aware polars regex at query
time (nlp.level_two), so non-ASCII terms could never match at level two while
level one stayed unaffected.

Both sides now share ONE implementation, matching the level-one contract:

- fullmap::level_two keeps Unicode alphanumeric characters plus underscore
  instead of stripping every non-ASCII byte, and is pub(crate) so nlp.rs can
  route through it.
- A new normalize_terms_l2 batch pyfunction exposes that exact filter to
  Python (GIL released, rayon, index-aligned, same shape as normalize_terms).
- nlp.level_two's default pattern routes through rs.normalize_terms_l2 via
  map_batches (nulls preserved, one Rust call per column); a custom regex
  keeps the vectorized polars path with no build-side contract.
- Golden pins regenerated deliberately: build_golden loses the three
  ASCII-stripped level-two twins of non-ASCII names (caf, nave, t -- each
  level-two form now equals its level-one form) and gains beta-catenin /
  betacatenin from a new Greek-letter fixture name; the Python
  test_fullmap_golden mirror updates in lockstep (54 rows / 51 probes).

Existing fullmaps must be rebuilt (build-fullmap) after upgrading: their
stored level-two keys predate the fix, so non-ASCII terms cannot resolve at
level two against them. The on-disk schema tag is unchanged.

Fixes #251
@coderabbitai

coderabbitai Bot commented Nov 5, 2026

Copy link
Copy Markdown

Important

  • Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

Run configuration

  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: c1f15d97-3578-4bc6-a47c-643d530da9d8
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

@SkyeAv
SkyeAv merged commit 1f65888 into main Nov 9, 2026
9 checks passed
SkyeAv added a commit that referenced this pull request Nov 9, 2026
Cut 22.3.0 and bump the package version in pyproject.toml,
CITATION.cff, and uv.lock.

Minor: add mechanical patch/minor/major release targets (#250) and
share one Unicode-aware level-two filter between fullmap build and
query paths, fixing non-ASCII term resolution (#252). Existing
fullmaps must be rebuilt with build-fullmap after upgrading; the
on-disk schema tag is unchanged.

The real-checkout bump test now derives its expected patch version
from pyproject.toml instead of pinning 22.2.2.

Changelog:
- Added the 22.3.0 - 2026-11-09 section covering #250 and #252
  with PR links and the fullmap rebuild requirement.

Docs: added the PyPI downloads badge to README.md.

Testing:
- make check -> Ruff, formatting, Pyright, and Clippy passed;
  Python 1355 passed, 1 skipped; Rust 158 passed, 1 ignored.
- uv lock --check -> resolved 139 packages.
- uv run mkdocs build --strict -> documentation built.
- npx markdownlint-cli2 -> 0 issues in 24 files.
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.

fix: L2 fullmap keys diverge between build and query for non-ASCII terms

1 participant