31ce04c655
Merge the beta-ready Yao Meta Skill architecture, report, evidence gate, and release-boundary updates.\n\nRelease boundary: beta/public testing is allowed; formal world-class, fully reviewed, or superiority claims remain blocked until the pending evidence gates are accepted.
99 lines
3.6 KiB
Python
99 lines
3.6 KiB
Python
#!/usr/bin/env python3
|
|
"""Git source/generated dirty classification for benchmark release locks."""
|
|
|
|
import subprocess
|
|
from pathlib import Path
|
|
from typing import Any
|
|
|
|
|
|
SCRIPT_INTERFACE = "internal-module"
|
|
SCRIPT_INTERFACE_REASON = "Imported by render_benchmark_reproducibility.py to keep release-lock git status classification out of the report renderer."
|
|
|
|
|
|
GENERATED_DIRTY_PREFIXES = (
|
|
"dist/",
|
|
"registry/index.json",
|
|
"registry/packages/",
|
|
"reports/",
|
|
"skill_atlas/",
|
|
"skill-ir/examples/",
|
|
)
|
|
|
|
|
|
def status_path(line: str) -> str:
|
|
path = line[3:].strip() if len(line) > 3 else line.strip()
|
|
if " -> " in path:
|
|
path = path.rsplit(" -> ", 1)[-1].strip()
|
|
return path
|
|
|
|
|
|
def is_generated_dirty_path(path: str) -> bool:
|
|
return any(path == prefix.rstrip("/") or path.startswith(prefix) for prefix in GENERATED_DIRTY_PREFIXES)
|
|
|
|
|
|
def git_status(skill_dir: Path) -> dict[str, Any]:
|
|
try:
|
|
proc = subprocess.run(
|
|
["git", "status", "--short", "--untracked-files=all"],
|
|
cwd=skill_dir,
|
|
capture_output=True,
|
|
text=True,
|
|
check=True,
|
|
)
|
|
except (OSError, subprocess.CalledProcessError):
|
|
return {
|
|
"available": False,
|
|
"dirty": None,
|
|
"changed_file_count": None,
|
|
"source_dirty": None,
|
|
"source_changed_file_count": None,
|
|
"generated_dirty": None,
|
|
"generated_changed_file_count": None,
|
|
}
|
|
lines = [line for line in proc.stdout.splitlines() if line.strip()]
|
|
paths = [status_path(line) for line in lines]
|
|
generated_lines = [line for line, path in zip(lines, paths) if is_generated_dirty_path(path)]
|
|
source_lines = [line for line, path in zip(lines, paths) if not is_generated_dirty_path(path)]
|
|
return {
|
|
"available": True,
|
|
"dirty": bool(lines),
|
|
"changed_file_count": len(lines),
|
|
"generated_dirty": bool(generated_lines),
|
|
"generated_changed_file_count": len(generated_lines),
|
|
"source_dirty": bool(source_lines),
|
|
"source_changed_file_count": len(source_lines),
|
|
"sample": lines[:12],
|
|
"source_sample": source_lines[:12],
|
|
"generated_sample": generated_lines[:12],
|
|
"generated_dirty_prefixes": list(GENERATED_DIRTY_PREFIXES),
|
|
"scope": "generation-time status before this report is written",
|
|
}
|
|
|
|
|
|
def release_lock_status(status: dict[str, Any], commit: str) -> dict[str, Any]:
|
|
available = status.get("available") is True
|
|
source_clean = status.get("source_dirty") is False
|
|
known_commit = bool(commit and commit != "unknown")
|
|
ready = available and source_clean and known_commit
|
|
reasons = []
|
|
if not available:
|
|
reasons.append("git status unavailable")
|
|
if not known_commit:
|
|
reasons.append("git commit unavailable")
|
|
if status.get("source_dirty") is True:
|
|
reasons.append("source files were dirty at generation time")
|
|
if status.get("source_dirty") is None:
|
|
reasons.append("working tree cleanliness unknown")
|
|
if status.get("generated_dirty") is True and status.get("source_dirty") is False:
|
|
reasons.append("only generated evidence artifacts were dirty at generation time")
|
|
if not reasons:
|
|
reasons.append("clean source tree at generation-time HEAD")
|
|
return {
|
|
"ready": ready,
|
|
"commit": commit,
|
|
"status_scope": status.get("scope", "generation-time status"),
|
|
"source_changed_file_count": status.get("source_changed_file_count"),
|
|
"generated_changed_file_count": status.get("generated_changed_file_count"),
|
|
"reason": "; ".join(reasons),
|
|
}
|