feat(migration): 建立 Skill 迁移工作流与追踪工具
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
#!/usr/bin/env python3
|
||||
"""根据扫描报告更新迁移台账;默认预览,显式 --apply 才写入。"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import hashlib
|
||||
import json
|
||||
from datetime import date
|
||||
from pathlib import Path
|
||||
|
||||
VALID_STATUS = {
|
||||
"pending", "specified", "rewriting", "review",
|
||||
"migrated", "excluded", "superseded",
|
||||
}
|
||||
|
||||
|
||||
def merge(lock: dict, report: dict) -> dict:
|
||||
"""保留人工维护字段,仅同步来源提交、数量和 Skill 指纹。"""
|
||||
lock.setdefault("schemaVersion", 1)
|
||||
lock["updatedAt"] = date.today().isoformat()
|
||||
lock.setdefault("sources", {})
|
||||
lock.setdefault("skills", {})
|
||||
for source in report.get("sources", []):
|
||||
source_id = source["id"]
|
||||
lock["sources"][source_id] = {
|
||||
"commit": source.get("commit"),
|
||||
"skillCount": source["skillCount"],
|
||||
}
|
||||
for skill in source["skills"]:
|
||||
# 发布台账不保存来源名称和路径;本地扫描报告负责提供可读映射。
|
||||
path_hash = hashlib.sha256(skill["relativePath"].encode("utf-8")).hexdigest()
|
||||
key = f"{source_id}:{path_hash[:16]}"
|
||||
current = lock["skills"].get(key, {})
|
||||
status = current.get("status", "pending")
|
||||
if status not in VALID_STATUS:
|
||||
raise ValueError(f"非法迁移状态:{key}={status}")
|
||||
lock["skills"][key] = {
|
||||
**current,
|
||||
"sourcePathHash": path_hash,
|
||||
"sourceSha256": skill["sha256"],
|
||||
"status": status,
|
||||
}
|
||||
return lock
|
||||
|
||||
|
||||
def main() -> None:
|
||||
parser = argparse.ArgumentParser(description="更新 Skill 迁移台账")
|
||||
parser.add_argument("--lock", required=True, type=Path)
|
||||
parser.add_argument("--report", required=True, type=Path)
|
||||
parser.add_argument("--apply", action="store_true", help="确认写入台账")
|
||||
args = parser.parse_args()
|
||||
lock = json.loads(args.lock.read_text(encoding="utf-8"))
|
||||
report = json.loads(args.report.read_text(encoding="utf-8"))
|
||||
content = json.dumps(merge(lock, report), ensure_ascii=False, indent=2) + "\n"
|
||||
if args.apply:
|
||||
temporary = args.lock.with_suffix(args.lock.suffix + ".tmp")
|
||||
temporary.write_text(content, encoding="utf-8")
|
||||
temporary.replace(args.lock)
|
||||
else:
|
||||
print(content, end="")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user