74768693ec
A club item's `assetId` (record +0x20) is family specific and is NOT the carddbid: per the client's own tables a kit carries the art class from fcc_kitcards.assetid - 14 for the 63xxxxx home/third band, 15 for the 64xxxxx away band - a badge carries its team id, and a ball and stadium their own asset number. The catalog shipped `asset_id`, the carddbid, in that slot. Measured on the live client with both kits resident: record +0x20 held 6300006 (home) and 6400003 (away) where the table says 14 and 15, while every other field - resourceId, cardassetid 35, category 2/3, teamid 21, year 0, itemState 101/102 - already matched. Operator reports both pre-match kit tiles rendering identically. assetId is the only field that diverges from the client's own data, and an assetId that is not a valid kit art class cannot resolve to distinct art. `resource_id` is derived from `asset_id`, and every home kit shares art class 14, so the two cannot be the same field: catalogs now carry an optional `club_asset_id`, defaulting to `asset_id` so a catalog predating the field and every non-club kind are unchanged. resolve_kit emits it as the wire `assetId`. Fixed at the source too - scripts/sold-staging-up.py emitted asset_id as the wire assetId for all four club families, so a re-emit would have regressed it. Field-offset note: club_items.json's _record_map is authoritative and my earlier working note had these transposed - assetId is +0x20 and cardassetid is +0x1c, not the reverse. Adds tools/live/diff_kit_records.py, which byte-diffs the two resident kit records and names the fields the decoded clone query consumes. Staging wire now reads assetId 14/15 with cardassetid 35 on both squad.actives and /club?type=equippables. Workspace 1250 passed, 0 failed. Client re-parse still to be confirmed visually.