Download scripts/check_channel_map.py from weideyouni/holoaeon: direct link, hf CLI and curl.
- Browser
- Download file 5.82 kB
-
https://huggingface.co/weideyouni/holoaeon/resolve/main/scripts/check_channel_map.py
- Command line
-
hf download hf://weideyouni/holoaeon/scripts/check_channel_map.py
-
curl -L -o check_channel_map.py https://huggingface.co/weideyouni/holoaeon/resolve/main/scripts/check_channel_map.py
5.82 kB
| # -*- coding: utf-8 -*- | |
| """B2b 校验器:通道映射 + 词表分域,判据 G1–G8。 | |
| 用法:python scripts/check_channel_map.py → 退出码 0/1 | |
| G1 channel_map.csv 12 行,LC01–LC12 顺序,分组 气5/血4/神3/淋巴0 | |
| G2 目标 17 · 已映射 12 · pending 5(神 1 / 淋巴 4),且 no_arithmetic=true | |
| G3 全仓(csv/json/生成脚本)不出现 "idx % 17" / "%17" 之类的算术推通道写法 | |
| G4 与 contract.channel_map() 逐行一致(同源,不各写一套) | |
| G5 通用闸恰 10 槽,且不含任何 E13/E14 槽位;includes_medical=false | |
| G6 医学侧 E14=24 / E13=12,copied_into_holoaeon=false | |
| G7 注入条件按 domain 分域:general 必 not_load medical;medical 额外要求 redlines | |
| G8 词表 spec_digest 可复算 | |
| """ | |
| import hashlib | |
| import json | |
| import os | |
| import sys | |
| ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) | |
| if ROOT not in sys.path: | |
| sys.path.insert(0, ROOT) | |
| from holoaeon.fusion_upgrade import contract as c | |
| CSV_F = os.path.join(ROOT, "data", "channel_map.csv") | |
| JSON_F = os.path.join(ROOT, "data", "channel_map.json") | |
| LEX_F = os.path.join(ROOT, "data", "skin_lexicon_rehab.json") | |
| GEN_SCRIPTS = [os.path.join(ROOT, "scripts", "gen_channel_map.py"), | |
| os.path.join(ROOT, "scripts", "gen_skin_lexicon.py")] | |
| def read_csv(path): | |
| with open(path, encoding="utf-8") as f: | |
| lines = [x.rstrip("\n") for x in f if x.strip()] | |
| header = lines[0].split(",") | |
| rows = [dict(zip(header, x.split(","))) for x in lines[1:]] | |
| return header, rows | |
| def main(): | |
| checks = [] | |
| def add(cid, ok, detail): | |
| checks.append({"id": cid, "ok": bool(ok), "detail": detail}) | |
| missing = [p for p in (CSV_F, JSON_F, LEX_F) if not os.path.isfile(p)] | |
| if missing: | |
| add("G0", False, "missing={}".format([os.path.basename(p) for p in missing])) | |
| print(json.dumps({"verdict": "FAIL", "checks": checks}, ensure_ascii=False, indent=2)) | |
| return 1 | |
| header, rows = read_csv(CSV_F) | |
| with open(JSON_F, encoding="utf-8") as f: | |
| meta = json.load(f) | |
| with open(LEX_F, encoding="utf-8") as f: | |
| lex = json.load(f) | |
| groups = {} | |
| for r in rows: | |
| groups[r["group"]] = groups.get(r["group"], 0) + 1 | |
| add("G1", len(rows) == 12 and [r["lc"] for r in rows] == ["LC%02d" % i for i in range(1, 13)] | |
| and groups == {"气": 5, "血": 4, "神": 3}, "rows={} groups={}".format(len(rows), groups)) | |
| add("G2", meta.get("mapped") == 12 and meta.get("targets") == 17 and meta.get("pending") == 5 | |
| and meta.get("pending_detail") == {"神": 1, "淋巴": 4} and meta.get("no_arithmetic") is True, | |
| "mapped={} targets={} pending={} detail={} no_arithmetic={}".format( | |
| meta.get("mapped"), meta.get("targets"), meta.get("pending"), | |
| meta.get("pending_detail"), meta.get("no_arithmetic"))) | |
| hits = [] | |
| for p in [CSV_F, JSON_F] + GEN_SCRIPTS: | |
| with open(p, encoding="utf-8") as f: | |
| text = f.read() | |
| for token in ("idx % 17", "idx%17", "% 17", "%17"): | |
| if token in text: | |
| hits.append("{}:{}".format(os.path.basename(p), token)) | |
| add("G3", not hits, "arithmetic_tokens={}".format(hits)) | |
| drift = [] | |
| ref = c.channel_map()["rows"] | |
| for i, r in enumerate(ref): | |
| row = rows[i] if i < len(rows) else {} | |
| if row.get("lc") != r["lc"] or row.get("group") != r["group"] \ | |
| or row.get("target_group") != r["target_group"] or row.get("status") != r["status"]: | |
| drift.append(r["lc"]) | |
| add("G4", not drift and len(ref) == len(rows), "drift={}".format(drift)) | |
| gen = lex.get("tracks", {}).get("general", {}) | |
| slots = gen.get("slots", []) | |
| med_tokens = [s for s in slots if "E13" in s or "E14" in s] | |
| add("G5", len(slots) == 10 and not med_tokens and gen.get("includes_medical") is False | |
| and gen.get("e13_e14_present") is False, | |
| "general_slots={} medical_slots_in_general={}".format(len(slots), med_tokens)) | |
| med = lex.get("tracks", {}).get("medical", {}) | |
| add("G6", med.get("e14_count") == 24 and med.get("e13_count") == 12 | |
| and len(med.get("e14_slots", [])) == 24 and len(med.get("e13_slots", [])) == 12 | |
| and med.get("copied_into_holoaeon") is False, | |
| "e14={}/{} e13={}/{} copied={}".format(len(med.get("e14_slots", [])), med.get("e14_count"), | |
| len(med.get("e13_slots", [])), med.get("e13_count"), | |
| med.get("copied_into_holoaeon"))) | |
| inj = lex.get("injection", {}) | |
| g = inj.get("general_gate", {}) | |
| m = inj.get("medical_gate", {}) | |
| add("G7", "medical" in g.get("must_not_load", []) and "general" in g.get("load", []) | |
| and "medical" in m.get("load", []) and "redlines" in str(m.get("extra_requirement", "")), | |
| "general_must_not_load={} medical_extra={}".format(g.get("must_not_load"), | |
| m.get("extra_requirement"))) | |
| core = {k: v for k, v in lex.items() if k != "spec_digest"} | |
| canon = json.dumps(core, sort_keys=True, separators=(",", ":"), ensure_ascii=False) | |
| want = hashlib.sha256(canon.encode("utf-8")).hexdigest()[:16] | |
| add("G8", lex.get("spec_digest") == want, | |
| "declared={} recomputed={}".format(lex.get("spec_digest"), want)) | |
| verdict = "PASS" if all(x["ok"] for x in checks) else "FAIL" | |
| print(json.dumps({"batch": "B2b", "channel_digest": meta.get("csv_sha256"), | |
| "lexicon_digest": lex.get("spec_digest"), "verdict": verdict, | |
| "failed": [x["id"] for x in checks if not x["ok"]], | |
| "checks": checks}, ensure_ascii=False, indent=2)) | |
| return 0 if verdict == "PASS" else 1 | |
| if __name__ == "__main__": | |
| sys.exit(main()) | |