Repository navigation
Expand file tree
/
Copy pathtest_structure.py
More file actions
157 lines (112 loc) · 6.18 KB
/
Copy pathtest_structure.py
File metadata and controls
157 lines (112 loc) · 6.18 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
# Copyright (c) 2026, MariaDB plc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License, version 2.0,
# as published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
# the GNU General Public License, version 2.0, for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""Tier 1 — static / structural checks of the vendored skills.
No DB, no LLM: fast and deterministic, suitable as the always-on CI gate.
Parametrized over every skill in the manifest (plus a few suite-wide invariants).
"""
from __future__ import annotations
import pytest
from lib import skills
pytestmark = pytest.mark.static
ALL_SKILLS = skills.load_skills()
STATEMENT_SKILLS = skills.statement_skills()
ADDITIONAL_SKILLS = skills.additional_skills()
def _id(s: skills.Skill) -> str:
return s.name
# --- per-skill frontmatter / naming -----------------------------------------
@pytest.mark.parametrize("skill", ALL_SKILLS, ids=_id)
def test_skill_md_exists(skill: skills.Skill):
assert skill.path.is_file(), f"missing SKILL.md at {skill.rel_path}"
@pytest.mark.parametrize("skill", ALL_SKILLS, ids=_id)
def test_frontmatter_has_name_and_description(skill: skills.Skill):
fm = skill.frontmatter
assert isinstance(fm.get("name"), str) and fm["name"].strip(), "frontmatter missing non-empty `name`"
desc = fm.get("description")
assert isinstance(desc, str) and len(desc.strip()) >= 20, "frontmatter missing a substantive `description`"
@pytest.mark.parametrize("skill", ALL_SKILLS, ids=_id)
def test_frontmatter_name_matches_dir(skill: skills.Skill):
assert skill.frontmatter.get("name") == skill.dir_name, (
f"frontmatter name {skill.frontmatter.get('name')!r} != directory {skill.dir_name!r}"
)
@pytest.mark.parametrize("skill", ALL_SKILLS, ids=_id)
def test_manifest_name_matches_frontmatter(skill: skills.Skill):
assert skill.name == skill.frontmatter.get("name"), (
f"manifest name {skill.name!r} != frontmatter name {skill.frontmatter.get('name')!r}"
)
@pytest.mark.parametrize("skill", ALL_SKILLS, ids=_id)
def test_description_has_use_when_trigger(skill: skills.Skill):
# The discoverability contract: every skill tells the agent when to use it.
assert "use when" in skill.frontmatter.get("description", "").lower(), (
"description should contain a 'Use when …' trigger clause"
)
@pytest.mark.parametrize("skill", ALL_SKILLS, ids=_id)
def test_sql_fences_balanced(skill: skills.Skill):
assert skill.fence_count() % 2 == 0, "unbalanced ``` code fences in SKILL.md"
@pytest.mark.parametrize("skill", ALL_SKILLS, ids=_id)
def test_see_also_refs_resolve(skill: skills.Skill):
known = skills.skill_names()
dangling = {r for r in skill.see_also_refs() if r not in known}
assert not dangling, f"See Also references unknown skills: {sorted(dangling)}"
# --- statement-skill content contract ---------------------------------------
@pytest.mark.parametrize("skill", STATEMENT_SKILLS, ids=_id)
def test_statement_has_llms_often_miss(skill: skills.Skill):
assert skills.has_section(skill.body, "What LLMs Often Miss"), (
"statement skills must carry a 'What LLMs Often Miss' section"
)
@pytest.mark.parametrize("skill", STATEMENT_SKILLS, ids=_id)
def test_statement_has_runnable_sql(skill: skills.Skill):
assert skill.sql_blocks(), "statement skills must include at least one ```sql block"
# --- suite-wide invariants ---------------------------------------------------
def test_manifest_paths_exist_on_disk():
missing = [s.rel_path for s in ALL_SKILLS if not s.path.is_file()]
assert not missing, f"manifest lists skills not on disk: {missing}"
def test_every_disk_skill_is_in_manifest():
manifest_paths = {(skills.SKILLS_ROOT / s.rel_path).resolve() for s in ALL_SKILLS}
disk_paths = {p.resolve() for p in skills.discover_disk_skills()}
orphans = disk_paths - manifest_paths
assert not orphans, f"SKILL.md files on disk but absent from manifest: {sorted(map(str, orphans))}"
def test_skill_names_unique():
names = [s.name for s in ALL_SKILLS]
dupes = {n for n in names if names.count(n) > 1}
assert not dupes, f"duplicate skill names: {sorted(dupes)}"
def test_expected_statement_skill_count():
# Guardrail against an unintended change to the vendored set: the count of
# granular statement skills. Bump this when sync-skills.sh pulls a ref that
# legitimately adds or removes statement skills.
assert len(STATEMENT_SKILLS) == 31, f"expected 31 statement skills, found {len(STATEMENT_SKILLS)}"
# --- vendored `additional` skills match their source in this repo ------------
#
# `additional-skills/` is the editable source; the copies under each plugin's
# skills/ are vendored by scripts/sync-skills.sh. Editing the source without
# re-running that script leaves every plugin shipping stale text, which no other
# check would notice: the manifest still agrees with what is on disk, and the
# stale copy still parses. This is the check that notices.
@pytest.mark.parametrize("skill", ADDITIONAL_SKILLS, ids=_id)
def test_additional_skill_matches_its_source(skill: skills.Skill):
sources = skills.additional_sources(skill.name)
assert sources, (
f"no source for the vendored {skill.name!r} under additional-skills/*/ — "
"it was removed from (or renamed in) the source tree without re-running "
"scripts/sync-skills.sh"
)
assert len(sources) == 1, (
f"{skill.name!r} exists in more than one additional-skills/ subfolder: "
+ ", ".join(str(p.relative_to(skills.REPO_ROOT)) for p in sources)
)
source = sources[0]
assert skill.path.read_text(encoding="utf-8") == source.read_text(encoding="utf-8"), (
f"vendored {skill.rel_path} differs from {source.relative_to(skills.REPO_ROOT)} — "
"re-run scripts/sync-skills.sh from the repo root"
)