mirror of
https://github.com/lllllllama/RigorPilot-Skills.git
synced 2026-09-14 13:43:27 +08:00
163 lines
6.7 KiB
Python
163 lines
6.7 KiB
Python
#!/usr/bin/env python3
|
|
"""Regression checks for README command extraction and selection heuristics."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import json
|
|
import subprocess
|
|
import sys
|
|
from pathlib import Path
|
|
from typing import Any, Dict, List
|
|
|
|
|
|
def run_extract(script: Path, readme_text: str, companion_files: Dict[str, str] | None = None) -> Dict[str, Any]:
|
|
temp_path = script.parent / ".tmp_readme_selection.md"
|
|
temp_path.write_text(readme_text, encoding="utf-8")
|
|
written: List[Path] = []
|
|
try:
|
|
for relative, content in (companion_files or {}).items():
|
|
companion = script.parent / relative
|
|
if companion.exists():
|
|
raise AssertionError(f"refusing to overwrite test companion: {companion}")
|
|
companion.parent.mkdir(parents=True, exist_ok=True)
|
|
companion.write_text(content, encoding="utf-8")
|
|
written.append(companion)
|
|
result = subprocess.run(
|
|
[sys.executable, str(script), "--readme", str(temp_path), "--json"],
|
|
check=True,
|
|
capture_output=True,
|
|
text=True,
|
|
)
|
|
return json.loads(result.stdout)
|
|
finally:
|
|
if temp_path.exists():
|
|
temp_path.unlink()
|
|
for companion in written:
|
|
companion.unlink()
|
|
|
|
|
|
def command_score(command: Dict[str, Any]) -> int:
|
|
text = str(command.get("command", "")).lower()
|
|
kind = command.get("kind", "run")
|
|
section = str(command.get("section") or "").lower()
|
|
score = {"run": 40, "smoke": 30, "asset": 10, "setup": 0}.get(kind, 0)
|
|
if any(token in text for token in ["python ", "python3 ", "./", "whisper "]):
|
|
score += 8
|
|
if any(token in text for token in ["txt2img", "img2img", "amg.py", "transcribe", "infer", "eval"]):
|
|
score += 8
|
|
if any(token in section for token in ["usage", "demo", "example", "inference", "evaluation", "text-to-image", "image-to-image"]):
|
|
score += 6
|
|
if any(token in section for token in ["install", "installation", "setup", "environment"]):
|
|
score -= 6
|
|
if "<" in text and ">" in text:
|
|
score -= 10
|
|
if text.startswith(("pip install", "conda install", "conda env create", "conda activate", "git clone", "cd ")):
|
|
score -= 12
|
|
return score
|
|
|
|
|
|
def choose_goal(commands: List[Dict[str, Any]]) -> str:
|
|
priority = ["inference", "evaluation", "training", "other"]
|
|
for category in priority:
|
|
candidates = [item for item in commands if item.get("category") == category]
|
|
if candidates:
|
|
best = max(candidates, key=command_score)
|
|
return str(best.get("command", ""))
|
|
return ""
|
|
|
|
|
|
def main() -> int:
|
|
parser = argparse.ArgumentParser(description="Run README extraction and selection regression tests.")
|
|
parser.add_argument(
|
|
"--cases",
|
|
default="tests/readme_selection_cases.json",
|
|
help="Path to README selection cases JSON.",
|
|
)
|
|
args = parser.parse_args()
|
|
|
|
repo_root = Path(__file__).resolve().parents[1]
|
|
extract_script = repo_root / "skills" / "repo-intake-and-plan" / "scripts" / "extract_commands.py"
|
|
payload = json.loads((repo_root / args.cases).read_text(encoding="utf-8"))
|
|
|
|
failures: List[str] = []
|
|
for case in payload["cases"]:
|
|
extracted = run_extract(extract_script, case["readme"])
|
|
selected = choose_goal(extracted["commands"])
|
|
if selected != case["expected_command"]:
|
|
failures.append(f"{case['id']}: expected `{case['expected_command']}`, got `{selected}`")
|
|
|
|
# Real-repo patterns (nanoGPT, dinov2): entrypoint-first classification and
|
|
# backslash-continuation joining.
|
|
nanogpt_readme = (
|
|
"# Demo\n\n## Quick start\n\n```bash\n"
|
|
"python train.py config/train_shakespeare_char.py --device=cpu --eval_iters=20\n"
|
|
"```\n"
|
|
)
|
|
extracted = run_extract(extract_script, nanogpt_readme)
|
|
if not extracted["commands"] or extracted["commands"][0]["category"] != "training":
|
|
failures.append("nanogpt-pattern: train.py with --eval_iters must classify as training, not evaluation")
|
|
|
|
micrograd_readme = (
|
|
"# micrograd\n\n## Running tests\n\n```bash\n"
|
|
"python -m pytest\n"
|
|
"```\n"
|
|
)
|
|
extracted = run_extract(extract_script, micrograd_readme)
|
|
if not extracted["commands"] or extracted["commands"][0]["category"] != "evaluation":
|
|
failures.append("micrograd-pattern: pytest under Running tests must classify as evaluation")
|
|
|
|
ambiguous_training_readme = (
|
|
"# Basic Example\n\n```bash\n"
|
|
"pip install -r requirements.txt\n"
|
|
"python main.py\n"
|
|
"```\n"
|
|
)
|
|
ambiguous_training_script = (
|
|
"def train(model, optimizer, train_loader):\n"
|
|
" model.train()\n"
|
|
" for data, target in train_loader:\n"
|
|
" loss = model(data).sum()\n"
|
|
" loss.backward()\n"
|
|
" optimizer.step()\n"
|
|
)
|
|
extracted = run_extract(
|
|
extract_script,
|
|
ambiguous_training_readme,
|
|
{"main.py": ambiguous_training_script},
|
|
)
|
|
main_command = next((item for item in extracted["commands"] if item["command"] == "python main.py"), None)
|
|
setup_command = next(
|
|
(item for item in extracted["commands"] if item["command"] == "pip install -r requirements.txt"),
|
|
None,
|
|
)
|
|
if not setup_command or setup_command["kind"] != "setup" or setup_command["category"] != "other":
|
|
failures.append("command-syntax: pip install under a generic Example heading must remain setup/other")
|
|
if not main_command or main_command["category"] != "training":
|
|
failures.append("entrypoint-structure: ambiguous main.py with optimizer/backward must classify as training")
|
|
elif main_command.get("classification_source") != "entrypoint-structure":
|
|
failures.append("entrypoint-structure: training promotion must expose its evidence source")
|
|
|
|
dinov2_readme = (
|
|
"# Demo\n\n## Evaluation\n\n```bash\n"
|
|
"python dinov2/run/eval/linear.py \\\n"
|
|
" --config-file dinov2/configs/eval/vitg14_pretrain.yaml \\\n"
|
|
" --pretrained-weights checkpoints/dinov2_vitg14_pretrain.pth\n"
|
|
"```\n"
|
|
)
|
|
extracted = run_extract(extract_script, dinov2_readme)
|
|
joined = extracted["commands"][0]["command"] if extracted["commands"] else ""
|
|
if "--config-file" not in joined or "--pretrained-weights" not in joined or joined.endswith("\\"):
|
|
failures.append("dinov2-pattern: backslash-continued command was not joined into one runnable command")
|
|
|
|
print(f"ok: {not failures}")
|
|
print(f"cases: {len(payload['cases'])}")
|
|
print(f"failures: {len(failures)}")
|
|
for failure in failures:
|
|
print(f"FAIL: {failure}")
|
|
return 0 if not failures else 1
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|