From 7d92059b4c2ae1a03a123fd3c851fa45f17355d9 Mon Sep 17 00:00:00 2001 From: huangruiteng Date: Sun, 4 Oct 2026 16:01:23 +0800 Subject: [PATCH 1/3] fix(packaging): ship project-scoped skill sources in wheels Signed-off-by: huangruiteng --- pyproject.toml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index cd7f3cab5a..2162921c4d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -77,6 +77,20 @@ include = ["loopx*"] "loopx.kunluncode_goal_mode" = ["README.md"] [tool.setuptools.data-files] +"share/loopx/skills/loopx-material" = [ + "skills/loopx-material/SKILL.md", + "skills/loopx-material/.loopx-skill-scope", +] +"share/loopx/skills/loopx-material/agents" = [ + "skills/loopx-material/agents/openai.yaml", +] +"share/loopx/skills/loopx-change-quality" = [ + "skills/loopx-change-quality/SKILL.md", + "skills/loopx-change-quality/.loopx-skill-scope", +] +"share/loopx/skills/loopx-change-quality/agents" = [ + "skills/loopx-change-quality/agents/openai.yaml", +] "share/loopx/skills/loopx-performance-diagnosis" = [ "skills/loopx-performance-diagnosis/SKILL.md", "skills/loopx-performance-diagnosis/.loopx-skill-scope", From fb03e66e2f13657ef7e2ec26e7f4f3cad1edc9d6 Mon Sep 17 00:00:00 2001 From: huangruiteng Date: Sun, 4 Oct 2026 16:01:23 +0800 Subject: [PATCH 2/3] docs(skills): clarify wheel-owned project skill delivery Signed-off-by: huangruiteng --- loopx/capabilities/project_skill_delivery/README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/loopx/capabilities/project_skill_delivery/README.md b/loopx/capabilities/project_skill_delivery/README.md index 023cea326b..025bd6bf37 100644 --- a/loopx/capabilities/project_skill_delivery/README.md +++ b/loopx/capabilities/project_skill_delivery/README.md @@ -72,6 +72,12 @@ earlier targets if a later replacement fails. The implementation copies the whole skill directory instead of linking `SKILL.md`, so supporting scripts, references, and host metadata remain complete. +Python distributions bundle the canonical `loopx-material` and +`loopx-change-quality` sources, scope markers and host display metadata +alongside the global workflows. Bundling a project skill does not add it to the +global host catalog or activate its capability. Project install, readback and +uninstall use the same release-owned sources in a wheel or source checkout. + ## Authority Boundary Project skill delivery controls discoverability, not domain authority. A From 5d5c60693aefd830167397618bd1e6ddbc3b9f96 Mon Sep 17 00:00:00 2001 From: huangruiteng Date: Sun, 4 Oct 2026 16:01:23 +0800 Subject: [PATCH 3/3] test(packaging): cover all declared skill scopes Signed-off-by: huangruiteng --- tests/test_packaged_skill_metadata.py | 29 +++++++++++++++++---------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/tests/test_packaged_skill_metadata.py b/tests/test_packaged_skill_metadata.py index 26750eeec3..33c3ef6119 100644 --- a/tests/test_packaged_skill_metadata.py +++ b/tests/test_packaged_skill_metadata.py @@ -1,8 +1,17 @@ import re from pathlib import Path +import pytest + +from loopx.capabilities.project_skill_delivery import classify_host_skill_sources + REPO_ROOT = Path(__file__).resolve().parents[1] +_SCOPED_SOURCES = classify_host_skill_sources(REPO_ROOT / "skills") +RELEASE_SKILL_IDS = ( + *_SCOPED_SOURCES["deliverable_skill_ids"], + *_SCOPED_SOURCES["project_skill_ids"], +) def test_packaged_loopx_skills_use_canonical_brand_display_names() -> None: @@ -20,24 +29,22 @@ def test_packaged_loopx_skills_use_canonical_brand_display_names() -> None: assert not display_name.startswith("Loopx"), display_name -def test_packaged_scope_markers_ship_with_workflow_sources(): +@pytest.mark.parametrize("skill_id", RELEASE_SKILL_IDS) +def test_release_scoped_skills_ship_source_and_scope_markers(skill_id): import tomllib - from loopx.skill_install_readback import PACKAGED_HOST_SKILL_IDS package = tomllib.loads((REPO_ROOT / "pyproject.toml").read_text()) data_files = package["tool"]["setuptools"]["data-files"] - for skill_id in PACKAGED_HOST_SKILL_IDS: - assert f"skills/{skill_id}/.loopx-skill-scope" in data_files[ - f"share/loopx/skills/{skill_id}" - ] + sources = data_files[f"share/loopx/skills/{skill_id}"] + assert f"skills/{skill_id}/SKILL.md" in sources + assert f"skills/{skill_id}/.loopx-skill-scope" in sources -def test_packaged_skill_display_metadata_is_in_distribution(): +@pytest.mark.parametrize("skill_id", RELEASE_SKILL_IDS) +def test_release_scoped_skill_display_metadata_is_in_distribution(skill_id): import tomllib - from loopx.skill_install_readback import PACKAGED_HOST_SKILL_IDS package = tomllib.loads((REPO_ROOT / "pyproject.toml").read_text(encoding="utf-8")) data_files = package["tool"]["setuptools"]["data-files"] - for skill_id in PACKAGED_HOST_SKILL_IDS: - assert f"skills/{skill_id}/agents/openai.yaml" in data_files[ - f"share/loopx/skills/{skill_id}/agents"] + assert f"skills/{skill_id}/agents/openai.yaml" in data_files[ + f"share/loopx/skills/{skill_id}/agents"]