fix(import-fifa17): nation/league/team are instance metadata, not definition identity

Evidence (resourceId 169193): its 4 owned copies are IDENTICAL in asset/rating/
position/all attributes and differ ONLY in nation/team/league (and those resolve
inconsistently, e.g. team 240 'Atletico Madrid' under league 16 'Ligue 1'). A
player's club affiliation is an instance-time snapshot, not part of the card
DEFINITION identity.

Correct the model (not a special-case): the definition-consistency gate now
compares a DefIdentity projection (asset_id/version/rating/position/attrs/
rareflag) and EXCLUDES nation/league/team. A club-only difference between copies
of one resourceId is no longer a conflict; a real identity disagreement
(rating/position/attrs/asset) still trips it. The definition's display
nation/league/club use the first-observed copy (deterministic; display-only,
never identity). No --defer-conflict allowlist entry is needed for 169193 now.

On the real profile: conflicts 1->0, 169193 reclassified conflict->NoName
(still deferred, unnameable), supported still 1681, deferred instances still 13,
BLOCKERS none without any --defer-conflict flag. 2 new tests (club-only diff is
not a conflict; rating diff still is). crate suite 25 green; clippy -D clean.
This commit is contained in:
funman300
2026-08-12 20:58:33 +00:00
parent e187cd49a2
commit 44fcf24d92
2 changed files with 89 additions and 4 deletions
+45
View File
@@ -319,6 +319,51 @@ fn emit_refuses_when_blocked() {
assert!(emit_content(&rep, dir.path(), "x").is_err());
}
#[test]
fn club_only_difference_across_copies_is_not_a_conflict() {
// Two owned copies of one resourceId, identical in asset/rating/position/
// attributes but DIFFERENT nation/team/league (a club-affiliation snapshot).
// Evidence (resourceId 169193) says this is NOT a conflict: one definition,
// both preserved wire ids, display club from the first-observed copy.
let a = format!(
r#"{{"id":100000001,"resourceId":20801,"assetId":20801,"itemType":"player","rareflag":1,
"rating":94,"preferredPosition":"ST","nation":38,"teamid":243,"leagueId":53,"attributeList":{}}}"#,
attrs()
);
let b = format!(
r#"{{"id":100000002,"resourceId":20801,"assetId":20801,"itemType":"player","rareflag":1,
"rating":94,"preferredPosition":"ST","nation":45,"teamid":21,"leagueId":16,"attributeList":{}}}"#,
attrs()
);
let plan = defs(&[a, b]);
assert!(
plan.conflicts.is_empty(),
"a club-only difference must NOT be a conflict"
);
assert_eq!(plan.supported.len(), 1, "one definition");
let d = &plan.supported[0];
assert_eq!(
d.wire_ids,
vec![100000001, 100000002],
"both copies preserved"
);
assert_eq!(d.nation, "Portugal", "display club = first observed copy");
assert_eq!(d.club, "Real Madrid");
assert_eq!(d.league, "LaLiga");
}
#[test]
fn identity_difference_across_copies_is_still_a_conflict() {
// A differing rating is a real definition-identity disagreement -> conflict,
// never silently merged.
let plan = defs(&[
player(100000001, 20801, 20801, 94),
player(100000002, 20801, 20801, 90),
]);
assert!(plan.supported.is_empty());
assert_eq!(plan.conflicts.len(), 1);
}
// ------------------------------------------------------------------ apply
use crate::apply::{