Hand-computing the plan's own test expectations against its own formula
showed four assertions could not pass:
- Body-only matches maxed at 1.0*1/3 = 0.333, below minScore 0.35, so no
low-weight field could ever return a result. The gate now uses the raw
field score; the weighted score only orders.
- The phrase bonus was dead code whenever every token matched, since the
base already saturated at 1.0. Base is now scaled by 0.85.
- Natural-language queries tanked the coverage multiplier; query tokens
are now stopword-filtered.
- 'decide' vs 'decision' is 4 edits apart and unmatchable; scoreToken
gains a shared-prefix rule.
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>