Files
YAO 31ce04c655 Split meta skill CLI and review gates
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.
2026-06-17 18:43:02 +08:00

448 lines
19 KiB
Python

#!/usr/bin/env python3
import argparse
import json
from datetime import date
from pathlib import Path
from typing import Any
try:
import yaml
except ImportError: # pragma: no cover
yaml = None
from skill_ir_paths import find_skill_ir as find_skill_ir_document
from compile_skill_targets import TARGET_TRANSFORMS, target_native_contract, target_permission_contract
ROOT = Path(__file__).resolve().parent.parent
COMPILER_SCHEMA_VERSION = "1.0"
COMPILER_NAME = "yao-skill-ir-compiler"
def display_path(path: Path, root: Path = ROOT) -> str:
try:
return str(path.resolve().relative_to(root.resolve()))
except ValueError:
return str(path.resolve())
def load_json(path: Path) -> dict[str, Any]:
if not path.exists():
return {}
try:
payload = json.loads(path.read_text(encoding="utf-8"))
except json.JSONDecodeError:
return {}
return payload if isinstance(payload, dict) else {}
def load_yaml(path: Path) -> dict[str, Any]:
if not path.exists() or yaml is None:
return {}
payload = yaml.safe_load(path.read_text(encoding="utf-8")) or {}
return payload if isinstance(payload, dict) else {}
def read_frontmatter(path: Path) -> dict[str, Any]:
if not path.exists():
return {}
text = path.read_text(encoding="utf-8", errors="replace")
if not text.startswith("---"):
return {}
parts = text.split("---", 2)
if len(parts) < 3:
return {}
if yaml is not None:
payload = yaml.safe_load(parts[1]) or {}
return payload if isinstance(payload, dict) else {}
data: dict[str, Any] = {}
for line in parts[1].splitlines():
if ":" not in line:
continue
key, value = line.split(":", 1)
data[key.strip()] = value.strip().strip('"')
return data
def find_skill_ir(skill_dir: Path, name: str) -> tuple[dict[str, Any], str]:
return find_skill_ir_document(skill_dir, name, fallback_source="frontmatter-fallback")
def count_list(payload: dict[str, Any], key: str) -> int:
value = payload.get(key, [])
return len(value) if isinstance(value, list) else 0
def list_or_empty(payload: dict[str, Any], key: str) -> list[str]:
value = payload.get(key, [])
return [str(item) for item in value] if isinstance(value, list) else []
def resource_counts(resources: dict[str, Any]) -> dict[str, int]:
return {key: count_list(resources, key) for key in ("references", "scripts", "assets", "reports")}
def eval_counts(eval_plan: dict[str, Any]) -> dict[str, int]:
return {
"trigger": count_list(eval_plan, "trigger"),
"output": count_list(eval_plan, "output"),
"adversarial": count_list(eval_plan, "adversarial"),
"baseline": 1 if eval_plan.get("baseline") else 0,
}
def scripts_with_flag(scripts: list[dict[str, Any]], flag: str) -> list[str]:
return [str(item.get("path")) for item in scripts if item.get(flag)]
def capability(name: str, scripts: list[str], review_reason: str) -> dict[str, Any]:
return {
"required": bool(scripts),
"script_count": len(scripts),
"scripts": scripts,
"review_reason": review_reason if scripts else "",
}
def permission_contract(skill_dir: Path) -> dict[str, Any]:
trust_path = skill_dir / "reports" / "security_trust_report.json"
trust = load_json(trust_path)
scripts = trust.get("scripts", []) if isinstance(trust.get("scripts"), list) else []
network_scripts = scripts_with_flag(scripts, "uses_network")
file_write_scripts = scripts_with_flag(scripts, "uses_file_write")
subprocess_scripts = scripts_with_flag(scripts, "uses_subprocess")
interactive_scripts = scripts_with_flag(scripts, "uses_input")
capabilities = {
"network": capability("network", network_scripts, "Outbound hosts must match security/network_policy.json."),
"file_write": capability("file_write", file_write_scripts, "Scripts write local files or generated artifacts."),
"subprocess": capability("subprocess", subprocess_scripts, "Scripts spawn local commands and need operator review."),
"interactive": capability("interactive", interactive_scripts, "Scripts prompt for user input or credentials."),
}
declared = [name for name, item in capabilities.items() if item["required"]]
help_smoke = trust.get("help_smoke", {}) if isinstance(trust.get("help_smoke"), dict) else {}
network_policy = trust.get("network_policy", {}) if isinstance(trust.get("network_policy"), dict) else {}
summary = trust.get("summary", {}) if isinstance(trust.get("summary"), dict) else {}
return {
"schema_version": "1.0",
"source": display_path(trust_path, skill_dir) if trust else "missing-security-trust-report",
"source_available": bool(trust),
"declared_capabilities": declared,
"review_required": bool(declared),
"capabilities": capabilities,
"network_policy": {
"source": network_policy.get("path", "security/network_policy.json"),
"covered_scripts": network_policy.get("covered_scripts", []),
"missing_scripts": network_policy.get("missing_scripts", []),
"mismatches": network_policy.get("mismatches", []),
},
"help_smoke": {
"enabled": bool(help_smoke.get("enabled")),
"checked_count": int(help_smoke.get("checked_count", 0) or 0),
"failed_count": int(help_smoke.get("failed_count", 0) or 0),
"failed_scripts": help_smoke.get("failed_scripts", []),
},
"trust_summary": {
"secret_findings": int(summary.get("secret_findings", 0) or 0),
"network_script_count": int(summary.get("network_script_count", len(network_scripts)) or 0),
"file_write_script_count": int(summary.get("file_write_script_count", len(file_write_scripts)) or 0),
"subprocess_script_count": len(subprocess_scripts),
"interactive_script_count": int(summary.get("interactive_script_count", len(interactive_scripts)) or 0),
"help_smoke_failed_count": int(summary.get("help_smoke_failed_count", 0) or 0),
},
}
def load_sources(skill_dir: Path) -> dict[str, Any]:
skill_dir = skill_dir.resolve()
frontmatter = read_frontmatter(skill_dir / "SKILL.md")
manifest = load_json(skill_dir / "manifest.json")
interface_doc = load_yaml(skill_dir / "agents" / "interface.yaml")
name = str(frontmatter.get("name") or manifest.get("name") or skill_dir.name)
ir, ir_source = find_skill_ir(skill_dir, name)
return {
"skill_dir": skill_dir,
"frontmatter": frontmatter,
"manifest": manifest,
"interface_doc": interface_doc,
"interface": interface_doc.get("interface", {}),
"compatibility": interface_doc.get("compatibility", {}),
"ir": ir,
"ir_source": ir_source,
}
def declared_targets(sources: dict[str, Any]) -> list[str]:
ir = sources["ir"]
compatibility = sources["compatibility"]
manifest = sources["manifest"]
candidates = (
ir.get("targets")
if isinstance(ir.get("targets"), list)
else manifest.get("target_platforms")
or compatibility.get("adapter_targets")
or []
)
targets = []
for item in candidates:
value = str(item).strip()
if value and value not in targets:
targets.append(value)
return targets or ["generic"]
def semantic_source(sources: dict[str, Any]) -> dict[str, Any]:
skill_dir = sources["skill_dir"]
frontmatter = sources["frontmatter"]
manifest = sources["manifest"]
interface = sources["interface"]
compatibility = sources["compatibility"]
ir = sources["ir"]
trigger = ir.get("trigger_surface", {}) if isinstance(ir.get("trigger_surface"), dict) else {}
workflow = ir.get("workflow", {}) if isinstance(ir.get("workflow"), dict) else {}
resources = ir.get("resources", {}) if isinstance(ir.get("resources"), dict) else {}
eval_plan = ir.get("eval_plan", {}) if isinstance(ir.get("eval_plan"), dict) else {}
description = str(trigger.get("description") or frontmatter.get("description") or "")
name = str(ir.get("name") or frontmatter.get("name") or manifest.get("name") or skill_dir.name)
permissions = permission_contract(skill_dir)
return {
"name": name,
"title": str(ir.get("title") or interface.get("display_name") or name),
"version": str(manifest.get("version") or frontmatter.get("version") or "1.0.0"),
"description": description,
"job_to_be_done": str(ir.get("job_to_be_done") or description),
"trigger": {
"description": description,
"should_trigger": list_or_empty(trigger, "should_trigger"),
"should_not_trigger": list_or_empty(trigger, "should_not_trigger"),
"edge_cases": list_or_empty(trigger, "edge_cases"),
},
"workflow": {
"steps": list_or_empty(workflow, "steps"),
"decision_points": list_or_empty(workflow, "decision_points"),
"failure_modes": list_or_empty(workflow, "failure_modes"),
},
"resources": {
"references": list_or_empty(resources, "references"),
"scripts": list_or_empty(resources, "scripts"),
"assets": list_or_empty(resources, "assets"),
"reports": list_or_empty(resources, "reports"),
"counts": resource_counts(resources),
},
"eval_plan": {
"trigger": list_or_empty(eval_plan, "trigger"),
"output": list_or_empty(eval_plan, "output"),
"adversarial": list_or_empty(eval_plan, "adversarial"),
"baseline": str(eval_plan.get("baseline") or ""),
"counts": eval_counts(eval_plan),
},
"risk": ir.get("risk", {}) if isinstance(ir.get("risk"), dict) else {},
"governance": ir.get("governance", {}) if isinstance(ir.get("governance"), dict) else {},
"runtime": {
"activation": compatibility.get("activation", {}) if isinstance(compatibility.get("activation"), dict) else {},
"execution": compatibility.get("execution", {}) if isinstance(compatibility.get("execution"), dict) else {},
"trust": compatibility.get("trust", {}) if isinstance(compatibility.get("trust"), dict) else {},
"adapter_targets": compatibility.get("adapter_targets", []),
"canonical_format": compatibility.get("canonical_format", "agent-skills"),
},
"permissions": permissions,
"source_files_count": count_list(ir, "source_files") if ir else 0,
}
def compile_target_contract(skill_dir: Path, target: str) -> dict[str, Any]:
sources = load_sources(skill_dir)
compatibility = sources["compatibility"]
degradation = compatibility.get("degradation", {}) if isinstance(compatibility.get("degradation"), dict) else {}
declared = declared_targets(sources)
failures: list[str] = []
warnings: list[str] = []
profile = TARGET_TRANSFORMS.get(target)
if profile is None:
failures.append(f"Unsupported compiler target: {target}")
profile = {
"adapter_mode": "unsupported",
"generated_files": [],
"metadata_mapping": {},
"preserved_semantics": [],
"unsupported_features": [],
}
if target not in declared and not (target in {"agent-skills", "vscode"} and "agent-skills-compatible" in declared):
warnings.append(f"Target is not declared in Skill IR or interface metadata: {target}")
if not sources["ir"]:
warnings.append("Skill IR is missing; compiler used frontmatter fallback")
contract = semantic_source(sources)
permissions = contract["permissions"]
target_permissions = target_permission_contract(target, permissions)
target_native = target_native_contract(target, profile, contract, target_permissions)
contract["target"] = target
contract["target_permission_contract"] = target_permissions
contract["target_native_contract"] = target_native
contract["degradation_strategy"] = degradation.get(target, degradation.get("generic", "neutral-source"))
contract["target_runtime"] = {
"adapter_mode": profile["adapter_mode"],
"generated_files": profile["generated_files"],
"metadata_mapping": profile["metadata_mapping"],
"preserved_semantics": profile["preserved_semantics"],
"native_surface": target_native["native_surface"],
}
return {
"schema_version": COMPILER_SCHEMA_VERSION,
"target": target,
"status": "block" if failures else ("warn" if warnings else "pass"),
"compiler": {
"name": COMPILER_NAME,
"schema_version": COMPILER_SCHEMA_VERSION,
"source": "skill-ir" if sources["ir"] else "frontmatter-fallback",
"ir_source": sources["ir_source"],
"ir_schema_version": str(sources["ir"].get("schema_version") or "none"),
},
"source": {
"skill_dir": display_path(sources["skill_dir"]),
"canonical_metadata": "agents/interface.yaml" if (sources["skill_dir"] / "agents" / "interface.yaml").exists() else "missing",
"declared_targets": declared,
},
"compiled_contract": contract,
"permission_contract": permissions,
"target_permission_contract": target_permissions,
"target_native_contract": target_native,
"target_transform": {
"target": target,
"adapter_mode": profile["adapter_mode"],
"generated_files": profile["generated_files"],
"metadata_mapping": profile["metadata_mapping"],
"preserved_semantics": profile["preserved_semantics"],
"degradation_strategy": contract["degradation_strategy"],
"permission_representation": target_permissions["representation"],
"native_surface": target_native["native_surface"],
"activation_policy": target_native["activation"]["policy"],
"resource_strategy": target_native["resources"]["strategy"],
"script_strategy": target_native["scripts"]["strategy"],
"permission_enforcement": target_native["permissions"]["enforcement"],
},
"unsupported_features": list(profile.get("unsupported_features", [])),
"warnings": warnings,
"failures": failures,
}
def compile_targets(skill_dir: Path, targets: list[str] | None = None, generated_at: str | None = None) -> dict[str, Any]:
sources = load_sources(skill_dir)
selected = targets or declared_targets(sources)
compiled = [compile_target_contract(skill_dir, target) for target in selected]
failures = [failure for item in compiled for failure in item["failures"]]
warnings = [warning for item in compiled for warning in item["warnings"]]
return {
"schema_version": COMPILER_SCHEMA_VERSION,
"ok": not failures,
"generated_at": generated_at or str(date.today()),
"skill_dir": display_path(Path(skill_dir).resolve()),
"summary": {
"target_count": len(compiled),
"pass_count": sum(1 for item in compiled if item["status"] == "pass"),
"warn_count": sum(1 for item in compiled if item["status"] == "warn"),
"block_count": sum(1 for item in compiled if item["status"] == "block"),
"failure_count": len(failures),
"warning_count": len(warnings),
},
"targets": compiled,
"failures": failures,
"warnings": warnings,
}
def render_markdown(report: dict[str, Any]) -> str:
summary = report["summary"]
lines = [
"# Compiled Targets",
"",
f"- OK: `{report['ok']}`",
f"- Targets: `{summary['target_count']}`",
f"- Pass: `{summary['pass_count']}`",
f"- Warn: `{summary['warn_count']}`",
f"- Block: `{summary['block_count']}`",
"",
"## Target Transforms",
"",
"| Target | Status | Native Surface | Adapter Mode | Permissions | Degradation | Generated Files |",
"| --- | --- | --- | --- | --- | --- | --- |",
]
for item in report["targets"]:
transform = item["target_transform"]
files = ", ".join(transform.get("generated_files", [])) or "none"
permissions = ", ".join(item.get("target_permission_contract", {}).get("declared_capabilities", [])) or "none"
lines.append(
f"| `{item['target']}` | `{item['status']}` | {transform.get('native_surface', '')} | `{transform.get('adapter_mode', '')}` | `{permissions}` | `{transform.get('degradation_strategy', '')}` | {files} |"
)
lines.extend(["", "## Native Behavior Contracts", ""])
for item in report["targets"]:
native = item.get("target_native_contract", {})
permissions = native.get("permissions", {})
review = native.get("review", {})
lines.extend(
[
f"### {item['target']}",
"",
f"- Native surface: {native.get('native_surface', '')}",
f"- Activation: {native.get('activation', {}).get('policy', '')}",
f"- Resources: {native.get('resources', {}).get('strategy', '')}",
f"- Scripts: {native.get('scripts', {}).get('strategy', '')}",
f"- Permission enforcement: `{permissions.get('enforcement', '')}`; native enforcement `{permissions.get('native_enforcement')}`",
f"- Review artifacts: {', '.join(review.get('artifacts', [])) or 'none'}",
"",
]
)
lines.extend(["", "## Failures", ""])
lines.extend([f"- {item}" for item in report["failures"]] or ["- None"])
lines.extend(["", "## Warnings", ""])
lines.extend([f"- {item}" for item in report["warnings"]] or ["- None"])
return "\n".join(lines).strip() + "\n"
def render_compile_report(
skill_dir: Path,
targets: list[str] | None = None,
output_json: Path | None = None,
output_md: Path | None = None,
generated_at: str | None = None,
) -> dict[str, Any]:
skill_dir = skill_dir.resolve()
reports = skill_dir / "reports"
reports.mkdir(parents=True, exist_ok=True)
output_json = output_json or reports / "compiled_targets.json"
output_md = output_md or reports / "compiled_targets.md"
report = compile_targets(skill_dir, targets=targets, generated_at=generated_at)
report["artifacts"] = {
"json": display_path(output_json),
"markdown": display_path(output_md),
}
output_json.parent.mkdir(parents=True, exist_ok=True)
output_json.write_text(json.dumps(report, ensure_ascii=False, indent=2) + "\n", encoding="utf-8")
output_md.write_text(render_markdown(report), encoding="utf-8")
return report
def main() -> None:
parser = argparse.ArgumentParser(description="Compile Skill IR into target-specific semantic contracts.")
parser.add_argument("skill_dir", nargs="?", default=".")
parser.add_argument("--target", action="append", default=[])
parser.add_argument("--output-json")
parser.add_argument("--output-md")
parser.add_argument("--generated-at")
args = parser.parse_args()
payload = render_compile_report(
Path(args.skill_dir),
targets=args.target or None,
output_json=Path(args.output_json).resolve() if args.output_json else None,
output_md=Path(args.output_md).resolve() if args.output_md else None,
generated_at=args.generated_at,
)
print(json.dumps(payload, ensure_ascii=False, indent=2))
raise SystemExit(0 if payload["ok"] else 2)
if __name__ == "__main__":
main()