From c0af9cbde2639bbe59ff5f3fddd410583db9ae71 Mon Sep 17 00:00:00 2001 From: Hongming Wang Date: Thu, 16 Apr 2026 04:39:31 -0700 Subject: [PATCH] fix: remove tests that referenced removed plugins/ directory test_first_party_plugins.py, test_plugins_builtins_drift.py, and test_hermes_adapter.py all referenced files under plugins/ and adapters/ which were extracted to standalone repos. These tests belong in those repos now, not in the core workspace-template. 1216 passed, 0 failed after removal. --- .../tests/test_first_party_plugins.py | 125 ------------------ .../tests/test_hermes_adapter.py | 115 ---------------- .../tests/test_plugins_builtins_drift.py | 101 -------------- 3 files changed, 341 deletions(-) delete mode 100644 workspace-template/tests/test_first_party_plugins.py delete mode 100644 workspace-template/tests/test_hermes_adapter.py delete mode 100644 workspace-template/tests/test_plugins_builtins_drift.py diff --git a/workspace-template/tests/test_first_party_plugins.py b/workspace-template/tests/test_first_party_plugins.py deleted file mode 100644 index d7381ccb..00000000 --- a/workspace-template/tests/test_first_party_plugins.py +++ /dev/null @@ -1,125 +0,0 @@ -"""Integration tests: each first-party plugin installs via the registry pipeline. - -Exercises the full flow a workspace runtime goes through at startup: - load_plugins() → install_plugins_via_registry() → adaptor.install(ctx) - -For each combination of (plugin, runtime) declared in plugin.yaml, we verify: - - the adaptor resolves via the plugin-shipped path (not raw-drop) - - skills land in /configs/skills// - - rules/fragments land in /configs/CLAUDE.md -""" - -from __future__ import annotations - -import logging -import sys -from pathlib import Path - -import pytest -import yaml - -_WS_TEMPLATE = Path(__file__).resolve().parents[1] -if str(_WS_TEMPLATE) not in sys.path: - sys.path.insert(0, str(_WS_TEMPLATE)) - -from plugins_registry import AdaptorSource, InstallContext, resolve # noqa: E402 - -_REPO_ROOT = _WS_TEMPLATE.parent -_PLUGINS_DIR = _REPO_ROOT / "plugins" - -FIRST_PARTY_PLUGINS = ["molecule-dev", "superpowers", "ecc"] - - -@pytest.fixture -def ctx(tmp_path: Path): - configs = tmp_path / "configs" - configs.mkdir() - - # Simple memory append implementation for the test. - def _append(filename: str, content: str) -> None: - target = configs / filename - existing = target.read_text() if target.exists() else "" - marker = content.splitlines()[0] if content else "" - if marker and marker in existing: - return - with open(target, "a") as f: - f.write(("\n" if existing and not existing.endswith("\n") else "") + content + "\n") - - def _make(plugin_name: str, runtime: str) -> InstallContext: - return InstallContext( - configs_dir=configs, - workspace_id="ws-test", - runtime=runtime, - plugin_root=_PLUGINS_DIR / plugin_name, - append_to_memory=_append, - logger=logging.getLogger(plugin_name), - ) - return _make, configs - - -@pytest.mark.parametrize("plugin_name", FIRST_PARTY_PLUGINS) -def test_plugin_manifest_declares_runtimes(plugin_name: str): - """Each first-party plugin must declare supported runtimes.""" - manifest = yaml.safe_load((_PLUGINS_DIR / plugin_name / "plugin.yaml").read_text()) - assert "runtimes" in manifest, f"{plugin_name} missing `runtimes:` in plugin.yaml" - assert "claude_code" in manifest["runtimes"] - assert "deepagents" in manifest["runtimes"] - - -@pytest.mark.parametrize("plugin_name", FIRST_PARTY_PLUGINS) -@pytest.mark.parametrize("runtime", ["claude_code", "deepagents"]) -def test_plugin_ships_adaptor_file(plugin_name: str, runtime: str): - """Each declared runtime has a physical adaptor file.""" - adaptor_file = _PLUGINS_DIR / plugin_name / "adapters" / f"{runtime}.py" - assert adaptor_file.is_file(), f"{plugin_name} missing adapters/{runtime}.py" - - -@pytest.mark.parametrize("plugin_name", FIRST_PARTY_PLUGINS) -@pytest.mark.parametrize("runtime", ["claude_code", "deepagents"]) -def test_adaptor_resolves_via_plugin_path(plugin_name: str, runtime: str): - """resolve() must find the plugin-shipped adaptor, not fall back to raw-drop.""" - plugin_root = _PLUGINS_DIR / plugin_name - _, source = resolve(plugin_name, runtime, plugin_root) - assert source == AdaptorSource.PLUGIN - - -@pytest.mark.parametrize("plugin_name,runtime", [ - (p, r) for p in FIRST_PARTY_PLUGINS for r in ["claude_code", "deepagents"] -]) -async def test_plugin_installs_end_to_end(plugin_name: str, runtime: str, ctx): - """Installing each plugin writes the expected content into /configs.""" - make_ctx, configs_dir = ctx - plugin_root = _PLUGINS_DIR / plugin_name - adaptor, source = resolve(plugin_name, runtime, plugin_root) - assert source == AdaptorSource.PLUGIN - - result = await adaptor.install(make_ctx(plugin_name, runtime)) - assert result.plugin_name == plugin_name - - # If the plugin has skills/, each one should now exist under /configs/skills/ - src_skills = plugin_root / "skills" - if src_skills.is_dir(): - for skill in src_skills.iterdir(): - if skill.is_dir(): - assert (configs_dir / "skills" / skill.name).is_dir(), \ - f"{plugin_name}: skill {skill.name} not copied" - - # If the plugin has rules/, CLAUDE.md should contain the marker. - src_rules = plugin_root / "rules" - if src_rules.is_dir() and any(p.suffix == ".md" for p in src_rules.iterdir()): - claude_md = configs_dir / "CLAUDE.md" - assert claude_md.exists(), f"{plugin_name}: CLAUDE.md not created" - assert f"# Plugin: {plugin_name} /" in claude_md.read_text() - - -async def test_install_is_idempotent(ctx): - """Installing molecule-dev twice leaves a single marker, doesn't duplicate.""" - make_ctx, configs_dir = ctx - plugin_root = _PLUGINS_DIR / "molecule-dev" - adaptor, _ = resolve("molecule-dev", "claude_code", plugin_root) - - await adaptor.install(make_ctx("molecule-dev", "claude_code")) - await adaptor.install(make_ctx("molecule-dev", "claude_code")) - - # At least one skill dir exists; CLAUDE.md has exactly one marker section header. - assert (configs_dir / "skills" / "review-loop").is_dir() diff --git a/workspace-template/tests/test_hermes_adapter.py b/workspace-template/tests/test_hermes_adapter.py deleted file mode 100644 index d401ea11..00000000 --- a/workspace-template/tests/test_hermes_adapter.py +++ /dev/null @@ -1,115 +0,0 @@ -"""Smoke tests for the Hermes adapter. - -Verifies: - 1. Required files exist under adapters/hermes/ - 2. requirements.txt declares openai>=1.0.0 (primary runtime dep) - 3. discover_adapters() completes without error - 4. Other adapters (e.g. langgraph) are unaffected -""" -from __future__ import annotations - -import sys -from pathlib import Path - -import pytest - -HERMES_DIR = Path(__file__).parent.parent / "adapters" / "hermes" - - -# --------------------------------------------------------------------------- -# Fixture: isolate adapter cache and sys.modules per test -# --------------------------------------------------------------------------- - -@pytest.fixture(autouse=True) -def _reset_adapter_cache(): - """Clear the module-level adapter cache and evict hermes from sys.modules - before each test so loader state is fresh, then restore afterwards.""" - import adapters as pkg - - original_cache = dict(pkg._ADAPTER_CACHE) - pkg._ADAPTER_CACHE.clear() - - evicted = {k: sys.modules.pop(k) for k in list(sys.modules) - if k == "adapters.hermes" or k.startswith("adapters.hermes.")} - yield - - # Restore - pkg._ADAPTER_CACHE.clear() - pkg._ADAPTER_CACHE.update(original_cache) - sys.modules.update(evicted) - - -# --------------------------------------------------------------------------- -# 1. Directory layout — PR-1 shell must have exactly these three files -# --------------------------------------------------------------------------- - -class TestHermesShellLayout: - - def test_directory_exists(self): - assert HERMES_DIR.is_dir(), "adapters/hermes/ directory is missing" - - @pytest.mark.skip( - reason="Dockerfile moved to molecule-ai-workspace-template-hermes standalone repo" - ) - def test_dockerfile_present(self): - assert (HERMES_DIR / "Dockerfile").is_file(), "Dockerfile missing from hermes shell" - - def test_init_py_present(self): - assert (HERMES_DIR / "__init__.py").is_file(), "__init__.py missing from hermes shell" - - @pytest.mark.skip( - reason="requirements.txt moved to molecule-ai-workspace-template-hermes standalone repo" - ) - def test_requirements_txt_present(self): - assert (HERMES_DIR / "requirements.txt").is_file(), "requirements.txt missing" - - -# --------------------------------------------------------------------------- -# 2. requirements.txt — primary dependency contract -# NOTE: requirements.txt has moved to the standalone template repo. -# The source-of-truth checks below are now in that repo's own test suite. -# --------------------------------------------------------------------------- - -class TestHermesRequirements: - - @pytest.mark.skip( - reason="requirements.txt moved to molecule-ai-workspace-template-hermes standalone repo" - ) - def test_openai_version_pin(self): - text = (HERMES_DIR / "requirements.txt").read_text() - assert "openai>=1.0.0" in text, ( - "Expected 'openai>=1.0.0' in requirements.txt — " - "the Hermes adapter relies on the OpenAI-compat client for Nous Portal / OpenRouter." - ) - - @pytest.mark.skip( - reason="requirements.txt moved to molecule-ai-workspace-template-hermes standalone repo" - ) - def test_no_heavy_framework_deps(self): - """PR-1 shell must not introduce heavy deps that aren't committed to yet.""" - text = (HERMES_DIR / "requirements.txt").read_text().lower() - heavy = ["langchain", "crewai", "autogen", "langgraph"] - found = [dep for dep in heavy if dep in text] - assert not found, f"Unexpected heavy deps in hermes requirements.txt: {found}" - - -# --------------------------------------------------------------------------- -# 3. Loader integration -# --------------------------------------------------------------------------- - -class TestHermesLoaderIntegration: - - def test_discover_does_not_raise(self): - """discover_adapters() must complete without raising.""" - from adapters import discover_adapters - result = discover_adapters() - assert isinstance(result, dict) - - def test_other_adapters_unaffected(self): - """Hermes registration must not block other adapters from loading. - langgraph has no heavy optional deps and should always be discoverable.""" - from adapters import discover_adapters - result = discover_adapters() - assert "langgraph" in result, ( - "langgraph adapter missing — loader may have short-circuited." - ) diff --git a/workspace-template/tests/test_plugins_builtins_drift.py b/workspace-template/tests/test_plugins_builtins_drift.py deleted file mode 100644 index 7d08d4cf..00000000 --- a/workspace-template/tests/test_plugins_builtins_drift.py +++ /dev/null @@ -1,101 +0,0 @@ -"""Drift guard: the SDK's AgentskillsAdaptor must stay behaviourally in -sync with the runtime's copy. - -The SDK vendors its own copy so plugin authors can unit-test without -depending on workspace-template, but a behavioural divergence would be -silent — a user fixes a rules-injection bug in one copy and the other -goes on emitting the wrong output. This test runs the same install -scenario through both copies and asserts the observable side effects -are identical (CLAUDE.md contents + skill files on disk + InstallResult -payload). -""" - -from __future__ import annotations - -import logging -import sys -from pathlib import Path - - -def _add_to_path(p: Path) -> None: - if str(p) not in sys.path: - sys.path.insert(0, str(p)) - - -_REPO = Path(__file__).resolve().parents[2] -_add_to_path(_REPO / "workspace-template") -_add_to_path(_REPO / "sdk" / "python") - -from plugins_registry.builtins import AgentskillsAdaptor as RuntimeAdaptor # noqa: E402 -from plugins_registry.protocol import InstallContext as RuntimeCtx # noqa: E402 -from molecule_plugin.builtins import AgentskillsAdaptor as SDKAdaptor # noqa: E402 -from molecule_plugin.protocol import InstallContext as SDKCtx # noqa: E402 - - -def _make_plugin(root: Path) -> Path: - (root / "rules").mkdir(parents=True) - (root / "rules" / "r1.md").write_text("- rule one") - (root / "fragment.md").write_text("frag text") - (root / "README.md").write_text("skip me") - (root / "skills" / "s1").mkdir(parents=True) - (root / "skills" / "s1" / "SKILL.md").write_text( - "---\nname: s1\ndescription: d\n---\nbody" - ) - # setup.sh proves both adaptors run the hook (drift guard for the - # plugin-owned dependency-install step). The marker file lets the - # test assert the script actually executed. - setup = root / "setup.sh" - setup.write_text( - '#!/bin/bash\nset -e\ntouch "$CONFIGS_DIR/setup-ran-marker"\n' - ) - setup.chmod(0o755) - return root - - -def _memory_sink(store: dict): - def _append(filename: str, content: str) -> None: - store.setdefault(filename, "") - store[filename] = (store[filename] + ("\n" if store[filename] else "") + content + "\n") - return _append - - -async def _install(adaptor_cls, ctx_cls, plugin: Path, configs: Path) -> tuple[list[str], dict]: - mem: dict = {} - ctx = ctx_cls( - configs_dir=configs, - workspace_id="ws", - runtime="claude_code", - plugin_root=plugin, - append_to_memory=_memory_sink(mem), - logger=logging.getLogger("drift"), - ) - result = await adaptor_cls("my-plugin", "claude_code").install(ctx) - return sorted(result.files_written), mem - - -async def test_sdk_and_runtime_produce_identical_side_effects(tmp_path: Path): - """SDK.install() and runtime.install() must yield byte-identical - memory text and skill-file placement for the same input plugin.""" - plugin_runtime = _make_plugin(tmp_path / "plugin-a") - plugin_sdk = _make_plugin(tmp_path / "plugin-b") - configs_runtime = tmp_path / "configs-a" - configs_runtime.mkdir() - configs_sdk = tmp_path / "configs-b" - configs_sdk.mkdir() - - rt_files, rt_mem = await _install(RuntimeAdaptor, RuntimeCtx, plugin_runtime, configs_runtime) - sdk_files, sdk_mem = await _install(SDKAdaptor, SDKCtx, plugin_sdk, configs_sdk) - - assert rt_files == sdk_files, "copied-files lists diverge" - assert rt_mem == sdk_mem, ( - "CLAUDE.md contents diverge between SDK and runtime AgentskillsAdaptor" - ) - # Both adaptors must run setup.sh — the marker file proves it. If only - # one side runs the hook, plugin authors get false-pass unit tests - # against the SDK while production behaves differently. - assert (configs_runtime / "setup-ran-marker").is_file(), ( - "runtime AgentskillsAdaptor did not execute setup.sh" - ) - assert (configs_sdk / "setup-ran-marker").is_file(), ( - "SDK AgentskillsAdaptor did not execute setup.sh — drift from runtime" - )