Files
SuperClaude/docs/architecture/MIGRATION_TO_CLEAN_ARCHITECTURE.md
kazuki e799c35efd refactor: migrate to clean architecture with src/ layout
## Migration Summary
- Moved from flat `superclaude/` to `src/superclaude/` (PEP 517/518)
- Deleted old structure (119 files removed)
- Added new structure with clean architecture layers

## Project Structure Changes
- OLD: `superclaude/{agents,commands,modes,framework}/`
- NEW: `src/superclaude/{cli,execution,pm_agent}/`

## Build System Updates
- Switched: setuptools → hatchling (modern, PEP 517)
- Updated: pyproject.toml with proper entry points
- Added: pytest plugin auto-discovery
- Version: 4.1.6 → 0.4.0 (clean slate)

## Makefile Enhancements
- Removed: `superclaude install` calls (deprecated)
- Added: `make verify` - Phase 1 installation verification
- Added: `make test-plugin` - pytest plugin loading test
- Added: `make doctor` - health check command

## Documentation Added
- docs/architecture/ - 7 architecture docs
- docs/research/python_src_layout_research_20251021.md
- docs/PR_STRATEGY.md

## Migration Phases
- Phase 1: Core installation  (this commit)
- Phase 2: Lazy loading + Skills system (next)
- Phase 3: PM Agent meta-layer (future)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-21 09:13:42 +09:00

19 KiB
Raw Blame History

Migration to Clean Plugin Architecture

Date: 2025-10-21 Status: Planning → Implementation Goal: Zero-footprint pytest plugin + Optional skills system


🎯 Design Philosophy

Before (Polluting Design)

Problem:
  - Installs to ~/.claude/superclaude/ (pollutes Claude Code)
  - Complex Component/Installer infrastructure (468-line base class)
  - Skills vs Commands混在 (2つのメカニズム)
  - setup.py packaging (deprecated)

Impact:
  - Claude Code directory pollution
  - Difficult to maintain
  - Not pip-installable cleanly
  - Confusing for users

After (Clean Design)

Solution:
  - Python package in site-packages/ only
  - pytest plugin via entry points (auto-discovery)
  - Optional Skills (user choice to install)
  - PEP 517 src/ layout (modern packaging)

Benefits:
  ✅ Zero ~/.claude/ pollution (unless user wants skills)
  ✅ pip install superclaude → pytest auto-loads
  ✅ Standard pytest plugin architecture
  ✅ Clear separation: core vs user config
  ✅ Tests stay in project root (not installed)

📂 New Directory Structure

superclaude/
├── src/                           # PEP 517 source layout
│   └── superclaude/              # Actual package
│       ├── __init__.py           # Package metadata
│       ├── __version__.py        # Version info
│       ├── pytest_plugin.py      # ⭐ pytest entry point
│       │
│       ├── pm_agent/             # PM Agent core logic
│       │   ├── __init__.py
│       │   ├── confidence.py     # Pre-execution confidence check
│       │   ├── self_check.py     # Post-implementation validation
│       │   ├── reflexion.py      # Error learning pattern
│       │   ├── token_budget.py   # Budget-aware operations
│       │   └── parallel.py       # Parallel-with-reflection
│       │
│       ├── cli/                  # CLI commands
│       │   ├── __init__.py
│       │   ├── main.py           # Entry point
│       │   ├── install_skill.py  # superclaude install-skill
│       │   └── doctor.py         # superclaude doctor
│       │
│       └── skills/               # Skill templates (not installed by default)
│           └── pm/               # PM Agent skill
│               ├── implementation.md
│               └── modules/
│                   ├── git-status.md
│                   ├── token-counter.md
│                   └── pm-formatter.md
│
├── tests/                        # Test suite (NOT installed)
│   ├── conftest.py              # pytest config + fixtures
│   ├── test_confidence_check.py
│   ├── test_self_check_protocol.py
│   ├── test_token_budget.py
│   ├── test_reflexion_pattern.py
│   └── test_pytest_plugin.py    # Plugin integration tests
│
├── docs/                         # Documentation
│   ├── architecture/
│   │   └── MIGRATION_TO_CLEAN_ARCHITECTURE.md (this file)
│   └── research/
│
├── scripts/                      # Utility scripts (not installed)
│   ├── analyze_workflow_metrics.py
│   └── ab_test_workflows.py
│
├── pyproject.toml               # ⭐ PEP 517 packaging + entry points
├── README.md
└── LICENSE

🔧 Entry Points Configuration

pyproject.toml (New)

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[project]
name = "superclaude"
version = "0.4.0"
description = "AI-enhanced development framework for Claude Code"
readme = "README.md"
license = {file = "LICENSE"}
authors = [
    {name = "Kazuki Nakai"}
]
requires-python = ">=3.10"
dependencies = [
    "pytest>=7.0.0",
    "pytest-cov>=4.0.0",
]

