sorter: weak tier and tokenless adoption need a shared rare token; pool scan takes best accepted entry
This commit is contained in:
@@ -24,6 +24,12 @@ CATALOG = {
|
||||
{"name": "Guardian Squad", "system": "Warhammer 40,000",
|
||||
"group": "Xenos Armies", "faction": "Aeldari",
|
||||
"class": "Battleline", "aliases": []},
|
||||
{"name": "Rangers", "system": "Warhammer 40,000",
|
||||
"group": "Xenos Armies", "faction": "Aeldari",
|
||||
"class": "Battleline", "aliases": []},
|
||||
{"name": "Dark Reapers", "system": "Warhammer 40,000",
|
||||
"group": "Xenos Armies", "faction": "Aeldari",
|
||||
"class": "Aspect Warriors", "aliases": []},
|
||||
]
|
||||
}
|
||||
|
||||
@@ -121,6 +127,57 @@ def test_cross_system_needs_token_containment():
|
||||
shutil.rmtree(root); shutil.rmtree(library)
|
||||
|
||||
|
||||
def test_weak_needs_shared_token():
|
||||
"""Sub-threshold hit with zero shared words is a fluke: reject.
|
||||
|
||||
'frontline squad' vs 'Guardian Squad' scores 0.552 but shares no
|
||||
token - it must NOT re-home, while 'guardian weapon team' (0.588,
|
||||
shares 'guardian') is accepted weak.
|
||||
"""
|
||||
root = Path(tempfile.mkdtemp(prefix="sorter_test_src_"))
|
||||
pack = root / "Aeldari Pack"
|
||||
write(pack / "frontline squad" / "f.stl")
|
||||
write(pack / "guardian weapon team" / "g.stl")
|
||||
library = make_lib()
|
||||
(root / "extract_manifest.jsonl").write_text(json.dumps({
|
||||
"archive": str(root / "Aeldari Pack.zip"),
|
||||
"dest": "Aeldari Pack", "unit": "Aeldari Pack.zip",
|
||||
}), encoding="utf-8")
|
||||
files = sorted((root / "Aeldari Pack").rglob("*"))
|
||||
items = sort_plan(files, library, get_catalog(), provenance={
|
||||
"Aeldari Pack": "Aeldari Pack.zip"}, root=root)
|
||||
by_name = {i.name: i for i in items}
|
||||
f = by_name["f.stl"]
|
||||
assert f.match_kind == "implicit", (f.match_kind, f.target)
|
||||
assert "frontline squad" in str(f.target)
|
||||
g = by_name["g.stl"]
|
||||
assert g.match_kind == "weak" and g.confidence == "low"
|
||||
shutil.rmtree(root); shutil.rmtree(library)
|
||||
|
||||
|
||||
def test_tokenless_needs_bonus():
|
||||
"""Same-faction adoption without a shared word needs +0.08.
|
||||
|
||||
'Aeldari Rangers' (0.667 vs 'Dark Reapers', tokenless) must not adopt
|
||||
Dark Reapers; it instead adopts 'Rangers' (0.636, shares 'ranger').
|
||||
"""
|
||||
root = Path(tempfile.mkdtemp(prefix="sorter_test_src_"))
|
||||
pack = root / "Aeldari Pack"
|
||||
write(pack / "Aeldari Rangers" / "r.stl")
|
||||
library = make_lib()
|
||||
(root / "extract_manifest.jsonl").write_text(json.dumps({
|
||||
"archive": str(root / "Aeldari Pack.zip"),
|
||||
"dest": "Aeldari Pack", "unit": "Aeldari Pack.zip",
|
||||
}), encoding="utf-8")
|
||||
files = sorted((root / "Aeldari Pack").rglob("*"))
|
||||
items = sort_plan(files, library, get_catalog(), provenance={
|
||||
"Aeldari Pack": "Aeldari Pack.zip"}, root=root)
|
||||
it = next(i for i in items if i.name == "r.stl")
|
||||
assert it.match_kind == "catalog" and it.unit == "Rangers", \
|
||||
(it.match_kind, it.unit, it.match_score)
|
||||
shutil.rmtree(root); shutil.rmtree(library)
|
||||
|
||||
|
||||
def test_nonprov_rehome():
|
||||
"""Loose noise file inside a named dir re-homes to the dir's unit."""
|
||||
root = Path(tempfile.mkdtemp(prefix="sorter_test_src_"))
|
||||
@@ -164,7 +221,8 @@ def load_catalog_path():
|
||||
def main():
|
||||
catalog = load_catalog_path()
|
||||
for fn in (test_prov_dir_rehome, test_prov_weak_tier, test_nonprov_rehome,
|
||||
test_cross_system_needs_token_containment, test_apply_weak_doc):
|
||||
test_cross_system_needs_token_containment, test_apply_weak_doc,
|
||||
test_weak_needs_shared_token, test_tokenless_needs_bonus):
|
||||
fn()
|
||||
print("OK", fn.__name__)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user