mirror of
https://github.com/lllllllama/RigorPilot-Skills.git
synced 2026-09-14 13:43:27 +08:00
123 lines
5.7 KiB
Python
123 lines
5.7 KiB
Python
#!/usr/bin/env python3
|
|
"""Build or verify the self-contained runtime shipped with the main skill."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import hashlib
|
|
import json
|
|
import shutil
|
|
from pathlib import Path
|
|
|
|
|
|
BUNDLE_FILES = {
|
|
"shared/scripts/agent_provider.py": "_bundled/shared/scripts/agent_provider.py",
|
|
"shared/scripts/command_utils.py": "_bundled/shared/scripts/command_utils.py",
|
|
"shared/scripts/model_adapter.py": "_bundled/shared/scripts/model_adapter.py",
|
|
"shared/scripts/resource_monitor.py": "_bundled/shared/scripts/resource_monitor.py",
|
|
"shared/scripts/runtime_runner.py": "_bundled/shared/scripts/runtime_runner.py",
|
|
"shared/scripts/task_queue.py": "_bundled/shared/scripts/task_queue.py",
|
|
"shared/scripts/lessons_store.py": "_bundled/shared/scripts/lessons_store.py",
|
|
"shared/scripts/write_run_bundle.py": "_bundled/shared/scripts/write_run_bundle.py",
|
|
"shared/scripts/write_explore_bundle.py": "_bundled/shared/scripts/write_explore_bundle.py",
|
|
"skills/repo-intake-and-plan/scripts/scan_repo.py": "_bundled/skills/repo-intake-and-plan/scripts/scan_repo.py",
|
|
"skills/repo-intake-and-plan/scripts/extract_commands.py": "_bundled/skills/repo-intake-and-plan/scripts/extract_commands.py",
|
|
"skills/env-and-assets-bootstrap/scripts/plan_setup.py": "_bundled/skills/env-and-assets-bootstrap/scripts/plan_setup.py",
|
|
"skills/env-and-assets-bootstrap/scripts/prepare_assets.py": "_bundled/skills/env-and-assets-bootstrap/scripts/prepare_assets.py",
|
|
"skills/minimal-run-and-audit/scripts/write_outputs.py": "_bundled/skills/minimal-run-and-audit/scripts/write_outputs.py",
|
|
"skills/run-train/scripts/run_training.py": "_bundled/skills/run-train/scripts/run_training.py",
|
|
"skills/run-train/scripts/write_outputs.py": "_bundled/skills/run-train/scripts/write_outputs.py",
|
|
"skills/analyze-project/scripts/analyze_project.py": "_bundled/skills/analyze-project/scripts/analyze_project.py",
|
|
"references/agent-operating-principles.md": "references/agent-operating-principles.md",
|
|
"references/research-rigor-principles.md": "references/research-rigor-principles.md",
|
|
"references/deep-learning-experiment-principles.md": "references/deep-learning-experiment-principles.md",
|
|
"references/continuous-learning-policy.md": "references/continuous-learning-policy.md",
|
|
"references/explore-variant-spec.md": "references/explore-variant-spec.md",
|
|
"references/research-thinking-loop.md": "references/research-thinking-loop.md",
|
|
"references/research-pitfall-checklist.md": "references/research-pitfall-checklist.md",
|
|
}
|
|
|
|
|
|
def normalized_bytes(path: Path) -> bytes:
|
|
"""Keep bundle identity stable across Git LF/CRLF checkout policies."""
|
|
return path.read_bytes().replace(b"\r\n", b"\n")
|
|
|
|
|
|
def digest(path: Path) -> str:
|
|
return hashlib.sha256(normalized_bytes(path)).hexdigest()
|
|
|
|
|
|
def expected_manifest(repo_root: Path) -> dict:
|
|
files = []
|
|
for source_rel, target_rel in sorted(BUNDLE_FILES.items()):
|
|
source = repo_root / source_rel
|
|
if not source.is_file():
|
|
raise FileNotFoundError(f"Bundle source does not exist: {source}")
|
|
files.append(
|
|
{
|
|
"source": source_rel,
|
|
"target": target_rel,
|
|
"sha256": digest(source),
|
|
}
|
|
)
|
|
return {"schema_version": "1.0", "files": files}
|
|
|
|
|
|
def sync(repo_root: Path, check: bool) -> list[str]:
|
|
skill_root = repo_root / "skills" / "ai-research-reproduction"
|
|
manifest = expected_manifest(repo_root)
|
|
failures: list[str] = []
|
|
|
|
for item in manifest["files"]:
|
|
source = repo_root / item["source"]
|
|
target = skill_root / item["target"]
|
|
if check:
|
|
if not target.is_file():
|
|
failures.append(f"missing bundled file: {item['target']}")
|
|
elif normalized_bytes(target) != normalized_bytes(source):
|
|
failures.append(f"stale bundled file: {item['target']}")
|
|
continue
|
|
target.parent.mkdir(parents=True, exist_ok=True)
|
|
shutil.copy2(source, target)
|
|
|
|
manifest_path = skill_root / "_bundled" / "MANIFEST.json"
|
|
rendered = json.dumps(manifest, indent=2, ensure_ascii=False) + "\n"
|
|
if check:
|
|
if not manifest_path.is_file():
|
|
failures.append("missing bundled file: _bundled/MANIFEST.json")
|
|
elif manifest_path.read_text(encoding="utf-8") != rendered:
|
|
failures.append("stale bundled file: _bundled/MANIFEST.json")
|
|
allowed = {
|
|
item["target"] for item in manifest["files"] if item["target"].startswith("_bundled/")
|
|
}
|
|
allowed.add("_bundled/MANIFEST.json")
|
|
for path in (skill_root / "_bundled").rglob("*"):
|
|
if path.is_file():
|
|
relative = path.relative_to(skill_root).as_posix()
|
|
if relative not in allowed:
|
|
failures.append(f"unexpected bundled file: {relative}")
|
|
else:
|
|
manifest_path.parent.mkdir(parents=True, exist_ok=True)
|
|
manifest_path.write_text(rendered, encoding="utf-8")
|
|
return failures
|
|
|
|
|
|
def main() -> int:
|
|
parser = argparse.ArgumentParser(description="Sync the main skill's self-contained runtime bundle.")
|
|
parser.add_argument("--check", action="store_true", help="Fail instead of writing when bundled files are missing or stale.")
|
|
args = parser.parse_args()
|
|
|
|
repo_root = Path(__file__).resolve().parents[1]
|
|
failures = sync(repo_root, args.check)
|
|
if failures:
|
|
for failure in failures:
|
|
print(f"ERROR: {failure}")
|
|
return 1
|
|
print("bundle_status: current" if args.check else "bundle_status: synchronized")
|
|
print(f"files: {len(BUNDLE_FILES)}")
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|