SIGN IN SIGN UP

feat: listing-quality overhaul from full audit — market pricing, vision aspect fill, data hygiene

Pricing (audit #1):
- Remove the hidden 18% markup + $29.99 default: the price the seller
  reviews is the price that publishes; missing/invalid price now blocks
  publish with an actionable error instead of listing at $35.39
- New comp-research engine (lib/ebay/comps.ts + /api/ebay/comps): searches
  active eBay listings via the Browse API, filters bad comps (lots, parts,
  repros, wrong condition), returns median/band/confidence; shown under the
  price field with one-click 'use median'

Item specifics (audit #2-#5):
- Aspect fill now re-sends the ORIGINAL PHOTOS with eBay's exact category
  schema (vision pass) so details the schema-blind first pass missed are
  recoverable (audit's core architectural fix)
- Remove the 25-aspect cap; prioritize required → recommended → optional
  (cap 40, logged when trimmed)
- Track aspect usage/cardinality/maxLength from the Taxonomy API; MULTI
  aspects keep all values ('Cotton/Polyester' no longer flattens to
  'Cotton'), SINGLE collapse safely; compound allowed values (Hook & Eye)
  are rejoined after splitting
- Placeholder phrases ('See tag in photos', 'Unknown') can never become
  searchable aspect values; prompts stop asking for them
- addMissingAspects no longer stamps 'Unbranded' into arbitrary fields

Measurements (audit #6): structured parsing — Inseam/Waist/Rise are only
filled from explicitly labeled measurements, never a 30-char text blob

Categories (audit #8): fallbacks are now eBay's own runner-up suggestions
for THIS item; when none work the publish stops with a clear error instead
of landing in an unrelated collectibles category

Catalog matching (audit #9): validated UPC/EAN/ISBN/MPN (check digits) go
into the Inventory product fields; includeCatalogProductDetails enabled
when a strong identifier exists

Also:
- Package weight/size defaults profiled by item class (coats/boots/media…)
- Taxonomy failures surface as UI warnings; EBAY_STRICT_QUALITY=1 blocks
  publish instead
- Deterministic title cleanup at analyze time (dedupe + append missing
  brand/size/color under 80 chars) so the reviewed title is the published one
- Test suite: vitest + 64 unit tests over the new pure modules
A
ashnicholes-droid committed
5f1797c831c1de1324e945eff5d565c39c6018c1
Parent: 22acb53