diff --git a/CHANGELOG.md b/CHANGELOG.md index 118c80c..34f3436 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,9 +8,10 @@ Contributors add user-facing entries under `[Unreleased]` in the same PR. Mainta ## [Unreleased] -### Documentation +### Changed -- Clarified that bundle tests must mock network calls and model downloads in CI. +- **Tests**: `tests/test_skill_issuer.py` now requires `test_skill.py` for every registry skill under `skills/` (#160). +- **Documentation**: Clarified that bundle tests must mock network calls and model downloads in CI (#170). ## [0.3.7] - 2026-06-22 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9f5b639..e74a081 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -252,7 +252,7 @@ The primary guide for the host LLM. ### 5. `test_skill.py` (bundle test) -- **Required** for every new registry skill (template: `templates/python_skill/test_skill.py`). +- **Required** for every new registry skill (template: `templates/python_skill/test_skill.py`; enforced by `tests/test_skill_issuer.py`). - Unit tests for schema compliance and deterministic execution paths (offline; mock externals). - Ships inside the skill bundle via `pip install skillware`. - Run: `pytest skills///test_skill.py` diff --git a/docs/TESTING.md b/docs/TESTING.md index d7b08a8..f86959b 100644 --- a/docs/TESTING.md +++ b/docs/TESTING.md @@ -41,6 +41,7 @@ pip install -r requirements.txt ### Framework test - Core engine health: loader, CLI, issuer rules, version policy. +- `tests/test_skill_issuer.py` also enforces registry packaging (`__init__.py`), issuer metadata, and presence of `test_skill.py` in every skill bundle. - Lives at the **root of `tests/`** only (`tests/test_loader.py`, `tests/test_cli.py`, …). - Clone-repo only; runs in CI via `pytest tests/` together with maintainer tests below. diff --git a/templates/python_skill/README.md b/templates/python_skill/README.md index 3e60bda..2e43528 100644 --- a/templates/python_skill/README.md +++ b/templates/python_skill/README.md @@ -10,7 +10,7 @@ Starter bundle under `skills///`. Copy this template from 4. **`skill.py`**: Implement deterministic logic; no LLM-generated code in the skill body. 5. **`instructions.md`**: Tell the agent when and how to use the tool. 6. **`card.json`**: Mirror `issuer` from the manifest; customize UI fields. -7. **`test_skill.py`**: Bundle test (required); offline, mock external services, including HTTP clients, LLM APIs, embedding/model loaders, and any first-run model downloads; run `pytest skills///test_skill.py`. See [TESTING.md](../../docs/TESTING.md). +7. **`test_skill.py`**: Bundle test (required; enforced by `tests/test_skill_issuer.py`); offline, mock external services, including HTTP clients, LLM APIs, embedding/model loaders, and any first-run model downloads; run `pytest skills///test_skill.py`. See [TESTING.md](../../docs/TESTING.md). 8. **`docs/skills/.md`**: Catalog page with **ID**, **Issuer**, and **Usage Examples** (all providers; see `docs/usage/skill_usage_template.md`). 9. **`docs/skills/README.md`**: Add a row to the skill library table. diff --git a/tests/test_skill_issuer.py b/tests/test_skill_issuer.py index 8c1fd14..c130033 100644 --- a/tests/test_skill_issuer.py +++ b/tests/test_skill_issuer.py @@ -64,6 +64,17 @@ def test_registry_skills_declare_issuer(): _assert_real_issuer(manifest.get("issuer"), f"{rel} manifest.yaml") +def test_registry_skills_have_bundle_test(): + """Every registry skill must ship a co-located bundle test (RFC #156).""" + for skill_dir in _discover_skill_dirs(): + rel = skill_dir.relative_to(REPO_ROOT).as_posix() + assert ( + skill_dir / "test_skill.py" + ).is_file(), ( + f"{rel}: add test_skill.py (bundle test required for every registry skill)" + ) + + def test_registry_skills_have_packaging_init_files(): """Each registry skill must be importable under the skills package for pip wheels.""" assert (