Scope OLX watches and searches to a category #18

Merged
kubus merged 1 commit from feat/olx-category-scoping into main 2026-09-30 21:37:53 +00:00
Owner

Step 2a of the reseller roadmap. OLX searches every category by default, so GPU and phone watches learn their typical price from the wrong items.

Live check (2026-09-30), "rtx 3070" on OLX: unscoped, 50 of 63 results were whole PCs/laptops (median 3 600 zł). Scoped to Karty graficzne, 2 of 49 (median 1 399 zł).

What changes

  • Watches, research watches and manual searches take an optional OLX category (migration 028). It is sent as category_id on OLX scans only; Allegro Lokalnie and Vinted are unaffected. For research watches it is part of the immutable criteria, so changing it starts a new series.
  • The picker (watch dialog, research dialog, Search) loads OLX's own per-category hit counts for the query in one request: GET /api/marketplaces/olx/categories?query=, plus MCP scout_olx_categories. scout_search accepts olxCategoryId.
  • Pasted OLX exact URLs used to silently drop their category and city path. They are now resolved through OLX friendly-links, including city, search[dist] and the private/business filter. friendly-links quietly falls back to the parent for unknown slugs, so Scout checks against the parent and fails closed rather than widening. Resolutions are cached per process.
  • A category OLX rejects (HTTP 400) or a path it can't resolve fails that watch's scan as a connector warning, without backoff. Previously any per-watch config error backed off every OLX watch.

Not in this PR

  • Seller type, listing age and promoted flags (step 2b, next PR).
  • The watch Location filter is unchanged; still waiting on the question about towns that ship.
  • iOS: no picker yet. iOS edits PATCH only the fields they know, so an existing category is kept.
  • Editing the category on an ordinary watch doesn't reset its already-learned baseline, same as editing its query today.

Verification

  • npm run typecheck, npm test (248/248), npm run build, and npm audit --omit=dev (0 vulnerabilities) all pass.
  • Live smoke test on a temporary DB: facet lookup, scoped manual search, a watch with a category, an exact URL with category + Kraków + 30 km (scanned OK), and an exact URL with an unknown slug (warning, no backoff). A malformed category payload returns 400.
  • The web UI was not checked visually (the preview browser couldn't reach the host).

🤖 Generated with Claude Code

Step 2a of the reseller roadmap. OLX searches every category by default, so GPU and phone watches learn their typical price from the wrong items. **Live check (2026-09-30), "rtx 3070" on OLX:** unscoped, 50 of 63 results were whole PCs/laptops (median 3 600 zł). Scoped to *Karty graficzne*, 2 of 49 (median 1 399 zł). ## What changes - Watches, research watches and manual searches take an optional **OLX category** (migration 028). It is sent as `category_id` on OLX scans only; Allegro Lokalnie and Vinted are unaffected. For research watches it is part of the immutable criteria, so changing it starts a new series. - The picker (watch dialog, research dialog, Search) loads OLX's own per-category hit counts for the query in one request: `GET /api/marketplaces/olx/categories?query=`, plus MCP `scout_olx_categories`. `scout_search` accepts `olxCategoryId`. - **Pasted OLX exact URLs** used to silently drop their category and city path. They are now resolved through OLX friendly-links, including city, `search[dist]` and the private/business filter. friendly-links quietly falls back to the parent for unknown slugs, so Scout checks against the parent and **fails closed rather than widening**. Resolutions are cached per process. - A category OLX rejects (HTTP 400) or a path it can't resolve fails **that watch's scan** as a connector `warning`, **without backoff**. Previously any per-watch config error backed off every OLX watch. ## Not in this PR - Seller type, listing age and promoted flags (step 2b, next PR). - The watch *Location* filter is unchanged; still waiting on the question about towns that ship. - iOS: no picker yet. iOS edits PATCH only the fields they know, so an existing category is kept. - Editing the category on an ordinary watch doesn't reset its already-learned baseline, same as editing its query today. ## Verification - `npm run typecheck`, `npm test` (248/248), `npm run build`, and `npm audit --omit=dev` (0 vulnerabilities) all pass. - Live smoke test on a temporary DB: facet lookup, scoped manual search, a watch with a category, an exact URL with category + Kraków + 30 km (scanned OK), and an exact URL with an unknown slug (warning, no backoff). A malformed category payload returns 400. - The web UI was not checked visually (the preview browser couldn't reach the host). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Scope OLX watches and searches to a category
Some checks failed
ci / verify (pull_request) Has been cancelled
da503d9763
OLX searches every category by default, so a GPU query is mostly whole PCs
and laptops and a phone query mostly cases, which skews typical prices. Live
on 2026-09-30, 50 of 63 unscoped "rtx 3070" results were PCs/laptops (median
3 600 zł); scoped to Karty graficzne it was 2 of 49 (median 1 399 zł).

- Watches, research watches (as immutable criteria) and manual searches take
  an optional OLX category, sent as category_id on OLX scans only.
- A picker loads OLX's own per-category hit counts for the query
  (GET /api/marketplaces/olx/categories, MCP scout_olx_categories).
- Pasted OLX exact URLs keep their category and city path, resolved through
  OLX friendly-links; a path OLX cannot resolve exactly fails closed instead
  of widening the search.
- A rejected category or unresolvable path fails that watch's scan as a
  connector warning without backing off every OLX watch.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
kubus merged commit 1b4dfe160a into main 2026-09-30 21:37:53 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
kubus/scout!18
No description provided.