Files
yao-meta-skill/scripts/resource_boundary_check.py
T

104 lines
3.6 KiB
Python

#!/usr/bin/env python3
import argparse
import json
from pathlib import Path
from context_sizer import estimate_tokens, read_text, TEXT_EXTS
OPTIONAL_DIRS = ("references", "scripts", "assets", "evals", "templates")
CANONICAL_PATHS = ("SKILL.md", "manifest.json", "agents", "references", "scripts", "assets", "evals", "templates")
def has_files(path: Path) -> bool:
return path.exists() and any(child.is_file() for child in path.rglob("*"))
def iter_relevant_files(root: Path) -> list[Path]:
files = []
for entry in CANONICAL_PATHS:
path = root / entry
if path.is_file():
files.append(path)
elif path.is_dir():
files.extend(sorted(file for file in path.rglob("*") if file.is_file()))
return files
def main() -> None:
parser = argparse.ArgumentParser(description="Check whether a skill package keeps resource boundaries under control.")
parser.add_argument("skill_dir")
parser.add_argument("--max-initial-tokens", type=int, default=1800)
parser.add_argument("--warn-skill-body-tokens", type=int, default=1400)
args = parser.parse_args()
root = Path(args.skill_dir).resolve()
skill_md = root / "SKILL.md"
failures = []
warnings = []
if not skill_md.exists():
failures.append("Missing SKILL.md")
report = {"ok": False, "failures": failures, "warnings": warnings}
print(json.dumps(report, ensure_ascii=False, indent=2))
raise SystemExit(2)
files = iter_relevant_files(root)
skill_body_tokens = 0
other_tokens = 0
initial_load_tokens = 0
total_text_tokens = 0
for path in files:
if path.suffix and path.suffix not in TEXT_EXTS and path.name != "SKILL.md":
continue
text = read_text(path)
tokens = estimate_tokens(text)
total_text_tokens += tokens
rel = path.relative_to(root)
if rel.name == "SKILL.md":
skill_body_tokens += tokens
initial_load_tokens += tokens
else:
other_tokens += tokens
if rel.parts[0] in {"agents"}:
initial_load_tokens += tokens
if initial_load_tokens > args.max_initial_tokens:
failures.append(
f"Estimated initial-load tokens exceed budget: {initial_load_tokens} > {args.max_initial_tokens}"
)
if skill_body_tokens > args.warn_skill_body_tokens:
warnings.append(f"SKILL.md is getting heavy: {skill_body_tokens} estimated tokens.")
skill_text = skill_md.read_text(encoding="utf-8")
for dirname in OPTIONAL_DIRS:
path = root / dirname
if path.exists() and not has_files(path):
warnings.append(f"{dirname}/ exists but is empty.")
continue
if has_files(path) and dirname not in skill_text and dirname.capitalize() not in skill_text:
warnings.append(f"{dirname}/ contains files but is not referenced explicitly in SKILL.md.")
if other_tokens and skill_body_tokens / (skill_body_tokens + other_tokens) > 0.75:
warnings.append("Most text still lives in SKILL.md; consider moving detail into references/ or scripts/.")
report = {
"ok": not failures,
"failures": failures,
"warnings": warnings,
"stats": {
"skill_body_tokens": skill_body_tokens,
"other_text_tokens": other_tokens,
"estimated_initial_load_tokens": initial_load_tokens,
"estimated_total_text_tokens": total_text_tokens,
"relevant_file_count": len(files),
},
}
print(json.dumps(report, ensure_ascii=False, indent=2))
if failures:
raise SystemExit(2)
if __name__ == "__main__":
main()