refactor(exam): SKILL 中文化,增加用户确认阶段,默认子代理分批处理
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Validate a question JSON file against the bundled schema.
|
||||
|
||||
Usage:
|
||||
python3 validate.py <json_file>
|
||||
echo '<json>' | python3 validate.py -
|
||||
|
||||
Exit codes: 0 = valid, 1 = errors found, 2 = usage error.
|
||||
"""
|
||||
import json
|
||||
import re
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
SCRIPT_DIR = Path(__file__).resolve().parent
|
||||
SCHEMA_PATH = SCRIPT_DIR.parent / "schema" / "question.schema.json"
|
||||
|
||||
VALID_TYPES = [
|
||||
"single_choice", "multiple_choice", "true_false",
|
||||
"fill_blank", "short_answer", "code_reading", "scenario",
|
||||
]
|
||||
ID_RE = re.compile(r"^(sc|mc|tf|fb|sa|cr|sn)-\d{3}$")
|
||||
|
||||
|
||||
def load_json(path: str) -> dict:
|
||||
if path == "-":
|
||||
return json.load(sys.stdin)
|
||||
with open(path, encoding="utf-8") as f:
|
||||
return json.load(f)
|
||||
|
||||
|
||||
def validate(data: dict, schema: dict) -> list[str]:
|
||||
"""Validate data against schema. Returns list of error strings."""
|
||||
errors = []
|
||||
|
||||
# Try jsonschema if available
|
||||
try:
|
||||
from jsonschema import Draft7Validator
|
||||
validator = Draft7Validator(schema)
|
||||
for err in sorted(validator.iter_errors(data), key=lambda e: list(e.path)):
|
||||
path_str = ".".join(str(p) for p in err.absolute_path) or "(root)"
|
||||
errors.append(f"{path_str}: {err.message}")
|
||||
return errors
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
# Fallback: manual validation
|
||||
required_top = ["topic", "type", "schema_version", "questions"]
|
||||
for field in required_top:
|
||||
if field not in data:
|
||||
errors.append(f"Missing required field: {field}")
|
||||
|
||||
if data.get("type") not in VALID_TYPES:
|
||||
errors.append(f"Invalid type: {data.get('type')}")
|
||||
|
||||
if data.get("schema_version") != "1.0.0":
|
||||
errors.append(f"schema_version must be '1.0.0', got '{data.get('schema_version')}'")
|
||||
|
||||
for i, q in enumerate(data.get("questions", [])):
|
||||
prefix = f"questions[{i}]"
|
||||
for field in ["id", "type", "difficulty", "tags", "question", "explanation"]:
|
||||
if field not in q:
|
||||
errors.append(f"{prefix}: missing '{field}'")
|
||||
if q.get("type") not in VALID_TYPES:
|
||||
errors.append(f"{prefix}: invalid type '{q.get('type')}'")
|
||||
if "difficulty" in q and not (1 <= q["difficulty"] <= 5):
|
||||
errors.append(f"{prefix}: difficulty must be 1-5")
|
||||
if "id" in q and not ID_RE.match(q["id"]):
|
||||
errors.append(f"{prefix}: id '{q['id']}' doesn't match pattern {{type}}-{{000}}")
|
||||
|
||||
return errors
|
||||
|
||||
|
||||
def main():
|
||||
if len(sys.argv) != 2:
|
||||
print(f"Usage: {sys.argv[0]} <json_file | ->", file=sys.stderr)
|
||||
sys.exit(2)
|
||||
|
||||
if not SCHEMA_PATH.exists():
|
||||
print(f"❌ Schema not found: {SCHEMA_PATH}", file=sys.stderr)
|
||||
sys.exit(2)
|
||||
|
||||
schema = load_json(str(SCHEMA_PATH))
|
||||
data = load_json(sys.argv[1])
|
||||
errors = validate(data, schema)
|
||||
|
||||
if errors:
|
||||
print(f"❌ {len(errors)} error(s):")
|
||||
for e in errors:
|
||||
print(f" • {e}")
|
||||
sys.exit(1)
|
||||
else:
|
||||
print(f"✅ Valid — {len(data.get('questions', []))} question(s)")
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user