[project.optional-dependencies]
dev = [
    "pytest-benchmark>=4.0.0",
    "scipy>=1.10.0",  # For A/B testing
]

# ⭐ pytest plugin auto-discovery
[project.entry-points.pytest11]
superclaude = "superclaude.pytest_plugin"

# ⭐ CLI commands
[project.entry-points.console_scripts]
superclaude = "superclaude.cli.main:main"

[tool.pytest.ini_options]
testpaths = ["tests"]
python_files = ["test_*.py"]
python_classes = ["Test*"]
python_functions = ["test_*"]
addopts = [
    "-v",
    "--strict-markers",
    "--tb=short",
]
markers = [
    "unit: Unit tests",
    "integration: Integration tests",
    "hallucination: Hallucination detection tests",
    "performance: Performance benchmark tests",
]

[tool.hatch.build.targets.wheel]
packages = ["src/superclaude"]

🎨 Core Components

1. pytest Plugin Entry Point

File: src/superclaude/pytest_plugin.py

"""
SuperClaude pytest plugin

Auto-loaded when superclaude is installed.
Provides PM Agent fixtures and hooks for enhanced testing.
"""

import pytest
from pathlib import Path
from typing import Dict, Any

from .pm_agent.confidence import ConfidenceChecker
from .pm_agent.self_check import SelfCheckProtocol
from .pm_agent.reflexion import ReflexionPattern
from .pm_agent.token_budget import TokenBudgetManager


def pytest_configure(config):
    """Register SuperClaude plugin and markers"""
    config.addinivalue_line(
        "markers",
        "confidence_check: Pre-execution confidence assessment"
    )
    config.addinivalue_line(
        "markers",
        "self_check: Post-implementation validation"
    )
    config.addinivalue_line(
        "markers",
        "reflexion: Error learning and prevention"
    )


@pytest.fixture
def confidence_checker():
    """Fixture for confidence checking"""
    return ConfidenceChecker()


@pytest.fixture
def self_check_protocol():
    """Fixture for self-check protocol"""
    return SelfCheckProtocol()


@pytest.fixture
def reflexion_pattern():
    """Fixture for reflexion pattern"""
    return ReflexionPattern()


@pytest.fixture
def token_budget(request):
    """Fixture for token budget management"""
    # Get test complexity from marker
    marker = request.node.get_closest_marker("complexity")
    complexity = marker.args[0] if marker else "medium"
    return TokenBudgetManager(complexity=complexity)


@pytest.fixture
def pm_context(tmp_path):
    """
    Fixture providing PM Agent context for testing

    Creates temporary memory directory structure:
    - docs/memory/pm_context.md
    - docs/memory/last_session.md
    - docs/memory/next_actions.md
    """
    memory_dir = tmp_path / "docs" / "memory"
    memory_dir.mkdir(parents=True)

    return {
        "memory_dir": memory_dir,
        "pm_context": memory_dir / "pm_context.md",
        "last_session": memory_dir / "last_session.md",
        "next_actions": memory_dir / "next_actions.md",
    }


def pytest_runtest_setup(item):
    """
    Pre-test hook for confidence checking

    If test is marked with @pytest.mark.confidence_check,
    run pre-execution confidence assessment.
    """
    marker = item.get_closest_marker("confidence_check")
    if marker:
        checker = ConfidenceChecker()
        confidence = checker.assess(item)

        if confidence < 0.7:
            pytest.skip(f"Confidence too low: {confidence:.0%}")


def pytest_runtest_makereport(item, call):
    """
    Post-test hook for self-check and reflexion

    Records test outcomes for reflexion learning.
    """
    if call.when == "call":
        marker = item.get_closest_marker("reflexion")
        if marker and call.excinfo is not None:
            # Test failed - apply reflexion pattern
            reflexion = ReflexionPattern()
            reflexion.record_error(
                test_name=item.name,
                error=call.excinfo.value,
                traceback=call.excinfo.traceback
            )

2. PM Agent Core Modules

File: src/superclaude/pm_agent/confidence.py

"""
Pre-execution confidence check

Prevents wrong-direction execution by assessing confidence BEFORE starting.
"""

from typing import Dict, Any


