List/home endpoints picked the family representative row via goods[0],
which drifted with the list sort parameter (cheapest under PRICE_ASC,
lowest id under DEFAULT ties), causing goodName and other
representative-derived fields to differ from the detail endpoint.
Extract pickFamilyRepresentative (goodPriority desc -> createdAt desc
-> id asc, same as getGoodByFamilyId) and use it in getGoods and
getHomeGoods grouping. Group ordering and API contracts unchanged.
Add SYNC_GUARDS thresholds so a partial/degenerate upstream response never
triggers a destructive operation:
- skip stale category deletion when the fetched tree is suspiciously small
vs the existing SDS category count
- skip delist detection unless both leaf-category and seen-product counts
are healthy
Verified: 77 tests pass; live SDS returns 226 categories (guard off),
incident-case ratios (2/226, 2/2) are correctly blocked.