Codify Skill Action sync/async and task-center gold standards (v1.0.40)
All checks were successful
技能自动化发布 / release (push) Successful in 7s

This commit is contained in:
2026-07-14 07:55:55 +08:00
parent 2e5a8d5eed
commit a7baba7210
13 changed files with 412 additions and 23 deletions

View File

@@ -45,6 +45,7 @@ POLICY_IDS = (
"POLICY-CONTROL-002",
"POLICY-CONTROL-003",
"POLICY-DATA-PATH-001",
"POLICY-SKILL-ACTION-001",
)
STRUCTURE_PATHS = (
@@ -734,6 +735,142 @@ class TestPolicyDataPath001(unittest.TestCase):
)
_TEMPLATE_PLACEHOLDER_SLUG = "your-skill-slug"
_RPA_SESSION_TOKENS = ("RpaVideoSession",)
def _service_has_rpa_video_session(skill_root: str) -> bool:
service_dir = os.path.join(skill_root, "scripts", "service")
if not os.path.isdir(service_dir):
return False
for rel in _walk_files(skill_root, "scripts/service", suffix=".py"):
text = _read_text(os.path.join(skill_root, rel))
if any(token in text for token in _RPA_SESSION_TOKENS):
return True
return False
def _load_actions_json(skill_root: str) -> dict | None:
path = os.path.join(skill_root, "assets", "actions.json")
if not os.path.isfile(path):
return None
import json
with open(path, encoding="utf-8") as f:
return json.load(f)
class TestPolicySkillAction001(unittest.TestCase):
def test_skill_action_runtime_doc_exists(self) -> None:
path = os.path.join(get_skill_root(), "development", "SKILL_ACTION_RUNTIME.md")
self.assertTrue(
os.path.isfile(path),
msg=_policy_msg(
"POLICY-SKILL-ACTION-001",
"development/SKILL_ACTION_RUNTIME.md",
"file missing",
),
)
text = _read_text(path)
for marker in ("executionProfile", "async", "任务中心", "run_skill_action"):
self.assertIn(
marker,
text,
msg=_policy_msg(
"POLICY-SKILL-ACTION-001",
"development/SKILL_ACTION_RUNTIME.md",
f"missing marker {marker!r}",
),
)
def test_schema_defines_execution_profile(self) -> None:
import json
path = os.path.join(get_skill_root(), "assets", "schemas", "skill-actions.schema.json")
self.assertTrue(os.path.isfile(path))
with open(path, encoding="utf-8") as f:
schema = json.load(f)
action_props = schema.get("$defs", {}).get("action", {}).get("properties", {})
profile = action_props.get("executionProfile")
self.assertIsInstance(
profile,
dict,
msg=_policy_msg(
"POLICY-SKILL-ACTION-001",
"assets/schemas/skill-actions.schema.json",
"action.properties.executionProfile missing",
),
)
self.assertEqual(set(profile.get("enum") or []), {"sync", "async"})
def test_actions_md_documents_execution_profile(self) -> None:
path = os.path.join(get_skill_root(), "references", "ACTIONS.md")
text = _read_text(path)
for marker in ("executionProfile", "async", "任务中心", "SKILL_ACTION_RUNTIME"):
self.assertIn(
marker,
text,
msg=_policy_msg(
"POLICY-SKILL-ACTION-001",
"references/ACTIONS.md",
f"missing marker {marker!r}",
),
)
def test_actions_json_actions_declare_execution_profile(self) -> None:
skill_root = get_skill_root()
manifest = _load_actions_json(skill_root)
if manifest is None:
return
offenders: list[str] = []
for action in manifest.get("actions") or []:
action_id = action.get("id", "?")
profile = action.get("executionProfile")
if profile not in ("sync", "async"):
offenders.append(f"{action_id}: executionProfile={profile!r}")
self.assertEqual(
offenders,
[],
msg=_policy_msg(
"POLICY-SKILL-ACTION-001",
"assets/actions.json",
"every action must set executionProfile to sync|async:\n" + "\n".join(offenders),
),
)
def test_business_rpa_skill_has_async_agent_action(self) -> None:
from util.constants import SKILL_SLUG
skill_root = get_skill_root()
if SKILL_SLUG == _TEMPLATE_PLACEHOLDER_SLUG:
self.skipTest("template placeholder slug skips business RPA action check")
if not _service_has_rpa_video_session(skill_root):
self.skipTest("no RpaVideoSession in scripts/service")
manifest = _load_actions_json(skill_root)
self.assertIsNotNone(
manifest,
msg=_policy_msg(
"POLICY-SKILL-ACTION-001",
"assets/actions.json",
"RPA skill must provide assets/actions.json",
),
)
found = False
for action in manifest.get("actions") or []:
placements = set(action.get("placements") or [])
if action.get("executionProfile") == "async" and "agent" in placements:
found = True
break
self.assertTrue(
found,
msg=_policy_msg(
"POLICY-SKILL-ACTION-001",
"assets/actions.json",
"RPA business skill needs at least one action with executionProfile=async and placements containing agent",
),
)
class TestPolicyDocs001(unittest.TestCase):
def test_policy_matrix_exists_and_lists_policy_ids(self) -> None:
skill_root = get_skill_root()