Skip to content

Stop a possessive from spending a head token-cap slot - #265

Merged
brad-richardson merged 1 commit into
mainfrom
fix/apostrophe-fragment-token-cap
Aug 7, 2026
Merged

Stop a possessive from spending a head token-cap slot#265
brad-richardson merged 1 commit into
mainfrom
fix/apostrophe-fragment-token-cap

Conversation

@brad-richardson

Copy link
Copy Markdown
Owner

Implements the Worker half of docs/plans/2026-08-07-apostrophe-folding-locus.md. No rebuild required.

The defect

The apostrophe is a plain separator on both sides of the pipeline, so Len's Mill Store indexes as [len, s, mill, store] — four clauses against a HEAD_QUERY_TOKEN_CAP of three. The head refuses the query before any read.

Measured on the corpus production serves: 733,701 records are over the cap only because of that split. Live today, Queen's Medical Center returns empty while Queens Medical Center answers — from different records that happen to be spelled without one.

The fix

The AND lanes drop apostrophe-born one-character fragments. A fragment has no retrieval value to lose: its posting is saturated by construction, and merge_bounded_candidates already admits a record absent from a saturated posting when its own display tokens carry the token. Dropping it removes a cap cost, not evidence.

Three things it deliberately does not do

It does not touch the phrase lane. eN: keys are built from the record's full name, fragment included, so a filtered key names something the head does not contain — e2:domino pizza where the producer wrote e3:domino s pizza. places_construction_head_records now takes the unfiltered clauses and the filtered clauses separately, and a test pins exactly that reason.

It does not drop short tokens generally. 5,071,193 records carry a one-character token with no apostrophe anywhere — H&M, A&W, initials, single CJK characters — and are retrievable today only because those postings survive. A blanket rule would break a working class to fix a broken one.

It does not treat U+02BC as an apostrophe. I assumed it was one and the test caught me: Unicode classifies the modifier letter as a letter, so the index tokenizer never splits on it and there is no fragment to drop. The test now asserts that, so a future "add the other apostrophes" change has to face it first.

A query that is nothing but fragments (L'A) keeps its clauses — an empty AND retrieves nothing at all, which is strictly worse than what this replaces.

Verification

  • Worker tests 249 passed (5 new), workspace green, fmt/clippy -D warnings clean, wasm32 checks clean.
  • Python pipeline suite 1,810 passed, 2 skipped.
  • The head cap contract test (test_worker_global_head_uses_one_three_token_cap) fired twice during development — once on a test local and once on a comment quoting the guard expression. The five production cap-guard sites are unchanged; the count is still 5.
  • A queries_without_an_apostrophe_are_bit_identical_to_query_terms test pins that every case in both frozen sets tokenizes exactly as before.

Before merge

This is a retrieval-path change, so the standing rule applies: it ships behind a paired measurement on the gold and everyday sets — and now the proximity stratum too, via #261. It needs a production deploy with an immediate paired compare and rollback readiness, since there is no Worker preview environment.

🤖 Generated with Claude Code

The apostrophe is a plain separator on both sides of the pipeline, so
`Len's Mill Store` indexes as [len, s, mill, store] and a query for it
arrives as four clauses against a HEAD_QUERY_TOKEN_CAP of three. The head
refuses it before any read. Measured on the corpus production serves,
733,701 records are over the cap ONLY because of that split, and production
returns empty for `Queen's Medical Center` while answering
`Queens Medical Center` -- from different records that happen to be spelled
without one.

The AND lanes now drop apostrophe-born one-character fragments. A fragment
has no retrieval value to lose: its posting is saturated by construction, and
merge_bounded_candidates already admits a record missing from a saturated
posting when its own display tokens carry the token. Dropping it removes a
cap cost, not evidence.

Three things this deliberately does not do.

It does not touch the phrase lane. `eN:` keys are built from the record's
full name, fragment included, so a filtered key names something the head does
not contain -- `e2:domino pizza` where the producer wrote
`e3:domino s pizza`. The lanes now take the unfiltered clauses and the
filtered clauses separately, and a test pins that reason.

It does not drop short tokens generally. 5,071,193 records carry a
one-character token with no apostrophe anywhere -- H&M, A&W, initials, single
CJK characters -- and are retrievable today only because those postings
survive.

It does not treat U+02BC as an apostrophe. Unicode classifies the modifier
letter as a letter, so the index tokenizer never splits on it and there is no
fragment to drop; the test asserts that so a future "add the other
apostrophes" change has to face it.

A query that is nothing but fragments keeps its clauses, because an empty AND
retrieves nothing at all.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@brad-richardson
brad-richardson merged commit fc90f1f into main Aug 7, 2026
9 checks passed
@brad-richardson
brad-richardson deleted the fix/apostrophe-fragment-token-cap branch August 7, 2026 02:54
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.

1 participant