from __future__ import annotations import subprocess import sys import tempfile import unittest from pathlib import Path REPO_ROOT = Path(__file__).resolve().parents[1] SCRIPT = ( REPO_ROOT / "skills" / "pouch" / "scripts" / "audit_skill_structure.py" ) class AuditSkillStructureTests(unittest.TestCase): def _write_skill(self, root: Path, *, body: str, description: str = "short") -> Path: skill = root / "demo" skill.mkdir() (skill / "SKILL.md").write_text( "---\n" "name: demo\n" f"description: {description}\n" "---\n\n" f"{body}\n", encoding="utf-8", ) return skill def _run(self, skill_dir: Path) -> subprocess.CompletedProcess[str]: return subprocess.run( [sys.executable, str(SCRIPT), str(skill_dir)], check=False, capture_output=True, text=True, ) def test_reports_within_budget_and_reference_size(self) -> None: with tempfile.TemporaryDirectory() as tmp: skill = self._write_skill( Path(tmp), body="# Demo\n\n## 步骤\n\n1. 做一件事。\n", ) (skill / "references").mkdir() (skill / "references" / "guide.md").write_text( "# Guide\n\n细节。\n", encoding="utf-8" ) result = self._run(skill) self.assertEqual(result.returncode, 0, result.stderr) self.assertIn("status: within-budget", result.stdout) self.assertIn("## 步骤", result.stdout) self.assertIn("references/guide.md", result.stdout) self.assertIn("notes:", result.stdout) self.assertIn("reference 未被 SKILL.md 链接: guide.md", result.stdout) def test_flags_hard_budget_and_vague_references(self) -> None: padding = "这是一段占位说明,用来把正文撑过硬顶。" * 400 with tempfile.TemporaryDirectory() as tmp: skill = self._write_skill( Path(tmp), body="# Demo\n\n详见 references/。\n\n" + padding, ) result = self._run(skill) self.assertEqual(result.returncode, 0, result.stderr) self.assertIn("status: over-hard-budget", result.stdout) self.assertIn("HARD SKILL.md", result.stdout) self.assertIn("见 references/", result.stdout) def test_missing_skill_exits_2(self) -> None: with tempfile.TemporaryDirectory() as tmp: result = self._run(Path(tmp) / "missing") self.assertEqual(result.returncode, 2) self.assertIn("找不到 skill", result.stderr)