mirror of
https://github.com/SuperClaude-Org/SuperClaude_Framework.git
synced 2025-12-29 16:16:08 +00:00
refactor: restructure core modules into context and memory packages
- Move pm_init components to dedicated packages - context/: PM mode initialization and contracts - memory/: Reflexion memory system - Remove deprecated superclaude/core/pm_init/ Breaking change: Import paths updated - Old: superclaude.core.pm_init.context_contract - New: superclaude.context.contract 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
12
superclaude/context/__init__.py
Normal file
12
superclaude/context/__init__.py
Normal file
@@ -0,0 +1,12 @@
|
||||
"""Project Context Management
|
||||
|
||||
Detects and manages project-specific configuration:
|
||||
- Context Contract (project rules)
|
||||
- Project structure detection
|
||||
- Initialization
|
||||
"""
|
||||
|
||||
from .contract import ContextContract
|
||||
from .init import initialize_context
|
||||
|
||||
__all__ = ["ContextContract", "initialize_context"]
|
||||
139
superclaude/context/contract.py
Normal file
139
superclaude/context/contract.py
Normal file
@@ -0,0 +1,139 @@
|
||||
"""Context Contract System
|
||||
|
||||
Auto-generates project-specific rules that must be enforced:
|
||||
- Infrastructure patterns (Kong, Traefik, Infisical)
|
||||
- Security policies (.env禁止, 秘密値管理)
|
||||
- Runtime requirements
|
||||
- Validation requirements
|
||||
"""
|
||||
|
||||
from pathlib import Path
|
||||
from typing import Dict, Any, List
|
||||
import yaml
|
||||
|
||||
|
||||
class ContextContract:
|
||||
"""Manages project-specific Context Contract"""
|
||||
|
||||
def __init__(self, git_root: Path, structure: Dict[str, Any]):
|
||||
self.git_root = git_root
|
||||
self.structure = structure
|
||||
self.contract_path = git_root / "docs" / "memory" / "context-contract.yaml"
|
||||
|
||||
def detect_principles(self) -> Dict[str, Any]:
|
||||
"""Detect project-specific principles from structure"""
|
||||
principles = {}
|
||||
|
||||
# Infisical detection
|
||||
if self.structure.get("infrastructure", {}).get("infisical"):
|
||||
principles["use_infisical_only"] = True
|
||||
principles["no_env_files"] = True
|
||||
else:
|
||||
principles["use_infisical_only"] = False
|
||||
principles["no_env_files"] = False
|
||||
|
||||
# Kong detection
|
||||
if self.structure.get("infrastructure", {}).get("kong"):
|
||||
principles["outbound_through"] = "kong"
|
||||
# Traefik detection
|
||||
elif self.structure.get("infrastructure", {}).get("traefik"):
|
||||
principles["outbound_through"] = "traefik"
|
||||
else:
|
||||
principles["outbound_through"] = None
|
||||
|
||||
# Supabase detection
|
||||
if self.structure.get("infrastructure", {}).get("supabase"):
|
||||
principles["supabase_integration"] = True
|
||||
else:
|
||||
principles["supabase_integration"] = False
|
||||
|
||||
return principles
|
||||
|
||||
def detect_runtime(self) -> Dict[str, Any]:
|
||||
"""Detect runtime requirements"""
|
||||
runtime = {}
|
||||
|
||||
# Node.js
|
||||
if "package.json" in self.structure.get("package_managers", {}).get("node", []):
|
||||
if "pnpm-lock.yaml" in self.structure.get("package_managers", {}).get("node", []):
|
||||
runtime["node"] = {
|
||||
"manager": "pnpm",
|
||||
"source": "lockfile-defined"
|
||||
}
|
||||
else:
|
||||
runtime["node"] = {
|
||||
"manager": "npm",
|
||||
"source": "package-json-defined"
|
||||
}
|
||||
|
||||
# Python
|
||||
if "pyproject.toml" in self.structure.get("package_managers", {}).get("python", []):
|
||||
if "uv.lock" in self.structure.get("package_managers", {}).get("python", []):
|
||||
runtime["python"] = {
|
||||
"manager": "uv",
|
||||
"source": "lockfile-defined"
|
||||
}
|
||||
else:
|
||||
runtime["python"] = {
|
||||
"manager": "pip",
|
||||
"source": "pyproject-defined"
|
||||
}
|
||||
|
||||
return runtime
|
||||
|
||||
def detect_validators(self) -> List[str]:
|
||||
"""Detect required validators"""
|
||||
validators = [
|
||||
"deps_exist_on_registry",
|
||||
"tests_must_run"
|
||||
]
|
||||
|
||||
principles = self.detect_principles()
|
||||
|
||||
if principles.get("use_infisical_only"):
|
||||
validators.append("no_env_file_creation")
|
||||
validators.append("no_hardcoded_secrets")
|
||||
|
||||
if principles.get("outbound_through"):
|
||||
validators.append("outbound_through_proxy")
|
||||
|
||||
return validators
|
||||
|
||||
def generate_contract(self) -> Dict[str, Any]:
|
||||
"""Generate Context Contract from detected structure"""
|
||||
return {
|
||||
"version": "1.0.0",
|
||||
"generated_at": "auto",
|
||||
"principles": self.detect_principles(),
|
||||
"runtime": self.detect_runtime(),
|
||||
"validators": self.detect_validators(),
|
||||
"structure_snapshot": self.structure
|
||||
}
|
||||
|
||||
def load_contract(self) -> Dict[str, Any]:
|
||||
"""Load existing Context Contract"""
|
||||
if not self.contract_path.exists():
|
||||
return {}
|
||||
|
||||
with open(self.contract_path, "r") as f:
|
||||
return yaml.safe_load(f)
|
||||
|
||||
def save_contract(self, contract: Dict[str, Any]) -> None:
|
||||
"""Save Context Contract to disk"""
|
||||
self.contract_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
with open(self.contract_path, "w") as f:
|
||||
yaml.dump(contract, f, default_flow_style=False, sort_keys=False)
|
||||
|
||||
def generate_or_load(self) -> Dict[str, Any]:
|
||||
"""Generate or load Context Contract"""
|
||||
# Try to load existing
|
||||
existing = self.load_contract()
|
||||
|
||||
# If exists and version matches, return it
|
||||
if existing and existing.get("version") == "1.0.0":
|
||||
return existing
|
||||
|
||||
# Otherwise, generate new contract
|
||||
contract = self.generate_contract()
|
||||
self.save_contract(contract)
|
||||
return contract
|
||||
134
superclaude/context/init.py
Normal file
134
superclaude/context/init.py
Normal file
@@ -0,0 +1,134 @@
|
||||
"""Context Initialization
|
||||
|
||||
Runs at session start to:
|
||||
1. Detect repository root and structure
|
||||
2. Generate Context Contract
|
||||
3. Load Reflexion Memory
|
||||
4. Set up project context
|
||||
"""
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
from typing import Optional, Dict, Any
|
||||
import yaml
|
||||
|
||||
from .contract import ContextContract
|
||||
from superclaude.memory import ReflexionMemory
|
||||
|
||||
|
||||
class PMInitializer:
|
||||
"""Initializes PM Mode with project context"""
|
||||
|
||||
def __init__(self, cwd: Optional[Path] = None):
|
||||
self.cwd = cwd or Path.cwd()
|
||||
self.git_root: Optional[Path] = None
|
||||
self.config: Dict[str, Any] = {}
|
||||
|
||||
def detect_git_root(self) -> Optional[Path]:
|
||||
"""Detect Git repository root"""
|
||||
try:
|
||||
result = subprocess.run(
|
||||
["git", "rev-parse", "--show-toplevel"],
|
||||
cwd=self.cwd,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
check=False
|
||||
)
|
||||
if result.returncode == 0:
|
||||
return Path(result.stdout.strip())
|
||||
except Exception:
|
||||
pass
|
||||
return None
|
||||
|
||||
def scan_project_structure(self) -> Dict[str, Any]:
|
||||
"""Lightweight scan of project structure (paths only, no content)"""
|
||||
if not self.git_root:
|
||||
return {}
|
||||
|
||||
structure = {
|
||||
"docker_compose": [],
|
||||
"infrastructure": {
|
||||
"traefik": [],
|
||||
"kong": [],
|
||||
"supabase": [],
|
||||
"infisical": []
|
||||
},
|
||||
"package_managers": {
|
||||
"node": [],
|
||||
"python": []
|
||||
},
|
||||
"config_files": []
|
||||
}
|
||||
|
||||
# Docker Compose files
|
||||
for pattern in ["docker-compose*.yml", "docker-compose*.yaml"]:
|
||||
structure["docker_compose"].extend([
|
||||
str(p.relative_to(self.git_root))
|
||||
for p in self.git_root.glob(pattern)
|
||||
])
|
||||
|
||||
# Infrastructure directories
|
||||
for infra_type in ["traefik", "kong", "supabase", "infisical"]:
|
||||
infra_path = self.git_root / "infra" / infra_type
|
||||
if infra_path.exists():
|
||||
structure["infrastructure"][infra_type].append(str(infra_path.relative_to(self.git_root)))
|
||||
|
||||
# Package managers
|
||||
if (self.git_root / "package.json").exists():
|
||||
structure["package_managers"]["node"].append("package.json")
|
||||
if (self.git_root / "pnpm-lock.yaml").exists():
|
||||
structure["package_managers"]["node"].append("pnpm-lock.yaml")
|
||||
if (self.git_root / "pyproject.toml").exists():
|
||||
structure["package_managers"]["python"].append("pyproject.toml")
|
||||
if (self.git_root / "uv.lock").exists():
|
||||
structure["package_managers"]["python"].append("uv.lock")
|
||||
|
||||
return structure
|
||||
|
||||
def initialize(self) -> Dict[str, Any]:
|
||||
"""Main initialization routine"""
|
||||
# Step 1: Detect Git root
|
||||
self.git_root = self.detect_git_root()
|
||||
if not self.git_root:
|
||||
return {
|
||||
"status": "not_git_repo",
|
||||
"message": "Not a Git repository - PM Mode running in standalone mode"
|
||||
}
|
||||
|
||||
# Step 2: Scan project structure (lightweight)
|
||||
structure = self.scan_project_structure()
|
||||
|
||||
# Step 3: Generate or load Context Contract
|
||||
contract = ContextContract(self.git_root, structure)
|
||||
contract_data = contract.generate_or_load()
|
||||
|
||||
# Step 4: Load Reflexion Memory
|
||||
memory = ReflexionMemory(self.git_root)
|
||||
memory_data = memory.load()
|
||||
|
||||
# Step 5: Return initialization data
|
||||
return {
|
||||
"status": "initialized",
|
||||
"git_root": str(self.git_root),
|
||||
"structure": structure,
|
||||
"context_contract": contract_data,
|
||||
"reflexion_memory": memory_data,
|
||||
"message": "PM Mode initialized successfully"
|
||||
}
|
||||
|
||||
|
||||
def initialize_context(cwd: Optional[Path] = None) -> Dict[str, Any]:
|
||||
"""
|
||||
Initialize project context.
|
||||
|
||||
This function runs at session start.
|
||||
|
||||
Args:
|
||||
cwd: Current working directory (defaults to os.getcwd())
|
||||
|
||||
Returns:
|
||||
Initialization status and configuration
|
||||
"""
|
||||
initializer = PMInitializer(cwd)
|
||||
return initializer.initialize()
|
||||
Reference in New Issue
Block a user