| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128 |
- #!/usr/bin/env python3
- """云端准备脚本(开发工具,不属于前端交付物)。
- 做的事:
- 1. 补齐字段:KfArtifact.layer(四层归属)、KfProject.layer、KfArtifact.sourceIdx(原材料层样例指针)
- 2. 补数:残留的 KfProbe 探针 -> 改名为标准的 KfSource(原材料层样例);
- 原文证据为空、但 evidenceLevel 标为 verified 的成果 -> 降为 supported(避免"无原文却称已验证")
- 3. 重建归纳:按 derivedFrom(-card + source 混合引用)重新计算 derivedArtifacts / derivedSources /
- owners / citedWith / evidenceQuotes / evidenceUnaligned / mentionCount
- 4. 验证 PARSE_MASTER_KEY(环境变量)有效
- 运行时:PARSE_MASTER_KEY=... python3 tools/setup_cloud.py
- --dry-run 只打印不写。
- """
- import json
- import os
- import sys
- import urllib.error
- import urllib.request
- BASE = "https://kangshifu.fmode.cn/parse"
- APP_ID = "FKieRbIoGt_main"
- MK = os.environ.get("PARSE_MASTER_KEY", "")
- DRY = "--dry-run" in sys.argv
- H = {"X-Parse-Application-Id": APP_ID, "Content-Type": "application/json"}
- if MK:
- H["X-Parse-Master-Key"] = MK
- def call(method, path, body=None):
- data = json.dumps(body, ensure_ascii=False).encode() if body is not None else None
- req = urllib.request.Request(BASE + path, data=data, headers=H, method=method)
- try:
- with urllib.request.urlopen(req, timeout=30) as r:
- return json.loads(r.read().decode() or "{}")
- except urllib.error.HTTPError as e:
- return {"_error": e.code, "_body": e.read().decode()[:400]}
- def fetch(cls):
- return call("GET", f"/classes/{cls}?limit=1000&order=createdAt").get("results", [])
- def ensure_fields():
- for cls, fields in [
- ("KfArtifact", {"layer": {"type": "String"}, "sourceIdx": {"type": "Number"}}),
- ("KfProject", {"layer": {"type": "String"}}),
- ]:
- if DRY:
- print("[dry] schema", cls, list(fields))
- continue
- r = call("PUT", f"/schemas/{cls}", {"className": cls, "fields": fields})
- print("schema", cls, "ok" if "fields" in r else r)
- def cleanup_probes():
- probes = fetch("KfProbe")
- for p in probes:
- title = "原材料层样例 · 探针记录"
- body = {
- "layer": "raw",
- "sourceType": "probe",
- "title": title,
- "summary": "开发期连通性探针,已转为标准原材料层样例记录。",
- "rawText": p.get("note", ""),
- "sources": [],
- "tags": [],
- "payload": {},
- "meta": {"migratedFrom": "KfProbe", "kfProbeId": p["objectId"]},
- }
- if DRY:
- print("[dry] probe -> KfSource", p["objectId"])
- continue
- r = call("POST", "/classes/KfSource", body)
- if "objectId" in r:
- call("DELETE", f"/classes/KfProbe/{p['objectId']}")
- print("probe", p["objectId"], "->", r["objectId"])
- def fix_evidence_levels():
- for a in fetch("KfArtifact"):
- if not a.get("sources") and a.get("evidenceLevel") == "verified":
- if DRY:
- print("[dry] downgrade", a["title"])
- continue
- call("PUT", f"/classes/KfArtifact/{a['objectId']}", {"evidenceLevel": "supported"})
- print("downgraded verified->supported:", a["title"])
- def rebuild_insights():
- arts = {a["objectId"]: a for a in fetch("KfArtifact")}
- srcs = {s["objectId"]: s for s in fetch("KfSource")}
- for ins in fetch("KfInsight"):
- pointed = ins.get("derivedFrom") or []
- art_ids = [i for i in pointed if i in arts]
- src_ids = [i for i in pointed if i in srcs]
- owners = sorted({arts[i].get("ownerName") for i in art_ids if arts[i].get("ownerName")})
- lvls = sorted({arts[i].get("evidenceLevel") for i in art_ids if arts[i].get("evidenceLevel")})
- cited_with = sorted({ins["objectId"] for a in arts.values()
- if set(a.get("sources") or []) & set(art_ids)} - {ins["objectId"]})
- upd = {
- "layer": "sediment",
- "derivedArtifacts": art_ids,
- "derivedSources": src_ids,
- "owners": owners,
- "ownerCount": len(owners),
- "crossRefCount": ins.get("crossRefCount", 0),
- "mentionCount": ins.get("crossRefCount", 0),
- "evidenceQuoteCount": len(art_ids),
- "evidenceUnaligned": "verified" not in lvls,
- "citedWith": cited_with,
- }
- if DRY:
- print("[dry] insight", ins["title"], upd)
- continue
- r = call("PUT", f"/classes/KfInsight/{ins['objectId']}", upd)
- print("insight", ins["title"], "ok" if "updatedAt" in r else r)
- if __name__ == "__main__":
- if not MK:
- sys.exit("PARSE_MASTER_KEY 未设置")
- print("masterKey auth:", "ok" if "results" in call("GET", "/classes/KfProject?limit=1") else "FAILED")
- ensure_fields()
- cleanup_probes()
- fix_evidence_levels()
- rebuild_insights()
|