#!/usr/bin/env python3 """ BR6 / D-T6 CI 门禁:中台 Skill 注册表 ↔ 设备端 Skill 类 action 对齐,防漂移。 离线纯校验(不依赖真机/WS),可进 CI。等价于 `python sdk/scripts/skill_registry_audit.py`。 """ import os import sys import importlib.util SDK_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) AUDIT = os.path.join(SDK_ROOT, "scripts", "skill_registry_audit.py") def _load_audit(): spec = importlib.util.spec_from_file_location("skill_registry_audit_under_test", AUDIT) mod = importlib.util.module_from_spec(spec) spec.loader.exec_module(mod) return mod def _collect_missing(): """复用审计逻辑,返回 (registry 校验数, 设备缺失列表)。""" mod = _load_audit() from skills import get_skill # noqa: WPS433 missing = [] ok = 0 for script in sorted(mod.DEVICE_EXECUTABLE_SCRIPTS): registry_actions = set(mod.flatten_actions(script)) cls = get_skill(script) device_actions = mod._public_methods(cls) for action in sorted(registry_actions): if action not in device_actions: missing.append(f"{script}.{action}") else: ok += 1 return ok, missing def test_registry_has_actions(): ok, _ = _collect_missing() assert ok > 0, "Skill 注册表应至少有若干 action 被校验" def test_no_registry_action_missing_on_device(): """注册表声明的 action 必须在设备端 Skill 类有同名 public method(防漂移门禁)。""" ok, missing = _collect_missing() assert not missing, ( f"注册表有 {len(missing)} 个 action 设备端缺失(漂移):{missing[:15]}" ) if __name__ == "__main__": ok, missing = _collect_missing() print(f"registry 校验 action 数: {ok} · 设备缺失: {len(missing)}") assert ok > 0 and not missing, f"门禁未通过: missing={missing[:15]}" print("✅ BR6/D-T6 Skill 注册表对齐门禁通过")