Stop a possessive from spending a head token-cap slot - #265
Merged
Conversation
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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 Storeindexes as[len, s, mill, store]— four clauses against aHEAD_QUERY_TOKEN_CAPof 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 Centerreturns empty whileQueens Medical Centeranswers — 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_candidatesalready 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 pizzawhere the producer wrotee3:domino s pizza.places_construction_head_recordsnow 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
fmt/clippy -D warningsclean, wasm32 checks clean.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.queries_without_an_apostrophe_are_bit_identical_to_query_termstest 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