Repository navigation
0.7.8: typo-tolerant make lookup, top_models(country:) by the country's own rank, dataset 2026.10.0 - #5
Merged
Conversation
…y's own rank + dataset 2026.10.0
- Vehicles.make / models / find: bounded Levenshtein fallback after exact,
alias and slug matching (1 edit for 4-5 chars, 2 from 6, none under 4),
unique-best only — two equally close makes return nil ("Acra": Acura/Acma).
"marcedes" -> Mercedes-Benz, "volkswagon" -> Volkswagen. fuzzy: false opts
out; both validators are exact-only. find runs its exact pass first, so no
0.7.7 answer changes.
- Model#country_ranks / #rank_in; top_models(country:) sorts by that rank
(unranked-there after, global order; data without the key = 0.7.7 order).
- Bundled snapshot 2026.07.4 -> 2026.10.0 via new rake "data:refresh[tag]",
which merges country_ranks from the same tag's catalog/ (asserts equality
once the projection ships the key natively — vehiclesdb-pipeline emit).
Co-Authored-By: Claude Opus 5.5 <[email protected]>
…dels/model/model_options
Codex review findings (both P2, both applied):
- Fuzzy.unique_closest accepted a lone length-compatible key at limit + 1
(`best` starts there): Vehicles.make("z" * 28) returned Saxas Nutzfahrzeuge
Werdau. Now gated on the limit; regression test added.
- models / model / model_options changed behaviour through make() but could
not take the exact-only opt-out; they now accept and forward fuzzy:.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Found by the DEVQ A1 resolver sweep: "volvo v" is two edits from "volvo",
so in find's fuzzy pass the make prefix swallowed the model's letter and
"Volvo V 60" resolved to Volvo "60" (same for "Mercedes-Benz B 180" ->
"180"). Word-deleting matches are now rejected; same-word-count typos
("marcedes benz") and fewer-words queries ("DeLorean" -> "De Lorean")
still resolve. Regression test added.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Found by the DEVQ A1 parity run through the web resolver's longest-prefix loop: "citroen e" is two edits from "citroen ds", so "Citroën e-C3" became Citroën DS C3 (and "peugeot e"/"volkswagen e" pulled e-5008 / e-Up onto the ICE ids before the word-count rule). Word-for-word initials must now agree. Parity: 1,255 A1 sweep queries resolve identically to production 0.7.7. Co-Authored-By: Claude Opus 5.5 <[email protected]>
1 (P2) Fuzzy.distance is now optimal string alignment: an adjacent swap is
one edit, so "telsa" ties Tesla/Temsa -> nil instead of confidently Temsa
(also "seta" no longer -> Setra). Early exit checks two rows.
2 (P2) the configured other_label never fuzzy-matches ("Otra" -> Ora broke
models(other_label, include_other: true)).
4 (P3) MCP top_models note describes the per-country order.
5 (P3) README rank_in example (the Corolla is gb #51; use the Golf, #2);
remaining "14 countries" -> 15, South America added.
6 (P3) README: ranks are per kind; us/ca cars have no ranks (global order).
7 (P3) README + CHANGELOG document the word-count / first-letter / swap guards.
8 (P3) data:refresh accepts refs/tags only; array-form git calls.
3 (P2, web) is filed for the coordinator: resolver.rb rung 3 should run an
exact pass (fuzzy: false) before a fuzzy one and label typo hits.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
…erifier P3 nits) Co-Authored-By: Claude Opus 5.5 <[email protected]>
…exact MCP tools, CI lint green
Coordinator additions (STRETCH 2026-10-10):
- Model#mass_decile (popularity.mass_decile, data 2026.10.1+, pipeline#255,
ruling R3), nil-safe on the bundled 2026.10.0; top_models(by:
:mass_decile) (unranked excluded; :global_decile stays the default);
README separates the two questions.
- Web-session requirement (verifier-grade): fuzzy never fires on input
containing "/" or slug-shaped ("marcedes-benz"): "marcedes-benz/c-class",
"/makes/marcedes", "car/marcedes-benz/c-class" -> nil, as in 0.7.7.
Human names ("Marcedes-Benz C-Class", "marcedes") still resolve. MCP tools
(search_makes, get_model) exact-only. Tests pin every case.
- CI: Ruby 3.4/rails_8.0 Lint job failed on main too (111 inherited
offenses); frozen in .rubocop_todo.yml (generated, no code change);
lib/vehicles/plates/series.rb added to .rubocop.yml's own ClassLength
Exclude (it overrides the todo). Ruby 3.3/rails_8.0 failure was a
rubygems.org network error during bundle install (re-run).
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Collaborator
Author
|
Delta c16818d (coordinator additions, STRETCH 2026-10-10):
|
…e stays exact
F1 (P2) Fuzzy.eligible_input? also rejects Symbols, any of / _ + \, leading/
trailing/double hyphens and UPPER-case hyphenated slugs — each fuzzed for
every typo (:marcedes_benz, "MARCEDES-BENZ", "marcedes+benz", …); 0.7.7
returns nil for all. Mixed case ("Marcedes-Benz") and plain words still
fuzz. Tests pin the verifier's full list.
F2 (P3) CHANGELOG upgrade note: single-word route params still fuzz.
F3 (P3) Model#mass_decile never raises on a non-Hash popularity.
F4 (P3) docs: by: with country (rank first), to_h :mass_decile, 110+1 frozen.
Manager re-check: 223 runs 0F/0E/0S; rubocop rc=0; 30,643 make+find queries
vs 0.7.7 code on the same 2026.10.0 data: 0 changed, 0 lost.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Collaborator
Author
|
REL merge gate (lane REL, owner-authorised stretch 2026-10-10) — independent check of the delta
|
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.
0.7.8 — typo-tolerant make lookup, per-country
top_models, dataset 2026.10.0Do not
gem pushfrom this PR — publishing is owner/release-workflow only. This PR bumps the version and ships the code + bundled data.Why
top_models(country:)sorted by GLOBAL popularity after filtering (bug filed by the SEO session: the Ukraine page and?country=strips were ordered by everybody else's popularity).global_decileis a presence-weighted average across countries (pipeline#205); a UK list must be in UK order.What
lib/vehicles/fuzzy.rb,Dataset#find_make): after exact name/slug/alias/built-in alias, the closest make by optimal string alignment (Levenshtein + adjacent swap = 1 edit), stdlib only. Budget: none under 4 characters, 1 edit for 4-5, 2 from 6 (within the requested ≤2). Unique best only — two makes tied →nil("Acra": Acura/Acma;"telsa": Tesla/Temsa). Guards, each added after a measured failure: a candidate may not have fewer words than the query ("Volvo V 60"→ Volvo "60" was possible); every word keeps its first letter ("citroen e"→ Citroën DS was possible through the web resolver's prefix loop); the configuredother_labelnever fuzzy-matches ("Otra"→ Ora).fuzzy: falseopts out onmake,models,model,model_options,find. Both validators stay exact — a typo never validates as a stored make.Vehicles.findruns its exact pass over every split before a fuzzy retry.Model#country_ranks/#rank_in(:gb);top_models(country:)orders by that country's own rank (ranks are per kind — passkind:), models without a rank there follow in the old order, data without the key degrades to the 0.7.7 order. US/CA cars have no ranks (presence-only sources) → global order (documented).rake "data:refresh[v2026.10.0]"(new,rakelib/data_refresh.rake, tags only) writesdata/vehicles.json= the release'sdist/vehicles.jsonplus onlycountry_ranks, merged from the same tag's opencatalog/<kind>/models.jsonpopularity.by_country[cc].rank; stripping the key gives the release bytes exactly. When the projection ships the key natively (companion pipeline PR,emit.rb write_dist_json!), the task asserts equality instead.data/PROVENANCE-vehicles.mdrecords tag/commit.rank_in, 15 countries / ~15k models), CHANGELOG 0.7.8, MCPtop_modelsnote, version 0.7.8.Evidence
bundle exec rake test: 213 runs, 189,522 assertions, 0 failures/errors/skips (base: 192). Required tests:marcedes→mercedes-benz,volkswagon→volkswagen, tie→nil (Acra, fixture asserts the tie is real in the data).bundle exec rubocop: 0 new offenses (main already carries 111; identical per-file/per-cop tally).app/models/resolver.rb), on 1,255 DEVQ A1 sweep queries, and (Opus verifier) on 37,050find+ 65,871 web-resolver-loop queries; 3,284 newly resolved, none >2 edits from its model.make()right 1,351/1,869 (1-edit) and 714/1,179 (2-edit); wrong-make 9 and 15 — mostly first-letter typos (renley→Riley), the documented trade-off of the first-letter rule.findwrong-make: 0.makefuzzy path 0.5 ms/call; exact hits unchanged (0.004 ms).Reviews (I-11 + codex)
codex exec review --base origin/main), round 1: [P2] out-of-budget candidate accepted (Vehicles.make("z" * 28)→ Saxas Nutzfahrzeuge Werdau) — fixed a802168 + regression test; [P2]fuzzy:not forwarded throughmodels/model/model_options— fixed a802168. Round 2: no actionable regressions.telsa→Temsa; P2 Other label; P2 web resolver loop [web-side, see below]; 5×P3 docs/rake) — all gem items fixed f9130ff/f36a6a3; re-check at f9130ff PASS (OSA vs textbook over 104,000 comparisons: 0 mismatches; rake refs/tags-only verified incl.v2026.10.0;echo pwnedrejected).Volvo V 60) 3bca6a8, first-letter (Citroën e-C3) d1263f9.For the web session (not in this PR)
GET /api/v1/makes/:make_slug/models?country=gbdoes not usetop_models;makes_controller#modelssorts by name, or[global_decile, name]withorder=popular(measured ford/gb: Mondeo #46 first, Fiesta Add first-class "Other / not in the list" escape hatch (v0.4.0) #1 absent from the first six). After bumping to 0.7.8: sort bym.rank_in(country) || Float::INFINITYfirst whencountryis given.resolver.rbrung 3 callsVehicles.makelongest-prefix-first; with 0.7.8 run an exact pass (fuzzy: false) before a fuzzy pass and label typo hits (make_typo:), lower confidence — today's corpus is clean, but by data, not design.Catalog.find_make) should passfuzzy: falseor 301 to the canonical slug, so/makes/marcedesdoes not serve a 200 duplicate.🤖 Generated with Claude Code