gwshop: fix primary-branch tie-break and refresh the committed catalog

- src/gwshop.rs: pick the FIRST longest facet path on ties, matching the
  original Python max(paths, key=len). Rust's max_by_key returned the last,
  which silently reclassified ~2298 entries for products faceted under
  several branches (e.g. a generic kit listed per chapter). Adds a regression
  test.
- AGENTS.md: document the first-longest tie-break and the facet-partition
  coverage shortfall (non-system merchandise left out; no model kits).
- data/gwshop_catalog.json: regenerate with the fixed binary (3491 -> 3459
  entries; 34 removed, 2 added, 188 structural + 785 collections changes).
This commit is contained in:
2026-10-11 13:10:24 +02:00
parent bc165093e2
commit 93b86d34af
3 changed files with 51501 additions and 51096 deletions
+8
View File
@@ -242,6 +242,14 @@ sorting pipeline — **change it first, then the code**. Summary:
public **search-only** key live in the gitignored `algolia.json` (or
`ALGOLIA_APP_ID`/`ALGOLIA_API_KEY`); never commit any other Algolia key.
`data/gwshop_catalog.json` is the committed snapshot and the sorter default.
- The dump partitions the index on the `GameSystemsRoot` hierarchical facet
(the search-only key cannot `/browse`; plain pagination caps at 1000 hits).
When a product is faceted under several branches of equal depth (e.g. a
generic kit listed per chapter), the **first longest path wins** — Python's
`max(paths, key=len)` semantics, reproduced explicitly because Rust's
`max_by_key` returns the *last* maximum. Products carrying no
`GameSystemsRoot` path (paints, Black Library books, White Dwarf, bases,
gifts — no miniature kits) are left out; the coverage shortfall is logged.
- Bookkeeping (`sorter_applied.jsonl`, `sorter_low_confidence.txt`) is written
to `<library>/../_logs/` by default — never inside the library, which may be
a seeded torrent whose file set is frozen.