class ConfidenceChecker:
    """
    Pre-implementation confidence assessment

    Usage:
        checker = ConfidenceChecker()
        confidence = checker.assess(context)

        if confidence >= 0.9:
            # High confidence - proceed
        elif confidence >= 0.7:
            # Medium confidence - present options
        else:
            # Low confidence - stop and request clarification
    """

    def assess(self, context: Any) -> float:
        """
        Assess confidence level (0.0 - 1.0)

        Checks:
        - Official documentation verified?
        - Existing patterns identified?
        - Implementation path clear?

        Returns:
            float: Confidence score (0.0 = no confidence, 1.0 = absolute)
        """
        score = 0.0
        checks = []

        # Check 1: Documentation verified (40%)
        if self._has_official_docs(context):
            score += 0.4
            checks.append("✅ Official documentation")
        else:
            checks.append("❌ Missing documentation")

        # Check 2: Existing patterns (30%)
        if self._has_existing_patterns(context):
            score += 0.3
            checks.append("✅ Existing patterns found")
        else:
            checks.append("❌ No existing patterns")

        # Check 3: Clear implementation path (30%)
        if self._has_clear_path(context):
            score += 0.3
            checks.append("✅ Implementation path clear")
        else:
            checks.append("❌ Implementation unclear")

        return score

    def _has_official_docs(self, context: Any) -> bool:
        """Check if official documentation exists"""
        # Placeholder - implement actual check
        return True

    def _has_existing_patterns(self, context: Any) -> bool:
        """Check if existing patterns can be followed"""
        # Placeholder - implement actual check
        return True

    def _has_clear_path(self, context: Any) -> bool:
        """Check if implementation path is clear"""
        # Placeholder - implement actual check
        return True

File: src/superclaude/pm_agent/self_check.py

"""
Post-implementation self-check protocol

Hallucination prevention through evidence-based validation.
"""

from typing import Dict, List, Tuple


class SelfCheckProtocol:
    """
    Post-implementation validation

    The Four Questions:
    1. テストは全てpassしてる
    2. 要件を全て満たしてる?
    3. 思い込みで実装してない?
    4. 証拠はある?
    """

    def validate(self, implementation: Dict) -> Tuple[bool, List[str]]:
        """
        Run self-check validation

        Args:
            implementation: Implementation details

        Returns:
            Tuple of (passed: bool, issues: List[str])
        """
        issues = []

        # Question 1: Tests passing?
        if not self._check_tests_passing(implementation):
            issues.append("❌ Tests not passing")

        # Question 2: Requirements met?
        if not self._check_requirements_met(implementation):
            issues.append("❌ Requirements not fully met")

        # Question 3: Assumptions verified?
        if not self._check_assumptions_verified(implementation):
            issues.append("❌ Unverified assumptions detected")

        # Question 4: Evidence provided?
        if not self._check_evidence_exists(implementation):
            issues.append("❌ Missing evidence")

        return len(issues) == 0, issues

    def _check_tests_passing(self, impl: Dict) -> bool:
        """Verify all tests pass"""
        # Placeholder - check test results
        return impl.get("tests_passed", False)

    def _check_requirements_met(self, impl: Dict) -> bool:
        """Verify all requirements satisfied"""
        # Placeholder - check requirements
        return impl.get("requirements_met", False)

    def _check_assumptions_verified(self, impl: Dict) -> bool:
        """Verify assumptions checked against docs"""
        # Placeholder - check assumptions
        return impl.get("assumptions_verified", True)

    def _check_evidence_exists(self, impl: Dict) -> bool:
        """Verify evidence provided"""
        # Placeholder - check evidence
        return impl.get("evidence_provided", False)

3. CLI Commands

File: src/superclaude/cli/main.py

"""
SuperClaude CLI

Commands:
  superclaude install-skill pm-agent  # Install PM Agent skill to ~/.claude/skills/
  superclaude doctor                   # Check installation health
"""

import click
from pathlib import Path


@click.group()
@click.version_option()
def main():
    """SuperClaude - AI-enhanced development framework"""
    pass


@main.command()
@click.argument("skill_name")
@click.option("--target", default="~/.claude/skills", help="Installation directory")
def install_skill(skill_name: str, target: str):
    """
    Install a SuperClaude skill to Claude Code

    Example:
        superclaude install-skill pm-agent
    """
    from ..skills import install_skill as install_fn

    target_path = Path(target).expanduser()
    click.echo(f"Installing skill '{skill_name}' to {target_path}...")

    if install_fn(skill_name, target_path):
        click.echo("✅ Skill installed successfully")
    else:
        click.echo("❌ Skill installation failed", err=True)


@main.command()
def doctor():
    """Check SuperClaude installation health"""
    click.echo("🔍 SuperClaude Doctor\n")

    # Check pytest plugin loaded
    import pytest
    config = pytest.Config.fromdictargs({}, [])
    plugins = config.pluginmanager.list_plugin_distinfo()

    superclaude_loaded = any(
        "superclaude" in str(plugin[0])
        for plugin in plugins
    )

    if superclaude_loaded:
        click.echo("✅ pytest plugin loaded")
    else:
        click.echo("❌ pytest plugin not loaded")

    # Check skills installed
    skills_dir = Path("~/.claude/skills").expanduser()
    if skills_dir.exists():
        skills = list(skills_dir.glob("*/implementation.md"))
        click.echo(f"✅ {len(skills)} skills installed")
    else:
        click.echo("⚠️  No skills installed (optional)")

    click.echo("\n✅ SuperClaude is healthy")


