scripts/validate_release.py
1.6 KB| 1 | from pathlib import Path |
| 2 | import re |
| 3 | |
| 4 | ROOT = Path(__file__).resolve().parents[1] |
| 5 | skill = ROOT / "SKILL.md" |
| 6 | text = skill.read_text(encoding="utf-8-sig") |
| 7 | |
| 8 | errors = [] |
| 9 | if not text.startswith("---\n"): |
| 10 | errors.append("missing YAML frontmatter") |
| 11 | for field in ("name:", "description:"): |
| 12 | if field not in text.split("---", 2)[1]: |
| 13 | errors.append(f"missing frontmatter field: {field}") |
| 14 | |
| 15 | match = re.search(r"^name:\s*([^\n]+)$", text, re.M) |
| 16 | if not match or not re.fullmatch(r"[a-z0-9]+(?:-[a-z0-9]+)*", match.group(1).strip()): |
| 17 | errors.append("skill name must use lowercase letters, numbers, and hyphens") |
| 18 | |
| 19 | for relative in ( |
| 20 | "references/workflow.md", |
| 21 | "references/output-spec.md", |
| 22 | "references/isolation-and-evidence.md", |
| 23 | "tests/pressure-scenarios.md", |
| 24 | ): |
| 25 | if not (ROOT / relative).exists(): |
| 26 | errors.append(f"missing required file: {relative}") |
| 27 | |
| 28 | privacy_patterns = { |
| 29 | "absolute Windows user path": r"[A-Za-z]:\\Users\\", |
| 30 | "absolute POSIX user path": r"/(?:home|Users)/", |
| 31 | "email address": r"\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b", |
| 32 | } |
| 33 | for label, pattern in privacy_patterns.items(): |
| 34 | if re.search(pattern, text, re.I): |
| 35 | errors.append(f"public package contains {label}") |
| 36 | |
| 37 | required_phrases = ( |
| 38 | "个人错题", |
| 39 | "考生隔离", |
| 40 | "题库真实题量", |
| 41 | "真题原文", |
| 42 | "回访清单", |
| 43 | ) |
| 44 | for phrase in required_phrases: |
| 45 | if phrase not in text: |
| 46 | errors.append(f"missing core instruction: {phrase}") |
| 47 | |
| 48 | if errors: |
| 49 | for error in errors: |
| 50 | print(f"ERROR: {error}") |
| 51 | raise SystemExit(1) |
| 52 | |
| 53 | print("OK: release skill structure and privacy checks passed") |
文件内容是平台检查时读出的文本,只供查看。平台不会运行包里的任何脚本或程序。

