Skip to content

Commit 10b89f2

Browse files
committed
fix(plugin-tests): the exclusion test asserts sources, not names — hermes mirror collisions ship their canonical artifact
Arrived red on main with the hermes merge (pre-dates v1.3.18's merge; reproduced at 9fa8aa0): SKILLS_NOT_IN_PLUGIN excludes the hermes mirror set, but seven of those names ALSO ship legitimately from core/system-skills/ and one ('sage') from the plugin overlay — the path-existence assertion failed on every collision. The exclusion governs the skills/ SOURCE, not the name: the test now exempts collision names and, in exchange, pins that the shipped bytes ARE the canonical source's (system-skill or overlay) — the Gate-4 stale-mirror hazard as a tripwire instead of a false alarm.
1 parent a21f887 commit 10b89f2

1 file changed

Lines changed: 39 additions & 1 deletion

File tree

develop/validators/tools/test_build_plugin.py

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,50 @@ def test_build_ships_every_declared_skill(self):
5050
self.assertTrue((out / "skills" / name / "SKILL.md").is_file(),
5151
f"{name} declared in PLUGIN_SKILLS but not shipped")
5252

53+
OVERLAY_SKILL_NAMES = frozenset(
54+
p.name for p in (REPO_ROOT / "runtime" / "plugin-overlay"
55+
/ "skills").iterdir()
56+
if (p / "SKILL.md").is_file())
57+
5358
def test_build_omits_excluded_skills(self):
59+
"""Excluded skills/ dirs must not ship — EXCEPT names the hermes
60+
mirror set shares with core/system-skills/ or the plugin
61+
overlay: those paths legitimately exist in the output because
62+
the SAME NAME ships from its canonical source (the exclusion
63+
governs the skills/ source, not the name). The companion test
64+
pins that the shipped bytes ARE the canonical source's, so a
65+
stale mirror can never ride the collision."""
5466
out = self._build()
55-
for name in build_plugin.SKILLS_NOT_IN_PLUGIN:
67+
for name in (build_plugin.SKILLS_NOT_IN_PLUGIN
68+
- build_plugin.SYSTEM_SKILL_NAMES
69+
- self.OVERLAY_SKILL_NAMES):
5670
self.assertFalse((out / "skills" / name).exists(),
5771
f"{name} is excluded but shipped anyway")
5872

73+
def test_collision_names_ship_the_canonical_source_not_the_mirror(self):
74+
"""The Gate-4 duplication lesson as a tripwire: for names that
75+
exist both as hermes mirrors (skills/) and as system skills or
76+
overlay skills, the plugin must ship the CANONICAL source — if
77+
an edit lands there and the plugin starts shipping the stale
78+
mirror, this fails."""
79+
out = self._build()
80+
for name in (build_plugin.SKILLS_NOT_IN_PLUGIN
81+
& build_plugin.SYSTEM_SKILL_NAMES):
82+
shipped = (out / "skills" / name / "SKILL.md").read_bytes()
83+
system = (REPO_ROOT / "core" / "system-skills" / name
84+
/ "SKILL.md").read_bytes()
85+
self.assertEqual(shipped, system,
86+
f"{name}: shipped bytes are not the "
87+
f"system-skill source")
88+
for name in (build_plugin.SKILLS_NOT_IN_PLUGIN
89+
& self.OVERLAY_SKILL_NAMES):
90+
shipped = (out / "skills" / name / "SKILL.md").read_bytes()
91+
overlay = (REPO_ROOT / "runtime" / "plugin-overlay" / "skills"
92+
/ name / "SKILL.md").read_bytes()
93+
self.assertEqual(shipped, overlay,
94+
f"{name}: shipped bytes are not the "
95+
f"overlay source")
96+
5997
def test_gate_scripts_are_identical_to_their_sources(self):
6098
"""A mis-wired FILE_MAP would ship a stale gate — the Gate 4 failure mode."""
6199
out = self._build()

0 commit comments

Comments
 (0)