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

693 lines
19 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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)
```yaml
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)
```yaml
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)
```toml
[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`
```python
"""
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`
```python
"""
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`
```python
"""
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`
```python
"""
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)
```bash
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)
```python
# 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
```bash
# 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
```bash
# 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
```bash
# 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