From e96f3ff376198d586b78da54a8984759a6b47039 Mon Sep 17 00:00:00 2001 From: Bai Zhantang <157573380+bzcsk2@users.noreply.github.com> Date: Thu, 25 Jun 2026 20:59:24 +0800 Subject: [PATCH 1/4] test: smoke test built skill bundle --- skills/detectoracle/scripts/verify.py | 87 +++++++++++++++++++++++++-- 1 file changed, 83 insertions(+), 4 deletions(-) diff --git a/skills/detectoracle/scripts/verify.py b/skills/detectoracle/scripts/verify.py index 84f481e..ef47c18 100644 --- a/skills/detectoracle/scripts/verify.py +++ b/skills/detectoracle/scripts/verify.py @@ -1,16 +1,96 @@ from __future__ import annotations +import subprocess import sys +import tempfile +import zipfile from pathlib import Path +REQUIRED_BUNDLE_ENTRIES = { + "SKILL.md", + "scripts/detectoracle.py", + "scripts/issueoracle.py", + "scripts/lib/version.py", + "scripts/lib/schema.py", + "scripts/lib/env.py", + "scripts/lib/pack_loader.py", + "scripts/lib/pattern_match.py", + "scripts/lib/review.py", + "scripts/lib/github_search.py", + "scripts/lib/issue_filter.py", +} + + +def _run(cmd: list[str], *, cwd: Path) -> subprocess.CompletedProcess: + return subprocess.run( + cmd, + cwd=cwd, + capture_output=True, + text=True, + timeout=30, + ) + + +def _summarize_failure(result: subprocess.CompletedProcess) -> str: + stdout = result.stdout.strip() + stderr = result.stderr.strip() + detail = stderr or stdout or "no output" + return f"exit={result.returncode}: {detail}" + + +def _verify_bundle_archive(bundle_path: Path) -> list[str]: + errors: list[str] = [] + + if not bundle_path.exists(): + return [f"Bundle not found: {bundle_path}"] + + try: + with zipfile.ZipFile(bundle_path, "r") as zf: + names = set(zf.namelist()) + missing = sorted(REQUIRED_BUNDLE_ENTRIES - names) + if missing: + errors.append(f"Bundle missing required entries: {', '.join(missing)}") + if not any(name.startswith("packs/") for name in names): + errors.append("Bundle missing packs/ content") + if not any(name.startswith("references/") for name in names): + errors.append("Bundle missing references/ content") + + if errors: + return errors + + with tempfile.TemporaryDirectory() as tmp: + extract_dir = Path(tmp) / "skill" + zf.extractall(extract_dir) + script = extract_dir / "scripts" / "detectoracle.py" + packs_dir = extract_dir / "packs" + + diagnose = _run([sys.executable, str(script), "diagnose"], cwd=extract_dir) + if diagnose.returncode != 0: + errors.append(f"Bundle diagnose failed: {_summarize_failure(diagnose)}") + + validate = _run( + [sys.executable, str(script), "validate", str(packs_dir)], + cwd=extract_dir, + ) + if validate.returncode != 0: + errors.append(f"Bundle validate failed: {_summarize_failure(validate)}") + except zipfile.BadZipFile as e: + errors.append(f"Bundle is not a valid zip archive: {e}") + except Exception as e: + errors.append(f"Bundle smoke test failed: {e}") + + return errors + + def verify(): errors = [] scripts_dir = Path(__file__).parent skill_dir = scripts_dir.parent + repo_root = skill_dir.parents[1] + bundle_path = repo_root / "dist" / "detectoracle.skill" - # Check critical files exist. The main script keeps its legacy file name during the rename. critical = [ skill_dir / "SKILL.md", scripts_dir / "detectoracle.py", @@ -29,12 +109,10 @@ def verify(): if not f.exists(): errors.append(f"Missing critical file: {f}") - # Try importing key modules sys.path.insert(0, str(scripts_dir)) try: from lib import schema - # Test round-trip p = schema.Pattern( id="test-pattern", title="Test", @@ -50,7 +128,6 @@ def verify(): except Exception as e: errors.append(f"Schema round-trip failed: {e}") - # Check packs packs_dir = skill_dir / "packs" if packs_dir.exists(): patterns_found = list(packs_dir.rglob("patterns.yaml")) @@ -59,6 +136,8 @@ def verify(): else: errors.append("packs/ directory missing") + errors.extend(_verify_bundle_archive(bundle_path)) + if errors: print("DETECTORACLE VERIFY FAILED:") for e in errors: From edd55faee55914ee442cd0ef6ce77e1e5dfe12ee Mon Sep 17 00:00:00 2001 From: Bai Zhantang <157573380+bzcsk2@users.noreply.github.com> Date: Thu, 25 Jun 2026 21:02:06 +0800 Subject: [PATCH 2/4] style: satisfy ruff for bundle smoke verify --- skills/detectoracle/scripts/verify.py | 60 +++++++++++++-------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/skills/detectoracle/scripts/verify.py b/skills/detectoracle/scripts/verify.py index ef47c18..b4e789d 100644 --- a/skills/detectoracle/scripts/verify.py +++ b/skills/detectoracle/scripts/verify.py @@ -48,33 +48,33 @@ def _verify_bundle_archive(bundle_path: Path) -> list[str]: try: with zipfile.ZipFile(bundle_path, "r") as zf: names = set(zf.namelist()) - missing = sorted(REQUIRED_BUNDLE_ENTRIES - names) - if missing: - errors.append(f"Bundle missing required entries: {', '.join(missing)}") - if not any(name.startswith("packs/") for name in names): - errors.append("Bundle missing packs/ content") - if not any(name.startswith("references/") for name in names): - errors.append("Bundle missing references/ content") - - if errors: - return errors - - with tempfile.TemporaryDirectory() as tmp: - extract_dir = Path(tmp) / "skill" - zf.extractall(extract_dir) - script = extract_dir / "scripts" / "detectoracle.py" - packs_dir = extract_dir / "packs" - - diagnose = _run([sys.executable, str(script), "diagnose"], cwd=extract_dir) - if diagnose.returncode != 0: - errors.append(f"Bundle diagnose failed: {_summarize_failure(diagnose)}") - - validate = _run( - [sys.executable, str(script), "validate", str(packs_dir)], - cwd=extract_dir, - ) - if validate.returncode != 0: - errors.append(f"Bundle validate failed: {_summarize_failure(validate)}") + missing = sorted(REQUIRED_BUNDLE_ENTRIES - names) + if missing: + errors.append(f"Bundle missing required entries: {', '.join(missing)}") + if not any(name.startswith("packs/") for name in names): + errors.append("Bundle missing packs/ content") + if not any(name.startswith("references/") for name in names): + errors.append("Bundle missing references/ content") + + if errors: + return errors + + with tempfile.TemporaryDirectory() as tmp, zipfile.ZipFile(bundle_path, "r") as zf: + extract_dir = Path(tmp) / "skill" + zf.extractall(extract_dir) + script = extract_dir / "scripts" / "detectoracle.py" + packs_dir = extract_dir / "packs" + + diagnose = _run([sys.executable, str(script), "diagnose"], cwd=extract_dir) + if diagnose.returncode != 0: + errors.append(f"Bundle diagnose failed: {_summarize_failure(diagnose)}") + + validate = _run( + [sys.executable, str(script), "validate", str(packs_dir)], + cwd=extract_dir, + ) + if validate.returncode != 0: + errors.append(f"Bundle validate failed: {_summarize_failure(validate)}") except zipfile.BadZipFile as e: errors.append(f"Bundle is not a valid zip archive: {e}") except Exception as e: @@ -143,9 +143,9 @@ def verify(): for e in errors: print(f" - {e}") return 1 - else: - print("DETECTORACLE VERIFY PASSED") - return 0 + + print("DETECTORACLE VERIFY PASSED") + return 0 if __name__ == "__main__": From 34235c6b725db2d15f00b58e3c405df2f2d3f586 Mon Sep 17 00:00:00 2001 From: Bai Zhantang <157573380+bzcsk2@users.noreply.github.com> Date: Thu, 25 Jun 2026 21:03:04 +0800 Subject: [PATCH 3/4] style: simplify verify smoke test lint surface --- skills/detectoracle/scripts/verify.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/skills/detectoracle/scripts/verify.py b/skills/detectoracle/scripts/verify.py index b4e789d..35e458e 100644 --- a/skills/detectoracle/scripts/verify.py +++ b/skills/detectoracle/scripts/verify.py @@ -22,7 +22,7 @@ } -def _run(cmd: list[str], *, cwd: Path) -> subprocess.CompletedProcess: +def _run(cmd: list[str], *, cwd: Path): return subprocess.run( cmd, cwd=cwd, @@ -32,7 +32,7 @@ def _run(cmd: list[str], *, cwd: Path) -> subprocess.CompletedProcess: ) -def _summarize_failure(result: subprocess.CompletedProcess) -> str: +def _summarize_failure(result) -> str: stdout = result.stdout.strip() stderr = result.stderr.strip() detail = stderr or stdout or "no output" @@ -83,7 +83,7 @@ def _verify_bundle_archive(bundle_path: Path) -> list[str]: return errors -def verify(): +def verify() -> int: errors = [] scripts_dir = Path(__file__).parent @@ -124,17 +124,16 @@ def verify(): ) d = p.model_dump() p2 = schema.Pattern(**d) - assert p.id == p2.id + if p.id != p2.id: + errors.append("Schema round-trip changed pattern id") except Exception as e: errors.append(f"Schema round-trip failed: {e}") packs_dir = skill_dir / "packs" - if packs_dir.exists(): - patterns_found = list(packs_dir.rglob("patterns.yaml")) - if not patterns_found: - errors.append("No pattern packs found") - else: + if not packs_dir.exists(): errors.append("packs/ directory missing") + elif not list(packs_dir.rglob("patterns.yaml")): + errors.append("No pattern packs found") errors.extend(_verify_bundle_archive(bundle_path)) From d7ab8f1ac5dc7ee5da2f5c743a22a93a9b681471 Mon Sep 17 00:00:00 2001 From: Bai Zhantang <157573380+bzcsk2@users.noreply.github.com> Date: Thu, 25 Jun 2026 21:04:55 +0800 Subject: [PATCH 4/4] style: format verify imports --- skills/detectoracle/scripts/verify.py | 1 - 1 file changed, 1 deletion(-) diff --git a/skills/detectoracle/scripts/verify.py b/skills/detectoracle/scripts/verify.py index 35e458e..c92b2a3 100644 --- a/skills/detectoracle/scripts/verify.py +++ b/skills/detectoracle/scripts/verify.py @@ -6,7 +6,6 @@ import zipfile from pathlib import Path - REQUIRED_BUNDLE_ENTRIES = { "SKILL.md", "scripts/detectoracle.py",