if __name__ == "__main__":
    main()

📋 Migration Checklist

Phase 1: Restructure (Day 1)

  • Create src/superclaude/ directory
  • Move current superclaude/src/superclaude/
  • Create src/superclaude/pytest_plugin.py
  • Extract PM Agent logic from Skills:
    • pm_agent/confidence.py
    • pm_agent/self_check.py
    • pm_agent/reflexion.py
    • pm_agent/token_budget.py
  • Create cli/ directory:
    • cli/main.py
    • cli/install_skill.py
  • Update pyproject.toml with entry points
  • Remove old setup.py
  • Remove setup/ directory (Component/Installer infrastructure)

Phase 2: Test Migration (Day 2)

  • Update tests/conftest.py for new structure
  • Migrate tests to use pytest plugin fixtures
  • Add test_pytest_plugin.py integration tests
  • Use pytester fixture for plugin testing
  • Run: pytest tests/ -v → All tests pass
  • Verify entry_points.txt generation

Phase 3: Clean Installation (Day 3)

  • Test: pip install -e . (editable mode)
  • Verify: pytest --trace-config shows superclaude plugin
  • Verify: ~/.claude/ remains clean (no pollution)
  • Test: superclaude doctor command works
  • Test: superclaude install-skill pm-agent
  • Verify: Skill installed to ~/.claude/skills/pm/

Phase 4: Documentation Update (Day 4)

  • Update README.md with new installation instructions
  • Document pytest plugin usage
  • Document CLI commands
  • Update CLAUDE.md (project instructions)
  • Create migration guide for users

🧪 Testing Strategy

Unit Tests (Existing)

pytest tests/test_confidence_check.py -v
pytest tests/test_self_check_protocol.py -v
pytest tests/test_token_budget.py -v
pytest tests/test_reflexion_pattern.py -v

Integration Tests (New)

# tests/test_pytest_plugin.py

def test_plugin_loads(pytester):
    """Test that superclaude plugin loads correctly"""
    pytester.makeconftest("""
        pytest_plugins = ['superclaude.pytest_plugin']
    """)

    result = pytester.runpytest("--trace-config")
    result.stdout.fnmatch_lines(["*superclaude*"])


def test_confidence_checker_fixture(pytester):
    """Test confidence_checker fixture availability"""
    pytester.makepyfile("""
        def test_example(confidence_checker):
            assert confidence_checker is not None
            confidence = confidence_checker.assess({})
            assert 0.0 <= confidence <= 1.0
    """)

    result = pytester.runpytest()
    result.assert_outcomes(passed=1)

Installation Tests

# Clean install
pip uninstall superclaude -y
pip install -e .

# Verify plugin loaded
pytest --trace-config | grep superclaude

# Verify CLI
superclaude --version
superclaude doctor

# Verify ~/.claude/ clean
ls ~/.claude/  # Should not have superclaude/ unless skill installed

🚀 Installation Instructions (New)

For Users

# Install from PyPI (future)
pip install superclaude

# Install from source (development)
git clone https://github.com/SuperClaude-Org/SuperClaude_Framework.git
cd SuperClaude_Framework
pip install -e .

# Verify installation
superclaude doctor

# Optional: Install PM Agent skill
superclaude install-skill pm-agent

For Developers

# Clone repository
git clone https://github.com/SuperClaude-Org/SuperClaude_Framework.git
cd SuperClaude_Framework

# Install in editable mode with dev dependencies
pip install -e ".[dev]"

# Run tests
pytest tests/ -v

# Check pytest plugin
pytest --trace-config

📊 Benefits Summary

Aspect Before After
~/.claude/ pollution Always polluted Clean (unless skill installed)
Packaging setup.py (deprecated) PEP 517 pyproject.toml
pytest integration Manual Auto-discovery via entry points
Installation Custom installer Standard pip install
Test location Installed to site-packages Stays in project root
Complexity 468-line Component base Simple pytest plugin
User choice Forced installation Optional skills

🎯 Success Criteria

  • pip install superclaude works cleanly
  • pytest auto-discovers superclaude plugin
  • ~/.claude/ remains untouched after pip install
  • All existing tests pass with new structure
  • superclaude doctor reports healthy
  • Skills install optionally: superclaude install-skill pm-agent
  • Documentation updated and accurate

Status: Ready to implement Next: Phase 1 - Restructure to src/ layout