mirror of
https://github.com/SuperClaude-Org/SuperClaude_Framework.git
synced 2025-12-29 16:16:08 +00:00
refactor: PEP8 compliance - directory rename and code formatting (#425)
* fix(orchestration): add WebFetch auto-trigger for infrastructure configuration Problem: Infrastructure configuration changes (e.g., Traefik port settings) were being made based on assumptions without consulting official documentation, violating the 'Evidence > assumptions' principle in PRINCIPLES.md. Solution: - Added Infrastructure Configuration Validation section to MODE_Orchestration.md - Auto-triggers WebFetch for infrastructure tools (Traefik, nginx, Docker, etc.) - Enforces MODE_DeepResearch activation for investigation - BLOCKS assumption-based configuration changes Testing: Verified WebFetch successfully retrieves Traefik official docs (port 80 default) This prevents production outages from infrastructure misconfiguration by ensuring all technical recommendations are backed by official documentation. * feat: Add PM Agent (Project Manager Agent) for seamless orchestration Introduces PM Agent as the default orchestration layer that coordinates all sub-agents and manages workflows automatically. Key Features: - Default orchestration: All user interactions handled by PM Agent - Auto-delegation: Intelligent sub-agent selection based on task analysis - Docker Gateway integration: Zero-token baseline with dynamic MCP loading - Self-improvement loop: Automatic documentation of patterns and mistakes - Optional override: Users can specify sub-agents explicitly if desired Architecture: - Agent spec: SuperClaude/Agents/pm-agent.md - Command: SuperClaude/Commands/pm.md - Updated docs: README.md (15→16 agents), agents.md (new Orchestration category) User Experience: - Default: PM Agent handles everything (seamless, no manual routing) - Optional: Explicit --agent flag for direct sub-agent access - Both modes available simultaneously (no user downside) Implementation Status: - ✅ Specification complete - ✅ Documentation complete - ⏳ Prototype implementation needed - ⏳ Docker Gateway integration needed - ⏳ Testing and validation needed Refs: kazukinakai/docker-mcp-gateway (IRIS MCP Gateway integration) * feat: Add Agent Orchestration rules for PM Agent default activation Implements PM Agent as the default orchestration layer in RULES.md. Key Changes: - New 'Agent Orchestration' section (CRITICAL priority) - PM Agent receives ALL user requests by default - Manual override with @agent-[name] bypasses PM Agent - Agent Selection Priority clearly defined: 1. Manual override → Direct routing 2. Default → PM Agent → Auto-delegation 3. Delegation based on keywords, file types, complexity, context User Experience: - Default: PM Agent handles everything (seamless) - Override: @agent-[name] for direct specialist access - Transparent: PM Agent reports delegation decisions This establishes PM Agent as the orchestration layer while respecting existing auto-activation patterns and manual overrides. Next Steps: - Local testing in agiletec project - Iteration based on actual behavior - Documentation updates as needed * refactor(pm-agent): redesign as self-improvement meta-layer Problem Resolution: PM Agent's initial design competed with existing auto-activation for task routing, creating confusion about orchestration responsibilities and adding unnecessary complexity. Design Change: Redefined PM Agent as a meta-layer agent that operates AFTER specialist agents complete tasks, focusing on: - Post-implementation documentation and pattern recording - Immediate mistake analysis with prevention checklists - Monthly documentation maintenance and noise reduction - Pattern extraction and knowledge synthesis Two-Layer Orchestration System: 1. Task Execution Layer: Existing auto-activation handles task routing (unchanged) 2. Self-Improvement Layer: PM Agent meta-layer handles documentation (new) Files Modified: - SuperClaude/Agents/pm-agent.md: Complete rewrite with meta-layer design - Category: orchestration → meta - Triggers: All user interactions → Post-implementation, mistakes, monthly - Behavioral Mindset: Continuous learning system - Self-Improvement Workflow: BEFORE/DURING/AFTER/MISTAKE RECOVERY/MAINTENANCE - SuperClaude/Core/RULES.md: Agent Orchestration section updated - Split into Task Execution Layer + Self-Improvement Layer - Added orchestration flow diagram - Clarified PM Agent activates AFTER task completion - README.md: Updated PM Agent description - "orchestrates all interactions" → "ensures continuous learning" - Docs/User-Guide/agents.md: PM Agent section rewritten - Section: Orchestration Agent → Meta-Layer Agent - Expertise: Project orchestration → Self-improvement workflow executor - Examples: Task coordination → Post-implementation documentation - PR_DOCUMENTATION.md: Comprehensive PR documentation added - Summary, motivation, changes, testing, breaking changes - Two-layer orchestration system diagram - Verification checklist Integration Validated: Tested with agiletec project's self-improvement-workflow.md: ✅ PM Agent aligns with existing BEFORE/DURING/AFTER/MISTAKE RECOVERY phases ✅ Complements (not competes with) existing workflow ✅ agiletec workflow defines WHAT, PM Agent defines WHO executes it Breaking Changes: None - Existing auto-activation continues unchanged - Specialist agents unaffected - User workflows remain the same - New capability: Automatic documentation and knowledge maintenance Value Proposition: Transforms SuperClaude into a continuously learning system that accumulates knowledge, prevents recurring mistakes, and maintains fresh documentation without manual intervention. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * docs: add Claude Code conversation history management research Research covering .jsonl file structure, performance impact, and retention policies. Content: - Claude Code .jsonl file format and message types - Performance issues from GitHub (memory leaks, conversation compaction) - Retention policies (consumer vs enterprise) - Rotation recommendations based on actual data - File history snapshot tracking mechanics Source: Moved from agiletec project (research applicable to all Claude Code projects) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * feat: add Development documentation structure Phase 1: Documentation Structure complete - Add Docs/Development/ directory for development documentation - Add ARCHITECTURE.md - System architecture with PM Agent meta-layer - Add ROADMAP.md - 5-phase development plan with checkboxes - Add TASKS.md - Daily task tracking with progress indicators - Add PROJECT_STATUS.md - Current status dashboard and metrics - Add pm-agent-integration.md - Implementation guide for PM Agent mode This establishes comprehensive documentation foundation for: - System architecture understanding - Development planning and tracking - Implementation guidance - Progress visibility Related: #pm-agent-mode #documentation #phase-1 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * feat: PM Agent session lifecycle and PDCA implementation Phase 2: PM Agent Mode Integration (Design Phase) Commands/pm.md updates: - Add "Always-Active Foundation Layer" concept - Add Session Lifecycle (Session Start/During Work/Session End) - Add PDCA Cycle (Plan/Do/Check/Act) automation - Add Serena MCP Memory Integration (list/read/write_memory) - Document auto-activation triggers Agents/pm-agent.md updates: - Add Session Start Protocol (MANDATORY auto-activation) - Add During Work PDCA Cycle with example workflows - Add Session End Protocol with state preservation - Add PDCA Self-Evaluation Pattern - Add Documentation Strategy (temp → patterns/mistakes) - Add Memory Operations Reference Key Features: - Session start auto-activation for context restoration - 30-minute checkpoint saves during work - Self-evaluation with think_about_* operations - Systematic documentation lifecycle - Knowledge evolution to CLAUDE.md Implementation Status: - ✅ Design complete (Commands/pm.md, Agents/pm-agent.md) - ⏳ Implementation pending (Core components) - ⏳ Serena MCP integration pending Salvaged from mistaken development in ~/.claude directory Related: #pm-agent-mode #session-lifecycle #pdca-cycle #phase-2 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * fix: disable Serena MCP auto-browser launch Disable web dashboard and GUI log window auto-launch in Serena MCP server to prevent intrusive browser popups on startup. Users can still manually access the dashboard at http://localhost:24282/dashboard/ if needed. Changes: - Add CLI flags to Serena run command: - --enable-web-dashboard false - --enable-gui-log-window false - Ensures Git-tracked configuration (no reliance on ~/.serena/serena_config.yml) - Aligns with AIRIS MCP Gateway integration approach 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor: rename directories to lowercase for PEP8 compliance - Rename superclaude/Agents -> superclaude/agents - Rename superclaude/Commands -> superclaude/commands - Rename superclaude/Core -> superclaude/core - Rename superclaude/Examples -> superclaude/examples - Rename superclaude/MCP -> superclaude/mcp - Rename superclaude/Modes -> superclaude/modes This change follows Python PEP8 naming conventions for package directories. * style: fix PEP8 violations and update package name to lowercase Changes: - Format all Python files with black (43 files reformatted) - Update package name from 'SuperClaude' to 'superclaude' in pyproject.toml - Fix import statements to use lowercase package name - Add missing imports (timedelta, __version__) - Remove old SuperClaude.egg-info directory PEP8 violations reduced from 2672 to 701 (mostly E501 line length due to black's 88 char vs flake8's 79 char limit). * docs: add PM Agent development documentation Add comprehensive PM Agent development documentation: - PM Agent ideal workflow (7-phase autonomous cycle) - Project structure understanding (Git vs installed environment) - Installation flow understanding (CommandsComponent behavior) - Task management system (current-tasks.md) Purpose: Eliminate repeated explanations and enable autonomous PDCA cycles 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * feat(pm-agent): add self-correcting execution and warning investigation culture ## Changes ### superclaude/commands/pm.md - Add "Self-Correcting Execution" section with root cause analysis protocol - Add "Warning/Error Investigation Culture" section enforcing zero-tolerance for dismissal - Define error detection protocol: STOP → Investigate → Hypothesis → Different Solution → Execute - Document anti-patterns (retry without understanding) and correct patterns (research-first) ### docs/Development/hypothesis-pm-autonomous-enhancement-2025-10-14.md - Add PDCA workflow hypothesis document for PM Agent autonomous enhancement ## Rationale PM Agent must never retry failed operations without understanding root causes. All warnings and errors require investigation via context7/WebFetch/documentation to ensure production-quality code and prevent technical debt accumulation. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * feat(installer): add airis-mcp-gateway MCP server option ## Changes - Add airis-mcp-gateway to MCP server options in installer - Configuration: GitHub-based installation via uvx - Repository: https://github.com/oraios/airis-mcp-gateway - Purpose: Dynamic MCP Gateway for zero-token baseline and on-demand tool loading ## Implementation Added to setup/components/mcp.py self.mcp_servers dictionary with: - install_method: github - install_command: uvx test installation - run_command: uvx runtime execution - required: False (optional server) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: kazuki <kazuki@kazukinoMacBook-Air.local> Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
parent
302c5851b1
commit
050d5ea2ab
@ -98,7 +98,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
### Technical
|
### Technical
|
||||||
- Added `setup/utils/updater.py` for PyPI update checking logic
|
- Added `setup/utils/updater.py` for PyPI update checking logic
|
||||||
- Added `bin/checkUpdate.js` for NPM update checking logic
|
- Added `bin/checkUpdate.js` for NPM update checking logic
|
||||||
- Integrated update checks into main entry points (SuperClaude/__main__.py and bin/cli.js)
|
- Integrated update checks into main entry points (superclaude/__main__.py and bin/cli.js)
|
||||||
- Non-blocking update checks with 2-second timeout to avoid delays
|
- Non-blocking update checks with 2-second timeout to avoid delays
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
@ -107,7 +107,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- Commands are now installed in `~/.claude/commands/sc/` subdirectory
|
- Commands are now installed in `~/.claude/commands/sc/` subdirectory
|
||||||
- All 21 commands updated: `/analyze` → `/sc:analyze`, `/build` → `/sc:build`, etc.
|
- All 21 commands updated: `/analyze` → `/sc:analyze`, `/build` → `/sc:build`, etc.
|
||||||
- Automatic migration from old command locations to new `sc/` subdirectory
|
- Automatic migration from old command locations to new `sc/` subdirectory
|
||||||
- **BREAKING**: Documentation reorganization - Docs/ directory renamed to Guides/
|
- **BREAKING**: Documentation reorganization - docs/ directory renamed to Guides/
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
- **NEW AGENTS**: 14 specialized domain agents with enhanced capabilities
|
- **NEW AGENTS**: 14 specialized domain agents with enhanced capabilities
|
||||||
@ -140,7 +140,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- Migration preserves existing functionality while preventing naming conflicts
|
- Migration preserves existing functionality while preventing naming conflicts
|
||||||
- Installation process detects and migrates existing commands automatically
|
- Installation process detects and migrates existing commands automatically
|
||||||
- Tab completion support for `/sc:` prefix to discover all SuperClaude commands
|
- Tab completion support for `/sc:` prefix to discover all SuperClaude commands
|
||||||
- Guides/ directory replaces Docs/ for improved organization
|
- Guides/ directory replaces docs/ for improved organization
|
||||||
|
|
||||||
## [4.0.6] - 2025-08-23
|
## [4.0.6] - 2025-08-23
|
||||||
|
|
||||||
|
|||||||
@ -12,7 +12,7 @@ SuperClaude Framework transforms Claude Code into a structured development platf
|
|||||||
**Before Reporting:**
|
**Before Reporting:**
|
||||||
- Search existing issues to avoid duplicates
|
- Search existing issues to avoid duplicates
|
||||||
- Test with latest SuperClaude version
|
- Test with latest SuperClaude version
|
||||||
- Verify issue isn't covered in [Troubleshooting Guide](Docs/Reference/troubleshooting.md)
|
- Verify issue isn't covered in [Troubleshooting Guide](docs/Reference/troubleshooting.md)
|
||||||
|
|
||||||
**Required Information:**
|
**Required Information:**
|
||||||
- SuperClaude version: `SuperClaude --version`
|
- SuperClaude version: `SuperClaude --version`
|
||||||
@ -188,8 +188,8 @@ Reference/ # Best practices and troubleshooting
|
|||||||
- Security best practices for external integrations
|
- Security best practices for external integrations
|
||||||
|
|
||||||
**Development Workflow:**
|
**Development Workflow:**
|
||||||
1. Review [Technical Architecture](Docs/Developer-Guide/technical-architecture.md)
|
1. Review [Technical Architecture](docs/Developer-Guide/technical-architecture.md)
|
||||||
2. Study [Contributing Code Guide](Docs/Developer-Guide/contributing-code.md)
|
2. Study [Contributing Code Guide](docs/Developer-Guide/contributing-code.md)
|
||||||
3. Set up development environment
|
3. Set up development environment
|
||||||
4. Create feature branch from `master`
|
4. Create feature branch from `master`
|
||||||
5. Implement changes with tests
|
5. Implement changes with tests
|
||||||
@ -203,7 +203,7 @@ Reference/ # Best practices and troubleshooting
|
|||||||
- Documentation completeness and clarity
|
- Documentation completeness and clarity
|
||||||
- Test coverage and quality
|
- Test coverage and quality
|
||||||
|
|
||||||
For detailed development guidelines, see [Contributing Code Guide](Docs/Developer-Guide/contributing-code.md).
|
For detailed development guidelines, see [Contributing Code Guide](docs/Developer-Guide/contributing-code.md).
|
||||||
|
|
||||||
## 🤝 Community Guidelines
|
## 🤝 Community Guidelines
|
||||||
|
|
||||||
@ -315,14 +315,14 @@ SuperClaude Framework enhances Claude Code for systematic software development w
|
|||||||
- Design discussions for major features
|
- Design discussions for major features
|
||||||
|
|
||||||
**Documentation Resources**
|
**Documentation Resources**
|
||||||
- [Troubleshooting Guide](Docs/Reference/troubleshooting.md) - Common issues and solutions
|
- [Troubleshooting Guide](docs/Reference/troubleshooting.md) - Common issues and solutions
|
||||||
- [Examples Cookbook](Docs/Reference/examples-cookbook.md) - Practical usage patterns
|
- [Examples Cookbook](docs/Reference/examples-cookbook.md) - Practical usage patterns
|
||||||
- [Quick Start Practices](Docs/Reference/quick-start-practices.md) - Optimization strategies
|
- [Quick Start Practices](docs/Reference/quick-start-practices.md) - Optimization strategies
|
||||||
- [Technical Architecture](Docs/Developer-Guide/technical-architecture.md) - Framework design
|
- [Technical Architecture](docs/Developer-Guide/technical-architecture.md) - Framework design
|
||||||
|
|
||||||
**Development Support**
|
**Development Support**
|
||||||
- [Contributing Code Guide](Docs/Developer-Guide/contributing-code.md) - Development setup
|
- [Contributing Code Guide](docs/Developer-Guide/contributing-code.md) - Development setup
|
||||||
- [Testing & Debugging](Docs/Developer-Guide/testing-debugging.md) - Quality procedures
|
- [Testing & Debugging](docs/Developer-Guide/testing-debugging.md) - Quality procedures
|
||||||
- Code review process through pull requests
|
- Code review process through pull requests
|
||||||
- Maintainer guidance on complex contributions
|
- Maintainer guidance on complex contributions
|
||||||
|
|
||||||
@ -344,7 +344,7 @@ Before seeking support, please:
|
|||||||
**Development Environment Issues:**
|
**Development Environment Issues:**
|
||||||
|
|
||||||
**Q: "SuperClaude install fails with permission errors"**
|
**Q: "SuperClaude install fails with permission errors"**
|
||||||
A: Use `pip install --user SuperClaude` or create virtual environment. See [Installation Guide](Docs/Getting-Started/installation.md) for details.
|
A: Use `pip install --user SuperClaude` or create virtual environment. See [Installation Guide](docs/Getting-Started/installation.md) for details.
|
||||||
|
|
||||||
**Q: "Commands not recognized after installation"**
|
**Q: "Commands not recognized after installation"**
|
||||||
A: Restart Claude Code session. Verify installation with `SuperClaude install --list-components`. Check ~/.claude directory exists.
|
A: Restart Claude Code session. Verify installation with `SuperClaude install --list-components`. Check ~/.claude directory exists.
|
||||||
@ -358,7 +358,7 @@ A: Check Node.js installation for MCP servers. Verify ~/.claude/.claude.json con
|
|||||||
A: Follow agent patterns in setup/components/agents.py. Include trigger keywords, capabilities description, and integration tests.
|
A: Follow agent patterns in setup/components/agents.py. Include trigger keywords, capabilities description, and integration tests.
|
||||||
|
|
||||||
**Q: "Testing framework setup?"**
|
**Q: "Testing framework setup?"**
|
||||||
A: See [Testing & Debugging Guide](Docs/Developer-Guide/testing-debugging.md). Use pytest for Python tests, include component validation.
|
A: See [Testing & Debugging Guide](docs/Developer-Guide/testing-debugging.md). Use pytest for Python tests, include component validation.
|
||||||
|
|
||||||
**Q: "Documentation structure?"**
|
**Q: "Documentation structure?"**
|
||||||
A: Follow existing patterns: Getting-Started → User-Guide → Developer-Guide → Reference. Include examples and progressive complexity.
|
A: Follow existing patterns: Getting-Started → User-Guide → Developer-Guide → Reference. Include examples and progressive complexity.
|
||||||
|
|||||||
30
README-ja.md
30
README-ja.md
@ -14,7 +14,7 @@
|
|||||||
<a href="https://superclaude.netlify.app/">
|
<a href="https://superclaude.netlify.app/">
|
||||||
<img src="https://img.shields.io/badge/🌐_ウェブサイトを訪問-blue" alt="Website">
|
<img src="https://img.shields.io/badge/🌐_ウェブサイトを訪問-blue" alt="Website">
|
||||||
</a>
|
</a>
|
||||||
<a href="https://pypi.org/project/SuperClaude/">
|
<a href="https://pypi.org/project/superclaude/">
|
||||||
<img src="https://img.shields.io/pypi/v/SuperClaude.svg?" alt="PyPI">
|
<img src="https://img.shields.io/pypi/v/SuperClaude.svg?" alt="PyPI">
|
||||||
</a>
|
</a>
|
||||||
<a href="https://www.npmjs.com/package/@bifrost_inc/superclaude">
|
<a href="https://www.npmjs.com/package/@bifrost_inc/superclaude">
|
||||||
@ -275,55 +275,55 @@ pip install --break-system-packages SuperClaude
|
|||||||
<tr>
|
<tr>
|
||||||
<td valign="top">
|
<td valign="top">
|
||||||
|
|
||||||
- 📝 [**クイックスタートガイド**](Docs/Getting-Started/quick-start.md)
|
- 📝 [**クイックスタートガイド**](docs/Getting-Started/quick-start.md)
|
||||||
*すぐに開始*
|
*すぐに開始*
|
||||||
|
|
||||||
- 💾 [**インストールガイド**](Docs/Getting-Started/installation.md)
|
- 💾 [**インストールガイド**](docs/Getting-Started/installation.md)
|
||||||
*詳細なセットアップ手順*
|
*詳細なセットアップ手順*
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
<td valign="top">
|
<td valign="top">
|
||||||
|
|
||||||
- 🎯 [**コマンドリファレンス**](Docs/User-Guide-jp/commands.md)
|
- 🎯 [**コマンドリファレンス**](docs/User-Guide-jp/commands.md)
|
||||||
*全21のスラッシュコマンド*
|
*全21のスラッシュコマンド*
|
||||||
|
|
||||||
- 🤖 [**エージェントガイド**](Docs/User-Guide-jp/agents.md)
|
- 🤖 [**エージェントガイド**](docs/User-Guide-jp/agents.md)
|
||||||
*14の専門エージェント*
|
*14の専門エージェント*
|
||||||
|
|
||||||
- 🎨 [**動作モード**](Docs/User-Guide-jp/modes.md)
|
- 🎨 [**動作モード**](docs/User-Guide-jp/modes.md)
|
||||||
*5つの適応モード*
|
*5つの適応モード*
|
||||||
|
|
||||||
- 🚩 [**フラグガイド**](Docs/User-Guide-jp/flags.md)
|
- 🚩 [**フラグガイド**](docs/User-Guide-jp/flags.md)
|
||||||
*動作制御パラメータ*
|
*動作制御パラメータ*
|
||||||
|
|
||||||
- 🔧 [**MCPサーバー**](Docs/User-Guide-jp/mcp-servers.md)
|
- 🔧 [**MCPサーバー**](docs/User-Guide-jp/mcp-servers.md)
|
||||||
*6つのサーバー統合*
|
*6つのサーバー統合*
|
||||||
|
|
||||||
- 💼 [**セッション管理**](Docs/User-Guide-jp/session-management.md)
|
- 💼 [**セッション管理**](docs/User-Guide-jp/session-management.md)
|
||||||
*状態の保存と復元*
|
*状態の保存と復元*
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
<td valign="top">
|
<td valign="top">
|
||||||
|
|
||||||
- 🏗️ [**技術アーキテクチャ**](Docs/Developer-Guide/technical-architecture.md)
|
- 🏗️ [**技術アーキテクチャ**](docs/Developer-Guide/technical-architecture.md)
|
||||||
*システム設計の詳細*
|
*システム設計の詳細*
|
||||||
|
|
||||||
- 💻 [**コード貢献**](Docs/Developer-Guide/contributing-code.md)
|
- 💻 [**コード貢献**](docs/Developer-Guide/contributing-code.md)
|
||||||
*開発ワークフロー*
|
*開発ワークフロー*
|
||||||
|
|
||||||
- 🧪 [**テスト&デバッグ**](Docs/Developer-Guide/testing-debugging.md)
|
- 🧪 [**テスト&デバッグ**](docs/Developer-Guide/testing-debugging.md)
|
||||||
*品質保証*
|
*品質保証*
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
<td valign="top">
|
<td valign="top">
|
||||||
|
|
||||||
- ✨ [**ベストプラクティス**](Docs/Reference/quick-start-practices.md)
|
- ✨ [**ベストプラクティス**](docs/Reference/quick-start-practices.md)
|
||||||
*プロのコツとパターン*
|
*プロのコツとパターン*
|
||||||
|
|
||||||
- 📓 [**サンプル集**](Docs/Reference/examples-cookbook.md)
|
- 📓 [**サンプル集**](docs/Reference/examples-cookbook.md)
|
||||||
*実際の使用例*
|
*実際の使用例*
|
||||||
|
|
||||||
- 🔍 [**トラブルシューティング**](Docs/Reference/troubleshooting.md)
|
- 🔍 [**トラブルシューティング**](docs/Reference/troubleshooting.md)
|
||||||
*一般的な問題と修正*
|
*一般的な問題と修正*
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
|
|||||||
30
README-kr.md
30
README-kr.md
@ -14,7 +14,7 @@
|
|||||||
<a href="https://superclaude.netlify.app/">
|
<a href="https://superclaude.netlify.app/">
|
||||||
<img src="https://img.shields.io/badge/🌐_웹사이트_방문-blue" alt="Website">
|
<img src="https://img.shields.io/badge/🌐_웹사이트_방문-blue" alt="Website">
|
||||||
</a>
|
</a>
|
||||||
<a href="https://pypi.org/project/SuperClaude/">
|
<a href="https://pypi.org/project/superclaude/">
|
||||||
<img src="https://img.shields.io/pypi/v/SuperClaude.svg?" alt="PyPI">
|
<img src="https://img.shields.io/pypi/v/SuperClaude.svg?" alt="PyPI">
|
||||||
</a>
|
</a>
|
||||||
<a href="https://www.npmjs.com/package/@bifrost_inc/superclaude">
|
<a href="https://www.npmjs.com/package/@bifrost_inc/superclaude">
|
||||||
@ -278,55 +278,55 @@ pip install --break-system-packages SuperClaude
|
|||||||
<tr>
|
<tr>
|
||||||
<td valign="top">
|
<td valign="top">
|
||||||
|
|
||||||
- 📝 [**빠른 시작 가이드**](Docs/Getting-Started/quick-start.md)
|
- 📝 [**빠른 시작 가이드**](docs/Getting-Started/quick-start.md)
|
||||||
*즉시 시작하기*
|
*즉시 시작하기*
|
||||||
|
|
||||||
- 💾 [**설치 가이드**](Docs/Getting-Started/installation.md)
|
- 💾 [**설치 가이드**](docs/Getting-Started/installation.md)
|
||||||
*상세한 설정 단계*
|
*상세한 설정 단계*
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
<td valign="top">
|
<td valign="top">
|
||||||
|
|
||||||
- 🎯 [**명령어 레퍼런스**](Docs/User-Guide/commands.md)
|
- 🎯 [**명령어 레퍼런스**](docs/User-Guide/commands.md)
|
||||||
*전체 21개 슬래시 명령어*
|
*전체 21개 슬래시 명령어*
|
||||||
|
|
||||||
- 🤖 [**에이전트 가이드**](Docs/User-Guide/agents.md)
|
- 🤖 [**에이전트 가이드**](docs/User-Guide/agents.md)
|
||||||
*14개 전문 에이전트*
|
*14개 전문 에이전트*
|
||||||
|
|
||||||
- 🎨 [**작동 모드**](Docs/User-Guide/modes.md)
|
- 🎨 [**작동 모드**](docs/User-Guide/modes.md)
|
||||||
*5가지 적응형 모드*
|
*5가지 적응형 모드*
|
||||||
|
|
||||||
- 🚩 [**플래그 가이드**](Docs/User-Guide/flags.md)
|
- 🚩 [**플래그 가이드**](docs/User-Guide/flags.md)
|
||||||
*동작 제어 매개변수*
|
*동작 제어 매개변수*
|
||||||
|
|
||||||
- 🔧 [**MCP 서버**](Docs/User-Guide/mcp-servers.md)
|
- 🔧 [**MCP 서버**](docs/User-Guide/mcp-servers.md)
|
||||||
*6개 서버 통합*
|
*6개 서버 통합*
|
||||||
|
|
||||||
- 💼 [**세션 관리**](Docs/User-Guide/session-management.md)
|
- 💼 [**세션 관리**](docs/User-Guide/session-management.md)
|
||||||
*상태 저장 및 복원*
|
*상태 저장 및 복원*
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
<td valign="top">
|
<td valign="top">
|
||||||
|
|
||||||
- 🏗️ [**기술 아키텍처**](Docs/Developer-Guide/technical-architecture.md)
|
- 🏗️ [**기술 아키텍처**](docs/Developer-Guide/technical-architecture.md)
|
||||||
*시스템 설계 세부사항*
|
*시스템 설계 세부사항*
|
||||||
|
|
||||||
- 💻 [**코드 기여**](Docs/Developer-Guide/contributing-code.md)
|
- 💻 [**코드 기여**](docs/Developer-Guide/contributing-code.md)
|
||||||
*개발 워크플로우*
|
*개발 워크플로우*
|
||||||
|
|
||||||
- 🧪 [**테스트 및 디버깅**](Docs/Developer-Guide/testing-debugging.md)
|
- 🧪 [**테스트 및 디버깅**](docs/Developer-Guide/testing-debugging.md)
|
||||||
*품질 보증*
|
*품질 보증*
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
<td valign="top">
|
<td valign="top">
|
||||||
|
|
||||||
- ✨ [**모범 사례**](Docs/Reference/quick-start-practices.md)
|
- ✨ [**모범 사례**](docs/Reference/quick-start-practices.md)
|
||||||
*전문가 팁과 패턴*
|
*전문가 팁과 패턴*
|
||||||
|
|
||||||
- 📓 [**예제 모음**](Docs/Reference/examples-cookbook.md)
|
- 📓 [**예제 모음**](docs/Reference/examples-cookbook.md)
|
||||||
*실제 사용 예제*
|
*실제 사용 예제*
|
||||||
|
|
||||||
- 🔍 [**문제 해결**](Docs/Reference/troubleshooting.md)
|
- 🔍 [**문제 해결**](docs/Reference/troubleshooting.md)
|
||||||
*일반적인 문제와 수정*
|
*일반적인 문제와 수정*
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
|
|||||||
30
README-zh.md
30
README-zh.md
@ -14,7 +14,7 @@
|
|||||||
<a href="https://superclaude.netlify.app/">
|
<a href="https://superclaude.netlify.app/">
|
||||||
<img src="https://img.shields.io/badge/🌐_访问网站-blue" alt="Website">
|
<img src="https://img.shields.io/badge/🌐_访问网站-blue" alt="Website">
|
||||||
</a>
|
</a>
|
||||||
<a href="https://pypi.org/project/SuperClaude/">
|
<a href="https://pypi.org/project/superclaude/">
|
||||||
<img src="https://img.shields.io/pypi/v/SuperClaude.svg?" alt="PyPI">
|
<img src="https://img.shields.io/pypi/v/SuperClaude.svg?" alt="PyPI">
|
||||||
</a>
|
</a>
|
||||||
<a href="https://www.npmjs.com/package/@bifrost_inc/superclaude">
|
<a href="https://www.npmjs.com/package/@bifrost_inc/superclaude">
|
||||||
@ -275,55 +275,55 @@ pip install --break-system-packages SuperClaude
|
|||||||
<tr>
|
<tr>
|
||||||
<td valign="top">
|
<td valign="top">
|
||||||
|
|
||||||
- 📝 [**快速开始指南**](Docs/Getting-Started/quick-start.md)
|
- 📝 [**快速开始指南**](docs/Getting-Started/quick-start.md)
|
||||||
*快速上手使用*
|
*快速上手使用*
|
||||||
|
|
||||||
- 💾 [**安装指南**](Docs/Getting-Started/installation.md)
|
- 💾 [**安装指南**](docs/Getting-Started/installation.md)
|
||||||
*详细的安装说明*
|
*详细的安装说明*
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
<td valign="top">
|
<td valign="top">
|
||||||
|
|
||||||
- 🎯 [**命令参考**](Docs/User-Guide-zh/commands.md)
|
- 🎯 [**命令参考**](docs/User-Guide-zh/commands.md)
|
||||||
*全部21个斜杠命令*
|
*全部21个斜杠命令*
|
||||||
|
|
||||||
- 🤖 [**智能体指南**](Docs/User-Guide-zh/agents.md)
|
- 🤖 [**智能体指南**](docs/User-Guide-zh/agents.md)
|
||||||
*14个专业智能体*
|
*14个专业智能体*
|
||||||
|
|
||||||
- 🎨 [**行为模式**](Docs/User-Guide-zh/modes.md)
|
- 🎨 [**行为模式**](docs/User-Guide-zh/modes.md)
|
||||||
*5种自适应模式*
|
*5种自适应模式*
|
||||||
|
|
||||||
- 🚩 [**标志指南**](Docs/User-Guide-zh/flags.md)
|
- 🚩 [**标志指南**](docs/User-Guide-zh/flags.md)
|
||||||
*控制行为参数*
|
*控制行为参数*
|
||||||
|
|
||||||
- 🔧 [**MCP服务器**](Docs/User-Guide-zh/mcp-servers.md)
|
- 🔧 [**MCP服务器**](docs/User-Guide-zh/mcp-servers.md)
|
||||||
*6个服务器集成*
|
*6个服务器集成*
|
||||||
|
|
||||||
- 💼 [**会话管理**](Docs/User-Guide-zh/session-management.md)
|
- 💼 [**会话管理**](docs/User-Guide-zh/session-management.md)
|
||||||
*保存和恢复状态*
|
*保存和恢复状态*
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
<td valign="top">
|
<td valign="top">
|
||||||
|
|
||||||
- 🏗️ [**技术架构**](Docs/Developer-Guide/technical-architecture.md)
|
- 🏗️ [**技术架构**](docs/Developer-Guide/technical-architecture.md)
|
||||||
*系统设计详情*
|
*系统设计详情*
|
||||||
|
|
||||||
- 💻 [**贡献代码**](Docs/Developer-Guide/contributing-code.md)
|
- 💻 [**贡献代码**](docs/Developer-Guide/contributing-code.md)
|
||||||
*开发工作流程*
|
*开发工作流程*
|
||||||
|
|
||||||
- 🧪 [**测试与调试**](Docs/Developer-Guide/testing-debugging.md)
|
- 🧪 [**测试与调试**](docs/Developer-Guide/testing-debugging.md)
|
||||||
*质量保证*
|
*质量保证*
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
<td valign="top">
|
<td valign="top">
|
||||||
|
|
||||||
- ✨ [**最佳实践**](Docs/Reference/quick-start-practices.md)
|
- ✨ [**最佳实践**](docs/Reference/quick-start-practices.md)
|
||||||
*专业技巧和模式*
|
*专业技巧和模式*
|
||||||
|
|
||||||
- 📓 [**示例手册**](Docs/Reference/examples-cookbook.md)
|
- 📓 [**示例手册**](docs/Reference/examples-cookbook.md)
|
||||||
*实际应用示例*
|
*实际应用示例*
|
||||||
|
|
||||||
- 🔍 [**故障排除**](Docs/Reference/troubleshooting.md)
|
- 🔍 [**故障排除**](docs/Reference/troubleshooting.md)
|
||||||
*常见问题和修复*
|
*常见问题和修复*
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
|
|||||||
28
README.md
28
README.md
@ -23,7 +23,7 @@
|
|||||||
<a href="https://superclaude.netlify.app/">
|
<a href="https://superclaude.netlify.app/">
|
||||||
<img src="https://img.shields.io/badge/🌐_Visit_Website-blue" alt="Website">
|
<img src="https://img.shields.io/badge/🌐_Visit_Website-blue" alt="Website">
|
||||||
</a>
|
</a>
|
||||||
<a href="https://pypi.org/project/SuperClaude/">
|
<a href="https://pypi.org/project/superclaude/">
|
||||||
<img src="https://img.shields.io/pypi/v/SuperClaude.svg?" alt="PyPI">
|
<img src="https://img.shields.io/pypi/v/SuperClaude.svg?" alt="PyPI">
|
||||||
</a>
|
</a>
|
||||||
<a href="https://pepy.tech/projects/superclaude">
|
<a href="https://pepy.tech/projects/superclaude">
|
||||||
@ -392,51 +392,51 @@ The Deep Research system intelligently coordinates multiple tools:
|
|||||||
<tr>
|
<tr>
|
||||||
<td valign="top">
|
<td valign="top">
|
||||||
|
|
||||||
- 📝 [**Quick Start Guide**](Docs/Getting-Started/quick-start.md)
|
- 📝 [**Quick Start Guide**](docs/Getting-Started/quick-start.md)
|
||||||
*Get up and running fast*
|
*Get up and running fast*
|
||||||
|
|
||||||
- 💾 [**Installation Guide**](Docs/Getting-Started/installation.md)
|
- 💾 [**Installation Guide**](docs/Getting-Started/installation.md)
|
||||||
*Detailed setup instructions*
|
*Detailed setup instructions*
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
<td valign="top">
|
<td valign="top">
|
||||||
|
|
||||||
- 🎯 [**Commands Reference**](Docs/User-Guide/commands.md)
|
- 🎯 [**Commands Reference**](docs/User-Guide/commands.md)
|
||||||
*All 25 slash commands*
|
*All 25 slash commands*
|
||||||
|
|
||||||
- 🤖 [**Agents Guide**](Docs/User-Guide/agents.md)
|
- 🤖 [**Agents Guide**](docs/User-Guide/agents.md)
|
||||||
*15 specialized agents*
|
*15 specialized agents*
|
||||||
|
|
||||||
- 🎨 [**Behavioral Modes**](Docs/User-Guide/modes.md)
|
- 🎨 [**Behavioral Modes**](docs/User-Guide/modes.md)
|
||||||
*7 adaptive modes*
|
*7 adaptive modes*
|
||||||
|
|
||||||
- 🚩 [**Flags Guide**](Docs/User-Guide/flags.md)
|
- 🚩 [**Flags Guide**](docs/User-Guide/flags.md)
|
||||||
*Control behaviors*
|
*Control behaviors*
|
||||||
|
|
||||||
- 🔧 [**MCP Servers**](Docs/User-Guide/mcp-servers.md)
|
- 🔧 [**MCP Servers**](docs/User-Guide/mcp-servers.md)
|
||||||
*7 server integrations*
|
*7 server integrations*
|
||||||
|
|
||||||
- 💼 [**Session Management**](Docs/User-Guide/session-management.md)
|
- 💼 [**Session Management**](docs/User-Guide/session-management.md)
|
||||||
*Save & restore state*
|
*Save & restore state*
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
<td valign="top">
|
<td valign="top">
|
||||||
|
|
||||||
- 🏗️ [**Technical Architecture**](Docs/Developer-Guide/technical-architecture.md)
|
- 🏗️ [**Technical Architecture**](docs/Developer-Guide/technical-architecture.md)
|
||||||
*System design details*
|
*System design details*
|
||||||
|
|
||||||
- 💻 [**Contributing Code**](Docs/Developer-Guide/contributing-code.md)
|
- 💻 [**Contributing Code**](docs/Developer-Guide/contributing-code.md)
|
||||||
*Development workflow*
|
*Development workflow*
|
||||||
|
|
||||||
- 🧪 [**Testing & Debugging**](Docs/Developer-Guide/testing-debugging.md)
|
- 🧪 [**Testing & Debugging**](docs/Developer-Guide/testing-debugging.md)
|
||||||
*Quality assurance*
|
*Quality assurance*
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
<td valign="top">
|
<td valign="top">
|
||||||
- 📓 [**Examples Cookbook**](Docs/Reference/examples-cookbook.md)
|
- 📓 [**Examples Cookbook**](docs/Reference/examples-cookbook.md)
|
||||||
*Real-world recipes*
|
*Real-world recipes*
|
||||||
|
|
||||||
- 🔍 [**Troubleshooting**](Docs/Reference/troubleshooting.md)
|
- 🔍 [**Troubleshooting**](docs/Reference/troubleshooting.md)
|
||||||
*Common issues & fixes*
|
*Common issues & fixes*
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
|
|||||||
18
SECURITY.md
18
SECURITY.md
@ -631,7 +631,7 @@ For critical vulnerabilities requiring immediate attention:
|
|||||||
**General Security Questions:**
|
**General Security Questions:**
|
||||||
- **GitHub Discussions**: https://github.com/SuperClaude-Org/SuperClaude_Framework/discussions
|
- **GitHub Discussions**: https://github.com/SuperClaude-Org/SuperClaude_Framework/discussions
|
||||||
- **Community Forums**: Security-focused discussion threads
|
- **Community Forums**: Security-focused discussion threads
|
||||||
- **Documentation**: [Security Best Practices](Docs/Reference/quick-start-practices.md#security-practices)
|
- **Documentation**: [Security Best Practices](docs/Reference/quick-start-practices.md#security-practices)
|
||||||
- **Issue Tracker**: Non-sensitive security configuration questions
|
- **Issue Tracker**: Non-sensitive security configuration questions
|
||||||
|
|
||||||
**Technical Security Support:**
|
**Technical Security Support:**
|
||||||
@ -663,25 +663,25 @@ For organizations requiring dedicated security support:
|
|||||||
|
|
||||||
### Security-Related Documentation
|
### Security-Related Documentation
|
||||||
**Framework Security Documentation:**
|
**Framework Security Documentation:**
|
||||||
- [Quick Start Practices Guide](Docs/Reference/quick-start-practices.md) - Security-focused usage patterns
|
- [Quick Start Practices Guide](docs/Reference/quick-start-practices.md) - Security-focused usage patterns
|
||||||
- [Technical Architecture](Docs/Developer-Guide/technical-architecture.md) - Security design principles
|
- [Technical Architecture](docs/Developer-Guide/technical-architecture.md) - Security design principles
|
||||||
- [Contributing Code Guide](Docs/Developer-Guide/contributing-code.md) - Secure development practices
|
- [Contributing Code Guide](docs/Developer-Guide/contributing-code.md) - Secure development practices
|
||||||
- [Testing & Debugging Guide](Docs/Developer-Guide/testing-debugging.md) - Security testing procedures
|
- [Testing & Debugging Guide](docs/Developer-Guide/testing-debugging.md) - Security testing procedures
|
||||||
|
|
||||||
**MCP Server Security:**
|
**MCP Server Security:**
|
||||||
- [MCP Servers Guide](Docs/User-Guide/mcp-servers.md) - Server security configuration
|
- [MCP Servers Guide](docs/User-Guide/mcp-servers.md) - Server security configuration
|
||||||
- [Troubleshooting Guide](Docs/Reference/troubleshooting.md) - Security-related issue resolution
|
- [Troubleshooting Guide](docs/Reference/troubleshooting.md) - Security-related issue resolution
|
||||||
- MCP Server Documentation - Individual server security considerations
|
- MCP Server Documentation - Individual server security considerations
|
||||||
- Configuration Security - Secure MCP setup and credential management
|
- Configuration Security - Secure MCP setup and credential management
|
||||||
|
|
||||||
**Agent Security:**
|
**Agent Security:**
|
||||||
- [Agents Guide](Docs/User-Guide/agents.md) - Agent security boundaries and coordination
|
- [Agents Guide](docs/User-Guide/agents.md) - Agent security boundaries and coordination
|
||||||
- Agent Development - Security considerations for agent implementation
|
- Agent Development - Security considerations for agent implementation
|
||||||
- Behavioral Modes - Security implications of different operational modes
|
- Behavioral Modes - Security implications of different operational modes
|
||||||
- Command Security - Security aspects of command execution and validation
|
- Command Security - Security aspects of command execution and validation
|
||||||
|
|
||||||
**Session Management Security:**
|
**Session Management Security:**
|
||||||
- [Session Management Guide](Docs/User-Guide/session-management.md) - Secure session handling
|
- [Session Management Guide](docs/User-Guide/session-management.md) - Secure session handling
|
||||||
- Memory Security - Secure handling of persistent session data
|
- Memory Security - Secure handling of persistent session data
|
||||||
- Project Isolation - Security boundaries between different projects
|
- Project Isolation - Security boundaries between different projects
|
||||||
- Context Security - Secure context loading and validation
|
- Context Security - Secure context loading and validation
|
||||||
|
|||||||
@ -1,291 +0,0 @@
|
|||||||
---
|
|
||||||
name: pm
|
|
||||||
description: "Project Manager Agent - Default orchestration agent that coordinates all sub-agents and manages workflows seamlessly"
|
|
||||||
category: orchestration
|
|
||||||
complexity: meta
|
|
||||||
mcp-servers: [sequential, context7, magic, playwright, morphllm, serena, tavily, chrome-devtools]
|
|
||||||
personas: [pm-agent]
|
|
||||||
---
|
|
||||||
|
|
||||||
# /sc:pm - Project Manager Agent
|
|
||||||
|
|
||||||
> **Default Orchestration Mode**: PM Agent is the default entry point for all user interactions. It automatically delegates to appropriate specialist agents based on task analysis without requiring manual agent selection.
|
|
||||||
|
|
||||||
## Triggers
|
|
||||||
- **Auto-Activation**: All user requests default to PM Agent unless explicit sub-agent override
|
|
||||||
- Vague project requests: "作りたい", "実装したい", "どうすれば"
|
|
||||||
- Multi-domain tasks requiring cross-functional coordination
|
|
||||||
- Ambiguous requirements needing discovery before implementation
|
|
||||||
- Complex projects requiring systematic planning and execution
|
|
||||||
|
|
||||||
## Context Trigger Pattern
|
|
||||||
```
|
|
||||||
# Default (no command needed - PM Agent handles all interactions)
|
|
||||||
"Build authentication system for my app"
|
|
||||||
|
|
||||||
# Explicit PM Agent invocation (optional)
|
|
||||||
/sc:pm [request] [--strategy brainstorm|direct|wave] [--verbose]
|
|
||||||
|
|
||||||
# Override to specific sub-agent (optional)
|
|
||||||
/sc:implement "user profile" --agent backend
|
|
||||||
```
|
|
||||||
|
|
||||||
## Behavioral Flow
|
|
||||||
1. **Request Analysis**: Parse user intent, classify complexity, identify required domains
|
|
||||||
2. **Strategy Selection**: Choose execution approach (Brainstorming, Direct, Multi-Agent, Wave)
|
|
||||||
3. **Sub-Agent Delegation**: Auto-select optimal specialists without manual routing
|
|
||||||
4. **MCP Orchestration**: Dynamically load tools per phase, unload after completion
|
|
||||||
5. **Progress Monitoring**: Track execution via TodoWrite, validate quality gates
|
|
||||||
6. **Self-Improvement**: Document continuously (implementations, mistakes, patterns)
|
|
||||||
|
|
||||||
Key behaviors:
|
|
||||||
- **Seamless Orchestration**: Users interact only with PM Agent, sub-agents work transparently
|
|
||||||
- **Auto-Delegation**: Intelligent routing to domain specialists based on task analysis
|
|
||||||
- **Zero-Token Efficiency**: Dynamic MCP tool loading via Docker Gateway integration
|
|
||||||
- **Self-Documenting**: Automatic knowledge capture in project docs and CLAUDE.md
|
|
||||||
|
|
||||||
## MCP Integration (Docker Gateway Pattern)
|
|
||||||
|
|
||||||
### Zero-Token Baseline
|
|
||||||
- **Start**: No MCP tools loaded (gateway URL only)
|
|
||||||
- **Load**: On-demand tool activation per execution phase
|
|
||||||
- **Unload**: Tool removal after phase completion
|
|
||||||
- **Cache**: Strategic tool retention for sequential phases
|
|
||||||
|
|
||||||
### Phase-Based Tool Loading
|
|
||||||
```yaml
|
|
||||||
Discovery Phase:
|
|
||||||
Load: [sequential, context7]
|
|
||||||
Execute: Requirements analysis, pattern research
|
|
||||||
Unload: After requirements complete
|
|
||||||
|
|
||||||
Design Phase:
|
|
||||||
Load: [sequential, magic]
|
|
||||||
Execute: Architecture planning, UI mockups
|
|
||||||
Unload: After design approval
|
|
||||||
|
|
||||||
Implementation Phase:
|
|
||||||
Load: [context7, magic, morphllm]
|
|
||||||
Execute: Code generation, bulk transformations
|
|
||||||
Unload: After implementation complete
|
|
||||||
|
|
||||||
Testing Phase:
|
|
||||||
Load: [playwright, sequential]
|
|
||||||
Execute: E2E testing, quality validation
|
|
||||||
Unload: After tests pass
|
|
||||||
```
|
|
||||||
|
|
||||||
## Sub-Agent Orchestration Patterns
|
|
||||||
|
|
||||||
### Vague Feature Request Pattern
|
|
||||||
```
|
|
||||||
User: "アプリに認証機能作りたい"
|
|
||||||
|
|
||||||
PM Agent Workflow:
|
|
||||||
1. Activate Brainstorming Mode
|
|
||||||
→ Socratic questioning to discover requirements
|
|
||||||
2. Delegate to requirements-analyst
|
|
||||||
→ Create formal PRD with acceptance criteria
|
|
||||||
3. Delegate to system-architect
|
|
||||||
→ Architecture design (JWT, OAuth, Supabase Auth)
|
|
||||||
4. Delegate to security-engineer
|
|
||||||
→ Threat modeling, security patterns
|
|
||||||
5. Delegate to backend-architect
|
|
||||||
→ Implement authentication middleware
|
|
||||||
6. Delegate to quality-engineer
|
|
||||||
→ Security testing, integration tests
|
|
||||||
7. Delegate to technical-writer
|
|
||||||
→ Documentation, update CLAUDE.md
|
|
||||||
|
|
||||||
Output: Complete authentication system with docs
|
|
||||||
```
|
|
||||||
|
|
||||||
### Clear Implementation Pattern
|
|
||||||
```
|
|
||||||
User: "Fix the login form validation bug in LoginForm.tsx:45"
|
|
||||||
|
|
||||||
PM Agent Workflow:
|
|
||||||
1. Load: [context7] for validation patterns
|
|
||||||
2. Analyze: Read LoginForm.tsx, identify root cause
|
|
||||||
3. Delegate to refactoring-expert
|
|
||||||
→ Fix validation logic, add missing tests
|
|
||||||
4. Delegate to quality-engineer
|
|
||||||
→ Validate fix, run regression tests
|
|
||||||
5. Document: Update self-improvement-workflow.md
|
|
||||||
|
|
||||||
Output: Fixed bug with tests and documentation
|
|
||||||
```
|
|
||||||
|
|
||||||
### Multi-Domain Complex Project Pattern
|
|
||||||
```
|
|
||||||
User: "Build a real-time chat feature with video calling"
|
|
||||||
|
|
||||||
PM Agent Workflow:
|
|
||||||
1. Delegate to requirements-analyst
|
|
||||||
→ User stories, acceptance criteria
|
|
||||||
2. Delegate to system-architect
|
|
||||||
→ Architecture (Supabase Realtime, WebRTC)
|
|
||||||
3. Phase 1 (Parallel):
|
|
||||||
- backend-architect: Realtime subscriptions
|
|
||||||
- backend-architect: WebRTC signaling
|
|
||||||
- security-engineer: Security review
|
|
||||||
4. Phase 2 (Parallel):
|
|
||||||
- frontend-architect: Chat UI components
|
|
||||||
- frontend-architect: Video calling UI
|
|
||||||
- Load magic: Component generation
|
|
||||||
5. Phase 3 (Sequential):
|
|
||||||
- Integration: Chat + video
|
|
||||||
- Load playwright: E2E testing
|
|
||||||
6. Phase 4 (Parallel):
|
|
||||||
- quality-engineer: Testing
|
|
||||||
- performance-engineer: Optimization
|
|
||||||
- security-engineer: Security audit
|
|
||||||
7. Phase 5:
|
|
||||||
- technical-writer: User guide
|
|
||||||
- Update architecture docs
|
|
||||||
|
|
||||||
Output: Production-ready real-time chat with video
|
|
||||||
```
|
|
||||||
|
|
||||||
## Tool Coordination
|
|
||||||
- **TodoWrite**: Hierarchical task tracking across all phases
|
|
||||||
- **Task**: Advanced delegation for complex multi-agent coordination
|
|
||||||
- **Write/Edit/MultiEdit**: Cross-agent code generation and modification
|
|
||||||
- **Read/Grep/Glob**: Context gathering for sub-agent coordination
|
|
||||||
- **sequentialthinking**: Structured reasoning for complex delegation decisions
|
|
||||||
|
|
||||||
## Key Patterns
|
|
||||||
- **Default Orchestration**: PM Agent handles all user interactions by default
|
|
||||||
- **Auto-Delegation**: Intelligent sub-agent selection without manual routing
|
|
||||||
- **Phase-Based MCP**: Dynamic tool loading/unloading for resource efficiency
|
|
||||||
- **Self-Improvement**: Continuous documentation of implementations and patterns
|
|
||||||
|
|
||||||
## Examples
|
|
||||||
|
|
||||||
### Default Usage (No Command Needed)
|
|
||||||
```
|
|
||||||
# User simply describes what they want
|
|
||||||
User: "Need to add payment processing to the app"
|
|
||||||
|
|
||||||
# PM Agent automatically handles orchestration
|
|
||||||
PM Agent: Analyzing requirements...
|
|
||||||
→ Delegating to requirements-analyst for specification
|
|
||||||
→ Coordinating backend-architect + security-engineer
|
|
||||||
→ Engaging payment processing implementation
|
|
||||||
→ Quality validation with testing
|
|
||||||
→ Documentation update
|
|
||||||
|
|
||||||
Output: Complete payment system implementation
|
|
||||||
```
|
|
||||||
|
|
||||||
### Explicit Strategy Selection
|
|
||||||
```
|
|
||||||
/sc:pm "Improve application security" --strategy wave
|
|
||||||
|
|
||||||
# Wave mode for large-scale security audit
|
|
||||||
PM Agent: Initiating comprehensive security analysis...
|
|
||||||
→ Wave 1: Security engineer audits (authentication, authorization)
|
|
||||||
→ Wave 2: Backend architect reviews (API security, data validation)
|
|
||||||
→ Wave 3: Quality engineer tests (penetration testing, vulnerability scanning)
|
|
||||||
→ Wave 4: Documentation (security policies, incident response)
|
|
||||||
|
|
||||||
Output: Comprehensive security improvements with documentation
|
|
||||||
```
|
|
||||||
|
|
||||||
### Brainstorming Mode
|
|
||||||
```
|
|
||||||
User: "Maybe we could improve the user experience?"
|
|
||||||
|
|
||||||
PM Agent: Activating Brainstorming Mode...
|
|
||||||
🤔 Discovery Questions:
|
|
||||||
- What specific UX challenges are users facing?
|
|
||||||
- Which workflows are most problematic?
|
|
||||||
- Have you gathered user feedback or analytics?
|
|
||||||
- What are your improvement priorities?
|
|
||||||
|
|
||||||
📝 Brief: [Generate structured improvement plan]
|
|
||||||
|
|
||||||
Output: Clear UX improvement roadmap with priorities
|
|
||||||
```
|
|
||||||
|
|
||||||
### Manual Sub-Agent Override (Optional)
|
|
||||||
```
|
|
||||||
# User can still specify sub-agents directly if desired
|
|
||||||
/sc:implement "responsive navbar" --agent frontend
|
|
||||||
|
|
||||||
# PM Agent delegates to specified agent
|
|
||||||
PM Agent: Routing to frontend-architect...
|
|
||||||
→ Frontend specialist handles implementation
|
|
||||||
→ PM Agent monitors progress and quality gates
|
|
||||||
|
|
||||||
Output: Frontend-optimized implementation
|
|
||||||
```
|
|
||||||
|
|
||||||
## Self-Improvement Integration
|
|
||||||
|
|
||||||
### Implementation Documentation
|
|
||||||
```yaml
|
|
||||||
After each successful implementation:
|
|
||||||
- Update docs/ with new patterns discovered
|
|
||||||
- Document architecture decisions in ADR format
|
|
||||||
- Add working examples to project documentation
|
|
||||||
- Update CLAUDE.md with new best practices
|
|
||||||
```
|
|
||||||
|
|
||||||
### Mistake Recording
|
|
||||||
```yaml
|
|
||||||
When errors occur:
|
|
||||||
- Capture error in self-improvement-workflow.md
|
|
||||||
- Document root cause analysis
|
|
||||||
- Create prevention checklist
|
|
||||||
- Update anti-patterns documentation
|
|
||||||
```
|
|
||||||
|
|
||||||
### Monthly Maintenance
|
|
||||||
```yaml
|
|
||||||
Regular documentation health:
|
|
||||||
- Remove outdated patterns and deprecated approaches
|
|
||||||
- Merge duplicate documentation
|
|
||||||
- Update version numbers and dependencies
|
|
||||||
- Prune noise, keep essential knowledge
|
|
||||||
```
|
|
||||||
|
|
||||||
## Boundaries
|
|
||||||
|
|
||||||
**Will:**
|
|
||||||
- Orchestrate all user interactions and automatically delegate to appropriate specialists
|
|
||||||
- Provide seamless experience without requiring manual agent selection
|
|
||||||
- Dynamically load/unload MCP tools for resource efficiency
|
|
||||||
- Continuously document implementations, mistakes, and patterns
|
|
||||||
- Transparently report delegation decisions and progress
|
|
||||||
|
|
||||||
**Will Not:**
|
|
||||||
- Bypass quality gates or compromise standards for speed
|
|
||||||
- Make unilateral technical decisions without appropriate sub-agent expertise
|
|
||||||
- Execute without proper planning for complex multi-domain projects
|
|
||||||
- Skip documentation or self-improvement recording steps
|
|
||||||
|
|
||||||
**User Control:**
|
|
||||||
- Default: PM Agent auto-delegates (seamless)
|
|
||||||
- Override: Explicit `--agent [name]` for direct sub-agent access
|
|
||||||
- Both options available simultaneously (no user downside)
|
|
||||||
|
|
||||||
## Performance Optimization
|
|
||||||
|
|
||||||
### Resource Efficiency
|
|
||||||
- **Zero-Token Baseline**: Start with no MCP tools (gateway only)
|
|
||||||
- **Dynamic Loading**: Load tools only when needed per phase
|
|
||||||
- **Strategic Unloading**: Remove tools after phase completion
|
|
||||||
- **Parallel Execution**: Concurrent sub-agent delegation when independent
|
|
||||||
|
|
||||||
### Quality Assurance
|
|
||||||
- **Domain Expertise**: Route to specialized agents for quality
|
|
||||||
- **Cross-Validation**: Multiple agent perspectives for complex decisions
|
|
||||||
- **Quality Gates**: Systematic validation at phase transitions
|
|
||||||
- **User Feedback**: Incorporate user guidance throughout execution
|
|
||||||
|
|
||||||
### Continuous Learning
|
|
||||||
- **Pattern Recognition**: Identify recurring successful patterns
|
|
||||||
- **Mistake Prevention**: Document errors with prevention checklist
|
|
||||||
- **Documentation Pruning**: Monthly cleanup to remove noise
|
|
||||||
- **Knowledge Synthesis**: Codify learnings in CLAUDE.md and docs/
|
|
||||||
@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
const { spawnSync } = require("child_process");
|
const { spawnSync } = require("child_process");
|
||||||
const { detectPython, detectPip } = require("./checkEnv");
|
const { detectPython, detectPip } = require("./check_env");
|
||||||
const { checkAndNotify } = require("./checkUpdate");
|
const { checkAndNotify } = require("./check_update");
|
||||||
|
|
||||||
let pythonCmd = detectPython();
|
let pythonCmd = detectPython();
|
||||||
if (!pythonCmd) {
|
if (!pythonCmd) {
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
const { run, detectPython, detectPip, detectPipx, isSuperClaudeInstalled, isSuperClaudeInstalledPipx, checkPythonEnvironment } = require("./checkEnv");
|
const { run, detectPython, detectPip, detectPipx, isSuperClaudeInstalled, isSuperClaudeInstalledPipx, checkPythonEnvironment } = require("./check_env");
|
||||||
|
|
||||||
console.log("🔍 Checking environment...");
|
console.log("🔍 Checking environment...");
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
const { run, detectPip, detectPipx, isSuperClaudeInstalledPipx, checkPythonEnvironment } = require("./checkEnv");
|
const { run, detectPip, detectPipx, isSuperClaudeInstalledPipx, checkPythonEnvironment } = require("./check_env");
|
||||||
|
|
||||||
console.log("🔄 Checking for SuperClaude updates...");
|
console.log("🔄 Checking for SuperClaude updates...");
|
||||||
|
|
||||||
|
|||||||
@ -57,14 +57,14 @@ SuperClaude is a **Context-Oriented Configuration Framework** - not executing so
|
|||||||
|
|
||||||
```
|
```
|
||||||
SuperClaude_Framework/
|
SuperClaude_Framework/
|
||||||
├── SuperClaude/ # Framework components (the source of truth)
|
├── superclaude/ # Framework components (the source of truth)
|
||||||
│ ├── Core/ # PRINCIPLES.md, RULES.md, FLAGS.md
|
│ ├── Core/ # PRINCIPLES.md, RULES.md, FLAGS.md
|
||||||
│ ├── Agents/ # 15 specialized domain experts
|
│ ├── Agents/ # 15 specialized domain experts
|
||||||
│ ├── Commands/ # 21 context trigger patterns (/sc: behavioral instructions)
|
│ ├── Commands/ # 21 context trigger patterns (/sc: behavioral instructions)
|
||||||
│ ├── Modes/ # 6 behavioral modification patterns
|
│ ├── Modes/ # 6 behavioral modification patterns
|
||||||
│ └── MCP/ # 6 MCP server configurations
|
│ └── MCP/ # 6 MCP server configurations
|
||||||
├── setup/ # Python installation system
|
├── setup/ # Python installation system
|
||||||
├── Docs/ # Documentation (what you're reading)
|
├── docs/ # Documentation (what you're reading)
|
||||||
└── tests/ # File validation scripts
|
└── tests/ # File validation scripts
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -82,7 +82,7 @@ User Input → Claude Code → Reads SuperClaude Context → Modified Behavior
|
|||||||
```
|
```
|
||||||
|
|
||||||
1. User types `/sc:implement "auth system"` **in Claude Code conversation** (not terminal)
|
1. User types `/sc:implement "auth system"` **in Claude Code conversation** (not terminal)
|
||||||
2. Claude Code reads `SuperClaude/Commands/implement.md`
|
2. Claude Code reads `superclaude/Commands/implement.md`
|
||||||
3. Command activates security-engineer agent context
|
3. Command activates security-engineer agent context
|
||||||
4. Context7 MCP provides authentication patterns
|
4. Context7 MCP provides authentication patterns
|
||||||
5. Claude generates complete, secure implementation
|
5. Claude generates complete, secure implementation
|
||||||
@ -208,7 +208,7 @@ Brief description of context file changes
|
|||||||
|
|
||||||
**Agent Development Process:**
|
**Agent Development Process:**
|
||||||
1. Identify domain expertise gap
|
1. Identify domain expertise gap
|
||||||
2. Create agent file in `SuperClaude/Agents/`
|
2. Create agent file in `superclaude/Agents/`
|
||||||
3. Define triggers, behaviors, and boundaries
|
3. Define triggers, behaviors, and boundaries
|
||||||
4. Test with various Claude Code scenarios
|
4. Test with various Claude Code scenarios
|
||||||
5. Document usage patterns and examples
|
5. Document usage patterns and examples
|
||||||
529
docs/Development/ARCHITECTURE.md
Normal file
529
docs/Development/ARCHITECTURE.md
Normal file
@ -0,0 +1,529 @@
|
|||||||
|
# SuperClaude Architecture
|
||||||
|
|
||||||
|
**Last Updated**: 2025-10-14
|
||||||
|
**Version**: 4.1.5
|
||||||
|
|
||||||
|
## 📋 Table of Contents
|
||||||
|
|
||||||
|
1. [System Overview](#system-overview)
|
||||||
|
2. [Core Architecture](#core-architecture)
|
||||||
|
3. [PM Agent Mode: The Meta-Layer](#pm-agent-mode-the-meta-layer)
|
||||||
|
4. [Component Relationships](#component-relationships)
|
||||||
|
5. [Serena MCP Integration](#serena-mcp-integration)
|
||||||
|
6. [PDCA Engine](#pdca-engine)
|
||||||
|
7. [Data Flow](#data-flow)
|
||||||
|
8. [Extension Points](#extension-points)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## System Overview
|
||||||
|
|
||||||
|
### What is SuperClaude?
|
||||||
|
|
||||||
|
SuperClaude is a **Context-Oriented Configuration Framework** that transforms Claude Code into a structured development platform. It is NOT standalone software with running processes - it is a collection of `.md` instruction files that Claude Code reads to adopt specialized behaviors.
|
||||||
|
|
||||||
|
### Key Components
|
||||||
|
|
||||||
|
```
|
||||||
|
SuperClaude Framework
|
||||||
|
├── Commands (26) → Workflow patterns
|
||||||
|
├── Agents (16) → Domain expertise
|
||||||
|
├── Modes (7) → Behavioral modifiers
|
||||||
|
├── MCP Servers (8) → External tool integrations
|
||||||
|
└── PM Agent Mode → Meta-layer orchestration (Always-Active)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Version Information
|
||||||
|
|
||||||
|
- **Current Version**: 4.1.5
|
||||||
|
- **Commands**: 26 slash commands (`/sc:*`)
|
||||||
|
- **Agents**: 16 specialized domain experts
|
||||||
|
- **Modes**: 7 behavioral modes
|
||||||
|
- **MCP Servers**: 8 integrations (Context7, Sequential, Magic, Playwright, Morphllm, Serena, Tavily, Chrome DevTools)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Core Architecture
|
||||||
|
|
||||||
|
### Context-Oriented Configuration
|
||||||
|
|
||||||
|
SuperClaude's architecture is built on a simple principle: **behavioral modification through structured context files**.
|
||||||
|
|
||||||
|
```
|
||||||
|
User Input
|
||||||
|
↓
|
||||||
|
Context Loading (CLAUDE.md imports)
|
||||||
|
↓
|
||||||
|
Command Detection (/sc:* pattern)
|
||||||
|
↓
|
||||||
|
Agent Activation (manual or auto)
|
||||||
|
↓
|
||||||
|
Mode Application (flags or triggers)
|
||||||
|
↓
|
||||||
|
MCP Tool Coordination
|
||||||
|
↓
|
||||||
|
Output Generation
|
||||||
|
```
|
||||||
|
|
||||||
|
### Directory Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
~/.claude/
|
||||||
|
├── CLAUDE.md # Main context with @imports
|
||||||
|
├── FLAGS.md # Flag definitions
|
||||||
|
├── RULES.md # Core behavioral rules
|
||||||
|
├── PRINCIPLES.md # Guiding principles
|
||||||
|
├── MODE_*.md # 7 behavioral modes
|
||||||
|
├── MCP_*.md # 8 MCP server integrations
|
||||||
|
├── agents/ # 16 specialized agents
|
||||||
|
│ ├── pm-agent.md # 🆕 Meta-layer orchestrator
|
||||||
|
│ ├── backend-architect.md
|
||||||
|
│ ├── frontend-architect.md
|
||||||
|
│ ├── security-engineer.md
|
||||||
|
│ └── ... (13 more)
|
||||||
|
└── commands/sc/ # 26 workflow commands
|
||||||
|
├── pm.md # 🆕 PM Agent command
|
||||||
|
├── implement.md
|
||||||
|
├── analyze.md
|
||||||
|
└── ... (23 more)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## PM Agent Mode: The Meta-Layer
|
||||||
|
|
||||||
|
### Position in Architecture
|
||||||
|
|
||||||
|
PM Agent operates as a **meta-layer** above all other components:
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────┐
|
||||||
|
│ PM Agent Mode (Meta-Layer) │
|
||||||
|
│ • Always Active (Session Start) │
|
||||||
|
│ • Context Preservation │
|
||||||
|
│ • PDCA Self-Evaluation │
|
||||||
|
│ • Knowledge Management │
|
||||||
|
└─────────────────────────────────────────────┘
|
||||||
|
↓
|
||||||
|
┌─────────────────────────────────────────────┐
|
||||||
|
│ Specialist Agents (16) │
|
||||||
|
│ backend-architect, security-engineer, etc. │
|
||||||
|
└─────────────────────────────────────────────┘
|
||||||
|
↓
|
||||||
|
┌─────────────────────────────────────────────┐
|
||||||
|
│ Commands & Modes │
|
||||||
|
│ /sc:implement, /sc:analyze, etc. │
|
||||||
|
└─────────────────────────────────────────────┘
|
||||||
|
↓
|
||||||
|
┌─────────────────────────────────────────────┐
|
||||||
|
│ MCP Tool Layer │
|
||||||
|
│ Context7, Sequential, Magic, etc. │
|
||||||
|
└─────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
### PM Agent Responsibilities
|
||||||
|
|
||||||
|
1. **Session Lifecycle Management**
|
||||||
|
- Auto-activation at session start
|
||||||
|
- Context restoration from Serena MCP memory
|
||||||
|
- User report generation (前回/進捗/今回/課題)
|
||||||
|
|
||||||
|
2. **PDCA Cycle Execution**
|
||||||
|
- Plan: Hypothesis generation
|
||||||
|
- Do: Experimentation with checkpoints
|
||||||
|
- Check: Self-evaluation
|
||||||
|
- Act: Knowledge extraction
|
||||||
|
|
||||||
|
3. **Documentation Strategy**
|
||||||
|
- Temporary documentation (`docs/temp/`)
|
||||||
|
- Formal patterns (`docs/patterns/`)
|
||||||
|
- Mistake records (`docs/mistakes/`)
|
||||||
|
- Knowledge evolution to CLAUDE.md
|
||||||
|
|
||||||
|
4. **Sub-Agent Orchestration**
|
||||||
|
- Auto-delegation to specialists
|
||||||
|
- Context coordination
|
||||||
|
- Quality gate validation
|
||||||
|
- Progress monitoring
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Component Relationships
|
||||||
|
|
||||||
|
### Commands → Agents → Modes → MCP
|
||||||
|
|
||||||
|
```
|
||||||
|
User: "/sc:implement authentication" --security
|
||||||
|
↓
|
||||||
|
[Command Layer]
|
||||||
|
commands/sc/implement.md
|
||||||
|
↓
|
||||||
|
[Agent Auto-Activation]
|
||||||
|
agents/security-engineer.md
|
||||||
|
agents/backend-architect.md
|
||||||
|
↓
|
||||||
|
[Mode Application]
|
||||||
|
MODE_Task_Management.md (TodoWrite)
|
||||||
|
↓
|
||||||
|
[MCP Tool Coordination]
|
||||||
|
Context7 (auth patterns)
|
||||||
|
Sequential (complex analysis)
|
||||||
|
↓
|
||||||
|
[PM Agent Meta-Layer]
|
||||||
|
Document learnings → docs/patterns/
|
||||||
|
```
|
||||||
|
|
||||||
|
### Activation Flow
|
||||||
|
|
||||||
|
1. **Explicit Command**: User types `/sc:implement`
|
||||||
|
- Loads `commands/sc/implement.md`
|
||||||
|
- Activates related agents (backend-architect, etc.)
|
||||||
|
|
||||||
|
2. **Agent Activation**: `@agent-security` or auto-detected
|
||||||
|
- Loads agent expertise context
|
||||||
|
- May activate related MCP servers
|
||||||
|
|
||||||
|
3. **Mode Application**: `--brainstorm` flag or keywords
|
||||||
|
- Modifies interaction style
|
||||||
|
- Enables specific behaviors
|
||||||
|
|
||||||
|
4. **PM Agent Meta-Layer**: Always active
|
||||||
|
- Monitors all interactions
|
||||||
|
- Documents learnings
|
||||||
|
- Preserves context across sessions
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Serena MCP Integration
|
||||||
|
|
||||||
|
### Memory Operations
|
||||||
|
|
||||||
|
Serena MCP provides semantic code analysis and session persistence through memory operations:
|
||||||
|
|
||||||
|
```
|
||||||
|
Session Start:
|
||||||
|
PM Agent → list_memories()
|
||||||
|
PM Agent → read_memory("pm_context")
|
||||||
|
PM Agent → read_memory("last_session")
|
||||||
|
PM Agent → read_memory("next_actions")
|
||||||
|
PM Agent → Report to User
|
||||||
|
|
||||||
|
During Work (every 30min):
|
||||||
|
PM Agent → write_memory("checkpoint", progress)
|
||||||
|
PM Agent → write_memory("decision", rationale)
|
||||||
|
|
||||||
|
Session End:
|
||||||
|
PM Agent → write_memory("last_session", summary)
|
||||||
|
PM Agent → write_memory("next_actions", todos)
|
||||||
|
PM Agent → write_memory("pm_context", complete_state)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Memory Structure
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"pm_context": {
|
||||||
|
"project": "SuperClaude_Framework",
|
||||||
|
"current_phase": "Phase 1: Documentation",
|
||||||
|
"active_tasks": ["ARCHITECTURE.md", "ROADMAP.md"],
|
||||||
|
"architecture": "Context-Oriented Configuration",
|
||||||
|
"patterns": ["PDCA Cycle", "Session Lifecycle"]
|
||||||
|
},
|
||||||
|
"last_session": {
|
||||||
|
"date": "2025-10-14",
|
||||||
|
"accomplished": ["PM Agent mode design", "Salvaged implementations"],
|
||||||
|
"issues": ["Serena MCP not configured"],
|
||||||
|
"learned": ["Session Lifecycle pattern", "PDCA automation"]
|
||||||
|
},
|
||||||
|
"next_actions": [
|
||||||
|
"Create docs/Development/ structure",
|
||||||
|
"Write ARCHITECTURE.md",
|
||||||
|
"Configure Serena MCP server"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## PDCA Engine
|
||||||
|
|
||||||
|
### Continuous Improvement Cycle
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────┐
|
||||||
|
│ Plan │ → write_memory("plan", goal)
|
||||||
|
│ (仮説) │ → docs/temp/hypothesis-YYYY-MM-DD.md
|
||||||
|
└──────┬──────┘
|
||||||
|
↓
|
||||||
|
┌─────────────┐
|
||||||
|
│ Do │ → TodoWrite tracking
|
||||||
|
│ (実験) │ → write_memory("checkpoint", progress)
|
||||||
|
└──────┬──────┘ → docs/temp/experiment-YYYY-MM-DD.md
|
||||||
|
↓
|
||||||
|
┌─────────────┐
|
||||||
|
│ Check │ → think_about_task_adherence()
|
||||||
|
│ (評価) │ → think_about_whether_you_are_done()
|
||||||
|
└──────┬──────┘ → docs/temp/lessons-YYYY-MM-DD.md
|
||||||
|
↓
|
||||||
|
┌─────────────┐
|
||||||
|
│ Act │ → Success: docs/patterns/[name].md
|
||||||
|
│ (改善) │ → Failure: docs/mistakes/mistake-*.md
|
||||||
|
└──────┬──────┘ → Update CLAUDE.md
|
||||||
|
↓
|
||||||
|
[Repeat]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Documentation Evolution
|
||||||
|
|
||||||
|
```
|
||||||
|
Trial-and-Error (docs/temp/)
|
||||||
|
↓
|
||||||
|
Success → Formal Pattern (docs/patterns/)
|
||||||
|
↓
|
||||||
|
Accumulate Knowledge
|
||||||
|
↓
|
||||||
|
Extract Best Practices → CLAUDE.md (Global Rules)
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
Mistake Detection (docs/temp/)
|
||||||
|
↓
|
||||||
|
Root Cause Analysis → docs/mistakes/
|
||||||
|
↓
|
||||||
|
Prevention Checklist
|
||||||
|
↓
|
||||||
|
Update Anti-Patterns → CLAUDE.md
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Data Flow
|
||||||
|
|
||||||
|
### Session Lifecycle Data Flow
|
||||||
|
|
||||||
|
```
|
||||||
|
Session Start:
|
||||||
|
┌──────────────┐
|
||||||
|
│ Claude Code │
|
||||||
|
│ Startup │
|
||||||
|
└──────┬───────┘
|
||||||
|
↓
|
||||||
|
┌──────────────┐
|
||||||
|
│ PM Agent │ list_memories()
|
||||||
|
│ Activation │ read_memory("pm_context")
|
||||||
|
└──────┬───────┘
|
||||||
|
↓
|
||||||
|
┌──────────────┐
|
||||||
|
│ Serena │ Return: pm_context,
|
||||||
|
│ MCP │ last_session,
|
||||||
|
└──────┬───────┘ next_actions
|
||||||
|
↓
|
||||||
|
┌──────────────┐
|
||||||
|
│ Context │ Restore project state
|
||||||
|
│ Restoration │ Generate user report
|
||||||
|
└──────┬───────┘
|
||||||
|
↓
|
||||||
|
┌──────────────┐
|
||||||
|
│ User │ 前回: [summary]
|
||||||
|
│ Report │ 進捗: [status]
|
||||||
|
└──────────────┘ 今回: [actions]
|
||||||
|
課題: [blockers]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Implementation Data Flow
|
||||||
|
|
||||||
|
```
|
||||||
|
User Request → PM Agent Analyzes
|
||||||
|
↓
|
||||||
|
PM Agent → Delegate to Specialist Agents
|
||||||
|
↓
|
||||||
|
Specialist Agents → Execute Implementation
|
||||||
|
↓
|
||||||
|
Implementation Complete → PM Agent Documents
|
||||||
|
↓
|
||||||
|
PM Agent → write_memory("checkpoint", progress)
|
||||||
|
PM Agent → docs/temp/experiment-*.md
|
||||||
|
↓
|
||||||
|
Success → docs/patterns/ | Failure → docs/mistakes/
|
||||||
|
↓
|
||||||
|
Update CLAUDE.md (if global pattern)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Extension Points
|
||||||
|
|
||||||
|
### Adding New Components
|
||||||
|
|
||||||
|
#### 1. New Command
|
||||||
|
```markdown
|
||||||
|
File: ~/.claude/commands/sc/new-command.md
|
||||||
|
Structure:
|
||||||
|
- Metadata (name, category, complexity)
|
||||||
|
- Triggers (when to use)
|
||||||
|
- Workflow Pattern (step-by-step)
|
||||||
|
- Examples
|
||||||
|
|
||||||
|
Integration:
|
||||||
|
- Auto-loads when user types /sc:new-command
|
||||||
|
- Can activate related agents
|
||||||
|
- PM Agent automatically documents usage patterns
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2. New Agent
|
||||||
|
```markdown
|
||||||
|
File: ~/.claude/agents/new-specialist.md
|
||||||
|
Structure:
|
||||||
|
- Metadata (name, category)
|
||||||
|
- Triggers (keywords, file types)
|
||||||
|
- Behavioral Mindset
|
||||||
|
- Focus Areas
|
||||||
|
|
||||||
|
Integration:
|
||||||
|
- Auto-activates on trigger keywords
|
||||||
|
- Manual activation: @agent-new-specialist
|
||||||
|
- PM Agent orchestrates with other agents
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3. New Mode
|
||||||
|
```markdown
|
||||||
|
File: ~/.claude/MODE_NewMode.md
|
||||||
|
Structure:
|
||||||
|
- Activation Triggers (flags, keywords)
|
||||||
|
- Behavioral Modifications
|
||||||
|
- Interaction Patterns
|
||||||
|
|
||||||
|
Integration:
|
||||||
|
- Flag: --new-mode
|
||||||
|
- Auto-activation on complexity threshold
|
||||||
|
- Modifies all agent behaviors
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 4. New MCP Server
|
||||||
|
```json
|
||||||
|
File: ~/.claude/.claude.json
|
||||||
|
{
|
||||||
|
"mcpServers": {
|
||||||
|
"new-server": {
|
||||||
|
"command": "npx",
|
||||||
|
"args": ["-y", "new-server-mcp@latest"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
File: ~/.claude/MCP_NewServer.md
|
||||||
|
Structure:
|
||||||
|
- Purpose (what this server provides)
|
||||||
|
- Triggers (when to use)
|
||||||
|
- Integration (how to coordinate with other tools)
|
||||||
|
```
|
||||||
|
|
||||||
|
### PM Agent Integration for Extensions
|
||||||
|
|
||||||
|
All new components automatically integrate with PM Agent meta-layer:
|
||||||
|
|
||||||
|
1. **Session Lifecycle**: New components' usage tracked across sessions
|
||||||
|
2. **PDCA Cycle**: Patterns extracted from new component usage
|
||||||
|
3. **Documentation**: Learnings automatically documented
|
||||||
|
4. **Orchestration**: PM Agent coordinates new components with existing ones
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Architecture Principles
|
||||||
|
|
||||||
|
### 1. Simplicity First
|
||||||
|
- No executing code, only context files
|
||||||
|
- No performance systems, only instructional patterns
|
||||||
|
- No detection engines, Claude Code does pattern matching
|
||||||
|
|
||||||
|
### 2. Context-Oriented
|
||||||
|
- Behavior modification through structured context
|
||||||
|
- Import system for modular context loading
|
||||||
|
- Clear trigger patterns for activation
|
||||||
|
|
||||||
|
### 3. Meta-Layer Design
|
||||||
|
- PM Agent orchestrates without interfering
|
||||||
|
- Specialist agents work transparently
|
||||||
|
- Users interact with cohesive system
|
||||||
|
|
||||||
|
### 4. Knowledge Accumulation
|
||||||
|
- Every experience generates learnings
|
||||||
|
- Mistakes documented with prevention
|
||||||
|
- Patterns extracted to reusable knowledge
|
||||||
|
|
||||||
|
### 5. Session Continuity
|
||||||
|
- Context preserved across sessions
|
||||||
|
- No re-explanation needed
|
||||||
|
- Seamless resumption from last checkpoint
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Technical Considerations
|
||||||
|
|
||||||
|
### Performance
|
||||||
|
- Framework is pure context (no runtime overhead)
|
||||||
|
- Token efficiency through dynamic MCP loading
|
||||||
|
- Strategic context caching for related phases
|
||||||
|
|
||||||
|
### Scalability
|
||||||
|
- Unlimited commands/agents/modes through context files
|
||||||
|
- Modular architecture supports independent development
|
||||||
|
- PM Agent meta-layer handles coordination complexity
|
||||||
|
|
||||||
|
### Maintainability
|
||||||
|
- Clear separation of concerns (Commands/Agents/Modes)
|
||||||
|
- Self-documenting through PDCA cycle
|
||||||
|
- Living documentation evolves with usage
|
||||||
|
|
||||||
|
### Extensibility
|
||||||
|
- Drop-in new contexts without code changes
|
||||||
|
- MCP servers add capabilities externally
|
||||||
|
- PM Agent auto-integrates new components
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Future Architecture
|
||||||
|
|
||||||
|
### Planned Enhancements
|
||||||
|
|
||||||
|
1. **Auto-Activation System**
|
||||||
|
- PM Agent activates automatically at session start
|
||||||
|
- No manual invocation needed
|
||||||
|
|
||||||
|
2. **Enhanced Memory Operations**
|
||||||
|
- Full Serena MCP integration
|
||||||
|
- Cross-project knowledge sharing
|
||||||
|
- Pattern recognition across sessions
|
||||||
|
|
||||||
|
3. **PDCA Automation**
|
||||||
|
- Automatic documentation lifecycle
|
||||||
|
- AI-driven pattern extraction
|
||||||
|
- Self-improving knowledge base
|
||||||
|
|
||||||
|
4. **Multi-Project Orchestration**
|
||||||
|
- PM Agent coordinates across projects
|
||||||
|
- Shared learnings and patterns
|
||||||
|
- Unified knowledge management
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
SuperClaude's architecture is elegantly simple: **structured context files** that Claude Code reads to adopt sophisticated behaviors. The addition of PM Agent mode as a meta-layer transforms this from a collection of tools into a **continuously learning, self-improving development platform**.
|
||||||
|
|
||||||
|
**Key Architectural Innovation**: PM Agent meta-layer provides:
|
||||||
|
- Always-active foundation layer
|
||||||
|
- Context preservation across sessions
|
||||||
|
- PDCA self-evaluation and learning
|
||||||
|
- Systematic knowledge management
|
||||||
|
- Seamless orchestration of specialist agents
|
||||||
|
|
||||||
|
This architecture enables SuperClaude to function as a **最高司令官 (Supreme Commander)** that orchestrates all development activities while continuously learning and improving from every interaction.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Last Verified**: 2025-10-14
|
||||||
|
**Next Review**: 2025-10-21 (1 week)
|
||||||
|
**Version**: 4.1.5
|
||||||
172
docs/Development/PROJECT_STATUS.md
Normal file
172
docs/Development/PROJECT_STATUS.md
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
# SuperClaude Project Status
|
||||||
|
|
||||||
|
**Last Updated**: 2025-10-14
|
||||||
|
**Version**: 4.1.5
|
||||||
|
**Phase**: Phase 1 - Documentation Structure
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📊 Quick Overview
|
||||||
|
|
||||||
|
| Metric | Status | Progress |
|
||||||
|
|--------|--------|----------|
|
||||||
|
| **Overall Completion** | 🔄 In Progress | 35% |
|
||||||
|
| **Phase 1 (Documentation)** | 🔄 In Progress | 66% |
|
||||||
|
| **Phase 2 (PM Agent)** | 🔄 In Progress | 30% |
|
||||||
|
| **Phase 3 (Serena MCP)** | ⏳ Not Started | 0% |
|
||||||
|
| **Phase 4 (Doc Strategy)** | ⏳ Not Started | 0% |
|
||||||
|
| **Phase 5 (Auto-Activation)** | 🔬 Research | 0% |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 Current Sprint
|
||||||
|
|
||||||
|
**Sprint**: Phase 1 - Documentation Structure
|
||||||
|
**Timeline**: 2025-10-14 ~ 2025-10-20
|
||||||
|
**Status**: 🔄 66% Complete
|
||||||
|
|
||||||
|
### This Week's Focus
|
||||||
|
- [ ] Complete Phase 1 documentation (TASKS.md, PROJECT_STATUS.md, pm-agent-integration.md)
|
||||||
|
- [ ] Commit Phase 1 changes
|
||||||
|
- [ ] Commit PM Agent Mode improvements
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ✅ Completed Features
|
||||||
|
|
||||||
|
### Core Framework (v4.1.5)
|
||||||
|
- ✅ **26 Commands**: `/sc:*` namespace
|
||||||
|
- ✅ **16 Agents**: Specialized domain experts
|
||||||
|
- ✅ **7 Modes**: Behavioral modifiers
|
||||||
|
- ✅ **8 MCP Servers**: External tool integrations
|
||||||
|
|
||||||
|
### PM Agent Mode (Design Phase)
|
||||||
|
- ✅ Session Lifecycle design
|
||||||
|
- ✅ PDCA Cycle design
|
||||||
|
- ✅ Documentation Strategy design
|
||||||
|
- ✅ Commands/pm.md updated
|
||||||
|
- ✅ Agents/pm-agent.md updated
|
||||||
|
|
||||||
|
### Documentation
|
||||||
|
- ✅ docs/Development/ARCHITECTURE.md
|
||||||
|
- ✅ docs/Development/ROADMAP.md
|
||||||
|
- ✅ docs/Development/TASKS.md
|
||||||
|
- ✅ docs/Development/PROJECT_STATUS.md
|
||||||
|
- ✅ docs/pm-agent-implementation-status.md
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔄 In Progress
|
||||||
|
|
||||||
|
### Phase 1: Documentation Structure (66%)
|
||||||
|
- [x] ARCHITECTURE.md
|
||||||
|
- [x] ROADMAP.md
|
||||||
|
- [x] TASKS.md
|
||||||
|
- [x] PROJECT_STATUS.md
|
||||||
|
- [ ] pm-agent-integration.md
|
||||||
|
|
||||||
|
### Phase 2: PM Agent Mode (30%)
|
||||||
|
- [ ] superclaude/Core/session_lifecycle.py
|
||||||
|
- [ ] superclaude/Core/pdca_engine.py
|
||||||
|
- [ ] superclaude/Core/memory_ops.py
|
||||||
|
- [ ] Unit tests
|
||||||
|
- [ ] Integration tests
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ⏳ Pending
|
||||||
|
|
||||||
|
### Phase 3: Serena MCP Integration (0%)
|
||||||
|
- Serena MCP server configuration
|
||||||
|
- Memory operations implementation
|
||||||
|
- Think operations implementation
|
||||||
|
- Cross-session persistence testing
|
||||||
|
|
||||||
|
### Phase 4: Documentation Strategy (0%)
|
||||||
|
- Directory templates creation
|
||||||
|
- Lifecycle automation
|
||||||
|
- Migration scripts
|
||||||
|
- Knowledge management
|
||||||
|
|
||||||
|
### Phase 5: Auto-Activation (0%)
|
||||||
|
- Claude Code initialization hooks research
|
||||||
|
- Auto-activation implementation
|
||||||
|
- Context restoration
|
||||||
|
- Performance optimization
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🚫 Blockers
|
||||||
|
|
||||||
|
### Critical
|
||||||
|
- **Serena MCP Not Configured**: Blocks Phase 3 (Memory Operations)
|
||||||
|
- **Auto-Activation Hooks Unknown**: Blocks Phase 5 (Research needed)
|
||||||
|
|
||||||
|
### Non-Critical
|
||||||
|
- Documentation directory structure (in progress - Phase 1)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📈 Metrics Dashboard
|
||||||
|
|
||||||
|
### Development Velocity
|
||||||
|
- **Phase 1**: 6 days estimated, on track for 7 days completion
|
||||||
|
- **Phase 2**: 14 days estimated, not yet started full implementation
|
||||||
|
- **Overall**: 35% complete, on schedule for 8-week timeline
|
||||||
|
|
||||||
|
### Code Quality
|
||||||
|
- **Test Coverage**: 0% (implementation not started)
|
||||||
|
- **Documentation Coverage**: 40% (4/10 major docs complete)
|
||||||
|
|
||||||
|
### Component Status
|
||||||
|
- **Commands**: ✅ 26/26 functional
|
||||||
|
- **Agents**: ✅ 16/16 functional, 1 (PM Agent) enhanced
|
||||||
|
- **Modes**: ✅ 7/7 functional
|
||||||
|
- **MCP Servers**: ⚠️ 7/8 functional (Serena pending)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 Upcoming Milestones
|
||||||
|
|
||||||
|
### Week 1 (Current)
|
||||||
|
- ✅ Complete Phase 1 documentation
|
||||||
|
- ✅ Commit changes to repository
|
||||||
|
|
||||||
|
### Week 2-3
|
||||||
|
- [ ] Implement PM Agent Core (session_lifecycle, pdca_engine, memory_ops)
|
||||||
|
- [ ] Write unit tests
|
||||||
|
- [ ] Update User-Guide documentation
|
||||||
|
|
||||||
|
### Week 4-5
|
||||||
|
- [ ] Configure Serena MCP server
|
||||||
|
- [ ] Implement memory operations
|
||||||
|
- [ ] Test cross-session persistence
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📝 Recent Changes
|
||||||
|
|
||||||
|
### 2025-10-14
|
||||||
|
- Created docs/Development/ structure
|
||||||
|
- Wrote ARCHITECTURE.md (system overview)
|
||||||
|
- Wrote ROADMAP.md (5-phase development plan)
|
||||||
|
- Wrote TASKS.md (task tracking)
|
||||||
|
- Wrote PROJECT_STATUS.md (this file)
|
||||||
|
- Salvaged PM Agent mode changes from ~/.claude
|
||||||
|
- Updated Commands/pm.md and Agents/pm-agent.md
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔮 Next Steps
|
||||||
|
|
||||||
|
1. **Complete pm-agent-integration.md** (Phase 1 final doc)
|
||||||
|
2. **Commit Phase 1 documentation** (establish foundation)
|
||||||
|
3. **Commit PM Agent Mode improvements** (design complete)
|
||||||
|
4. **Begin Phase 2 implementation** (Core components)
|
||||||
|
5. **Configure Serena MCP** (unblock Phase 3)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Last Verified**: 2025-10-14
|
||||||
|
**Next Review**: 2025-10-17 (Mid-week check)
|
||||||
|
**Version**: 4.1.5
|
||||||
349
docs/Development/ROADMAP.md
Normal file
349
docs/Development/ROADMAP.md
Normal file
@ -0,0 +1,349 @@
|
|||||||
|
# SuperClaude Development Roadmap
|
||||||
|
|
||||||
|
**Last Updated**: 2025-10-14
|
||||||
|
**Version**: 4.1.5
|
||||||
|
|
||||||
|
## 🎯 Vision
|
||||||
|
|
||||||
|
Transform SuperClaude into a self-improving development platform with PM Agent mode as the always-active meta-layer, enabling continuous context preservation, systematic knowledge management, and intelligent orchestration of all development activities.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📊 Phase Overview
|
||||||
|
|
||||||
|
| Phase | Status | Timeline | Focus |
|
||||||
|
|-------|--------|----------|-------|
|
||||||
|
| **Phase 1** | ✅ Completed | Week 1 | Documentation Structure |
|
||||||
|
| **Phase 2** | 🔄 In Progress | Week 2-3 | PM Agent Mode Integration |
|
||||||
|
| **Phase 3** | ⏳ Planned | Week 4-5 | Serena MCP Integration |
|
||||||
|
| **Phase 4** | ⏳ Planned | Week 6-7 | Documentation Strategy |
|
||||||
|
| **Phase 5** | 🔬 Research | Week 8+ | Auto-Activation System |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 1: Documentation Structure ✅
|
||||||
|
|
||||||
|
**Goal**: Create comprehensive documentation foundation for development
|
||||||
|
|
||||||
|
**Timeline**: Week 1 (2025-10-14 ~ 2025-10-20)
|
||||||
|
|
||||||
|
**Status**: ✅ Completed
|
||||||
|
|
||||||
|
### Tasks
|
||||||
|
|
||||||
|
- [x] Create `docs/Development/` directory structure
|
||||||
|
- [x] Write `ARCHITECTURE.md` - System overview with PM Agent position
|
||||||
|
- [x] Write `ROADMAP.md` - Phase-based development plan with checkboxes
|
||||||
|
- [ ] Write `TASKS.md` - Current task tracking system
|
||||||
|
- [ ] Write `PROJECT_STATUS.md` - Implementation status dashboard
|
||||||
|
- [ ] Write `pm-agent-integration.md` - Integration guide and procedures
|
||||||
|
|
||||||
|
### Deliverables
|
||||||
|
|
||||||
|
- [x] **docs/Development/ARCHITECTURE.md** - Complete system architecture
|
||||||
|
- [x] **docs/Development/ROADMAP.md** - This file (development roadmap)
|
||||||
|
- [ ] **docs/Development/TASKS.md** - Task management with checkboxes
|
||||||
|
- [ ] **docs/Development/PROJECT_STATUS.md** - Current status and metrics
|
||||||
|
- [ ] **docs/Development/pm-agent-integration.md** - Integration procedures
|
||||||
|
|
||||||
|
### Success Criteria
|
||||||
|
|
||||||
|
- [x] Documentation structure established
|
||||||
|
- [x] Architecture clearly documented
|
||||||
|
- [ ] Roadmap with phase breakdown complete
|
||||||
|
- [ ] Task tracking system functional
|
||||||
|
- [ ] Status dashboard provides visibility
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 2: PM Agent Mode Integration 🔄
|
||||||
|
|
||||||
|
**Goal**: Integrate PM Agent mode as always-active meta-layer
|
||||||
|
|
||||||
|
**Timeline**: Week 2-3 (2025-10-21 ~ 2025-11-03)
|
||||||
|
|
||||||
|
**Status**: 🔄 In Progress (30% complete)
|
||||||
|
|
||||||
|
### Tasks
|
||||||
|
|
||||||
|
#### Documentation Updates
|
||||||
|
- [x] Update `superclaude/Commands/pm.md` with Session Lifecycle
|
||||||
|
- [x] Update `superclaude/Agents/pm-agent.md` with PDCA Cycle
|
||||||
|
- [x] Create `docs/pm-agent-implementation-status.md`
|
||||||
|
- [ ] Update `docs/User-Guide/agents.md` - Add PM Agent section
|
||||||
|
- [ ] Update `docs/User-Guide/commands.md` - Add /sc:pm command
|
||||||
|
|
||||||
|
#### Core Implementation
|
||||||
|
- [ ] Implement `superclaude/Core/session_lifecycle.py`
|
||||||
|
- [ ] Session start hooks
|
||||||
|
- [ ] Context restoration logic
|
||||||
|
- [ ] User report generation
|
||||||
|
- [ ] Error handling and fallback
|
||||||
|
- [ ] Implement `superclaude/Core/pdca_engine.py`
|
||||||
|
- [ ] Plan phase automation
|
||||||
|
- [ ] Do phase tracking
|
||||||
|
- [ ] Check phase self-evaluation
|
||||||
|
- [ ] Act phase documentation
|
||||||
|
- [ ] Implement `superclaude/Core/memory_ops.py`
|
||||||
|
- [ ] Serena MCP wrapper
|
||||||
|
- [ ] Memory operation abstractions
|
||||||
|
- [ ] Checkpoint management
|
||||||
|
- [ ] Session state handling
|
||||||
|
|
||||||
|
#### Testing
|
||||||
|
- [ ] Unit tests for session_lifecycle.py
|
||||||
|
- [ ] Unit tests for pdca_engine.py
|
||||||
|
- [ ] Unit tests for memory_ops.py
|
||||||
|
- [ ] Integration tests for PM Agent flow
|
||||||
|
- [ ] Test auto-activation at session start
|
||||||
|
|
||||||
|
### Deliverables
|
||||||
|
|
||||||
|
- [x] **Updated pm.md and pm-agent.md** - Design documentation
|
||||||
|
- [x] **pm-agent-implementation-status.md** - Status tracking
|
||||||
|
- [ ] **superclaude/Core/session_lifecycle.py** - Session management
|
||||||
|
- [ ] **superclaude/Core/pdca_engine.py** - PDCA automation
|
||||||
|
- [ ] **superclaude/Core/memory_ops.py** - Memory operations
|
||||||
|
- [ ] **tests/test_pm_agent.py** - Comprehensive test suite
|
||||||
|
|
||||||
|
### Success Criteria
|
||||||
|
|
||||||
|
- [ ] PM Agent mode loads at session start
|
||||||
|
- [ ] Session Lifecycle functional
|
||||||
|
- [ ] PDCA Cycle automated
|
||||||
|
- [ ] Memory operations working
|
||||||
|
- [ ] All tests passing (>90% coverage)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 3: Serena MCP Integration ⏳
|
||||||
|
|
||||||
|
**Goal**: Full Serena MCP integration for session persistence
|
||||||
|
|
||||||
|
**Timeline**: Week 4-5 (2025-11-04 ~ 2025-11-17)
|
||||||
|
|
||||||
|
**Status**: ⏳ Planned
|
||||||
|
|
||||||
|
### Tasks
|
||||||
|
|
||||||
|
#### MCP Configuration
|
||||||
|
- [ ] Install and configure Serena MCP server
|
||||||
|
- [ ] Update `~/.claude/.claude.json` with Serena config
|
||||||
|
- [ ] Test basic Serena operations
|
||||||
|
- [ ] Troubleshoot connection issues
|
||||||
|
|
||||||
|
#### Memory Operations Implementation
|
||||||
|
- [ ] Implement `list_memories()` integration
|
||||||
|
- [ ] Implement `read_memory(key)` integration
|
||||||
|
- [ ] Implement `write_memory(key, value)` integration
|
||||||
|
- [ ] Implement `delete_memory(key)` integration
|
||||||
|
- [ ] Test memory persistence across sessions
|
||||||
|
|
||||||
|
#### Think Operations Implementation
|
||||||
|
- [ ] Implement `think_about_task_adherence()` hook
|
||||||
|
- [ ] Implement `think_about_collected_information()` hook
|
||||||
|
- [ ] Implement `think_about_whether_you_are_done()` hook
|
||||||
|
- [ ] Integrate with TodoWrite completion tracking
|
||||||
|
- [ ] Test self-evaluation triggers
|
||||||
|
|
||||||
|
#### Cross-Session Testing
|
||||||
|
- [ ] Test context restoration after restart
|
||||||
|
- [ ] Test checkpoint save/restore
|
||||||
|
- [ ] Test memory persistence durability
|
||||||
|
- [ ] Test multi-project memory isolation
|
||||||
|
- [ ] Performance testing (memory operations latency)
|
||||||
|
|
||||||
|
### Deliverables
|
||||||
|
|
||||||
|
- [ ] **Serena MCP Server** - Configured and operational
|
||||||
|
- [ ] **superclaude/Core/serena_client.py** - Serena MCP client wrapper
|
||||||
|
- [ ] **superclaude/Core/think_operations.py** - Think hooks implementation
|
||||||
|
- [ ] **docs/troubleshooting/serena-setup.md** - Setup guide
|
||||||
|
- [ ] **tests/test_serena_integration.py** - Integration test suite
|
||||||
|
|
||||||
|
### Success Criteria
|
||||||
|
|
||||||
|
- [ ] Serena MCP server operational
|
||||||
|
- [ ] All memory operations functional
|
||||||
|
- [ ] Think operations trigger correctly
|
||||||
|
- [ ] Cross-session persistence verified
|
||||||
|
- [ ] Performance acceptable (<100ms per operation)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 4: Documentation Strategy ⏳
|
||||||
|
|
||||||
|
**Goal**: Implement systematic documentation lifecycle
|
||||||
|
|
||||||
|
**Timeline**: Week 6-7 (2025-11-18 ~ 2025-12-01)
|
||||||
|
|
||||||
|
**Status**: ⏳ Planned
|
||||||
|
|
||||||
|
### Tasks
|
||||||
|
|
||||||
|
#### Directory Structure
|
||||||
|
- [ ] Create `docs/temp/` template structure
|
||||||
|
- [ ] Create `docs/patterns/` template structure
|
||||||
|
- [ ] Create `docs/mistakes/` template structure
|
||||||
|
- [ ] Add README.md to each directory explaining purpose
|
||||||
|
- [ ] Create .gitignore for temporary files
|
||||||
|
|
||||||
|
#### File Templates
|
||||||
|
- [ ] Create `hypothesis-template.md` for Plan phase
|
||||||
|
- [ ] Create `experiment-template.md` for Do phase
|
||||||
|
- [ ] Create `lessons-template.md` for Check phase
|
||||||
|
- [ ] Create `pattern-template.md` for successful patterns
|
||||||
|
- [ ] Create `mistake-template.md` for error records
|
||||||
|
|
||||||
|
#### Lifecycle Automation
|
||||||
|
- [ ] Implement 7-day temporary file cleanup
|
||||||
|
- [ ] Create docs/temp → docs/patterns migration script
|
||||||
|
- [ ] Create docs/temp → docs/mistakes migration script
|
||||||
|
- [ ] Automate "Last Verified" date updates
|
||||||
|
- [ ] Implement duplicate pattern detection
|
||||||
|
|
||||||
|
#### Knowledge Management
|
||||||
|
- [ ] Implement pattern extraction logic
|
||||||
|
- [ ] Implement CLAUDE.md auto-update mechanism
|
||||||
|
- [ ] Create knowledge graph visualization
|
||||||
|
- [ ] Implement pattern search functionality
|
||||||
|
- [ ] Create mistake prevention checklist generator
|
||||||
|
|
||||||
|
### Deliverables
|
||||||
|
|
||||||
|
- [ ] **docs/temp/**, **docs/patterns/**, **docs/mistakes/** - Directory templates
|
||||||
|
- [ ] **superclaude/Core/doc_lifecycle.py** - Lifecycle automation
|
||||||
|
- [ ] **superclaude/Core/knowledge_manager.py** - Knowledge extraction
|
||||||
|
- [ ] **scripts/migrate_docs.py** - Migration utilities
|
||||||
|
- [ ] **tests/test_doc_lifecycle.py** - Lifecycle test suite
|
||||||
|
|
||||||
|
### Success Criteria
|
||||||
|
|
||||||
|
- [ ] Directory templates functional
|
||||||
|
- [ ] Lifecycle automation working
|
||||||
|
- [ ] Migration scripts reliable
|
||||||
|
- [ ] Knowledge extraction accurate
|
||||||
|
- [ ] CLAUDE.md auto-updates verified
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 5: Auto-Activation System 🔬
|
||||||
|
|
||||||
|
**Goal**: PM Agent activates automatically at every session start
|
||||||
|
|
||||||
|
**Timeline**: Week 8+ (2025-12-02 onwards)
|
||||||
|
|
||||||
|
**Status**: 🔬 Research Needed
|
||||||
|
|
||||||
|
### Research Phase
|
||||||
|
|
||||||
|
- [ ] Research Claude Code initialization hooks
|
||||||
|
- [ ] Investigate session start event handling
|
||||||
|
- [ ] Study existing auto-activation patterns
|
||||||
|
- [ ] Analyze Claude Code plugin system (if available)
|
||||||
|
- [ ] Review Anthropic documentation on extensibility
|
||||||
|
|
||||||
|
### Tasks
|
||||||
|
|
||||||
|
#### Hook Implementation
|
||||||
|
- [ ] Identify session start hook mechanism
|
||||||
|
- [ ] Implement PM Agent auto-activation hook
|
||||||
|
- [ ] Test activation timing and reliability
|
||||||
|
- [ ] Handle edge cases (crash recovery, etc.)
|
||||||
|
- [ ] Performance optimization (minimize startup delay)
|
||||||
|
|
||||||
|
#### Context Restoration
|
||||||
|
- [ ] Implement automatic context loading
|
||||||
|
- [ ] Test memory restoration at startup
|
||||||
|
- [ ] Verify user report generation
|
||||||
|
- [ ] Handle missing or corrupted memory
|
||||||
|
- [ ] Graceful fallback for new sessions
|
||||||
|
|
||||||
|
#### Integration Testing
|
||||||
|
- [ ] Test across multiple sessions
|
||||||
|
- [ ] Test with different project contexts
|
||||||
|
- [ ] Test memory persistence durability
|
||||||
|
- [ ] Test error recovery mechanisms
|
||||||
|
- [ ] Performance testing (startup time impact)
|
||||||
|
|
||||||
|
### Deliverables
|
||||||
|
|
||||||
|
- [ ] **superclaude/Core/auto_activation.py** - Auto-activation system
|
||||||
|
- [ ] **docs/Developer-Guide/auto-activation.md** - Implementation guide
|
||||||
|
- [ ] **tests/test_auto_activation.py** - Auto-activation tests
|
||||||
|
- [ ] **Performance Report** - Startup time impact analysis
|
||||||
|
|
||||||
|
### Success Criteria
|
||||||
|
|
||||||
|
- [ ] PM Agent activates at every session start
|
||||||
|
- [ ] Context restoration reliable (>99%)
|
||||||
|
- [ ] User report generated consistently
|
||||||
|
- [ ] Startup delay minimal (<500ms)
|
||||||
|
- [ ] Error recovery robust
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🚀 Future Enhancements (Post-Phase 5)
|
||||||
|
|
||||||
|
### Multi-Project Orchestration
|
||||||
|
- [ ] Cross-project knowledge sharing
|
||||||
|
- [ ] Unified pattern library
|
||||||
|
- [ ] Multi-project context switching
|
||||||
|
- [ ] Project-specific memory namespaces
|
||||||
|
|
||||||
|
### AI-Driven Pattern Recognition
|
||||||
|
- [ ] Machine learning for pattern extraction
|
||||||
|
- [ ] Automatic best practice identification
|
||||||
|
- [ ] Predictive mistake prevention
|
||||||
|
- [ ] Smart knowledge graph generation
|
||||||
|
|
||||||
|
### Enhanced Self-Evaluation
|
||||||
|
- [ ] Advanced think operations
|
||||||
|
- [ ] Quality scoring automation
|
||||||
|
- [ ] Performance regression detection
|
||||||
|
- [ ] Code quality trend analysis
|
||||||
|
|
||||||
|
### Community Features
|
||||||
|
- [ ] Pattern sharing marketplace
|
||||||
|
- [ ] Community knowledge contributions
|
||||||
|
- [ ] Collaborative PDCA cycles
|
||||||
|
- [ ] Public pattern library
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📊 Metrics & KPIs
|
||||||
|
|
||||||
|
### Phase Completion Metrics
|
||||||
|
|
||||||
|
| Metric | Target | Current | Status |
|
||||||
|
|--------|--------|---------|--------|
|
||||||
|
| Documentation Coverage | 100% | 40% | 🔄 In Progress |
|
||||||
|
| PM Agent Integration | 100% | 30% | 🔄 In Progress |
|
||||||
|
| Serena MCP Integration | 100% | 0% | ⏳ Pending |
|
||||||
|
| Documentation Strategy | 100% | 0% | ⏳ Pending |
|
||||||
|
| Auto-Activation | 100% | 0% | 🔬 Research |
|
||||||
|
|
||||||
|
### Quality Metrics
|
||||||
|
|
||||||
|
| Metric | Target | Current | Status |
|
||||||
|
|--------|--------|---------|--------|
|
||||||
|
| Test Coverage | >90% | 0% | ⏳ Pending |
|
||||||
|
| Context Restoration Rate | 100% | N/A | ⏳ Pending |
|
||||||
|
| Session Continuity | >95% | N/A | ⏳ Pending |
|
||||||
|
| Documentation Freshness | <7 days | N/A | ⏳ Pending |
|
||||||
|
| Mistake Prevention | <10% recurring | N/A | ⏳ Pending |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔄 Update Schedule
|
||||||
|
|
||||||
|
- **Weekly**: Task progress updates
|
||||||
|
- **Bi-weekly**: Phase milestone reviews
|
||||||
|
- **Monthly**: Roadmap revision and priority adjustment
|
||||||
|
- **Quarterly**: Long-term vision alignment
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Last Verified**: 2025-10-14
|
||||||
|
**Next Review**: 2025-10-21 (1 week)
|
||||||
|
**Version**: 4.1.5
|
||||||
151
docs/Development/TASKS.md
Normal file
151
docs/Development/TASKS.md
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
# SuperClaude Development Tasks
|
||||||
|
|
||||||
|
**Last Updated**: 2025-10-14
|
||||||
|
**Current Sprint**: Phase 1 - Documentation Structure
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔥 High Priority (This Week: 2025-10-14 ~ 2025-10-20)
|
||||||
|
|
||||||
|
### Phase 1: Documentation Structure
|
||||||
|
- [x] Create docs/Development/ directory
|
||||||
|
- [x] Write ARCHITECTURE.md
|
||||||
|
- [x] Write ROADMAP.md
|
||||||
|
- [ ] Write TASKS.md (this file)
|
||||||
|
- [ ] Write PROJECT_STATUS.md
|
||||||
|
- [ ] Write pm-agent-integration.md
|
||||||
|
- [ ] Commit Phase 1 changes
|
||||||
|
|
||||||
|
### PM Agent Mode
|
||||||
|
- [x] Design Session Lifecycle
|
||||||
|
- [x] Design PDCA Cycle
|
||||||
|
- [x] Update Commands/pm.md
|
||||||
|
- [x] Update Agents/pm-agent.md
|
||||||
|
- [x] Create pm-agent-implementation-status.md
|
||||||
|
- [ ] Commit PM Agent Mode changes
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📋 Medium Priority (This Month: October 2025)
|
||||||
|
|
||||||
|
### Phase 2: Core Implementation
|
||||||
|
- [ ] Implement superclaude/Core/session_lifecycle.py
|
||||||
|
- [ ] Implement superclaude/Core/pdca_engine.py
|
||||||
|
- [ ] Implement superclaude/Core/memory_ops.py
|
||||||
|
- [ ] Write unit tests for PM Agent core
|
||||||
|
- [ ] Update User-Guide documentation
|
||||||
|
|
||||||
|
### Testing & Validation
|
||||||
|
- [ ] Create test suite for session_lifecycle
|
||||||
|
- [ ] Create test suite for pdca_engine
|
||||||
|
- [ ] Create test suite for memory_ops
|
||||||
|
- [ ] Integration testing for PM Agent flow
|
||||||
|
- [ ] Performance benchmarking
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 💡 Low Priority (Future)
|
||||||
|
|
||||||
|
### Phase 3: Serena MCP Integration
|
||||||
|
- [ ] Configure Serena MCP server
|
||||||
|
- [ ] Test Serena connection
|
||||||
|
- [ ] Implement memory operations
|
||||||
|
- [ ] Test cross-session persistence
|
||||||
|
|
||||||
|
### Phase 4: Documentation Strategy
|
||||||
|
- [ ] Create docs/temp/ template
|
||||||
|
- [ ] Create docs/patterns/ template
|
||||||
|
- [ ] Create docs/mistakes/ template
|
||||||
|
- [ ] Implement 7-day cleanup automation
|
||||||
|
|
||||||
|
### Phase 5: Auto-Activation
|
||||||
|
- [ ] Research Claude Code init hooks
|
||||||
|
- [ ] Implement auto-activation
|
||||||
|
- [ ] Test session start behavior
|
||||||
|
- [ ] Performance optimization
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🐛 Bugs & Issues
|
||||||
|
|
||||||
|
### Known Issues
|
||||||
|
- [ ] Serena MCP not configured (blocker for Phase 3)
|
||||||
|
- [ ] Auto-activation hooks unknown (research needed for Phase 5)
|
||||||
|
- [ ] Documentation directory structure missing (in progress)
|
||||||
|
|
||||||
|
### Recent Fixes
|
||||||
|
- [x] PM Agent changes salvaged from ~/.claude directory (2025-10-14)
|
||||||
|
- [x] Git repository cleanup in ~/.claude (2025-10-14)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ✅ Completed Tasks
|
||||||
|
|
||||||
|
### 2025-10-14
|
||||||
|
- [x] Salvaged PM Agent mode changes from ~/.claude
|
||||||
|
- [x] Cleaned up ~/.claude git repository
|
||||||
|
- [x] Created pm-agent-implementation-status.md
|
||||||
|
- [x] Created docs/Development/ directory
|
||||||
|
- [x] Wrote ARCHITECTURE.md
|
||||||
|
- [x] Wrote ROADMAP.md
|
||||||
|
- [x] Wrote TASKS.md
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📊 Sprint Metrics
|
||||||
|
|
||||||
|
### Current Sprint (Week 1)
|
||||||
|
- **Planned Tasks**: 8
|
||||||
|
- **Completed**: 7
|
||||||
|
- **In Progress**: 1
|
||||||
|
- **Blocked**: 0
|
||||||
|
- **Completion Rate**: 87.5%
|
||||||
|
|
||||||
|
### Overall Progress (Phase 1)
|
||||||
|
- **Total Tasks**: 6
|
||||||
|
- **Completed**: 3
|
||||||
|
- **Remaining**: 3
|
||||||
|
- **On Schedule**: ✅ Yes
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔄 Task Management Process
|
||||||
|
|
||||||
|
### Weekly Cycle
|
||||||
|
1. **Monday**: Review last week, plan this week
|
||||||
|
2. **Mid-week**: Progress check, adjust priorities
|
||||||
|
3. **Friday**: Update task status, prepare next week
|
||||||
|
|
||||||
|
### Task Categories
|
||||||
|
- 🔥 **High Priority**: Must complete this week
|
||||||
|
- 📋 **Medium Priority**: Complete this month
|
||||||
|
- 💡 **Low Priority**: Future enhancements
|
||||||
|
- 🐛 **Bugs**: Critical issues requiring immediate attention
|
||||||
|
|
||||||
|
### Status Markers
|
||||||
|
- ✅ **Completed**: Task finished and verified
|
||||||
|
- 🔄 **In Progress**: Currently working on
|
||||||
|
- ⏳ **Pending**: Waiting for dependencies
|
||||||
|
- 🚫 **Blocked**: Cannot proceed (document blocker)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📝 Task Template
|
||||||
|
|
||||||
|
When adding new tasks, use this format:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
- [ ] Task description
|
||||||
|
- **Priority**: High/Medium/Low
|
||||||
|
- **Estimate**: 1-2 hours / 1-2 days / 1 week
|
||||||
|
- **Dependencies**: List dependent tasks
|
||||||
|
- **Blocker**: Any blocking issues
|
||||||
|
- **Assigned**: Person/Team
|
||||||
|
- **Due Date**: YYYY-MM-DD
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Last Verified**: 2025-10-14
|
||||||
|
**Next Update**: 2025-10-17 (Mid-week check)
|
||||||
|
**Version**: 4.1.5
|
||||||
@ -0,0 +1,390 @@
|
|||||||
|
# PM Agent Autonomous Enhancement - 改善提案
|
||||||
|
|
||||||
|
> **Date**: 2025-10-14
|
||||||
|
> **Status**: 提案中(ユーザーレビュー待ち)
|
||||||
|
> **Goal**: ユーザーインプット最小化 + 確信を持った先回り提案
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 現状の問題点
|
||||||
|
|
||||||
|
### 既存の `superclaude/commands/pm.md`
|
||||||
|
```yaml
|
||||||
|
良い点:
|
||||||
|
✅ PDCAサイクルが定義されている
|
||||||
|
✅ サブエージェント連携が明確
|
||||||
|
✅ ドキュメント記録の仕組みがある
|
||||||
|
|
||||||
|
改善が必要な点:
|
||||||
|
❌ ユーザーインプット依存度が高い
|
||||||
|
❌ 調査フェーズが受動的
|
||||||
|
❌ 提案が「どうしますか?」スタイル
|
||||||
|
❌ 確信を持った提案がない
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 💡 改善提案
|
||||||
|
|
||||||
|
### Phase 0: **自律的調査フェーズ**(新規追加)
|
||||||
|
|
||||||
|
#### ユーザーリクエスト受信時の自動実行
|
||||||
|
```yaml
|
||||||
|
Auto-Investigation (許可不要・自動実行):
|
||||||
|
1. Context Restoration:
|
||||||
|
- Read docs/Development/tasks/current-tasks.md
|
||||||
|
- list_memories() → 前回のセッション確認
|
||||||
|
- read_memory("project_context") → プロジェクト理解
|
||||||
|
- read_memory("past_mistakes") → 過去の失敗確認
|
||||||
|
|
||||||
|
2. Project Analysis:
|
||||||
|
- Read CLAUDE.md → プロジェクト固有ルール
|
||||||
|
- Glob **/*.md → ドキュメント構造把握
|
||||||
|
- mcp__serena__get_symbols_overview → コード構造理解
|
||||||
|
- Grep "TODO\|FIXME\|XXX" → 既知の課題確認
|
||||||
|
|
||||||
|
3. Current State Assessment:
|
||||||
|
- Bash "git status" → 現在の状態
|
||||||
|
- Bash "git log -5 --oneline" → 最近の変更
|
||||||
|
- Read tests/ → テストカバレッジ確認
|
||||||
|
- Security scan → セキュリティリスク確認
|
||||||
|
|
||||||
|
4. Competitive Research (必要時):
|
||||||
|
- tavily search → ベストプラクティス調査
|
||||||
|
- context7 → 公式ドキュメント参照
|
||||||
|
- Deep Research → 競合サービス分析
|
||||||
|
|
||||||
|
5. Architecture Evaluation:
|
||||||
|
- 既存アーキテクチャの強み分析
|
||||||
|
- 技術スタックの特徴把握
|
||||||
|
- 拡張可能性の評価
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 出力形式
|
||||||
|
```markdown
|
||||||
|
📊 自律調査完了
|
||||||
|
|
||||||
|
現状分析:
|
||||||
|
- プロジェクト: [名前]([技術スタック])
|
||||||
|
- 進捗: [前回セッションの続き or 新規タスク]
|
||||||
|
- コードベース: [ファイル数]、テストカバレッジ [%]
|
||||||
|
- 既知の課題: [TODO/FIXME数]
|
||||||
|
- 最近の変更: [git log要約]
|
||||||
|
|
||||||
|
アーキテクチャの強み:
|
||||||
|
- [強み1]: [具体的な理由]
|
||||||
|
- [強み2]: [具体的な理由]
|
||||||
|
|
||||||
|
不足している要素:
|
||||||
|
- [不足1]: [影響]
|
||||||
|
- [不足2]: [影響]
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Phase 1: **確信を持った提案**(強化)
|
||||||
|
|
||||||
|
#### ❌ 改善前(受動的)
|
||||||
|
```
|
||||||
|
User: "認証機能作って"
|
||||||
|
|
||||||
|
PM Agent: "認証機能を実装しますね。
|
||||||
|
どんな認証方式がいいですか?"
|
||||||
|
|
||||||
|
→ ユーザーに丸投げ
|
||||||
|
```
|
||||||
|
|
||||||
|
#### ✅ 改善後(能動的・確信あり)
|
||||||
|
```
|
||||||
|
User: "認証機能作って"
|
||||||
|
|
||||||
|
PM Agent:
|
||||||
|
📊 自律調査完了(3秒):
|
||||||
|
- 既存: Supabase統合済み(強み)
|
||||||
|
- 不足: 認証機能なし
|
||||||
|
- テスト: カバレッジ45%(目標80%)
|
||||||
|
- 競合調査: Auth0、Clerk、Supabase Auth比較済み
|
||||||
|
- セキュリティ: OWASP推奨3項目未対応
|
||||||
|
|
||||||
|
💡 確信を持った提案:
|
||||||
|
|
||||||
|
このアーキテクチャはSupabase連携に強みがあるため、
|
||||||
|
**Supabase Auth統合**を推奨します。
|
||||||
|
|
||||||
|
具体的な実装方針:
|
||||||
|
1. Supabase Auth統合(JWT + リフレッシュトークン)
|
||||||
|
2. MFA対応(TOTP実装)
|
||||||
|
3. セキュリティテスト追加(カバレッジ85%目標)
|
||||||
|
4. 既存APIとのシームレス統合
|
||||||
|
|
||||||
|
選択理由:
|
||||||
|
✅ 既存のSupabase接続再利用(実装コスト最小)
|
||||||
|
✅ エンタープライズグレードのセキュリティ
|
||||||
|
✅ 無料枠で十分な機能(コスト効率◎)
|
||||||
|
✅ 将来のスケーラビリティ確保
|
||||||
|
|
||||||
|
代替案との比較:
|
||||||
|
- Auth0: 月$25〜、実装複雑度高
|
||||||
|
- Clerk: 月$25〜、React特化(このプロジェクトはNext.js)
|
||||||
|
- Supabase Auth: 無料、既存統合済み ← 推奨
|
||||||
|
|
||||||
|
この方針で進めてよろしいですか?
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Phase 2: **自律実行**(既存を強化)
|
||||||
|
|
||||||
|
#### 承認後の自動フロー
|
||||||
|
```yaml
|
||||||
|
User: "OK"
|
||||||
|
|
||||||
|
PM Agent(完全自律実行):
|
||||||
|
1. Architecture Design:
|
||||||
|
- system-architect: Supabase Auth設計
|
||||||
|
- security-engineer: セキュリティレビュー
|
||||||
|
|
||||||
|
2. Implementation:
|
||||||
|
- backend-architect: API統合実装
|
||||||
|
- frontend-architect: UI実装
|
||||||
|
- Load magic: Login/Register components
|
||||||
|
|
||||||
|
3. Testing:
|
||||||
|
- Write tests/auth/*.test.ts
|
||||||
|
- pytest実行 → 失敗検出
|
||||||
|
|
||||||
|
4. Self-Correction:
|
||||||
|
- context7 → Supabase公式ドキュメント確認
|
||||||
|
- エラー原因特定: "JWTシークレット未設定"
|
||||||
|
- 修正実装
|
||||||
|
- 再テスト → 合格
|
||||||
|
|
||||||
|
5. Documentation:
|
||||||
|
- Update docs/patterns/supabase-auth-integration.md
|
||||||
|
- Update CLAUDE.md(認証パターン追加)
|
||||||
|
- write_memory("success_pattern", 詳細)
|
||||||
|
|
||||||
|
6. Report:
|
||||||
|
✅ 認証機能実装完了
|
||||||
|
|
||||||
|
実装内容:
|
||||||
|
- Supabase Auth統合(JWT + リフレッシュ)
|
||||||
|
- MFA対応(TOTP)
|
||||||
|
- テストカバレッジ: 45% → 87%(目標達成)
|
||||||
|
- セキュリティ: OWASP準拠確認済み
|
||||||
|
|
||||||
|
学習記録:
|
||||||
|
- 成功パターン: docs/patterns/supabase-auth-integration.md
|
||||||
|
- 遭遇したエラー: JWT設定不足(修正済み)
|
||||||
|
- 次回の改善: 環境変数チェックリスト更新
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔧 実装方針
|
||||||
|
|
||||||
|
### `superclaude/commands/pm.md` への追加セクション
|
||||||
|
|
||||||
|
#### 1. Autonomous Investigation Phase(新規)
|
||||||
|
```markdown
|
||||||
|
## Phase 0: Autonomous Investigation (Auto-Execute)
|
||||||
|
|
||||||
|
**Trigger**: Any user request received
|
||||||
|
|
||||||
|
**Execution**: Automatic, no permission required
|
||||||
|
|
||||||
|
### Investigation Steps:
|
||||||
|
1. **Context Restoration**
|
||||||
|
- Read `docs/Development/tasks/current-tasks.md`
|
||||||
|
- Serena memory restoration
|
||||||
|
- Project context loading
|
||||||
|
|
||||||
|
2. **Project Analysis**
|
||||||
|
- CLAUDE.md → Project rules
|
||||||
|
- Code structure analysis
|
||||||
|
- Test coverage check
|
||||||
|
- Security scan
|
||||||
|
- Known issues detection (TODO/FIXME)
|
||||||
|
|
||||||
|
3. **Competitive Research** (when relevant)
|
||||||
|
- Best practices research (Tavily)
|
||||||
|
- Official documentation (Context7)
|
||||||
|
- Alternative solutions analysis
|
||||||
|
|
||||||
|
4. **Architecture Evaluation**
|
||||||
|
- Identify architectural strengths
|
||||||
|
- Detect technology stack characteristics
|
||||||
|
- Assess extensibility
|
||||||
|
|
||||||
|
### Output Format:
|
||||||
|
```
|
||||||
|
📊 Autonomous Investigation Complete
|
||||||
|
|
||||||
|
Current State:
|
||||||
|
- Project: [name] ([stack])
|
||||||
|
- Progress: [status]
|
||||||
|
- Codebase: [files count], Test Coverage: [%]
|
||||||
|
- Known Issues: [count]
|
||||||
|
- Recent Changes: [git log summary]
|
||||||
|
|
||||||
|
Architectural Strengths:
|
||||||
|
- [strength 1]: [rationale]
|
||||||
|
- [strength 2]: [rationale]
|
||||||
|
|
||||||
|
Missing Elements:
|
||||||
|
- [gap 1]: [impact]
|
||||||
|
- [gap 2]: [impact]
|
||||||
|
```
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2. Confident Proposal Phase(強化)
|
||||||
|
```markdown
|
||||||
|
## Phase 1: Confident Proposal (Enhanced)
|
||||||
|
|
||||||
|
**Principle**: Never ask "What do you want?" - Always propose with conviction
|
||||||
|
|
||||||
|
### Proposal Format:
|
||||||
|
```
|
||||||
|
💡 Confident Proposal:
|
||||||
|
|
||||||
|
[Implementation approach] is recommended.
|
||||||
|
|
||||||
|
Specific Implementation Plan:
|
||||||
|
1. [Step 1 with rationale]
|
||||||
|
2. [Step 2 with rationale]
|
||||||
|
3. [Step 3 with rationale]
|
||||||
|
|
||||||
|
Selection Rationale:
|
||||||
|
✅ [Reason 1]: [Evidence]
|
||||||
|
✅ [Reason 2]: [Evidence]
|
||||||
|
✅ [Reason 3]: [Evidence]
|
||||||
|
|
||||||
|
Alternatives Considered:
|
||||||
|
- [Alt 1]: [Why not chosen]
|
||||||
|
- [Alt 2]: [Why not chosen]
|
||||||
|
- [Recommended]: [Why chosen] ← Recommended
|
||||||
|
|
||||||
|
Proceed with this approach?
|
||||||
|
```
|
||||||
|
|
||||||
|
### Anti-Patterns (Never Do):
|
||||||
|
❌ "What authentication do you want?" (Passive)
|
||||||
|
❌ "How should we implement this?" (Uncertain)
|
||||||
|
❌ "There are several options..." (Indecisive)
|
||||||
|
|
||||||
|
✅ "Supabase Auth is recommended because..." (Confident)
|
||||||
|
✅ "Based on your architecture's Supabase integration..." (Evidence-based)
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3. Autonomous Execution Phase(既存を明示化)
|
||||||
|
```markdown
|
||||||
|
## Phase 2: Autonomous Execution
|
||||||
|
|
||||||
|
**Trigger**: User approval ("OK", "Go ahead", "Yes")
|
||||||
|
|
||||||
|
**Execution**: Fully autonomous, systematic PDCA
|
||||||
|
|
||||||
|
### Self-Correction Loop:
|
||||||
|
```yaml
|
||||||
|
Implementation:
|
||||||
|
- Execute with sub-agents
|
||||||
|
- Write comprehensive tests
|
||||||
|
- Run validation
|
||||||
|
|
||||||
|
Error Detected:
|
||||||
|
→ Context7: Check official documentation
|
||||||
|
→ Identify root cause
|
||||||
|
→ Implement fix
|
||||||
|
→ Re-test
|
||||||
|
→ Repeat until passing
|
||||||
|
|
||||||
|
Success:
|
||||||
|
→ Document pattern (docs/patterns/)
|
||||||
|
→ Update learnings (write_memory)
|
||||||
|
→ Report completion with evidence
|
||||||
|
```
|
||||||
|
|
||||||
|
### Quality Gates:
|
||||||
|
- Tests must pass (no exceptions)
|
||||||
|
- Coverage targets must be met
|
||||||
|
- Security checks must pass
|
||||||
|
- Documentation must be updated
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📊 期待される効果
|
||||||
|
|
||||||
|
### Before (現状)
|
||||||
|
```yaml
|
||||||
|
User Input Required: 高
|
||||||
|
- 認証方式の選択
|
||||||
|
- 実装方針の決定
|
||||||
|
- エラー対応の指示
|
||||||
|
- テスト方針の決定
|
||||||
|
|
||||||
|
Proposal Quality: 受動的
|
||||||
|
- "どうしますか?"スタイル
|
||||||
|
- 選択肢の羅列のみ
|
||||||
|
- ユーザーが決定
|
||||||
|
|
||||||
|
Execution: 半自動
|
||||||
|
- エラー時にユーザーに報告
|
||||||
|
- 修正方針をユーザーが指示
|
||||||
|
```
|
||||||
|
|
||||||
|
### After (改善後)
|
||||||
|
```yaml
|
||||||
|
User Input Required: 最小
|
||||||
|
- "認証機能作って"のみ
|
||||||
|
- 提案への承認/拒否のみ
|
||||||
|
|
||||||
|
Proposal Quality: 能動的・確信あり
|
||||||
|
- 調査済みの根拠提示
|
||||||
|
- 明確な推奨案
|
||||||
|
- 代替案との比較
|
||||||
|
|
||||||
|
Execution: 完全自律
|
||||||
|
- エラー自己修正
|
||||||
|
- 公式ドキュメント自動参照
|
||||||
|
- テスト合格まで自動実行
|
||||||
|
- 学習自動記録
|
||||||
|
```
|
||||||
|
|
||||||
|
### 定量的目標
|
||||||
|
- ユーザーインプット削減: **80%削減**
|
||||||
|
- 提案品質向上: **確信度90%以上**
|
||||||
|
- 自律実行成功率: **95%以上**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🚀 実装ステップ
|
||||||
|
|
||||||
|
### Step 1: pm.md 修正
|
||||||
|
- [ ] Phase 0: Autonomous Investigation 追加
|
||||||
|
- [ ] Phase 1: Confident Proposal 強化
|
||||||
|
- [ ] Phase 2: Autonomous Execution 明示化
|
||||||
|
- [ ] Examples セクションに具体例追加
|
||||||
|
|
||||||
|
### Step 2: テスト作成
|
||||||
|
- [ ] `tests/test_pm_autonomous.py`
|
||||||
|
- [ ] 自律調査フローのテスト
|
||||||
|
- [ ] 確信提案フォーマットのテスト
|
||||||
|
- [ ] 自己修正ループのテスト
|
||||||
|
|
||||||
|
### Step 3: 動作確認
|
||||||
|
- [ ] 開発版インストール
|
||||||
|
- [ ] 実際のワークフローで検証
|
||||||
|
- [ ] フィードバック収集
|
||||||
|
|
||||||
|
### Step 4: 学習記録
|
||||||
|
- [ ] `docs/patterns/pm-autonomous-workflow.md`
|
||||||
|
- [ ] 成功パターンの文書化
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ✅ ユーザー承認待ち
|
||||||
|
|
||||||
|
**この方針で実装を進めてよろしいですか?**
|
||||||
|
|
||||||
|
承認いただければ、すぐに `superclaude/commands/pm.md` の修正を開始します。
|
||||||
378
docs/Development/installation-flow-understanding.md
Normal file
378
docs/Development/installation-flow-understanding.md
Normal file
@ -0,0 +1,378 @@
|
|||||||
|
# SuperClaude Installation Flow - Complete Understanding
|
||||||
|
|
||||||
|
> **学習内容**: インストーラーがどうやって `~/.claude/` にファイルを配置するかの完全理解
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔄 インストールフロー全体像
|
||||||
|
|
||||||
|
### ユーザー操作
|
||||||
|
```bash
|
||||||
|
# Step 1: パッケージインストール
|
||||||
|
pipx install SuperClaude
|
||||||
|
# または
|
||||||
|
npm install -g @bifrost_inc/superclaude
|
||||||
|
|
||||||
|
# Step 2: セットアップ実行
|
||||||
|
SuperClaude install
|
||||||
|
```
|
||||||
|
|
||||||
|
### 内部処理の流れ
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
1. Entry Point:
|
||||||
|
File: superclaude/__main__.py → main()
|
||||||
|
|
||||||
|
2. CLI Parser:
|
||||||
|
File: superclaude/__main__.py → create_parser()
|
||||||
|
Command: "install" サブコマンド登録
|
||||||
|
|
||||||
|
3. Component Manager:
|
||||||
|
File: setup/cli/install.py
|
||||||
|
Role: インストールコンポーネントの調整
|
||||||
|
|
||||||
|
4. Commands Component:
|
||||||
|
File: setup/components/commands.py → CommandsComponent
|
||||||
|
Role: スラッシュコマンドのインストール
|
||||||
|
|
||||||
|
5. Source Files:
|
||||||
|
Location: superclaude/commands/*.md
|
||||||
|
Content: pm.md, implement.md, test.md, etc.
|
||||||
|
|
||||||
|
6. Destination:
|
||||||
|
Location: ~/.claude/commands/sc/*.md
|
||||||
|
Result: ユーザー環境に配置
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📁 CommandsComponent の詳細
|
||||||
|
|
||||||
|
### クラス構造
|
||||||
|
```python
|
||||||
|
class CommandsComponent(Component):
|
||||||
|
"""
|
||||||
|
Role: スラッシュコマンドのインストール・管理
|
||||||
|
Parent: setup/core/base.py → Component
|
||||||
|
Install Path: ~/.claude/commands/sc/
|
||||||
|
"""
|
||||||
|
```
|
||||||
|
|
||||||
|
### 主要メソッド
|
||||||
|
|
||||||
|
#### 1. `__init__()`
|
||||||
|
```python
|
||||||
|
def __init__(self, install_dir: Optional[Path] = None):
|
||||||
|
super().__init__(install_dir, Path("commands/sc"))
|
||||||
|
```
|
||||||
|
**理解**:
|
||||||
|
- `install_dir`: `~/.claude/` (ユーザー環境)
|
||||||
|
- `Path("commands/sc")`: サブディレクトリ指定
|
||||||
|
- 結果: `~/.claude/commands/sc/` にインストール
|
||||||
|
|
||||||
|
#### 2. `_get_source_dir()`
|
||||||
|
```python
|
||||||
|
def _get_source_dir(self) -> Path:
|
||||||
|
# setup/components/commands.py の位置から計算
|
||||||
|
project_root = Path(__file__).parent.parent.parent
|
||||||
|
# → ~/github/SuperClaude_Framework/
|
||||||
|
|
||||||
|
return project_root / "superclaude" / "commands"
|
||||||
|
# → ~/github/SuperClaude_Framework/superclaude/commands/
|
||||||
|
```
|
||||||
|
|
||||||
|
**理解**:
|
||||||
|
```
|
||||||
|
Source: ~/github/SuperClaude_Framework/superclaude/commands/*.md
|
||||||
|
Target: ~/.claude/commands/sc/*.md
|
||||||
|
|
||||||
|
つまり:
|
||||||
|
superclaude/commands/pm.md
|
||||||
|
↓ コピー
|
||||||
|
~/.claude/commands/sc/pm.md
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3. `_install()` - インストール実行
|
||||||
|
```python
|
||||||
|
def _install(self, config: Dict[str, Any]) -> bool:
|
||||||
|
self.logger.info("Installing SuperClaude command definitions...")
|
||||||
|
|
||||||
|
# 既存コマンドのマイグレーション
|
||||||
|
self._migrate_existing_commands()
|
||||||
|
|
||||||
|
# 親クラスのインストール実行
|
||||||
|
return super()._install(config)
|
||||||
|
```
|
||||||
|
|
||||||
|
**理解**:
|
||||||
|
1. ログ出力
|
||||||
|
2. 旧バージョンからの移行処理
|
||||||
|
3. 実際のファイルコピー(親クラスで実行)
|
||||||
|
|
||||||
|
#### 4. `_migrate_existing_commands()` - マイグレーション
|
||||||
|
```python
|
||||||
|
def _migrate_existing_commands(self) -> None:
|
||||||
|
"""
|
||||||
|
旧Location: ~/.claude/commands/*.md
|
||||||
|
新Location: ~/.claude/commands/sc/*.md
|
||||||
|
|
||||||
|
V3 → V4 移行時の処理
|
||||||
|
"""
|
||||||
|
old_commands_dir = self.install_dir / "commands"
|
||||||
|
new_commands_dir = self.install_dir / "commands" / "sc"
|
||||||
|
|
||||||
|
# 旧場所からファイル検出
|
||||||
|
# 新場所へコピー
|
||||||
|
# 旧場所から削除
|
||||||
|
```
|
||||||
|
|
||||||
|
**理解**:
|
||||||
|
- V3: `/analyze` → V4: `/sc:analyze`
|
||||||
|
- 名前空間衝突を防ぐため `/sc:` プレフィックス
|
||||||
|
|
||||||
|
#### 5. `_post_install()` - メタデータ更新
|
||||||
|
```python
|
||||||
|
def _post_install(self) -> bool:
|
||||||
|
# メタデータ更新
|
||||||
|
metadata_mods = self.get_metadata_modifications()
|
||||||
|
self.settings_manager.update_metadata(metadata_mods)
|
||||||
|
|
||||||
|
# コンポーネント登録
|
||||||
|
self.settings_manager.add_component_registration(
|
||||||
|
"commands",
|
||||||
|
{
|
||||||
|
"version": __version__,
|
||||||
|
"category": "commands",
|
||||||
|
"files_count": len(self.component_files),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
**理解**:
|
||||||
|
- `~/.claude/.superclaude.json` 更新
|
||||||
|
- インストール済みコンポーネント記録
|
||||||
|
- バージョン管理
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📋 実際のファイルマッピング
|
||||||
|
|
||||||
|
### Source(このプロジェクト)
|
||||||
|
```
|
||||||
|
~/github/SuperClaude_Framework/superclaude/commands/
|
||||||
|
├── pm.md # PM Agent定義
|
||||||
|
├── implement.md # Implement コマンド
|
||||||
|
├── test.md # Test コマンド
|
||||||
|
├── analyze.md # Analyze コマンド
|
||||||
|
├── research.md # Research コマンド
|
||||||
|
├── ...(全26コマンド)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Destination(ユーザー環境)
|
||||||
|
```
|
||||||
|
~/.claude/commands/sc/
|
||||||
|
├── pm.md # → /sc:pm で実行可能
|
||||||
|
├── implement.md # → /sc:implement で実行可能
|
||||||
|
├── test.md # → /sc:test で実行可能
|
||||||
|
├── analyze.md # → /sc:analyze で実行可能
|
||||||
|
├── research.md # → /sc:research で実行可能
|
||||||
|
├── ...(全26コマンド)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Claude Code動作
|
||||||
|
```
|
||||||
|
User: /sc:pm "Build authentication"
|
||||||
|
|
||||||
|
Claude Code:
|
||||||
|
1. ~/.claude/commands/sc/pm.md 読み込み
|
||||||
|
2. YAML frontmatter 解析
|
||||||
|
3. Markdown本文を展開
|
||||||
|
4. PM Agent として実行
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔧 他のコンポーネント
|
||||||
|
|
||||||
|
### Modes Component
|
||||||
|
```python
|
||||||
|
File: setup/components/modes.py
|
||||||
|
Source: superclaude/modes/*.md
|
||||||
|
Target: ~/.claude/*.md
|
||||||
|
|
||||||
|
Example:
|
||||||
|
superclaude/modes/MODE_Brainstorming.md
|
||||||
|
↓
|
||||||
|
~/.claude/MODE_Brainstorming.md
|
||||||
|
```
|
||||||
|
|
||||||
|
### Agents Component
|
||||||
|
```python
|
||||||
|
File: setup/components/agents.py
|
||||||
|
Source: superclaude/agents/*.md
|
||||||
|
Target: ~/.claude/agents/*.md(または統合先)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Core Component
|
||||||
|
```python
|
||||||
|
File: setup/components/core.py
|
||||||
|
Source: superclaude/core/CLAUDE.md
|
||||||
|
Target: ~/.claude/CLAUDE.md
|
||||||
|
|
||||||
|
これがグローバル設定!
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 💡 開発時の注意点
|
||||||
|
|
||||||
|
### ✅ 正しい変更方法
|
||||||
|
```bash
|
||||||
|
# 1. ソースファイルを変更(Git管理)
|
||||||
|
cd ~/github/SuperClaude_Framework
|
||||||
|
vim superclaude/commands/pm.md
|
||||||
|
|
||||||
|
# 2. テスト追加
|
||||||
|
Write tests/test_pm_command.py
|
||||||
|
|
||||||
|
# 3. テスト実行
|
||||||
|
pytest tests/test_pm_command.py -v
|
||||||
|
|
||||||
|
# 4. コミット
|
||||||
|
git add superclaude/commands/pm.md tests/
|
||||||
|
git commit -m "feat: enhance PM command"
|
||||||
|
|
||||||
|
# 5. 開発版インストール
|
||||||
|
pip install -e .
|
||||||
|
# または
|
||||||
|
SuperClaude install --dev
|
||||||
|
|
||||||
|
# 6. 動作確認
|
||||||
|
claude
|
||||||
|
/sc:pm "test"
|
||||||
|
```
|
||||||
|
|
||||||
|
### ❌ 間違った変更方法
|
||||||
|
```bash
|
||||||
|
# ダメ!Git管理外を直接変更
|
||||||
|
vim ~/.claude/commands/sc/pm.md
|
||||||
|
|
||||||
|
# 変更は次回インストール時に上書きされる
|
||||||
|
SuperClaude install # ← 変更が消える!
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 PM Mode改善の正しいフロー
|
||||||
|
|
||||||
|
### Phase 1: 理解(今ここ!)
|
||||||
|
```bash
|
||||||
|
✅ setup/components/commands.py 理解完了
|
||||||
|
✅ superclaude/commands/*.md の存在確認完了
|
||||||
|
✅ インストールフロー理解完了
|
||||||
|
```
|
||||||
|
|
||||||
|
### Phase 2: 現在の仕様確認
|
||||||
|
```bash
|
||||||
|
# ソース確認(Git管理)
|
||||||
|
Read superclaude/commands/pm.md
|
||||||
|
|
||||||
|
# インストール後確認(参考用)
|
||||||
|
Read ~/.claude/commands/sc/pm.md
|
||||||
|
|
||||||
|
# 「なるほど、こういう仕様になってるのか」
|
||||||
|
```
|
||||||
|
|
||||||
|
### Phase 3: 改善案作成
|
||||||
|
```bash
|
||||||
|
# このプロジェクト内で(Git管理)
|
||||||
|
Write docs/Development/hypothesis-pm-enhancement-2025-10-14.md
|
||||||
|
|
||||||
|
内容:
|
||||||
|
- 現状の問題(ドキュメント寄りすぎ、PMO機能不足)
|
||||||
|
- 改善案(自律的PDCA、自己評価)
|
||||||
|
- 実装方針
|
||||||
|
- 期待される効果
|
||||||
|
```
|
||||||
|
|
||||||
|
### Phase 4: 実装
|
||||||
|
```bash
|
||||||
|
# ソースファイル修正
|
||||||
|
Edit superclaude/commands/pm.md
|
||||||
|
|
||||||
|
変更例:
|
||||||
|
- PDCA自動実行の強化
|
||||||
|
- docs/ ディレクトリ活用の明示
|
||||||
|
- 自己評価ステップの追加
|
||||||
|
- エラー時再学習フローの追加
|
||||||
|
```
|
||||||
|
|
||||||
|
### Phase 5: テスト・検証
|
||||||
|
```bash
|
||||||
|
# テスト追加
|
||||||
|
Write tests/test_pm_enhanced.py
|
||||||
|
|
||||||
|
# テスト実行
|
||||||
|
pytest tests/test_pm_enhanced.py -v
|
||||||
|
|
||||||
|
# 開発版インストール
|
||||||
|
SuperClaude install --dev
|
||||||
|
|
||||||
|
# 実際に使ってみる
|
||||||
|
claude
|
||||||
|
/sc:pm "test enhanced workflow"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Phase 6: 学習記録
|
||||||
|
```bash
|
||||||
|
# 成功パターン記録
|
||||||
|
Write docs/patterns/pm-autonomous-workflow.md
|
||||||
|
|
||||||
|
# 失敗があれば記録
|
||||||
|
Write docs/mistakes/mistake-2025-10-14.md
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📊 Component間の依存関係
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
Commands Component:
|
||||||
|
depends_on: ["core"]
|
||||||
|
|
||||||
|
Core Component:
|
||||||
|
provides:
|
||||||
|
- ~/.claude/CLAUDE.md(グローバル設定)
|
||||||
|
- 基本ディレクトリ構造
|
||||||
|
|
||||||
|
Modes Component:
|
||||||
|
depends_on: ["core"]
|
||||||
|
provides:
|
||||||
|
- ~/.claude/MODE_*.md
|
||||||
|
|
||||||
|
Agents Component:
|
||||||
|
depends_on: ["core"]
|
||||||
|
provides:
|
||||||
|
- エージェント定義
|
||||||
|
|
||||||
|
MCP Component:
|
||||||
|
depends_on: ["core"]
|
||||||
|
provides:
|
||||||
|
- MCPサーバー設定
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🚀 次のアクション
|
||||||
|
|
||||||
|
理解完了!次は:
|
||||||
|
|
||||||
|
1. ✅ `superclaude/commands/pm.md` の現在の仕様確認
|
||||||
|
2. ✅ 改善提案ドキュメント作成
|
||||||
|
3. ✅ 実装修正(PDCA強化、PMO機能追加)
|
||||||
|
4. ✅ テスト追加・実行
|
||||||
|
5. ✅ 動作確認
|
||||||
|
6. ✅ 学習記録
|
||||||
|
|
||||||
|
このドキュメント自体が**インストールフローの完全理解記録**として機能する。
|
||||||
|
次回のセッションで読めば、同じ説明を繰り返さなくて済む。
|
||||||
341
docs/Development/pm-agent-ideal-workflow.md
Normal file
341
docs/Development/pm-agent-ideal-workflow.md
Normal file
@ -0,0 +1,341 @@
|
|||||||
|
# PM Agent - Ideal Autonomous Workflow
|
||||||
|
|
||||||
|
> **目的**: 何百回も同じ指示を繰り返さないための自律的オーケストレーションシステム
|
||||||
|
|
||||||
|
## 🎯 解決すべき問題
|
||||||
|
|
||||||
|
### 現状の課題
|
||||||
|
- **繰り返し指示**: 同じことを何百回も説明している
|
||||||
|
- **同じミスの反復**: 一度間違えたことを再度間違える
|
||||||
|
- **知識の喪失**: セッションが途切れると学習内容が失われる
|
||||||
|
- **コンテキスト制限**: 限られたコンテキストで効率的に動作できていない
|
||||||
|
|
||||||
|
### あるべき姿
|
||||||
|
**自律的で賢いPM Agent** - ドキュメントから学び、計画し、実行し、検証し、学習を記録するループ
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📋 完璧なワークフロー(理想形)
|
||||||
|
|
||||||
|
### Phase 1: 📖 状況把握(Context Restoration)
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
1. ドキュメント読み込み:
|
||||||
|
優先順位:
|
||||||
|
1. タスク管理ドキュメント → 進捗確認
|
||||||
|
- docs/Development/tasks/current-tasks.md
|
||||||
|
- 前回どこまでやったか
|
||||||
|
- 次に何をすべきか
|
||||||
|
|
||||||
|
2. アーキテクチャドキュメント → 仕組み理解
|
||||||
|
- docs/Development/architecture-*.md
|
||||||
|
- このプロジェクトの構造
|
||||||
|
- インストールフロー
|
||||||
|
- コンポーネント連携
|
||||||
|
|
||||||
|
3. 禁止事項・ルール → 制約確認
|
||||||
|
- CLAUDE.md(グローバル)
|
||||||
|
- PROJECT/CLAUDE.md(プロジェクト固有)
|
||||||
|
- docs/Development/constraints.md
|
||||||
|
|
||||||
|
4. 過去の学び → 同じミスを防ぐ
|
||||||
|
- docs/mistakes/ (失敗記録)
|
||||||
|
- docs/patterns/ (成功パターン)
|
||||||
|
|
||||||
|
2. ユーザーリクエスト理解:
|
||||||
|
- 何をしたいのか
|
||||||
|
- どこまで進んでいるのか
|
||||||
|
- 何が課題なのか
|
||||||
|
```
|
||||||
|
|
||||||
|
### Phase 2: 🔍 調査・分析(Research & Analysis)
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
1. 既存実装の理解:
|
||||||
|
# ソースコード側(Git管理)
|
||||||
|
- setup/components/*.py → インストールロジック
|
||||||
|
- superclaude/ → ランタイムロジック
|
||||||
|
- tests/ → テストパターン
|
||||||
|
|
||||||
|
# インストール後(ユーザー環境・Git管理外)
|
||||||
|
- ~/.claude/commands/sc/ → 実際の配置確認
|
||||||
|
- ~/.claude/*.md → 現在の仕様確認
|
||||||
|
|
||||||
|
理解内容:
|
||||||
|
「なるほど、ここでこう処理されて、
|
||||||
|
こういうファイルが ~/.claude/ に作られるのね」
|
||||||
|
|
||||||
|
2. ベストプラクティス調査:
|
||||||
|
# Deep Research活用
|
||||||
|
- 公式リファレンス確認
|
||||||
|
- 他プロジェクトの実装調査
|
||||||
|
- 最新のベストプラクティス
|
||||||
|
|
||||||
|
気づき:
|
||||||
|
- 「ここ無駄だな」
|
||||||
|
- 「ここ古いな」
|
||||||
|
- 「これはいい実装だな」
|
||||||
|
- 「この共通化できるな」
|
||||||
|
|
||||||
|
3. 重複・改善ポイント発見:
|
||||||
|
- ライブラリの共通化可能性
|
||||||
|
- 重複実装の検出
|
||||||
|
- コード品質向上余地
|
||||||
|
```
|
||||||
|
|
||||||
|
### Phase 3: 📝 計画立案(Planning)
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
1. 改善仮説作成:
|
||||||
|
# このプロジェクト内で(Git管理)
|
||||||
|
File: docs/Development/hypothesis-YYYY-MM-DD.md
|
||||||
|
|
||||||
|
内容:
|
||||||
|
- 現状の問題点
|
||||||
|
- 改善案
|
||||||
|
- 期待される効果(トークン削減、パフォーマンス向上等)
|
||||||
|
- 実装方針
|
||||||
|
- 必要なテスト
|
||||||
|
|
||||||
|
2. ユーザーレビュー:
|
||||||
|
「こういうプランでこんなことをやろうと思っています」
|
||||||
|
|
||||||
|
提示内容:
|
||||||
|
- 調査結果のサマリー
|
||||||
|
- 改善提案(理由付き)
|
||||||
|
- 実装ステップ
|
||||||
|
- 期待される成果
|
||||||
|
|
||||||
|
ユーザー承認待ち → OK出たら実装へ
|
||||||
|
```
|
||||||
|
|
||||||
|
### Phase 4: 🛠️ 実装(Implementation)
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
1. ソースコード修正:
|
||||||
|
# Git管理されているこのプロジェクトで作業
|
||||||
|
cd ~/github/SuperClaude_Framework
|
||||||
|
|
||||||
|
修正対象:
|
||||||
|
- setup/components/*.py → インストールロジック
|
||||||
|
- superclaude/ → ランタイム機能
|
||||||
|
- setup/data/*.json → 設定データ
|
||||||
|
|
||||||
|
# サブエージェント活用
|
||||||
|
- backend-architect: アーキテクチャ実装
|
||||||
|
- refactoring-expert: コード改善
|
||||||
|
- quality-engineer: テスト設計
|
||||||
|
|
||||||
|
2. 実装記録:
|
||||||
|
File: docs/Development/experiment-YYYY-MM-DD.md
|
||||||
|
|
||||||
|
内容:
|
||||||
|
- 試行錯誤の記録
|
||||||
|
- 遭遇したエラー
|
||||||
|
- 解決方法
|
||||||
|
- 気づき
|
||||||
|
```
|
||||||
|
|
||||||
|
### Phase 5: ✅ 検証(Validation)
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
1. テスト作成・実行:
|
||||||
|
# テストを書く
|
||||||
|
Write tests/test_new_feature.py
|
||||||
|
|
||||||
|
# テスト実行
|
||||||
|
pytest tests/test_new_feature.py -v
|
||||||
|
|
||||||
|
# ユーザー要求を満たしているか確認
|
||||||
|
- 期待通りの動作か?
|
||||||
|
- エッジケースは?
|
||||||
|
- パフォーマンスは?
|
||||||
|
|
||||||
|
2. エラー時の対応:
|
||||||
|
エラー発生
|
||||||
|
↓
|
||||||
|
公式リファレンス確認
|
||||||
|
「このエラー何でだろう?」
|
||||||
|
「ここの定義違ってたんだ」
|
||||||
|
↓
|
||||||
|
修正
|
||||||
|
↓
|
||||||
|
再テスト
|
||||||
|
↓
|
||||||
|
合格まで繰り返し
|
||||||
|
|
||||||
|
3. 動作確認:
|
||||||
|
# インストールして実際の環境でテスト
|
||||||
|
SuperClaude install --dev
|
||||||
|
|
||||||
|
# 動作確認
|
||||||
|
claude # 起動して実際に試す
|
||||||
|
```
|
||||||
|
|
||||||
|
### Phase 6: 📚 学習記録(Learning Documentation)
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
1. 成功パターン記録:
|
||||||
|
File: docs/patterns/[pattern-name].md
|
||||||
|
|
||||||
|
内容:
|
||||||
|
- どんな問題を解決したか
|
||||||
|
- どう実装したか
|
||||||
|
- なぜこのアプローチか
|
||||||
|
- 再利用可能なパターン
|
||||||
|
|
||||||
|
2. 失敗・ミス記録:
|
||||||
|
File: docs/mistakes/mistake-YYYY-MM-DD.md
|
||||||
|
|
||||||
|
内容:
|
||||||
|
- どんなミスをしたか
|
||||||
|
- なぜ起きたか
|
||||||
|
- 防止策
|
||||||
|
- チェックリスト
|
||||||
|
|
||||||
|
3. タスク更新:
|
||||||
|
File: docs/Development/tasks/current-tasks.md
|
||||||
|
|
||||||
|
内容:
|
||||||
|
- 完了したタスク
|
||||||
|
- 次のタスク
|
||||||
|
- 進捗状況
|
||||||
|
- ブロッカー
|
||||||
|
|
||||||
|
4. グローバルパターン更新:
|
||||||
|
必要に応じて:
|
||||||
|
- CLAUDE.md更新(グローバルルール)
|
||||||
|
- PROJECT/CLAUDE.md更新(プロジェクト固有)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Phase 7: 🔄 セッション保存(Session Persistence)
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
1. Serenaメモリー保存:
|
||||||
|
write_memory("session_summary", 完了内容)
|
||||||
|
write_memory("next_actions", 次のアクション)
|
||||||
|
write_memory("learnings", 学んだこと)
|
||||||
|
|
||||||
|
2. ドキュメント整理:
|
||||||
|
- docs/temp/ → docs/patterns/ or docs/mistakes/
|
||||||
|
- 一時ファイル削除
|
||||||
|
- 正式ドキュメント更新
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔧 活用可能なツール・リソース
|
||||||
|
|
||||||
|
### MCPサーバー(フル活用)
|
||||||
|
- **Sequential**: 複雑な分析・推論
|
||||||
|
- **Context7**: 公式ドキュメント参照
|
||||||
|
- **Tavily**: Deep Research(ベストプラクティス調査)
|
||||||
|
- **Serena**: セッション永続化、メモリー管理
|
||||||
|
- **Playwright**: E2Eテスト、動作確認
|
||||||
|
- **Morphllm**: 一括コード変換
|
||||||
|
- **Magic**: UI生成(必要時)
|
||||||
|
- **Chrome DevTools**: パフォーマンス測定
|
||||||
|
|
||||||
|
### サブエージェント(適材適所)
|
||||||
|
- **requirements-analyst**: 要件整理
|
||||||
|
- **system-architect**: アーキテクチャ設計
|
||||||
|
- **backend-architect**: バックエンド実装
|
||||||
|
- **refactoring-expert**: コード改善
|
||||||
|
- **security-engineer**: セキュリティ検証
|
||||||
|
- **quality-engineer**: テスト設計・実行
|
||||||
|
- **performance-engineer**: パフォーマンス最適化
|
||||||
|
- **technical-writer**: ドキュメント執筆
|
||||||
|
|
||||||
|
### 他プロジェクト統合
|
||||||
|
- **makefile-global**: Makefile標準化パターン
|
||||||
|
- **airis-mcp-gateway**: MCPゲートウェイ統合
|
||||||
|
- その他有用なパターンは積極的に取り込む
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 重要な原則
|
||||||
|
|
||||||
|
### Git管理の区別
|
||||||
|
```yaml
|
||||||
|
✅ Git管理されている(変更追跡可能):
|
||||||
|
- ~/github/SuperClaude_Framework/
|
||||||
|
- ここで全ての変更を行う
|
||||||
|
- コミット履歴で追跡
|
||||||
|
- PR提出可能
|
||||||
|
|
||||||
|
❌ Git管理外(変更追跡不可):
|
||||||
|
- ~/.claude/
|
||||||
|
- 読むだけ、理解のみ
|
||||||
|
- テスト時のみ一時変更(必ず戻す!)
|
||||||
|
```
|
||||||
|
|
||||||
|
### テスト時の注意
|
||||||
|
```bash
|
||||||
|
# テスト前: 必ずバックアップ
|
||||||
|
cp ~/.claude/commands/sc/pm.md ~/.claude/commands/sc/pm.md.backup
|
||||||
|
|
||||||
|
# テスト実行
|
||||||
|
# ... 検証 ...
|
||||||
|
|
||||||
|
# テスト後: 必ず復元!!
|
||||||
|
mv ~/.claude/commands/sc/pm.md.backup ~/.claude/commands/sc/pm.md
|
||||||
|
```
|
||||||
|
|
||||||
|
### ドキュメント構造
|
||||||
|
```
|
||||||
|
docs/
|
||||||
|
├── Development/ # 開発用ドキュメント
|
||||||
|
│ ├── tasks/ # タスク管理
|
||||||
|
│ ├── architecture-*.md # アーキテクチャ
|
||||||
|
│ ├── constraints.md # 制約・禁止事項
|
||||||
|
│ ├── hypothesis-*.md # 改善仮説
|
||||||
|
│ └── experiment-*.md # 実験記録
|
||||||
|
├── patterns/ # 成功パターン(清書後)
|
||||||
|
├── mistakes/ # 失敗記録と防止策
|
||||||
|
└── (既存のUser-Guide等)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🚀 実装優先度
|
||||||
|
|
||||||
|
### Phase 1(必須)
|
||||||
|
1. ドキュメント構造整備
|
||||||
|
2. タスク管理システム
|
||||||
|
3. セッション復元ワークフロー
|
||||||
|
|
||||||
|
### Phase 2(重要)
|
||||||
|
4. 自己評価・検証ループ
|
||||||
|
5. 学習記録自動化
|
||||||
|
6. エラー時再学習フロー
|
||||||
|
|
||||||
|
### Phase 3(強化)
|
||||||
|
7. PMO機能(重複検出、共通化提案)
|
||||||
|
8. パフォーマンス測定・改善
|
||||||
|
9. 他プロジェクト統合
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📊 成功指標
|
||||||
|
|
||||||
|
### 定量的指標
|
||||||
|
- **繰り返し指示の削減**: 同じ指示 → 50%削減目標
|
||||||
|
- **ミス再発率**: 同じミス → 80%削減目標
|
||||||
|
- **セッション復元時間**: <30秒で前回の続きから開始
|
||||||
|
|
||||||
|
### 定性的指標
|
||||||
|
- ユーザーが「前回の続きから」と言うだけで再開できる
|
||||||
|
- 過去のミスを自動的に避けられる
|
||||||
|
- 公式ドキュメント参照が自動化されている
|
||||||
|
- 実装→テスト→検証が自律的に回る
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 💡 次のアクション
|
||||||
|
|
||||||
|
このドキュメント作成後:
|
||||||
|
1. 既存のインストールロジック理解(setup/components/)
|
||||||
|
2. タスク管理ドキュメント作成(docs/Development/tasks/)
|
||||||
|
3. PM Agent実装修正(このワークフローを実際に実装)
|
||||||
|
|
||||||
|
このドキュメント自体が**PM Agentの憲法**となる。
|
||||||
477
docs/Development/pm-agent-integration.md
Normal file
477
docs/Development/pm-agent-integration.md
Normal file
@ -0,0 +1,477 @@
|
|||||||
|
# PM Agent Mode Integration Guide
|
||||||
|
|
||||||
|
**Last Updated**: 2025-10-14
|
||||||
|
**Target Version**: 4.2.0
|
||||||
|
**Status**: Implementation Guide
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📋 Overview
|
||||||
|
|
||||||
|
This guide provides step-by-step procedures for integrating PM Agent mode as SuperClaude's always-active meta-layer with session lifecycle management, PDCA self-evaluation, and systematic knowledge management.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 Integration Goals
|
||||||
|
|
||||||
|
1. **Session Lifecycle**: Auto-activation at session start with context restoration
|
||||||
|
2. **PDCA Engine**: Automated Plan-Do-Check-Act cycle execution
|
||||||
|
3. **Memory Operations**: Serena MCP integration for session persistence
|
||||||
|
4. **Documentation Strategy**: Systematic knowledge evolution
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📐 Architecture Integration
|
||||||
|
|
||||||
|
### PM Agent Position
|
||||||
|
|
||||||
|
```
|
||||||
|
┌──────────────────────────────────────────┐
|
||||||
|
│ PM Agent Mode (Meta-Layer) │
|
||||||
|
│ • Always Active │
|
||||||
|
│ • Session Management │
|
||||||
|
│ • PDCA Self-Evaluation │
|
||||||
|
└──────────────┬───────────────────────────┘
|
||||||
|
↓
|
||||||
|
[Specialist Agents Layer]
|
||||||
|
↓
|
||||||
|
[Commands & Modes Layer]
|
||||||
|
↓
|
||||||
|
[MCP Tool Layer]
|
||||||
|
```
|
||||||
|
|
||||||
|
See: [ARCHITECTURE.md](./ARCHITECTURE.md) for full system architecture
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔧 Phase 2: Core Implementation
|
||||||
|
|
||||||
|
### File Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
superclaude/
|
||||||
|
├── Commands/
|
||||||
|
│ └── pm.md # ✅ Already updated
|
||||||
|
├── Agents/
|
||||||
|
│ └── pm-agent.md # ✅ Already updated
|
||||||
|
└── Core/
|
||||||
|
├── __init__.py # Module initialization
|
||||||
|
├── session_lifecycle.py # 🆕 Session management
|
||||||
|
├── pdca_engine.py # 🆕 PDCA automation
|
||||||
|
└── memory_ops.py # 🆕 Memory operations
|
||||||
|
```
|
||||||
|
|
||||||
|
### Implementation Order
|
||||||
|
|
||||||
|
1. `memory_ops.py` - Serena MCP wrapper (foundation)
|
||||||
|
2. `session_lifecycle.py` - Session management (depends on memory_ops)
|
||||||
|
3. `pdca_engine.py` - PDCA automation (depends on memory_ops)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1️⃣ memory_ops.py Implementation
|
||||||
|
|
||||||
|
### Purpose
|
||||||
|
Wrapper for Serena MCP memory operations with error handling and fallback.
|
||||||
|
|
||||||
|
### Key Functions
|
||||||
|
|
||||||
|
```python
|
||||||
|
# superclaude/Core/memory_ops.py
|
||||||
|
|
||||||
|
class MemoryOperations:
|
||||||
|
"""Serena MCP memory operations wrapper"""
|
||||||
|
|
||||||
|
def list_memories() -> List[str]:
|
||||||
|
"""List all available memories"""
|
||||||
|
|
||||||
|
def read_memory(key: str) -> Optional[Dict]:
|
||||||
|
"""Read memory by key"""
|
||||||
|
|
||||||
|
def write_memory(key: str, value: Dict) -> bool:
|
||||||
|
"""Write memory with key"""
|
||||||
|
|
||||||
|
def delete_memory(key: str) -> bool:
|
||||||
|
"""Delete memory by key"""
|
||||||
|
```
|
||||||
|
|
||||||
|
### Integration Points
|
||||||
|
- Connect to Serena MCP server
|
||||||
|
- Handle connection errors gracefully
|
||||||
|
- Provide fallback for offline mode
|
||||||
|
- Validate memory structure
|
||||||
|
|
||||||
|
### Testing
|
||||||
|
```bash
|
||||||
|
pytest tests/test_memory_ops.py -v
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2️⃣ session_lifecycle.py Implementation
|
||||||
|
|
||||||
|
### Purpose
|
||||||
|
Auto-activation at session start, context restoration, user report generation.
|
||||||
|
|
||||||
|
### Key Functions
|
||||||
|
|
||||||
|
```python
|
||||||
|
# superclaude/Core/session_lifecycle.py
|
||||||
|
|
||||||
|
class SessionLifecycle:
|
||||||
|
"""Session lifecycle management"""
|
||||||
|
|
||||||
|
def on_session_start():
|
||||||
|
"""Hook for session start (auto-activation)"""
|
||||||
|
# 1. list_memories()
|
||||||
|
# 2. read_memory("pm_context")
|
||||||
|
# 3. read_memory("last_session")
|
||||||
|
# 4. read_memory("next_actions")
|
||||||
|
# 5. generate_user_report()
|
||||||
|
|
||||||
|
def generate_user_report() -> str:
|
||||||
|
"""Generate user report (前回/進捗/今回/課題)"""
|
||||||
|
|
||||||
|
def on_session_end():
|
||||||
|
"""Hook for session end (checkpoint save)"""
|
||||||
|
# 1. write_memory("last_session", summary)
|
||||||
|
# 2. write_memory("next_actions", todos)
|
||||||
|
# 3. write_memory("pm_context", complete_state)
|
||||||
|
```
|
||||||
|
|
||||||
|
### User Report Format
|
||||||
|
```
|
||||||
|
前回: [last session summary]
|
||||||
|
進捗: [current progress status]
|
||||||
|
今回: [planned next actions]
|
||||||
|
課題: [blockers or issues]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Integration Points
|
||||||
|
- Hook into Claude Code session start
|
||||||
|
- Read memories using memory_ops
|
||||||
|
- Generate human-readable report
|
||||||
|
- Handle missing or corrupted memory
|
||||||
|
|
||||||
|
### Testing
|
||||||
|
```bash
|
||||||
|
pytest tests/test_session_lifecycle.py -v
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3️⃣ pdca_engine.py Implementation
|
||||||
|
|
||||||
|
### Purpose
|
||||||
|
Automate PDCA cycle execution with documentation generation.
|
||||||
|
|
||||||
|
### Key Functions
|
||||||
|
|
||||||
|
```python
|
||||||
|
# superclaude/Core/pdca_engine.py
|
||||||
|
|
||||||
|
class PDCAEngine:
|
||||||
|
"""PDCA cycle automation"""
|
||||||
|
|
||||||
|
def plan_phase(goal: str):
|
||||||
|
"""Generate hypothesis (仮説)"""
|
||||||
|
# 1. write_memory("plan", goal)
|
||||||
|
# 2. Create docs/temp/hypothesis-YYYY-MM-DD.md
|
||||||
|
|
||||||
|
def do_phase():
|
||||||
|
"""Track experimentation (実験)"""
|
||||||
|
# 1. TodoWrite tracking
|
||||||
|
# 2. write_memory("checkpoint", progress) every 30min
|
||||||
|
# 3. Update docs/temp/experiment-YYYY-MM-DD.md
|
||||||
|
|
||||||
|
def check_phase():
|
||||||
|
"""Self-evaluation (評価)"""
|
||||||
|
# 1. think_about_task_adherence()
|
||||||
|
# 2. think_about_whether_you_are_done()
|
||||||
|
# 3. Create docs/temp/lessons-YYYY-MM-DD.md
|
||||||
|
|
||||||
|
def act_phase():
|
||||||
|
"""Knowledge extraction (改善)"""
|
||||||
|
# 1. Success → docs/patterns/[pattern-name].md
|
||||||
|
# 2. Failure → docs/mistakes/mistake-YYYY-MM-DD.md
|
||||||
|
# 3. Update CLAUDE.md if global pattern
|
||||||
|
```
|
||||||
|
|
||||||
|
### Documentation Templates
|
||||||
|
|
||||||
|
**hypothesis-template.md**:
|
||||||
|
```markdown
|
||||||
|
# Hypothesis: [Goal Description]
|
||||||
|
|
||||||
|
Date: YYYY-MM-DD
|
||||||
|
Status: Planning
|
||||||
|
|
||||||
|
## Goal
|
||||||
|
What are we trying to accomplish?
|
||||||
|
|
||||||
|
## Approach
|
||||||
|
How will we implement this?
|
||||||
|
|
||||||
|
## Success Criteria
|
||||||
|
How do we know when we're done?
|
||||||
|
|
||||||
|
## Potential Risks
|
||||||
|
What could go wrong?
|
||||||
|
```
|
||||||
|
|
||||||
|
**experiment-template.md**:
|
||||||
|
```markdown
|
||||||
|
# Experiment Log: [Implementation Name]
|
||||||
|
|
||||||
|
Date: YYYY-MM-DD
|
||||||
|
Status: In Progress
|
||||||
|
|
||||||
|
## Implementation Steps
|
||||||
|
- [ ] Step 1
|
||||||
|
- [ ] Step 2
|
||||||
|
|
||||||
|
## Errors Encountered
|
||||||
|
- Error 1: Description, solution
|
||||||
|
|
||||||
|
## Solutions Applied
|
||||||
|
- Solution 1: Description, result
|
||||||
|
|
||||||
|
## Checkpoint Saves
|
||||||
|
- 10:00: [progress snapshot]
|
||||||
|
- 10:30: [progress snapshot]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Integration Points
|
||||||
|
- Create docs/ directory templates
|
||||||
|
- Integrate with TodoWrite
|
||||||
|
- Call Serena MCP think operations
|
||||||
|
- Generate documentation files
|
||||||
|
|
||||||
|
### Testing
|
||||||
|
```bash
|
||||||
|
pytest tests/test_pdca_engine.py -v
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔌 Phase 3: Serena MCP Integration
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
```bash
|
||||||
|
# Install Serena MCP server
|
||||||
|
# See: docs/troubleshooting/serena-installation.md
|
||||||
|
```
|
||||||
|
|
||||||
|
### Configuration
|
||||||
|
```json
|
||||||
|
// ~/.claude/.claude.json
|
||||||
|
{
|
||||||
|
"mcpServers": {
|
||||||
|
"serena": {
|
||||||
|
"command": "uv",
|
||||||
|
"args": ["run", "serena-mcp"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Memory Structure
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"pm_context": {
|
||||||
|
"project": "SuperClaude_Framework",
|
||||||
|
"current_phase": "Phase 2",
|
||||||
|
"architecture": "Context-Oriented Configuration",
|
||||||
|
"patterns": ["PDCA Cycle", "Session Lifecycle"]
|
||||||
|
},
|
||||||
|
"last_session": {
|
||||||
|
"date": "2025-10-14",
|
||||||
|
"accomplished": ["Phase 1 complete"],
|
||||||
|
"issues": ["Serena MCP not configured"],
|
||||||
|
"learned": ["Session Lifecycle pattern"]
|
||||||
|
},
|
||||||
|
"next_actions": [
|
||||||
|
"Implement session_lifecycle.py",
|
||||||
|
"Configure Serena MCP",
|
||||||
|
"Test memory operations"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Testing Serena Connection
|
||||||
|
```bash
|
||||||
|
# Test memory operations
|
||||||
|
python -m SuperClaude.Core.memory_ops --test
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📁 Phase 4: Documentation Strategy
|
||||||
|
|
||||||
|
### Directory Structure
|
||||||
|
```
|
||||||
|
docs/
|
||||||
|
├── temp/ # Temporary (7-day lifecycle)
|
||||||
|
│ ├── hypothesis-YYYY-MM-DD.md
|
||||||
|
│ ├── experiment-YYYY-MM-DD.md
|
||||||
|
│ └── lessons-YYYY-MM-DD.md
|
||||||
|
├── patterns/ # Formal patterns (永久保存)
|
||||||
|
│ └── [pattern-name].md
|
||||||
|
└── mistakes/ # Mistake records (永久保存)
|
||||||
|
└── mistake-YYYY-MM-DD.md
|
||||||
|
```
|
||||||
|
|
||||||
|
### Lifecycle Automation
|
||||||
|
```bash
|
||||||
|
# Create cleanup script
|
||||||
|
scripts/cleanup_temp_docs.sh
|
||||||
|
|
||||||
|
# Run daily via cron
|
||||||
|
0 0 * * * /path/to/scripts/cleanup_temp_docs.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
### Migration Scripts
|
||||||
|
```bash
|
||||||
|
# Migrate successful experiments to patterns
|
||||||
|
python scripts/migrate_to_patterns.py
|
||||||
|
|
||||||
|
# Migrate failures to mistakes
|
||||||
|
python scripts/migrate_to_mistakes.py
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🚀 Phase 5: Auto-Activation (Research Needed)
|
||||||
|
|
||||||
|
### Research Questions
|
||||||
|
1. How does Claude Code handle initialization?
|
||||||
|
2. Are there plugin hooks available?
|
||||||
|
3. Can we intercept session start events?
|
||||||
|
|
||||||
|
### Implementation Plan (TBD)
|
||||||
|
Once research complete, implement auto-activation hooks:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# superclaude/Core/auto_activation.py (future)
|
||||||
|
|
||||||
|
def on_claude_code_start():
|
||||||
|
"""Auto-activate PM Agent at session start"""
|
||||||
|
session_lifecycle.on_session_start()
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ✅ Implementation Checklist
|
||||||
|
|
||||||
|
### Phase 2: Core Implementation
|
||||||
|
- [ ] Implement `memory_ops.py`
|
||||||
|
- [ ] Write unit tests for memory_ops
|
||||||
|
- [ ] Implement `session_lifecycle.py`
|
||||||
|
- [ ] Write unit tests for session_lifecycle
|
||||||
|
- [ ] Implement `pdca_engine.py`
|
||||||
|
- [ ] Write unit tests for pdca_engine
|
||||||
|
- [ ] Integration testing
|
||||||
|
|
||||||
|
### Phase 3: Serena MCP
|
||||||
|
- [ ] Install Serena MCP server
|
||||||
|
- [ ] Configure `.claude.json`
|
||||||
|
- [ ] Test memory operations
|
||||||
|
- [ ] Test think operations
|
||||||
|
- [ ] Test cross-session persistence
|
||||||
|
|
||||||
|
### Phase 4: Documentation Strategy
|
||||||
|
- [ ] Create `docs/temp/` template
|
||||||
|
- [ ] Create `docs/patterns/` template
|
||||||
|
- [ ] Create `docs/mistakes/` template
|
||||||
|
- [ ] Implement lifecycle automation
|
||||||
|
- [ ] Create migration scripts
|
||||||
|
|
||||||
|
### Phase 5: Auto-Activation
|
||||||
|
- [ ] Research Claude Code hooks
|
||||||
|
- [ ] Design auto-activation system
|
||||||
|
- [ ] Implement auto-activation
|
||||||
|
- [ ] Test session start behavior
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🧪 Testing Strategy
|
||||||
|
|
||||||
|
### Unit Tests
|
||||||
|
```bash
|
||||||
|
tests/
|
||||||
|
├── test_memory_ops.py # Memory operations
|
||||||
|
├── test_session_lifecycle.py # Session management
|
||||||
|
└── test_pdca_engine.py # PDCA automation
|
||||||
|
```
|
||||||
|
|
||||||
|
### Integration Tests
|
||||||
|
```bash
|
||||||
|
tests/integration/
|
||||||
|
├── test_pm_agent_flow.py # End-to-end PM Agent
|
||||||
|
├── test_serena_integration.py # Serena MCP integration
|
||||||
|
└── test_cross_session.py # Session persistence
|
||||||
|
```
|
||||||
|
|
||||||
|
### Manual Testing
|
||||||
|
1. Start new session → Verify context restoration
|
||||||
|
2. Work on task → Verify checkpoint saves
|
||||||
|
3. End session → Verify state preservation
|
||||||
|
4. Restart → Verify seamless resumption
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📊 Success Criteria
|
||||||
|
|
||||||
|
### Functional
|
||||||
|
- [ ] PM Agent activates at session start
|
||||||
|
- [ ] Context restores from memory
|
||||||
|
- [ ] User report generates correctly
|
||||||
|
- [ ] PDCA cycle executes automatically
|
||||||
|
- [ ] Documentation strategy works
|
||||||
|
|
||||||
|
### Performance
|
||||||
|
- [ ] Session start delay <500ms
|
||||||
|
- [ ] Memory operations <100ms
|
||||||
|
- [ ] Context restoration reliable (>99%)
|
||||||
|
|
||||||
|
### Quality
|
||||||
|
- [ ] Test coverage >90%
|
||||||
|
- [ ] No regression in existing features
|
||||||
|
- [ ] Documentation complete
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔧 Troubleshooting
|
||||||
|
|
||||||
|
### Common Issues
|
||||||
|
|
||||||
|
**"Serena MCP not connecting"**
|
||||||
|
- Check server installation
|
||||||
|
- Verify `.claude.json` configuration
|
||||||
|
- Test connection: `claude mcp list`
|
||||||
|
|
||||||
|
**"Memory operations failing"**
|
||||||
|
- Check network connection
|
||||||
|
- Verify Serena server running
|
||||||
|
- Check error logs
|
||||||
|
|
||||||
|
**"Context not restoring"**
|
||||||
|
- Verify memory structure
|
||||||
|
- Check `pm_context` exists
|
||||||
|
- Test with fresh memory
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📚 References
|
||||||
|
|
||||||
|
- [ARCHITECTURE.md](./ARCHITECTURE.md) - System architecture
|
||||||
|
- [ROADMAP.md](./ROADMAP.md) - Development roadmap
|
||||||
|
- [pm-agent-implementation-status.md](../pm-agent-implementation-status.md) - Status tracking
|
||||||
|
- [Commands/pm.md](../../superclaude/Commands/pm.md) - PM Agent command
|
||||||
|
- [Agents/pm-agent.md](../../superclaude/Agents/pm-agent.md) - PM Agent persona
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Last Verified**: 2025-10-14
|
||||||
|
**Next Review**: 2025-10-21 (1 week)
|
||||||
|
**Version**: 4.1.5
|
||||||
368
docs/Development/project-structure-understanding.md
Normal file
368
docs/Development/project-structure-understanding.md
Normal file
@ -0,0 +1,368 @@
|
|||||||
|
# SuperClaude Framework - Project Structure Understanding
|
||||||
|
|
||||||
|
> **Critical Understanding**: このプロジェクトとインストール後の環境の関係
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🏗️ 2つの世界の区別
|
||||||
|
|
||||||
|
### 1. このプロジェクト(Git管理・開発環境)
|
||||||
|
|
||||||
|
**Location**: `~/github/SuperClaude_Framework/`
|
||||||
|
|
||||||
|
**Role**: ソースコード・開発・テスト
|
||||||
|
|
||||||
|
```
|
||||||
|
SuperClaude_Framework/
|
||||||
|
├── setup/ # インストーラーロジック
|
||||||
|
│ ├── components/ # コンポーネント定義(何をインストールするか)
|
||||||
|
│ ├── data/ # 設定データ(JSON/YAML)
|
||||||
|
│ ├── cli/ # CLIインターフェース
|
||||||
|
│ ├── utils/ # ユーティリティ関数
|
||||||
|
│ └── services/ # サービスロジック
|
||||||
|
│
|
||||||
|
├── superclaude/ # ランタイムロジック(実行時の動作)
|
||||||
|
│ ├── core/ # コア機能
|
||||||
|
│ ├── modes/ # 行動モード
|
||||||
|
│ ├── agents/ # エージェント定義
|
||||||
|
│ ├── mcp/ # MCPサーバー統合
|
||||||
|
│ └── commands/ # コマンド実装
|
||||||
|
│
|
||||||
|
├── tests/ # テストコード
|
||||||
|
├── docs/ # 開発者向けドキュメント
|
||||||
|
├── pyproject.toml # Python設定
|
||||||
|
└── package.json # npm設定
|
||||||
|
```
|
||||||
|
|
||||||
|
**Operations**:
|
||||||
|
- ✅ ソースコード変更
|
||||||
|
- ✅ Git コミット・PR
|
||||||
|
- ✅ テスト実行
|
||||||
|
- ✅ ドキュメント作成
|
||||||
|
- ✅ バージョン管理
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 2. インストール後(ユーザー環境・Git管理外)
|
||||||
|
|
||||||
|
**Location**: `~/.claude/`
|
||||||
|
|
||||||
|
**Role**: 実際に動作する設定・コマンド(ユーザー環境)
|
||||||
|
|
||||||
|
```
|
||||||
|
~/.claude/
|
||||||
|
├── commands/
|
||||||
|
│ └── sc/ # スラッシュコマンド(インストール後)
|
||||||
|
│ ├── pm.md
|
||||||
|
│ ├── implement.md
|
||||||
|
│ ├── test.md
|
||||||
|
│ └── ... (26 commands)
|
||||||
|
│
|
||||||
|
├── CLAUDE.md # グローバル設定(インストール後)
|
||||||
|
├── *.md # モード定義(インストール後)
|
||||||
|
│ ├── MODE_Brainstorming.md
|
||||||
|
│ ├── MODE_Orchestration.md
|
||||||
|
│ └── ...
|
||||||
|
│
|
||||||
|
└── .claude.json # Claude Code設定
|
||||||
|
```
|
||||||
|
|
||||||
|
**Operations**:
|
||||||
|
- ✅ **読むだけ**(理解・確認用)
|
||||||
|
- ✅ 動作確認
|
||||||
|
- ⚠️ テスト時のみ一時変更(**必ず元に戻す!**)
|
||||||
|
- ❌ 永続的な変更禁止(Git追跡不可)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔄 インストールフロー
|
||||||
|
|
||||||
|
### ユーザー操作
|
||||||
|
```bash
|
||||||
|
# 1. インストール
|
||||||
|
pipx install SuperClaude
|
||||||
|
# または
|
||||||
|
npm install -g @bifrost_inc/superclaude
|
||||||
|
|
||||||
|
# 2. セットアップ実行
|
||||||
|
SuperClaude install
|
||||||
|
```
|
||||||
|
|
||||||
|
### 内部処理(setup/が実行)
|
||||||
|
```python
|
||||||
|
# setup/components/*.py が実行される
|
||||||
|
|
||||||
|
1. ~/.claude/ ディレクトリ作成
|
||||||
|
2. commands/sc/ にスラッシュコマンド配置
|
||||||
|
3. CLAUDE.md と各種 *.md 配置
|
||||||
|
4. .claude.json 更新
|
||||||
|
5. MCPサーバー設定
|
||||||
|
```
|
||||||
|
|
||||||
|
### 結果
|
||||||
|
- **このプロジェクトのファイル** → **~/.claude/ にコピー**
|
||||||
|
- ユーザーがClaude起動 → `~/.claude/` の設定が読み込まれる
|
||||||
|
- `/sc:pm` 実行 → `~/.claude/commands/sc/pm.md` が展開される
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📝 開発ワークフロー
|
||||||
|
|
||||||
|
### ❌ 間違った方法
|
||||||
|
```bash
|
||||||
|
# Git管理外を直接変更
|
||||||
|
vim ~/.claude/commands/sc/pm.md # ← ダメ!履歴追えない
|
||||||
|
|
||||||
|
# 変更テスト
|
||||||
|
claude # 動作確認
|
||||||
|
|
||||||
|
# 変更が ~/.claude/ に残る
|
||||||
|
# → 元に戻すの忘れる
|
||||||
|
# → 設定がぐちゃぐちゃになる
|
||||||
|
# → Gitで追跡できない
|
||||||
|
```
|
||||||
|
|
||||||
|
### ✅ 正しい方法
|
||||||
|
|
||||||
|
#### Step 1: 既存実装を理解
|
||||||
|
```bash
|
||||||
|
cd ~/github/SuperClaude_Framework
|
||||||
|
|
||||||
|
# インストールロジック確認
|
||||||
|
Read setup/components/commands.py # コマンドのインストール方法
|
||||||
|
Read setup/components/modes.py # モードのインストール方法
|
||||||
|
Read setup/data/commands.json # コマンド定義データ
|
||||||
|
|
||||||
|
# インストール後の状態確認(理解のため)
|
||||||
|
ls ~/.claude/commands/sc/
|
||||||
|
cat ~/.claude/commands/sc/pm.md # 現在の仕様確認
|
||||||
|
|
||||||
|
# 「なるほど、setup/components/commands.py でこう処理されて、
|
||||||
|
# ~/.claude/commands/sc/ に配置されるのね」
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Step 2: 改善案をドキュメント化
|
||||||
|
```bash
|
||||||
|
cd ~/github/SuperClaude_Framework
|
||||||
|
|
||||||
|
# Git管理されているこのプロジェクト内で
|
||||||
|
Write docs/Development/hypothesis-pm-improvement-YYYY-MM-DD.md
|
||||||
|
|
||||||
|
# 内容例:
|
||||||
|
# - 現状の問題
|
||||||
|
# - 改善案
|
||||||
|
# - 実装方針
|
||||||
|
# - 期待される効果
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Step 3: テストが必要な場合
|
||||||
|
```bash
|
||||||
|
# バックアップ作成(必須!)
|
||||||
|
cp ~/.claude/commands/sc/pm.md ~/.claude/commands/sc/pm.md.backup
|
||||||
|
|
||||||
|
# 実験的変更
|
||||||
|
vim ~/.claude/commands/sc/pm.md
|
||||||
|
|
||||||
|
# Claude起動して検証
|
||||||
|
claude
|
||||||
|
# ... 動作確認 ...
|
||||||
|
|
||||||
|
# テスト完了後、必ず復元!!
|
||||||
|
mv ~/.claude/commands/sc/pm.md.backup ~/.claude/commands/sc/pm.md
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Step 4: 本実装
|
||||||
|
```bash
|
||||||
|
cd ~/github/SuperClaude_Framework
|
||||||
|
|
||||||
|
# ソースコード側で変更
|
||||||
|
Edit setup/components/commands.py # インストールロジック修正
|
||||||
|
Edit setup/data/commands/pm.md # コマンド仕様修正
|
||||||
|
|
||||||
|
# テスト追加
|
||||||
|
Write tests/test_pm_command.py
|
||||||
|
|
||||||
|
# テスト実行
|
||||||
|
pytest tests/test_pm_command.py -v
|
||||||
|
|
||||||
|
# コミット(Git履歴に残る)
|
||||||
|
git add setup/ tests/
|
||||||
|
git commit -m "feat: enhance PM command with autonomous workflow"
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Step 5: 動作確認
|
||||||
|
```bash
|
||||||
|
# 開発版インストール
|
||||||
|
cd ~/github/SuperClaude_Framework
|
||||||
|
pip install -e .
|
||||||
|
|
||||||
|
# または
|
||||||
|
SuperClaude install --dev
|
||||||
|
|
||||||
|
# 実際の環境でテスト
|
||||||
|
claude
|
||||||
|
/sc:pm "test request"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 重要なルール
|
||||||
|
|
||||||
|
### Rule 1: Git管理の境界を守る
|
||||||
|
- **変更**: このプロジェクト内のみ
|
||||||
|
- **確認**: `~/.claude/` は読むだけ
|
||||||
|
- **テスト**: バックアップ → 変更 → 復元
|
||||||
|
|
||||||
|
### Rule 2: テスト時は必ず復元
|
||||||
|
```bash
|
||||||
|
# テスト前
|
||||||
|
cp original backup
|
||||||
|
|
||||||
|
# テスト
|
||||||
|
# ... 実験 ...
|
||||||
|
|
||||||
|
# テスト後(必須!)
|
||||||
|
mv backup original
|
||||||
|
```
|
||||||
|
|
||||||
|
### Rule 3: ドキュメント駆動開発
|
||||||
|
1. 理解 → docs/Development/ に記録
|
||||||
|
2. 仮説 → docs/Development/hypothesis-*.md
|
||||||
|
3. 実験 → docs/Development/experiment-*.md
|
||||||
|
4. 成功 → docs/patterns/
|
||||||
|
5. 失敗 → docs/mistakes/
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📚 理解すべきファイル
|
||||||
|
|
||||||
|
### インストーラー側(setup/)
|
||||||
|
```python
|
||||||
|
# 優先度: 高
|
||||||
|
setup/components/commands.py # コマンドインストール
|
||||||
|
setup/components/modes.py # モードインストール
|
||||||
|
setup/components/agents.py # エージェント定義
|
||||||
|
setup/data/commands/*.md # コマンド仕様(ソース)
|
||||||
|
setup/data/modes/*.md # モード仕様(ソース)
|
||||||
|
|
||||||
|
# これらが ~/.claude/ に配置される
|
||||||
|
```
|
||||||
|
|
||||||
|
### ランタイム側(superclaude/)
|
||||||
|
```python
|
||||||
|
# 優先度: 中
|
||||||
|
superclaude/__main__.py # CLIエントリーポイント
|
||||||
|
superclaude/core/ # コア機能実装
|
||||||
|
superclaude/agents/ # エージェントロジック
|
||||||
|
```
|
||||||
|
|
||||||
|
### インストール後(~/.claude/)
|
||||||
|
```markdown
|
||||||
|
# 優先度: 理解のため(変更不可)
|
||||||
|
~/.claude/commands/sc/pm.md # 実際に動くPM仕様
|
||||||
|
~/.claude/MODE_*.md # 実際に動くモード仕様
|
||||||
|
~/.claude/CLAUDE.md # 実際に読み込まれるグローバル設定
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔍 デバッグ方法
|
||||||
|
|
||||||
|
### インストール確認
|
||||||
|
```bash
|
||||||
|
# インストール済みコンポーネント確認
|
||||||
|
SuperClaude install --list-components
|
||||||
|
|
||||||
|
# インストール先確認
|
||||||
|
ls -la ~/.claude/commands/sc/
|
||||||
|
ls -la ~/.claude/*.md
|
||||||
|
```
|
||||||
|
|
||||||
|
### 動作確認
|
||||||
|
```bash
|
||||||
|
# Claude起動
|
||||||
|
claude
|
||||||
|
|
||||||
|
# コマンド実行
|
||||||
|
/sc:pm "test"
|
||||||
|
|
||||||
|
# ログ確認(必要に応じて)
|
||||||
|
tail -f ~/.claude/logs/*.log
|
||||||
|
```
|
||||||
|
|
||||||
|
### トラブルシューティング
|
||||||
|
```bash
|
||||||
|
# 設定が壊れた場合
|
||||||
|
SuperClaude install --force # 再インストール
|
||||||
|
|
||||||
|
# 開発版に切り替え
|
||||||
|
cd ~/github/SuperClaude_Framework
|
||||||
|
pip install -e .
|
||||||
|
|
||||||
|
# 本番版に戻す
|
||||||
|
pip uninstall superclaude
|
||||||
|
pipx install SuperClaude
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 💡 よくある間違い
|
||||||
|
|
||||||
|
### 間違い1: Git管理外を変更
|
||||||
|
```bash
|
||||||
|
# ❌ WRONG
|
||||||
|
vim ~/.claude/commands/sc/pm.md
|
||||||
|
git add ~/.claude/ # ← できない!Git管理外
|
||||||
|
```
|
||||||
|
|
||||||
|
### 間違い2: バックアップなしテスト
|
||||||
|
```bash
|
||||||
|
# ❌ WRONG
|
||||||
|
vim ~/.claude/commands/sc/pm.md
|
||||||
|
# テスト...
|
||||||
|
# 元に戻すの忘れる → 設定ぐちゃぐちゃ
|
||||||
|
```
|
||||||
|
|
||||||
|
### 間違い3: ソース確認せずに変更
|
||||||
|
```bash
|
||||||
|
# ❌ WRONG
|
||||||
|
「PMモード直したい」
|
||||||
|
→ いきなり ~/.claude/ 変更
|
||||||
|
→ ソースコード理解してない
|
||||||
|
→ 再インストールで上書きされる
|
||||||
|
```
|
||||||
|
|
||||||
|
### 正解
|
||||||
|
```bash
|
||||||
|
# ✅ CORRECT
|
||||||
|
1. setup/components/ でロジック理解
|
||||||
|
2. docs/Development/ に改善案記録
|
||||||
|
3. setup/ 側で変更・テスト
|
||||||
|
4. Git コミット
|
||||||
|
5. SuperClaude install --dev で動作確認
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🚀 次のステップ
|
||||||
|
|
||||||
|
このドキュメント理解後:
|
||||||
|
|
||||||
|
1. **setup/components/ 読解**
|
||||||
|
- インストールロジックの理解
|
||||||
|
- どこに何が配置されるか
|
||||||
|
|
||||||
|
2. **既存仕様の把握**
|
||||||
|
- `~/.claude/commands/sc/pm.md` 確認(読むだけ)
|
||||||
|
- 現在の動作理解
|
||||||
|
|
||||||
|
3. **改善提案作成**
|
||||||
|
- `docs/Development/hypothesis-*.md` 作成
|
||||||
|
- ユーザーレビュー
|
||||||
|
|
||||||
|
4. **実装・テスト**
|
||||||
|
- `setup/` 側で変更
|
||||||
|
- `tests/` でテスト追加
|
||||||
|
- Git管理下で開発
|
||||||
|
|
||||||
|
これで**何百回も同じ説明をしなくて済む**ようになる。
|
||||||
163
docs/Development/tasks/current-tasks.md
Normal file
163
docs/Development/tasks/current-tasks.md
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
# Current Tasks - SuperClaude Framework
|
||||||
|
|
||||||
|
> **Last Updated**: 2025-10-14
|
||||||
|
> **Session**: PM Agent Enhancement & PDCA Integration
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 Main Objective
|
||||||
|
|
||||||
|
**PM Agent を完璧な自律的オーケストレーターに進化させる**
|
||||||
|
|
||||||
|
- 繰り返し指示を不要にする
|
||||||
|
- 同じミスを繰り返さない
|
||||||
|
- セッション間で学習内容を保持
|
||||||
|
- 自律的にPDCAサイクルを回す
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ✅ Completed Tasks
|
||||||
|
|
||||||
|
### Phase 1: ドキュメント基盤整備
|
||||||
|
- [x] **PM Agent理想ワークフローをドキュメント化**
|
||||||
|
- File: `docs/Development/pm-agent-ideal-workflow.md`
|
||||||
|
- Content: 完璧なワークフロー(7フェーズ)
|
||||||
|
- Purpose: 次回セッションで同じ説明を繰り返さない
|
||||||
|
|
||||||
|
- [x] **プロジェクト構造理解をドキュメント化**
|
||||||
|
- File: `docs/Development/project-structure-understanding.md`
|
||||||
|
- Content: Git管理とインストール後環境の区別
|
||||||
|
- Purpose: 何百回も説明した内容を外部化
|
||||||
|
|
||||||
|
- [x] **インストールフロー理解をドキュメント化**
|
||||||
|
- File: `docs/Development/installation-flow-understanding.md`
|
||||||
|
- Content: CommandsComponent動作の完全理解
|
||||||
|
- Source: `superclaude/commands/*.md` → `~/.claude/commands/sc/*.md`
|
||||||
|
|
||||||
|
- [x] **ディレクトリ構造作成**
|
||||||
|
- `docs/Development/tasks/` - タスク管理
|
||||||
|
- `docs/patterns/` - 成功パターン記録
|
||||||
|
- `docs/mistakes/` - 失敗記録と防止策
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔄 In Progress
|
||||||
|
|
||||||
|
### Phase 2: 現状分析と改善提案
|
||||||
|
|
||||||
|
- [ ] **superclaude/commands/pm.md 現在の仕様確認**
|
||||||
|
- Status: Pending
|
||||||
|
- Action: ソースファイルを読んで現在の実装を理解
|
||||||
|
- File: `superclaude/commands/pm.md`
|
||||||
|
|
||||||
|
- [ ] **~/.claude/commands/sc/pm.md 動作確認**
|
||||||
|
- Status: Pending
|
||||||
|
- Action: インストール後の実際の仕様確認(読むだけ)
|
||||||
|
- File: `~/.claude/commands/sc/pm.md`
|
||||||
|
|
||||||
|
- [ ] **改善提案ドキュメント作成**
|
||||||
|
- Status: Pending
|
||||||
|
- Action: 仮説ドキュメント作成
|
||||||
|
- File: `docs/Development/hypothesis-pm-enhancement-2025-10-14.md`
|
||||||
|
- Content:
|
||||||
|
- 現状の問題点(ドキュメント寄り、PMO機能不足)
|
||||||
|
- 改善案(自律的PDCA、自己評価)
|
||||||
|
- 実装方針
|
||||||
|
- 期待される効果
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📋 Pending Tasks
|
||||||
|
|
||||||
|
### Phase 3: 実装修正
|
||||||
|
|
||||||
|
- [ ] **superclaude/commands/pm.md 修正**
|
||||||
|
- Content:
|
||||||
|
- PDCA自動実行の強化
|
||||||
|
- docs/ディレクトリ活用の明示
|
||||||
|
- 自己評価ステップの追加
|
||||||
|
- エラー時再学習フローの追加
|
||||||
|
- PMO機能(重複検出、共通化提案)
|
||||||
|
|
||||||
|
- [ ] **MODE_Task_Management.md 修正**
|
||||||
|
- Serenaメモリー → docs/統合
|
||||||
|
- タスク管理ドキュメント連携
|
||||||
|
|
||||||
|
### Phase 4: テスト・検証
|
||||||
|
|
||||||
|
- [ ] **テスト追加**
|
||||||
|
- File: `tests/test_pm_enhanced.py`
|
||||||
|
- Coverage: PDCA実行、自己評価、学習記録
|
||||||
|
|
||||||
|
- [ ] **動作確認**
|
||||||
|
- 開発版インストール: `SuperClaude install --dev`
|
||||||
|
- 実際のワークフロー実行
|
||||||
|
- Before/After比較
|
||||||
|
|
||||||
|
### Phase 5: 学習記録
|
||||||
|
|
||||||
|
- [ ] **成功パターン記録**
|
||||||
|
- File: `docs/patterns/pm-autonomous-workflow.md`
|
||||||
|
- Content: 自律的PDCAパターンの詳細
|
||||||
|
|
||||||
|
- [ ] **失敗記録(必要時)**
|
||||||
|
- File: `docs/mistakes/mistake-2025-10-14.md`
|
||||||
|
- Content: 遭遇したエラーと防止策
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 Success Criteria
|
||||||
|
|
||||||
|
### 定量的指標
|
||||||
|
- [ ] 繰り返し指示 50%削減
|
||||||
|
- [ ] 同じミス再発率 80%削減
|
||||||
|
- [ ] セッション復元時間 <30秒
|
||||||
|
|
||||||
|
### 定性的指標
|
||||||
|
- [ ] 「前回の続きから」だけで再開可能
|
||||||
|
- [ ] 過去のミスを自動的に回避
|
||||||
|
- [ ] 公式ドキュメント参照が自動化
|
||||||
|
- [ ] 実装→テスト→検証が自律的に回る
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📝 Notes
|
||||||
|
|
||||||
|
### 重要な学び
|
||||||
|
- **Git管理の区別が最重要**
|
||||||
|
- このプロジェクト(Git管理)で変更
|
||||||
|
- `~/.claude/`(Git管理外)は読むだけ
|
||||||
|
- テスト時のバックアップ・復元必須
|
||||||
|
|
||||||
|
- **ドキュメント駆動開発**
|
||||||
|
- 理解 → docs/Development/ に記録
|
||||||
|
- 仮説 → hypothesis-*.md
|
||||||
|
- 実験 → experiment-*.md
|
||||||
|
- 成功 → docs/patterns/
|
||||||
|
- 失敗 → docs/mistakes/
|
||||||
|
|
||||||
|
- **インストールフロー**
|
||||||
|
- Source: `superclaude/commands/*.md`
|
||||||
|
- Installer: `setup/components/commands.py`
|
||||||
|
- Target: `~/.claude/commands/sc/*.md`
|
||||||
|
|
||||||
|
### ブロッカー
|
||||||
|
- なし(現時点)
|
||||||
|
|
||||||
|
### 次回セッション用のメモ
|
||||||
|
1. このファイル(current-tasks.md)を最初に読む
|
||||||
|
2. Completedセクションで進捗確認
|
||||||
|
3. In Progressから再開
|
||||||
|
4. 新しい学びを適切なドキュメントに記録
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔗 Related Documentation
|
||||||
|
|
||||||
|
- [PM Agent理想ワークフロー](../pm-agent-ideal-workflow.md)
|
||||||
|
- [プロジェクト構造理解](../project-structure-understanding.md)
|
||||||
|
- [インストールフロー理解](../installation-flow-understanding.md)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**次のステップ**: `superclaude/commands/pm.md` を読んで現在の仕様を確認する
|
||||||
556
docs/Reference/claude-code-history-management.md
Normal file
556
docs/Reference/claude-code-history-management.md
Normal file
@ -0,0 +1,556 @@
|
|||||||
|
# Claude Code Conversation History Management Research
|
||||||
|
|
||||||
|
**Research Date**: 2025-10-09
|
||||||
|
**Purpose**: Understand .jsonl file structure, performance impact, and establish rotation policy
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Official Documentation & Purpose
|
||||||
|
|
||||||
|
### .jsonl File Structure
|
||||||
|
**Location**: `~/.claude/projects/{project-directory}/`
|
||||||
|
|
||||||
|
**Data Structure** (from analysis of actual files):
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "summary|file-history-snapshot|user|assistant|system|tool_use|tool_result|message",
|
||||||
|
"timestamp": "ISO-8601 timestamp",
|
||||||
|
"cwd": "/absolute/path/to/working/directory",
|
||||||
|
"sessionId": "uuid",
|
||||||
|
"gitBranch": "branch-name",
|
||||||
|
"content": "message content or command",
|
||||||
|
"messageId": "uuid for message tracking"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Key Message Types** (from 2.6MB conversation analysis):
|
||||||
|
- `message` (228): Container for conversation messages
|
||||||
|
- `assistant` (228): Claude's responses
|
||||||
|
- `user` (182): User inputs
|
||||||
|
- `tool_use` (137): Tool invocations
|
||||||
|
- `tool_result` (137): Tool execution results
|
||||||
|
- `text` (74): Text content blocks
|
||||||
|
- `file-history-snapshot` (39): File state tracking
|
||||||
|
- `thinking` (31): Claude's reasoning process
|
||||||
|
- `system` (12): System-level messages
|
||||||
|
|
||||||
|
### File History Snapshot Purpose
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "file-history-snapshot",
|
||||||
|
"messageId": "uuid",
|
||||||
|
"snapshot": {
|
||||||
|
"messageId": "uuid",
|
||||||
|
"trackedFileBackups": {},
|
||||||
|
"timestamp": "ISO-8601"
|
||||||
|
},
|
||||||
|
"isSnapshotUpdate": false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Purpose** (inferred from structure):
|
||||||
|
- Tracks file states at specific conversation points
|
||||||
|
- Enables undo/redo functionality for file changes
|
||||||
|
- Provides rollback capability for edits
|
||||||
|
- **Note**: No official documentation found on this feature
|
||||||
|
|
||||||
|
### Conversation Loading Behavior
|
||||||
|
**Official Best Practices** ([source](https://www.anthropic.com/engineering/claude-code-best-practices)):
|
||||||
|
- "All conversations are automatically saved locally with their full message history"
|
||||||
|
- "When resuming, the entire message history is restored to maintain context"
|
||||||
|
- "Tool usage and results from previous conversations preserved"
|
||||||
|
|
||||||
|
**Resume Commands**:
|
||||||
|
- `--continue`: Automatically continue most recent conversation
|
||||||
|
- `/resume`: Show list of recent sessions and choose one
|
||||||
|
- Session ID specification: Resume specific conversation
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Performance Impact
|
||||||
|
|
||||||
|
### Known Issues from GitHub
|
||||||
|
|
||||||
|
#### Issue #5024: History Accumulation Causing Performance Issues
|
||||||
|
**Status**: Open (Major Issue)
|
||||||
|
**URL**: https://github.com/anthropics/claude-code/issues/5024
|
||||||
|
|
||||||
|
**Reported Problems**:
|
||||||
|
- File sizes growing to "hundreds of MB or more"
|
||||||
|
- Slower application startup times
|
||||||
|
- System performance degradation
|
||||||
|
- No automatic cleanup mechanism
|
||||||
|
- One user reported file size of 968KB+ continuously growing
|
||||||
|
|
||||||
|
**Current Workaround**:
|
||||||
|
- Manual editing of `.claude.json` (risky - can break configurations)
|
||||||
|
- `claude history clear` (removes ALL history across ALL projects)
|
||||||
|
|
||||||
|
#### Issue #7985: Severe Memory Leak
|
||||||
|
**Status**: Critical
|
||||||
|
**URL**: https://github.com/anthropics/claude-code/issues/7985
|
||||||
|
|
||||||
|
**Reported Problems**:
|
||||||
|
- Context accumulation causing massive memory usage
|
||||||
|
- Memory leaks with objects not garbage collected
|
||||||
|
- One user reported ~570GB of virtual memory usage
|
||||||
|
- Long-running sessions become unusable
|
||||||
|
|
||||||
|
#### Issue #8839: Conversation Compaction Failure
|
||||||
|
**Status**: Regression (after undo/redo feature)
|
||||||
|
**URL**: https://github.com/anthropics/claude-code/issues/8839
|
||||||
|
|
||||||
|
**Impact**:
|
||||||
|
- Claude Code can no longer automatically compact long conversations
|
||||||
|
- "Too long" errors after conversation history navigation feature added
|
||||||
|
- Conversations become unmanageable without manual intervention
|
||||||
|
|
||||||
|
#### Issue #8755: /clear Command Not Working
|
||||||
|
**Status**: Bug
|
||||||
|
**URL**: https://github.com/anthropics/claude-code/issues/8755
|
||||||
|
|
||||||
|
**Impact**:
|
||||||
|
- `/clear` command stopped functioning for some users
|
||||||
|
- "Clear Conversations" menu option non-functional
|
||||||
|
- Users cannot reset context window as recommended
|
||||||
|
|
||||||
|
### Actual Performance Data (Your Environment)
|
||||||
|
|
||||||
|
**Current State** (as of 2025-10-09):
|
||||||
|
- **Total agiletec project**: 33MB (57 conversation files)
|
||||||
|
- **Largest file**: 2.6MB (462 lines)
|
||||||
|
- **Average file**: ~580KB
|
||||||
|
- **Files >1MB**: 3 files
|
||||||
|
- **Total across all projects**: ~62MB
|
||||||
|
|
||||||
|
**Age Distribution**:
|
||||||
|
- Files older than 30 days: 0
|
||||||
|
- Files older than 7 days: 4
|
||||||
|
- Most files: <7 days old
|
||||||
|
|
||||||
|
**Comparison to Other Projects**:
|
||||||
|
```
|
||||||
|
33M agiletec (57 files) - Most active
|
||||||
|
14M SSD-2TB project
|
||||||
|
6.3M tokium
|
||||||
|
2.6M bunseki
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Official Retention Policies
|
||||||
|
|
||||||
|
### Standard Retention (Consumer)
|
||||||
|
**Source**: [Anthropic Privacy Center](https://privacy.claude.com/en/articles/10023548-how-long-do-you-store-my-data)
|
||||||
|
|
||||||
|
- **Prompts/Responses**: Up to 30 days in back-end logs
|
||||||
|
- **Deleted chats**: Immediately removed from UI, purged within 30 days
|
||||||
|
- **API logs**: Reducing to 7 days starting September 15, 2025 (from 30 days)
|
||||||
|
|
||||||
|
### Enterprise Controls
|
||||||
|
**Source**: [Custom Data Retention Controls](https://privacy.anthropic.com/en/articles/10440198-custom-data-retention-controls-for-claude-enterprise)
|
||||||
|
|
||||||
|
- **Minimum retention**: 30 days
|
||||||
|
- **Retention start**: Last observed activity (last message or project update)
|
||||||
|
- **Custom periods**: Available for organizations
|
||||||
|
|
||||||
|
### Local Storage (No Official Policy)
|
||||||
|
**Finding**: No official documentation found regarding:
|
||||||
|
- Recommended local .jsonl file retention periods
|
||||||
|
- Automatic cleanup of old conversations
|
||||||
|
- Performance thresholds for file sizes
|
||||||
|
- Safe deletion procedures
|
||||||
|
|
||||||
|
**Current Tools**:
|
||||||
|
- `claude history clear`: Removes ALL history (all projects, destructive)
|
||||||
|
- No selective cleanup tools available
|
||||||
|
- No archive functionality
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Best Practices (Official & Community)
|
||||||
|
|
||||||
|
### Official Recommendations
|
||||||
|
|
||||||
|
#### Context Management
|
||||||
|
**Source**: [Claude Code Best Practices](https://www.anthropic.com/engineering/claude-code-best-practices)
|
||||||
|
|
||||||
|
**Key Guidelines**:
|
||||||
|
1. **Use `/clear` frequently**: "Reset context window between tasks"
|
||||||
|
2. **Scope conversations**: "One project or feature per conversation"
|
||||||
|
3. **Clear before switching**: "/clear before fixing bugs to prevent context pollution"
|
||||||
|
4. **Don't rely on long context**: "Claude's context window can fill with irrelevant conversation"
|
||||||
|
|
||||||
|
**Quote**: "During long sessions, Claude's context window can fill with irrelevant conversation, file contents, and commands which can reduce performance, so use the /clear command frequently between tasks to reset the context window."
|
||||||
|
|
||||||
|
#### CLAUDE.md Strategy
|
||||||
|
- **Persistent context**: Use CLAUDE.md files for stable instructions
|
||||||
|
- **Auto-loaded**: "Claude automatically pulls into context when starting"
|
||||||
|
- **Hierarchy**: Global (`~/.claude/CLAUDE.md`) → Workspace → Project
|
||||||
|
- **Refinement**: "Take time to experiment and determine what produces best results"
|
||||||
|
|
||||||
|
#### When to Restart vs /clear
|
||||||
|
**Source**: [Community Best Practices](https://claudelog.com/faqs/does-claude-code-store-my-data/)
|
||||||
|
|
||||||
|
**Use `/clear` when**:
|
||||||
|
- Starting new task/feature
|
||||||
|
- Switching between features
|
||||||
|
- Context becomes polluted
|
||||||
|
- Before bug fixing
|
||||||
|
|
||||||
|
**Restart session when**:
|
||||||
|
- Switching projects
|
||||||
|
- Updating CLAUDE.md files
|
||||||
|
- Experiencing session issues
|
||||||
|
- Memory usage high
|
||||||
|
|
||||||
|
### Community Strategies
|
||||||
|
|
||||||
|
#### Conversation Organization
|
||||||
|
**Pattern**: "Scope a chat to one project or feature"
|
||||||
|
- Start conversation for specific goal
|
||||||
|
- Use `/clear` when goal complete
|
||||||
|
- Don't mix unrelated tasks in same conversation
|
||||||
|
|
||||||
|
#### Context Optimization
|
||||||
|
**Pattern**: "Avoid extensive, unrefined context"
|
||||||
|
- Iterate on CLAUDE.md effectiveness
|
||||||
|
- Remove ineffective instructions
|
||||||
|
- Test and refine periodically
|
||||||
|
|
||||||
|
#### Incognito Mode for Sensitive Work
|
||||||
|
**Pattern**: "Ghost icon for temporary conversations"
|
||||||
|
- Not saved to chat history
|
||||||
|
- No contribution to context memory
|
||||||
|
- Useful for experimental or sensitive work
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Recommended Rotation Policy
|
||||||
|
|
||||||
|
### Immediate Actions (No Risk)
|
||||||
|
|
||||||
|
#### 1. Delete Very Old Conversations (>30 days)
|
||||||
|
```bash
|
||||||
|
# Backup first
|
||||||
|
mkdir -p ~/.claude/projects-archive/$(date +%Y-%m)
|
||||||
|
|
||||||
|
# Find and archive
|
||||||
|
find ~/.claude/projects/ -name "*.jsonl" -mtime +30 -type f \
|
||||||
|
-exec mv {} ~/.claude/projects-archive/$(date +%Y-%m)/ \;
|
||||||
|
```
|
||||||
|
|
||||||
|
**Rationale**:
|
||||||
|
- Aligns with Anthropic's 30-day back-end retention
|
||||||
|
- Minimal functionality loss (context rarely useful after 30 days)
|
||||||
|
- Significant space savings
|
||||||
|
|
||||||
|
#### 2. Archive Project-Specific Old Conversations (>14 days)
|
||||||
|
```bash
|
||||||
|
# Per-project archive
|
||||||
|
mkdir -p ~/.claude/projects-archive/agiletec/$(date +%Y-%m)
|
||||||
|
|
||||||
|
find ~/.claude/projects/-Users-kazuki-github-agiletec -name "*.jsonl" -mtime +14 -type f \
|
||||||
|
-exec mv {} ~/.claude/projects-archive/agiletec/$(date +%Y-%m)/ \;
|
||||||
|
```
|
||||||
|
|
||||||
|
**Rationale**:
|
||||||
|
- 14 days provides buffer for resumed work
|
||||||
|
- Most development tasks complete within 2 weeks
|
||||||
|
- Easy to restore if needed
|
||||||
|
|
||||||
|
### Periodic Maintenance (Weekly)
|
||||||
|
|
||||||
|
#### 3. Identify Large Files for Manual Review
|
||||||
|
```bash
|
||||||
|
# Find files >1MB
|
||||||
|
find ~/.claude/projects/ -name "*.jsonl" -type f -size +1M -exec ls -lh {} \;
|
||||||
|
|
||||||
|
# Review and archive if not actively used
|
||||||
|
```
|
||||||
|
|
||||||
|
**Criteria for Archival**:
|
||||||
|
- File >1MB and not modified in 7 days
|
||||||
|
- Completed feature/project conversations
|
||||||
|
- Debugging sessions that are resolved
|
||||||
|
|
||||||
|
### Aggressive Cleanup (Monthly)
|
||||||
|
|
||||||
|
#### 4. Archive All Inactive Conversations (>7 days)
|
||||||
|
```bash
|
||||||
|
# Monthly archive
|
||||||
|
mkdir -p ~/.claude/projects-archive/$(date +%Y-%m)
|
||||||
|
|
||||||
|
find ~/.claude/projects/ -name "*.jsonl" -mtime +7 -type f \
|
||||||
|
-exec mv {} ~/.claude/projects-archive/$(date +%Y-%m)/ \;
|
||||||
|
```
|
||||||
|
|
||||||
|
**When to Use**:
|
||||||
|
- Project directory >50MB
|
||||||
|
- Startup performance degraded
|
||||||
|
- Running low on disk space
|
||||||
|
|
||||||
|
### Emergency Cleanup (Performance Issues)
|
||||||
|
|
||||||
|
#### 5. Nuclear Option - Keep Only Recent Week
|
||||||
|
```bash
|
||||||
|
# BACKUP EVERYTHING FIRST
|
||||||
|
tar -czf ~/claude-history-backup-$(date +%Y%m%d).tar.gz ~/.claude/projects/
|
||||||
|
|
||||||
|
# Keep only last 7 days
|
||||||
|
find ~/.claude/projects/ -name "*.jsonl" -mtime +7 -type f -delete
|
||||||
|
```
|
||||||
|
|
||||||
|
**When to Use**:
|
||||||
|
- Claude Code startup >10 seconds
|
||||||
|
- Memory usage abnormally high
|
||||||
|
- Experiencing Issue #7985 symptoms
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Proposed Automated Solution
|
||||||
|
|
||||||
|
### Shell Script: `claude-history-rotate.sh`
|
||||||
|
```bash
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# Claude Code Conversation History Rotation
|
||||||
|
# Usage: ./claude-history-rotate.sh [--dry-run] [--days N]
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
DAYS=${DAYS:-30}
|
||||||
|
DRY_RUN=false
|
||||||
|
ARCHIVE_BASE=~/.claude/projects-archive
|
||||||
|
|
||||||
|
# Parse arguments
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case $1 in
|
||||||
|
--dry-run) DRY_RUN=true; shift ;;
|
||||||
|
--days) DAYS="$2"; shift 2 ;;
|
||||||
|
*) echo "Unknown option: $1"; exit 1 ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
# Create archive directory
|
||||||
|
ARCHIVE_DIR="$ARCHIVE_BASE/$(date +%Y-%m)"
|
||||||
|
mkdir -p "$ARCHIVE_DIR"
|
||||||
|
|
||||||
|
# Find old conversations
|
||||||
|
OLD_FILES=$(find ~/.claude/projects/ -name "*.jsonl" -mtime "+$DAYS" -type f)
|
||||||
|
|
||||||
|
if [[ -z "$OLD_FILES" ]]; then
|
||||||
|
echo "No files older than $DAYS days found."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Count and size
|
||||||
|
FILE_COUNT=$(echo "$OLD_FILES" | wc -l | tr -d ' ')
|
||||||
|
TOTAL_SIZE=$(echo "$OLD_FILES" | xargs du -ch | tail -1 | awk '{print $1}')
|
||||||
|
|
||||||
|
echo "Found $FILE_COUNT files older than $DAYS days ($TOTAL_SIZE total)"
|
||||||
|
|
||||||
|
if [[ "$DRY_RUN" == "true" ]]; then
|
||||||
|
echo "DRY RUN - Would archive:"
|
||||||
|
echo "$OLD_FILES"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Archive files
|
||||||
|
echo "$OLD_FILES" | while read -r file; do
|
||||||
|
mv "$file" "$ARCHIVE_DIR/"
|
||||||
|
echo "Archived: $(basename "$file")"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "✓ Archived $FILE_COUNT files to $ARCHIVE_DIR"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Cron Job Setup (Optional)
|
||||||
|
```bash
|
||||||
|
# Add to crontab (monthly cleanup)
|
||||||
|
# 0 3 1 * * /Users/kazuki/.local/bin/claude-history-rotate.sh --days 30
|
||||||
|
|
||||||
|
# Or use launchd on macOS
|
||||||
|
cat > ~/Library/LaunchAgents/com.user.claude-history-rotate.plist <<'EOF'
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>Label</key>
|
||||||
|
<string>com.user.claude-history-rotate</string>
|
||||||
|
<key>ProgramArguments</key>
|
||||||
|
<array>
|
||||||
|
<string>/Users/kazuki/.local/bin/claude-history-rotate.sh</string>
|
||||||
|
<string>--days</string>
|
||||||
|
<string>30</string>
|
||||||
|
</array>
|
||||||
|
<key>StartCalendarInterval</key>
|
||||||
|
<dict>
|
||||||
|
<key>Day</key>
|
||||||
|
<integer>1</integer>
|
||||||
|
<key>Hour</key>
|
||||||
|
<integer>3</integer>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
|
EOF
|
||||||
|
|
||||||
|
launchctl load ~/Library/LaunchAgents/com.user.claude-history-rotate.plist
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. Monitoring & Alerts
|
||||||
|
|
||||||
|
### Disk Usage Check Script
|
||||||
|
```bash
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# claude-history-check.sh
|
||||||
|
|
||||||
|
THRESHOLD_MB=100
|
||||||
|
PROJECTS_DIR=~/.claude/projects
|
||||||
|
|
||||||
|
TOTAL_SIZE_MB=$(du -sm "$PROJECTS_DIR" | awk '{print $1}')
|
||||||
|
|
||||||
|
echo "Claude Code conversation history: ${TOTAL_SIZE_MB}MB"
|
||||||
|
|
||||||
|
if [[ $TOTAL_SIZE_MB -gt $THRESHOLD_MB ]]; then
|
||||||
|
echo "⚠️ WARNING: History size exceeds ${THRESHOLD_MB}MB threshold"
|
||||||
|
echo "Consider running: claude-history-rotate.sh --days 30"
|
||||||
|
|
||||||
|
# Find largest projects
|
||||||
|
echo ""
|
||||||
|
echo "Largest projects:"
|
||||||
|
du -sm "$PROJECTS_DIR"/*/ | sort -rn | head -5
|
||||||
|
fi
|
||||||
|
```
|
||||||
|
|
||||||
|
### Performance Indicators to Watch
|
||||||
|
1. **Startup time**: >5 seconds = investigate
|
||||||
|
2. **File sizes**: >2MB per conversation = review
|
||||||
|
3. **Total size**: >100MB across all projects = cleanup
|
||||||
|
4. **Memory usage**: >2GB during session = Issue #7985
|
||||||
|
5. **Conversation length**: >500 message pairs = use `/clear`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. Key Takeaways & Recommendations
|
||||||
|
|
||||||
|
### Critical Findings
|
||||||
|
|
||||||
|
✅ **Safe to Delete**:
|
||||||
|
- Conversations >30 days old (aligns with Anthropic retention)
|
||||||
|
- Completed feature/project conversations
|
||||||
|
- Large files (>1MB) not accessed in 14+ days
|
||||||
|
|
||||||
|
⚠️ **Caution Required**:
|
||||||
|
- Active project conversations (<7 days)
|
||||||
|
- Files referenced in recent work
|
||||||
|
- Conversations with unfinished tasks
|
||||||
|
|
||||||
|
❌ **Known Issues**:
|
||||||
|
- No official cleanup tools (Issue #5024)
|
||||||
|
- Memory leaks in long sessions (Issue #7985)
|
||||||
|
- `/clear` command bugs (Issue #8755)
|
||||||
|
- Conversation compaction broken (Issue #8839)
|
||||||
|
|
||||||
|
### Recommended Policy for Your Environment
|
||||||
|
|
||||||
|
**Daily Practice**:
|
||||||
|
- Use `/clear` between major tasks
|
||||||
|
- Scope conversations to single features
|
||||||
|
- Restart session if >2 hours continuous work
|
||||||
|
|
||||||
|
**Weekly Review** (Sunday):
|
||||||
|
```bash
|
||||||
|
# Check current state
|
||||||
|
du -sh ~/.claude/projects/*/
|
||||||
|
|
||||||
|
# Archive old conversations (>14 days)
|
||||||
|
claude-history-rotate.sh --days 14 --dry-run # Preview
|
||||||
|
claude-history-rotate.sh --days 14 # Execute
|
||||||
|
```
|
||||||
|
|
||||||
|
**Monthly Cleanup** (1st of month):
|
||||||
|
```bash
|
||||||
|
# Aggressive cleanup (>30 days)
|
||||||
|
claude-history-rotate.sh --days 30
|
||||||
|
|
||||||
|
# Review large files
|
||||||
|
find ~/.claude/projects/ -name "*.jsonl" -size +1M -mtime +7
|
||||||
|
```
|
||||||
|
|
||||||
|
**Performance Threshold Actions**:
|
||||||
|
- Total size >50MB: Archive 30-day-old conversations
|
||||||
|
- Total size >100MB: Archive 14-day-old conversations
|
||||||
|
- Total size >200MB: Emergency cleanup (7-day retention)
|
||||||
|
- Startup >10s: Investigate memory leaks, consider Issue #7985
|
||||||
|
|
||||||
|
### Future-Proofing
|
||||||
|
|
||||||
|
**Watch for Official Solutions**:
|
||||||
|
- `claude history prune` command (requested in #5024)
|
||||||
|
- Automatic history rotation feature
|
||||||
|
- Configurable retention settings
|
||||||
|
- Separate configuration from history storage
|
||||||
|
|
||||||
|
**Community Tools**:
|
||||||
|
- [cclogviewer](https://github.com/hesreallyhim/awesome-claude-code): View .jsonl files
|
||||||
|
- Consider contributing to #5024 discussion
|
||||||
|
- Monitor anthropics/claude-code releases
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. References
|
||||||
|
|
||||||
|
### Official Documentation
|
||||||
|
- [Claude Code Best Practices](https://www.anthropic.com/engineering/claude-code-best-practices)
|
||||||
|
- [How Long Do You Store My Data?](https://privacy.claude.com/en/articles/10023548-how-long-do-you-store-my-data)
|
||||||
|
- [Custom Data Retention Controls](https://privacy.anthropic.com/en/articles/10440198-custom-data-retention-controls-for-claude-enterprise)
|
||||||
|
|
||||||
|
### GitHub Issues
|
||||||
|
- [#5024: History accumulation causes performance issues](https://github.com/anthropics/claude-code/issues/5024)
|
||||||
|
- [#7985: Severe memory leak](https://github.com/anthropics/claude-code/issues/7985)
|
||||||
|
- [#8839: Conversation compaction failure](https://github.com/anthropics/claude-code/issues/8839)
|
||||||
|
- [#8755: /clear command not working](https://github.com/anthropics/claude-code/issues/8755)
|
||||||
|
|
||||||
|
### Community Resources
|
||||||
|
- [Awesome Claude Code](https://github.com/hesreallyhim/awesome-claude-code)
|
||||||
|
- [Claude Code Context Guide](https://www.arsturn.com/blog/beyond-prompting-a-guide-to-managing-context-in-claude-code)
|
||||||
|
- [ClaudeLog Documentation](https://claudelog.com/)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Appendix: Current Environment Statistics
|
||||||
|
|
||||||
|
**Generated**: 2025-10-09 04:24 JST
|
||||||
|
|
||||||
|
### Project Size Breakdown
|
||||||
|
```
|
||||||
|
33M -Users-kazuki-github-agiletec (57 files)
|
||||||
|
14M -Volumes-SSD-2TB (project count: N/A)
|
||||||
|
6.3M -Users-kazuki-github-tokium
|
||||||
|
2.6M -Users-kazuki-github-bunseki
|
||||||
|
1.9M -Users-kazuki
|
||||||
|
1.9M -Users-kazuki-github-superclaude
|
||||||
|
---
|
||||||
|
Total: ~62MB across all projects
|
||||||
|
```
|
||||||
|
|
||||||
|
### agiletec Project Details
|
||||||
|
- **Total conversations**: 57
|
||||||
|
- **Largest file**: 2.6MB (d4852655-b760-4311-8f67-26f593f2403f.jsonl)
|
||||||
|
- **Files >1MB**: 3 files
|
||||||
|
- **Avg file size**: ~580KB
|
||||||
|
- **Files >7 days**: 4 files
|
||||||
|
- **Files >30 days**: 0 files
|
||||||
|
|
||||||
|
### Immediate Recommendation
|
||||||
|
**Status**: ✅ Healthy (no immediate action required)
|
||||||
|
|
||||||
|
**Reasoning**:
|
||||||
|
- Total size (33MB) well below concern threshold (100MB)
|
||||||
|
- No files >30 days old
|
||||||
|
- Only 4 files >7 days old
|
||||||
|
- Largest file (2.6MB) within acceptable range
|
||||||
|
|
||||||
|
**Next Review**: 2025-10-16 (weekly check)
|
||||||
@ -1,12 +1,12 @@
|
|||||||
# SuperClaude エージェントガイド 🤖
|
# SuperClaude エージェントガイド 🤖
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/agents.md#superclaude-agents-guide-)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/agents.md#superclaude-agents-guide-)
|
||||||
|
|
||||||
SuperClaude は、Claude Code が専門知識を得るために呼び出すことができる 14 のドメイン スペシャリスト エージェントを提供します。
|
SuperClaude は、Claude Code が専門知識を得るために呼び出すことができる 14 のドメイン スペシャリスト エージェントを提供します。
|
||||||
|
|
||||||
## 🧪 エージェントのアクティベーションのテスト
|
## 🧪 エージェントのアクティベーションのテスト
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/agents.md#-testing-agent-activation)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/agents.md#-testing-agent-activation)
|
||||||
|
|
||||||
このガイドを使用する前に、エージェントの選択が機能することを確認してください。
|
このガイドを使用する前に、エージェントの選択が機能することを確認してください。
|
||||||
|
|
||||||
@ -37,23 +37,23 @@ SuperClaude は、Claude Code が専門知識を得るために呼び出すこ
|
|||||||
|
|
||||||
## コアコンセプト
|
## コアコンセプト
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/agents.md#core-concepts)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/agents.md#core-concepts)
|
||||||
|
|
||||||
### SuperClaude エージェントとは何ですか?
|
### SuperClaude エージェントとは何ですか?
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/agents.md#what-are-superclaude-agents)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/agents.md#what-are-superclaude-agents)
|
||||||
|
|
||||||
**エージェントは**、Claude Codeの行動を変更するコンテキスト指示として実装された、専門分野のAIドメインエキスパートです。各エージェントは、ドメイン固有の専門知識、行動パターン、問題解決アプローチを含む、ディレクトリ`.md`内に綿密に作成されたファイルです`SuperClaude/Agents/`。
|
**エージェントは**、Claude Codeの行動を変更するコンテキスト指示として実装された、専門分野のAIドメインエキスパートです。各エージェントは、ドメイン固有の専門知識、行動パターン、問題解決アプローチを含む、ディレクトリ`.md`内に綿密に作成されたファイルです`superclaude/Agents/`。
|
||||||
|
|
||||||
**重要**: エージェントは別個の AI モデルやソフトウェアではなく、Claude Code が読み取って特殊な動作を採用するコンテキスト構成です。
|
**重要**: エージェントは別個の AI モデルやソフトウェアではなく、Claude Code が読み取って特殊な動作を採用するコンテキスト構成です。
|
||||||
|
|
||||||
### エージェントの2つの使用方法
|
### エージェントの2つの使用方法
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/agents.md#two-ways-to-use-agents)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/agents.md#two-ways-to-use-agents)
|
||||||
|
|
||||||
#### 1. @agent- プレフィックスを使用した手動呼び出し
|
#### 1. @agent- プレフィックスを使用した手動呼び出し
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/agents.md#1-manual-invocation-with-agent--prefix)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/agents.md#1-manual-invocation-with-agent--prefix)
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
# Directly invoke a specific agent
|
# Directly invoke a specific agent
|
||||||
@ -64,7 +64,7 @@ SuperClaude は、Claude Code が専門知識を得るために呼び出すこ
|
|||||||
|
|
||||||
#### 2. 自動アクティベーション(行動ルーティング)
|
#### 2. 自動アクティベーション(行動ルーティング)
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/agents.md#2-auto-activation-behavioral-routing)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/agents.md#2-auto-activation-behavioral-routing)
|
||||||
|
|
||||||
「自動アクティベーション」とは、Claude Codeがリクエスト内のキーワードとパターンに基づいて適切なコンテキストで動作指示を読み取り、エンゲージすることを意味します。SuperClaudeは、Claudeが最適なスペシャリストにルーティングするための動作ガイドラインを提供します。
|
「自動アクティベーション」とは、Claude Codeがリクエスト内のキーワードとパターンに基づいて適切なコンテキストで動作指示を読み取り、エンゲージすることを意味します。SuperClaudeは、Claudeが最適なスペシャリストにルーティングするための動作ガイドラインを提供します。
|
||||||
|
|
||||||
@ -83,7 +83,7 @@ SuperClaude は、Claude Code が専門知識を得るために呼び出すこ
|
|||||||
|
|
||||||
### エージェント選択ルール
|
### エージェント選択ルール
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/agents.md#agent-selection-rules)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/agents.md#agent-selection-rules)
|
||||||
|
|
||||||
**優先順位の階層:**
|
**優先順位の階層:**
|
||||||
|
|
||||||
@ -115,11 +115,11 @@ Task Analysis →
|
|||||||
|
|
||||||
## クイックスタートの例
|
## クイックスタートの例
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/agents.md#quick-start-examples)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/agents.md#quick-start-examples)
|
||||||
|
|
||||||
### 手動エージェント呼び出し
|
### 手動エージェント呼び出し
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/agents.md#manual-agent-invocation)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/agents.md#manual-agent-invocation)
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
# Explicitly call specific agents with @agent- prefix
|
# Explicitly call specific agents with @agent- prefix
|
||||||
@ -131,7 +131,7 @@ Task Analysis →
|
|||||||
|
|
||||||
### 自動エージェント調整
|
### 自動エージェント調整
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/agents.md#automatic-agent-coordination)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/agents.md#automatic-agent-coordination)
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
# Commands that trigger auto-activation
|
# Commands that trigger auto-activation
|
||||||
@ -150,7 +150,7 @@ Task Analysis →
|
|||||||
|
|
||||||
### 手動と自動のアプローチを組み合わせる
|
### 手動と自動のアプローチを組み合わせる
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/agents.md#combining-manual-and-auto-approaches)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/agents.md#combining-manual-and-auto-approaches)
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
# Start with command (auto-activation)
|
# Start with command (auto-activation)
|
||||||
@ -165,15 +165,15 @@ Task Analysis →
|
|||||||
|
|
||||||
## SuperClaude エージェントチーム 👥
|
## SuperClaude エージェントチーム 👥
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/agents.md#the-superclaude-agent-team-)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/agents.md#the-superclaude-agent-team-)
|
||||||
|
|
||||||
### アーキテクチャとシステム設計エージェント 🏗️
|
### アーキテクチャとシステム設計エージェント 🏗️
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/agents.md#architecture--system-design-agents-%EF%B8%8F)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/agents.md#architecture--system-design-agents-%EF%B8%8F)
|
||||||
|
|
||||||
### システムアーキテクト 🏢
|
### システムアーキテクト 🏢
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/agents.md#system-architect-)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/agents.md#system-architect-)
|
||||||
|
|
||||||
**専門分野**:スケーラビリティとサービスアーキテクチャに重点を置いた大規模分散システム設計
|
**専門分野**:スケーラビリティとサービスアーキテクチャに重点を置いた大規模分散システム設計
|
||||||
|
|
||||||
@ -199,7 +199,7 @@ Task Analysis →
|
|||||||
|
|
||||||
### 成功基準
|
### 成功基準
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/agents.md#success-criteria)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/agents.md#success-criteria)
|
||||||
|
|
||||||
- [ ] 応答に表れたシステムレベルの思考
|
- [ ] 応答に表れたシステムレベルの思考
|
||||||
- [ ] サービスの境界と統合パターンについて言及する
|
- [ ] サービスの境界と統合パターンについて言及する
|
||||||
@ -216,7 +216,7 @@ Task Analysis →
|
|||||||
|
|
||||||
### バックエンドアーキテクト ⚙️
|
### バックエンドアーキテクト ⚙️
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/agents.md#backend-architect-%EF%B8%8F)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/agents.md#backend-architect-%EF%B8%8F)
|
||||||
|
|
||||||
**専門分野**: APIの信頼性とデータの整合性を重視した堅牢なサーバーサイドシステム設計
|
**専門分野**: APIの信頼性とデータの整合性を重視した堅牢なサーバーサイドシステム設計
|
||||||
|
|
||||||
@ -246,7 +246,7 @@ Task Analysis →
|
|||||||
|
|
||||||
### フロントエンドアーキテクト 🎨
|
### フロントエンドアーキテクト 🎨
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/agents.md#frontend-architect-)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/agents.md#frontend-architect-)
|
||||||
|
|
||||||
**専門分野**: アクセシビリティとユーザーエクスペリエンスを重視した最新の Web アプリケーション アーキテクチャ
|
**専門分野**: アクセシビリティとユーザーエクスペリエンスを重視した最新の Web アプリケーション アーキテクチャ
|
||||||
|
|
||||||
@ -276,7 +276,7 @@ Task Analysis →
|
|||||||
|
|
||||||
### DevOps アーキテクト 🚀
|
### DevOps アーキテクト 🚀
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/agents.md#devops-architect-)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/agents.md#devops-architect-)
|
||||||
|
|
||||||
**専門分野**: 信頼性の高いソフトウェア配信のためのインフラストラクチャ自動化と展開パイプライン設計
|
**専門分野**: 信頼性の高いソフトウェア配信のためのインフラストラクチャ自動化と展開パイプライン設計
|
||||||
|
|
||||||
@ -304,11 +304,11 @@ Task Analysis →
|
|||||||
|
|
||||||
### 品質・分析エージェント 🔍
|
### 品質・分析エージェント 🔍
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/agents.md#quality--analysis-agents-)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/agents.md#quality--analysis-agents-)
|
||||||
|
|
||||||
### セキュリティエンジニア 🔒
|
### セキュリティエンジニア 🔒
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/agents.md#security-engineer-)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/agents.md#security-engineer-)
|
||||||
|
|
||||||
**専門分野**: 脅威モデリングと脆弱性防止に重点を置いたアプリケーション セキュリティ アーキテクチャ
|
**専門分野**: 脅威モデリングと脆弱性防止に重点を置いたアプリケーション セキュリティ アーキテクチャ
|
||||||
|
|
||||||
@ -338,7 +338,7 @@ Task Analysis →
|
|||||||
|
|
||||||
### パフォーマンスエンジニア ⚡
|
### パフォーマンスエンジニア ⚡
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/agents.md#performance-engineer-)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/agents.md#performance-engineer-)
|
||||||
|
|
||||||
**専門分野**:スケーラビリティとリソース効率を重視したシステムパフォーマンスの最適化
|
**専門分野**:スケーラビリティとリソース効率を重視したシステムパフォーマンスの最適化
|
||||||
|
|
||||||
@ -368,7 +368,7 @@ Task Analysis →
|
|||||||
|
|
||||||
### 根本原因分析者 🔍
|
### 根本原因分析者 🔍
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/agents.md#root-cause-analyst-)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/agents.md#root-cause-analyst-)
|
||||||
|
|
||||||
**専門分野**:証拠に基づく分析と仮説検定を用いた体系的な問題調査
|
**専門分野**:証拠に基づく分析と仮説検定を用いた体系的な問題調査
|
||||||
|
|
||||||
@ -398,7 +398,7 @@ Task Analysis →
|
|||||||
|
|
||||||
### 品質エンジニア ✅
|
### 品質エンジニア ✅
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/agents.md#quality-engineer-)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/agents.md#quality-engineer-)
|
||||||
|
|
||||||
**専門分野**:自動化とカバレッジに重点を置いた包括的なテスト戦略と品質保証
|
**専門分野**:自動化とカバレッジに重点を置いた包括的なテスト戦略と品質保証
|
||||||
|
|
||||||
@ -428,7 +428,7 @@ Task Analysis →
|
|||||||
|
|
||||||
### リファクタリングの専門家 🔧
|
### リファクタリングの専門家 🔧
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/agents.md#refactoring-expert-)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/agents.md#refactoring-expert-)
|
||||||
|
|
||||||
**専門分野**:体系的なリファクタリングと技術的負債管理によるコード品質の改善
|
**専門分野**:体系的なリファクタリングと技術的負債管理によるコード品質の改善
|
||||||
|
|
||||||
@ -456,11 +456,11 @@ Task Analysis →
|
|||||||
|
|
||||||
### 専門開発エージェント 🎯
|
### 専門開発エージェント 🎯
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/agents.md#specialized-development-agents-)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/agents.md#specialized-development-agents-)
|
||||||
|
|
||||||
### Python エキスパート 🐍
|
### Python エキスパート 🐍
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/agents.md#python-expert-)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/agents.md#python-expert-)
|
||||||
|
|
||||||
**専門分野**: 最新のフレームワークとパフォーマンスを重視した、本番環境対応の Python 開発
|
**専門分野**: 最新のフレームワークとパフォーマンスを重視した、本番環境対応の Python 開発
|
||||||
|
|
||||||
@ -490,7 +490,7 @@ Task Analysis →
|
|||||||
|
|
||||||
### 要件アナリスト 📝
|
### 要件アナリスト 📝
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/agents.md#requirements-analyst-)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/agents.md#requirements-analyst-)
|
||||||
|
|
||||||
**専門分野**:体系的なステークホルダー分析による要件発見と仕様策定
|
**専門分野**:体系的なステークホルダー分析による要件発見と仕様策定
|
||||||
|
|
||||||
@ -518,11 +518,11 @@ Task Analysis →
|
|||||||
|
|
||||||
### コミュニケーションと学習エージェント 📚
|
### コミュニケーションと学習エージェント 📚
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/agents.md#communication--learning-agents-)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/agents.md#communication--learning-agents-)
|
||||||
|
|
||||||
### テクニカルライター 📚
|
### テクニカルライター 📚
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/agents.md#technical-writer-)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/agents.md#technical-writer-)
|
||||||
|
|
||||||
**専門分野**: 視聴者分析と明確さを重視した技術文書作成とコミュニケーション
|
**専門分野**: 視聴者分析と明確さを重視した技術文書作成とコミュニケーション
|
||||||
|
|
||||||
@ -552,7 +552,7 @@ Task Analysis →
|
|||||||
|
|
||||||
### 学習ガイド 🎓
|
### 学習ガイド 🎓
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/agents.md#learning-guide-)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/agents.md#learning-guide-)
|
||||||
|
|
||||||
**専門分野**:スキル開発とメンターシップに重点を置いた教育コンテンツの設計と漸進的学習
|
**専門分野**:スキル開発とメンターシップに重点を置いた教育コンテンツの設計と漸進的学習
|
||||||
|
|
||||||
@ -582,11 +582,11 @@ Task Analysis →
|
|||||||
|
|
||||||
## エージェントの調整と統合 🤝
|
## エージェントの調整と統合 🤝
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/agents.md#agent-coordination--integration-)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/agents.md#agent-coordination--integration-)
|
||||||
|
|
||||||
### 調整パターン
|
### 調整パターン
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/agents.md#coordination-patterns)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/agents.md#coordination-patterns)
|
||||||
|
|
||||||
**アーキテクチャチーム**:
|
**アーキテクチャチーム**:
|
||||||
|
|
||||||
@ -608,7 +608,7 @@ Task Analysis →
|
|||||||
|
|
||||||
### MCP サーバー統合
|
### MCP サーバー統合
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/agents.md#mcp-server-integration)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/agents.md#mcp-server-integration)
|
||||||
|
|
||||||
**MCP サーバーによる拡張機能**:
|
**MCP サーバーによる拡張機能**:
|
||||||
|
|
||||||
@ -621,20 +621,20 @@ Task Analysis →
|
|||||||
|
|
||||||
### エージェントのアクティベーションのトラブルシューティング
|
### エージェントのアクティベーションのトラブルシューティング
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/agents.md#troubleshooting-agent-activation)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/agents.md#troubleshooting-agent-activation)
|
||||||
|
|
||||||
## トラブルシューティング
|
## トラブルシューティング
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/agents.md#troubleshooting)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/agents.md#troubleshooting)
|
||||||
|
|
||||||
トラブルシューティングのヘルプについては、以下を参照してください。
|
トラブルシューティングのヘルプについては、以下を参照してください。
|
||||||
|
|
||||||
- [よくある問題](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/Reference/common-issues.md)- よくある問題に対するクイック修正
|
- [よくある問題](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/Reference/common-issues.md)- よくある問題に対するクイック修正
|
||||||
- [トラブルシューティングガイド](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/Reference/troubleshooting.md)- 包括的な問題解決
|
- [トラブルシューティングガイド](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/Reference/troubleshooting.md)- 包括的な問題解決
|
||||||
|
|
||||||
### よくある問題
|
### よくある問題
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/agents.md#common-issues)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/agents.md#common-issues)
|
||||||
|
|
||||||
- **エージェントのアクティベーションなし**: ドメインキーワード「セキュリティ」、「パフォーマンス」、「フロントエンド」を使用します
|
- **エージェントのアクティベーションなし**: ドメインキーワード「セキュリティ」、「パフォーマンス」、「フロントエンド」を使用します
|
||||||
- **間違ったエージェントが選択されました**: エージェントのドキュメントでトリガーキーワードを確認してください
|
- **間違ったエージェントが選択されました**: エージェントのドキュメントでトリガーキーワードを確認してください
|
||||||
@ -644,7 +644,7 @@ Task Analysis →
|
|||||||
|
|
||||||
### 即時修正
|
### 即時修正
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/agents.md#immediate-fixes)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/agents.md#immediate-fixes)
|
||||||
|
|
||||||
- **エージェントの強制アクティベーション**: リクエストで明示的なドメインキーワードを使用する
|
- **エージェントの強制アクティベーション**: リクエストで明示的なドメインキーワードを使用する
|
||||||
- **エージェントの選択をリセット**: エージェントの状態をリセットするには、Claude Code セッションを再起動します。
|
- **エージェントの選択をリセット**: エージェントの状態をリセットするには、Claude Code セッションを再起動します。
|
||||||
@ -653,7 +653,7 @@ Task Analysis →
|
|||||||
|
|
||||||
### エージェント固有のトラブルシューティング
|
### エージェント固有のトラブルシューティング
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/agents.md#agent-specific-troubleshooting)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/agents.md#agent-specific-troubleshooting)
|
||||||
|
|
||||||
**セキュリティエージェントなし:**
|
**セキュリティエージェントなし:**
|
||||||
|
|
||||||
@ -697,7 +697,7 @@ Task Analysis →
|
|||||||
|
|
||||||
### サポートレベル
|
### サポートレベル
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/agents.md#support-levels)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/agents.md#support-levels)
|
||||||
|
|
||||||
**クイックフィックス:**
|
**クイックフィックス:**
|
||||||
|
|
||||||
@ -707,13 +707,13 @@ Task Analysis →
|
|||||||
|
|
||||||
**詳細なヘルプ:**
|
**詳細なヘルプ:**
|
||||||
|
|
||||||
- エージェントのインストールに関する問題については、[一般的な問題ガイド](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/Reference/common-issues.md)を参照してください。
|
- エージェントのインストールに関する問題については、[一般的な問題ガイド](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/Reference/common-issues.md)を参照してください。
|
||||||
- 対象エージェントのトリガーキーワードを確認する
|
- 対象エージェントのトリガーキーワードを確認する
|
||||||
|
|
||||||
**専門家によるサポート:**
|
**専門家によるサポート:**
|
||||||
|
|
||||||
- 使用`SuperClaude install --diagnose`
|
- 使用`SuperClaude install --diagnose`
|
||||||
- 協調分析については[診断リファレンスガイド](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/Reference/diagnostic-reference.md)を参照してください
|
- 協調分析については[診断リファレンスガイド](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/Reference/diagnostic-reference.md)を参照してください
|
||||||
|
|
||||||
**コミュニティサポート:**
|
**コミュニティサポート:**
|
||||||
|
|
||||||
@ -722,7 +722,7 @@ Task Analysis →
|
|||||||
|
|
||||||
### 成功の検証
|
### 成功の検証
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/agents.md#success-validation)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/agents.md#success-validation)
|
||||||
|
|
||||||
エージェントの修正を適用した後、次のようにテストします。
|
エージェントの修正を適用した後、次のようにテストします。
|
||||||
|
|
||||||
@ -734,7 +734,7 @@ Task Analysis →
|
|||||||
|
|
||||||
## クイックトラブルシューティング(レガシー)
|
## クイックトラブルシューティング(レガシー)
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/agents.md#quick-troubleshooting-legacy)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/agents.md#quick-troubleshooting-legacy)
|
||||||
|
|
||||||
- **エージェントが有効化されていない場合**→ ドメインキーワード「セキュリティ」、「パフォーマンス」、「フロントエンド」を使用します
|
- **エージェントが有効化されていない場合**→ ドメインキーワード「セキュリティ」、「パフォーマンス」、「フロントエンド」を使用します
|
||||||
- **エージェントが間違っている**→ エージェントのドキュメントでトリガーキーワードを確認してください
|
- **エージェントが間違っている**→ エージェントのドキュメントでトリガーキーワードを確認してください
|
||||||
@ -762,11 +762,11 @@ Task Analysis →
|
|||||||
|
|
||||||
## クイックリファレンス 📋
|
## クイックリファレンス 📋
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/agents.md#quick-reference-)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/agents.md#quick-reference-)
|
||||||
|
|
||||||
### エージェントトリガー検索
|
### エージェントトリガー検索
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/agents.md#agent-trigger-lookup)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/agents.md#agent-trigger-lookup)
|
||||||
|
|
||||||
|トリガータイプ|キーワード/パターン|活性化エージェント|
|
|トリガータイプ|キーワード/パターン|活性化エージェント|
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
@ -786,7 +786,7 @@ Task Analysis →
|
|||||||
|
|
||||||
### コマンドエージェントマッピング
|
### コマンドエージェントマッピング
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/agents.md#command-agent-mapping)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/agents.md#command-agent-mapping)
|
||||||
|
|
||||||
|指示|主な薬剤|サポートエージェント|
|
|指示|主な薬剤|サポートエージェント|
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
@ -801,7 +801,7 @@ Task Analysis →
|
|||||||
|
|
||||||
### 効果的な薬剤の組み合わせ
|
### 効果的な薬剤の組み合わせ
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/agents.md#effective-agent-combinations)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/agents.md#effective-agent-combinations)
|
||||||
|
|
||||||
**開発ワークフロー**:
|
**開発ワークフロー**:
|
||||||
|
|
||||||
@ -822,11 +822,11 @@ Task Analysis →
|
|||||||
|
|
||||||
## ベストプラクティス💡
|
## ベストプラクティス💡
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/agents.md#best-practices-)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/agents.md#best-practices-)
|
||||||
|
|
||||||
### はじめに(シンプルなアプローチ)
|
### はじめに(シンプルなアプローチ)
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/agents.md#getting-started-simple-approach)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/agents.md#getting-started-simple-approach)
|
||||||
|
|
||||||
**自然言語ファースト:**
|
**自然言語ファースト:**
|
||||||
|
|
||||||
@ -837,7 +837,7 @@ Task Analysis →
|
|||||||
|
|
||||||
### エージェントの選択の最適化
|
### エージェントの選択の最適化
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/agents.md#optimizing-agent-selection)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/agents.md#optimizing-agent-selection)
|
||||||
|
|
||||||
**効果的なキーワードの使用法:**
|
**効果的なキーワードの使用法:**
|
||||||
|
|
||||||
@ -859,7 +859,7 @@ Task Analysis →
|
|||||||
|
|
||||||
### 一般的な使用パターン
|
### 一般的な使用パターン
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/agents.md#common-usage-patterns)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/agents.md#common-usage-patterns)
|
||||||
|
|
||||||
**開発ワークフロー:**
|
**開発ワークフロー:**
|
||||||
|
|
||||||
@ -895,7 +895,7 @@ Task Analysis →
|
|||||||
|
|
||||||
### 高度なエージェント調整
|
### 高度なエージェント調整
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/agents.md#advanced-agent-coordination)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/agents.md#advanced-agent-coordination)
|
||||||
|
|
||||||
**マルチドメインプロジェクト:**
|
**マルチドメインプロジェクト:**
|
||||||
|
|
||||||
@ -923,7 +923,7 @@ Task Analysis →
|
|||||||
|
|
||||||
### 品質重視の開発
|
### 品質重視の開発
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/agents.md#quality-driven-development)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/agents.md#quality-driven-development)
|
||||||
|
|
||||||
**セキュリティ第一のアプローチ:** 開発リクエストには常にセキュリティに関する考慮事項を含め、ドメインスペシャリストとともにセキュリティエンジニアを自動的に関与させます。
|
**セキュリティ第一のアプローチ:** 開発リクエストには常にセキュリティに関する考慮事項を含め、ドメインスペシャリストとともにセキュリティエンジニアを自動的に関与させます。
|
||||||
|
|
||||||
@ -937,11 +937,11 @@ Task Analysis →
|
|||||||
|
|
||||||
## エージェントインテリジェンスを理解する🧠
|
## エージェントインテリジェンスを理解する🧠
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/agents.md#understanding-agent-intelligence-)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/agents.md#understanding-agent-intelligence-)
|
||||||
|
|
||||||
### エージェントを効果的にする要素
|
### エージェントを効果的にする要素
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/agents.md#what-makes-agents-effective)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/agents.md#what-makes-agents-effective)
|
||||||
|
|
||||||
**ドメイン専門知識**: 各エージェントは、それぞれのドメインに特有の専門的な知識パターン、行動アプローチ、問題解決方法論を備えています。
|
**ドメイン専門知識**: 各エージェントは、それぞれのドメインに特有の専門的な知識パターン、行動アプローチ、問題解決方法論を備えています。
|
||||||
|
|
||||||
@ -953,7 +953,7 @@ Task Analysis →
|
|||||||
|
|
||||||
### エージェント vs. 従来のAI
|
### エージェント vs. 従来のAI
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/agents.md#agent-vs-traditional-ai)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/agents.md#agent-vs-traditional-ai)
|
||||||
|
|
||||||
**従来のアプローチ**: 単一のAIが、さまざまなレベルの専門知識を持つすべてのドメインを処理します。 **エージェントアプローチ**: 専門のエキスパートが、深いドメイン知識と集中的な問題解決で協力します。
|
**従来のアプローチ**: 単一のAIが、さまざまなレベルの専門知識を持つすべてのドメインを処理します。 **エージェントアプローチ**: 専門のエキスパートが、深いドメイン知識と集中的な問題解決で協力します。
|
||||||
|
|
||||||
@ -966,7 +966,7 @@ Task Analysis →
|
|||||||
|
|
||||||
### システムを信頼し、パターンを理解する
|
### システムを信頼し、パターンを理解する
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/agents.md#trust-the-system-understand-the-patterns)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/agents.md#trust-the-system-understand-the-patterns)
|
||||||
|
|
||||||
**期待すること**:
|
**期待すること**:
|
||||||
|
|
||||||
@ -986,36 +986,36 @@ Task Analysis →
|
|||||||
|
|
||||||
## 関連リソース 📚
|
## 関連リソース 📚
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/agents.md#related-resources-)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/agents.md#related-resources-)
|
||||||
|
|
||||||
### 必須ドキュメント
|
### 必須ドキュメント
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/agents.md#essential-documentation)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/agents.md#essential-documentation)
|
||||||
|
|
||||||
- **[コマンドガイド](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/commands.md)**- 最適なエージェント調整をトリガーするSuperClaudeコマンドをマスターする
|
- **[コマンドガイド](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/commands.md)**- 最適なエージェント調整をトリガーするSuperClaudeコマンドをマスターする
|
||||||
- **[MCP サーバー](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/mcp-servers.md)**- 専用ツールの統合によるエージェント機能の強化
|
- **[MCP サーバー](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/mcp-servers.md)**- 専用ツールの統合によるエージェント機能の強化
|
||||||
- **[セッション管理](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/session-management.md)**- 永続的なエージェントコンテキストによる長期ワークフロー
|
- **[セッション管理](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/session-management.md)**- 永続的なエージェントコンテキストによる長期ワークフロー
|
||||||
|
|
||||||
### 高度な使用法
|
### 高度な使用法
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/agents.md#advanced-usage)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/agents.md#advanced-usage)
|
||||||
|
|
||||||
- **[行動モード](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/modes.md)**- エージェントの調整を強化するためのコンテキスト最適化
|
- **[行動モード](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/modes.md)**- エージェントの調整を強化するためのコンテキスト最適化
|
||||||
- **[はじめに](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/Getting-Started/quick-start.md)**- エージェントの最適化のための専門家のテクニック
|
- **[はじめに](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/Getting-Started/quick-start.md)**- エージェントの最適化のための専門家のテクニック
|
||||||
- **[例のクックブック](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/Reference/examples-cookbook.md)**- 現実世界のエージェントの調整パターン
|
- **[例のクックブック](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/Reference/examples-cookbook.md)**- 現実世界のエージェントの調整パターン
|
||||||
|
|
||||||
### 開発リソース
|
### 開発リソース
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/agents.md#development-resources)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/agents.md#development-resources)
|
||||||
|
|
||||||
- **[技術アーキテクチャ](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/Developer-Guide/technical-architecture.md)**- SuperClaude のエージェント システム設計を理解する
|
- **[技術アーキテクチャ](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/Developer-Guide/technical-architecture.md)**- SuperClaude のエージェント システム設計を理解する
|
||||||
- **[貢献](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/Developer-Guide/contributing-code.md)**- エージェントの機能と調整パターンの拡張
|
- **[貢献](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/Developer-Guide/contributing-code.md)**- エージェントの機能と調整パターンの拡張
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## エージェントとしての道のり 🚀
|
## エージェントとしての道のり 🚀
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/agents.md#your-agent-journey-)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/agents.md#your-agent-journey-)
|
||||||
|
|
||||||
**第1週:自然な使用法** 自然な言語による説明から始めましょう。どのエージェントが、そしてなぜアクティブになるのかに注目しましょう。プロセスを考えすぎずに、キーワードのパターンに対する直感を養います。
|
**第1週:自然な使用法** 自然な言語による説明から始めましょう。どのエージェントが、そしてなぜアクティブになるのかに注目しましょう。プロセスを考えすぎずに、キーワードのパターンに対する直感を養います。
|
||||||
|
|
||||||
@ -1,12 +1,12 @@
|
|||||||
# SuperClaude コマンドガイド
|
# SuperClaude コマンドガイド
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/commands.md#superclaude-commands-guide)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/commands.md#superclaude-commands-guide)
|
||||||
|
|
||||||
`/sc:*`SuperClaude は、ワークフロー用コマンドと`@agent-*`スペシャリスト用コマンドの 21 個の Claude Code コマンドを提供します。
|
`/sc:*`SuperClaude は、ワークフロー用コマンドと`@agent-*`スペシャリスト用コマンドの 21 個の Claude Code コマンドを提供します。
|
||||||
|
|
||||||
## コマンドの種類
|
## コマンドの種類
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/commands.md#command-types)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/commands.md#command-types)
|
||||||
|
|
||||||
|タイプ|使用場所|形式|例|
|
|タイプ|使用場所|形式|例|
|
||||||
|---|---|---|---|
|
|---|---|---|---|
|
||||||
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
## クイックテスト
|
## クイックテスト
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/commands.md#quick-test)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/commands.md#quick-test)
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
# Terminal: Verify installation
|
# Terminal: Verify installation
|
||||||
@ -32,11 +32,11 @@ python3 -m SuperClaude --version
|
|||||||
|
|
||||||
## 🎯 SuperClaude コマンドの理解
|
## 🎯 SuperClaude コマンドの理解
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/commands.md#-understanding-superclaude-commands)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/commands.md#-understanding-superclaude-commands)
|
||||||
|
|
||||||
## SuperClaudeの仕組み
|
## SuperClaudeの仕組み
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/commands.md#how-superclaude-works)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/commands.md#how-superclaude-works)
|
||||||
|
|
||||||
SuperClaude は、Claude Code が特殊な動作を実行するために読み込む動作コンテキストファイルを提供します。 と入力すると`/sc:implement`、Claude Code は`implement.md`コンテキストファイルを読み込み、その動作指示に従います。
|
SuperClaude は、Claude Code が特殊な動作を実行するために読み込む動作コンテキストファイルを提供します。 と入力すると`/sc:implement`、Claude Code は`implement.md`コンテキストファイルを読み込み、その動作指示に従います。
|
||||||
|
|
||||||
@ -44,7 +44,7 @@ SuperClaude は、Claude Code が特殊な動作を実行するために読み
|
|||||||
|
|
||||||
### コマンドの種類:
|
### コマンドの種類:
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/commands.md#command-types-1)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/commands.md#command-types-1)
|
||||||
|
|
||||||
- **スラッシュコマンド**(`/sc:*`):ワークフローパターンと動作モードをトリガーする
|
- **スラッシュコマンド**(`/sc:*`):ワークフローパターンと動作モードをトリガーする
|
||||||
- **エージェントの呼び出し**(`@agent-*`):特定のドメインスペシャリストを手動で起動する
|
- **エージェントの呼び出し**(`@agent-*`):特定のドメインスペシャリストを手動で起動する
|
||||||
@ -52,10 +52,10 @@ SuperClaude は、Claude Code が特殊な動作を実行するために読み
|
|||||||
|
|
||||||
### コンテキストメカニズム:
|
### コンテキストメカニズム:
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/commands.md#the-context-mechanism)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/commands.md#the-context-mechanism)
|
||||||
|
|
||||||
1. **ユーザー入力**: 入力する`/sc:implement "auth system"`
|
1. **ユーザー入力**: 入力する`/sc:implement "auth system"`
|
||||||
2. **コンテキスト読み込み**: クロードコード読み取り`~/.claude/SuperClaude/Commands/implement.md`
|
2. **コンテキスト読み込み**: クロードコード読み取り`~/.claude/superclaude/Commands/implement.md`
|
||||||
3. **行動の採用**:クロードはドメインの専門知識、ツールの選択、検証パターンを適用します
|
3. **行動の採用**:クロードはドメインの専門知識、ツールの選択、検証パターンを適用します
|
||||||
4. **強化された出力**: セキュリティ上の考慮事項とベストプラクティスを備えた構造化された実装
|
4. **強化された出力**: セキュリティ上の考慮事項とベストプラクティスを備えた構造化された実装
|
||||||
|
|
||||||
@ -63,7 +63,7 @@ SuperClaude は、Claude Code が特殊な動作を実行するために読み
|
|||||||
|
|
||||||
### インストールコマンドと使用コマンド
|
### インストールコマンドと使用コマンド
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/commands.md#installation-vs-usage-commands)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/commands.md#installation-vs-usage-commands)
|
||||||
|
|
||||||
**🖥️ ターミナルコマンド**(実際の CLI ソフトウェア):
|
**🖥️ ターミナルコマンド**(実際の CLI ソフトウェア):
|
||||||
|
|
||||||
@ -83,11 +83,11 @@ SuperClaude は、Claude Code が特殊な動作を実行するために読み
|
|||||||
|
|
||||||
## 🧪 セットアップのテスト
|
## 🧪 セットアップのテスト
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/commands.md#-testing-your-setup)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/commands.md#-testing-your-setup)
|
||||||
|
|
||||||
### 🖥️ ターミナル検証(ターミナル/CMDで実行)
|
### 🖥️ ターミナル検証(ターミナル/CMDで実行)
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/commands.md#%EF%B8%8F-terminal-verification-run-in-terminalcmd)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/commands.md#%EF%B8%8F-terminal-verification-run-in-terminalcmd)
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
# Verify SuperClaude is working (primary method)
|
# Verify SuperClaude is working (primary method)
|
||||||
@ -104,7 +104,7 @@ python3 -m SuperClaude install --list-components | grep mcp
|
|||||||
|
|
||||||
### 💬 クロードコードテスト(クロードコードチャットに入力)
|
### 💬 クロードコードテスト(クロードコードチャットに入力)
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/commands.md#-claude-code-testing-type-in-claude-code-chat)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/commands.md#-claude-code-testing-type-in-claude-code-chat)
|
||||||
|
|
||||||
```
|
```
|
||||||
# Test basic /sc: command
|
# Test basic /sc: command
|
||||||
@ -116,11 +116,11 @@ python3 -m SuperClaude install --list-components | grep mcp
|
|||||||
# Example behavior: List of available commands
|
# Example behavior: List of available commands
|
||||||
```
|
```
|
||||||
|
|
||||||
**テストが失敗した場合**:[インストールガイド](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/Getting-Started/installation.md)または[トラブルシューティングを確認してください](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/commands.md#troubleshooting)
|
**テストが失敗した場合**:[インストールガイド](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/Getting-Started/installation.md)または[トラブルシューティングを確認してください](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/commands.md#troubleshooting)
|
||||||
|
|
||||||
### 📝 コマンドクイックリファレンス
|
### 📝 コマンドクイックリファレンス
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/commands.md#-command-quick-reference)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/commands.md#-command-quick-reference)
|
||||||
|
|
||||||
|コマンドタイプ|走る場所|形式|目的|例|
|
|コマンドタイプ|走る場所|形式|目的|例|
|
||||||
|---|---|---|---|---|
|
|---|---|---|---|---|
|
||||||
@ -134,25 +134,25 @@ python3 -m SuperClaude install --list-components | grep mcp
|
|||||||
|
|
||||||
## 目次
|
## 目次
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/commands.md#table-of-contents)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/commands.md#table-of-contents)
|
||||||
|
|
||||||
- [必須コマンド](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/commands.md#essential-commands)- ここから始めましょう(8つのコアコマンド)
|
- [必須コマンド](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/commands.md#essential-commands)- ここから始めましょう(8つのコアコマンド)
|
||||||
- [一般的なワークフロー](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/commands.md#common-workflows)- 機能するコマンドの組み合わせ
|
- [一般的なワークフロー](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/commands.md#common-workflows)- 機能するコマンドの組み合わせ
|
||||||
- [完全なコマンドリファレンス](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/commands.md#full-command-reference)- カテゴリ別に整理された全21個のコマンド
|
- [完全なコマンドリファレンス](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/commands.md#full-command-reference)- カテゴリ別に整理された全21個のコマンド
|
||||||
- [トラブルシューティング](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/commands.md#troubleshooting)- よくある問題と解決策
|
- [トラブルシューティング](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/commands.md#troubleshooting)- よくある問題と解決策
|
||||||
- [コマンドインデックス](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/commands.md#command-index)- カテゴリ別にコマンドを検索
|
- [コマンドインデックス](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/commands.md#command-index)- カテゴリ別にコマンドを検索
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 必須コマンド
|
## 必須コマンド
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/commands.md#essential-commands)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/commands.md#essential-commands)
|
||||||
|
|
||||||
**即時の生産性向上のためのコアワークフロー コマンド:**
|
**即時の生産性向上のためのコアワークフロー コマンド:**
|
||||||
|
|
||||||
### `/sc:brainstorm`- プロジェクト発見
|
### `/sc:brainstorm`- プロジェクト発見
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/commands.md#scbrainstorm---project-discovery)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/commands.md#scbrainstorm---project-discovery)
|
||||||
|
|
||||||
**目的**: 対話型の要件検出とプロジェクト計画
|
**目的**: 対話型の要件検出とプロジェクト計画
|
||||||
**構文**:`/sc:brainstorm "your idea"` `[--strategy systematic|creative]`
|
**構文**:`/sc:brainstorm "your idea"` `[--strategy systematic|creative]`
|
||||||
@ -165,7 +165,7 @@ python3 -m SuperClaude install --list-components | grep mcp
|
|||||||
|
|
||||||
### `/sc:implement`- 機能開発
|
### `/sc:implement`- 機能開発
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/commands.md#scimplement---feature-development)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/commands.md#scimplement---feature-development)
|
||||||
|
|
||||||
**目的**: インテリジェントなスペシャリストルーティングによるフルスタック機能の実装
|
**目的**: インテリジェントなスペシャリストルーティングによるフルスタック機能の実装
|
||||||
**構文**:`/sc:implement "feature description"` `[--type frontend|backend|fullstack] [--focus security|performance]`
|
**構文**:`/sc:implement "feature description"` `[--type frontend|backend|fullstack] [--focus security|performance]`
|
||||||
@ -179,7 +179,7 @@ python3 -m SuperClaude install --list-components | grep mcp
|
|||||||
|
|
||||||
### `/sc:analyze`- コード評価
|
### `/sc:analyze`- コード評価
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/commands.md#scanalyze---code-assessment)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/commands.md#scanalyze---code-assessment)
|
||||||
|
|
||||||
**目的**: 品質、セキュリティ、パフォーマンスにわたる包括的なコード分析
|
**目的**: 品質、セキュリティ、パフォーマンスにわたる包括的なコード分析
|
||||||
**構文**:`/sc:analyze [path]` `[--focus quality|security|performance|architecture]`
|
**構文**:`/sc:analyze [path]` `[--focus quality|security|performance|architecture]`
|
||||||
@ -192,7 +192,7 @@ python3 -m SuperClaude install --list-components | grep mcp
|
|||||||
|
|
||||||
### `/sc:troubleshoot`- 問題診断
|
### `/sc:troubleshoot`- 問題診断
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/commands.md#sctroubleshoot---problem-diagnosis)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/commands.md#sctroubleshoot---problem-diagnosis)
|
||||||
|
|
||||||
**目的**: 根本原因分析による体系的な問題診断
|
**目的**: 根本原因分析による体系的な問題診断
|
||||||
**構文**:`/sc:troubleshoot "issue description"` `[--type build|runtime|performance]`
|
**構文**:`/sc:troubleshoot "issue description"` `[--type build|runtime|performance]`
|
||||||
@ -205,7 +205,7 @@ python3 -m SuperClaude install --list-components | grep mcp
|
|||||||
|
|
||||||
### `/sc:test`- 品質保証
|
### `/sc:test`- 品質保証
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/commands.md#sctest---quality-assurance)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/commands.md#sctest---quality-assurance)
|
||||||
|
|
||||||
**目的**: カバレッジ分析による包括的なテスト
|
**目的**: カバレッジ分析による包括的なテスト
|
||||||
**構文**:`/sc:test` `[--type unit|integration|e2e] [--coverage] [--fix]`
|
**構文**:`/sc:test` `[--type unit|integration|e2e] [--coverage] [--fix]`
|
||||||
@ -218,7 +218,7 @@ python3 -m SuperClaude install --list-components | grep mcp
|
|||||||
|
|
||||||
### `/sc:improve`- コード強化
|
### `/sc:improve`- コード強化
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/commands.md#scimprove---code-enhancement)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/commands.md#scimprove---code-enhancement)
|
||||||
|
|
||||||
**目的**: 体系的なコードの改善と最適化を適用する
|
**目的**: 体系的なコードの改善と最適化を適用する
|
||||||
**構文**:`/sc:improve [path]` `[--type performance|quality|security] [--preview]`
|
**構文**:`/sc:improve [path]` `[--type performance|quality|security] [--preview]`
|
||||||
@ -231,7 +231,7 @@ python3 -m SuperClaude install --list-components | grep mcp
|
|||||||
|
|
||||||
### `/sc:document`- ドキュメント生成
|
### `/sc:document`- ドキュメント生成
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/commands.md#scdocument---documentation-generation)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/commands.md#scdocument---documentation-generation)
|
||||||
|
|
||||||
**目的**: コードとAPIの包括的なドキュメントを生成する
|
**目的**: コードとAPIの包括的なドキュメントを生成する
|
||||||
**構文**:`/sc:document [path]` `[--type api|user-guide|technical] [--format markdown|html]`
|
**構文**:`/sc:document [path]` `[--type api|user-guide|technical] [--format markdown|html]`
|
||||||
@ -244,7 +244,7 @@ python3 -m SuperClaude install --list-components | grep mcp
|
|||||||
|
|
||||||
### `/sc:workflow`- 実装計画
|
### `/sc:workflow`- 実装計画
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/commands.md#scworkflow---implementation-planning)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/commands.md#scworkflow---implementation-planning)
|
||||||
|
|
||||||
**目的**: 要件から構造化された実装計画を生成する
|
**目的**: 要件から構造化された実装計画を生成する
|
||||||
**構文**:`/sc:workflow "feature description"` `[--strategy agile|waterfall] [--format markdown]`
|
**構文**:`/sc:workflow "feature description"` `[--strategy agile|waterfall] [--format markdown]`
|
||||||
@ -259,13 +259,13 @@ python3 -m SuperClaude install --list-components | grep mcp
|
|||||||
|
|
||||||
## 一般的なワークフロー
|
## 一般的なワークフロー
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/commands.md#common-workflows)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/commands.md#common-workflows)
|
||||||
|
|
||||||
**実証済みのコマンドの組み合わせ:**
|
**実証済みのコマンドの組み合わせ:**
|
||||||
|
|
||||||
### 新しいプロジェクトのセットアップ
|
### 新しいプロジェクトのセットアップ
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/commands.md#new-project-setup)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/commands.md#new-project-setup)
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
/sc:brainstorm "project concept" # Define requirements
|
/sc:brainstorm "project concept" # Define requirements
|
||||||
@ -275,7 +275,7 @@ python3 -m SuperClaude install --list-components | grep mcp
|
|||||||
|
|
||||||
### 機能開発
|
### 機能開発
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/commands.md#feature-development)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/commands.md#feature-development)
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
/sc:implement "feature name" # Build the feature
|
/sc:implement "feature name" # Build the feature
|
||||||
@ -285,7 +285,7 @@ python3 -m SuperClaude install --list-components | grep mcp
|
|||||||
|
|
||||||
### コード品質の改善
|
### コード品質の改善
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/commands.md#code-quality-improvement)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/commands.md#code-quality-improvement)
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
/sc:analyze --focus quality # Assess current state
|
/sc:analyze --focus quality # Assess current state
|
||||||
@ -295,7 +295,7 @@ python3 -m SuperClaude install --list-components | grep mcp
|
|||||||
|
|
||||||
### バグ調査
|
### バグ調査
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/commands.md#bug-investigation)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/commands.md#bug-investigation)
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
/sc:troubleshoot "issue description" # Diagnose the problem
|
/sc:troubleshoot "issue description" # Diagnose the problem
|
||||||
@ -305,11 +305,11 @@ python3 -m SuperClaude install --list-components | grep mcp
|
|||||||
|
|
||||||
## 完全なコマンドリファレンス
|
## 完全なコマンドリファレンス
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/commands.md#full-command-reference)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/commands.md#full-command-reference)
|
||||||
|
|
||||||
### 開発コマンド
|
### 開発コマンド
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/commands.md#development-commands)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/commands.md#development-commands)
|
||||||
|
|
||||||
|指示|目的|最適な用途|
|
|指示|目的|最適な用途|
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
@ -320,7 +320,7 @@ python3 -m SuperClaude install --list-components | grep mcp
|
|||||||
|
|
||||||
### 分析コマンド
|
### 分析コマンド
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/commands.md#analysis-commands)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/commands.md#analysis-commands)
|
||||||
|
|
||||||
|指示|目的|最適な用途|
|
|指示|目的|最適な用途|
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
@ -330,7 +330,7 @@ python3 -m SuperClaude install --list-components | grep mcp
|
|||||||
|
|
||||||
### 品質コマンド
|
### 品質コマンド
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/commands.md#quality-commands)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/commands.md#quality-commands)
|
||||||
|
|
||||||
|指示|目的|最適な用途|
|
|指示|目的|最適な用途|
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
@ -341,7 +341,7 @@ python3 -m SuperClaude install --list-components | grep mcp
|
|||||||
|
|
||||||
### プロジェクト管理
|
### プロジェクト管理
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/commands.md#project-management)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/commands.md#project-management)
|
||||||
|
|
||||||
|指示|目的|最適な用途|
|
|指示|目的|最適な用途|
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
@ -351,7 +351,7 @@ python3 -m SuperClaude install --list-components | grep mcp
|
|||||||
|
|
||||||
### ユーティリティコマンド
|
### ユーティリティコマンド
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/commands.md#utility-commands)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/commands.md#utility-commands)
|
||||||
|
|
||||||
|指示|目的|最適な用途|
|
|指示|目的|最適な用途|
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
@ -360,7 +360,7 @@ python3 -m SuperClaude install --list-components | grep mcp
|
|||||||
|
|
||||||
### セッションコマンド
|
### セッションコマンド
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/commands.md#session-commands)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/commands.md#session-commands)
|
||||||
|
|
||||||
|指示|目的|最適な用途|
|
|指示|目的|最適な用途|
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
@ -373,7 +373,7 @@ python3 -m SuperClaude install --list-components | grep mcp
|
|||||||
|
|
||||||
## コマンドインデックス
|
## コマンドインデックス
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/commands.md#command-index)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/commands.md#command-index)
|
||||||
|
|
||||||
**機能別:**
|
**機能別:**
|
||||||
|
|
||||||
@ -392,7 +392,7 @@ python3 -m SuperClaude install --list-components | grep mcp
|
|||||||
|
|
||||||
## トラブルシューティング
|
## トラブルシューティング
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/commands.md#troubleshooting)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/commands.md#troubleshooting)
|
||||||
|
|
||||||
**コマンドの問題:**
|
**コマンドの問題:**
|
||||||
|
|
||||||
@ -404,12 +404,12 @@ python3 -m SuperClaude install --list-components | grep mcp
|
|||||||
|
|
||||||
- セッションをリセット:`/sc:load`再初期化する
|
- セッションをリセット:`/sc:load`再初期化する
|
||||||
- ステータスを確認:`SuperClaude install --list-components`
|
- ステータスを確認:`SuperClaude install --list-components`
|
||||||
- ヘルプ:[トラブルシューティングガイド](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/Reference/troubleshooting.md)
|
- ヘルプ:[トラブルシューティングガイド](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/Reference/troubleshooting.md)
|
||||||
|
|
||||||
## 次のステップ
|
## 次のステップ
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/commands.md#next-steps)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/commands.md#next-steps)
|
||||||
|
|
||||||
- [フラグガイド](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/flags.md)- コマンドの動作を制御する
|
- [フラグガイド](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/flags.md)- コマンドの動作を制御する
|
||||||
- [エージェントガイド](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/agents.md)- スペシャリストのアクティベーション
|
- [エージェントガイド](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/agents.md)- スペシャリストのアクティベーション
|
||||||
- [例のクックブック](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/Reference/examples-cookbook.md)- 実際の使用パターン
|
- [例のクックブック](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/Reference/examples-cookbook.md)- 実際の使用パターン
|
||||||
@ -1,16 +1,16 @@
|
|||||||
# SuperClaude フラグガイド 🏁
|
# SuperClaude フラグガイド 🏁
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/flags.md#superclaude-flags-guide-)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/flags.md#superclaude-flags-guide-)
|
||||||
|
|
||||||
**ほとんどのフラグは自動的にアクティブになります**。Claude Code は、リクエスト内のキーワードとパターンに基づいて適切なコンテキストを実行するための動作指示を読み取ります。
|
**ほとんどのフラグは自動的にアクティブになります**。Claude Code は、リクエスト内のキーワードとパターンに基づいて適切なコンテキストを実行するための動作指示を読み取ります。
|
||||||
|
|
||||||
## 必須の自動アクティベーションフラグ(ユースケースの90%)
|
## 必須の自動アクティベーションフラグ(ユースケースの90%)
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/flags.md#essential-auto-activation-flags-90-of-use-cases)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/flags.md#essential-auto-activation-flags-90-of-use-cases)
|
||||||
|
|
||||||
### コア分析フラグ
|
### コア分析フラグ
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/flags.md#core-analysis-flags)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/flags.md#core-analysis-flags)
|
||||||
|
|
||||||
|フラグ|起動時|何をするのか|
|
|フラグ|起動時|何をするのか|
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
### MCP サーバーフラグ
|
### MCP サーバーフラグ
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/flags.md#mcp-server-flags)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/flags.md#mcp-server-flags)
|
||||||
|
|
||||||
|フラグ|サーバ|目的|自動トリガー|
|
|フラグ|サーバ|目的|自動トリガー|
|
||||||
|---|---|---|---|
|
|---|---|---|---|
|
||||||
@ -33,7 +33,7 @@
|
|||||||
|
|
||||||
### 動作モードフラグ
|
### 動作モードフラグ
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/flags.md#behavioral-mode-flags)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/flags.md#behavioral-mode-flags)
|
||||||
|
|
||||||
|フラグ|起動時|何をするのか|
|
|フラグ|起動時|何をするのか|
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
@ -45,7 +45,7 @@
|
|||||||
|
|
||||||
### 実行制御フラグ
|
### 実行制御フラグ
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/flags.md#execution-control-flags)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/flags.md#execution-control-flags)
|
||||||
|
|
||||||
|フラグ|起動時|何をするのか|
|
|フラグ|起動時|何をするのか|
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
@ -56,11 +56,11 @@
|
|||||||
|
|
||||||
## コマンド固有のフラグ
|
## コマンド固有のフラグ
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/flags.md#command-specific-flags)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/flags.md#command-specific-flags)
|
||||||
|
|
||||||
### 分析コマンドフラグ(`/sc:analyze`)
|
### 分析コマンドフラグ(`/sc:analyze`)
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/flags.md#analysis-command-flags-scanalyze)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/flags.md#analysis-command-flags-scanalyze)
|
||||||
|
|
||||||
|フラグ|目的|価値観|
|
|フラグ|目的|価値観|
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
@ -70,7 +70,7 @@
|
|||||||
|
|
||||||
### ビルドコマンドフラグ(`/sc:build`)
|
### ビルドコマンドフラグ(`/sc:build`)
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/flags.md#build-command-flags-scbuild)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/flags.md#build-command-flags-scbuild)
|
||||||
|
|
||||||
|フラグ|目的|価値観|
|
|フラグ|目的|価値観|
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
@ -81,7 +81,7 @@
|
|||||||
|
|
||||||
### 設計コマンドフラグ(`/sc:design`)
|
### 設計コマンドフラグ(`/sc:design`)
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/flags.md#design-command-flags-scdesign)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/flags.md#design-command-flags-scdesign)
|
||||||
|
|
||||||
|フラグ|目的|価値観|
|
|フラグ|目的|価値観|
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
@ -90,7 +90,7 @@
|
|||||||
|
|
||||||
### コマンドフラグの説明(`/sc:explain`)
|
### コマンドフラグの説明(`/sc:explain`)
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/flags.md#explain-command-flags-scexplain)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/flags.md#explain-command-flags-scexplain)
|
||||||
|
|
||||||
|フラグ|目的|価値観|
|
|フラグ|目的|価値観|
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
@ -100,7 +100,7 @@
|
|||||||
|
|
||||||
### コマンドフラグの改善(`/sc:improve`)
|
### コマンドフラグの改善(`/sc:improve`)
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/flags.md#improve-command-flags-scimprove)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/flags.md#improve-command-flags-scimprove)
|
||||||
|
|
||||||
|フラグ|目的|価値観|
|
|フラグ|目的|価値観|
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
@ -111,7 +111,7 @@
|
|||||||
|
|
||||||
### タスクコマンドフラグ(`/sc:task`)
|
### タスクコマンドフラグ(`/sc:task`)
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/flags.md#task-command-flags-sctask)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/flags.md#task-command-flags-sctask)
|
||||||
|
|
||||||
|フラグ|目的|価値観|
|
|フラグ|目的|価値観|
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
@ -121,7 +121,7 @@
|
|||||||
|
|
||||||
### ワークフローコマンドフラグ(`/sc:workflow`)
|
### ワークフローコマンドフラグ(`/sc:workflow`)
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/flags.md#workflow-command-flags-scworkflow)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/flags.md#workflow-command-flags-scworkflow)
|
||||||
|
|
||||||
|フラグ|目的|価値観|
|
|フラグ|目的|価値観|
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
@ -131,7 +131,7 @@
|
|||||||
|
|
||||||
### コマンドフラグのトラブルシューティング ( `/sc:troubleshoot`)
|
### コマンドフラグのトラブルシューティング ( `/sc:troubleshoot`)
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/flags.md#troubleshoot-command-flags-sctroubleshoot)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/flags.md#troubleshoot-command-flags-sctroubleshoot)
|
||||||
|
|
||||||
|フラグ|目的|価値観|
|
|フラグ|目的|価値観|
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
@ -141,7 +141,7 @@
|
|||||||
|
|
||||||
### クリーンアップコマンドフラグ(`/sc:cleanup`)
|
### クリーンアップコマンドフラグ(`/sc:cleanup`)
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/flags.md#cleanup-command-flags-sccleanup)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/flags.md#cleanup-command-flags-sccleanup)
|
||||||
|
|
||||||
|フラグ|目的|価値観|
|
|フラグ|目的|価値観|
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
@ -152,7 +152,7 @@
|
|||||||
|
|
||||||
### コマンドフラグの推定(`/sc:estimate`)
|
### コマンドフラグの推定(`/sc:estimate`)
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/flags.md#estimate-command-flags-scestimate)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/flags.md#estimate-command-flags-scestimate)
|
||||||
|
|
||||||
|フラグ|目的|価値観|
|
|フラグ|目的|価値観|
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
@ -162,7 +162,7 @@
|
|||||||
|
|
||||||
### インデックスコマンドフラグ(`/sc:index`)
|
### インデックスコマンドフラグ(`/sc:index`)
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/flags.md#index-command-flags-scindex)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/flags.md#index-command-flags-scindex)
|
||||||
|
|
||||||
|フラグ|目的|価値観|
|
|フラグ|目的|価値観|
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
@ -171,7 +171,7 @@
|
|||||||
|
|
||||||
### コマンドフラグを反映する ( `/sc:reflect`)
|
### コマンドフラグを反映する ( `/sc:reflect`)
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/flags.md#reflect-command-flags-screflect)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/flags.md#reflect-command-flags-screflect)
|
||||||
|
|
||||||
|フラグ|目的|価値観|
|
|フラグ|目的|価値観|
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
@ -181,7 +181,7 @@
|
|||||||
|
|
||||||
### スポーンコマンドフラグ(`/sc:spawn`)
|
### スポーンコマンドフラグ(`/sc:spawn`)
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/flags.md#spawn-command-flags-scspawn)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/flags.md#spawn-command-flags-scspawn)
|
||||||
|
|
||||||
|フラグ|目的|価値観|
|
|フラグ|目的|価値観|
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
@ -190,7 +190,7 @@
|
|||||||
|
|
||||||
### Gitコマンドフラグ(`/sc:git`)
|
### Gitコマンドフラグ(`/sc:git`)
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/flags.md#git-command-flags-scgit)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/flags.md#git-command-flags-scgit)
|
||||||
|
|
||||||
|フラグ|目的|価値観|
|
|フラグ|目的|価値観|
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
@ -199,7 +199,7 @@
|
|||||||
|
|
||||||
### 選択ツールコマンドフラグ ( `/sc:select-tool`)
|
### 選択ツールコマンドフラグ ( `/sc:select-tool`)
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/flags.md#select-tool-command-flags-scselect-tool)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/flags.md#select-tool-command-flags-scselect-tool)
|
||||||
|
|
||||||
|フラグ|目的|価値観|
|
|フラグ|目的|価値観|
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
@ -208,7 +208,7 @@
|
|||||||
|
|
||||||
### テストコマンドフラグ(`/sc:test`)
|
### テストコマンドフラグ(`/sc:test`)
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/flags.md#test-command-flags-sctest)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/flags.md#test-command-flags-sctest)
|
||||||
|
|
||||||
|フラグ|目的|価値観|
|
|フラグ|目的|価値観|
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
@ -218,11 +218,11 @@
|
|||||||
|
|
||||||
## 高度な制御フラグ
|
## 高度な制御フラグ
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/flags.md#advanced-control-flags)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/flags.md#advanced-control-flags)
|
||||||
|
|
||||||
### 範囲と焦点
|
### 範囲と焦点
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/flags.md#scope-and-focus)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/flags.md#scope-and-focus)
|
||||||
|
|
||||||
|フラグ|目的|価値観|
|
|フラグ|目的|価値観|
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
@ -231,7 +231,7 @@
|
|||||||
|
|
||||||
### 実行制御
|
### 実行制御
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/flags.md#execution-control)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/flags.md#execution-control)
|
||||||
|
|
||||||
|フラグ|目的|価値観|
|
|フラグ|目的|価値観|
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
@ -242,7 +242,7 @@
|
|||||||
|
|
||||||
### システムフラグ(SuperClaude インストール)
|
### システムフラグ(SuperClaude インストール)
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/flags.md#system-flags-superclaude-installation)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/flags.md#system-flags-superclaude-installation)
|
||||||
|
|
||||||
|フラグ|目的|価値観|
|
|フラグ|目的|価値観|
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
@ -258,11 +258,11 @@
|
|||||||
|
|
||||||
## 一般的な使用パターン
|
## 一般的な使用パターン
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/flags.md#common-usage-patterns)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/flags.md#common-usage-patterns)
|
||||||
|
|
||||||
### フロントエンド開発
|
### フロントエンド開発
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/flags.md#frontend-development)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/flags.md#frontend-development)
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
/sc:implement "responsive dashboard" --magic --c7
|
/sc:implement "responsive dashboard" --magic --c7
|
||||||
@ -273,7 +273,7 @@
|
|||||||
|
|
||||||
### バックエンド開発
|
### バックエンド開発
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/flags.md#backend-development)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/flags.md#backend-development)
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
/sc:analyze api/ --focus performance --seq --think
|
/sc:analyze api/ --focus performance --seq --think
|
||||||
@ -284,7 +284,7 @@
|
|||||||
|
|
||||||
### 大規模プロジェクト
|
### 大規模プロジェクト
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/flags.md#large-projects)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/flags.md#large-projects)
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
/sc:analyze . --ultrathink --all-mcp --safe-mode
|
/sc:analyze . --ultrathink --all-mcp --safe-mode
|
||||||
@ -295,7 +295,7 @@
|
|||||||
|
|
||||||
### 品質とメンテナンス
|
### 品質とメンテナンス
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/flags.md#quality--maintenance)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/flags.md#quality--maintenance)
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
/sc:improve src/ --type quality --safe --interactive
|
/sc:improve src/ --type quality --safe --interactive
|
||||||
@ -306,11 +306,11 @@
|
|||||||
|
|
||||||
## フラグインタラクション
|
## フラグインタラクション
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/flags.md#flag-interactions)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/flags.md#flag-interactions)
|
||||||
|
|
||||||
### 互換性のある組み合わせ
|
### 互換性のある組み合わせ
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/flags.md#compatible-combinations)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/flags.md#compatible-combinations)
|
||||||
|
|
||||||
- `--think`+ `--c7`: ドキュメント付き分析
|
- `--think`+ `--c7`: ドキュメント付き分析
|
||||||
- `--magic`+ `--play`: テスト付きのUI生成
|
- `--magic`+ `--play`: テスト付きのUI生成
|
||||||
@ -320,7 +320,7 @@
|
|||||||
|
|
||||||
### 競合するフラグ
|
### 競合するフラグ
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/flags.md#conflicting-flags)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/flags.md#conflicting-flags)
|
||||||
|
|
||||||
- `--all-mcp`個別のMCPフラグと比較(どちらか一方を使用)
|
- `--all-mcp`個別のMCPフラグと比較(どちらか一方を使用)
|
||||||
- `--no-mcp`任意のMCPフラグと比較(--no-mcpが優先)
|
- `--no-mcp`任意のMCPフラグと比較(--no-mcpが優先)
|
||||||
@ -329,7 +329,7 @@
|
|||||||
|
|
||||||
### 関係の自動有効化
|
### 関係の自動有効化
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/flags.md#auto-enabling-relationships)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/flags.md#auto-enabling-relationships)
|
||||||
|
|
||||||
- `--safe-mode`自動的`--uc`に有効になり、`--validate`
|
- `--safe-mode`自動的`--uc`に有効になり、`--validate`
|
||||||
- `--ultrathink`すべてのMCPサーバーを自動的に有効にする
|
- `--ultrathink`すべてのMCPサーバーを自動的に有効にする
|
||||||
@ -338,11 +338,11 @@
|
|||||||
|
|
||||||
## トラブルシューティングフラグ
|
## トラブルシューティングフラグ
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/flags.md#troubleshooting-flags)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/flags.md#troubleshooting-flags)
|
||||||
|
|
||||||
### よくある問題
|
### よくある問題
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/flags.md#common-issues)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/flags.md#common-issues)
|
||||||
|
|
||||||
- **ツールが多すぎる**:`--no-mcp`ネイティブツールのみでテストする
|
- **ツールが多すぎる**:`--no-mcp`ネイティブツールのみでテストする
|
||||||
- **操作が遅すぎます**:`--uc`出力を圧縮するために追加します
|
- **操作が遅すぎます**:`--uc`出力を圧縮するために追加します
|
||||||
@ -351,7 +351,7 @@
|
|||||||
|
|
||||||
### デバッグフラグ
|
### デバッグフラグ
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/flags.md#debug-flags)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/flags.md#debug-flags)
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
/sc:analyze . --verbose # Shows decision logic and flag activation
|
/sc:analyze . --verbose # Shows decision logic and flag activation
|
||||||
@ -361,7 +361,7 @@
|
|||||||
|
|
||||||
### クイックフィックス
|
### クイックフィックス
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/flags.md#quick-fixes)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/flags.md#quick-fixes)
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
/sc:analyze . --help # Shows available flags for command
|
/sc:analyze . --help # Shows available flags for command
|
||||||
@ -371,7 +371,7 @@
|
|||||||
|
|
||||||
## フラグの優先ルール
|
## フラグの優先ルール
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/flags.md#flag-priority-rules)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/flags.md#flag-priority-rules)
|
||||||
|
|
||||||
1. **安全第一**: `--safe-mode`> `--validate`> 最適化フラグ
|
1. **安全第一**: `--safe-mode`> `--validate`> 最適化フラグ
|
||||||
2. **明示的なオーバーライド**: ユーザーフラグ > 自動検出
|
2. **明示的なオーバーライド**: ユーザーフラグ > 自動検出
|
||||||
@ -381,8 +381,8 @@
|
|||||||
|
|
||||||
## 関連リソース
|
## 関連リソース
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/flags.md#related-resources)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/flags.md#related-resources)
|
||||||
|
|
||||||
- [コマンドガイド](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/commands.md)- これらのフラグを使用するコマンド
|
- [コマンドガイド](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/commands.md)- これらのフラグを使用するコマンド
|
||||||
- [MCP サーバーガイド](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/mcp-servers.md)- MCP フラグのアクティブ化について
|
- [MCP サーバーガイド](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/mcp-servers.md)- MCP フラグのアクティブ化について
|
||||||
- [セッション管理](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/session-management.md)- 永続セッションでのフラグの使用
|
- [セッション管理](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/session-management.md)- 永続セッションでのフラグの使用
|
||||||
@ -1,16 +1,16 @@
|
|||||||
# SuperClaude MCP サーバーガイド 🔌
|
# SuperClaude MCP サーバーガイド 🔌
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/mcp-servers.md#superclaude-mcp-servers-guide-)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/mcp-servers.md#superclaude-mcp-servers-guide-)
|
||||||
|
|
||||||
## 概要
|
## 概要
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/mcp-servers.md#overview)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/mcp-servers.md#overview)
|
||||||
|
|
||||||
MCP(モデルコンテキストプロトコル)サーバーは、専用ツールを通じてClaude Codeの機能を拡張します。SuperClaudeは6つのMCPサーバーを統合し、タスクに応じてサーバーをいつ起動するかをClaudeに指示します。
|
MCP(モデルコンテキストプロトコル)サーバーは、専用ツールを通じてClaude Codeの機能を拡張します。SuperClaudeは6つのMCPサーバーを統合し、タスクに応じてサーバーをいつ起動するかをClaudeに指示します。
|
||||||
|
|
||||||
### 🔍 現実チェック
|
### 🔍 現実チェック
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/mcp-servers.md#-reality-check)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/mcp-servers.md#-reality-check)
|
||||||
|
|
||||||
- **MCPサーバーとは**: 追加ツールを提供する外部Node.jsプロセス
|
- **MCPサーバーとは**: 追加ツールを提供する外部Node.jsプロセス
|
||||||
- **含まれていないもの**:SuperClaude 機能が組み込まれている
|
- **含まれていないもの**:SuperClaude 機能が組み込まれている
|
||||||
@ -28,9 +28,9 @@ MCP(モデルコンテキストプロトコル)サーバーは、専用ツ
|
|||||||
|
|
||||||
## クイックスタート
|
## クイックスタート
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/mcp-servers.md#quick-start)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/mcp-servers.md#quick-start)
|
||||||
|
|
||||||
**セットアップの確認**:MCPサーバーは自動的に起動します。インストールとトラブルシューティングについては、[「インストールガイド」](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/Getting-Started/installation.md)と[「トラブルシューティング」](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/Reference/troubleshooting.md)を参照してください。
|
**セットアップの確認**:MCPサーバーは自動的に起動します。インストールとトラブルシューティングについては、[「インストールガイド」](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/Getting-Started/installation.md)と[「トラブルシューティング」](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/Reference/troubleshooting.md)を参照してください。
|
||||||
|
|
||||||
**自動アクティベーションロジック:**
|
**自動アクティベーションロジック:**
|
||||||
|
|
||||||
@ -45,11 +45,11 @@ MCP(モデルコンテキストプロトコル)サーバーは、専用ツ
|
|||||||
|
|
||||||
## サーバーの詳細
|
## サーバーの詳細
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/mcp-servers.md#server-details)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/mcp-servers.md#server-details)
|
||||||
|
|
||||||
### コンテキスト7 📚
|
### コンテキスト7 📚
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/mcp-servers.md#context7-)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/mcp-servers.md#context7-)
|
||||||
|
|
||||||
**目的**: 公式ライブラリドキュメントへのアクセス **トリガー**: インポートステートメント、フレームワークキーワード、ドキュメントリクエスト **要件**: Node.js 16+、APIキーなし
|
**目的**: 公式ライブラリドキュメントへのアクセス **トリガー**: インポートステートメント、フレームワークキーワード、ドキュメントリクエスト **要件**: Node.js 16+、APIキーなし
|
||||||
|
|
||||||
@ -64,7 +64,7 @@ MCP(モデルコンテキストプロトコル)サーバーは、専用ツ
|
|||||||
|
|
||||||
### 連続思考 🧠
|
### 連続思考 🧠
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/mcp-servers.md#sequential-thinking-)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/mcp-servers.md#sequential-thinking-)
|
||||||
|
|
||||||
**目的**: 構造化された多段階の推論と体系的な分析 **トリガー**: 複雑なデバッグ、`--think`フラグ、アーキテクチャ分析 **要件**: Node.js 16+、APIキーなし
|
**目的**: 構造化された多段階の推論と体系的な分析 **トリガー**: 複雑なデバッグ、`--think`フラグ、アーキテクチャ分析 **要件**: Node.js 16+、APIキーなし
|
||||||
|
|
||||||
@ -79,7 +79,7 @@ MCP(モデルコンテキストプロトコル)サーバーは、専用ツ
|
|||||||
|
|
||||||
### 魔法✨
|
### 魔法✨
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/mcp-servers.md#magic-)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/mcp-servers.md#magic-)
|
||||||
|
|
||||||
**目的**: 21st.dev パターンからのモダン UI コンポーネント生成 **トリガー**: UI リクエスト、`/ui`コマンド、コンポーネント開発 **要件**: Node.js 16+、TWENTYFIRST_API_KEY()
|
**目的**: 21st.dev パターンからのモダン UI コンポーネント生成 **トリガー**: UI リクエスト、`/ui`コマンド、コンポーネント開発 **要件**: Node.js 16+、TWENTYFIRST_API_KEY()
|
||||||
|
|
||||||
@ -94,7 +94,7 @@ export TWENTYFIRST_API_KEY="your_key_here"
|
|||||||
|
|
||||||
### 劇作家🎭
|
### 劇作家🎭
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/mcp-servers.md#playwright-)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/mcp-servers.md#playwright-)
|
||||||
|
|
||||||
**目的**: 実際のブラウザ自動化とE2Eテスト **トリガー**: ブラウザテスト、E2Eシナリオ、視覚的検証 **要件**: Node.js 16以上、APIキーなし
|
**目的**: 実際のブラウザ自動化とE2Eテスト **トリガー**: ブラウザテスト、E2Eシナリオ、視覚的検証 **要件**: Node.js 16以上、APIキーなし
|
||||||
|
|
||||||
@ -109,7 +109,7 @@ export TWENTYFIRST_API_KEY="your_key_here"
|
|||||||
|
|
||||||
### morphllm-fast-apply 🔄
|
### morphllm-fast-apply 🔄
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/mcp-servers.md#morphllm-fast-apply-)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/mcp-servers.md#morphllm-fast-apply-)
|
||||||
|
|
||||||
**目的**: 効率的なパターンベースのコード変換 **トリガー**: 複数ファイルの編集、リファクタリング、フレームワークの移行 **要件**: Node.js 16+、MORPH_API_KEY
|
**目的**: 効率的なパターンベースのコード変換 **トリガー**: 複数ファイルの編集、リファクタリング、フレームワークの移行 **要件**: Node.js 16+、MORPH_API_KEY
|
||||||
|
|
||||||
@ -124,7 +124,7 @@ export MORPH_API_KEY="your_key_here"
|
|||||||
|
|
||||||
### セレナ🧭
|
### セレナ🧭
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/mcp-servers.md#serena-)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/mcp-servers.md#serena-)
|
||||||
|
|
||||||
**目的**: プロジェクトメモリを使用したセマンティックコード理解 **トリガー**: シンボル操作、大規模コードベース、セッション管理 **要件**: Python 3.9+、UV パッケージマネージャー、API キーなし
|
**目的**: プロジェクトメモリを使用したセマンティックコード理解 **トリガー**: シンボル操作、大規模コードベース、セッション管理 **要件**: Python 3.9+、UV パッケージマネージャー、API キーなし
|
||||||
|
|
||||||
@ -139,7 +139,7 @@ export MORPH_API_KEY="your_key_here"
|
|||||||
|
|
||||||
## 構成
|
## 構成
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/mcp-servers.md#configuration)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/mcp-servers.md#configuration)
|
||||||
|
|
||||||
**MCP 構成ファイル ( `~/.claude.json`):**
|
**MCP 構成ファイル ( `~/.claude.json`):**
|
||||||
|
|
||||||
@ -178,7 +178,7 @@ export MORPH_API_KEY="your_key_here"
|
|||||||
|
|
||||||
## 使用パターン
|
## 使用パターン
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/mcp-servers.md#usage-patterns)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/mcp-servers.md#usage-patterns)
|
||||||
|
|
||||||
**サーバー制御:**
|
**サーバー制御:**
|
||||||
|
|
||||||
@ -207,7 +207,7 @@ export MORPH_API_KEY="your_key_here"
|
|||||||
|
|
||||||
## トラブルシューティング
|
## トラブルシューティング
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/mcp-servers.md#troubleshooting)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/mcp-servers.md#troubleshooting)
|
||||||
|
|
||||||
**よくある問題:**
|
**よくある問題:**
|
||||||
|
|
||||||
@ -255,7 +255,7 @@ echo 'export MORPH_API_KEY="your_key"' >> ~/.bashrc
|
|||||||
|
|
||||||
## サーバーの組み合わせ
|
## サーバーの組み合わせ
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/mcp-servers.md#server-combinations)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/mcp-servers.md#server-combinations)
|
||||||
|
|
||||||
**APIキーなし(無料)** :
|
**APIキーなし(無料)** :
|
||||||
|
|
||||||
@ -278,7 +278,7 @@ echo 'export MORPH_API_KEY="your_key"' >> ~/.bashrc
|
|||||||
|
|
||||||
## 統合
|
## 統合
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/mcp-servers.md#integration)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/mcp-servers.md#integration)
|
||||||
|
|
||||||
**SuperClaude コマンドを使用する場合:**
|
**SuperClaude コマンドを使用する場合:**
|
||||||
|
|
||||||
@ -300,20 +300,20 @@ echo 'export MORPH_API_KEY="your_key"' >> ~/.bashrc
|
|||||||
|
|
||||||
## 関連リソース
|
## 関連リソース
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/mcp-servers.md#related-resources)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/mcp-servers.md#related-resources)
|
||||||
|
|
||||||
**必読:**
|
**必読:**
|
||||||
|
|
||||||
- [コマンドガイド](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/commands.md)- MCPサーバーをアクティブ化するコマンド
|
- [コマンドガイド](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/commands.md)- MCPサーバーをアクティブ化するコマンド
|
||||||
- [クイックスタートガイド](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/Getting-Started/quick-start.md)- MCP セットアップガイド
|
- [クイックスタートガイド](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/Getting-Started/quick-start.md)- MCP セットアップガイド
|
||||||
|
|
||||||
**高度な使用法:**
|
**高度な使用法:**
|
||||||
|
|
||||||
- [行動モード](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/modes.md)- モード-MCP調整
|
- [行動モード](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/modes.md)- モード-MCP調整
|
||||||
- [エージェントガイド](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/agents.md)- エージェントとMCPの統合
|
- [エージェントガイド](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/agents.md)- エージェントとMCPの統合
|
||||||
- [セッション管理](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/session-management.md)- Serena ワークフロー
|
- [セッション管理](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/session-management.md)- Serena ワークフロー
|
||||||
|
|
||||||
**技術リファレンス:**
|
**技術リファレンス:**
|
||||||
|
|
||||||
- [例のクックブック](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/Reference/examples-cookbook.md)- MCP ワークフローパターン
|
- [例のクックブック](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/Reference/examples-cookbook.md)- MCP ワークフローパターン
|
||||||
- [技術アーキテクチャ](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/Developer-Guide/technical-architecture.md)- 統合の詳細
|
- [技術アーキテクチャ](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/Developer-Guide/technical-architecture.md)- 統合の詳細
|
||||||
@ -1,16 +1,16 @@
|
|||||||
# SuperClaude 行動モードガイド 🧠
|
# SuperClaude 行動モードガイド 🧠
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/modes.md#superclaude-behavioral-modes-guide-)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/modes.md#superclaude-behavioral-modes-guide-)
|
||||||
|
|
||||||
## ✅ クイック検証
|
## ✅ クイック検証
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/modes.md#-quick-verification)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/modes.md#-quick-verification)
|
||||||
|
|
||||||
コマンドを使用してモードをテストします`/sc:`。モードはタスクの複雑さに基づいて自動的にアクティブになります。コマンドの完全なリファレンスについては、[コマンドガイド](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/commands.md)をご覧ください。
|
コマンドを使用してモードをテストします`/sc:`。モードはタスクの複雑さに基づいて自動的にアクティブになります。コマンドの完全なリファレンスについては、[コマンドガイド](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/commands.md)をご覧ください。
|
||||||
|
|
||||||
## クイックリファレンステーブル
|
## クイックリファレンステーブル
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/modes.md#quick-reference-table)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/modes.md#quick-reference-table)
|
||||||
|
|
||||||
|モード|目的|自動トリガー|重要な行動|最適な用途|
|
|モード|目的|自動トリガー|重要な行動|最適な用途|
|
||||||
|---|---|---|---|---|
|
|---|---|---|---|---|
|
||||||
@ -24,7 +24,7 @@
|
|||||||
|
|
||||||
## はじめに(2分の概要)
|
## はじめに(2分の概要)
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/modes.md#getting-started-2-minute-overview)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/modes.md#getting-started-2-minute-overview)
|
||||||
|
|
||||||
**モードは動作指示を通じてアクティブ化されます**- Claude Code はコンテキスト ファイルを読み取り、タスクのパターンと複雑さに基づいてどのモード動作を採用するかを決定します。
|
**モードは動作指示を通じてアクティブ化されます**- Claude Code はコンテキスト ファイルを読み取り、タスクのパターンと複雑さに基づいてどのモード動作を採用するかを決定します。
|
||||||
|
|
||||||
@ -47,11 +47,11 @@
|
|||||||
|
|
||||||
## モードの詳細
|
## モードの詳細
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/modes.md#mode-details)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/modes.md#mode-details)
|
||||||
|
|
||||||
### 🧠 ブレインストーミングモード - インタラクティブな発見
|
### 🧠 ブレインストーミングモード - インタラクティブな発見
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/modes.md#-brainstorming-mode---interactive-discovery)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/modes.md#-brainstorming-mode---interactive-discovery)
|
||||||
|
|
||||||
**目的**: 共同作業による発見を通じて、漠然としたアイデアを構造化された要件に変換します。
|
**目的**: 共同作業による発見を通じて、漠然としたアイデアを構造化された要件に変換します。
|
||||||
|
|
||||||
@ -85,7 +85,7 @@ Brainstorming Approach:
|
|||||||
|
|
||||||
#### 成功基準
|
#### 成功基準
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/modes.md#success-criteria)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/modes.md#success-criteria)
|
||||||
|
|
||||||
- [ ] すぐに解決策を提示するのではなく、質問で応答する
|
- [ ] すぐに解決策を提示するのではなく、質問で応答する
|
||||||
- [ ] 質問はユーザーのニーズ、技術的制約、ビジネス目標を探ります
|
- [ ] 質問はユーザーのニーズ、技術的制約、ビジネス目標を探ります
|
||||||
@ -106,7 +106,7 @@ Brainstorming Approach:
|
|||||||
|
|
||||||
### 🔍 内省モード - メタ認知分析
|
### 🔍 内省モード - メタ認知分析
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/modes.md#-introspection-mode---meta-cognitive-analysis)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/modes.md#-introspection-mode---meta-cognitive-analysis)
|
||||||
|
|
||||||
**目的**: 学習の最適化と透明な意思決定のための推論プロセスを公開します。
|
**目的**: 学習の最適化と透明な意思決定のための推論プロセスを公開します。
|
||||||
|
|
||||||
@ -149,7 +149,7 @@ Introspective Approach:
|
|||||||
|
|
||||||
### 📋 タスク管理モード - 複雑な調整
|
### 📋 タスク管理モード - 複雑な調整
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/modes.md#-task-management-mode---complex-coordination)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/modes.md#-task-management-mode---complex-coordination)
|
||||||
|
|
||||||
**目的**: 複数ステップの操作のためのセッション永続性を備えた階層的なタスク構成。
|
**目的**: 複数ステップの操作のためのセッション永続性を備えた階層的なタスク構成。
|
||||||
|
|
||||||
@ -193,7 +193,7 @@ Task Management Approach:
|
|||||||
|
|
||||||
### 🎯 オーケストレーションモード - インテリジェントなツール選択
|
### 🎯 オーケストレーションモード - インテリジェントなツール選択
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/modes.md#-orchestration-mode---intelligent-tool-selection)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/modes.md#-orchestration-mode---intelligent-tool-selection)
|
||||||
|
|
||||||
**目的**: インテリジェントなツールルーティングと並列調整を通じてタスクの実行を最適化します。
|
**目的**: インテリジェントなツールルーティングと並列調整を通じてタスクの実行を最適化します。
|
||||||
|
|
||||||
@ -235,7 +235,7 @@ Orchestration Approach:
|
|||||||
|
|
||||||
### ⚡ トークン効率モード - 圧縮通信
|
### ⚡ トークン効率モード - 圧縮通信
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/modes.md#-token-efficiency-mode---compressed-communication)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/modes.md#-token-efficiency-mode---compressed-communication)
|
||||||
|
|
||||||
**目的**: 情報の品質を維持しながら、シンボル システムを通じて推定 30 ~ 50% のトークン削減を実現します。
|
**目的**: 情報の品質を維持しながら、シンボル システムを通じて推定 30 ~ 50% のトークン削減を実現します。
|
||||||
|
|
||||||
@ -276,7 +276,7 @@ Token Efficient Approach:
|
|||||||
|
|
||||||
### 🎨 標準モード - バランスのとれたデフォルト
|
### 🎨 標準モード - バランスのとれたデフォルト
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/modes.md#-standard-mode---balanced-default)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/modes.md#-standard-mode---balanced-default)
|
||||||
|
|
||||||
**目的**: 簡単な開発タスクに対して明確でプロフェッショナルなコミュニケーションを提供します。
|
**目的**: 簡単な開発タスクに対して明確でプロフェッショナルなコミュニケーションを提供します。
|
||||||
|
|
||||||
@ -319,11 +319,11 @@ Standard Approach: Consistent, professional baseline for all tasks
|
|||||||
|
|
||||||
## 高度な使用法
|
## 高度な使用法
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/modes.md#advanced-usage)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/modes.md#advanced-usage)
|
||||||
|
|
||||||
### モードの組み合わせ
|
### モードの組み合わせ
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/modes.md#mode-combinations)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/modes.md#mode-combinations)
|
||||||
|
|
||||||
**マルチモードワークフロー:**
|
**マルチモードワークフロー:**
|
||||||
|
|
||||||
@ -341,7 +341,7 @@ Standard Approach: Consistent, professional baseline for all tasks
|
|||||||
|
|
||||||
### 手動モード制御
|
### 手動モード制御
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/modes.md#manual-mode-control)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/modes.md#manual-mode-control)
|
||||||
|
|
||||||
**特定の動作を強制する:**
|
**特定の動作を強制する:**
|
||||||
|
|
||||||
@ -366,7 +366,7 @@ Standard Approach: Consistent, professional baseline for all tasks
|
|||||||
|
|
||||||
### モードの境界と優先順位
|
### モードの境界と優先順位
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/modes.md#mode-boundaries-and-priority)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/modes.md#mode-boundaries-and-priority)
|
||||||
|
|
||||||
**モードがアクティブになると:**
|
**モードがアクティブになると:**
|
||||||
|
|
||||||
@ -387,11 +387,11 @@ Standard Approach: Consistent, professional baseline for all tasks
|
|||||||
|
|
||||||
## 実世界の例
|
## 実世界の例
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/modes.md#real-world-examples)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/modes.md#real-world-examples)
|
||||||
|
|
||||||
### 完全なワークフローの例
|
### 完全なワークフローの例
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/modes.md#complete-workflow-examples)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/modes.md#complete-workflow-examples)
|
||||||
|
|
||||||
**新規プロジェクト開発:**
|
**新規プロジェクト開発:**
|
||||||
|
|
||||||
@ -430,7 +430,7 @@ Standard Approach: Consistent, professional baseline for all tasks
|
|||||||
|
|
||||||
### モードの組み合わせパターン
|
### モードの組み合わせパターン
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/modes.md#mode-combination-patterns)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/modes.md#mode-combination-patterns)
|
||||||
|
|
||||||
**非常に複雑なシナリオ:**
|
**非常に複雑なシナリオ:**
|
||||||
|
|
||||||
@ -447,11 +447,11 @@ Standard Approach: Consistent, professional baseline for all tasks
|
|||||||
|
|
||||||
## クイックリファレンス
|
## クイックリファレンス
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/modes.md#quick-reference)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/modes.md#quick-reference)
|
||||||
|
|
||||||
### モード起動パターン
|
### モード起動パターン
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/modes.md#mode-activation-patterns)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/modes.md#mode-activation-patterns)
|
||||||
|
|
||||||
|トリガータイプ|入力例|モードが有効|主要な動作|
|
|トリガータイプ|入力例|モードが有効|主要な動作|
|
||||||
|---|---|---|---|
|
|---|---|---|---|
|
||||||
@ -464,7 +464,7 @@ Standard Approach: Consistent, professional baseline for all tasks
|
|||||||
|
|
||||||
### 手動オーバーライドコマンド
|
### 手動オーバーライドコマンド
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/modes.md#manual-override-commands)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/modes.md#manual-override-commands)
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
# Force specific mode behaviors
|
# Force specific mode behaviors
|
||||||
@ -483,26 +483,26 @@ Standard Approach: Consistent, professional baseline for all tasks
|
|||||||
|
|
||||||
## トラブルシューティング
|
## トラブルシューティング
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/modes.md#troubleshooting)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/modes.md#troubleshooting)
|
||||||
|
|
||||||
トラブルシューティングのヘルプについては、以下を参照してください。
|
トラブルシューティングのヘルプについては、以下を参照してください。
|
||||||
|
|
||||||
- [よくある問題](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/Reference/common-issues.md)- よくある問題に対するクイック修正
|
- [よくある問題](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/Reference/common-issues.md)- よくある問題に対するクイック修正
|
||||||
- [トラブルシューティングガイド](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/Reference/troubleshooting.md)- 包括的な問題解決
|
- [トラブルシューティングガイド](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/Reference/troubleshooting.md)- 包括的な問題解決
|
||||||
|
|
||||||
### よくある問題
|
### よくある問題
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/modes.md#common-issues)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/modes.md#common-issues)
|
||||||
|
|
||||||
- **モードがアクティブ化されていません**: 手動フラグを使用してください: `--brainstorm`、、`--introspect``--uc`
|
- **モードがアクティブ化されていません**: 手動フラグを使用してください: `--brainstorm`、、`--introspect``--uc`
|
||||||
- **間違ったモードがアクティブです**: リクエスト内の複雑なトリガーとキーワードを確認してください
|
- **間違ったモードがアクティブです**: リクエスト内の複雑なトリガーとキーワードを確認してください
|
||||||
- **予期しないモード切り替え**:タスクの進行に基づく通常の動作
|
- **予期しないモード切り替え**:タスクの進行に基づく通常の動作
|
||||||
- **実行への影響**: モードはツールの使用を最適化するものであり、実行には影響しないはずです。
|
- **実行への影響**: モードはツールの使用を最適化するものであり、実行には影響しないはずです。
|
||||||
- **モードの競合**:[フラグガイドでフラグの優先順位ルールを確認してください](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/flags.md)
|
- **モードの競合**:[フラグガイドでフラグの優先順位ルールを確認してください](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/flags.md)
|
||||||
|
|
||||||
### 即時修正
|
### 即時修正
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/modes.md#immediate-fixes)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/modes.md#immediate-fixes)
|
||||||
|
|
||||||
- **特定のモードを強制**:`--brainstorm`またはのような明示的なフラグを使用する`--task-manage`
|
- **特定のモードを強制**:`--brainstorm`またはのような明示的なフラグを使用する`--task-manage`
|
||||||
- **リセットモードの動作**: モード状態をリセットするには、Claude Code セッションを再起動します。
|
- **リセットモードの動作**: モード状態をリセットするには、Claude Code セッションを再起動します。
|
||||||
@ -511,7 +511,7 @@ Standard Approach: Consistent, professional baseline for all tasks
|
|||||||
|
|
||||||
### モード固有のトラブルシューティング
|
### モード固有のトラブルシューティング
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/modes.md#mode-specific-troubleshooting)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/modes.md#mode-specific-troubleshooting)
|
||||||
|
|
||||||
**ブレインストーミングモードの問題:**
|
**ブレインストーミングモードの問題:**
|
||||||
|
|
||||||
@ -564,7 +564,7 @@ Standard Approach: Consistent, professional baseline for all tasks
|
|||||||
|
|
||||||
### エラーコードリファレンス
|
### エラーコードリファレンス
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/modes.md#error-code-reference)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/modes.md#error-code-reference)
|
||||||
|
|
||||||
|モードエラー|意味|クイックフィックス|
|
|モードエラー|意味|クイックフィックス|
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
@ -579,7 +579,7 @@ Standard Approach: Consistent, professional baseline for all tasks
|
|||||||
|
|
||||||
### プログレッシブサポートレベル
|
### プログレッシブサポートレベル
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/modes.md#progressive-support-levels)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/modes.md#progressive-support-levels)
|
||||||
|
|
||||||
**レベル 1: クイックフィックス (< 2 分)**
|
**レベル 1: クイックフィックス (< 2 分)**
|
||||||
|
|
||||||
@ -596,7 +596,7 @@ Standard Approach: Consistent, professional baseline for all tasks
|
|||||||
# Review request complexity and triggers
|
# Review request complexity and triggers
|
||||||
```
|
```
|
||||||
|
|
||||||
- モードのインストールに関する問題については、[一般的な問題ガイドを](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/Reference/common-issues.md)参照してください。
|
- モードのインストールに関する問題については、[一般的な問題ガイドを](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/Reference/common-issues.md)参照してください。
|
||||||
|
|
||||||
**レベル3: 専門家によるサポート(30分以上)**
|
**レベル3: 専門家によるサポート(30分以上)**
|
||||||
|
|
||||||
@ -607,7 +607,7 @@ SuperClaude install --diagnose
|
|||||||
# Review behavioral triggers and thresholds
|
# Review behavioral triggers and thresholds
|
||||||
```
|
```
|
||||||
|
|
||||||
- 行動モード分析については[診断リファレンスガイド](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/Reference/diagnostic-reference.md)を参照してください
|
- 行動モード分析については[診断リファレンスガイド](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/Reference/diagnostic-reference.md)を参照してください
|
||||||
|
|
||||||
**レベル4: コミュニティサポート**
|
**レベル4: コミュニティサポート**
|
||||||
|
|
||||||
@ -617,7 +617,7 @@ SuperClaude install --diagnose
|
|||||||
|
|
||||||
### 成功の検証
|
### 成功の検証
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/modes.md#success-validation)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/modes.md#success-validation)
|
||||||
|
|
||||||
モード修正を適用した後、次のようにテストします。
|
モード修正を適用した後、次のようにテストします。
|
||||||
|
|
||||||
@ -629,17 +629,17 @@ SuperClaude install --diagnose
|
|||||||
|
|
||||||
## クイックトラブルシューティング(レガシー)
|
## クイックトラブルシューティング(レガシー)
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/modes.md#quick-troubleshooting-legacy)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/modes.md#quick-troubleshooting-legacy)
|
||||||
|
|
||||||
- **モードがアクティブ化されない**→手動フラグを使用: `--brainstorm`、、`--introspect``--uc`
|
- **モードがアクティブ化されない**→手動フラグを使用: `--brainstorm`、、`--introspect``--uc`
|
||||||
- **間違ったモードがアクティブです**→ リクエスト内の複雑なトリガーとキーワードを確認してください
|
- **間違ったモードがアクティブです**→ リクエスト内の複雑なトリガーとキーワードを確認してください
|
||||||
- **予期せぬモード切り替え**→ タスクの進行に基づく通常の動作
|
- **予期せぬモード切り替え**→ タスクの進行に基づく通常の動作
|
||||||
- **実行への影響**→ モードはツールの使用を最適化するものであり、実行には影響しないはずです
|
- **実行への影響**→ モードはツールの使用を最適化するものであり、実行には影響しないはずです
|
||||||
- **モードの競合→**[フラグガイド](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/flags.md)でフラグの優先順位ルールを確認してください[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/flags.md)
|
- **モードの競合→**[フラグガイド](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/flags.md)でフラグの優先順位ルールを確認してください[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/flags.md)
|
||||||
|
|
||||||
## よくある質問
|
## よくある質問
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/modes.md#frequently-asked-questions)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/modes.md#frequently-asked-questions)
|
||||||
|
|
||||||
**Q: どのモードがアクティブになっているかはどうすればわかりますか?** A: 通信パターンで次のインジケーターを確認してください。
|
**Q: どのモードがアクティブになっているかはどうすればわかりますか?** A: 通信パターンで次のインジケーターを確認してください。
|
||||||
|
|
||||||
@ -674,7 +674,7 @@ SuperClaude install --diagnose
|
|||||||
|
|
||||||
## まとめ
|
## まとめ
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/modes.md#summary)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/modes.md#summary)
|
||||||
|
|
||||||
SuperClaude の 5 つの行動モードは、ユーザーのニーズに自動的に適合する**インテリジェントな適応システムを作成します。**
|
SuperClaude の 5 つの行動モードは、ユーザーのニーズに自動的に適合する**インテリジェントな適応システムを作成します。**
|
||||||
|
|
||||||
@ -691,36 +691,36 @@ SuperClaude の 5 つの行動モードは、ユーザーのニーズに自動
|
|||||||
|
|
||||||
## 関連ガイド
|
## 関連ガイド
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/modes.md#related-guides)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/modes.md#related-guides)
|
||||||
|
|
||||||
**学習の進捗:**
|
**学習の進捗:**
|
||||||
|
|
||||||
**🌱 エッセンシャル(第1週)**
|
**🌱 エッセンシャル(第1週)**
|
||||||
|
|
||||||
- [クイックスタートガイド](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/Getting-Started/quick-start.md)- モードの有効化例
|
- [クイックスタートガイド](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/Getting-Started/quick-start.md)- モードの有効化例
|
||||||
- [コマンドリファレンス](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/commands.md)- コマンドは自動的にモードをアクティブ化します
|
- [コマンドリファレンス](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/commands.md)- コマンドは自動的にモードをアクティブ化します
|
||||||
- [インストールガイド](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/Getting-Started/installation.md)- 動作モードの設定
|
- [インストールガイド](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/Getting-Started/installation.md)- 動作モードの設定
|
||||||
|
|
||||||
**🌿中級(第2~3週)**
|
**🌿中級(第2~3週)**
|
||||||
|
|
||||||
- [エージェントガイド](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/agents.md)- モードとスペシャリストの連携方法
|
- [エージェントガイド](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/agents.md)- モードとスペシャリストの連携方法
|
||||||
- [フラグガイド](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/flags.md)- 手動モードの制御と最適化
|
- [フラグガイド](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/flags.md)- 手動モードの制御と最適化
|
||||||
- [例文集](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/Reference/examples-cookbook.md)- モードパターンの実践
|
- [例文集](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/Reference/examples-cookbook.md)- モードパターンの実践
|
||||||
|
|
||||||
**🌲 上級(2ヶ月目以降)**
|
**🌲 上級(2ヶ月目以降)**
|
||||||
|
|
||||||
- [MCP サーバー](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/mcp-servers.md)- 拡張機能を備えたモード統合
|
- [MCP サーバー](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/mcp-servers.md)- 拡張機能を備えたモード統合
|
||||||
- [セッション管理](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/session-management.md)- タスク管理モードのワークフロー
|
- [セッション管理](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/session-management.md)- タスク管理モードのワークフロー
|
||||||
- [はじめに](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/Getting-Started/quick-start.md)- モードの使用パターン
|
- [はじめに](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/Getting-Started/quick-start.md)- モードの使用パターン
|
||||||
|
|
||||||
**🔧 エキスパート**
|
**🔧 エキスパート**
|
||||||
|
|
||||||
- [技術アーキテクチャ](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/Developer-Guide/technical-architecture.md)- モード実装の詳細
|
- [技術アーキテクチャ](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/Developer-Guide/technical-architecture.md)- モード実装の詳細
|
||||||
- [コードの貢献](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/Developer-Guide/contributing-code.md)- モードの機能を拡張する
|
- [コードの貢献](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/Developer-Guide/contributing-code.md)- モードの機能を拡張する
|
||||||
|
|
||||||
**モード固有のガイド:**
|
**モード固有のガイド:**
|
||||||
|
|
||||||
- **ブレインストーミング**:[要件発見パターン](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/Reference/examples-cookbook.md#requirements)
|
- **ブレインストーミング**:[要件発見パターン](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/Reference/examples-cookbook.md#requirements)
|
||||||
- **タスク管理**:[セッション管理ガイド](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/session-management.md)
|
- **タスク管理**:[セッション管理ガイド](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/session-management.md)
|
||||||
- **オーケストレーション**: [MCP サーバー ガイド](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/mcp-servers.md)
|
- **オーケストレーション**: [MCP サーバー ガイド](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/mcp-servers.md)
|
||||||
- **トークン効率**:[コマンドの基礎](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/commands.md#token-efficiency)
|
- **トークン効率**:[コマンドの基礎](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/commands.md#token-efficiency)
|
||||||
@ -1,16 +1,16 @@
|
|||||||
# セッション管理ガイド
|
# セッション管理ガイド
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/session-management.md#session-management-guide)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/session-management.md#session-management-guide)
|
||||||
|
|
||||||
SuperClaude は、Serena MCP サーバーを通じて永続的なセッション管理を提供し、Claude Code の会話全体にわたる真のコンテキスト保存と長期的なプロジェクト継続性を実現します。
|
SuperClaude は、Serena MCP サーバーを通じて永続的なセッション管理を提供し、Claude Code の会話全体にわたる真のコンテキスト保存と長期的なプロジェクト継続性を実現します。
|
||||||
|
|
||||||
## 永続メモリを使用したコアセッションコマンド
|
## 永続メモリを使用したコアセッションコマンド
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/session-management.md#core-session-commands-with-persistent-memory)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/session-management.md#core-session-commands-with-persistent-memory)
|
||||||
|
|
||||||
### `/sc:load`- 永続メモリによるコンテキストの読み込み
|
### `/sc:load`- 永続メモリによるコンテキストの読み込み
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/session-management.md#scload---context-loading-with-persistent-memory)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/session-management.md#scload---context-loading-with-persistent-memory)
|
||||||
|
|
||||||
**目的**: 以前のセッションからのプロジェクトコンテキストと永続メモリを使用してセッションを初期化します。MCP
|
**目的**: 以前のセッションからのプロジェクトコンテキストと永続メモリを使用してセッションを初期化します。MCP
|
||||||
**統合**: Serena MCP をトリガーして、保存されたプロジェクトメモリを読み取ります。
|
**統合**: Serena MCP をトリガーして、保存されたプロジェクトメモリを読み取ります。
|
||||||
@ -38,7 +38,7 @@ SuperClaude は、Serena MCP サーバーを通じて永続的なセッション
|
|||||||
|
|
||||||
### `/sc:save`- メモリへのセッションの永続性
|
### `/sc:save`- メモリへのセッションの永続性
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/session-management.md#scsave---session-persistence-to-memory)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/session-management.md#scsave---session-persistence-to-memory)
|
||||||
|
|
||||||
**目的**: 現在のセッション状態と決定を永続メモリ
|
**目的**: 現在のセッション状態と決定を永続メモリ
|
||||||
**MCP に保存します。統合**: Serena MCP をトリガーしてメモリ ファイルに書き込みます。
|
**MCP に保存します。統合**: Serena MCP をトリガーしてメモリ ファイルに書き込みます。
|
||||||
@ -66,7 +66,7 @@ SuperClaude は、Serena MCP サーバーを通じて永続的なセッション
|
|||||||
|
|
||||||
### `/sc:reflect`- メモリコンテキストによる進捗状況の評価
|
### `/sc:reflect`- メモリコンテキストによる進捗状況の評価
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/session-management.md#screflect---progress-assessment-with-memory-context)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/session-management.md#screflect---progress-assessment-with-memory-context)
|
||||||
|
|
||||||
**目的**: 保存されたメモリに対して現在の進行状況を分析し、セッションの完全性を検証する
|
**目的**: 保存されたメモリに対して現在の進行状況を分析し、セッションの完全性を検証する
|
||||||
**MCP 統合**: Serena MCP を使用して、保存されたメモリと現在の状態を比較する
|
**MCP 統合**: Serena MCP を使用して、保存されたメモリと現在の状態を比較する
|
||||||
@ -94,11 +94,11 @@ SuperClaude は、Serena MCP サーバーを通じて永続的なセッション
|
|||||||
|
|
||||||
## 永続メモリアーキテクチャ
|
## 永続メモリアーキテクチャ
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/session-management.md#persistent-memory-architecture)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/session-management.md#persistent-memory-architecture)
|
||||||
|
|
||||||
### Serena MCP が真の永続性を実現する方法
|
### Serena MCP が真の永続性を実現する方法
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/session-management.md#how-serena-mcp-enables-true-persistence)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/session-management.md#how-serena-mcp-enables-true-persistence)
|
||||||
|
|
||||||
**メモリストレージ**:
|
**メモリストレージ**:
|
||||||
|
|
||||||
@ -123,11 +123,11 @@ SuperClaude は、Serena MCP サーバーを通じて永続的なセッション
|
|||||||
|
|
||||||
## 永続性を備えたセッションライフサイクルパターン
|
## 永続性を備えたセッションライフサイクルパターン
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/session-management.md#session-lifecycle-patterns-with-persistence)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/session-management.md#session-lifecycle-patterns-with-persistence)
|
||||||
|
|
||||||
### 新しいプロジェクトの初期化
|
### 新しいプロジェクトの初期化
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/session-management.md#new-project-initialization)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/session-management.md#new-project-initialization)
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
# 1. Start fresh project
|
# 1. Start fresh project
|
||||||
@ -145,7 +145,7 @@ SuperClaude は、Serena MCP サーバーを通じて永続的なセッション
|
|||||||
|
|
||||||
### 既存の作業の再開(クロス会話)
|
### 既存の作業の再開(クロス会話)
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/session-management.md#resuming-existing-work-cross-conversation)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/session-management.md#resuming-existing-work-cross-conversation)
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
# 1. Load previous context from persistent memory
|
# 1. Load previous context from persistent memory
|
||||||
@ -163,7 +163,7 @@ SuperClaude は、Serena MCP サーバーを通じて永続的なセッション
|
|||||||
|
|
||||||
### 長期プロジェクト管理
|
### 長期プロジェクト管理
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/session-management.md#long-term-project-management)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/session-management.md#long-term-project-management)
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
# Weekly checkpoint pattern with persistence
|
# Weekly checkpoint pattern with persistence
|
||||||
@ -180,11 +180,11 @@ SuperClaude は、Serena MCP サーバーを通じて永続的なセッション
|
|||||||
|
|
||||||
## クロス会話の継続性
|
## クロス会話の継続性
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/session-management.md#cross-conversation-continuity)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/session-management.md#cross-conversation-continuity)
|
||||||
|
|
||||||
### 粘り強く新しい会話を始める
|
### 粘り強く新しい会話を始める
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/session-management.md#starting-new-conversations-with-persistence)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/session-management.md#starting-new-conversations-with-persistence)
|
||||||
|
|
||||||
新しい Claude Code 会話を開始すると、永続メモリ システムによって次のことが可能になります。
|
新しい Claude Code 会話を開始すると、永続メモリ システムによって次のことが可能になります。
|
||||||
|
|
||||||
@ -208,7 +208,7 @@ SuperClaude は、Serena MCP サーバーを通じて永続的なセッション
|
|||||||
|
|
||||||
### メモリ最適化
|
### メモリ最適化
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/session-management.md#memory-optimization)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/session-management.md#memory-optimization)
|
||||||
|
|
||||||
**有効なメモリ使用量**:
|
**有効なメモリ使用量**:
|
||||||
|
|
||||||
@ -233,11 +233,11 @@ SuperClaude は、Serena MCP サーバーを通じて永続的なセッション
|
|||||||
|
|
||||||
## 永続セッションのベストプラクティス
|
## 永続セッションのベストプラクティス
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/session-management.md#best-practices-for-persistent-sessions)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/session-management.md#best-practices-for-persistent-sessions)
|
||||||
|
|
||||||
### セッション開始プロトコル
|
### セッション開始プロトコル
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/session-management.md#session-start-protocol)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/session-management.md#session-start-protocol)
|
||||||
|
|
||||||
1. `/sc:load`既存のプロジェクトの場合は常に
|
1. `/sc:load`既存のプロジェクトの場合は常に
|
||||||
2. `/sc:reflect`記憶から現在の状態を理解するために使用する
|
2. `/sc:reflect`記憶から現在の状態を理解するために使用する
|
||||||
@ -246,7 +246,7 @@ SuperClaude は、Serena MCP サーバーを通じて永続的なセッション
|
|||||||
|
|
||||||
### セッション終了プロトコル
|
### セッション終了プロトコル
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/session-management.md#session-end-protocol)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/session-management.md#session-end-protocol)
|
||||||
|
|
||||||
1. `/sc:reflect`保存された目標に対する完全性を評価するために使用します
|
1. `/sc:reflect`保存された目標に対する完全性を評価するために使用します
|
||||||
2. 重要な決定を`/sc:save`将来のセッションのために保存する
|
2. 重要な決定を`/sc:save`将来のセッションのために保存する
|
||||||
@ -255,7 +255,7 @@ SuperClaude は、Serena MCP サーバーを通じて永続的なセッション
|
|||||||
|
|
||||||
### 記憶品質の維持
|
### 記憶品質の維持
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/session-management.md#memory-quality-maintenance)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/session-management.md#memory-quality-maintenance)
|
||||||
|
|
||||||
- 簡単に思い出せるように、分かりやすく説明的なメモリ名を使用する
|
- 簡単に思い出せるように、分かりやすく説明的なメモリ名を使用する
|
||||||
- 決定事項と代替アプローチに関する背景情報を含める
|
- 決定事項と代替アプローチに関する背景情報を含める
|
||||||
@ -264,11 +264,11 @@ SuperClaude は、Serena MCP サーバーを通じて永続的なセッション
|
|||||||
|
|
||||||
## 他のSuperClaude機能との統合
|
## 他のSuperClaude機能との統合
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/session-management.md#integration-with-other-superclaude-features)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/session-management.md#integration-with-other-superclaude-features)
|
||||||
|
|
||||||
### MCP サーバー調整
|
### MCP サーバー調整
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/session-management.md#mcp-server-coordination)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/session-management.md#mcp-server-coordination)
|
||||||
|
|
||||||
- **Serena MCP** : 永続メモリインフラストラクチャを提供します
|
- **Serena MCP** : 永続メモリインフラストラクチャを提供します
|
||||||
- **シーケンシャルMCP** : 保存されたメモリを使用して複雑な分析を強化します
|
- **シーケンシャルMCP** : 保存されたメモリを使用して複雑な分析を強化します
|
||||||
@ -277,7 +277,7 @@ SuperClaude は、Serena MCP サーバーを通じて永続的なセッション
|
|||||||
|
|
||||||
### エージェントとメモリの連携
|
### エージェントとメモリの連携
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/session-management.md#agent-collaboration-with-memory)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/session-management.md#agent-collaboration-with-memory)
|
||||||
|
|
||||||
- エージェントは強化されたコンテキストのために永続的なメモリにアクセスします
|
- エージェントは強化されたコンテキストのために永続的なメモリにアクセスします
|
||||||
- 以前の専門家の決定は保存され、参照されます
|
- 以前の専門家の決定は保存され、参照されます
|
||||||
@ -286,7 +286,7 @@ SuperClaude は、Serena MCP サーバーを通じて永続的なセッション
|
|||||||
|
|
||||||
### 永続性を備えたコマンド統合
|
### 永続性を備えたコマンド統合
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/session-management.md#command-integration-with-persistence)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/session-management.md#command-integration-with-persistence)
|
||||||
|
|
||||||
- すべての`/sc:`コマンドは永続的なコンテキストを参照し、そのコンテキストに基づいて構築できます。
|
- すべての`/sc:`コマンドは永続的なコンテキストを参照し、そのコンテキストに基づいて構築できます。
|
||||||
- 以前のコマンド出力と決定はセッション間で利用可能
|
- 以前のコマンド出力と決定はセッション間で利用可能
|
||||||
@ -295,11 +295,11 @@ SuperClaude は、Serena MCP サーバーを通じて永続的なセッション
|
|||||||
|
|
||||||
## 永続セッションのトラブルシューティング
|
## 永続セッションのトラブルシューティング
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/session-management.md#troubleshooting-persistent-sessions)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/session-management.md#troubleshooting-persistent-sessions)
|
||||||
|
|
||||||
### よくある問題
|
### よくある問題
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/session-management.md#common-issues)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/session-management.md#common-issues)
|
||||||
|
|
||||||
**メモリが読み込まれません**:
|
**メモリが読み込まれません**:
|
||||||
|
|
||||||
@ -324,7 +324,7 @@ SuperClaude は、Serena MCP サーバーを通じて永続的なセッション
|
|||||||
|
|
||||||
### クイックフィックス
|
### クイックフィックス
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/session-management.md#quick-fixes)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/session-management.md#quick-fixes)
|
||||||
|
|
||||||
**セッション状態をリセット**:
|
**セッション状態をリセット**:
|
||||||
|
|
||||||
@ -349,11 +349,11 @@ SuperClaude は、Serena MCP サーバーを通じて永続的なセッション
|
|||||||
|
|
||||||
## 高度な永続セッションパターン
|
## 高度な永続セッションパターン
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/session-management.md#advanced-persistent-session-patterns)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/session-management.md#advanced-persistent-session-patterns)
|
||||||
|
|
||||||
### 複数フェーズのプロジェクト
|
### 複数フェーズのプロジェクト
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/session-management.md#multi-phase-projects)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/session-management.md#multi-phase-projects)
|
||||||
|
|
||||||
- 整理のためにフェーズ固有のメモリ命名を使用する
|
- 整理のためにフェーズ固有のメモリ命名を使用する
|
||||||
- フェーズ全体でアーキテクチャ上の決定の継続性を維持する
|
- フェーズ全体でアーキテクチャ上の決定の継続性を維持する
|
||||||
@ -362,7 +362,7 @@ SuperClaude は、Serena MCP サーバーを通じて永続的なセッション
|
|||||||
|
|
||||||
### チームコラボレーション
|
### チームコラボレーション
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/session-management.md#team-collaboration)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/session-management.md#team-collaboration)
|
||||||
|
|
||||||
- 共有メモリの規則と命名規則
|
- 共有メモリの規則と命名規則
|
||||||
- チームのコンテキストにおける意思決定根拠の保存
|
- チームのコンテキストにおける意思決定根拠の保存
|
||||||
@ -371,7 +371,7 @@ SuperClaude は、Serena MCP サーバーを通じて永続的なセッション
|
|||||||
|
|
||||||
### 長期メンテナンス
|
### 長期メンテナンス
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/session-management.md#long-term-maintenance)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/session-management.md#long-term-maintenance)
|
||||||
|
|
||||||
- 完了したプロジェクトのメモリアーカイブ戦略
|
- 完了したプロジェクトのメモリアーカイブ戦略
|
||||||
- 蓄積された記憶によるパターンライブラリの開発
|
- 蓄積された記憶によるパターンライブラリの開発
|
||||||
@ -380,11 +380,11 @@ SuperClaude は、Serena MCP サーバーを通じて永続的なセッション
|
|||||||
|
|
||||||
## 永続セッション管理の主な利点
|
## 永続セッション管理の主な利点
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/session-management.md#key-benefits-of-persistent-session-management)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/session-management.md#key-benefits-of-persistent-session-management)
|
||||||
|
|
||||||
### プロジェクトの継続性
|
### プロジェクトの継続性
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/session-management.md#project-continuity)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/session-management.md#project-continuity)
|
||||||
|
|
||||||
- 複数の会話にわたるシームレスな作業継続
|
- 複数の会話にわたるシームレスな作業継続
|
||||||
- Claude Codeセッション間でコンテキストが失われることはありません
|
- Claude Codeセッション間でコンテキストが失われることはありません
|
||||||
@ -393,7 +393,7 @@ SuperClaude は、Serena MCP サーバーを通じて永続的なセッション
|
|||||||
|
|
||||||
### 生産性の向上
|
### 生産性の向上
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/session-management.md#enhanced-productivity)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/session-management.md#enhanced-productivity)
|
||||||
|
|
||||||
- プロジェクトのコンテキストを再度説明する必要性が減少
|
- プロジェクトのコンテキストを再度説明する必要性が減少
|
||||||
- 起動時間が速く、作業を継続できる
|
- 起動時間が速く、作業を継続できる
|
||||||
@ -402,7 +402,7 @@ SuperClaude は、Serena MCP サーバーを通じて永続的なセッション
|
|||||||
|
|
||||||
### 品質の一貫性
|
### 品質の一貫性
|
||||||
|
|
||||||
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/Docs/User-Guide/session-management.md#quality-consistency)
|
[](https://github.com/khayashi4337/SuperClaude_Framework/blob/master/docs/User-Guide/session-management.md#quality-consistency)
|
||||||
|
|
||||||
- セッション間で一貫したアーキテクチャパターン
|
- セッション間で一貫したアーキテクチャパターン
|
||||||
- コード品質の決定と標準の保持
|
- コード品質の決定と標準の保持
|
||||||
@ -35,7 +35,7 @@ SuperClaude는 Claude Code가 전문 지식을 위해 호출할 수 있는 15개
|
|||||||
|
|
||||||
### SuperClaude 에이전트란?
|
### SuperClaude 에이전트란?
|
||||||
|
|
||||||
**에이전트**는 Claude Code의 동작을 수정하는 컨텍스트 지시문으로 구현된 전문 AI 도메인 전문가입니다. 각 에이전트는 `SuperClaude/Agents/` 디렉토리에 있는 신중하게 작성된 `.md` 파일로, 도메인별 전문 지식, 행동 패턴, 문제 해결 접근 방식을 포함합니다.
|
**에이전트**는 Claude Code의 동작을 수정하는 컨텍스트 지시문으로 구현된 전문 AI 도메인 전문가입니다. 각 에이전트는 `superclaude/Agents/` 디렉토리에 있는 신중하게 작성된 `.md` 파일로, 도메인별 전문 지식, 행동 패턴, 문제 해결 접근 방식을 포함합니다.
|
||||||
|
|
||||||
**중요**: 에이전트는 별도의 AI 모델이나 소프트웨어가 아닙니다 - Claude Code가 읽어 전문화된 행동을 채택하는 컨텍스트 구성입니다.
|
**중요**: 에이전트는 별도의 AI 모델이나 소프트웨어가 아닙니다 - Claude Code가 읽어 전문화된 행동을 채택하는 컨텍스트 구성입니다.
|
||||||
|
|
||||||
@ -38,7 +38,7 @@ SuperClaude는 Claude Code가 읽어 전문화된 동작을 채택하는 행동
|
|||||||
|
|
||||||
### 컨텍스트 메커니즘:
|
### 컨텍스트 메커니즘:
|
||||||
1. **사용자 입력**: `/sc:implement "인증 시스템"` 입력
|
1. **사용자 입력**: `/sc:implement "인증 시스템"` 입력
|
||||||
2. **컨텍스트 로딩**: Claude Code가 `~/.claude/SuperClaude/Commands/implement.md` 읽음
|
2. **컨텍스트 로딩**: Claude Code가 `~/.claude/superclaude/Commands/implement.md` 읽음
|
||||||
3. **동작 채택**: Claude가 도메인 전문 지식, 도구 선택, 검증 패턴 적용
|
3. **동작 채택**: Claude가 도메인 전문 지식, 도구 선택, 검증 패턴 적용
|
||||||
4. **향상된 출력**: 보안 고려사항 및 모범 사례를 갖춘 구조화된 구현
|
4. **향상된 출력**: 보안 고려사항 및 모범 사례를 갖춘 구조화된 구현
|
||||||
|
|
||||||
@ -35,7 +35,7 @@ SuperClaude 提供了 14 个领域专业智能体,Claude Code 可以调用它
|
|||||||
## 核心概念
|
## 核心概念
|
||||||
|
|
||||||
### 什么是 SuperClaude 智能体?
|
### 什么是 SuperClaude 智能体?
|
||||||
**智能体**是专业的 AI 领域专家,以上下文指令的形式实现,用于修改 Claude Code 的行为。每个智能体都是 `SuperClaude/Agents/` 目录中精心制作的 `.md` 文件,包含领域特定的专业知识、行为模式和问题解决方法。
|
**智能体**是专业的 AI 领域专家,以上下文指令的形式实现,用于修改 Claude Code 的行为。每个智能体都是 `superclaude/Agents/` 目录中精心制作的 `.md` 文件,包含领域特定的专业知识、行为模式和问题解决方法。
|
||||||
|
|
||||||
**重要提示**:智能体不是独立的 AI 模型或软件 - 它们是 Claude Code 读取的上下文配置,用于采用专门的行为。
|
**重要提示**:智能体不是独立的 AI 模型或软件 - 它们是 Claude Code 读取的上下文配置,用于采用专门的行为。
|
||||||
|
|
||||||
@ -38,7 +38,7 @@ SuperClaude 提供行为上下文文件,Claude Code 通过读取这些文件
|
|||||||
|
|
||||||
### 上下文机制:
|
### 上下文机制:
|
||||||
1. **用户输入**:您输入 `/sc:implement "auth system"`
|
1. **用户输入**:您输入 `/sc:implement "auth system"`
|
||||||
2. **上下文加载**:Claude Code 读取 `~/.claude/SuperClaude/Commands/implement.md`
|
2. **上下文加载**:Claude Code 读取 `~/.claude/superclaude/Commands/implement.md`
|
||||||
3. **行为采用**:Claude 运用专业知识进行工具选择和验证
|
3. **行为采用**:Claude 运用专业知识进行工具选择和验证
|
||||||
4. **增强输出**:带有安全考虑和最佳实践的结构化实现
|
4. **增强输出**:带有安全考虑和最佳实践的结构化实现
|
||||||
|
|
||||||
@ -35,7 +35,7 @@ Before using this guide, verify agent selection works:
|
|||||||
## Core Concepts
|
## Core Concepts
|
||||||
|
|
||||||
### What are SuperClaude Agents?
|
### What are SuperClaude Agents?
|
||||||
**Agents** are specialized AI domain experts implemented as context instructions that modify Claude Code's behavior. Each agent is a carefully crafted `.md` file in the `SuperClaude/Agents/` directory containing domain-specific expertise, behavioral patterns, and problem-solving approaches.
|
**Agents** are specialized AI domain experts implemented as context instructions that modify Claude Code's behavior. Each agent is a carefully crafted `.md` file in the `superclaude/Agents/` directory containing domain-specific expertise, behavioral patterns, and problem-solving approaches.
|
||||||
|
|
||||||
**Important**: Agents are NOT separate AI models or software - they are context configurations that Claude Code reads to adopt specialized behaviors.
|
**Important**: Agents are NOT separate AI models or software - they are context configurations that Claude Code reads to adopt specialized behaviors.
|
||||||
|
|
||||||
@ -38,7 +38,7 @@ SuperClaude provides behavioral context files that Claude Code reads to adopt sp
|
|||||||
|
|
||||||
### The Context Mechanism:
|
### The Context Mechanism:
|
||||||
1. **User Input**: You type `/sc:implement "auth system"`
|
1. **User Input**: You type `/sc:implement "auth system"`
|
||||||
2. **Context Loading**: Claude Code reads `~/.claude/SuperClaude/Commands/implement.md`
|
2. **Context Loading**: Claude Code reads `~/.claude/superclaude/Commands/implement.md`
|
||||||
3. **Behavior Adoption**: Claude applies domain expertise, tool selection, and validation patterns
|
3. **Behavior Adoption**: Claude applies domain expertise, tool selection, and validation patterns
|
||||||
4. **Enhanced Output**: Structured implementation with security considerations and best practices
|
4. **Enhanced Output**: Structured implementation with security considerations and best practices
|
||||||
|
|
||||||
332
docs/pm-agent-implementation-status.md
Normal file
332
docs/pm-agent-implementation-status.md
Normal file
@ -0,0 +1,332 @@
|
|||||||
|
# PM Agent Implementation Status
|
||||||
|
|
||||||
|
**Last Updated**: 2025-10-14
|
||||||
|
**Version**: 1.0.0
|
||||||
|
|
||||||
|
## 📋 Overview
|
||||||
|
|
||||||
|
PM Agent has been redesigned as an **Always-Active Foundation Layer** that provides continuous context preservation, PDCA self-evaluation, and systematic knowledge management across sessions.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ✅ Implemented Features
|
||||||
|
|
||||||
|
### 1. Session Lifecycle (Serena MCP Memory Integration)
|
||||||
|
|
||||||
|
**Status**: ✅ Documented (Implementation Pending)
|
||||||
|
|
||||||
|
#### Session Start Protocol
|
||||||
|
- **Auto-Activation**: PM Agent restores context at every session start
|
||||||
|
- **Memory Operations**:
|
||||||
|
- `list_memories()` → Check existing state
|
||||||
|
- `read_memory("pm_context")` → Overall project context
|
||||||
|
- `read_memory("last_session")` → Previous session summary
|
||||||
|
- `read_memory("next_actions")` → Planned next steps
|
||||||
|
- **User Report**: Automatic status report (前回/進捗/今回/課題)
|
||||||
|
|
||||||
|
**Implementation Details**: superclaude/Commands/pm.md:34-97
|
||||||
|
|
||||||
|
#### During Work (PDCA Cycle)
|
||||||
|
- **Plan Phase**: Hypothesis generation with `docs/temp/hypothesis-*.md`
|
||||||
|
- **Do Phase**: Experimentation with `docs/temp/experiment-*.md`
|
||||||
|
- **Check Phase**: Self-evaluation with `docs/temp/lessons-*.md`
|
||||||
|
- **Act Phase**: Success → `docs/patterns/` | Failure → `docs/mistakes/`
|
||||||
|
|
||||||
|
**Implementation Details**: superclaude/Commands/pm.md:56-80, superclaude/Agents/pm-agent.md:48-98
|
||||||
|
|
||||||
|
#### Session End Protocol
|
||||||
|
- **Final Checkpoint**: `think_about_whether_you_are_done()`
|
||||||
|
- **State Preservation**: `write_memory("pm_context", complete_state)`
|
||||||
|
- **Documentation Cleanup**: Temporary → Formal/Mistakes
|
||||||
|
|
||||||
|
**Implementation Details**: superclaude/Commands/pm.md:82-97, superclaude/Agents/pm-agent.md:100-135
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 2. PDCA Self-Evaluation Pattern
|
||||||
|
|
||||||
|
**Status**: ✅ Documented (Implementation Pending)
|
||||||
|
|
||||||
|
#### Plan (仮説生成)
|
||||||
|
- Goal definition and success criteria
|
||||||
|
- Hypothesis formulation
|
||||||
|
- Risk identification
|
||||||
|
|
||||||
|
#### Do (実験実行)
|
||||||
|
- TodoWrite task tracking
|
||||||
|
- 30-minute checkpoint saves
|
||||||
|
- Trial-and-error recording
|
||||||
|
|
||||||
|
#### Check (自己評価)
|
||||||
|
- `think_about_task_adherence()` → Pattern compliance
|
||||||
|
- `think_about_collected_information()` → Context sufficiency
|
||||||
|
- `think_about_whether_you_are_done()` → Completion verification
|
||||||
|
|
||||||
|
#### Act (改善実行)
|
||||||
|
- Success → Extract pattern → docs/patterns/
|
||||||
|
- Failure → Root cause analysis → docs/mistakes/
|
||||||
|
- Update CLAUDE.md if global pattern
|
||||||
|
|
||||||
|
**Implementation Details**: superclaude/Agents/pm-agent.md:137-175
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3. Documentation Strategy (Trial-and-Error to Knowledge)
|
||||||
|
|
||||||
|
**Status**: ✅ Documented (Implementation Pending)
|
||||||
|
|
||||||
|
#### Temporary Documentation (`docs/temp/`)
|
||||||
|
- **Purpose**: Trial-and-error experimentation
|
||||||
|
- **Files**:
|
||||||
|
- `hypothesis-YYYY-MM-DD.md` → Initial plan
|
||||||
|
- `experiment-YYYY-MM-DD.md` → Implementation log
|
||||||
|
- `lessons-YYYY-MM-DD.md` → Reflections
|
||||||
|
- **Lifecycle**: 7 days → Move to formal or delete
|
||||||
|
|
||||||
|
#### Formal Documentation (`docs/patterns/`)
|
||||||
|
- **Purpose**: Successful patterns ready for reuse
|
||||||
|
- **Trigger**: Verified implementation success
|
||||||
|
- **Content**: Clean approach + concrete examples + "Last Verified" date
|
||||||
|
|
||||||
|
#### Mistake Documentation (`docs/mistakes/`)
|
||||||
|
- **Purpose**: Error records with prevention strategies
|
||||||
|
- **Structure**:
|
||||||
|
- What Happened (現象)
|
||||||
|
- Root Cause (根本原因)
|
||||||
|
- Why Missed (なぜ見逃したか)
|
||||||
|
- Fix Applied (修正内容)
|
||||||
|
- Prevention Checklist (防止策)
|
||||||
|
- Lesson Learned (教訓)
|
||||||
|
|
||||||
|
**Implementation Details**: superclaude/Agents/pm-agent.md:177-235
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 4. Memory Operations Reference
|
||||||
|
|
||||||
|
**Status**: ✅ Documented (Implementation Pending)
|
||||||
|
|
||||||
|
#### Memory Types
|
||||||
|
- **Session Start**: `pm_context`, `last_session`, `next_actions`
|
||||||
|
- **During Work**: `plan`, `checkpoint`, `decision`
|
||||||
|
- **Self-Evaluation**: `think_about_*` operations
|
||||||
|
- **Session End**: `last_session`, `next_actions`, `pm_context`
|
||||||
|
|
||||||
|
**Implementation Details**: superclaude/Agents/pm-agent.md:237-267
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🚧 Pending Implementation
|
||||||
|
|
||||||
|
### 1. Serena MCP Memory Operations
|
||||||
|
|
||||||
|
**Required Actions**:
|
||||||
|
- [ ] Implement `list_memories()` integration
|
||||||
|
- [ ] Implement `read_memory(key)` integration
|
||||||
|
- [ ] Implement `write_memory(key, value)` integration
|
||||||
|
- [ ] Test memory persistence across sessions
|
||||||
|
|
||||||
|
**Blockers**: Requires Serena MCP server configuration
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 2. PDCA Think Operations
|
||||||
|
|
||||||
|
**Required Actions**:
|
||||||
|
- [ ] Implement `think_about_task_adherence()` hook
|
||||||
|
- [ ] Implement `think_about_collected_information()` hook
|
||||||
|
- [ ] Implement `think_about_whether_you_are_done()` hook
|
||||||
|
- [ ] Integrate with TodoWrite completion tracking
|
||||||
|
|
||||||
|
**Blockers**: Requires Serena MCP server configuration
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3. Documentation Directory Structure
|
||||||
|
|
||||||
|
**Required Actions**:
|
||||||
|
- [ ] Create `docs/temp/` directory template
|
||||||
|
- [ ] Create `docs/patterns/` directory template
|
||||||
|
- [ ] Create `docs/mistakes/` directory template
|
||||||
|
- [ ] Implement automatic file lifecycle management (7-day cleanup)
|
||||||
|
|
||||||
|
**Blockers**: None (can be implemented immediately)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 4. Auto-Activation at Session Start
|
||||||
|
|
||||||
|
**Required Actions**:
|
||||||
|
- [ ] Implement PM Agent auto-activation hook
|
||||||
|
- [ ] Integrate with Claude Code session lifecycle
|
||||||
|
- [ ] Test context restoration across sessions
|
||||||
|
- [ ] Verify "前回/進捗/今回/課題" report generation
|
||||||
|
|
||||||
|
**Blockers**: Requires understanding of Claude Code initialization hooks
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📊 Implementation Roadmap
|
||||||
|
|
||||||
|
### Phase 1: Documentation Structure (Immediate)
|
||||||
|
**Timeline**: 1-2 days
|
||||||
|
**Complexity**: Low
|
||||||
|
|
||||||
|
1. Create `docs/temp/`, `docs/patterns/`, `docs/mistakes/` directories
|
||||||
|
2. Add README.md to each directory explaining purpose
|
||||||
|
3. Create template files for hypothesis/experiment/lessons
|
||||||
|
|
||||||
|
### Phase 2: Serena MCP Integration (High Priority)
|
||||||
|
**Timeline**: 1 week
|
||||||
|
**Complexity**: Medium
|
||||||
|
|
||||||
|
1. Configure Serena MCP server
|
||||||
|
2. Implement memory operations (read/write/list)
|
||||||
|
3. Test memory persistence
|
||||||
|
4. Integrate with PM Agent workflow
|
||||||
|
|
||||||
|
### Phase 3: PDCA Think Operations (High Priority)
|
||||||
|
**Timeline**: 1 week
|
||||||
|
**Complexity**: Medium
|
||||||
|
|
||||||
|
1. Implement think_about_* hooks
|
||||||
|
2. Integrate with TodoWrite
|
||||||
|
3. Test self-evaluation flow
|
||||||
|
4. Document best practices
|
||||||
|
|
||||||
|
### Phase 4: Auto-Activation (Critical)
|
||||||
|
**Timeline**: 2 weeks
|
||||||
|
**Complexity**: High
|
||||||
|
|
||||||
|
1. Research Claude Code initialization hooks
|
||||||
|
2. Implement PM Agent auto-activation
|
||||||
|
3. Test session start protocol
|
||||||
|
4. Verify context restoration
|
||||||
|
|
||||||
|
### Phase 5: Documentation Lifecycle (Medium Priority)
|
||||||
|
**Timeline**: 3-5 days
|
||||||
|
**Complexity**: Low
|
||||||
|
|
||||||
|
1. Implement 7-day temporary file cleanup
|
||||||
|
2. Create docs/temp → docs/patterns migration script
|
||||||
|
3. Create docs/temp → docs/mistakes migration script
|
||||||
|
4. Automate "Last Verified" date updates
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔍 Testing Strategy
|
||||||
|
|
||||||
|
### Unit Tests
|
||||||
|
- [ ] Memory operations (read/write/list)
|
||||||
|
- [ ] Think operations (task_adherence/collected_information/done)
|
||||||
|
- [ ] File lifecycle management (7-day cleanup)
|
||||||
|
|
||||||
|
### Integration Tests
|
||||||
|
- [ ] Session start → context restoration → user report
|
||||||
|
- [ ] PDCA cycle → temporary docs → formal docs
|
||||||
|
- [ ] Mistake detection → root cause analysis → prevention checklist
|
||||||
|
|
||||||
|
### E2E Tests
|
||||||
|
- [ ] Full session lifecycle (start → work → end)
|
||||||
|
- [ ] Cross-session context preservation
|
||||||
|
- [ ] Knowledge accumulation over time
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📖 Documentation Updates Needed
|
||||||
|
|
||||||
|
### SuperClaude Framework
|
||||||
|
- [x] `superclaude/Commands/pm.md` - Updated with session lifecycle
|
||||||
|
- [x] `superclaude/Agents/pm-agent.md` - Updated with PDCA and memory operations
|
||||||
|
- [ ] `docs/ARCHITECTURE.md` - Add PM Agent architecture section
|
||||||
|
- [ ] `docs/GETTING_STARTED.md` - Add PM Agent usage examples
|
||||||
|
|
||||||
|
### Global CLAUDE.md (Future)
|
||||||
|
- [ ] Add PM Agent PDCA cycle to global rules
|
||||||
|
- [ ] Document session lifecycle best practices
|
||||||
|
- [ ] Add memory operations reference
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🐛 Known Issues
|
||||||
|
|
||||||
|
### Issue 1: Serena MCP Not Configured
|
||||||
|
**Status**: Blocker
|
||||||
|
**Impact**: High (prevents memory operations)
|
||||||
|
**Resolution**: Configure Serena MCP server in project
|
||||||
|
|
||||||
|
### Issue 2: Auto-Activation Hook Unknown
|
||||||
|
**Status**: Research Needed
|
||||||
|
**Impact**: High (prevents session start automation)
|
||||||
|
**Resolution**: Research Claude Code initialization hooks
|
||||||
|
|
||||||
|
### Issue 3: Documentation Directory Structure Missing
|
||||||
|
**Status**: Can Implement Immediately
|
||||||
|
**Impact**: Medium (prevents PDCA documentation flow)
|
||||||
|
**Resolution**: Create directory structure (Phase 1)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📈 Success Metrics
|
||||||
|
|
||||||
|
### Quantitative
|
||||||
|
- **Context Restoration Rate**: 100% (sessions resume without re-explanation)
|
||||||
|
- **Documentation Coverage**: >80% (implementations documented)
|
||||||
|
- **Mistake Prevention**: <10% (recurring mistakes)
|
||||||
|
- **Session Continuity**: >90% (successful checkpoint restorations)
|
||||||
|
|
||||||
|
### Qualitative
|
||||||
|
- Users never re-explain project context
|
||||||
|
- Knowledge accumulates systematically
|
||||||
|
- Mistakes documented with prevention checklists
|
||||||
|
- Documentation stays fresh (Last Verified dates)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 Next Steps
|
||||||
|
|
||||||
|
1. **Immediate**: Create documentation directory structure (Phase 1)
|
||||||
|
2. **High Priority**: Configure Serena MCP server (Phase 2)
|
||||||
|
3. **High Priority**: Implement PDCA think operations (Phase 3)
|
||||||
|
4. **Critical**: Research and implement auto-activation (Phase 4)
|
||||||
|
5. **Medium Priority**: Implement documentation lifecycle automation (Phase 5)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📚 References
|
||||||
|
|
||||||
|
- **PM Agent Command**: `superclaude/Commands/pm.md`
|
||||||
|
- **PM Agent Persona**: `superclaude/Agents/pm-agent.md`
|
||||||
|
- **Salvaged Changes**: `tmp/salvaged-pm-agent/`
|
||||||
|
- **Original Patches**: `tmp/salvaged-pm-agent/*.patch`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔐 Commit Information
|
||||||
|
|
||||||
|
**Branch**: master
|
||||||
|
**Salvaged From**: `/Users/kazuki/.claude` (mistaken development location)
|
||||||
|
**Integration Date**: 2025-10-14
|
||||||
|
**Status**: Documentation complete, implementation pending
|
||||||
|
|
||||||
|
**Git Operations**:
|
||||||
|
```bash
|
||||||
|
# Salvaged valuable changes to tmp/
|
||||||
|
cp ~/.claude/Commands/pm.md tmp/salvaged-pm-agent/pm.md
|
||||||
|
cp ~/.claude/agents/pm-agent.md tmp/salvaged-pm-agent/pm-agent.md
|
||||||
|
git diff ~/.claude/CLAUDE.md > tmp/salvaged-pm-agent/CLAUDE.md.patch
|
||||||
|
git diff ~/.claude/RULES.md > tmp/salvaged-pm-agent/RULES.md.patch
|
||||||
|
|
||||||
|
# Cleaned up .claude directory
|
||||||
|
cd ~/.claude && git reset --hard HEAD
|
||||||
|
cd ~/.claude && rm -rf .git
|
||||||
|
|
||||||
|
# Applied changes to SuperClaude_Framework
|
||||||
|
cp tmp/salvaged-pm-agent/pm.md superclaude/Commands/pm.md
|
||||||
|
cp tmp/salvaged-pm-agent/pm-agent.md superclaude/Agents/pm-agent.md
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Last Verified**: 2025-10-14
|
||||||
|
**Next Review**: 2025-10-21 (1 week)
|
||||||
191
pr_documentation.md
Normal file
191
pr_documentation.md
Normal file
@ -0,0 +1,191 @@
|
|||||||
|
# Pull Request: Redesign PM Agent as Self-Improvement Meta-Layer
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
Redesigned PM Agent from task orchestration system to self-improvement workflow executor (meta-layer agent). PM Agent now complements existing auto-activation by systematically documenting implementations, analyzing mistakes, and maintaining knowledge base quality.
|
||||||
|
|
||||||
|
## Motivation
|
||||||
|
|
||||||
|
**Problem**: Initial PM Agent design competed with existing auto-activation system for task routing, creating confusion about responsibilities and adding unnecessary complexity.
|
||||||
|
|
||||||
|
**Solution**: Redefined PM Agent as a meta-layer that operates AFTER specialist agents complete tasks, focusing on:
|
||||||
|
- Post-implementation documentation
|
||||||
|
- Immediate mistake analysis and prevention
|
||||||
|
- Monthly documentation maintenance
|
||||||
|
- Pattern extraction and knowledge synthesis
|
||||||
|
|
||||||
|
**Value Proposition**: Transforms SuperClaude into a continuously learning system that accumulates knowledge, prevents recurring mistakes, and maintains fresh documentation without manual intervention.
|
||||||
|
|
||||||
|
## Changes
|
||||||
|
|
||||||
|
### 1. PM Agent Agent File (`superclaude/Agents/pm-agent.md`)
|
||||||
|
**Status**: Complete rewrite
|
||||||
|
|
||||||
|
**Before**:
|
||||||
|
- Category: orchestration
|
||||||
|
- Triggers: All user interactions (default mode)
|
||||||
|
- Role: Task router and sub-agent coordinator
|
||||||
|
- Competed with existing auto-activation
|
||||||
|
|
||||||
|
**After**:
|
||||||
|
- Category: meta
|
||||||
|
- Triggers: Post-implementation, mistake detection, monthly maintenance
|
||||||
|
- Role: Self-improvement workflow executor
|
||||||
|
- Complements existing auto-activation
|
||||||
|
|
||||||
|
**Key Additions**:
|
||||||
|
- Behavioral Mindset: "Think like a continuous learning system"
|
||||||
|
- Focus Areas: Implementation Documentation, Mistake Analysis, Pattern Recognition, Knowledge Maintenance, Self-Improvement Loop
|
||||||
|
- Self-Improvement Workflow Integration: BEFORE/DURING/AFTER/MISTAKE RECOVERY/MAINTENANCE phases
|
||||||
|
- Quality Standards: Latest, Minimal, Clear, Practical documentation criteria
|
||||||
|
- Performance Metrics: Documentation coverage, mistake prevention effectiveness, knowledge maintenance health
|
||||||
|
|
||||||
|
**Workflow Examples**:
|
||||||
|
1. Post-Implementation Documentation: Backend architect implements JWT → PM Agent documents pattern
|
||||||
|
2. Immediate Mistake Analysis: Kong Gateway bypass detected → PM Agent stops, analyzes, documents prevention
|
||||||
|
3. Monthly Documentation Maintenance: PM Agent prunes outdated docs, merges duplicates, updates versions
|
||||||
|
|
||||||
|
### 2. Framework Rules (`superclaude/Core/RULES.md`)
|
||||||
|
**Status**: Agent Orchestration section updated (lines 17-44)
|
||||||
|
|
||||||
|
**Changes**:
|
||||||
|
- Split orchestration into two clear layers:
|
||||||
|
- **Task Execution Layer**: Existing auto-activation (unchanged)
|
||||||
|
- **Self-Improvement Layer**: PM Agent meta-layer (new)
|
||||||
|
- Added orchestration flow diagram showing task execution → documentation cycle
|
||||||
|
- Clarified examples: ✅ Right patterns and ❌ Wrong anti-patterns
|
||||||
|
- Emphasized PM Agent activates AFTER task completion, not before/during
|
||||||
|
|
||||||
|
**Purpose**: Eliminate confusion between task routing (auto-activation) and learning (PM Agent)
|
||||||
|
|
||||||
|
### 3. README.md
|
||||||
|
**Status**: PM Agent description updated (line 208)
|
||||||
|
|
||||||
|
**Before**: "PM Agent orchestrates all interactions seamlessly"
|
||||||
|
|
||||||
|
**After**: "PM Agent ensures continuous learning through systematic documentation"
|
||||||
|
|
||||||
|
**Impact**: Accurate representation of PM Agent's meta-layer role in main documentation
|
||||||
|
|
||||||
|
### 4. Agents Guide (`docs/User-Guide/agents.md`)
|
||||||
|
**Status**: PM Agent section completely rewritten (lines 140-208)
|
||||||
|
|
||||||
|
**Changes**:
|
||||||
|
- Section title: "Orchestration Agent" → "Meta-Layer Agent"
|
||||||
|
- Expertise: Project orchestration → Self-improvement workflow executor
|
||||||
|
- Auto-Activation: Default mode for all interactions → Post-implementation, mistake detection, monthly maintenance
|
||||||
|
- Capabilities: Workflow orchestration → Implementation documentation, mistake analysis, pattern recognition, knowledge maintenance
|
||||||
|
- Examples: Vague feature requests → Post-implementation documentation, immediate mistake analysis, monthly maintenance
|
||||||
|
- Integration: Orchestrates entire ecosystem → Documents specialist agents' work
|
||||||
|
|
||||||
|
**Purpose**: User-facing documentation accurately reflects PM Agent's actual behavior
|
||||||
|
|
||||||
|
## Two-Layer Orchestration System
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────────┐
|
||||||
|
│ Task Execution Layer (Existing Auto-Activation) │
|
||||||
|
│ ─────────────────────────────────────────────────────── │
|
||||||
|
│ User Request → Context Analysis → Specialist Selection │
|
||||||
|
│ backend-architect | frontend-architect | security, etc. │
|
||||||
|
│ │
|
||||||
|
│ ↓ Implementation Complete ↓ │
|
||||||
|
└─────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
┌─────────────────────────────────────────────────────────┐
|
||||||
|
│ Self-Improvement Layer (PM Agent Meta-Layer) │
|
||||||
|
│ ─────────────────────────────────────────────────────── │
|
||||||
|
│ PM Agent Auto-Triggers → Documentation → Learning │
|
||||||
|
│ Pattern Recording | Mistake Analysis | Maintenance │
|
||||||
|
│ │
|
||||||
|
│ ↓ Knowledge Base Updated ↓ │
|
||||||
|
└─────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
**Flow**:
|
||||||
|
1. User: "Add JWT authentication"
|
||||||
|
2. Task Execution Layer: Auto-activation → security-engineer + backend-architect → Implementation
|
||||||
|
3. Self-Improvement Layer: PM Agent auto-triggers → Documents JWT pattern in docs/authentication.md → Records security decisions → Updates CLAUDE.md
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
**Validation Method**: Verified integration with existing self-improvement workflow
|
||||||
|
|
||||||
|
**Test Case**: agiletec project
|
||||||
|
- ✅ Reviewed `/Users/kazuki/github/agiletec/docs/self-improvement-workflow.md`
|
||||||
|
- ✅ Confirmed PM Agent design aligns with BEFORE/DURING/AFTER/MISTAKE RECOVERY phases
|
||||||
|
- ✅ Verified PM Agent complements (not competes with) existing workflow
|
||||||
|
- ✅ Confirmed agiletec workflow defines WHAT, PM Agent defines WHO executes it
|
||||||
|
|
||||||
|
**Integration Check**:
|
||||||
|
- ✅ PM Agent operates as meta-layer above specialist agents
|
||||||
|
- ✅ Existing auto-activation handles task routing (unchanged)
|
||||||
|
- ✅ PM Agent handles post-implementation documentation (new capability)
|
||||||
|
- ✅ No conflicts with existing agent activation patterns
|
||||||
|
|
||||||
|
## Breaking Changes
|
||||||
|
|
||||||
|
**None**. This is a design clarification and documentation update:
|
||||||
|
|
||||||
|
- ✅ Existing auto-activation continues to work identically
|
||||||
|
- ✅ Specialist agents (backend-architect, frontend-architect, etc.) unchanged
|
||||||
|
- ✅ User workflows remain the same
|
||||||
|
- ✅ Manual `@agent-[name]` override still works
|
||||||
|
- ✅ Commands (`/sc:implement`, `/sc:build`, etc.) unchanged
|
||||||
|
|
||||||
|
**New Capability**: PM Agent now automatically documents implementations and maintains knowledge base without user intervention.
|
||||||
|
|
||||||
|
## Impact on User Experience
|
||||||
|
|
||||||
|
**Before**:
|
||||||
|
- User requests task → Specialist agents implement → User manually documents (if at all)
|
||||||
|
- Mistakes repeated due to lack of systematic documentation
|
||||||
|
- Documentation becomes outdated over time
|
||||||
|
|
||||||
|
**After**:
|
||||||
|
- User requests task → Specialist agents implement → PM Agent auto-documents patterns
|
||||||
|
- Mistakes automatically analyzed with prevention checklists created
|
||||||
|
- Documentation systematically maintained through monthly reviews
|
||||||
|
|
||||||
|
**Result**: Zero additional user effort, continuous improvement built into framework
|
||||||
|
|
||||||
|
## Verification Checklist
|
||||||
|
|
||||||
|
- [x] PM Agent agent file completely rewritten with meta-layer design
|
||||||
|
- [x] RULES.md Agent Orchestration section updated with two-layer system
|
||||||
|
- [x] README.md PM Agent description updated
|
||||||
|
- [x] agents.md PM Agent section completely rewritten
|
||||||
|
- [x] Integration validated with agiletec project self-improvement workflow
|
||||||
|
- [x] All files properly formatted and consistent
|
||||||
|
- [x] No breaking changes to existing functionality
|
||||||
|
- [x] Documentation accurately reflects implementation
|
||||||
|
|
||||||
|
## Future Enhancements
|
||||||
|
|
||||||
|
**Potential Additions** (not included in this PR):
|
||||||
|
1. `/sc:pm status` - Show documentation coverage and maintenance health
|
||||||
|
2. `/sc:pm review` - Manual trigger for documentation review
|
||||||
|
3. Performance metrics dashboard - Track mistake prevention effectiveness
|
||||||
|
4. Integration with CI/CD - Auto-generate documentation on PR merge
|
||||||
|
|
||||||
|
**These are OPTIONAL** and should be separate PRs based on user feedback.
|
||||||
|
|
||||||
|
## Related Issues
|
||||||
|
|
||||||
|
Addresses internal design discussion about PM Agent role clarity and integration with existing auto-activation system.
|
||||||
|
|
||||||
|
## Reviewer Notes
|
||||||
|
|
||||||
|
**Key Points to Review**:
|
||||||
|
1. **pm-agent.md**: Complete rewrite - verify behavioral mindset, focus areas, and workflow examples make sense
|
||||||
|
2. **RULES.md**: Two-layer orchestration system - verify clear distinction between task execution and self-improvement
|
||||||
|
3. **agents.md**: User-facing documentation - verify accurate representation of PM Agent behavior
|
||||||
|
4. **Integration**: Verify PM Agent complements (not competes with) existing auto-activation
|
||||||
|
|
||||||
|
**Expected Outcome**: PM Agent transforms SuperClaude into a continuously learning system through systematic documentation, mistake analysis, and knowledge maintenance.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**PR Type**: Enhancement (Design Clarification)
|
||||||
|
**Complexity**: Medium (Documentation-focused, no code changes)
|
||||||
|
**Risk**: Low (No breaking changes, purely additive capability)
|
||||||
@ -3,7 +3,7 @@ requires = ["setuptools>=61.0", "wheel"]
|
|||||||
build-backend = "setuptools.build_meta"
|
build-backend = "setuptools.build_meta"
|
||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "SuperClaude"
|
name = "superclaude"
|
||||||
version = "4.1.5"
|
version = "4.1.5"
|
||||||
authors = [
|
authors = [
|
||||||
{name = "NomenAK", email = "anton.knoery@gmail.com"},
|
{name = "NomenAK", email = "anton.knoery@gmail.com"},
|
||||||
@ -43,8 +43,8 @@ GitHub = "https://github.com/SuperClaude-Org/SuperClaude_Framework"
|
|||||||
"NomenAK" = "https://github.com/NomenAK"
|
"NomenAK" = "https://github.com/NomenAK"
|
||||||
|
|
||||||
[project.scripts]
|
[project.scripts]
|
||||||
SuperClaude = "SuperClaude.__main__:main"
|
SuperClaude = "superclaude.__main__:main"
|
||||||
superclaude = "SuperClaude.__main__:main"
|
superclaude = "superclaude.__main__:main"
|
||||||
|
|
||||||
[project.optional-dependencies]
|
[project.optional-dependencies]
|
||||||
dev = [
|
dev = [
|
||||||
@ -64,12 +64,12 @@ include-package-data = true
|
|||||||
|
|
||||||
[tool.setuptools.packages.find]
|
[tool.setuptools.packages.find]
|
||||||
where = ["."]
|
where = ["."]
|
||||||
include = ["SuperClaude*", "setup*"]
|
include = ["superclaude*", "setup*"]
|
||||||
exclude = ["tests*", "*.tests*", "*.tests", ".git*", ".venv*", "*.egg-info*"]
|
exclude = ["tests*", "*.tests*", "*.tests", ".git*", ".venv*", "*.egg-info*"]
|
||||||
|
|
||||||
[tool.setuptools.package-data]
|
[tool.setuptools.package-data]
|
||||||
"setup" = ["data/*.json", "data/*.yaml", "data/*.yml", "components/*.py", "**/*.py"]
|
"setup" = ["data/*.json", "data/*.yaml", "data/*.yml", "components/*.py", "**/*.py"]
|
||||||
"SuperClaude" = ["*.md", "*.txt", "**/*.md", "**/*.txt", "**/*.json", "**/*.yaml", "**/*.yml"]
|
"superclaude" = ["*.md", "*.txt", "**/*.md", "**/*.txt", "**/*.json", "**/*.yaml", "**/*.yml"]
|
||||||
|
|
||||||
[tool.black]
|
[tool.black]
|
||||||
line-length = 88
|
line-length = 88
|
||||||
@ -115,7 +115,7 @@ markers = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[tool.coverage.run]
|
[tool.coverage.run]
|
||||||
source = ["SuperClaude", "setup"]
|
source = ["superclaude", "setup"]
|
||||||
omit = [
|
omit = [
|
||||||
"*/tests/*",
|
"*/tests/*",
|
||||||
"*/test_*",
|
"*/test_*",
|
||||||
|
|||||||
@ -107,8 +107,8 @@ Set these in your GitHub repository settings → Secrets and variables → Actio
|
|||||||
|
|
||||||
Before publishing, ensure version consistency across:
|
Before publishing, ensure version consistency across:
|
||||||
- `pyproject.toml`
|
- `pyproject.toml`
|
||||||
- `SuperClaude/__init__.py`
|
- `superclaude/__init__.py`
|
||||||
- `SuperClaude/__main__.py`
|
- `superclaude/__main__.py`
|
||||||
- `setup/__init__.py`
|
- `setup/__init__.py`
|
||||||
|
|
||||||
The build script validates version consistency automatically.
|
The build script validates version consistency automatically.
|
||||||
|
|||||||
@ -17,16 +17,13 @@ PROJECT_ROOT = Path(__file__).parent.parent
|
|||||||
DIST_DIR = PROJECT_ROOT / "dist"
|
DIST_DIR = PROJECT_ROOT / "dist"
|
||||||
BUILD_DIR = PROJECT_ROOT / "build"
|
BUILD_DIR = PROJECT_ROOT / "build"
|
||||||
|
|
||||||
|
|
||||||
def run_command(cmd: List[str], description: str) -> Tuple[bool, str]:
|
def run_command(cmd: List[str], description: str) -> Tuple[bool, str]:
|
||||||
"""Run a command and return success status and output"""
|
"""Run a command and return success status and output"""
|
||||||
print(f"🔄 {description}...")
|
print(f"🔄 {description}...")
|
||||||
try:
|
try:
|
||||||
result = subprocess.run(
|
result = subprocess.run(
|
||||||
cmd,
|
cmd, capture_output=True, text=True, cwd=PROJECT_ROOT, check=True
|
||||||
capture_output=True,
|
|
||||||
text=True,
|
|
||||||
cwd=PROJECT_ROOT,
|
|
||||||
check=True
|
|
||||||
)
|
)
|
||||||
print(f"✅ {description} completed successfully")
|
print(f"✅ {description} completed successfully")
|
||||||
return True, result.stdout
|
return True, result.stdout
|
||||||
@ -39,10 +36,11 @@ def run_command(cmd: List[str], description: str) -> Tuple[bool, str]:
|
|||||||
print(f"❌ {description} failed with exception: {e}")
|
print(f"❌ {description} failed with exception: {e}")
|
||||||
return False, str(e)
|
return False, str(e)
|
||||||
|
|
||||||
|
|
||||||
def clean_build_artifacts():
|
def clean_build_artifacts():
|
||||||
"""Clean previous build artifacts"""
|
"""Clean previous build artifacts"""
|
||||||
artifacts = [DIST_DIR, BUILD_DIR, PROJECT_ROOT / "SuperClaude.egg-info"]
|
artifacts = [DIST_DIR, BUILD_DIR, PROJECT_ROOT / "superclaude.egg-info"]
|
||||||
|
|
||||||
for artifact in artifacts:
|
for artifact in artifacts:
|
||||||
if artifact.exists():
|
if artifact.exists():
|
||||||
print(f"🧹 Removing {artifact}")
|
print(f"🧹 Removing {artifact}")
|
||||||
@ -51,179 +49,214 @@ def clean_build_artifacts():
|
|||||||
else:
|
else:
|
||||||
artifact.unlink()
|
artifact.unlink()
|
||||||
|
|
||||||
|
|
||||||
def install_build_tools() -> bool:
|
def install_build_tools() -> bool:
|
||||||
"""Install required build tools"""
|
"""Install required build tools"""
|
||||||
tools = ["build", "twine"]
|
tools = ["build", "twine"]
|
||||||
|
|
||||||
for tool in tools:
|
for tool in tools:
|
||||||
success, _ = run_command(
|
success, _ = run_command(
|
||||||
[sys.executable, "-m", "pip", "install", "--upgrade", tool],
|
[sys.executable, "-m", "pip", "install", "--upgrade", tool],
|
||||||
f"Installing {tool}"
|
f"Installing {tool}",
|
||||||
)
|
)
|
||||||
if not success:
|
if not success:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def validate_project_structure() -> bool:
|
def validate_project_structure() -> bool:
|
||||||
"""Validate project structure before building"""
|
"""Validate project structure before building"""
|
||||||
required_files = [
|
required_files = [
|
||||||
"pyproject.toml",
|
"pyproject.toml",
|
||||||
"README.md",
|
"README.md",
|
||||||
"LICENSE",
|
"LICENSE",
|
||||||
"SuperClaude/__init__.py",
|
"superclaude/__init__.py",
|
||||||
"SuperClaude/__main__.py",
|
"superclaude/__main__.py",
|
||||||
"setup/__init__.py"
|
"setup/__init__.py",
|
||||||
]
|
]
|
||||||
|
|
||||||
print("🔍 Validating project structure...")
|
print("🔍 Validating project structure...")
|
||||||
|
|
||||||
for file_path in required_files:
|
for file_path in required_files:
|
||||||
full_path = PROJECT_ROOT / file_path
|
full_path = PROJECT_ROOT / file_path
|
||||||
if not full_path.exists():
|
if not full_path.exists():
|
||||||
print(f"❌ Missing required file: {file_path}")
|
print(f"❌ Missing required file: {file_path}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# Check if version is consistent
|
# Check if version is consistent
|
||||||
try:
|
try:
|
||||||
from SuperClaude import __version__
|
from superclaude import __version__
|
||||||
|
|
||||||
print(f"📦 Package version: {__version__}")
|
print(f"📦 Package version: {__version__}")
|
||||||
except ImportError as e:
|
except ImportError as e:
|
||||||
print(f"❌ Could not import version from SuperClaude: {e}")
|
print(f"❌ Could not import version from SuperClaude: {e}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
print("✅ Project structure validation passed")
|
print("✅ Project structure validation passed")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def build_package() -> bool:
|
def build_package() -> bool:
|
||||||
"""Build the package"""
|
"""Build the package"""
|
||||||
return run_command(
|
return run_command(
|
||||||
[sys.executable, "-m", "build"],
|
[sys.executable, "-m", "build"], "Building package distributions"
|
||||||
"Building package distributions"
|
|
||||||
)[0]
|
)[0]
|
||||||
|
|
||||||
|
|
||||||
def validate_distribution() -> bool:
|
def validate_distribution() -> bool:
|
||||||
"""Validate the built distribution"""
|
"""Validate the built distribution"""
|
||||||
if not DIST_DIR.exists():
|
if not DIST_DIR.exists():
|
||||||
print("❌ Distribution directory does not exist")
|
print("❌ Distribution directory does not exist")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
dist_files = list(DIST_DIR.glob("*"))
|
dist_files = list(DIST_DIR.glob("*"))
|
||||||
if not dist_files:
|
if not dist_files:
|
||||||
print("❌ No distribution files found")
|
print("❌ No distribution files found")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
print(f"📦 Found distribution files:")
|
print(f"📦 Found distribution files:")
|
||||||
for file in dist_files:
|
for file in dist_files:
|
||||||
print(f" - {file.name}")
|
print(f" - {file.name}")
|
||||||
|
|
||||||
# Check with twine
|
# Check with twine
|
||||||
return run_command(
|
return run_command(
|
||||||
[sys.executable, "-m", "twine", "check"] + [str(f) for f in dist_files],
|
[sys.executable, "-m", "twine", "check"] + [str(f) for f in dist_files],
|
||||||
"Validating distributions with twine"
|
"Validating distributions with twine",
|
||||||
)[0]
|
)[0]
|
||||||
|
|
||||||
|
|
||||||
def upload_to_testpypi() -> bool:
|
def upload_to_testpypi() -> bool:
|
||||||
"""Upload to TestPyPI for testing"""
|
"""Upload to TestPyPI for testing"""
|
||||||
dist_files = list(DIST_DIR.glob("*"))
|
dist_files = list(DIST_DIR.glob("*"))
|
||||||
return run_command(
|
return run_command(
|
||||||
[sys.executable, "-m", "twine", "upload", "--repository", "testpypi"] + [str(f) for f in dist_files],
|
[sys.executable, "-m", "twine", "upload", "--repository", "testpypi"]
|
||||||
"Uploading to TestPyPI"
|
+ [str(f) for f in dist_files],
|
||||||
|
"Uploading to TestPyPI",
|
||||||
)[0]
|
)[0]
|
||||||
|
|
||||||
|
|
||||||
def upload_to_pypi() -> bool:
|
def upload_to_pypi() -> bool:
|
||||||
"""Upload to production PyPI"""
|
"""Upload to production PyPI"""
|
||||||
dist_files = list(DIST_DIR.glob("*"))
|
dist_files = list(DIST_DIR.glob("*"))
|
||||||
|
|
||||||
# Check if we have API token in environment
|
# Check if we have API token in environment
|
||||||
if os.getenv('PYPI_API_TOKEN'):
|
if os.getenv("PYPI_API_TOKEN"):
|
||||||
cmd = [
|
cmd = [
|
||||||
sys.executable, "-m", "twine", "upload",
|
sys.executable,
|
||||||
"--username", "__token__",
|
"-m",
|
||||||
"--password", os.getenv('PYPI_API_TOKEN')
|
"twine",
|
||||||
|
"upload",
|
||||||
|
"--username",
|
||||||
|
"__token__",
|
||||||
|
"--password",
|
||||||
|
os.getenv("PYPI_API_TOKEN"),
|
||||||
] + [str(f) for f in dist_files]
|
] + [str(f) for f in dist_files]
|
||||||
else:
|
else:
|
||||||
# Fall back to .pypirc configuration
|
# Fall back to .pypirc configuration
|
||||||
cmd = [sys.executable, "-m", "twine", "upload"] + [str(f) for f in dist_files]
|
cmd = [sys.executable, "-m", "twine", "upload"] + [str(f) for f in dist_files]
|
||||||
|
|
||||||
return run_command(cmd, "Uploading to PyPI")[0]
|
return run_command(cmd, "Uploading to PyPI")[0]
|
||||||
|
|
||||||
|
|
||||||
def test_installation_from_testpypi() -> bool:
|
def test_installation_from_testpypi() -> bool:
|
||||||
"""Test installation from TestPyPI"""
|
"""Test installation from TestPyPI"""
|
||||||
print("🧪 Testing installation from TestPyPI...")
|
print("🧪 Testing installation from TestPyPI...")
|
||||||
print(" Note: This will install in a separate process")
|
print(" Note: This will install in a separate process")
|
||||||
|
|
||||||
success, output = run_command([
|
success, output = run_command(
|
||||||
sys.executable, "-m", "pip", "install",
|
[
|
||||||
"--index-url", "https://test.pypi.org/simple/",
|
sys.executable,
|
||||||
"--extra-index-url", "https://pypi.org/simple/",
|
"-m",
|
||||||
"SuperClaude", "--force-reinstall", "--no-deps"
|
"pip",
|
||||||
], "Installing from TestPyPI")
|
"install",
|
||||||
|
"--index-url",
|
||||||
|
"https://test.pypi.org/simple/",
|
||||||
|
"--extra-index-url",
|
||||||
|
"https://pypi.org/simple/",
|
||||||
|
"SuperClaude",
|
||||||
|
"--force-reinstall",
|
||||||
|
"--no-deps",
|
||||||
|
],
|
||||||
|
"Installing from TestPyPI",
|
||||||
|
)
|
||||||
|
|
||||||
if success:
|
if success:
|
||||||
print("✅ Test installation successful")
|
print("✅ Test installation successful")
|
||||||
# Try to import the package
|
# Try to import the package
|
||||||
try:
|
try:
|
||||||
import SuperClaude
|
import superclaude
|
||||||
print(f"✅ Package import successful, version: {SuperClaude.__version__}")
|
|
||||||
|
print(f"✅ Package import successful, version: {superclaude.__version__}")
|
||||||
return True
|
return True
|
||||||
except ImportError as e:
|
except ImportError as e:
|
||||||
print(f"❌ Package import failed: {e}")
|
print(f"❌ Package import failed: {e}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
"""Main execution function"""
|
"""Main execution function"""
|
||||||
parser = argparse.ArgumentParser(description="Build and upload SuperClaude to PyPI")
|
parser = argparse.ArgumentParser(description="Build and upload SuperClaude to PyPI")
|
||||||
parser.add_argument("--testpypi", action="store_true", help="Upload to TestPyPI instead of PyPI")
|
parser.add_argument(
|
||||||
parser.add_argument("--test-install", action="store_true", help="Test installation from TestPyPI")
|
"--testpypi", action="store_true", help="Upload to TestPyPI instead of PyPI"
|
||||||
parser.add_argument("--skip-build", action="store_true", help="Skip build step (use existing dist)")
|
)
|
||||||
parser.add_argument("--skip-validation", action="store_true", help="Skip validation steps")
|
parser.add_argument(
|
||||||
parser.add_argument("--clean", action="store_true", help="Only clean build artifacts")
|
"--test-install", action="store_true", help="Test installation from TestPyPI"
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--skip-build", action="store_true", help="Skip build step (use existing dist)"
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--skip-validation", action="store_true", help="Skip validation steps"
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--clean", action="store_true", help="Only clean build artifacts"
|
||||||
|
)
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
# Change to project root
|
# Change to project root
|
||||||
os.chdir(PROJECT_ROOT)
|
os.chdir(PROJECT_ROOT)
|
||||||
|
|
||||||
if args.clean:
|
if args.clean:
|
||||||
clean_build_artifacts()
|
clean_build_artifacts()
|
||||||
return
|
return
|
||||||
|
|
||||||
print("🚀 SuperClaude PyPI Build and Upload Script")
|
print("🚀 SuperClaude PyPI Build and Upload Script")
|
||||||
print(f"📁 Working directory: {PROJECT_ROOT}")
|
print(f"📁 Working directory: {PROJECT_ROOT}")
|
||||||
|
|
||||||
# Step 1: Clean previous builds
|
# Step 1: Clean previous builds
|
||||||
clean_build_artifacts()
|
clean_build_artifacts()
|
||||||
|
|
||||||
# Step 2: Install build tools
|
# Step 2: Install build tools
|
||||||
if not install_build_tools():
|
if not install_build_tools():
|
||||||
print("❌ Failed to install build tools")
|
print("❌ Failed to install build tools")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
# Step 3: Validate project structure
|
# Step 3: Validate project structure
|
||||||
if not args.skip_validation and not validate_project_structure():
|
if not args.skip_validation and not validate_project_structure():
|
||||||
print("❌ Project structure validation failed")
|
print("❌ Project structure validation failed")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
# Step 4: Build package
|
# Step 4: Build package
|
||||||
if not args.skip_build:
|
if not args.skip_build:
|
||||||
if not build_package():
|
if not build_package():
|
||||||
print("❌ Package build failed")
|
print("❌ Package build failed")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
# Step 5: Validate distribution
|
# Step 5: Validate distribution
|
||||||
if not args.skip_validation and not validate_distribution():
|
if not args.skip_validation and not validate_distribution():
|
||||||
print("❌ Distribution validation failed")
|
print("❌ Distribution validation failed")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
# Step 6: Upload
|
# Step 6: Upload
|
||||||
if args.testpypi:
|
if args.testpypi:
|
||||||
if not upload_to_testpypi():
|
if not upload_to_testpypi():
|
||||||
print("❌ Upload to TestPyPI failed")
|
print("❌ Upload to TestPyPI failed")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
# Test installation if requested
|
# Test installation if requested
|
||||||
if args.test_install:
|
if args.test_install:
|
||||||
if not test_installation_from_testpypi():
|
if not test_installation_from_testpypi():
|
||||||
@ -231,16 +264,19 @@ def main():
|
|||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
else:
|
else:
|
||||||
# Confirm production upload
|
# Confirm production upload
|
||||||
response = input("🚨 Upload to production PyPI? This cannot be undone! (yes/no): ")
|
response = input(
|
||||||
|
"🚨 Upload to production PyPI? This cannot be undone! (yes/no): "
|
||||||
|
)
|
||||||
if response.lower() != "yes":
|
if response.lower() != "yes":
|
||||||
print("❌ Upload cancelled")
|
print("❌ Upload cancelled")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
if not upload_to_pypi():
|
if not upload_to_pypi():
|
||||||
print("❌ Upload to PyPI failed")
|
print("❌ Upload to PyPI failed")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
print("✅ All operations completed successfully!")
|
print("✅ All operations completed successfully!")
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|||||||
@ -12,6 +12,7 @@ from typing import List, Tuple
|
|||||||
# Project root
|
# Project root
|
||||||
PROJECT_ROOT = Path(__file__).parent.parent
|
PROJECT_ROOT = Path(__file__).parent.parent
|
||||||
|
|
||||||
|
|
||||||
def check_file_exists(file_path: Path, description: str) -> bool:
|
def check_file_exists(file_path: Path, description: str) -> bool:
|
||||||
"""Check if a required file exists"""
|
"""Check if a required file exists"""
|
||||||
if file_path.exists():
|
if file_path.exists():
|
||||||
@ -21,42 +22,45 @@ def check_file_exists(file_path: Path, description: str) -> bool:
|
|||||||
print(f"❌ Missing {description}: {file_path}")
|
print(f"❌ Missing {description}: {file_path}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def check_version_consistency() -> bool:
|
def check_version_consistency() -> bool:
|
||||||
"""Check if versions are consistent across files"""
|
"""Check if versions are consistent across files"""
|
||||||
print("\n🔍 Checking version consistency...")
|
print("\n🔍 Checking version consistency...")
|
||||||
|
|
||||||
versions = {}
|
versions = {}
|
||||||
|
|
||||||
# Check pyproject.toml
|
# Check pyproject.toml
|
||||||
try:
|
try:
|
||||||
pyproject_path = PROJECT_ROOT / "pyproject.toml"
|
pyproject_path = PROJECT_ROOT / "pyproject.toml"
|
||||||
with open(pyproject_path, 'r') as f:
|
with open(pyproject_path, "r") as f:
|
||||||
pyproject = toml.load(f)
|
pyproject = toml.load(f)
|
||||||
versions['pyproject.toml'] = pyproject['project']['version']
|
versions["pyproject.toml"] = pyproject["project"]["version"]
|
||||||
print(f"📋 pyproject.toml version: {versions['pyproject.toml']}")
|
print(f"📋 pyproject.toml version: {versions['pyproject.toml']}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"❌ Error reading pyproject.toml: {e}")
|
print(f"❌ Error reading pyproject.toml: {e}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# Check SuperClaude/__init__.py
|
# Check superclaude/__init__.py
|
||||||
try:
|
try:
|
||||||
sys.path.insert(0, str(PROJECT_ROOT))
|
sys.path.insert(0, str(PROJECT_ROOT))
|
||||||
from SuperClaude import __version__
|
from superclaude import __version__
|
||||||
versions['SuperClaude/__init__.py'] = __version__
|
|
||||||
print(f"📦 Package version: {versions['SuperClaude/__init__.py']}")
|
versions["superclaude/__init__.py"] = __version__
|
||||||
|
print(f"📦 Package version: {versions['superclaude/__init__.py']}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"❌ Error importing SuperClaude version: {e}")
|
print(f"❌ Error importing SuperClaude version: {e}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# Check setup/__init__.py
|
# Check setup/__init__.py
|
||||||
try:
|
try:
|
||||||
from setup import __version__ as setup_version
|
from setup import __version__ as setup_version
|
||||||
versions['setup/__init__.py'] = setup_version
|
|
||||||
|
versions["setup/__init__.py"] = setup_version
|
||||||
print(f"🔧 Setup version: {versions['setup/__init__.py']}")
|
print(f"🔧 Setup version: {versions['setup/__init__.py']}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"❌ Error importing setup version: {e}")
|
print(f"❌ Error importing setup version: {e}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# Check consistency
|
# Check consistency
|
||||||
all_versions = list(versions.values())
|
all_versions = list(versions.values())
|
||||||
if len(set(all_versions)) == 1:
|
if len(set(all_versions)) == 1:
|
||||||
@ -66,33 +70,35 @@ def check_version_consistency() -> bool:
|
|||||||
print(f"❌ Version mismatch: {versions}")
|
print(f"❌ Version mismatch: {versions}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def check_package_structure() -> bool:
|
def check_package_structure() -> bool:
|
||||||
"""Check if package structure is correct"""
|
"""Check if package structure is correct"""
|
||||||
print("\n🏗️ Checking package structure...")
|
print("\n🏗️ Checking package structure...")
|
||||||
|
|
||||||
required_structure = [
|
required_structure = [
|
||||||
("SuperClaude/__init__.py", "Main package __init__.py"),
|
("superclaude/__init__.py", "Main package __init__.py"),
|
||||||
("SuperClaude/__main__.py", "Main entry point"),
|
("superclaude/__main__.py", "Main entry point"),
|
||||||
("SuperClaude/Core/__init__.py", "Core module __init__.py"),
|
("superclaude/Core/__init__.py", "Core module __init__.py"),
|
||||||
("SuperClaude/Commands/__init__.py", "Commands module __init__.py"),
|
("superclaude/Commands/__init__.py", "Commands module __init__.py"),
|
||||||
("SuperClaude/Agents/__init__.py", "Agents module __init__.py"),
|
("superclaude/Agents/__init__.py", "Agents module __init__.py"),
|
||||||
("SuperClaude/Modes/__init__.py", "Modes module __init__.py"),
|
("superclaude/Modes/__init__.py", "Modes module __init__.py"),
|
||||||
("SuperClaude/MCP/__init__.py", "MCP module __init__.py"),
|
("superclaude/MCP/__init__.py", "MCP module __init__.py"),
|
||||||
("setup/__init__.py", "Setup package __init__.py"),
|
("setup/__init__.py", "Setup package __init__.py"),
|
||||||
]
|
]
|
||||||
|
|
||||||
all_good = True
|
all_good = True
|
||||||
for file_path, description in required_structure:
|
for file_path, description in required_structure:
|
||||||
full_path = PROJECT_ROOT / file_path
|
full_path = PROJECT_ROOT / file_path
|
||||||
if not check_file_exists(full_path, description):
|
if not check_file_exists(full_path, description):
|
||||||
all_good = False
|
all_good = False
|
||||||
|
|
||||||
return all_good
|
return all_good
|
||||||
|
|
||||||
|
|
||||||
def check_required_files() -> bool:
|
def check_required_files() -> bool:
|
||||||
"""Check if all required files are present"""
|
"""Check if all required files are present"""
|
||||||
print("\n📄 Checking required files...")
|
print("\n📄 Checking required files...")
|
||||||
|
|
||||||
required_files = [
|
required_files = [
|
||||||
("pyproject.toml", "Package configuration"),
|
("pyproject.toml", "Package configuration"),
|
||||||
("README.md", "Project README"),
|
("README.md", "Project README"),
|
||||||
@ -100,77 +106,81 @@ def check_required_files() -> bool:
|
|||||||
("MANIFEST.in", "Package manifest"),
|
("MANIFEST.in", "Package manifest"),
|
||||||
("setup.py", "Setup script"),
|
("setup.py", "Setup script"),
|
||||||
]
|
]
|
||||||
|
|
||||||
all_good = True
|
all_good = True
|
||||||
for file_path, description in required_files:
|
for file_path, description in required_files:
|
||||||
full_path = PROJECT_ROOT / file_path
|
full_path = PROJECT_ROOT / file_path
|
||||||
if not check_file_exists(full_path, description):
|
if not check_file_exists(full_path, description):
|
||||||
all_good = False
|
all_good = False
|
||||||
|
|
||||||
return all_good
|
return all_good
|
||||||
|
|
||||||
|
|
||||||
def check_pyproject_config() -> bool:
|
def check_pyproject_config() -> bool:
|
||||||
"""Check pyproject.toml configuration"""
|
"""Check pyproject.toml configuration"""
|
||||||
print("\n⚙️ Checking pyproject.toml configuration...")
|
print("\n⚙️ Checking pyproject.toml configuration...")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
pyproject_path = PROJECT_ROOT / "pyproject.toml"
|
pyproject_path = PROJECT_ROOT / "pyproject.toml"
|
||||||
with open(pyproject_path, 'r') as f:
|
with open(pyproject_path, "r") as f:
|
||||||
pyproject = toml.load(f)
|
pyproject = toml.load(f)
|
||||||
|
|
||||||
project = pyproject.get('project', {})
|
project = pyproject.get("project", {})
|
||||||
|
|
||||||
# Required fields
|
# Required fields
|
||||||
required_fields = ['name', 'version', 'description', 'authors']
|
required_fields = ["name", "version", "description", "authors"]
|
||||||
for field in required_fields:
|
for field in required_fields:
|
||||||
if field in project:
|
if field in project:
|
||||||
print(f"✅ {field}: {project[field]}")
|
print(f"✅ {field}: {project[field]}")
|
||||||
else:
|
else:
|
||||||
print(f"❌ Missing required field: {field}")
|
print(f"❌ Missing required field: {field}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# Check entry points
|
# Check entry points
|
||||||
scripts = project.get('scripts', {})
|
scripts = project.get("scripts", {})
|
||||||
if 'SuperClaude' in scripts:
|
if "superclaude" in scripts:
|
||||||
print(f"✅ CLI entry point: {scripts['SuperClaude']}")
|
print(f"✅ CLI entry point: {scripts['superclaude']}")
|
||||||
else:
|
else:
|
||||||
print("❌ Missing CLI entry point")
|
print("❌ Missing CLI entry point")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# Check classifiers
|
# Check classifiers
|
||||||
classifiers = project.get('classifiers', [])
|
classifiers = project.get("classifiers", [])
|
||||||
if len(classifiers) > 0:
|
if len(classifiers) > 0:
|
||||||
print(f"✅ {len(classifiers)} PyPI classifiers defined")
|
print(f"✅ {len(classifiers)} PyPI classifiers defined")
|
||||||
else:
|
else:
|
||||||
print("⚠️ No PyPI classifiers defined")
|
print("⚠️ No PyPI classifiers defined")
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"❌ Error reading pyproject.toml: {e}")
|
print(f"❌ Error reading pyproject.toml: {e}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def check_import_test() -> bool:
|
def check_import_test() -> bool:
|
||||||
"""Test if the package can be imported"""
|
"""Test if the package can be imported"""
|
||||||
print("\n🧪 Testing package import...")
|
print("\n🧪 Testing package import...")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
sys.path.insert(0, str(PROJECT_ROOT))
|
sys.path.insert(0, str(PROJECT_ROOT))
|
||||||
import SuperClaude
|
import superclaude
|
||||||
|
|
||||||
print(f"✅ SuperClaude import successful")
|
print(f"✅ SuperClaude import successful")
|
||||||
print(f"📦 Version: {SuperClaude.__version__}")
|
print(f"📦 Version: {superclaude.__version__}")
|
||||||
print(f"👤 Author: {SuperClaude.__author__}")
|
print(f"👤 Author: {superclaude.__author__}")
|
||||||
return True
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"❌ Import failed: {e}")
|
print(f"❌ Import failed: {e}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
"""Main validation function"""
|
"""Main validation function"""
|
||||||
print("🔍 SuperClaude PyPI Readiness Validation")
|
print("🔍 SuperClaude PyPI Readiness Validation")
|
||||||
print(f"📁 Project root: {PROJECT_ROOT}")
|
print(f"📁 Project root: {PROJECT_ROOT}")
|
||||||
print("=" * 50)
|
print("=" * 50)
|
||||||
|
|
||||||
checks = [
|
checks = [
|
||||||
("Required Files", check_required_files),
|
("Required Files", check_required_files),
|
||||||
("Package Structure", check_package_structure),
|
("Package Structure", check_package_structure),
|
||||||
@ -178,9 +188,9 @@ def main():
|
|||||||
("PyProject Configuration", check_pyproject_config),
|
("PyProject Configuration", check_pyproject_config),
|
||||||
("Import Test", check_import_test),
|
("Import Test", check_import_test),
|
||||||
]
|
]
|
||||||
|
|
||||||
results = []
|
results = []
|
||||||
|
|
||||||
for name, check_func in checks:
|
for name, check_func in checks:
|
||||||
try:
|
try:
|
||||||
result = check_func()
|
result = check_func()
|
||||||
@ -188,23 +198,23 @@ def main():
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"❌ {name} check failed with exception: {e}")
|
print(f"❌ {name} check failed with exception: {e}")
|
||||||
results.append((name, False))
|
results.append((name, False))
|
||||||
|
|
||||||
# Summary
|
# Summary
|
||||||
print("\n" + "=" * 50)
|
print("\n" + "=" * 50)
|
||||||
print("📊 VALIDATION SUMMARY")
|
print("📊 VALIDATION SUMMARY")
|
||||||
print("=" * 50)
|
print("=" * 50)
|
||||||
|
|
||||||
passed = 0
|
passed = 0
|
||||||
total = len(results)
|
total = len(results)
|
||||||
|
|
||||||
for name, result in results:
|
for name, result in results:
|
||||||
status = "✅ PASS" if result else "❌ FAIL"
|
status = "✅ PASS" if result else "❌ FAIL"
|
||||||
print(f"{status} {name}")
|
print(f"{status} {name}")
|
||||||
if result:
|
if result:
|
||||||
passed += 1
|
passed += 1
|
||||||
|
|
||||||
print(f"\n📈 Overall: {passed}/{total} checks passed")
|
print(f"\n📈 Overall: {passed}/{total} checks passed")
|
||||||
|
|
||||||
if passed == total:
|
if passed == total:
|
||||||
print("🎉 Project is ready for PyPI publication!")
|
print("🎉 Project is ready for PyPI publication!")
|
||||||
print("\nNext steps:")
|
print("\nNext steps:")
|
||||||
@ -215,6 +225,7 @@ def main():
|
|||||||
print("❌ Project needs fixes before PyPI publication")
|
print("❌ Project needs fixes before PyPI publication")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
success = main()
|
success = main()
|
||||||
sys.exit(0 if success else 1)
|
sys.exit(0 if success else 1)
|
||||||
|
|||||||
@ -21,4 +21,4 @@ DATA_DIR = SETUP_DIR / "data"
|
|||||||
from .utils.paths import get_home_directory
|
from .utils.paths import get_home_directory
|
||||||
|
|
||||||
# Installation target
|
# Installation target
|
||||||
DEFAULT_INSTALL_DIR = get_home_directory() / ".claude"
|
DEFAULT_INSTALL_DIR = get_home_directory() / ".claude"
|
||||||
|
|||||||
@ -7,5 +7,5 @@ from .base import OperationBase
|
|||||||
from .commands import *
|
from .commands import *
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
'OperationBase',
|
"OperationBase",
|
||||||
]
|
]
|
||||||
|
|||||||
@ -19,61 +19,65 @@ def get_command_info():
|
|||||||
"install": {
|
"install": {
|
||||||
"name": "install",
|
"name": "install",
|
||||||
"description": "Install SuperClaude framework components",
|
"description": "Install SuperClaude framework components",
|
||||||
"module": "setup.cli.commands.install"
|
"module": "setup.cli.commands.install",
|
||||||
},
|
},
|
||||||
"update": {
|
"update": {
|
||||||
"name": "update",
|
"name": "update",
|
||||||
"description": "Update existing SuperClaude installation",
|
"description": "Update existing SuperClaude installation",
|
||||||
"module": "setup.cli.commands.update"
|
"module": "setup.cli.commands.update",
|
||||||
},
|
},
|
||||||
"uninstall": {
|
"uninstall": {
|
||||||
"name": "uninstall",
|
"name": "uninstall",
|
||||||
"description": "Remove SuperClaude framework installation",
|
"description": "Remove SuperClaude framework installation",
|
||||||
"module": "setup.cli.commands.uninstall"
|
"module": "setup.cli.commands.uninstall",
|
||||||
},
|
},
|
||||||
"backup": {
|
"backup": {
|
||||||
"name": "backup",
|
"name": "backup",
|
||||||
"description": "Backup and restore SuperClaude installations",
|
"description": "Backup and restore SuperClaude installations",
|
||||||
"module": "setup.cli.commands.backup"
|
"module": "setup.cli.commands.backup",
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class OperationBase:
|
class OperationBase:
|
||||||
"""Base class for all operations providing common functionality"""
|
"""Base class for all operations providing common functionality"""
|
||||||
|
|
||||||
def __init__(self, operation_name: str):
|
def __init__(self, operation_name: str):
|
||||||
self.operation_name = operation_name
|
self.operation_name = operation_name
|
||||||
self.logger = None
|
self.logger = None
|
||||||
|
|
||||||
def setup_operation_logging(self, args):
|
def setup_operation_logging(self, args):
|
||||||
"""Setup operation-specific logging"""
|
"""Setup operation-specific logging"""
|
||||||
from ..utils.logger import get_logger
|
from ..utils.logger import get_logger
|
||||||
|
|
||||||
self.logger = get_logger()
|
self.logger = get_logger()
|
||||||
self.logger.info(f"Starting {self.operation_name} operation")
|
self.logger.info(f"Starting {self.operation_name} operation")
|
||||||
|
|
||||||
def validate_global_args(self, args):
|
def validate_global_args(self, args):
|
||||||
"""Validate global arguments common to all operations"""
|
"""Validate global arguments common to all operations"""
|
||||||
errors = []
|
errors = []
|
||||||
|
|
||||||
# Validate install directory
|
# Validate install directory
|
||||||
if hasattr(args, 'install_dir') and args.install_dir:
|
if hasattr(args, "install_dir") and args.install_dir:
|
||||||
from ..utils.security import SecurityValidator
|
from ..utils.security import SecurityValidator
|
||||||
is_safe, validation_errors = SecurityValidator.validate_installation_target(args.install_dir)
|
|
||||||
|
is_safe, validation_errors = SecurityValidator.validate_installation_target(
|
||||||
|
args.install_dir
|
||||||
|
)
|
||||||
if not is_safe:
|
if not is_safe:
|
||||||
errors.extend(validation_errors)
|
errors.extend(validation_errors)
|
||||||
|
|
||||||
# Check for conflicting flags
|
# Check for conflicting flags
|
||||||
if hasattr(args, 'verbose') and hasattr(args, 'quiet'):
|
if hasattr(args, "verbose") and hasattr(args, "quiet"):
|
||||||
if args.verbose and args.quiet:
|
if args.verbose and args.quiet:
|
||||||
errors.append("Cannot specify both --verbose and --quiet")
|
errors.append("Cannot specify both --verbose and --quiet")
|
||||||
|
|
||||||
return len(errors) == 0, errors
|
return len(errors) == 0, errors
|
||||||
|
|
||||||
def handle_operation_error(self, operation: str, error: Exception):
|
def handle_operation_error(self, operation: str, error: Exception):
|
||||||
"""Standard error handling for operations"""
|
"""Standard error handling for operations"""
|
||||||
if self.logger:
|
if self.logger:
|
||||||
self.logger.exception(f"Error in {operation} operation: {error}")
|
self.logger.exception(f"Error in {operation} operation: {error}")
|
||||||
else:
|
else:
|
||||||
print(f"Error in {operation} operation: {error}")
|
print(f"Error in {operation} operation: {error}")
|
||||||
return 1
|
return 1
|
||||||
|
|||||||
@ -10,9 +10,9 @@ from .update import UpdateOperation
|
|||||||
from .backup import BackupOperation
|
from .backup import BackupOperation
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
'OperationBase',
|
"OperationBase",
|
||||||
'InstallOperation',
|
"InstallOperation",
|
||||||
'UninstallOperation',
|
"UninstallOperation",
|
||||||
'UpdateOperation',
|
"UpdateOperation",
|
||||||
'BackupOperation'
|
"BackupOperation",
|
||||||
]
|
]
|
||||||
|
|||||||
@ -9,14 +9,22 @@ import tarfile
|
|||||||
import json
|
import json
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from ...utils.paths import get_home_directory
|
from ...utils.paths import get_home_directory
|
||||||
from datetime import datetime
|
from datetime import datetime, timedelta
|
||||||
from typing import List, Optional, Dict, Any, Tuple
|
from typing import List, Optional, Dict, Any, Tuple
|
||||||
import argparse
|
import argparse
|
||||||
|
|
||||||
from ...services.settings import SettingsService
|
from ...services.settings import SettingsService
|
||||||
from ...utils.ui import (
|
from ...utils.ui import (
|
||||||
display_header, display_info, display_success, display_error,
|
display_header,
|
||||||
display_warning, Menu, confirm, ProgressBar, Colors, format_size
|
display_info,
|
||||||
|
display_success,
|
||||||
|
display_error,
|
||||||
|
display_warning,
|
||||||
|
Menu,
|
||||||
|
confirm,
|
||||||
|
ProgressBar,
|
||||||
|
Colors,
|
||||||
|
format_size,
|
||||||
)
|
)
|
||||||
from ...utils.logger import get_logger
|
from ...utils.logger import get_logger
|
||||||
from ... import DEFAULT_INSTALL_DIR
|
from ... import DEFAULT_INSTALL_DIR
|
||||||
@ -25,7 +33,7 @@ from . import OperationBase
|
|||||||
|
|
||||||
class BackupOperation(OperationBase):
|
class BackupOperation(OperationBase):
|
||||||
"""Backup operation implementation"""
|
"""Backup operation implementation"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__("backup")
|
super().__init__("backup")
|
||||||
|
|
||||||
@ -33,7 +41,7 @@ class BackupOperation(OperationBase):
|
|||||||
def register_parser(subparsers, global_parser=None) -> argparse.ArgumentParser:
|
def register_parser(subparsers, global_parser=None) -> argparse.ArgumentParser:
|
||||||
"""Register backup CLI arguments"""
|
"""Register backup CLI arguments"""
|
||||||
parents = [global_parser] if global_parser else []
|
parents = [global_parser] if global_parser else []
|
||||||
|
|
||||||
parser = subparsers.add_parser(
|
parser = subparsers.add_parser(
|
||||||
"backup",
|
"backup",
|
||||||
help="Backup and restore SuperClaude installations",
|
help="Backup and restore SuperClaude installations",
|
||||||
@ -48,84 +56,70 @@ Examples:
|
|||||||
SuperClaude backup --cleanup --force # Clean up old backups (forced)
|
SuperClaude backup --cleanup --force # Clean up old backups (forced)
|
||||||
""",
|
""",
|
||||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||||
parents=parents
|
parents=parents,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Backup operations (mutually exclusive)
|
# Backup operations (mutually exclusive)
|
||||||
operation_group = parser.add_mutually_exclusive_group(required=True)
|
operation_group = parser.add_mutually_exclusive_group(required=True)
|
||||||
|
|
||||||
operation_group.add_argument(
|
operation_group.add_argument(
|
||||||
"--create",
|
"--create", action="store_true", help="Create a new backup"
|
||||||
action="store_true",
|
|
||||||
help="Create a new backup"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
operation_group.add_argument(
|
operation_group.add_argument(
|
||||||
"--list",
|
"--list", action="store_true", help="List available backups"
|
||||||
action="store_true",
|
|
||||||
help="List available backups"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
operation_group.add_argument(
|
operation_group.add_argument(
|
||||||
"--restore",
|
"--restore",
|
||||||
nargs="?",
|
nargs="?",
|
||||||
const="interactive",
|
const="interactive",
|
||||||
help="Restore from backup (optionally specify backup file)"
|
help="Restore from backup (optionally specify backup file)",
|
||||||
)
|
)
|
||||||
|
|
||||||
operation_group.add_argument(
|
operation_group.add_argument(
|
||||||
"--info",
|
"--info", type=str, help="Show information about a specific backup file"
|
||||||
type=str,
|
|
||||||
help="Show information about a specific backup file"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
operation_group.add_argument(
|
operation_group.add_argument(
|
||||||
"--cleanup",
|
"--cleanup", action="store_true", help="Clean up old backup files"
|
||||||
action="store_true",
|
|
||||||
help="Clean up old backup files"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Backup options
|
# Backup options
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--backup-dir",
|
"--backup-dir",
|
||||||
type=Path,
|
type=Path,
|
||||||
help="Backup directory (default: <install-dir>/backups)"
|
help="Backup directory (default: <install-dir>/backups)",
|
||||||
)
|
)
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument("--name", type=str, help="Custom backup name (for --create)")
|
||||||
"--name",
|
|
||||||
type=str,
|
|
||||||
help="Custom backup name (for --create)"
|
|
||||||
)
|
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--compress",
|
"--compress",
|
||||||
choices=["none", "gzip", "bzip2"],
|
choices=["none", "gzip", "bzip2"],
|
||||||
default="gzip",
|
default="gzip",
|
||||||
help="Compression method (default: gzip)"
|
help="Compression method (default: gzip)",
|
||||||
)
|
)
|
||||||
|
|
||||||
# Restore options
|
# Restore options
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--overwrite",
|
"--overwrite",
|
||||||
action="store_true",
|
action="store_true",
|
||||||
help="Overwrite existing files during restore"
|
help="Overwrite existing files during restore",
|
||||||
)
|
)
|
||||||
|
|
||||||
# Cleanup options
|
# Cleanup options
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--keep",
|
"--keep",
|
||||||
type=int,
|
type=int,
|
||||||
default=5,
|
default=5,
|
||||||
help="Number of backups to keep during cleanup (default: 5)"
|
help="Number of backups to keep during cleanup (default: 5)",
|
||||||
)
|
)
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--older-than",
|
"--older-than", type=int, help="Remove backups older than N days"
|
||||||
type=int,
|
|
||||||
help="Remove backups older than N days"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
|
|
||||||
@ -141,7 +135,10 @@ def check_installation_exists(install_dir: Path) -> bool:
|
|||||||
"""Check if SuperClaude installation (v2 included) exists"""
|
"""Check if SuperClaude installation (v2 included) exists"""
|
||||||
settings_manager = SettingsService(install_dir)
|
settings_manager = SettingsService(install_dir)
|
||||||
|
|
||||||
return settings_manager.check_installation_exists() or settings_manager.check_v2_installation_exists()
|
return (
|
||||||
|
settings_manager.check_installation_exists()
|
||||||
|
or settings_manager.check_v2_installation_exists()
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def get_backup_info(backup_path: Path) -> Dict[str, Any]:
|
def get_backup_info(backup_path: Path) -> Dict[str, Any]:
|
||||||
@ -151,18 +148,18 @@ def get_backup_info(backup_path: Path) -> Dict[str, Any]:
|
|||||||
"exists": backup_path.exists(),
|
"exists": backup_path.exists(),
|
||||||
"size": 0,
|
"size": 0,
|
||||||
"created": None,
|
"created": None,
|
||||||
"metadata": {}
|
"metadata": {},
|
||||||
}
|
}
|
||||||
|
|
||||||
if not backup_path.exists():
|
if not backup_path.exists():
|
||||||
return info
|
return info
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Get file stats
|
# Get file stats
|
||||||
stats = backup_path.stat()
|
stats = backup_path.stat()
|
||||||
info["size"] = stats.st_size
|
info["size"] = stats.st_size
|
||||||
info["created"] = datetime.fromtimestamp(stats.st_mtime)
|
info["created"] = datetime.fromtimestamp(stats.st_mtime)
|
||||||
|
|
||||||
# Try to read metadata from backup
|
# Try to read metadata from backup
|
||||||
if backup_path.suffix == ".gz":
|
if backup_path.suffix == ".gz":
|
||||||
mode = "r:gz"
|
mode = "r:gz"
|
||||||
@ -170,7 +167,7 @@ def get_backup_info(backup_path: Path) -> Dict[str, Any]:
|
|||||||
mode = "r:bz2"
|
mode = "r:bz2"
|
||||||
else:
|
else:
|
||||||
mode = "r"
|
mode = "r"
|
||||||
|
|
||||||
with tarfile.open(backup_path, mode) as tar:
|
with tarfile.open(backup_path, mode) as tar:
|
||||||
# Look for metadata file
|
# Look for metadata file
|
||||||
try:
|
try:
|
||||||
@ -180,32 +177,32 @@ def get_backup_info(backup_path: Path) -> Dict[str, Any]:
|
|||||||
info["metadata"] = json.loads(metadata_file.read().decode())
|
info["metadata"] = json.loads(metadata_file.read().decode())
|
||||||
except KeyError:
|
except KeyError:
|
||||||
pass # No metadata file
|
pass # No metadata file
|
||||||
|
|
||||||
# Get list of files in backup
|
# Get list of files in backup
|
||||||
info["files"] = len(tar.getnames())
|
info["files"] = len(tar.getnames())
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
info["error"] = str(e)
|
info["error"] = str(e)
|
||||||
|
|
||||||
return info
|
return info
|
||||||
|
|
||||||
|
|
||||||
def list_backups(backup_dir: Path) -> List[Dict[str, Any]]:
|
def list_backups(backup_dir: Path) -> List[Dict[str, Any]]:
|
||||||
"""List all available backups"""
|
"""List all available backups"""
|
||||||
backups = []
|
backups = []
|
||||||
|
|
||||||
if not backup_dir.exists():
|
if not backup_dir.exists():
|
||||||
return backups
|
return backups
|
||||||
|
|
||||||
# Find all backup files
|
# Find all backup files
|
||||||
for backup_file in backup_dir.glob("*.tar*"):
|
for backup_file in backup_dir.glob("*.tar*"):
|
||||||
if backup_file.is_file():
|
if backup_file.is_file():
|
||||||
info = get_backup_info(backup_file)
|
info = get_backup_info(backup_file)
|
||||||
backups.append(info)
|
backups.append(info)
|
||||||
|
|
||||||
# Sort by creation date (newest first)
|
# Sort by creation date (newest first)
|
||||||
backups.sort(key=lambda x: x.get("created", datetime.min), reverse=True)
|
backups.sort(key=lambda x: x.get("created", datetime.min), reverse=True)
|
||||||
|
|
||||||
return backups
|
return backups
|
||||||
|
|
||||||
|
|
||||||
@ -213,43 +210,49 @@ def display_backup_list(backups: List[Dict[str, Any]]) -> None:
|
|||||||
"""Display list of available backups"""
|
"""Display list of available backups"""
|
||||||
print(f"\n{Colors.CYAN}{Colors.BRIGHT}Available Backups{Colors.RESET}")
|
print(f"\n{Colors.CYAN}{Colors.BRIGHT}Available Backups{Colors.RESET}")
|
||||||
print("=" * 70)
|
print("=" * 70)
|
||||||
|
|
||||||
if not backups:
|
if not backups:
|
||||||
print(f"{Colors.YELLOW}No backups found{Colors.RESET}")
|
print(f"{Colors.YELLOW}No backups found{Colors.RESET}")
|
||||||
return
|
return
|
||||||
|
|
||||||
print(f"{'Name':<30} {'Size':<10} {'Created':<20} {'Files':<8}")
|
print(f"{'Name':<30} {'Size':<10} {'Created':<20} {'Files':<8}")
|
||||||
print("-" * 70)
|
print("-" * 70)
|
||||||
|
|
||||||
for backup in backups:
|
for backup in backups:
|
||||||
name = backup["path"].name
|
name = backup["path"].name
|
||||||
size = format_size(backup["size"]) if backup["size"] > 0 else "unknown"
|
size = format_size(backup["size"]) if backup["size"] > 0 else "unknown"
|
||||||
created = backup["created"].strftime("%Y-%m-%d %H:%M") if backup["created"] else "unknown"
|
created = (
|
||||||
|
backup["created"].strftime("%Y-%m-%d %H:%M")
|
||||||
|
if backup["created"]
|
||||||
|
else "unknown"
|
||||||
|
)
|
||||||
files = str(backup.get("files", "unknown"))
|
files = str(backup.get("files", "unknown"))
|
||||||
|
|
||||||
print(f"{name:<30} {size:<10} {created:<20} {files:<8}")
|
print(f"{name:<30} {size:<10} {created:<20} {files:<8}")
|
||||||
|
|
||||||
print()
|
print()
|
||||||
|
|
||||||
|
|
||||||
def create_backup_metadata(install_dir: Path) -> Dict[str, Any]:
|
def create_backup_metadata(install_dir: Path) -> Dict[str, Any]:
|
||||||
"""Create metadata for the backup"""
|
"""Create metadata for the backup"""
|
||||||
|
from setup import __version__
|
||||||
|
|
||||||
metadata = {
|
metadata = {
|
||||||
"backup_version": __version__,
|
"backup_version": __version__,
|
||||||
"created": datetime.now().isoformat(),
|
"created": datetime.now().isoformat(),
|
||||||
"install_dir": str(install_dir),
|
"install_dir": str(install_dir),
|
||||||
"components": {},
|
"components": {},
|
||||||
"framework_version": "unknown"
|
"framework_version": "unknown",
|
||||||
}
|
}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Get installed components from metadata
|
# Get installed components from metadata
|
||||||
settings_manager = SettingsService(install_dir)
|
settings_manager = SettingsService(install_dir)
|
||||||
framework_config = settings_manager.get_metadata_setting("framework")
|
framework_config = settings_manager.get_metadata_setting("framework")
|
||||||
|
|
||||||
if framework_config:
|
if framework_config:
|
||||||
metadata["framework_version"] = framework_config.get("version", "unknown")
|
metadata["framework_version"] = framework_config.get("version", "unknown")
|
||||||
|
|
||||||
if "components" in framework_config:
|
if "components" in framework_config:
|
||||||
for component_name in framework_config["components"]:
|
for component_name in framework_config["components"]:
|
||||||
version = settings_manager.get_component_version(component_name)
|
version = settings_manager.get_component_version(component_name)
|
||||||
@ -257,31 +260,31 @@ def create_backup_metadata(install_dir: Path) -> Dict[str, Any]:
|
|||||||
metadata["components"][component_name] = version
|
metadata["components"][component_name] = version
|
||||||
except Exception:
|
except Exception:
|
||||||
pass # Continue without metadata
|
pass # Continue without metadata
|
||||||
|
|
||||||
return metadata
|
return metadata
|
||||||
|
|
||||||
|
|
||||||
def create_backup(args: argparse.Namespace) -> bool:
|
def create_backup(args: argparse.Namespace) -> bool:
|
||||||
"""Create a new backup"""
|
"""Create a new backup"""
|
||||||
logger = get_logger()
|
logger = get_logger()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Check if installation exists
|
# Check if installation exists
|
||||||
if not check_installation_exists(args.install_dir):
|
if not check_installation_exists(args.install_dir):
|
||||||
logger.error(f"No SuperClaude installation found in {args.install_dir}")
|
logger.error(f"No SuperClaude installation found in {args.install_dir}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# Setup backup directory
|
# Setup backup directory
|
||||||
backup_dir = get_backup_directory(args)
|
backup_dir = get_backup_directory(args)
|
||||||
backup_dir.mkdir(parents=True, exist_ok=True)
|
backup_dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
# Generate backup filename
|
# Generate backup filename
|
||||||
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
||||||
if args.name:
|
if args.name:
|
||||||
backup_name = f"{args.name}_{timestamp}"
|
backup_name = f"{args.name}_{timestamp}"
|
||||||
else:
|
else:
|
||||||
backup_name = f"superclaude_backup_{timestamp}"
|
backup_name = f"superclaude_backup_{timestamp}"
|
||||||
|
|
||||||
# Determine compression
|
# Determine compression
|
||||||
if args.compress == "gzip":
|
if args.compress == "gzip":
|
||||||
backup_file = backup_dir / f"{backup_name}.tar.gz"
|
backup_file = backup_dir / f"{backup_name}.tar.gz"
|
||||||
@ -292,24 +295,27 @@ def create_backup(args: argparse.Namespace) -> bool:
|
|||||||
else:
|
else:
|
||||||
backup_file = backup_dir / f"{backup_name}.tar"
|
backup_file = backup_dir / f"{backup_name}.tar"
|
||||||
mode = "w"
|
mode = "w"
|
||||||
|
|
||||||
logger.info(f"Creating backup: {backup_file}")
|
logger.info(f"Creating backup: {backup_file}")
|
||||||
|
|
||||||
# Create metadata
|
# Create metadata
|
||||||
metadata = create_backup_metadata(args.install_dir)
|
metadata = create_backup_metadata(args.install_dir)
|
||||||
|
|
||||||
# Create backup
|
# Create backup
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
|
|
||||||
with tarfile.open(backup_file, mode) as tar:
|
with tarfile.open(backup_file, mode) as tar:
|
||||||
# Add metadata file
|
# Add metadata file
|
||||||
import tempfile
|
import tempfile
|
||||||
with tempfile.NamedTemporaryFile(mode='w', suffix='.json', delete=False) as temp_file:
|
|
||||||
|
with tempfile.NamedTemporaryFile(
|
||||||
|
mode="w", suffix=".json", delete=False
|
||||||
|
) as temp_file:
|
||||||
json.dump(metadata, temp_file, indent=2)
|
json.dump(metadata, temp_file, indent=2)
|
||||||
temp_file.flush()
|
temp_file.flush()
|
||||||
tar.add(temp_file.name, arcname="backup_metadata.json")
|
tar.add(temp_file.name, arcname="backup_metadata.json")
|
||||||
Path(temp_file.name).unlink() # Clean up temp file
|
Path(temp_file.name).unlink() # Clean up temp file
|
||||||
|
|
||||||
# Add installation directory contents (excluding backups and local dirs)
|
# Add installation directory contents (excluding backups and local dirs)
|
||||||
files_added = 0
|
files_added = 0
|
||||||
for item in args.install_dir.rglob("*"):
|
for item in args.install_dir.rglob("*"):
|
||||||
@ -317,30 +323,30 @@ def create_backup(args: argparse.Namespace) -> bool:
|
|||||||
try:
|
try:
|
||||||
# Create relative path for archive
|
# Create relative path for archive
|
||||||
rel_path = item.relative_to(args.install_dir)
|
rel_path = item.relative_to(args.install_dir)
|
||||||
|
|
||||||
# Skip files in excluded directories
|
# Skip files in excluded directories
|
||||||
if rel_path.parts and rel_path.parts[0] in ["backups", "local"]:
|
if rel_path.parts and rel_path.parts[0] in ["backups", "local"]:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
tar.add(item, arcname=str(rel_path))
|
tar.add(item, arcname=str(rel_path))
|
||||||
files_added += 1
|
files_added += 1
|
||||||
|
|
||||||
if files_added % 10 == 0:
|
if files_added % 10 == 0:
|
||||||
logger.debug(f"Added {files_added} files to backup")
|
logger.debug(f"Added {files_added} files to backup")
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning(f"Could not add {item} to backup: {e}")
|
logger.warning(f"Could not add {item} to backup: {e}")
|
||||||
|
|
||||||
duration = time.time() - start_time
|
duration = time.time() - start_time
|
||||||
file_size = backup_file.stat().st_size
|
file_size = backup_file.stat().st_size
|
||||||
|
|
||||||
logger.success(f"Backup created successfully in {duration:.1f} seconds")
|
logger.success(f"Backup created successfully in {duration:.1f} seconds")
|
||||||
logger.info(f"Backup file: {backup_file}")
|
logger.info(f"Backup file: {backup_file}")
|
||||||
logger.info(f"Files archived: {files_added}")
|
logger.info(f"Files archived: {files_added}")
|
||||||
logger.info(f"Backup size: {format_size(file_size)}")
|
logger.info(f"Backup size: {format_size(file_size)}")
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.exception(f"Failed to create backup: {e}")
|
logger.exception(f"Failed to create backup: {e}")
|
||||||
return False
|
return False
|
||||||
@ -349,20 +355,20 @@ def create_backup(args: argparse.Namespace) -> bool:
|
|||||||
def restore_backup(backup_path: Path, args: argparse.Namespace) -> bool:
|
def restore_backup(backup_path: Path, args: argparse.Namespace) -> bool:
|
||||||
"""Restore from a backup file"""
|
"""Restore from a backup file"""
|
||||||
logger = get_logger()
|
logger = get_logger()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if not backup_path.exists():
|
if not backup_path.exists():
|
||||||
logger.error(f"Backup file not found: {backup_path}")
|
logger.error(f"Backup file not found: {backup_path}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# Check backup file
|
# Check backup file
|
||||||
info = get_backup_info(backup_path)
|
info = get_backup_info(backup_path)
|
||||||
if "error" in info:
|
if "error" in info:
|
||||||
logger.error(f"Invalid backup file: {info['error']}")
|
logger.error(f"Invalid backup file: {info['error']}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
logger.info(f"Restoring from backup: {backup_path}")
|
logger.info(f"Restoring from backup: {backup_path}")
|
||||||
|
|
||||||
# Determine compression
|
# Determine compression
|
||||||
if backup_path.suffix == ".gz":
|
if backup_path.suffix == ".gz":
|
||||||
mode = "r:gz"
|
mode = "r:gz"
|
||||||
@ -370,47 +376,47 @@ def restore_backup(backup_path: Path, args: argparse.Namespace) -> bool:
|
|||||||
mode = "r:bz2"
|
mode = "r:bz2"
|
||||||
else:
|
else:
|
||||||
mode = "r"
|
mode = "r"
|
||||||
|
|
||||||
# Create backup of current installation if it exists
|
# Create backup of current installation if it exists
|
||||||
if check_installation_exists(args.install_dir) and not args.dry_run:
|
if check_installation_exists(args.install_dir) and not args.dry_run:
|
||||||
logger.info("Creating backup of current installation before restore")
|
logger.info("Creating backup of current installation before restore")
|
||||||
# This would call create_backup internally
|
# This would call create_backup internally
|
||||||
|
|
||||||
# Extract backup
|
# Extract backup
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
files_restored = 0
|
files_restored = 0
|
||||||
|
|
||||||
with tarfile.open(backup_path, mode) as tar:
|
with tarfile.open(backup_path, mode) as tar:
|
||||||
# Extract all files except metadata
|
# Extract all files except metadata
|
||||||
for member in tar.getmembers():
|
for member in tar.getmembers():
|
||||||
if member.name == "backup_metadata.json":
|
if member.name == "backup_metadata.json":
|
||||||
continue
|
continue
|
||||||
|
|
||||||
try:
|
try:
|
||||||
target_path = args.install_dir / member.name
|
target_path = args.install_dir / member.name
|
||||||
|
|
||||||
# Check if file exists and overwrite flag
|
# Check if file exists and overwrite flag
|
||||||
if target_path.exists() and not args.overwrite:
|
if target_path.exists() and not args.overwrite:
|
||||||
logger.warning(f"Skipping existing file: {target_path}")
|
logger.warning(f"Skipping existing file: {target_path}")
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Extract file
|
# Extract file
|
||||||
tar.extract(member, args.install_dir)
|
tar.extract(member, args.install_dir)
|
||||||
files_restored += 1
|
files_restored += 1
|
||||||
|
|
||||||
if files_restored % 10 == 0:
|
if files_restored % 10 == 0:
|
||||||
logger.debug(f"Restored {files_restored} files")
|
logger.debug(f"Restored {files_restored} files")
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning(f"Could not restore {member.name}: {e}")
|
logger.warning(f"Could not restore {member.name}: {e}")
|
||||||
|
|
||||||
duration = time.time() - start_time
|
duration = time.time() - start_time
|
||||||
|
|
||||||
logger.success(f"Restore completed successfully in {duration:.1f} seconds")
|
logger.success(f"Restore completed successfully in {duration:.1f} seconds")
|
||||||
logger.info(f"Files restored: {files_restored}")
|
logger.info(f"Files restored: {files_restored}")
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.exception(f"Failed to restore backup: {e}")
|
logger.exception(f"Failed to restore backup: {e}")
|
||||||
return False
|
return False
|
||||||
@ -421,69 +427,73 @@ def interactive_restore_selection(backups: List[Dict[str, Any]]) -> Optional[Pat
|
|||||||
if not backups:
|
if not backups:
|
||||||
print(f"{Colors.YELLOW}No backups available for restore{Colors.RESET}")
|
print(f"{Colors.YELLOW}No backups available for restore{Colors.RESET}")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
print(f"\n{Colors.CYAN}Select Backup to Restore:{Colors.RESET}")
|
print(f"\n{Colors.CYAN}Select Backup to Restore:{Colors.RESET}")
|
||||||
|
|
||||||
# Create menu options
|
# Create menu options
|
||||||
backup_options = []
|
backup_options = []
|
||||||
for backup in backups:
|
for backup in backups:
|
||||||
name = backup["path"].name
|
name = backup["path"].name
|
||||||
size = format_size(backup["size"]) if backup["size"] > 0 else "unknown"
|
size = format_size(backup["size"]) if backup["size"] > 0 else "unknown"
|
||||||
created = backup["created"].strftime("%Y-%m-%d %H:%M") if backup["created"] else "unknown"
|
created = (
|
||||||
|
backup["created"].strftime("%Y-%m-%d %H:%M")
|
||||||
|
if backup["created"]
|
||||||
|
else "unknown"
|
||||||
|
)
|
||||||
backup_options.append(f"{name} ({size}, {created})")
|
backup_options.append(f"{name} ({size}, {created})")
|
||||||
|
|
||||||
menu = Menu("Select backup:", backup_options)
|
menu = Menu("Select backup:", backup_options)
|
||||||
choice = menu.display()
|
choice = menu.display()
|
||||||
|
|
||||||
if choice == -1 or choice >= len(backups):
|
if choice == -1 or choice >= len(backups):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
return backups[choice]["path"]
|
return backups[choice]["path"]
|
||||||
|
|
||||||
|
|
||||||
def cleanup_old_backups(backup_dir: Path, args: argparse.Namespace) -> bool:
|
def cleanup_old_backups(backup_dir: Path, args: argparse.Namespace) -> bool:
|
||||||
"""Clean up old backup files"""
|
"""Clean up old backup files"""
|
||||||
logger = get_logger()
|
logger = get_logger()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
backups = list_backups(backup_dir)
|
backups = list_backups(backup_dir)
|
||||||
if not backups:
|
if not backups:
|
||||||
logger.info("No backups found to clean up")
|
logger.info("No backups found to clean up")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
to_remove = []
|
to_remove = []
|
||||||
|
|
||||||
# Remove by age
|
# Remove by age
|
||||||
if args.older_than:
|
if args.older_than:
|
||||||
cutoff_date = datetime.now() - timedelta(days=args.older_than)
|
cutoff_date = datetime.now() - timedelta(days=args.older_than)
|
||||||
for backup in backups:
|
for backup in backups:
|
||||||
if backup["created"] and backup["created"] < cutoff_date:
|
if backup["created"] and backup["created"] < cutoff_date:
|
||||||
to_remove.append(backup)
|
to_remove.append(backup)
|
||||||
|
|
||||||
# Keep only N most recent
|
# Keep only N most recent
|
||||||
if args.keep and len(backups) > args.keep:
|
if args.keep and len(backups) > args.keep:
|
||||||
# Sort by date and take oldest ones to remove
|
# Sort by date and take oldest ones to remove
|
||||||
backups.sort(key=lambda x: x.get("created", datetime.min), reverse=True)
|
backups.sort(key=lambda x: x.get("created", datetime.min), reverse=True)
|
||||||
to_remove.extend(backups[args.keep:])
|
to_remove.extend(backups[args.keep :])
|
||||||
|
|
||||||
# Remove duplicates
|
# Remove duplicates
|
||||||
to_remove = list({backup["path"]: backup for backup in to_remove}.values())
|
to_remove = list({backup["path"]: backup for backup in to_remove}.values())
|
||||||
|
|
||||||
if not to_remove:
|
if not to_remove:
|
||||||
logger.info("No backups need to be cleaned up")
|
logger.info("No backups need to be cleaned up")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
logger.info(f"Cleaning up {len(to_remove)} old backups")
|
logger.info(f"Cleaning up {len(to_remove)} old backups")
|
||||||
|
|
||||||
for backup in to_remove:
|
for backup in to_remove:
|
||||||
try:
|
try:
|
||||||
backup["path"].unlink()
|
backup["path"].unlink()
|
||||||
logger.info(f"Removed backup: {backup['path'].name}")
|
logger.info(f"Removed backup: {backup['path'].name}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning(f"Could not remove {backup['path'].name}: {e}")
|
logger.warning(f"Could not remove {backup['path'].name}: {e}")
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.exception(f"Failed to cleanup backups: {e}")
|
logger.exception(f"Failed to cleanup backups: {e}")
|
||||||
return False
|
return False
|
||||||
@ -503,7 +513,7 @@ def run(args: argparse.Namespace) -> int:
|
|||||||
print(f" Expected prefix: {expected_home}")
|
print(f" Expected prefix: {expected_home}")
|
||||||
print(f" Provided path: {actual_dir}")
|
print(f" Provided path: {actual_dir}")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Validate global arguments
|
# Validate global arguments
|
||||||
success, errors = operation.validate_global_args(args)
|
success, errors = operation.validate_global_args(args)
|
||||||
@ -511,26 +521,27 @@ def run(args: argparse.Namespace) -> int:
|
|||||||
for error in errors:
|
for error in errors:
|
||||||
logger.error(error)
|
logger.error(error)
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
# Display header
|
# Display header
|
||||||
if not args.quiet:
|
if not args.quiet:
|
||||||
from setup.cli.base import __version__
|
from setup.cli.base import __version__
|
||||||
|
|
||||||
display_header(
|
display_header(
|
||||||
f"SuperClaude Backup v{__version__}",
|
f"SuperClaude Backup v{__version__}",
|
||||||
"Backup and restore SuperClaude installations"
|
"Backup and restore SuperClaude installations",
|
||||||
)
|
)
|
||||||
|
|
||||||
backup_dir = get_backup_directory(args)
|
backup_dir = get_backup_directory(args)
|
||||||
|
|
||||||
# Handle different backup operations
|
# Handle different backup operations
|
||||||
if args.create:
|
if args.create:
|
||||||
success = create_backup(args)
|
success = create_backup(args)
|
||||||
|
|
||||||
elif args.list:
|
elif args.list:
|
||||||
backups = list_backups(backup_dir)
|
backups = list_backups(backup_dir)
|
||||||
display_backup_list(backups)
|
display_backup_list(backups)
|
||||||
success = True
|
success = True
|
||||||
|
|
||||||
elif args.restore:
|
elif args.restore:
|
||||||
if args.restore == "interactive":
|
if args.restore == "interactive":
|
||||||
# Interactive restore
|
# Interactive restore
|
||||||
@ -544,14 +555,14 @@ def run(args: argparse.Namespace) -> int:
|
|||||||
backup_path = Path(args.restore)
|
backup_path = Path(args.restore)
|
||||||
if not backup_path.is_absolute():
|
if not backup_path.is_absolute():
|
||||||
backup_path = backup_dir / backup_path
|
backup_path = backup_dir / backup_path
|
||||||
|
|
||||||
success = restore_backup(backup_path, args)
|
success = restore_backup(backup_path, args)
|
||||||
|
|
||||||
elif args.info:
|
elif args.info:
|
||||||
backup_path = Path(args.info)
|
backup_path = Path(args.info)
|
||||||
if not backup_path.is_absolute():
|
if not backup_path.is_absolute():
|
||||||
backup_path = backup_dir / backup_path
|
backup_path = backup_dir / backup_path
|
||||||
|
|
||||||
info = get_backup_info(backup_path)
|
info = get_backup_info(backup_path)
|
||||||
if info["exists"]:
|
if info["exists"]:
|
||||||
print(f"\n{Colors.CYAN}Backup Information:{Colors.RESET}")
|
print(f"\n{Colors.CYAN}Backup Information:{Colors.RESET}")
|
||||||
@ -559,10 +570,12 @@ def run(args: argparse.Namespace) -> int:
|
|||||||
print(f"Size: {format_size(info['size'])}")
|
print(f"Size: {format_size(info['size'])}")
|
||||||
print(f"Created: {info['created']}")
|
print(f"Created: {info['created']}")
|
||||||
print(f"Files: {info.get('files', 'unknown')}")
|
print(f"Files: {info.get('files', 'unknown')}")
|
||||||
|
|
||||||
if info["metadata"]:
|
if info["metadata"]:
|
||||||
metadata = info["metadata"]
|
metadata = info["metadata"]
|
||||||
print(f"Framework Version: {metadata.get('framework_version', 'unknown')}")
|
print(
|
||||||
|
f"Framework Version: {metadata.get('framework_version', 'unknown')}"
|
||||||
|
)
|
||||||
if metadata.get("components"):
|
if metadata.get("components"):
|
||||||
print("Components:")
|
print("Components:")
|
||||||
for comp, ver in metadata["components"].items():
|
for comp, ver in metadata["components"].items():
|
||||||
@ -571,14 +584,14 @@ def run(args: argparse.Namespace) -> int:
|
|||||||
logger.error(f"Backup file not found: {backup_path}")
|
logger.error(f"Backup file not found: {backup_path}")
|
||||||
success = False
|
success = False
|
||||||
success = True
|
success = True
|
||||||
|
|
||||||
elif args.cleanup:
|
elif args.cleanup:
|
||||||
success = cleanup_old_backups(backup_dir, args)
|
success = cleanup_old_backups(backup_dir, args)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
logger.error("No backup operation specified")
|
logger.error("No backup operation specified")
|
||||||
success = False
|
success = False
|
||||||
|
|
||||||
if success:
|
if success:
|
||||||
if not args.quiet and args.create:
|
if not args.quiet and args.create:
|
||||||
display_success("Backup operation completed successfully!")
|
display_success("Backup operation completed successfully!")
|
||||||
@ -588,7 +601,7 @@ def run(args: argparse.Namespace) -> int:
|
|||||||
else:
|
else:
|
||||||
display_error("Backup operation failed. Check logs for details.")
|
display_error("Backup operation failed. Check logs for details.")
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
print(f"\n{Colors.YELLOW}Backup operation cancelled by user{Colors.RESET}")
|
print(f"\n{Colors.YELLOW}Backup operation cancelled by user{Colors.RESET}")
|
||||||
return 130
|
return 130
|
||||||
|
|||||||
@ -15,8 +15,17 @@ from ...core.registry import ComponentRegistry
|
|||||||
from ...services.config import ConfigService
|
from ...services.config import ConfigService
|
||||||
from ...core.validator import Validator
|
from ...core.validator import Validator
|
||||||
from ...utils.ui import (
|
from ...utils.ui import (
|
||||||
display_header, display_info, display_success, display_error,
|
display_header,
|
||||||
display_warning, Menu, confirm, ProgressBar, Colors, format_size, prompt_api_key
|
display_info,
|
||||||
|
display_success,
|
||||||
|
display_error,
|
||||||
|
display_warning,
|
||||||
|
Menu,
|
||||||
|
confirm,
|
||||||
|
ProgressBar,
|
||||||
|
Colors,
|
||||||
|
format_size,
|
||||||
|
prompt_api_key,
|
||||||
)
|
)
|
||||||
from ...utils.environment import setup_environment_variables
|
from ...utils.environment import setup_environment_variables
|
||||||
from ...utils.logger import get_logger
|
from ...utils.logger import get_logger
|
||||||
@ -26,7 +35,7 @@ from . import OperationBase
|
|||||||
|
|
||||||
class InstallOperation(OperationBase):
|
class InstallOperation(OperationBase):
|
||||||
"""Installation operation implementation"""
|
"""Installation operation implementation"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__("install")
|
super().__init__("install")
|
||||||
|
|
||||||
@ -34,7 +43,7 @@ class InstallOperation(OperationBase):
|
|||||||
def register_parser(subparsers, global_parser=None) -> argparse.ArgumentParser:
|
def register_parser(subparsers, global_parser=None) -> argparse.ArgumentParser:
|
||||||
"""Register installation CLI arguments"""
|
"""Register installation CLI arguments"""
|
||||||
parents = [global_parser] if global_parser else []
|
parents = [global_parser] if global_parser else []
|
||||||
|
|
||||||
parser = subparsers.add_parser(
|
parser = subparsers.add_parser(
|
||||||
"install",
|
"install",
|
||||||
help="Install SuperClaude framework components",
|
help="Install SuperClaude framework components",
|
||||||
@ -47,54 +56,51 @@ Examples:
|
|||||||
SuperClaude install --verbose --force # Verbose with force mode
|
SuperClaude install --verbose --force # Verbose with force mode
|
||||||
""",
|
""",
|
||||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||||
parents=parents
|
parents=parents,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Installation mode options
|
# Installation mode options
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--components",
|
"--components", type=str, nargs="+", help="Specific components to install"
|
||||||
type=str,
|
|
||||||
nargs="+",
|
|
||||||
help="Specific components to install"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Installation options
|
# Installation options
|
||||||
parser.add_argument(
|
parser.add_argument("--no-backup", action="store_true", help="Skip backup creation")
|
||||||
"--no-backup",
|
|
||||||
action="store_true",
|
|
||||||
help="Skip backup creation"
|
|
||||||
)
|
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--list-components",
|
"--list-components",
|
||||||
action="store_true",
|
action="store_true",
|
||||||
help="List available components and exit"
|
help="List available components and exit",
|
||||||
)
|
)
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--diagnose",
|
"--diagnose",
|
||||||
action="store_true",
|
action="store_true",
|
||||||
help="Run system diagnostics and show installation help"
|
help="Run system diagnostics and show installation help",
|
||||||
)
|
)
|
||||||
|
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
|
|
||||||
def validate_system_requirements(validator: Validator, component_names: List[str]) -> bool:
|
def validate_system_requirements(
|
||||||
|
validator: Validator, component_names: List[str]
|
||||||
|
) -> bool:
|
||||||
"""Validate system requirements"""
|
"""Validate system requirements"""
|
||||||
logger = get_logger()
|
logger = get_logger()
|
||||||
|
|
||||||
logger.info("Validating system requirements...")
|
logger.info("Validating system requirements...")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Load requirements configuration
|
# Load requirements configuration
|
||||||
config_manager = ConfigService(DATA_DIR)
|
config_manager = ConfigService(DATA_DIR)
|
||||||
requirements = config_manager.get_requirements_for_components(component_names)
|
requirements = config_manager.get_requirements_for_components(component_names)
|
||||||
|
|
||||||
# Validate requirements
|
# Validate requirements
|
||||||
success, errors = validator.validate_component_requirements(component_names, requirements)
|
success, errors = validator.validate_component_requirements(
|
||||||
|
component_names, requirements
|
||||||
|
)
|
||||||
|
|
||||||
if success:
|
if success:
|
||||||
logger.success("All system requirements met")
|
logger.success("All system requirements met")
|
||||||
return True
|
return True
|
||||||
@ -102,67 +108,79 @@ def validate_system_requirements(validator: Validator, component_names: List[str
|
|||||||
logger.error("System requirements not met:")
|
logger.error("System requirements not met:")
|
||||||
for error in errors:
|
for error in errors:
|
||||||
logger.error(f" - {error}")
|
logger.error(f" - {error}")
|
||||||
|
|
||||||
# Provide additional guidance
|
# Provide additional guidance
|
||||||
print(f"\n{Colors.CYAN}💡 Installation Help:{Colors.RESET}")
|
print(f"\n{Colors.CYAN}💡 Installation Help:{Colors.RESET}")
|
||||||
print(" Run 'SuperClaude install --diagnose' for detailed system diagnostics")
|
print(
|
||||||
|
" Run 'superclaude install --diagnose' for detailed system diagnostics"
|
||||||
|
)
|
||||||
print(" and step-by-step installation instructions.")
|
print(" and step-by-step installation instructions.")
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Could not validate system requirements: {e}")
|
logger.error(f"Could not validate system requirements: {e}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def get_components_to_install(args: argparse.Namespace, registry: ComponentRegistry, config_manager: ConfigService) -> Optional[List[str]]:
|
def get_components_to_install(
|
||||||
|
args: argparse.Namespace, registry: ComponentRegistry, config_manager: ConfigService
|
||||||
|
) -> Optional[List[str]]:
|
||||||
"""Determine which components to install"""
|
"""Determine which components to install"""
|
||||||
logger = get_logger()
|
logger = get_logger()
|
||||||
|
|
||||||
# Explicit components specified
|
# Explicit components specified
|
||||||
if args.components:
|
if args.components:
|
||||||
if 'all' in args.components:
|
if "all" in args.components:
|
||||||
components = ["core", "commands", "agents", "modes", "mcp", "mcp_docs"]
|
components = ["core", "commands", "agents", "modes", "mcp", "mcp_docs"]
|
||||||
else:
|
else:
|
||||||
components = args.components
|
components = args.components
|
||||||
|
|
||||||
# If mcp or mcp_docs is specified non-interactively, we should still ask which servers to install.
|
# If mcp or mcp_docs is specified non-interactively, we should still ask which servers to install.
|
||||||
if 'mcp' in components or 'mcp_docs' in components:
|
if "mcp" in components or "mcp_docs" in components:
|
||||||
selected_servers = select_mcp_servers(registry)
|
selected_servers = select_mcp_servers(registry)
|
||||||
if not hasattr(config_manager, '_installation_context'):
|
if not hasattr(config_manager, "_installation_context"):
|
||||||
config_manager._installation_context = {}
|
config_manager._installation_context = {}
|
||||||
config_manager._installation_context["selected_mcp_servers"] = selected_servers
|
config_manager._installation_context["selected_mcp_servers"] = (
|
||||||
|
selected_servers
|
||||||
|
)
|
||||||
|
|
||||||
# If the user selected some servers, ensure both mcp and mcp_docs are included
|
# If the user selected some servers, ensure both mcp and mcp_docs are included
|
||||||
if selected_servers:
|
if selected_servers:
|
||||||
if 'mcp' not in components:
|
if "mcp" not in components:
|
||||||
components.append('mcp')
|
components.append("mcp")
|
||||||
logger.debug(f"Auto-added 'mcp' component for selected servers: {selected_servers}")
|
logger.debug(
|
||||||
if 'mcp_docs' not in components:
|
f"Auto-added 'mcp' component for selected servers: {selected_servers}"
|
||||||
components.append('mcp_docs')
|
)
|
||||||
logger.debug(f"Auto-added 'mcp_docs' component for selected servers: {selected_servers}")
|
if "mcp_docs" not in components:
|
||||||
|
components.append("mcp_docs")
|
||||||
|
logger.debug(
|
||||||
|
f"Auto-added 'mcp_docs' component for selected servers: {selected_servers}"
|
||||||
|
)
|
||||||
|
|
||||||
logger.info(f"Final components to install: {components}")
|
logger.info(f"Final components to install: {components}")
|
||||||
|
|
||||||
# If mcp_docs was explicitly requested but no servers selected, allow auto-detection
|
# If mcp_docs was explicitly requested but no servers selected, allow auto-detection
|
||||||
elif not selected_servers and 'mcp_docs' in components:
|
elif not selected_servers and "mcp_docs" in components:
|
||||||
logger.info("mcp_docs component will auto-detect existing MCP servers")
|
logger.info("mcp_docs component will auto-detect existing MCP servers")
|
||||||
logger.info("Documentation will be installed for any detected servers")
|
logger.info("Documentation will be installed for any detected servers")
|
||||||
|
|
||||||
return components
|
return components
|
||||||
|
|
||||||
# Interactive two-stage selection
|
# Interactive two-stage selection
|
||||||
return interactive_component_selection(registry, config_manager)
|
return interactive_component_selection(registry, config_manager)
|
||||||
|
|
||||||
|
|
||||||
def collect_api_keys_for_servers(selected_servers: List[str], mcp_instance) -> Dict[str, str]:
|
def collect_api_keys_for_servers(
|
||||||
|
selected_servers: List[str], mcp_instance
|
||||||
|
) -> Dict[str, str]:
|
||||||
"""
|
"""
|
||||||
Collect API keys for servers that require them
|
Collect API keys for servers that require them
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
selected_servers: List of selected server keys
|
selected_servers: List of selected server keys
|
||||||
mcp_instance: MCP component instance
|
mcp_instance: MCP component instance
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Dictionary of environment variable names to API key values
|
Dictionary of environment variable names to API key values
|
||||||
"""
|
"""
|
||||||
@ -170,132 +188,164 @@ def collect_api_keys_for_servers(selected_servers: List[str], mcp_instance) -> D
|
|||||||
servers_needing_keys = [
|
servers_needing_keys = [
|
||||||
(server_key, mcp_instance.mcp_servers[server_key])
|
(server_key, mcp_instance.mcp_servers[server_key])
|
||||||
for server_key in selected_servers
|
for server_key in selected_servers
|
||||||
if server_key in mcp_instance.mcp_servers and
|
if server_key in mcp_instance.mcp_servers
|
||||||
mcp_instance.mcp_servers[server_key].get("requires_api_key", False)
|
and mcp_instance.mcp_servers[server_key].get("requires_api_key", False)
|
||||||
]
|
]
|
||||||
|
|
||||||
if not servers_needing_keys:
|
if not servers_needing_keys:
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
# Display API key configuration header
|
# Display API key configuration header
|
||||||
print(f"\n{Colors.CYAN}{Colors.BRIGHT}=== API Key Configuration ==={Colors.RESET}")
|
print(f"\n{Colors.CYAN}{Colors.BRIGHT}=== API Key Configuration ==={Colors.RESET}")
|
||||||
print(f"{Colors.YELLOW}The following servers require API keys for full functionality:{Colors.RESET}\n")
|
print(
|
||||||
|
f"{Colors.YELLOW}The following servers require API keys for full functionality:{Colors.RESET}\n"
|
||||||
|
)
|
||||||
|
|
||||||
collected_keys = {}
|
collected_keys = {}
|
||||||
for server_key, server_info in servers_needing_keys:
|
for server_key, server_info in servers_needing_keys:
|
||||||
api_key_env = server_info.get("api_key_env")
|
api_key_env = server_info.get("api_key_env")
|
||||||
service_name = server_info["name"]
|
service_name = server_info["name"]
|
||||||
|
|
||||||
if api_key_env:
|
if api_key_env:
|
||||||
key = prompt_api_key(service_name, api_key_env)
|
key = prompt_api_key(service_name, api_key_env)
|
||||||
if key:
|
if key:
|
||||||
collected_keys[api_key_env] = key
|
collected_keys[api_key_env] = key
|
||||||
|
|
||||||
return collected_keys
|
return collected_keys
|
||||||
|
|
||||||
|
|
||||||
def select_mcp_servers(registry: ComponentRegistry) -> List[str]:
|
def select_mcp_servers(registry: ComponentRegistry) -> List[str]:
|
||||||
"""Stage 1: MCP Server Selection with API Key Collection"""
|
"""Stage 1: MCP Server Selection with API Key Collection"""
|
||||||
logger = get_logger()
|
logger = get_logger()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Get MCP component to access server list
|
# Get MCP component to access server list
|
||||||
mcp_instance = registry.get_component_instance("mcp", get_home_directory() / ".claude")
|
mcp_instance = registry.get_component_instance(
|
||||||
if not mcp_instance or not hasattr(mcp_instance, 'mcp_servers'):
|
"mcp", get_home_directory() / ".claude"
|
||||||
|
)
|
||||||
|
if not mcp_instance or not hasattr(mcp_instance, "mcp_servers"):
|
||||||
logger.error("Could not access MCP server information")
|
logger.error("Could not access MCP server information")
|
||||||
return []
|
return []
|
||||||
|
|
||||||
# Create MCP server menu
|
# Create MCP server menu
|
||||||
mcp_servers = mcp_instance.mcp_servers
|
mcp_servers = mcp_instance.mcp_servers
|
||||||
server_options = []
|
server_options = []
|
||||||
|
|
||||||
for server_key, server_info in mcp_servers.items():
|
for server_key, server_info in mcp_servers.items():
|
||||||
description = server_info["description"]
|
description = server_info["description"]
|
||||||
api_key_note = " (requires API key)" if server_info.get("requires_api_key", False) else ""
|
api_key_note = (
|
||||||
|
" (requires API key)"
|
||||||
|
if server_info.get("requires_api_key", False)
|
||||||
|
else ""
|
||||||
|
)
|
||||||
server_options.append(f"{server_key} - {description}{api_key_note}")
|
server_options.append(f"{server_key} - {description}{api_key_note}")
|
||||||
|
|
||||||
print(f"\n{Colors.CYAN}{Colors.BRIGHT}{'='*51}{Colors.RESET}")
|
print(f"\n{Colors.CYAN}{Colors.BRIGHT}{'='*51}{Colors.RESET}")
|
||||||
print(f"{Colors.CYAN}{Colors.BRIGHT}Stage 1: MCP Server Selection (Optional){Colors.RESET}")
|
print(
|
||||||
|
f"{Colors.CYAN}{Colors.BRIGHT}Stage 1: MCP Server Selection (Optional){Colors.RESET}"
|
||||||
|
)
|
||||||
print(f"{Colors.CYAN}{Colors.BRIGHT}{'='*51}{Colors.RESET}")
|
print(f"{Colors.CYAN}{Colors.BRIGHT}{'='*51}{Colors.RESET}")
|
||||||
print(f"\n{Colors.BLUE}MCP servers extend Claude Code with specialized capabilities.{Colors.RESET}")
|
print(
|
||||||
print(f"{Colors.BLUE}Select servers to configure (you can always add more later):{Colors.RESET}")
|
f"\n{Colors.BLUE}MCP servers extend Claude Code with specialized capabilities.{Colors.RESET}"
|
||||||
|
)
|
||||||
|
print(
|
||||||
|
f"{Colors.BLUE}Select servers to configure (you can always add more later):{Colors.RESET}"
|
||||||
|
)
|
||||||
|
|
||||||
# Add option to skip MCP
|
# Add option to skip MCP
|
||||||
server_options.append("Skip MCP Server installation")
|
server_options.append("Skip MCP Server installation")
|
||||||
|
|
||||||
menu = Menu("Select MCP servers to configure:", server_options, multi_select=True)
|
menu = Menu(
|
||||||
|
"Select MCP servers to configure:", server_options, multi_select=True
|
||||||
|
)
|
||||||
selections = menu.display()
|
selections = menu.display()
|
||||||
|
|
||||||
if not selections:
|
if not selections:
|
||||||
logger.info("No MCP servers selected")
|
logger.info("No MCP servers selected")
|
||||||
return []
|
return []
|
||||||
|
|
||||||
# Filter out the "skip" option and return server keys
|
# Filter out the "skip" option and return server keys
|
||||||
server_keys = list(mcp_servers.keys())
|
server_keys = list(mcp_servers.keys())
|
||||||
selected_servers = []
|
selected_servers = []
|
||||||
|
|
||||||
for i in selections:
|
for i in selections:
|
||||||
if i < len(server_keys): # Not the "skip" option
|
if i < len(server_keys): # Not the "skip" option
|
||||||
selected_servers.append(server_keys[i])
|
selected_servers.append(server_keys[i])
|
||||||
|
|
||||||
if selected_servers:
|
if selected_servers:
|
||||||
logger.info(f"Selected MCP servers: {', '.join(selected_servers)}")
|
logger.info(f"Selected MCP servers: {', '.join(selected_servers)}")
|
||||||
|
|
||||||
# NEW: Collect API keys for selected servers
|
# NEW: Collect API keys for selected servers
|
||||||
collected_keys = collect_api_keys_for_servers(selected_servers, mcp_instance)
|
collected_keys = collect_api_keys_for_servers(
|
||||||
|
selected_servers, mcp_instance
|
||||||
|
)
|
||||||
|
|
||||||
# Set up environment variables
|
# Set up environment variables
|
||||||
if collected_keys:
|
if collected_keys:
|
||||||
setup_environment_variables(collected_keys)
|
setup_environment_variables(collected_keys)
|
||||||
|
|
||||||
# Store keys for MCP component to use during installation
|
# Store keys for MCP component to use during installation
|
||||||
mcp_instance.collected_api_keys = collected_keys
|
mcp_instance.collected_api_keys = collected_keys
|
||||||
else:
|
else:
|
||||||
logger.info("No MCP servers selected")
|
logger.info("No MCP servers selected")
|
||||||
|
|
||||||
return selected_servers
|
return selected_servers
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Error in MCP server selection: {e}")
|
logger.error(f"Error in MCP server selection: {e}")
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
|
||||||
def select_framework_components(registry: ComponentRegistry, config_manager: ConfigService, selected_mcp_servers: List[str]) -> List[str]:
|
def select_framework_components(
|
||||||
|
registry: ComponentRegistry,
|
||||||
|
config_manager: ConfigService,
|
||||||
|
selected_mcp_servers: List[str],
|
||||||
|
) -> List[str]:
|
||||||
"""Stage 2: Framework Component Selection"""
|
"""Stage 2: Framework Component Selection"""
|
||||||
logger = get_logger()
|
logger = get_logger()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Framework components (excluding MCP-related ones)
|
# Framework components (excluding MCP-related ones)
|
||||||
framework_components = ["core", "modes", "commands", "agents"]
|
framework_components = ["core", "modes", "commands", "agents"]
|
||||||
|
|
||||||
# Create component menu
|
# Create component menu
|
||||||
component_options = []
|
component_options = []
|
||||||
component_info = {}
|
component_info = {}
|
||||||
|
|
||||||
for component_name in framework_components:
|
for component_name in framework_components:
|
||||||
metadata = registry.get_component_metadata(component_name)
|
metadata = registry.get_component_metadata(component_name)
|
||||||
if metadata:
|
if metadata:
|
||||||
description = metadata.get("description", "No description")
|
description = metadata.get("description", "No description")
|
||||||
component_options.append(f"{component_name} - {description}")
|
component_options.append(f"{component_name} - {description}")
|
||||||
component_info[component_name] = metadata
|
component_info[component_name] = metadata
|
||||||
|
|
||||||
# Add MCP documentation option
|
# Add MCP documentation option
|
||||||
if selected_mcp_servers:
|
if selected_mcp_servers:
|
||||||
mcp_docs_desc = f"MCP documentation for {', '.join(selected_mcp_servers)} (auto-selected)"
|
mcp_docs_desc = f"MCP documentation for {', '.join(selected_mcp_servers)} (auto-selected)"
|
||||||
component_options.append(f"mcp_docs - {mcp_docs_desc}")
|
component_options.append(f"mcp_docs - {mcp_docs_desc}")
|
||||||
auto_selected_mcp_docs = True
|
auto_selected_mcp_docs = True
|
||||||
else:
|
else:
|
||||||
component_options.append("mcp_docs - MCP server documentation (none selected)")
|
component_options.append(
|
||||||
|
"mcp_docs - MCP server documentation (none selected)"
|
||||||
|
)
|
||||||
auto_selected_mcp_docs = False
|
auto_selected_mcp_docs = False
|
||||||
|
|
||||||
print(f"\n{Colors.CYAN}{Colors.BRIGHT}{'='*51}{Colors.RESET}")
|
print(f"\n{Colors.CYAN}{Colors.BRIGHT}{'='*51}{Colors.RESET}")
|
||||||
print(f"{Colors.CYAN}{Colors.BRIGHT}Stage 2: Framework Component Selection{Colors.RESET}")
|
print(
|
||||||
|
f"{Colors.CYAN}{Colors.BRIGHT}Stage 2: Framework Component Selection{Colors.RESET}"
|
||||||
|
)
|
||||||
print(f"{Colors.CYAN}{Colors.BRIGHT}{'='*51}{Colors.RESET}")
|
print(f"{Colors.CYAN}{Colors.BRIGHT}{'='*51}{Colors.RESET}")
|
||||||
print(f"\n{Colors.BLUE}Select SuperClaude framework components to install:{Colors.RESET}")
|
print(
|
||||||
|
f"\n{Colors.BLUE}Select SuperClaude framework components to install:{Colors.RESET}"
|
||||||
menu = Menu("Select components (Core is recommended):", component_options, multi_select=True)
|
)
|
||||||
|
|
||||||
|
menu = Menu(
|
||||||
|
"Select components (Core is recommended):",
|
||||||
|
component_options,
|
||||||
|
multi_select=True,
|
||||||
|
)
|
||||||
selections = menu.display()
|
selections = menu.display()
|
||||||
|
|
||||||
if not selections:
|
if not selections:
|
||||||
# Default to core if nothing selected
|
# Default to core if nothing selected
|
||||||
logger.info("No components selected, defaulting to core")
|
logger.info("No components selected, defaulting to core")
|
||||||
@ -303,11 +353,11 @@ def select_framework_components(registry: ComponentRegistry, config_manager: Con
|
|||||||
else:
|
else:
|
||||||
selected_components = []
|
selected_components = []
|
||||||
all_components = framework_components + ["mcp_docs"]
|
all_components = framework_components + ["mcp_docs"]
|
||||||
|
|
||||||
for i in selections:
|
for i in selections:
|
||||||
if i < len(all_components):
|
if i < len(all_components):
|
||||||
selected_components.append(all_components[i])
|
selected_components.append(all_components[i])
|
||||||
|
|
||||||
# Auto-select MCP docs if not explicitly deselected and we have MCP servers
|
# Auto-select MCP docs if not explicitly deselected and we have MCP servers
|
||||||
if auto_selected_mcp_docs and "mcp_docs" not in selected_components:
|
if auto_selected_mcp_docs and "mcp_docs" not in selected_components:
|
||||||
# Check if user explicitly deselected it
|
# Check if user explicitly deselected it
|
||||||
@ -316,82 +366,96 @@ def select_framework_components(registry: ComponentRegistry, config_manager: Con
|
|||||||
# User didn't select it, but we auto-select it
|
# User didn't select it, but we auto-select it
|
||||||
selected_components.append("mcp_docs")
|
selected_components.append("mcp_docs")
|
||||||
logger.info("Auto-selected MCP documentation for configured servers")
|
logger.info("Auto-selected MCP documentation for configured servers")
|
||||||
|
|
||||||
# Always include MCP component if servers were selected
|
# Always include MCP component if servers were selected
|
||||||
if selected_mcp_servers and "mcp" not in selected_components:
|
if selected_mcp_servers and "mcp" not in selected_components:
|
||||||
selected_components.append("mcp")
|
selected_components.append("mcp")
|
||||||
|
|
||||||
logger.info(f"Selected framework components: {', '.join(selected_components)}")
|
logger.info(f"Selected framework components: {', '.join(selected_components)}")
|
||||||
return selected_components
|
return selected_components
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Error in framework component selection: {e}")
|
logger.error(f"Error in framework component selection: {e}")
|
||||||
return ["core"] # Fallback to core
|
return ["core"] # Fallback to core
|
||||||
|
|
||||||
|
|
||||||
def interactive_component_selection(registry: ComponentRegistry, config_manager: ConfigService) -> Optional[List[str]]:
|
def interactive_component_selection(
|
||||||
|
registry: ComponentRegistry, config_manager: ConfigService
|
||||||
|
) -> Optional[List[str]]:
|
||||||
"""Two-stage interactive component selection"""
|
"""Two-stage interactive component selection"""
|
||||||
logger = get_logger()
|
logger = get_logger()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
print(f"\n{Colors.CYAN}SuperClaude Interactive Installation{Colors.RESET}")
|
print(f"\n{Colors.CYAN}SuperClaude Interactive Installation{Colors.RESET}")
|
||||||
print(f"{Colors.BLUE}Select components to install using the two-stage process:{Colors.RESET}")
|
print(
|
||||||
|
f"{Colors.BLUE}Select components to install using the two-stage process:{Colors.RESET}"
|
||||||
|
)
|
||||||
|
|
||||||
# Stage 1: MCP Server Selection
|
# Stage 1: MCP Server Selection
|
||||||
selected_mcp_servers = select_mcp_servers(registry)
|
selected_mcp_servers = select_mcp_servers(registry)
|
||||||
|
|
||||||
# Stage 2: Framework Component Selection
|
# Stage 2: Framework Component Selection
|
||||||
selected_components = select_framework_components(registry, config_manager, selected_mcp_servers)
|
selected_components = select_framework_components(
|
||||||
|
registry, config_manager, selected_mcp_servers
|
||||||
|
)
|
||||||
|
|
||||||
# Store selected MCP servers for components to use
|
# Store selected MCP servers for components to use
|
||||||
if not hasattr(config_manager, '_installation_context'):
|
if not hasattr(config_manager, "_installation_context"):
|
||||||
config_manager._installation_context = {}
|
config_manager._installation_context = {}
|
||||||
config_manager._installation_context["selected_mcp_servers"] = selected_mcp_servers
|
config_manager._installation_context["selected_mcp_servers"] = (
|
||||||
|
selected_mcp_servers
|
||||||
|
)
|
||||||
|
|
||||||
return selected_components
|
return selected_components
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Error in component selection: {e}")
|
logger.error(f"Error in component selection: {e}")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def display_installation_plan(components: List[str], registry: ComponentRegistry, install_dir: Path) -> None:
|
def display_installation_plan(
|
||||||
|
components: List[str], registry: ComponentRegistry, install_dir: Path
|
||||||
|
) -> None:
|
||||||
"""Display installation plan"""
|
"""Display installation plan"""
|
||||||
logger = get_logger()
|
logger = get_logger()
|
||||||
|
|
||||||
print(f"\n{Colors.CYAN}{Colors.BRIGHT}Installation Plan{Colors.RESET}")
|
print(f"\n{Colors.CYAN}{Colors.BRIGHT}Installation Plan{Colors.RESET}")
|
||||||
print("=" * 50)
|
print("=" * 50)
|
||||||
|
|
||||||
# Resolve dependencies
|
# Resolve dependencies
|
||||||
try:
|
try:
|
||||||
ordered_components = registry.resolve_dependencies(components)
|
ordered_components = registry.resolve_dependencies(components)
|
||||||
|
|
||||||
print(f"{Colors.BLUE}Installation Directory:{Colors.RESET} {install_dir}")
|
print(f"{Colors.BLUE}Installation Directory:{Colors.RESET} {install_dir}")
|
||||||
print(f"{Colors.BLUE}Components to install:{Colors.RESET}")
|
print(f"{Colors.BLUE}Components to install:{Colors.RESET}")
|
||||||
|
|
||||||
total_size = 0
|
total_size = 0
|
||||||
for i, component_name in enumerate(ordered_components, 1):
|
for i, component_name in enumerate(ordered_components, 1):
|
||||||
metadata = registry.get_component_metadata(component_name)
|
metadata = registry.get_component_metadata(component_name)
|
||||||
if metadata:
|
if metadata:
|
||||||
description = metadata.get("description", "No description")
|
description = metadata.get("description", "No description")
|
||||||
print(f" {i}. {component_name} - {description}")
|
print(f" {i}. {component_name} - {description}")
|
||||||
|
|
||||||
# Get size estimate if component supports it
|
# Get size estimate if component supports it
|
||||||
try:
|
try:
|
||||||
instance = registry.get_component_instance(component_name, install_dir)
|
instance = registry.get_component_instance(
|
||||||
if instance and hasattr(instance, 'get_size_estimate'):
|
component_name, install_dir
|
||||||
|
)
|
||||||
|
if instance and hasattr(instance, "get_size_estimate"):
|
||||||
size = instance.get_size_estimate()
|
size = instance.get_size_estimate()
|
||||||
total_size += size
|
total_size += size
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
print(f" {i}. {component_name} - Unknown component")
|
print(f" {i}. {component_name} - Unknown component")
|
||||||
|
|
||||||
if total_size > 0:
|
if total_size > 0:
|
||||||
print(f"\n{Colors.BLUE}Estimated size:{Colors.RESET} {format_size(total_size)}")
|
print(
|
||||||
|
f"\n{Colors.BLUE}Estimated size:{Colors.RESET} {format_size(total_size)}"
|
||||||
|
)
|
||||||
|
|
||||||
print()
|
print()
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Could not resolve dependencies: {e}")
|
logger.error(f"Could not resolve dependencies: {e}")
|
||||||
raise
|
raise
|
||||||
@ -400,101 +464,113 @@ def display_installation_plan(components: List[str], registry: ComponentRegistry
|
|||||||
def run_system_diagnostics(validator: Validator) -> None:
|
def run_system_diagnostics(validator: Validator) -> None:
|
||||||
"""Run comprehensive system diagnostics"""
|
"""Run comprehensive system diagnostics"""
|
||||||
logger = get_logger()
|
logger = get_logger()
|
||||||
|
|
||||||
print(f"\n{Colors.CYAN}{Colors.BRIGHT}SuperClaude System Diagnostics{Colors.RESET}")
|
print(f"\n{Colors.CYAN}{Colors.BRIGHT}SuperClaude System Diagnostics{Colors.RESET}")
|
||||||
print("=" * 50)
|
print("=" * 50)
|
||||||
|
|
||||||
# Run diagnostics
|
# Run diagnostics
|
||||||
diagnostics = validator.diagnose_system()
|
diagnostics = validator.diagnose_system()
|
||||||
|
|
||||||
# Display platform info
|
# Display platform info
|
||||||
print(f"{Colors.BLUE}Platform:{Colors.RESET} {diagnostics['platform']}")
|
print(f"{Colors.BLUE}Platform:{Colors.RESET} {diagnostics['platform']}")
|
||||||
|
|
||||||
# Display check results
|
# Display check results
|
||||||
print(f"\n{Colors.BLUE}System Checks:{Colors.RESET}")
|
print(f"\n{Colors.BLUE}System Checks:{Colors.RESET}")
|
||||||
all_passed = True
|
all_passed = True
|
||||||
|
|
||||||
for check_name, check_info in diagnostics['checks'].items():
|
for check_name, check_info in diagnostics["checks"].items():
|
||||||
status = check_info['status']
|
status = check_info["status"]
|
||||||
message = check_info['message']
|
message = check_info["message"]
|
||||||
|
|
||||||
if status == 'pass':
|
if status == "pass":
|
||||||
print(f" ✅ {check_name}: {message}")
|
print(f" ✅ {check_name}: {message}")
|
||||||
else:
|
else:
|
||||||
print(f" ❌ {check_name}: {message}")
|
print(f" ❌ {check_name}: {message}")
|
||||||
all_passed = False
|
all_passed = False
|
||||||
|
|
||||||
# Display issues and recommendations
|
# Display issues and recommendations
|
||||||
if diagnostics['issues']:
|
if diagnostics["issues"]:
|
||||||
print(f"\n{Colors.YELLOW}Issues Found:{Colors.RESET}")
|
print(f"\n{Colors.YELLOW}Issues Found:{Colors.RESET}")
|
||||||
for issue in diagnostics['issues']:
|
for issue in diagnostics["issues"]:
|
||||||
print(f" ⚠️ {issue}")
|
print(f" ⚠️ {issue}")
|
||||||
|
|
||||||
print(f"\n{Colors.CYAN}Recommendations:{Colors.RESET}")
|
print(f"\n{Colors.CYAN}Recommendations:{Colors.RESET}")
|
||||||
for recommendation in diagnostics['recommendations']:
|
for recommendation in diagnostics["recommendations"]:
|
||||||
print(recommendation)
|
print(recommendation)
|
||||||
|
|
||||||
# Summary
|
# Summary
|
||||||
if all_passed:
|
if all_passed:
|
||||||
print(f"\n{Colors.GREEN}✅ All system checks passed! Your system is ready for SuperClaude.{Colors.RESET}")
|
print(
|
||||||
|
f"\n{Colors.GREEN}✅ All system checks passed! Your system is ready for superclaude.{Colors.RESET}"
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
print(f"\n{Colors.YELLOW}⚠️ Some issues found. Please address the recommendations above.{Colors.RESET}")
|
print(
|
||||||
|
f"\n{Colors.YELLOW}⚠️ Some issues found. Please address the recommendations above.{Colors.RESET}"
|
||||||
|
)
|
||||||
|
|
||||||
print(f"\n{Colors.BLUE}Next steps:{Colors.RESET}")
|
print(f"\n{Colors.BLUE}Next steps:{Colors.RESET}")
|
||||||
if all_passed:
|
if all_passed:
|
||||||
print(" 1. Run 'SuperClaude install' to proceed with installation")
|
print(" 1. Run 'superclaude install' to proceed with installation")
|
||||||
print(" 2. Choose your preferred installation mode (quick, minimal, or custom)")
|
print(
|
||||||
|
" 2. Choose your preferred installation mode (quick, minimal, or custom)"
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
print(" 1. Install missing dependencies using the commands above")
|
print(" 1. Install missing dependencies using the commands above")
|
||||||
print(" 2. Restart your terminal after installing tools")
|
print(" 2. Restart your terminal after installing tools")
|
||||||
print(" 3. Run 'SuperClaude install --diagnose' again to verify")
|
print(" 3. Run 'superclaude install --diagnose' again to verify")
|
||||||
|
|
||||||
|
|
||||||
def perform_installation(components: List[str], args: argparse.Namespace, config_manager: ConfigService = None) -> bool:
|
def perform_installation(
|
||||||
|
components: List[str],
|
||||||
|
args: argparse.Namespace,
|
||||||
|
config_manager: ConfigService = None,
|
||||||
|
) -> bool:
|
||||||
"""Perform the actual installation"""
|
"""Perform the actual installation"""
|
||||||
logger = get_logger()
|
logger = get_logger()
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Create installer
|
# Create installer
|
||||||
installer = Installer(args.install_dir, dry_run=args.dry_run)
|
installer = Installer(args.install_dir, dry_run=args.dry_run)
|
||||||
|
|
||||||
# Create component registry
|
# Create component registry
|
||||||
registry = ComponentRegistry(PROJECT_ROOT / "setup" / "components")
|
registry = ComponentRegistry(PROJECT_ROOT / "setup" / "components")
|
||||||
registry.discover_components()
|
registry.discover_components()
|
||||||
|
|
||||||
# Create component instances
|
# Create component instances
|
||||||
component_instances = registry.create_component_instances(components, args.install_dir)
|
component_instances = registry.create_component_instances(
|
||||||
|
components, args.install_dir
|
||||||
|
)
|
||||||
|
|
||||||
if not component_instances:
|
if not component_instances:
|
||||||
logger.error("No valid component instances created")
|
logger.error("No valid component instances created")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# Register components with installer
|
# Register components with installer
|
||||||
installer.register_components(list(component_instances.values()))
|
installer.register_components(list(component_instances.values()))
|
||||||
|
|
||||||
# The 'components' list is already resolved, so we can use it directly.
|
# The 'components' list is already resolved, so we can use it directly.
|
||||||
ordered_components = components
|
ordered_components = components
|
||||||
|
|
||||||
# Setup progress tracking
|
# Setup progress tracking
|
||||||
progress = ProgressBar(
|
progress = ProgressBar(
|
||||||
total=len(ordered_components),
|
total=len(ordered_components), prefix="Installing: ", suffix=""
|
||||||
prefix="Installing: ",
|
|
||||||
suffix=""
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Install components
|
# Install components
|
||||||
logger.info(f"Installing {len(ordered_components)} components...")
|
logger.info(f"Installing {len(ordered_components)} components...")
|
||||||
|
|
||||||
config = {
|
config = {
|
||||||
"force": args.force,
|
"force": args.force,
|
||||||
"backup": not args.no_backup,
|
"backup": not args.no_backup,
|
||||||
"dry_run": args.dry_run,
|
"dry_run": args.dry_run,
|
||||||
"selected_mcp_servers": getattr(config_manager, '_installation_context', {}).get("selected_mcp_servers", [])
|
"selected_mcp_servers": getattr(
|
||||||
|
config_manager, "_installation_context", {}
|
||||||
|
).get("selected_mcp_servers", []),
|
||||||
}
|
}
|
||||||
|
|
||||||
success = installer.install_components(ordered_components, config)
|
success = installer.install_components(ordered_components, config)
|
||||||
|
|
||||||
# Update progress
|
# Update progress
|
||||||
for i, component_name in enumerate(ordered_components):
|
for i, component_name in enumerate(ordered_components):
|
||||||
if component_name in installer.installed_components:
|
if component_name in installer.installed_components:
|
||||||
@ -502,32 +578,36 @@ def perform_installation(components: List[str], args: argparse.Namespace, config
|
|||||||
else:
|
else:
|
||||||
progress.update(i + 1, f"Failed {component_name}")
|
progress.update(i + 1, f"Failed {component_name}")
|
||||||
time.sleep(0.1) # Brief pause for visual effect
|
time.sleep(0.1) # Brief pause for visual effect
|
||||||
|
|
||||||
progress.finish("Installation complete")
|
progress.finish("Installation complete")
|
||||||
|
|
||||||
# Show results
|
# Show results
|
||||||
duration = time.time() - start_time
|
duration = time.time() - start_time
|
||||||
|
|
||||||
if success:
|
if success:
|
||||||
logger.success(f"Installation completed successfully in {duration:.1f} seconds")
|
logger.success(
|
||||||
|
f"Installation completed successfully in {duration:.1f} seconds"
|
||||||
|
)
|
||||||
|
|
||||||
# Show summary
|
# Show summary
|
||||||
summary = installer.get_installation_summary()
|
summary = installer.get_installation_summary()
|
||||||
if summary['installed']:
|
if summary["installed"]:
|
||||||
logger.info(f"Installed components: {', '.join(summary['installed'])}")
|
logger.info(f"Installed components: {', '.join(summary['installed'])}")
|
||||||
|
|
||||||
if summary['backup_path']:
|
if summary["backup_path"]:
|
||||||
logger.info(f"Backup created: {summary['backup_path']}")
|
logger.info(f"Backup created: {summary['backup_path']}")
|
||||||
|
|
||||||
else:
|
else:
|
||||||
logger.error(f"Installation completed with errors in {duration:.1f} seconds")
|
logger.error(
|
||||||
|
f"Installation completed with errors in {duration:.1f} seconds"
|
||||||
|
)
|
||||||
|
|
||||||
summary = installer.get_installation_summary()
|
summary = installer.get_installation_summary()
|
||||||
if summary['failed']:
|
if summary["failed"]:
|
||||||
logger.error(f"Failed components: {', '.join(summary['failed'])}")
|
logger.error(f"Failed components: {', '.join(summary['failed'])}")
|
||||||
|
|
||||||
return success
|
return success
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.exception(f"Unexpected error during installation: {e}")
|
logger.exception(f"Unexpected error during installation: {e}")
|
||||||
return False
|
return False
|
||||||
@ -547,18 +627,18 @@ def run(args: argparse.Namespace) -> int:
|
|||||||
try:
|
try:
|
||||||
# Verify the resolved path is still within user home
|
# Verify the resolved path is still within user home
|
||||||
install_dir_resolved.relative_to(expected_home)
|
install_dir_resolved.relative_to(expected_home)
|
||||||
|
|
||||||
# Additional check: if there's a symlink in the path, verify it doesn't escape user home
|
# Additional check: if there's a symlink in the path, verify it doesn't escape user home
|
||||||
if install_dir_original != install_dir_resolved:
|
if install_dir_original != install_dir_resolved:
|
||||||
# Path contains symlinks - verify each component stays within user home
|
# Path contains symlinks - verify each component stays within user home
|
||||||
current_path = expected_home
|
current_path = expected_home
|
||||||
parts = install_dir_original.parts
|
parts = install_dir_original.parts
|
||||||
home_parts = expected_home.parts
|
home_parts = expected_home.parts
|
||||||
|
|
||||||
# Skip home directory parts
|
# Skip home directory parts
|
||||||
if len(parts) >= len(home_parts) and parts[:len(home_parts)] == home_parts:
|
if len(parts) >= len(home_parts) and parts[: len(home_parts)] == home_parts:
|
||||||
relative_parts = parts[len(home_parts):]
|
relative_parts = parts[len(home_parts) :]
|
||||||
|
|
||||||
for part in relative_parts:
|
for part in relative_parts:
|
||||||
current_path = current_path / part
|
current_path = current_path / part
|
||||||
if current_path.is_symlink():
|
if current_path.is_symlink():
|
||||||
@ -575,7 +655,7 @@ def run(args: argparse.Namespace) -> int:
|
|||||||
print(f"\n[x] Security validation failed: {e}")
|
print(f"\n[x] Security validation failed: {e}")
|
||||||
print(f" Please use a standard directory path within your user profile.")
|
print(f" Please use a standard directory path within your user profile.")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Validate global arguments
|
# Validate global arguments
|
||||||
success, errors = operation.validate_global_args(args)
|
success, errors = operation.validate_global_args(args)
|
||||||
@ -583,20 +663,21 @@ def run(args: argparse.Namespace) -> int:
|
|||||||
for error in errors:
|
for error in errors:
|
||||||
logger.error(error)
|
logger.error(error)
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
# Display header
|
# Display header
|
||||||
if not args.quiet:
|
if not args.quiet:
|
||||||
from setup.cli.base import __version__
|
from setup.cli.base import __version__
|
||||||
|
|
||||||
display_header(
|
display_header(
|
||||||
f"SuperClaude Installation v{__version__}",
|
f"SuperClaude Installation v{__version__}",
|
||||||
"Installing SuperClaude framework components"
|
"Installing SuperClaude framework components",
|
||||||
)
|
)
|
||||||
|
|
||||||
# Handle special modes
|
# Handle special modes
|
||||||
if args.list_components:
|
if args.list_components:
|
||||||
registry = ComponentRegistry(PROJECT_ROOT / "setup" / "components")
|
registry = ComponentRegistry(PROJECT_ROOT / "setup" / "components")
|
||||||
registry.discover_components()
|
registry.discover_components()
|
||||||
|
|
||||||
components = registry.list_components()
|
components = registry.list_components()
|
||||||
if components:
|
if components:
|
||||||
print(f"\n{Colors.CYAN}Available Components:{Colors.RESET}")
|
print(f"\n{Colors.CYAN}Available Components:{Colors.RESET}")
|
||||||
@ -611,22 +692,22 @@ def run(args: argparse.Namespace) -> int:
|
|||||||
else:
|
else:
|
||||||
print("No components found")
|
print("No components found")
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
# Handle diagnostic mode
|
# Handle diagnostic mode
|
||||||
if args.diagnose:
|
if args.diagnose:
|
||||||
validator = Validator()
|
validator = Validator()
|
||||||
run_system_diagnostics(validator)
|
run_system_diagnostics(validator)
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
# Create component registry and load configuration
|
# Create component registry and load configuration
|
||||||
logger.info("Initializing installation system...")
|
logger.info("Initializing installation system...")
|
||||||
|
|
||||||
registry = ComponentRegistry(PROJECT_ROOT / "setup" / "components")
|
registry = ComponentRegistry(PROJECT_ROOT / "setup" / "components")
|
||||||
registry.discover_components()
|
registry.discover_components()
|
||||||
|
|
||||||
config_manager = ConfigService(DATA_DIR)
|
config_manager = ConfigService(DATA_DIR)
|
||||||
validator = Validator()
|
validator = Validator()
|
||||||
|
|
||||||
# Validate configuration
|
# Validate configuration
|
||||||
config_errors = config_manager.validate_config_files()
|
config_errors = config_manager.validate_config_files()
|
||||||
if config_errors:
|
if config_errors:
|
||||||
@ -634,9 +715,11 @@ def run(args: argparse.Namespace) -> int:
|
|||||||
for error in config_errors:
|
for error in config_errors:
|
||||||
logger.error(f" - {error}")
|
logger.error(f" - {error}")
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
# Get components to install
|
# Get components to install
|
||||||
components_to_install = get_components_to_install(args, registry, config_manager)
|
components_to_install = get_components_to_install(
|
||||||
|
args, registry, config_manager
|
||||||
|
)
|
||||||
if not components_to_install:
|
if not components_to_install:
|
||||||
logger.error("No components selected for installation")
|
logger.error("No components selected for installation")
|
||||||
return 1
|
return 1
|
||||||
@ -647,50 +730,58 @@ def run(args: argparse.Namespace) -> int:
|
|||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
logger.error(f"Dependency resolution error: {e}")
|
logger.error(f"Dependency resolution error: {e}")
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
# Validate system requirements for all components
|
# Validate system requirements for all components
|
||||||
if not validate_system_requirements(validator, resolved_components):
|
if not validate_system_requirements(validator, resolved_components):
|
||||||
if not args.force:
|
if not args.force:
|
||||||
logger.error("System requirements not met. Use --force to override.")
|
logger.error("System requirements not met. Use --force to override.")
|
||||||
return 1
|
return 1
|
||||||
else:
|
else:
|
||||||
logger.warning("System requirements not met, but continuing due to --force flag")
|
logger.warning(
|
||||||
|
"System requirements not met, but continuing due to --force flag"
|
||||||
|
)
|
||||||
|
|
||||||
# Check for existing installation
|
# Check for existing installation
|
||||||
if args.install_dir.exists() and not args.force:
|
if args.install_dir.exists() and not args.force:
|
||||||
if not args.dry_run:
|
if not args.dry_run:
|
||||||
logger.warning(f"Installation directory already exists: {args.install_dir}")
|
logger.warning(
|
||||||
if not args.yes and not confirm("Continue and update existing installation?", default=False):
|
f"Installation directory already exists: {args.install_dir}"
|
||||||
|
)
|
||||||
|
if not args.yes and not confirm(
|
||||||
|
"Continue and update existing installation?", default=False
|
||||||
|
):
|
||||||
logger.info("Installation cancelled by user")
|
logger.info("Installation cancelled by user")
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
# Display installation plan
|
# Display installation plan
|
||||||
if not args.quiet:
|
if not args.quiet:
|
||||||
display_installation_plan(resolved_components, registry, args.install_dir)
|
display_installation_plan(resolved_components, registry, args.install_dir)
|
||||||
|
|
||||||
if not args.dry_run:
|
if not args.dry_run:
|
||||||
if not args.yes and not confirm("Proceed with installation?", default=True):
|
if not args.yes and not confirm(
|
||||||
|
"Proceed with installation?", default=True
|
||||||
|
):
|
||||||
logger.info("Installation cancelled by user")
|
logger.info("Installation cancelled by user")
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
# Perform installation
|
# Perform installation
|
||||||
success = perform_installation(resolved_components, args, config_manager)
|
success = perform_installation(resolved_components, args, config_manager)
|
||||||
|
|
||||||
if success:
|
if success:
|
||||||
if not args.quiet:
|
if not args.quiet:
|
||||||
display_success("SuperClaude installation completed successfully!")
|
display_success("SuperClaude installation completed successfully!")
|
||||||
|
|
||||||
if not args.dry_run:
|
if not args.dry_run:
|
||||||
print(f"\n{Colors.CYAN}Next steps:{Colors.RESET}")
|
print(f"\n{Colors.CYAN}Next steps:{Colors.RESET}")
|
||||||
print(f"1. Restart your Claude Code session")
|
print(f"1. Restart your Claude Code session")
|
||||||
print(f"2. Framework files are now available in {args.install_dir}")
|
print(f"2. Framework files are now available in {args.install_dir}")
|
||||||
print(f"3. Use SuperClaude commands and features in Claude Code")
|
print(f"3. Use SuperClaude commands and features in Claude Code")
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
else:
|
else:
|
||||||
display_error("Installation failed. Check logs for details.")
|
display_error("Installation failed. Check logs for details.")
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
print(f"\n{Colors.YELLOW}Installation cancelled by user{Colors.RESET}")
|
print(f"\n{Colors.YELLOW}Installation cancelled by user{Colors.RESET}")
|
||||||
return 130
|
return 130
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -15,8 +15,17 @@ from ...core.registry import ComponentRegistry
|
|||||||
from ...services.settings import SettingsService
|
from ...services.settings import SettingsService
|
||||||
from ...core.validator import Validator
|
from ...core.validator import Validator
|
||||||
from ...utils.ui import (
|
from ...utils.ui import (
|
||||||
display_header, display_info, display_success, display_error,
|
display_header,
|
||||||
display_warning, Menu, confirm, ProgressBar, Colors, format_size, prompt_api_key
|
display_info,
|
||||||
|
display_success,
|
||||||
|
display_error,
|
||||||
|
display_warning,
|
||||||
|
Menu,
|
||||||
|
confirm,
|
||||||
|
ProgressBar,
|
||||||
|
Colors,
|
||||||
|
format_size,
|
||||||
|
prompt_api_key,
|
||||||
)
|
)
|
||||||
from ...utils.environment import setup_environment_variables
|
from ...utils.environment import setup_environment_variables
|
||||||
from ...utils.logger import get_logger
|
from ...utils.logger import get_logger
|
||||||
@ -26,7 +35,7 @@ from . import OperationBase
|
|||||||
|
|
||||||
class UpdateOperation(OperationBase):
|
class UpdateOperation(OperationBase):
|
||||||
"""Update operation implementation"""
|
"""Update operation implementation"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__("update")
|
super().__init__("update")
|
||||||
|
|
||||||
@ -34,7 +43,7 @@ class UpdateOperation(OperationBase):
|
|||||||
def register_parser(subparsers, global_parser=None) -> argparse.ArgumentParser:
|
def register_parser(subparsers, global_parser=None) -> argparse.ArgumentParser:
|
||||||
"""Register update CLI arguments"""
|
"""Register update CLI arguments"""
|
||||||
parents = [global_parser] if global_parser else []
|
parents = [global_parser] if global_parser else []
|
||||||
|
|
||||||
parser = subparsers.add_parser(
|
parser = subparsers.add_parser(
|
||||||
"update",
|
"update",
|
||||||
help="Update existing SuperClaude installation",
|
help="Update existing SuperClaude installation",
|
||||||
@ -47,51 +56,44 @@ Examples:
|
|||||||
SuperClaude update --backup --force # Create backup before update (forced)
|
SuperClaude update --backup --force # Create backup before update (forced)
|
||||||
""",
|
""",
|
||||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||||
parents=parents
|
parents=parents,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Update mode options
|
# Update mode options
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--check",
|
"--check",
|
||||||
action="store_true",
|
action="store_true",
|
||||||
help="Check for available updates without installing"
|
help="Check for available updates without installing",
|
||||||
)
|
)
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--components",
|
"--components", type=str, nargs="+", help="Specific components to update"
|
||||||
type=str,
|
|
||||||
nargs="+",
|
|
||||||
help="Specific components to update"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Backup options
|
# Backup options
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--backup",
|
"--backup", action="store_true", help="Create backup before update"
|
||||||
action="store_true",
|
|
||||||
help="Create backup before update"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument("--no-backup", action="store_true", help="Skip backup creation")
|
||||||
"--no-backup",
|
|
||||||
action="store_true",
|
|
||||||
help="Skip backup creation"
|
|
||||||
)
|
|
||||||
|
|
||||||
# Update options
|
# Update options
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--reinstall",
|
"--reinstall",
|
||||||
action="store_true",
|
action="store_true",
|
||||||
help="Reinstall components even if versions match"
|
help="Reinstall components even if versions match",
|
||||||
)
|
)
|
||||||
|
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
|
|
||||||
def check_installation_exists(install_dir: Path) -> bool:
|
def check_installation_exists(install_dir: Path) -> bool:
|
||||||
"""Check if SuperClaude installation exists"""
|
"""Check if SuperClaude installation exists"""
|
||||||
settings_manager = SettingsService(install_dir)
|
settings_manager = SettingsService(install_dir)
|
||||||
|
|
||||||
return settings_manager.check_installation_exists()
|
return settings_manager.check_installation_exists()
|
||||||
|
|
||||||
|
|
||||||
def get_installed_components(install_dir: Path) -> Dict[str, Dict[str, Any]]:
|
def get_installed_components(install_dir: Path) -> Dict[str, Dict[str, Any]]:
|
||||||
"""Get currently installed components and their versions"""
|
"""Get currently installed components and their versions"""
|
||||||
try:
|
try:
|
||||||
@ -101,10 +103,12 @@ def get_installed_components(install_dir: Path) -> Dict[str, Dict[str, Any]]:
|
|||||||
return {}
|
return {}
|
||||||
|
|
||||||
|
|
||||||
def get_available_updates(installed_components: Dict[str, str], registry: ComponentRegistry) -> Dict[str, Dict[str, str]]:
|
def get_available_updates(
|
||||||
|
installed_components: Dict[str, str], registry: ComponentRegistry
|
||||||
|
) -> Dict[str, Dict[str, str]]:
|
||||||
"""Check for available updates"""
|
"""Check for available updates"""
|
||||||
updates = {}
|
updates = {}
|
||||||
|
|
||||||
for component_name, current_version in installed_components.items():
|
for component_name, current_version in installed_components.items():
|
||||||
try:
|
try:
|
||||||
metadata = registry.get_component_metadata(component_name)
|
metadata = registry.get_component_metadata(component_name)
|
||||||
@ -114,27 +118,29 @@ def get_available_updates(installed_components: Dict[str, str], registry: Compon
|
|||||||
updates[component_name] = {
|
updates[component_name] = {
|
||||||
"current": current_version,
|
"current": current_version,
|
||||||
"available": available_version,
|
"available": available_version,
|
||||||
"description": metadata.get("description", "No description")
|
"description": metadata.get("description", "No description"),
|
||||||
}
|
}
|
||||||
except Exception:
|
except Exception:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
return updates
|
return updates
|
||||||
|
|
||||||
|
|
||||||
def display_update_check(installed_components: Dict[str, str], available_updates: Dict[str, Dict[str, str]]) -> None:
|
def display_update_check(
|
||||||
|
installed_components: Dict[str, str], available_updates: Dict[str, Dict[str, str]]
|
||||||
|
) -> None:
|
||||||
"""Display update check results"""
|
"""Display update check results"""
|
||||||
print(f"\n{Colors.CYAN}{Colors.BRIGHT}Update Check Results{Colors.RESET}")
|
print(f"\n{Colors.CYAN}{Colors.BRIGHT}Update Check Results{Colors.RESET}")
|
||||||
print("=" * 50)
|
print("=" * 50)
|
||||||
|
|
||||||
if not installed_components:
|
if not installed_components:
|
||||||
print(f"{Colors.YELLOW}No SuperClaude installation found{Colors.RESET}")
|
print(f"{Colors.YELLOW}No SuperClaude installation found{Colors.RESET}")
|
||||||
return
|
return
|
||||||
|
|
||||||
print(f"{Colors.BLUE}Currently installed components:{Colors.RESET}")
|
print(f"{Colors.BLUE}Currently installed components:{Colors.RESET}")
|
||||||
for component, version in installed_components.items():
|
for component, version in installed_components.items():
|
||||||
print(f" {component}: v{version}")
|
print(f" {component}: v{version}")
|
||||||
|
|
||||||
if available_updates:
|
if available_updates:
|
||||||
print(f"\n{Colors.GREEN}Available updates:{Colors.RESET}")
|
print(f"\n{Colors.GREEN}Available updates:{Colors.RESET}")
|
||||||
for component, info in available_updates.items():
|
for component, info in available_updates.items():
|
||||||
@ -142,47 +148,54 @@ def display_update_check(installed_components: Dict[str, str], available_updates
|
|||||||
print(f" {info['description']}")
|
print(f" {info['description']}")
|
||||||
else:
|
else:
|
||||||
print(f"\n{Colors.GREEN}All components are up to date{Colors.RESET}")
|
print(f"\n{Colors.GREEN}All components are up to date{Colors.RESET}")
|
||||||
|
|
||||||
print()
|
print()
|
||||||
|
|
||||||
|
|
||||||
def get_components_to_update(args: argparse.Namespace, installed_components: Dict[str, str],
|
def get_components_to_update(
|
||||||
available_updates: Dict[str, Dict[str, str]]) -> Optional[List[str]]:
|
args: argparse.Namespace,
|
||||||
|
installed_components: Dict[str, str],
|
||||||
|
available_updates: Dict[str, Dict[str, str]],
|
||||||
|
) -> Optional[List[str]]:
|
||||||
"""Determine which components to update"""
|
"""Determine which components to update"""
|
||||||
logger = get_logger()
|
logger = get_logger()
|
||||||
|
|
||||||
# Explicit components specified
|
# Explicit components specified
|
||||||
if args.components:
|
if args.components:
|
||||||
# Validate that specified components are installed
|
# Validate that specified components are installed
|
||||||
invalid_components = [c for c in args.components if c not in installed_components]
|
invalid_components = [
|
||||||
|
c for c in args.components if c not in installed_components
|
||||||
|
]
|
||||||
if invalid_components:
|
if invalid_components:
|
||||||
logger.error(f"Components not installed: {invalid_components}")
|
logger.error(f"Components not installed: {invalid_components}")
|
||||||
return None
|
return None
|
||||||
return args.components
|
return args.components
|
||||||
|
|
||||||
# If no updates available and not forcing reinstall
|
# If no updates available and not forcing reinstall
|
||||||
if not available_updates and not args.reinstall:
|
if not available_updates and not args.reinstall:
|
||||||
logger.info("No updates available")
|
logger.info("No updates available")
|
||||||
return []
|
return []
|
||||||
|
|
||||||
# Interactive selection
|
# Interactive selection
|
||||||
if available_updates:
|
if available_updates:
|
||||||
return interactive_update_selection(available_updates, installed_components)
|
return interactive_update_selection(available_updates, installed_components)
|
||||||
elif args.reinstall:
|
elif args.reinstall:
|
||||||
# Reinstall all components
|
# Reinstall all components
|
||||||
return list(installed_components.keys())
|
return list(installed_components.keys())
|
||||||
|
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
|
||||||
def collect_api_keys_for_servers(selected_servers: List[str], mcp_instance) -> Dict[str, str]:
|
def collect_api_keys_for_servers(
|
||||||
|
selected_servers: List[str], mcp_instance
|
||||||
|
) -> Dict[str, str]:
|
||||||
"""
|
"""
|
||||||
Collect API keys for servers that require them during update
|
Collect API keys for servers that require them during update
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
selected_servers: List of selected server keys
|
selected_servers: List of selected server keys
|
||||||
mcp_instance: MCP component instance
|
mcp_instance: MCP component instance
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Dictionary of environment variable names to API key values
|
Dictionary of environment variable names to API key values
|
||||||
"""
|
"""
|
||||||
@ -190,81 +203,90 @@ def collect_api_keys_for_servers(selected_servers: List[str], mcp_instance) -> D
|
|||||||
servers_needing_keys = [
|
servers_needing_keys = [
|
||||||
(server_key, mcp_instance.mcp_servers[server_key])
|
(server_key, mcp_instance.mcp_servers[server_key])
|
||||||
for server_key in selected_servers
|
for server_key in selected_servers
|
||||||
if server_key in mcp_instance.mcp_servers and
|
if server_key in mcp_instance.mcp_servers
|
||||||
mcp_instance.mcp_servers[server_key].get("requires_api_key", False)
|
and mcp_instance.mcp_servers[server_key].get("requires_api_key", False)
|
||||||
]
|
]
|
||||||
|
|
||||||
if not servers_needing_keys:
|
if not servers_needing_keys:
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
# Display API key configuration header
|
# Display API key configuration header
|
||||||
print(f"\n{Colors.CYAN}{Colors.BRIGHT}=== API Key Configuration ==={Colors.RESET}")
|
print(f"\n{Colors.CYAN}{Colors.BRIGHT}=== API Key Configuration ==={Colors.RESET}")
|
||||||
print(f"{Colors.YELLOW}New MCP servers require API keys for full functionality:{Colors.RESET}\n")
|
print(
|
||||||
|
f"{Colors.YELLOW}New MCP servers require API keys for full functionality:{Colors.RESET}\n"
|
||||||
|
)
|
||||||
|
|
||||||
collected_keys = {}
|
collected_keys = {}
|
||||||
for server_key, server_info in servers_needing_keys:
|
for server_key, server_info in servers_needing_keys:
|
||||||
api_key_env = server_info.get("api_key_env")
|
api_key_env = server_info.get("api_key_env")
|
||||||
service_name = server_info["name"]
|
service_name = server_info["name"]
|
||||||
|
|
||||||
if api_key_env:
|
if api_key_env:
|
||||||
key = prompt_api_key(service_name, api_key_env)
|
key = prompt_api_key(service_name, api_key_env)
|
||||||
if key:
|
if key:
|
||||||
collected_keys[api_key_env] = key
|
collected_keys[api_key_env] = key
|
||||||
|
|
||||||
return collected_keys
|
return collected_keys
|
||||||
|
|
||||||
|
|
||||||
def interactive_update_selection(available_updates: Dict[str, Dict[str, str]],
|
def interactive_update_selection(
|
||||||
installed_components: Dict[str, str]) -> Optional[List[str]]:
|
available_updates: Dict[str, Dict[str, str]], installed_components: Dict[str, str]
|
||||||
|
) -> Optional[List[str]]:
|
||||||
"""Interactive update selection"""
|
"""Interactive update selection"""
|
||||||
if not available_updates:
|
if not available_updates:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
print(f"\n{Colors.CYAN}Available Updates:{Colors.RESET}")
|
print(f"\n{Colors.CYAN}Available Updates:{Colors.RESET}")
|
||||||
|
|
||||||
# Create menu options
|
# Create menu options
|
||||||
update_options = []
|
update_options = []
|
||||||
component_names = []
|
component_names = []
|
||||||
|
|
||||||
for component, info in available_updates.items():
|
for component, info in available_updates.items():
|
||||||
update_options.append(f"{component}: v{info['current']} → v{info['available']}")
|
update_options.append(f"{component}: v{info['current']} → v{info['available']}")
|
||||||
component_names.append(component)
|
component_names.append(component)
|
||||||
|
|
||||||
# Add bulk options
|
# Add bulk options
|
||||||
preset_options = [
|
preset_options = [
|
||||||
"Update All Components",
|
"Update All Components",
|
||||||
"Select Individual Components",
|
"Select Individual Components",
|
||||||
"Cancel Update"
|
"Cancel Update",
|
||||||
]
|
]
|
||||||
|
|
||||||
menu = Menu("Select update option:", preset_options)
|
menu = Menu("Select update option:", preset_options)
|
||||||
choice = menu.display()
|
choice = menu.display()
|
||||||
|
|
||||||
if choice == -1 or choice == 2: # Cancelled
|
if choice == -1 or choice == 2: # Cancelled
|
||||||
return None
|
return None
|
||||||
elif choice == 0: # Update all
|
elif choice == 0: # Update all
|
||||||
return component_names
|
return component_names
|
||||||
elif choice == 1: # Select individual
|
elif choice == 1: # Select individual
|
||||||
component_menu = Menu("Select components to update:", update_options, multi_select=True)
|
component_menu = Menu(
|
||||||
|
"Select components to update:", update_options, multi_select=True
|
||||||
|
)
|
||||||
selections = component_menu.display()
|
selections = component_menu.display()
|
||||||
|
|
||||||
if not selections:
|
if not selections:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
return [component_names[i] for i in selections]
|
return [component_names[i] for i in selections]
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def display_update_plan(components: List[str], available_updates: Dict[str, Dict[str, str]],
|
def display_update_plan(
|
||||||
installed_components: Dict[str, str], install_dir: Path) -> None:
|
components: List[str],
|
||||||
|
available_updates: Dict[str, Dict[str, str]],
|
||||||
|
installed_components: Dict[str, str],
|
||||||
|
install_dir: Path,
|
||||||
|
) -> None:
|
||||||
"""Display update plan"""
|
"""Display update plan"""
|
||||||
print(f"\n{Colors.CYAN}{Colors.BRIGHT}Update Plan{Colors.RESET}")
|
print(f"\n{Colors.CYAN}{Colors.BRIGHT}Update Plan{Colors.RESET}")
|
||||||
print("=" * 50)
|
print("=" * 50)
|
||||||
|
|
||||||
print(f"{Colors.BLUE}Installation Directory:{Colors.RESET} {install_dir}")
|
print(f"{Colors.BLUE}Installation Directory:{Colors.RESET} {install_dir}")
|
||||||
print(f"{Colors.BLUE}Components to update:{Colors.RESET}")
|
print(f"{Colors.BLUE}Components to update:{Colors.RESET}")
|
||||||
|
|
||||||
for i, component_name in enumerate(components, 1):
|
for i, component_name in enumerate(components, 1):
|
||||||
if component_name in available_updates:
|
if component_name in available_updates:
|
||||||
info = available_updates[component_name]
|
info = available_updates[component_name]
|
||||||
@ -272,72 +294,80 @@ def display_update_plan(components: List[str], available_updates: Dict[str, Dict
|
|||||||
else:
|
else:
|
||||||
current_version = installed_components.get(component_name, "unknown")
|
current_version = installed_components.get(component_name, "unknown")
|
||||||
print(f" {i}. {component_name}: v{current_version} (reinstall)")
|
print(f" {i}. {component_name}: v{current_version} (reinstall)")
|
||||||
|
|
||||||
print()
|
print()
|
||||||
|
|
||||||
|
|
||||||
def perform_update(components: List[str], args: argparse.Namespace, registry: ComponentRegistry) -> bool:
|
def perform_update(
|
||||||
|
components: List[str], args: argparse.Namespace, registry: ComponentRegistry
|
||||||
|
) -> bool:
|
||||||
"""Perform the actual update"""
|
"""Perform the actual update"""
|
||||||
logger = get_logger()
|
logger = get_logger()
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Create installer
|
# Create installer
|
||||||
installer = Installer(args.install_dir, dry_run=args.dry_run)
|
installer = Installer(args.install_dir, dry_run=args.dry_run)
|
||||||
|
|
||||||
# Create component instances
|
# Create component instances
|
||||||
component_instances = registry.create_component_instances(components, args.install_dir)
|
component_instances = registry.create_component_instances(
|
||||||
|
components, args.install_dir
|
||||||
|
)
|
||||||
|
|
||||||
if not component_instances:
|
if not component_instances:
|
||||||
logger.error("No valid component instances created")
|
logger.error("No valid component instances created")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# Handle MCP component specially - collect API keys for new servers
|
# Handle MCP component specially - collect API keys for new servers
|
||||||
collected_api_keys = {}
|
collected_api_keys = {}
|
||||||
if "mcp" in components and "mcp" in component_instances:
|
if "mcp" in components and "mcp" in component_instances:
|
||||||
mcp_instance = component_instances["mcp"]
|
mcp_instance = component_instances["mcp"]
|
||||||
if hasattr(mcp_instance, 'mcp_servers'):
|
if hasattr(mcp_instance, "mcp_servers"):
|
||||||
# Get all available MCP servers
|
# Get all available MCP servers
|
||||||
all_server_keys = list(mcp_instance.mcp_servers.keys())
|
all_server_keys = list(mcp_instance.mcp_servers.keys())
|
||||||
|
|
||||||
# Collect API keys for any servers that require them
|
# Collect API keys for any servers that require them
|
||||||
collected_api_keys = collect_api_keys_for_servers(all_server_keys, mcp_instance)
|
collected_api_keys = collect_api_keys_for_servers(
|
||||||
|
all_server_keys, mcp_instance
|
||||||
|
)
|
||||||
|
|
||||||
# Set up environment variables if any keys were collected
|
# Set up environment variables if any keys were collected
|
||||||
if collected_api_keys:
|
if collected_api_keys:
|
||||||
setup_environment_variables(collected_api_keys)
|
setup_environment_variables(collected_api_keys)
|
||||||
|
|
||||||
# Store keys for MCP component to use during update
|
# Store keys for MCP component to use during update
|
||||||
mcp_instance.collected_api_keys = collected_api_keys
|
mcp_instance.collected_api_keys = collected_api_keys
|
||||||
|
|
||||||
logger.info(f"Collected {len(collected_api_keys)} API keys for MCP server update")
|
logger.info(
|
||||||
|
f"Collected {len(collected_api_keys)} API keys for MCP server update"
|
||||||
|
)
|
||||||
|
|
||||||
# Register components with installer
|
# Register components with installer
|
||||||
installer.register_components(list(component_instances.values()))
|
installer.register_components(list(component_instances.values()))
|
||||||
|
|
||||||
# Setup progress tracking
|
# Setup progress tracking
|
||||||
progress = ProgressBar(
|
progress = ProgressBar(total=len(components), prefix="Updating: ", suffix="")
|
||||||
total=len(components),
|
|
||||||
prefix="Updating: ",
|
|
||||||
suffix=""
|
|
||||||
)
|
|
||||||
|
|
||||||
# Update components
|
# Update components
|
||||||
logger.info(f"Updating {len(components)} components...")
|
logger.info(f"Updating {len(components)} components...")
|
||||||
|
|
||||||
# Determine backup strategy
|
# Determine backup strategy
|
||||||
backup = args.backup or (not args.no_backup and not args.dry_run)
|
backup = args.backup or (not args.no_backup and not args.dry_run)
|
||||||
|
|
||||||
config = {
|
config = {
|
||||||
"force": args.force,
|
"force": args.force,
|
||||||
"backup": backup,
|
"backup": backup,
|
||||||
"dry_run": args.dry_run,
|
"dry_run": args.dry_run,
|
||||||
"update_mode": True,
|
"update_mode": True,
|
||||||
"selected_mcp_servers": list(mcp_instance.mcp_servers.keys()) if "mcp" in component_instances else []
|
"selected_mcp_servers": (
|
||||||
|
list(mcp_instance.mcp_servers.keys())
|
||||||
|
if "mcp" in component_instances
|
||||||
|
else []
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
success = installer.update_components(components, config)
|
success = installer.update_components(components, config)
|
||||||
|
|
||||||
# Update progress
|
# Update progress
|
||||||
for i, component_name in enumerate(components):
|
for i, component_name in enumerate(components):
|
||||||
if component_name in installer.updated_components:
|
if component_name in installer.updated_components:
|
||||||
@ -345,32 +375,32 @@ def perform_update(components: List[str], args: argparse.Namespace, registry: Co
|
|||||||
else:
|
else:
|
||||||
progress.update(i + 1, f"Failed {component_name}")
|
progress.update(i + 1, f"Failed {component_name}")
|
||||||
time.sleep(0.1) # Brief pause for visual effect
|
time.sleep(0.1) # Brief pause for visual effect
|
||||||
|
|
||||||
progress.finish("Update complete")
|
progress.finish("Update complete")
|
||||||
|
|
||||||
# Show results
|
# Show results
|
||||||
duration = time.time() - start_time
|
duration = time.time() - start_time
|
||||||
|
|
||||||
if success:
|
if success:
|
||||||
logger.success(f"Update completed successfully in {duration:.1f} seconds")
|
logger.success(f"Update completed successfully in {duration:.1f} seconds")
|
||||||
|
|
||||||
# Show summary
|
# Show summary
|
||||||
summary = installer.get_update_summary()
|
summary = installer.get_update_summary()
|
||||||
if summary.get('updated'):
|
if summary.get("updated"):
|
||||||
logger.info(f"Updated components: {', '.join(summary['updated'])}")
|
logger.info(f"Updated components: {', '.join(summary['updated'])}")
|
||||||
|
|
||||||
if summary.get('backup_path'):
|
if summary.get("backup_path"):
|
||||||
logger.info(f"Backup created: {summary['backup_path']}")
|
logger.info(f"Backup created: {summary['backup_path']}")
|
||||||
|
|
||||||
else:
|
else:
|
||||||
logger.error(f"Update completed with errors in {duration:.1f} seconds")
|
logger.error(f"Update completed with errors in {duration:.1f} seconds")
|
||||||
|
|
||||||
summary = installer.get_update_summary()
|
summary = installer.get_update_summary()
|
||||||
if summary.get('failed'):
|
if summary.get("failed"):
|
||||||
logger.error(f"Failed components: {', '.join(summary['failed'])}")
|
logger.error(f"Failed components: {', '.join(summary['failed'])}")
|
||||||
|
|
||||||
return success
|
return success
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.exception(f"Unexpected error during update: {e}")
|
logger.exception(f"Unexpected error during update: {e}")
|
||||||
return False
|
return False
|
||||||
@ -393,7 +423,7 @@ def run(args: argparse.Namespace) -> int:
|
|||||||
print(f" Expected prefix: {expected_home}")
|
print(f" Expected prefix: {expected_home}")
|
||||||
print(f" Provided path: {actual_dir}")
|
print(f" Provided path: {actual_dir}")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Validate global arguments
|
# Validate global arguments
|
||||||
success, errors = operation.validate_global_args(args)
|
success, errors = operation.validate_global_args(args)
|
||||||
@ -401,79 +431,83 @@ def run(args: argparse.Namespace) -> int:
|
|||||||
for error in errors:
|
for error in errors:
|
||||||
logger.error(error)
|
logger.error(error)
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
# Display header
|
# Display header
|
||||||
if not args.quiet:
|
if not args.quiet:
|
||||||
display_header(
|
display_header(
|
||||||
f"SuperClaude Update v{__version__}",
|
f"SuperClaude Update v{__version__}",
|
||||||
"Updating SuperClaude framework components"
|
"Updating SuperClaude framework components",
|
||||||
)
|
)
|
||||||
|
|
||||||
# Check if SuperClaude is installed
|
# Check if SuperClaude is installed
|
||||||
if not check_installation_exists(args.install_dir):
|
if not check_installation_exists(args.install_dir):
|
||||||
logger.error(f"SuperClaude installation not found in {args.install_dir}")
|
logger.error(f"SuperClaude installation not found in {args.install_dir}")
|
||||||
logger.info("Use 'SuperClaude install' to install SuperClaude first")
|
logger.info("Use 'superclaude install' to install SuperClaude first")
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
# Create component registry
|
# Create component registry
|
||||||
logger.info("Checking for available updates...")
|
logger.info("Checking for available updates...")
|
||||||
|
|
||||||
registry = ComponentRegistry(PROJECT_ROOT / "setup" / "components")
|
registry = ComponentRegistry(PROJECT_ROOT / "setup" / "components")
|
||||||
registry.discover_components()
|
registry.discover_components()
|
||||||
|
|
||||||
# Get installed components
|
# Get installed components
|
||||||
installed_components = get_installed_components(args.install_dir)
|
installed_components = get_installed_components(args.install_dir)
|
||||||
if not installed_components:
|
if not installed_components:
|
||||||
logger.error("Could not determine installed components")
|
logger.error("Could not determine installed components")
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
# Check for available updates
|
# Check for available updates
|
||||||
available_updates = get_available_updates(installed_components, registry)
|
available_updates = get_available_updates(installed_components, registry)
|
||||||
|
|
||||||
# Display update check results
|
# Display update check results
|
||||||
if not args.quiet:
|
if not args.quiet:
|
||||||
display_update_check(installed_components, available_updates)
|
display_update_check(installed_components, available_updates)
|
||||||
|
|
||||||
# If only checking for updates, exit here
|
# If only checking for updates, exit here
|
||||||
if args.check:
|
if args.check:
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
# Get components to update
|
# Get components to update
|
||||||
components = get_components_to_update(args, installed_components, available_updates)
|
components = get_components_to_update(
|
||||||
|
args, installed_components, available_updates
|
||||||
|
)
|
||||||
if components is None:
|
if components is None:
|
||||||
logger.info("Update cancelled by user")
|
logger.info("Update cancelled by user")
|
||||||
return 0
|
return 0
|
||||||
elif not components:
|
elif not components:
|
||||||
logger.info("No components selected for update")
|
logger.info("No components selected for update")
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
# Display update plan
|
# Display update plan
|
||||||
if not args.quiet:
|
if not args.quiet:
|
||||||
display_update_plan(components, available_updates, installed_components, args.install_dir)
|
display_update_plan(
|
||||||
|
components, available_updates, installed_components, args.install_dir
|
||||||
|
)
|
||||||
|
|
||||||
if not args.dry_run:
|
if not args.dry_run:
|
||||||
if not args.yes and not confirm("Proceed with update?", default=True):
|
if not args.yes and not confirm("Proceed with update?", default=True):
|
||||||
logger.info("Update cancelled by user")
|
logger.info("Update cancelled by user")
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
# Perform update
|
# Perform update
|
||||||
success = perform_update(components, args, registry)
|
success = perform_update(components, args, registry)
|
||||||
|
|
||||||
if success:
|
if success:
|
||||||
if not args.quiet:
|
if not args.quiet:
|
||||||
display_success("SuperClaude update completed successfully!")
|
display_success("SuperClaude update completed successfully!")
|
||||||
|
|
||||||
if not args.dry_run:
|
if not args.dry_run:
|
||||||
print(f"\n{Colors.CYAN}Next steps:{Colors.RESET}")
|
print(f"\n{Colors.CYAN}Next steps:{Colors.RESET}")
|
||||||
print(f"1. Restart your Claude Code session")
|
print(f"1. Restart your Claude Code session")
|
||||||
print(f"2. Updated components are now available")
|
print(f"2. Updated components are now available")
|
||||||
print(f"3. Check for any breaking changes in documentation")
|
print(f"3. Check for any breaking changes in documentation")
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
else:
|
else:
|
||||||
display_error("Update failed. Check logs for details.")
|
display_error("Update failed. Check logs for details.")
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
print(f"\n{Colors.YELLOW}Update cancelled by user{Colors.RESET}")
|
print(f"\n{Colors.YELLOW}Update cancelled by user{Colors.RESET}")
|
||||||
return 130
|
return 130
|
||||||
|
|||||||
@ -8,10 +8,10 @@ from .modes import ModesComponent
|
|||||||
from .mcp_docs import MCPDocsComponent
|
from .mcp_docs import MCPDocsComponent
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
'CoreComponent',
|
"CoreComponent",
|
||||||
'CommandsComponent',
|
"CommandsComponent",
|
||||||
'MCPComponent',
|
"MCPComponent",
|
||||||
'AgentsComponent',
|
"AgentsComponent",
|
||||||
'ModesComponent',
|
"ModesComponent",
|
||||||
'MCPDocsComponent'
|
"MCPDocsComponent",
|
||||||
]
|
]
|
||||||
|
|||||||
@ -11,20 +11,20 @@ from setup import __version__
|
|||||||
|
|
||||||
class AgentsComponent(Component):
|
class AgentsComponent(Component):
|
||||||
"""SuperClaude specialized AI agents component"""
|
"""SuperClaude specialized AI agents component"""
|
||||||
|
|
||||||
def __init__(self, install_dir: Optional[Path] = None):
|
def __init__(self, install_dir: Optional[Path] = None):
|
||||||
"""Initialize agents component"""
|
"""Initialize agents component"""
|
||||||
super().__init__(install_dir, Path("agents"))
|
super().__init__(install_dir, Path("agents"))
|
||||||
|
|
||||||
def get_metadata(self) -> Dict[str, str]:
|
def get_metadata(self) -> Dict[str, str]:
|
||||||
"""Get component metadata"""
|
"""Get component metadata"""
|
||||||
return {
|
return {
|
||||||
"name": "agents",
|
"name": "agents",
|
||||||
"version": __version__,
|
"version": __version__,
|
||||||
"description": "15 specialized AI agents with domain expertise and intelligent routing",
|
"description": "15 specialized AI agents with domain expertise and intelligent routing",
|
||||||
"category": "agents"
|
"category": "agents",
|
||||||
}
|
}
|
||||||
|
|
||||||
def get_metadata_modifications(self) -> Dict[str, Any]:
|
def get_metadata_modifications(self) -> Dict[str, Any]:
|
||||||
"""Get metadata modifications for agents"""
|
"""Get metadata modifications for agents"""
|
||||||
return {
|
return {
|
||||||
@ -33,27 +33,29 @@ class AgentsComponent(Component):
|
|||||||
"version": __version__,
|
"version": __version__,
|
||||||
"installed": True,
|
"installed": True,
|
||||||
"agents_count": len(self.component_files),
|
"agents_count": len(self.component_files),
|
||||||
"install_directory": str(self.install_component_subdir)
|
"install_directory": str(self.install_component_subdir),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def _install(self, config: Dict[str, Any]) -> bool:
|
def _install(self, config: Dict[str, Any]) -> bool:
|
||||||
"""Install agents component"""
|
"""Install agents component"""
|
||||||
self.logger.info("Installing SuperClaude specialized agents...")
|
self.logger.info("Installing SuperClaude specialized agents...")
|
||||||
|
|
||||||
# Call parent install method
|
# Call parent install method
|
||||||
success = super()._install(config)
|
success = super()._install(config)
|
||||||
|
|
||||||
if success:
|
if success:
|
||||||
# Run post-install setup
|
# Run post-install setup
|
||||||
success = self._post_install()
|
success = self._post_install()
|
||||||
|
|
||||||
if success:
|
if success:
|
||||||
self.logger.success(f"Successfully installed {len(self.component_files)} specialized agents")
|
self.logger.success(
|
||||||
|
f"Successfully installed {len(self.component_files)} specialized agents"
|
||||||
|
)
|
||||||
|
|
||||||
return success
|
return success
|
||||||
|
|
||||||
def _post_install(self) -> bool:
|
def _post_install(self) -> bool:
|
||||||
"""Post-install setup for agents"""
|
"""Post-install setup for agents"""
|
||||||
try:
|
try:
|
||||||
@ -61,27 +63,30 @@ class AgentsComponent(Component):
|
|||||||
metadata_mods = self.get_metadata_modifications()
|
metadata_mods = self.get_metadata_modifications()
|
||||||
self.settings_manager.update_metadata(metadata_mods)
|
self.settings_manager.update_metadata(metadata_mods)
|
||||||
self.logger.info("Updated metadata with agents configuration")
|
self.logger.info("Updated metadata with agents configuration")
|
||||||
|
|
||||||
# Add component registration
|
# Add component registration
|
||||||
self.settings_manager.add_component_registration("agents", {
|
self.settings_manager.add_component_registration(
|
||||||
"version": __version__,
|
"agents",
|
||||||
"category": "agents",
|
{
|
||||||
"agents_count": len(self.component_files),
|
"version": __version__,
|
||||||
"agents_list": self.component_files
|
"category": "agents",
|
||||||
})
|
"agents_count": len(self.component_files),
|
||||||
|
"agents_list": self.component_files,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
self.logger.info("Registered agents component in metadata")
|
self.logger.info("Registered agents component in metadata")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.error(f"Failed to complete agents post-install: {e}")
|
self.logger.error(f"Failed to complete agents post-install: {e}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def uninstall(self) -> bool:
|
def uninstall(self) -> bool:
|
||||||
"""Uninstall agents component"""
|
"""Uninstall agents component"""
|
||||||
try:
|
try:
|
||||||
self.logger.info("Uninstalling SuperClaude agents component...")
|
self.logger.info("Uninstalling SuperClaude agents component...")
|
||||||
|
|
||||||
# Remove agent files
|
# Remove agent files
|
||||||
removed_count = 0
|
removed_count = 0
|
||||||
for filename in self.component_files:
|
for filename in self.component_files:
|
||||||
@ -91,15 +96,17 @@ class AgentsComponent(Component):
|
|||||||
self.logger.debug(f"Removed agent: {filename}")
|
self.logger.debug(f"Removed agent: {filename}")
|
||||||
else:
|
else:
|
||||||
self.logger.warning(f"Could not remove agent: {filename}")
|
self.logger.warning(f"Could not remove agent: {filename}")
|
||||||
|
|
||||||
# Remove agents directory if empty
|
# Remove agents directory if empty
|
||||||
try:
|
try:
|
||||||
if self.install_component_subdir.exists() and not any(self.install_component_subdir.iterdir()):
|
if self.install_component_subdir.exists() and not any(
|
||||||
|
self.install_component_subdir.iterdir()
|
||||||
|
):
|
||||||
self.install_component_subdir.rmdir()
|
self.install_component_subdir.rmdir()
|
||||||
self.logger.debug("Removed empty agents directory")
|
self.logger.debug("Removed empty agents directory")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.warning(f"Could not remove agents directory: {e}")
|
self.logger.warning(f"Could not remove agents directory: {e}")
|
||||||
|
|
||||||
# Update metadata to remove agents component
|
# Update metadata to remove agents component
|
||||||
try:
|
try:
|
||||||
if self.settings_manager.is_component_installed("agents"):
|
if self.settings_manager.is_component_installed("agents"):
|
||||||
@ -107,33 +114,39 @@ class AgentsComponent(Component):
|
|||||||
self.logger.info("Removed agents component from metadata")
|
self.logger.info("Removed agents component from metadata")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.warning(f"Could not update metadata: {e}")
|
self.logger.warning(f"Could not update metadata: {e}")
|
||||||
|
|
||||||
self.logger.success(f"Agents component uninstalled ({removed_count} agents removed)")
|
self.logger.success(
|
||||||
|
f"Agents component uninstalled ({removed_count} agents removed)"
|
||||||
|
)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.exception(f"Unexpected error during agents uninstallation: {e}")
|
self.logger.exception(f"Unexpected error during agents uninstallation: {e}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def get_dependencies(self) -> List[str]:
|
def get_dependencies(self) -> List[str]:
|
||||||
"""Get component dependencies"""
|
"""Get component dependencies"""
|
||||||
return ["core"]
|
return ["core"]
|
||||||
|
|
||||||
def update(self, config: Dict[str, Any]) -> bool:
|
def update(self, config: Dict[str, Any]) -> bool:
|
||||||
"""Update agents component"""
|
"""Update agents component"""
|
||||||
try:
|
try:
|
||||||
self.logger.info("Updating SuperClaude agents component...")
|
self.logger.info("Updating SuperClaude agents component...")
|
||||||
|
|
||||||
# Check current version
|
# Check current version
|
||||||
current_version = self.settings_manager.get_component_version("agents")
|
current_version = self.settings_manager.get_component_version("agents")
|
||||||
target_version = self.get_metadata()["version"]
|
target_version = self.get_metadata()["version"]
|
||||||
|
|
||||||
if current_version == target_version:
|
if current_version == target_version:
|
||||||
self.logger.info(f"Agents component already at version {target_version}")
|
self.logger.info(
|
||||||
|
f"Agents component already at version {target_version}"
|
||||||
|
)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
self.logger.info(f"Updating agents component from {current_version} to {target_version}")
|
self.logger.info(
|
||||||
|
f"Updating agents component from {current_version} to {target_version}"
|
||||||
|
)
|
||||||
|
|
||||||
# Create backup of existing agents
|
# Create backup of existing agents
|
||||||
backup_files = []
|
backup_files = []
|
||||||
for filename in self.component_files:
|
for filename in self.component_files:
|
||||||
@ -143,49 +156,54 @@ class AgentsComponent(Component):
|
|||||||
if backup_path:
|
if backup_path:
|
||||||
backup_files.append(backup_path)
|
backup_files.append(backup_path)
|
||||||
self.logger.debug(f"Backed up agent: {filename}")
|
self.logger.debug(f"Backed up agent: {filename}")
|
||||||
|
|
||||||
# Perform installation (will overwrite existing files)
|
# Perform installation (will overwrite existing files)
|
||||||
if self._install(config):
|
if self._install(config):
|
||||||
self.logger.success(f"Agents component updated to version {target_version}")
|
self.logger.success(
|
||||||
|
f"Agents component updated to version {target_version}"
|
||||||
|
)
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
# Restore backups on failure
|
# Restore backups on failure
|
||||||
self.logger.error("Agents update failed, restoring backups...")
|
self.logger.error("Agents update failed, restoring backups...")
|
||||||
for backup_path in backup_files:
|
for backup_path in backup_files:
|
||||||
try:
|
try:
|
||||||
original_path = self.install_component_subdir / backup_path.name.replace('.backup', '')
|
original_path = (
|
||||||
|
self.install_component_subdir
|
||||||
|
/ backup_path.name.replace(".backup", "")
|
||||||
|
)
|
||||||
self.file_manager.copy_file(backup_path, original_path)
|
self.file_manager.copy_file(backup_path, original_path)
|
||||||
self.logger.debug(f"Restored {original_path.name}")
|
self.logger.debug(f"Restored {original_path.name}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.warning(f"Could not restore {backup_path}: {e}")
|
self.logger.warning(f"Could not restore {backup_path}: {e}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.exception(f"Unexpected error during agents update: {e}")
|
self.logger.exception(f"Unexpected error during agents update: {e}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def _get_source_dir(self) -> Path:
|
def _get_source_dir(self) -> Path:
|
||||||
"""Get source directory for agent files"""
|
"""Get source directory for agent files"""
|
||||||
# Assume we're in SuperClaude/setup/components/agents.py
|
# Assume we're in superclaude/setup/components/agents.py
|
||||||
# and agent files are in SuperClaude/SuperClaude/Agents/
|
# and agent files are in superclaude/superclaude/Agents/
|
||||||
project_root = Path(__file__).parent.parent.parent
|
project_root = Path(__file__).parent.parent.parent
|
||||||
return project_root / "SuperClaude" / "Agents"
|
return project_root / "superclaude" / "agents"
|
||||||
|
|
||||||
def get_size_estimate(self) -> int:
|
def get_size_estimate(self) -> int:
|
||||||
"""Get estimated installation size"""
|
"""Get estimated installation size"""
|
||||||
total_size = 0
|
total_size = 0
|
||||||
source_dir = self._get_source_dir()
|
source_dir = self._get_source_dir()
|
||||||
|
|
||||||
for filename in self.component_files:
|
for filename in self.component_files:
|
||||||
file_path = source_dir / filename
|
file_path = source_dir / filename
|
||||||
if file_path.exists():
|
if file_path.exists():
|
||||||
total_size += file_path.stat().st_size
|
total_size += file_path.stat().st_size
|
||||||
|
|
||||||
# Add overhead for directories and metadata
|
# Add overhead for directories and metadata
|
||||||
total_size += 5120 # ~5KB overhead
|
total_size += 5120 # ~5KB overhead
|
||||||
|
|
||||||
return total_size
|
return total_size
|
||||||
|
|
||||||
def get_installation_summary(self) -> Dict[str, Any]:
|
def get_installation_summary(self) -> Dict[str, Any]:
|
||||||
"""Get installation summary"""
|
"""Get installation summary"""
|
||||||
return {
|
return {
|
||||||
@ -195,46 +213,48 @@ class AgentsComponent(Component):
|
|||||||
"agent_files": self.component_files,
|
"agent_files": self.component_files,
|
||||||
"estimated_size": self.get_size_estimate(),
|
"estimated_size": self.get_size_estimate(),
|
||||||
"install_directory": str(self.install_component_subdir),
|
"install_directory": str(self.install_component_subdir),
|
||||||
"dependencies": self.get_dependencies()
|
"dependencies": self.get_dependencies(),
|
||||||
}
|
}
|
||||||
|
|
||||||
def validate_installation(self) -> Tuple[bool, List[str]]:
|
def validate_installation(self) -> Tuple[bool, List[str]]:
|
||||||
"""Validate that agents component is correctly installed"""
|
"""Validate that agents component is correctly installed"""
|
||||||
errors = []
|
errors = []
|
||||||
|
|
||||||
# Check if agents directory exists
|
# Check if agents directory exists
|
||||||
if not self.install_component_subdir.exists():
|
if not self.install_component_subdir.exists():
|
||||||
errors.append(f"Agents directory not found: {self.install_component_subdir}")
|
errors.append(
|
||||||
|
f"Agents directory not found: {self.install_component_subdir}"
|
||||||
|
)
|
||||||
return False, errors
|
return False, errors
|
||||||
|
|
||||||
# Check if all agent files exist
|
# Check if all agent files exist
|
||||||
missing_agents = []
|
missing_agents = []
|
||||||
for filename in self.component_files:
|
for filename in self.component_files:
|
||||||
agent_path = self.install_component_subdir / filename
|
agent_path = self.install_component_subdir / filename
|
||||||
if not agent_path.exists():
|
if not agent_path.exists():
|
||||||
missing_agents.append(filename)
|
missing_agents.append(filename)
|
||||||
|
|
||||||
if missing_agents:
|
if missing_agents:
|
||||||
errors.append(f"Missing agent files: {missing_agents}")
|
errors.append(f"Missing agent files: {missing_agents}")
|
||||||
|
|
||||||
# Check version in metadata
|
# Check version in metadata
|
||||||
if not self.get_installed_version():
|
if not self.get_installed_version():
|
||||||
errors.append("Agents component not registered in metadata")
|
errors.append("Agents component not registered in metadata")
|
||||||
|
|
||||||
# Check if at least some standard agents are present
|
# Check if at least some standard agents are present
|
||||||
expected_agents = [
|
expected_agents = [
|
||||||
"system-architect.md",
|
"system-architect.md",
|
||||||
"frontend-architect.md",
|
"frontend-architect.md",
|
||||||
"backend-architect.md",
|
"backend-architect.md",
|
||||||
"security-engineer.md"
|
"security-engineer.md",
|
||||||
]
|
]
|
||||||
|
|
||||||
missing_core_agents = []
|
missing_core_agents = []
|
||||||
for agent in expected_agents:
|
for agent in expected_agents:
|
||||||
if agent not in self.component_files:
|
if agent not in self.component_files:
|
||||||
missing_core_agents.append(agent)
|
missing_core_agents.append(agent)
|
||||||
|
|
||||||
if missing_core_agents:
|
if missing_core_agents:
|
||||||
errors.append(f"Missing core agent files: {missing_core_agents}")
|
errors.append(f"Missing core agent files: {missing_core_agents}")
|
||||||
|
|
||||||
return len(errors) == 0, errors
|
return len(errors) == 0, errors
|
||||||
|
|||||||
@ -8,22 +8,23 @@ from pathlib import Path
|
|||||||
from ..core.base import Component
|
from ..core.base import Component
|
||||||
from setup import __version__
|
from setup import __version__
|
||||||
|
|
||||||
|
|
||||||
class CommandsComponent(Component):
|
class CommandsComponent(Component):
|
||||||
"""SuperClaude slash commands component"""
|
"""SuperClaude slash commands component"""
|
||||||
|
|
||||||
def __init__(self, install_dir: Optional[Path] = None):
|
def __init__(self, install_dir: Optional[Path] = None):
|
||||||
"""Initialize commands component"""
|
"""Initialize commands component"""
|
||||||
super().__init__(install_dir, Path("commands/sc"))
|
super().__init__(install_dir, Path("commands/sc"))
|
||||||
|
|
||||||
def get_metadata(self) -> Dict[str, str]:
|
def get_metadata(self) -> Dict[str, str]:
|
||||||
"""Get component metadata"""
|
"""Get component metadata"""
|
||||||
return {
|
return {
|
||||||
"name": "commands",
|
"name": "commands",
|
||||||
"version": __version__,
|
"version": __version__,
|
||||||
"description": "SuperClaude slash command definitions",
|
"description": "SuperClaude slash command definitions",
|
||||||
"category": "commands"
|
"category": "commands",
|
||||||
}
|
}
|
||||||
|
|
||||||
def get_metadata_modifications(self) -> Dict[str, Any]:
|
def get_metadata_modifications(self) -> Dict[str, Any]:
|
||||||
"""Get metadata modifications for commands component"""
|
"""Get metadata modifications for commands component"""
|
||||||
return {
|
return {
|
||||||
@ -31,16 +32,12 @@ class CommandsComponent(Component):
|
|||||||
"commands": {
|
"commands": {
|
||||||
"version": __version__,
|
"version": __version__,
|
||||||
"installed": True,
|
"installed": True,
|
||||||
"files_count": len(self.component_files)
|
"files_count": len(self.component_files),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"commands": {
|
"commands": {"enabled": True, "version": __version__, "auto_update": False},
|
||||||
"enabled": True,
|
|
||||||
"version": __version__,
|
|
||||||
"auto_update": False
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def _install(self, config: Dict[str, Any]) -> bool:
|
def _install(self, config: Dict[str, Any]) -> bool:
|
||||||
"""Install commands component"""
|
"""Install commands component"""
|
||||||
self.logger.info("Installing SuperClaude command definitions...")
|
self.logger.info("Installing SuperClaude command definitions...")
|
||||||
@ -48,7 +45,7 @@ class CommandsComponent(Component):
|
|||||||
# Check for and migrate existing commands from old location
|
# Check for and migrate existing commands from old location
|
||||||
self._migrate_existing_commands()
|
self._migrate_existing_commands()
|
||||||
|
|
||||||
return super()._install(config);
|
return super()._install(config)
|
||||||
|
|
||||||
def _post_install(self) -> bool:
|
def _post_install(self) -> bool:
|
||||||
# Update metadata
|
# Update metadata
|
||||||
@ -58,27 +55,30 @@ class CommandsComponent(Component):
|
|||||||
self.logger.info("Updated metadata with commands configuration")
|
self.logger.info("Updated metadata with commands configuration")
|
||||||
|
|
||||||
# Add component registration to metadata
|
# Add component registration to metadata
|
||||||
self.settings_manager.add_component_registration("commands", {
|
self.settings_manager.add_component_registration(
|
||||||
"version": __version__,
|
"commands",
|
||||||
"category": "commands",
|
{
|
||||||
"files_count": len(self.component_files)
|
"version": __version__,
|
||||||
})
|
"category": "commands",
|
||||||
|
"files_count": len(self.component_files),
|
||||||
|
},
|
||||||
|
)
|
||||||
self.logger.info("Updated metadata with commands component registration")
|
self.logger.info("Updated metadata with commands component registration")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.error(f"Failed to update metadata: {e}")
|
self.logger.error(f"Failed to update metadata: {e}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def uninstall(self) -> bool:
|
def uninstall(self) -> bool:
|
||||||
"""Uninstall commands component"""
|
"""Uninstall commands component"""
|
||||||
try:
|
try:
|
||||||
self.logger.info("Uninstalling SuperClaude commands component...")
|
self.logger.info("Uninstalling SuperClaude commands component...")
|
||||||
|
|
||||||
# Remove command files from sc subdirectory
|
# Remove command files from sc subdirectory
|
||||||
commands_dir = self.install_dir / "commands" / "sc"
|
commands_dir = self.install_dir / "commands" / "sc"
|
||||||
removed_count = 0
|
removed_count = 0
|
||||||
|
|
||||||
for filename in self.component_files:
|
for filename in self.component_files:
|
||||||
file_path = commands_dir / filename
|
file_path = commands_dir / filename
|
||||||
if self.file_manager.remove_file(file_path):
|
if self.file_manager.remove_file(file_path):
|
||||||
@ -86,11 +86,11 @@ class CommandsComponent(Component):
|
|||||||
self.logger.debug(f"Removed {filename}")
|
self.logger.debug(f"Removed {filename}")
|
||||||
else:
|
else:
|
||||||
self.logger.warning(f"Could not remove {filename}")
|
self.logger.warning(f"Could not remove {filename}")
|
||||||
|
|
||||||
# Also check and remove any old commands in root commands directory
|
# Also check and remove any old commands in root commands directory
|
||||||
old_commands_dir = self.install_dir / "commands"
|
old_commands_dir = self.install_dir / "commands"
|
||||||
old_removed_count = 0
|
old_removed_count = 0
|
||||||
|
|
||||||
for filename in self.component_files:
|
for filename in self.component_files:
|
||||||
old_file_path = old_commands_dir / filename
|
old_file_path = old_commands_dir / filename
|
||||||
if old_file_path.exists() and old_file_path.is_file():
|
if old_file_path.exists() and old_file_path.is_file():
|
||||||
@ -99,12 +99,14 @@ class CommandsComponent(Component):
|
|||||||
self.logger.debug(f"Removed old {filename}")
|
self.logger.debug(f"Removed old {filename}")
|
||||||
else:
|
else:
|
||||||
self.logger.warning(f"Could not remove old {filename}")
|
self.logger.warning(f"Could not remove old {filename}")
|
||||||
|
|
||||||
if old_removed_count > 0:
|
if old_removed_count > 0:
|
||||||
self.logger.info(f"Also removed {old_removed_count} commands from old location")
|
self.logger.info(
|
||||||
|
f"Also removed {old_removed_count} commands from old location"
|
||||||
|
)
|
||||||
|
|
||||||
removed_count += old_removed_count
|
removed_count += old_removed_count
|
||||||
|
|
||||||
# Remove sc subdirectory if empty
|
# Remove sc subdirectory if empty
|
||||||
try:
|
try:
|
||||||
if commands_dir.exists():
|
if commands_dir.exists():
|
||||||
@ -112,17 +114,19 @@ class CommandsComponent(Component):
|
|||||||
if not remaining_files:
|
if not remaining_files:
|
||||||
commands_dir.rmdir()
|
commands_dir.rmdir()
|
||||||
self.logger.debug("Removed empty sc commands directory")
|
self.logger.debug("Removed empty sc commands directory")
|
||||||
|
|
||||||
# Also remove parent commands directory if empty
|
# Also remove parent commands directory if empty
|
||||||
parent_commands_dir = self.install_dir / "commands"
|
parent_commands_dir = self.install_dir / "commands"
|
||||||
if parent_commands_dir.exists():
|
if parent_commands_dir.exists():
|
||||||
remaining_files = list(parent_commands_dir.iterdir())
|
remaining_files = list(parent_commands_dir.iterdir())
|
||||||
if not remaining_files:
|
if not remaining_files:
|
||||||
parent_commands_dir.rmdir()
|
parent_commands_dir.rmdir()
|
||||||
self.logger.debug("Removed empty parent commands directory")
|
self.logger.debug(
|
||||||
|
"Removed empty parent commands directory"
|
||||||
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.warning(f"Could not remove commands directory: {e}")
|
self.logger.warning(f"Could not remove commands directory: {e}")
|
||||||
|
|
||||||
# Update metadata to remove commands component
|
# Update metadata to remove commands component
|
||||||
try:
|
try:
|
||||||
if self.settings_manager.is_component_installed("commands"):
|
if self.settings_manager.is_component_installed("commands"):
|
||||||
@ -135,37 +139,45 @@ class CommandsComponent(Component):
|
|||||||
self.logger.info("Removed commands component from metadata")
|
self.logger.info("Removed commands component from metadata")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.warning(f"Could not update metadata: {e}")
|
self.logger.warning(f"Could not update metadata: {e}")
|
||||||
|
|
||||||
self.logger.success(f"Commands component uninstalled ({removed_count} files removed)")
|
self.logger.success(
|
||||||
|
f"Commands component uninstalled ({removed_count} files removed)"
|
||||||
|
)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.exception(f"Unexpected error during commands uninstallation: {e}")
|
self.logger.exception(
|
||||||
|
f"Unexpected error during commands uninstallation: {e}"
|
||||||
|
)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def get_dependencies(self) -> List[str]:
|
def get_dependencies(self) -> List[str]:
|
||||||
"""Get dependencies"""
|
"""Get dependencies"""
|
||||||
return ["core"]
|
return ["core"]
|
||||||
|
|
||||||
def update(self, config: Dict[str, Any]) -> bool:
|
def update(self, config: Dict[str, Any]) -> bool:
|
||||||
"""Update commands component"""
|
"""Update commands component"""
|
||||||
try:
|
try:
|
||||||
self.logger.info("Updating SuperClaude commands component...")
|
self.logger.info("Updating SuperClaude commands component...")
|
||||||
|
|
||||||
# Check current version
|
# Check current version
|
||||||
current_version = self.settings_manager.get_component_version("commands")
|
current_version = self.settings_manager.get_component_version("commands")
|
||||||
target_version = self.get_metadata()["version"]
|
target_version = self.get_metadata()["version"]
|
||||||
|
|
||||||
if current_version == target_version:
|
if current_version == target_version:
|
||||||
self.logger.info(f"Commands component already at version {target_version}")
|
self.logger.info(
|
||||||
|
f"Commands component already at version {target_version}"
|
||||||
|
)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
self.logger.info(f"Updating commands component from {current_version} to {target_version}")
|
self.logger.info(
|
||||||
|
f"Updating commands component from {current_version} to {target_version}"
|
||||||
|
)
|
||||||
|
|
||||||
# Create backup of existing command files
|
# Create backup of existing command files
|
||||||
commands_dir = self.install_dir / "commands" / "sc"
|
commands_dir = self.install_dir / "commands" / "sc"
|
||||||
backup_files = []
|
backup_files = []
|
||||||
|
|
||||||
if commands_dir.exists():
|
if commands_dir.exists():
|
||||||
for filename in self.component_files:
|
for filename in self.component_files:
|
||||||
file_path = commands_dir / filename
|
file_path = commands_dir / filename
|
||||||
@ -174,10 +186,10 @@ class CommandsComponent(Component):
|
|||||||
if backup_path:
|
if backup_path:
|
||||||
backup_files.append(backup_path)
|
backup_files.append(backup_path)
|
||||||
self.logger.debug(f"Backed up {filename}")
|
self.logger.debug(f"Backed up {filename}")
|
||||||
|
|
||||||
# Perform installation (overwrites existing files)
|
# Perform installation (overwrites existing files)
|
||||||
success = self.install(config)
|
success = self.install(config)
|
||||||
|
|
||||||
if success:
|
if success:
|
||||||
# Remove backup files on successful update
|
# Remove backup files on successful update
|
||||||
for backup_path in backup_files:
|
for backup_path in backup_files:
|
||||||
@ -185,35 +197,37 @@ class CommandsComponent(Component):
|
|||||||
backup_path.unlink()
|
backup_path.unlink()
|
||||||
except Exception:
|
except Exception:
|
||||||
pass # Ignore cleanup errors
|
pass # Ignore cleanup errors
|
||||||
|
|
||||||
self.logger.success(f"Commands component updated to version {target_version}")
|
self.logger.success(
|
||||||
|
f"Commands component updated to version {target_version}"
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
# Restore from backup on failure
|
# Restore from backup on failure
|
||||||
self.logger.warning("Update failed, restoring from backup...")
|
self.logger.warning("Update failed, restoring from backup...")
|
||||||
for backup_path in backup_files:
|
for backup_path in backup_files:
|
||||||
try:
|
try:
|
||||||
original_path = backup_path.with_suffix('')
|
original_path = backup_path.with_suffix("")
|
||||||
backup_path.rename(original_path)
|
backup_path.rename(original_path)
|
||||||
self.logger.debug(f"Restored {original_path.name}")
|
self.logger.debug(f"Restored {original_path.name}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.error(f"Could not restore {backup_path}: {e}")
|
self.logger.error(f"Could not restore {backup_path}: {e}")
|
||||||
|
|
||||||
return success
|
return success
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.exception(f"Unexpected error during commands update: {e}")
|
self.logger.exception(f"Unexpected error during commands update: {e}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def validate_installation(self) -> Tuple[bool, List[str]]:
|
def validate_installation(self) -> Tuple[bool, List[str]]:
|
||||||
"""Validate commands component installation"""
|
"""Validate commands component installation"""
|
||||||
errors = []
|
errors = []
|
||||||
|
|
||||||
# Check if sc commands directory exists
|
# Check if sc commands directory exists
|
||||||
commands_dir = self.install_dir / "commands" / "sc"
|
commands_dir = self.install_dir / "commands" / "sc"
|
||||||
if not commands_dir.exists():
|
if not commands_dir.exists():
|
||||||
errors.append("SC commands directory not found")
|
errors.append("SC commands directory not found")
|
||||||
return False, errors
|
return False, errors
|
||||||
|
|
||||||
# Check if all command files exist
|
# Check if all command files exist
|
||||||
for filename in self.component_files:
|
for filename in self.component_files:
|
||||||
file_path = commands_dir / filename
|
file_path = commands_dir / filename
|
||||||
@ -221,7 +235,7 @@ class CommandsComponent(Component):
|
|||||||
errors.append(f"Missing command file: {filename}")
|
errors.append(f"Missing command file: {filename}")
|
||||||
elif not file_path.is_file():
|
elif not file_path.is_file():
|
||||||
errors.append(f"Command file is not a regular file: {filename}")
|
errors.append(f"Command file is not a regular file: {filename}")
|
||||||
|
|
||||||
# Check metadata registration
|
# Check metadata registration
|
||||||
if not self.settings_manager.is_component_installed("commands"):
|
if not self.settings_manager.is_component_installed("commands"):
|
||||||
errors.append("Commands component not registered in metadata")
|
errors.append("Commands component not registered in metadata")
|
||||||
@ -230,32 +244,34 @@ class CommandsComponent(Component):
|
|||||||
installed_version = self.settings_manager.get_component_version("commands")
|
installed_version = self.settings_manager.get_component_version("commands")
|
||||||
expected_version = self.get_metadata()["version"]
|
expected_version = self.get_metadata()["version"]
|
||||||
if installed_version != expected_version:
|
if installed_version != expected_version:
|
||||||
errors.append(f"Version mismatch: installed {installed_version}, expected {expected_version}")
|
errors.append(
|
||||||
|
f"Version mismatch: installed {installed_version}, expected {expected_version}"
|
||||||
|
)
|
||||||
|
|
||||||
return len(errors) == 0, errors
|
return len(errors) == 0, errors
|
||||||
|
|
||||||
def _get_source_dir(self) -> Path:
|
def _get_source_dir(self) -> Path:
|
||||||
"""Get source directory for command files"""
|
"""Get source directory for command files"""
|
||||||
# Assume we're in SuperClaude/setup/components/commands.py
|
# Assume we're in superclaude/setup/components/commands.py
|
||||||
# and command files are in SuperClaude/SuperClaude/Commands/
|
# and command files are in superclaude/superclaude/Commands/
|
||||||
project_root = Path(__file__).parent.parent.parent
|
project_root = Path(__file__).parent.parent.parent
|
||||||
return project_root / "SuperClaude" / "Commands"
|
return project_root / "superclaude" / "commands"
|
||||||
|
|
||||||
def get_size_estimate(self) -> int:
|
def get_size_estimate(self) -> int:
|
||||||
"""Get estimated installation size"""
|
"""Get estimated installation size"""
|
||||||
total_size = 0
|
total_size = 0
|
||||||
source_dir = self._get_source_dir()
|
source_dir = self._get_source_dir()
|
||||||
|
|
||||||
for filename in self.component_files:
|
for filename in self.component_files:
|
||||||
file_path = source_dir / filename
|
file_path = source_dir / filename
|
||||||
if file_path.exists():
|
if file_path.exists():
|
||||||
total_size += file_path.stat().st_size
|
total_size += file_path.stat().st_size
|
||||||
|
|
||||||
# Add overhead for directory and settings
|
# Add overhead for directory and settings
|
||||||
total_size += 5120 # ~5KB overhead
|
total_size += 5120 # ~5KB overhead
|
||||||
|
|
||||||
return total_size
|
return total_size
|
||||||
|
|
||||||
def get_installation_summary(self) -> Dict[str, Any]:
|
def get_installation_summary(self) -> Dict[str, Any]:
|
||||||
"""Get installation summary"""
|
"""Get installation summary"""
|
||||||
return {
|
return {
|
||||||
@ -265,66 +281,84 @@ class CommandsComponent(Component):
|
|||||||
"command_files": self.component_files,
|
"command_files": self.component_files,
|
||||||
"estimated_size": self.get_size_estimate(),
|
"estimated_size": self.get_size_estimate(),
|
||||||
"install_directory": str(self.install_dir / "commands" / "sc"),
|
"install_directory": str(self.install_dir / "commands" / "sc"),
|
||||||
"dependencies": self.get_dependencies()
|
"dependencies": self.get_dependencies(),
|
||||||
}
|
}
|
||||||
|
|
||||||
def _migrate_existing_commands(self) -> None:
|
def _migrate_existing_commands(self) -> None:
|
||||||
"""Migrate existing commands from old location to new sc subdirectory"""
|
"""Migrate existing commands from old location to new sc subdirectory"""
|
||||||
try:
|
try:
|
||||||
old_commands_dir = self.install_dir / "commands"
|
old_commands_dir = self.install_dir / "commands"
|
||||||
new_commands_dir = self.install_dir / "commands" / "sc"
|
new_commands_dir = self.install_dir / "commands" / "sc"
|
||||||
|
|
||||||
# Check if old commands exist in root commands directory
|
# Check if old commands exist in root commands directory
|
||||||
migrated_count = 0
|
migrated_count = 0
|
||||||
commands_to_migrate = []
|
commands_to_migrate = []
|
||||||
|
|
||||||
if old_commands_dir.exists():
|
if old_commands_dir.exists():
|
||||||
for filename in self.component_files:
|
for filename in self.component_files:
|
||||||
old_file_path = old_commands_dir / filename
|
old_file_path = old_commands_dir / filename
|
||||||
if old_file_path.exists() and old_file_path.is_file():
|
if old_file_path.exists() and old_file_path.is_file():
|
||||||
commands_to_migrate.append(filename)
|
commands_to_migrate.append(filename)
|
||||||
|
|
||||||
if commands_to_migrate:
|
if commands_to_migrate:
|
||||||
self.logger.info(f"Found {len(commands_to_migrate)} existing commands to migrate to sc/ subdirectory")
|
self.logger.info(
|
||||||
|
f"Found {len(commands_to_migrate)} existing commands to migrate to sc/ subdirectory"
|
||||||
|
)
|
||||||
|
|
||||||
# Ensure new directory exists
|
# Ensure new directory exists
|
||||||
if not self.file_manager.ensure_directory(new_commands_dir):
|
if not self.file_manager.ensure_directory(new_commands_dir):
|
||||||
self.logger.error(f"Could not create sc commands directory: {new_commands_dir}")
|
self.logger.error(
|
||||||
|
f"Could not create sc commands directory: {new_commands_dir}"
|
||||||
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
# Move files from old to new location
|
# Move files from old to new location
|
||||||
for filename in commands_to_migrate:
|
for filename in commands_to_migrate:
|
||||||
old_file_path = old_commands_dir / filename
|
old_file_path = old_commands_dir / filename
|
||||||
new_file_path = new_commands_dir / filename
|
new_file_path = new_commands_dir / filename
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Copy file to new location
|
# Copy file to new location
|
||||||
if self.file_manager.copy_file(old_file_path, new_file_path):
|
if self.file_manager.copy_file(old_file_path, new_file_path):
|
||||||
# Remove old file
|
# Remove old file
|
||||||
if self.file_manager.remove_file(old_file_path):
|
if self.file_manager.remove_file(old_file_path):
|
||||||
migrated_count += 1
|
migrated_count += 1
|
||||||
self.logger.debug(f"Migrated {filename} to sc/ subdirectory")
|
self.logger.debug(
|
||||||
|
f"Migrated {filename} to sc/ subdirectory"
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
self.logger.warning(f"Could not remove old {filename}")
|
self.logger.warning(f"Could not remove old {filename}")
|
||||||
else:
|
else:
|
||||||
self.logger.warning(f"Could not copy {filename} to sc/ subdirectory")
|
self.logger.warning(
|
||||||
|
f"Could not copy {filename} to sc/ subdirectory"
|
||||||
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.warning(f"Error migrating {filename}: {e}")
|
self.logger.warning(f"Error migrating {filename}: {e}")
|
||||||
|
|
||||||
if migrated_count > 0:
|
if migrated_count > 0:
|
||||||
self.logger.success(f"Successfully migrated {migrated_count} commands to /sc: namespace")
|
self.logger.success(
|
||||||
self.logger.info("Commands are now available as /sc:analyze, /sc:build, etc.")
|
f"Successfully migrated {migrated_count} commands to /sc: namespace"
|
||||||
|
)
|
||||||
|
self.logger.info(
|
||||||
|
"Commands are now available as /sc:analyze, /sc:build, etc."
|
||||||
|
)
|
||||||
|
|
||||||
# Try to remove old commands directory if empty
|
# Try to remove old commands directory if empty
|
||||||
try:
|
try:
|
||||||
if old_commands_dir.exists():
|
if old_commands_dir.exists():
|
||||||
remaining_files = [f for f in old_commands_dir.iterdir() if f.is_file()]
|
remaining_files = [
|
||||||
|
f for f in old_commands_dir.iterdir() if f.is_file()
|
||||||
|
]
|
||||||
if not remaining_files:
|
if not remaining_files:
|
||||||
# Only remove if no user files remain
|
# Only remove if no user files remain
|
||||||
old_commands_dir.rmdir()
|
old_commands_dir.rmdir()
|
||||||
self.logger.debug("Removed empty old commands directory")
|
self.logger.debug(
|
||||||
|
"Removed empty old commands directory"
|
||||||
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.debug(f"Could not remove old commands directory: {e}")
|
self.logger.debug(
|
||||||
|
f"Could not remove old commands directory: {e}"
|
||||||
|
)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.warning(f"Error during command migration: {e}")
|
self.logger.warning(f"Error during command migration: {e}")
|
||||||
|
|||||||
@ -10,45 +10,46 @@ from ..core.base import Component
|
|||||||
from ..services.claude_md import CLAUDEMdService
|
from ..services.claude_md import CLAUDEMdService
|
||||||
from setup import __version__
|
from setup import __version__
|
||||||
|
|
||||||
|
|
||||||
class CoreComponent(Component):
|
class CoreComponent(Component):
|
||||||
"""Core SuperClaude framework files component"""
|
"""Core SuperClaude framework files component"""
|
||||||
|
|
||||||
def __init__(self, install_dir: Optional[Path] = None):
|
def __init__(self, install_dir: Optional[Path] = None):
|
||||||
"""Initialize core component"""
|
"""Initialize core component"""
|
||||||
super().__init__(install_dir)
|
super().__init__(install_dir)
|
||||||
|
|
||||||
def get_metadata(self) -> Dict[str, str]:
|
def get_metadata(self) -> Dict[str, str]:
|
||||||
"""Get component metadata"""
|
"""Get component metadata"""
|
||||||
return {
|
return {
|
||||||
"name": "core",
|
"name": "core",
|
||||||
"version": __version__,
|
"version": __version__,
|
||||||
"description": "SuperClaude framework documentation and core files",
|
"description": "SuperClaude framework documentation and core files",
|
||||||
"category": "core"
|
"category": "core",
|
||||||
}
|
}
|
||||||
|
|
||||||
def get_metadata_modifications(self) -> Dict[str, Any]:
|
def get_metadata_modifications(self) -> Dict[str, Any]:
|
||||||
"""Get metadata modifications for SuperClaude"""
|
"""Get metadata modifications for SuperClaude"""
|
||||||
return {
|
return {
|
||||||
"framework": {
|
"framework": {
|
||||||
"version": __version__,
|
"version": __version__,
|
||||||
"name": "SuperClaude",
|
"name": "superclaude",
|
||||||
"description": "AI-enhanced development framework for Claude Code",
|
"description": "AI-enhanced development framework for Claude Code",
|
||||||
"installation_type": "global",
|
"installation_type": "global",
|
||||||
"components": ["core"]
|
"components": ["core"],
|
||||||
},
|
},
|
||||||
"superclaude": {
|
"superclaude": {
|
||||||
"enabled": True,
|
"enabled": True,
|
||||||
"version": __version__,
|
"version": __version__,
|
||||||
"profile": "default",
|
"profile": "default",
|
||||||
"auto_update": False
|
"auto_update": False,
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
def _install(self, config: Dict[str, Any]) -> bool:
|
def _install(self, config: Dict[str, Any]) -> bool:
|
||||||
"""Install core component"""
|
"""Install core component"""
|
||||||
self.logger.info("Installing SuperClaude core framework files...")
|
self.logger.info("Installing SuperClaude core framework files...")
|
||||||
|
|
||||||
return super()._install(config);
|
return super()._install(config)
|
||||||
|
|
||||||
def _post_install(self) -> bool:
|
def _post_install(self) -> bool:
|
||||||
# Create or update metadata
|
# Create or update metadata
|
||||||
@ -56,19 +57,24 @@ class CoreComponent(Component):
|
|||||||
metadata_mods = self.get_metadata_modifications()
|
metadata_mods = self.get_metadata_modifications()
|
||||||
self.settings_manager.update_metadata(metadata_mods)
|
self.settings_manager.update_metadata(metadata_mods)
|
||||||
self.logger.info("Updated metadata with framework configuration")
|
self.logger.info("Updated metadata with framework configuration")
|
||||||
|
|
||||||
# Add component registration to metadata
|
# Add component registration to metadata
|
||||||
self.settings_manager.add_component_registration("core", {
|
self.settings_manager.add_component_registration(
|
||||||
"version": __version__,
|
"core",
|
||||||
"category": "core",
|
{
|
||||||
"files_count": len(self.component_files)
|
"version": __version__,
|
||||||
})
|
"category": "core",
|
||||||
|
"files_count": len(self.component_files),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
self.logger.info("Updated metadata with core component registration")
|
self.logger.info("Updated metadata with core component registration")
|
||||||
|
|
||||||
# Migrate any existing SuperClaude data from settings.json
|
# Migrate any existing SuperClaude data from settings.json
|
||||||
if self.settings_manager.migrate_superclaude_data():
|
if self.settings_manager.migrate_superclaude_data():
|
||||||
self.logger.info("Migrated existing SuperClaude data from settings.json")
|
self.logger.info(
|
||||||
|
"Migrated existing SuperClaude data from settings.json"
|
||||||
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.error(f"Failed to update metadata: {e}")
|
self.logger.error(f"Failed to update metadata: {e}")
|
||||||
return False
|
return False
|
||||||
@ -79,24 +85,25 @@ class CoreComponent(Component):
|
|||||||
dir_path = self.install_dir / dirname
|
dir_path = self.install_dir / dirname
|
||||||
if not self.file_manager.ensure_directory(dir_path):
|
if not self.file_manager.ensure_directory(dir_path):
|
||||||
self.logger.warning(f"Could not create directory: {dir_path}")
|
self.logger.warning(f"Could not create directory: {dir_path}")
|
||||||
|
|
||||||
# Update CLAUDE.md with core framework imports
|
# Update CLAUDE.md with core framework imports
|
||||||
try:
|
try:
|
||||||
manager = CLAUDEMdService(self.install_dir)
|
manager = CLAUDEMdService(self.install_dir)
|
||||||
manager.add_imports(self.component_files, category="Core Framework")
|
manager.add_imports(self.component_files, category="Core Framework")
|
||||||
self.logger.info("Updated CLAUDE.md with core framework imports")
|
self.logger.info("Updated CLAUDE.md with core framework imports")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.warning(f"Failed to update CLAUDE.md with core framework imports: {e}")
|
self.logger.warning(
|
||||||
|
f"Failed to update CLAUDE.md with core framework imports: {e}"
|
||||||
|
)
|
||||||
# Don't fail the whole installation for this
|
# Don't fail the whole installation for this
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def uninstall(self) -> bool:
|
def uninstall(self) -> bool:
|
||||||
"""Uninstall core component"""
|
"""Uninstall core component"""
|
||||||
try:
|
try:
|
||||||
self.logger.info("Uninstalling SuperClaude core component...")
|
self.logger.info("Uninstalling SuperClaude core component...")
|
||||||
|
|
||||||
# Remove framework files
|
# Remove framework files
|
||||||
removed_count = 0
|
removed_count = 0
|
||||||
for filename in self.component_files:
|
for filename in self.component_files:
|
||||||
@ -106,7 +113,7 @@ class CoreComponent(Component):
|
|||||||
self.logger.debug(f"Removed {filename}")
|
self.logger.debug(f"Removed {filename}")
|
||||||
else:
|
else:
|
||||||
self.logger.warning(f"Could not remove {filename}")
|
self.logger.warning(f"Could not remove {filename}")
|
||||||
|
|
||||||
# Update metadata to remove core component
|
# Update metadata to remove core component
|
||||||
try:
|
try:
|
||||||
if self.settings_manager.is_component_installed("core"):
|
if self.settings_manager.is_component_installed("core"):
|
||||||
@ -121,33 +128,37 @@ class CoreComponent(Component):
|
|||||||
self.logger.info("Removed core component from metadata")
|
self.logger.info("Removed core component from metadata")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.warning(f"Could not update metadata: {e}")
|
self.logger.warning(f"Could not update metadata: {e}")
|
||||||
|
|
||||||
self.logger.success(f"Core component uninstalled ({removed_count} files removed)")
|
self.logger.success(
|
||||||
|
f"Core component uninstalled ({removed_count} files removed)"
|
||||||
|
)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.exception(f"Unexpected error during core uninstallation: {e}")
|
self.logger.exception(f"Unexpected error during core uninstallation: {e}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def get_dependencies(self) -> List[str]:
|
def get_dependencies(self) -> List[str]:
|
||||||
"""Get component dependencies (core has none)"""
|
"""Get component dependencies (core has none)"""
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def update(self, config: Dict[str, Any]) -> bool:
|
def update(self, config: Dict[str, Any]) -> bool:
|
||||||
"""Update core component"""
|
"""Update core component"""
|
||||||
try:
|
try:
|
||||||
self.logger.info("Updating SuperClaude core component...")
|
self.logger.info("Updating SuperClaude core component...")
|
||||||
|
|
||||||
# Check current version
|
# Check current version
|
||||||
current_version = self.settings_manager.get_component_version("core")
|
current_version = self.settings_manager.get_component_version("core")
|
||||||
target_version = self.get_metadata()["version"]
|
target_version = self.get_metadata()["version"]
|
||||||
|
|
||||||
if current_version == target_version:
|
if current_version == target_version:
|
||||||
self.logger.info(f"Core component already at version {target_version}")
|
self.logger.info(f"Core component already at version {target_version}")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
self.logger.info(f"Updating core component from {current_version} to {target_version}")
|
self.logger.info(
|
||||||
|
f"Updating core component from {current_version} to {target_version}"
|
||||||
|
)
|
||||||
|
|
||||||
# Create backup of existing files
|
# Create backup of existing files
|
||||||
backup_files = []
|
backup_files = []
|
||||||
for filename in self.component_files:
|
for filename in self.component_files:
|
||||||
@ -157,10 +168,10 @@ class CoreComponent(Component):
|
|||||||
if backup_path:
|
if backup_path:
|
||||||
backup_files.append(backup_path)
|
backup_files.append(backup_path)
|
||||||
self.logger.debug(f"Backed up {filename}")
|
self.logger.debug(f"Backed up {filename}")
|
||||||
|
|
||||||
# Perform installation (overwrites existing files)
|
# Perform installation (overwrites existing files)
|
||||||
success = self.install(config)
|
success = self.install(config)
|
||||||
|
|
||||||
if success:
|
if success:
|
||||||
# Remove backup files on successful update
|
# Remove backup files on successful update
|
||||||
for backup_path in backup_files:
|
for backup_path in backup_files:
|
||||||
@ -168,29 +179,31 @@ class CoreComponent(Component):
|
|||||||
backup_path.unlink()
|
backup_path.unlink()
|
||||||
except Exception:
|
except Exception:
|
||||||
pass # Ignore cleanup errors
|
pass # Ignore cleanup errors
|
||||||
|
|
||||||
self.logger.success(f"Core component updated to version {target_version}")
|
self.logger.success(
|
||||||
|
f"Core component updated to version {target_version}"
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
# Restore from backup on failure
|
# Restore from backup on failure
|
||||||
self.logger.warning("Update failed, restoring from backup...")
|
self.logger.warning("Update failed, restoring from backup...")
|
||||||
for backup_path in backup_files:
|
for backup_path in backup_files:
|
||||||
try:
|
try:
|
||||||
original_path = backup_path.with_suffix('')
|
original_path = backup_path.with_suffix("")
|
||||||
shutil.move(str(backup_path), str(original_path))
|
shutil.move(str(backup_path), str(original_path))
|
||||||
self.logger.debug(f"Restored {original_path.name}")
|
self.logger.debug(f"Restored {original_path.name}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.error(f"Could not restore {backup_path}: {e}")
|
self.logger.error(f"Could not restore {backup_path}: {e}")
|
||||||
|
|
||||||
return success
|
return success
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.exception(f"Unexpected error during core update: {e}")
|
self.logger.exception(f"Unexpected error during core update: {e}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def validate_installation(self) -> Tuple[bool, List[str]]:
|
def validate_installation(self) -> Tuple[bool, List[str]]:
|
||||||
"""Validate core component installation"""
|
"""Validate core component installation"""
|
||||||
errors = []
|
errors = []
|
||||||
|
|
||||||
# Check if all framework files exist
|
# Check if all framework files exist
|
||||||
for filename in self.component_files:
|
for filename in self.component_files:
|
||||||
file_path = self.install_dir / filename
|
file_path = self.install_dir / filename
|
||||||
@ -198,7 +211,7 @@ class CoreComponent(Component):
|
|||||||
errors.append(f"Missing framework file: {filename}")
|
errors.append(f"Missing framework file: {filename}")
|
||||||
elif not file_path.is_file():
|
elif not file_path.is_file():
|
||||||
errors.append(f"Framework file is not a regular file: {filename}")
|
errors.append(f"Framework file is not a regular file: {filename}")
|
||||||
|
|
||||||
# Check metadata registration
|
# Check metadata registration
|
||||||
if not self.settings_manager.is_component_installed("core"):
|
if not self.settings_manager.is_component_installed("core"):
|
||||||
errors.append("Core component not registered in metadata")
|
errors.append("Core component not registered in metadata")
|
||||||
@ -207,8 +220,10 @@ class CoreComponent(Component):
|
|||||||
installed_version = self.settings_manager.get_component_version("core")
|
installed_version = self.settings_manager.get_component_version("core")
|
||||||
expected_version = self.get_metadata()["version"]
|
expected_version = self.get_metadata()["version"]
|
||||||
if installed_version != expected_version:
|
if installed_version != expected_version:
|
||||||
errors.append(f"Version mismatch: installed {installed_version}, expected {expected_version}")
|
errors.append(
|
||||||
|
f"Version mismatch: installed {installed_version}, expected {expected_version}"
|
||||||
|
)
|
||||||
|
|
||||||
# Check metadata structure
|
# Check metadata structure
|
||||||
try:
|
try:
|
||||||
framework_config = self.settings_manager.get_metadata_setting("framework")
|
framework_config = self.settings_manager.get_metadata_setting("framework")
|
||||||
@ -221,31 +236,31 @@ class CoreComponent(Component):
|
|||||||
errors.append(f"Missing framework.{key} in metadata")
|
errors.append(f"Missing framework.{key} in metadata")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
errors.append(f"Could not validate metadata: {e}")
|
errors.append(f"Could not validate metadata: {e}")
|
||||||
|
|
||||||
return len(errors) == 0, errors
|
return len(errors) == 0, errors
|
||||||
|
|
||||||
def _get_source_dir(self):
|
def _get_source_dir(self):
|
||||||
"""Get source directory for framework files"""
|
"""Get source directory for framework files"""
|
||||||
# Assume we're in SuperClaude/setup/components/core.py
|
# Assume we're in superclaude/setup/components/core.py
|
||||||
# and framework files are in SuperClaude/SuperClaude/Core/
|
# and framework files are in superclaude/superclaude/Core/
|
||||||
project_root = Path(__file__).parent.parent.parent
|
project_root = Path(__file__).parent.parent.parent
|
||||||
return project_root / "SuperClaude" / "Core"
|
return project_root / "superclaude" / "core"
|
||||||
|
|
||||||
def get_size_estimate(self) -> int:
|
def get_size_estimate(self) -> int:
|
||||||
"""Get estimated installation size"""
|
"""Get estimated installation size"""
|
||||||
total_size = 0
|
total_size = 0
|
||||||
source_dir = self._get_source_dir()
|
source_dir = self._get_source_dir()
|
||||||
|
|
||||||
for filename in self.component_files:
|
for filename in self.component_files:
|
||||||
file_path = source_dir / filename
|
file_path = source_dir / filename
|
||||||
if file_path.exists():
|
if file_path.exists():
|
||||||
total_size += file_path.stat().st_size
|
total_size += file_path.stat().st_size
|
||||||
|
|
||||||
# Add overhead for settings.json and directories
|
# Add overhead for settings.json and directories
|
||||||
total_size += 10240 # ~10KB overhead
|
total_size += 10240 # ~10KB overhead
|
||||||
|
|
||||||
return total_size
|
return total_size
|
||||||
|
|
||||||
def get_installation_summary(self) -> Dict[str, Any]:
|
def get_installation_summary(self) -> Dict[str, Any]:
|
||||||
"""Get installation summary"""
|
"""Get installation summary"""
|
||||||
return {
|
return {
|
||||||
@ -255,5 +270,5 @@ class CoreComponent(Component):
|
|||||||
"framework_files": self.component_files,
|
"framework_files": self.component_files,
|
||||||
"estimated_size": self.get_size_estimate(),
|
"estimated_size": self.get_size_estimate(),
|
||||||
"install_directory": str(self.install_dir),
|
"install_directory": str(self.install_dir),
|
||||||
"dependencies": self.get_dependencies()
|
"dependencies": self.get_dependencies(),
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -12,13 +12,13 @@ from ..services.claude_md import CLAUDEMdService
|
|||||||
|
|
||||||
class MCPDocsComponent(Component):
|
class MCPDocsComponent(Component):
|
||||||
"""MCP documentation component - installs docs for selected MCP servers"""
|
"""MCP documentation component - installs docs for selected MCP servers"""
|
||||||
|
|
||||||
def __init__(self, install_dir: Optional[Path] = None):
|
def __init__(self, install_dir: Optional[Path] = None):
|
||||||
"""Initialize MCP docs component"""
|
"""Initialize MCP docs component"""
|
||||||
# Initialize attributes before calling parent constructor
|
# Initialize attributes before calling parent constructor
|
||||||
# because parent calls _discover_component_files() which needs these
|
# because parent calls _discover_component_files() which needs these
|
||||||
self.selected_servers: List[str] = []
|
self.selected_servers: List[str] = []
|
||||||
|
|
||||||
# Map server names to documentation files
|
# Map server names to documentation files
|
||||||
self.server_docs_map = {
|
self.server_docs_map = {
|
||||||
"context7": "MCP_Context7.md",
|
"context7": "MCP_Context7.md",
|
||||||
@ -29,18 +29,18 @@ class MCPDocsComponent(Component):
|
|||||||
"serena": "MCP_Serena.md",
|
"serena": "MCP_Serena.md",
|
||||||
"morphllm": "MCP_Morphllm.md",
|
"morphllm": "MCP_Morphllm.md",
|
||||||
"morphllm-fast-apply": "MCP_Morphllm.md", # Handle both naming conventions
|
"morphllm-fast-apply": "MCP_Morphllm.md", # Handle both naming conventions
|
||||||
"tavily": "MCP_Tavily.md"
|
"tavily": "MCP_Tavily.md",
|
||||||
}
|
}
|
||||||
|
|
||||||
super().__init__(install_dir, Path(""))
|
super().__init__(install_dir, Path(""))
|
||||||
|
|
||||||
def get_metadata(self) -> Dict[str, str]:
|
def get_metadata(self) -> Dict[str, str]:
|
||||||
"""Get component metadata"""
|
"""Get component metadata"""
|
||||||
return {
|
return {
|
||||||
"name": "mcp_docs",
|
"name": "mcp_docs",
|
||||||
"version": __version__,
|
"version": __version__,
|
||||||
"description": "MCP server documentation and usage guides",
|
"description": "MCP server documentation and usage guides",
|
||||||
"category": "documentation"
|
"category": "documentation",
|
||||||
}
|
}
|
||||||
|
|
||||||
def is_reinstallable(self) -> bool:
|
def is_reinstallable(self) -> bool:
|
||||||
@ -54,11 +54,11 @@ class MCPDocsComponent(Component):
|
|||||||
"""Set which MCP servers were selected for documentation installation"""
|
"""Set which MCP servers were selected for documentation installation"""
|
||||||
self.selected_servers = selected_servers
|
self.selected_servers = selected_servers
|
||||||
self.logger.debug(f"MCP docs will be installed for: {selected_servers}")
|
self.logger.debug(f"MCP docs will be installed for: {selected_servers}")
|
||||||
|
|
||||||
def get_files_to_install(self) -> List[Tuple[Path, Path]]:
|
def get_files_to_install(self) -> List[Tuple[Path, Path]]:
|
||||||
"""
|
"""
|
||||||
Return list of files to install based on selected MCP servers
|
Return list of files to install based on selected MCP servers
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
List of tuples (source_path, target_path)
|
List of tuples (source_path, target_path)
|
||||||
"""
|
"""
|
||||||
@ -73,12 +73,16 @@ class MCPDocsComponent(Component):
|
|||||||
target = self.install_dir / doc_file
|
target = self.install_dir / doc_file
|
||||||
if source.exists():
|
if source.exists():
|
||||||
files.append((source, target))
|
files.append((source, target))
|
||||||
self.logger.debug(f"Will install documentation for {server_name}: {doc_file}")
|
self.logger.debug(
|
||||||
|
f"Will install documentation for {server_name}: {doc_file}"
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
self.logger.warning(f"Documentation file not found for {server_name}: {doc_file}")
|
self.logger.warning(
|
||||||
|
f"Documentation file not found for {server_name}: {doc_file}"
|
||||||
|
)
|
||||||
|
|
||||||
return files
|
return files
|
||||||
|
|
||||||
def _discover_component_files(self) -> List[str]:
|
def _discover_component_files(self) -> List[str]:
|
||||||
"""
|
"""
|
||||||
Override parent method to dynamically discover files based on selected servers
|
Override parent method to dynamically discover files based on selected servers
|
||||||
@ -90,7 +94,7 @@ class MCPDocsComponent(Component):
|
|||||||
if server_name in self.server_docs_map:
|
if server_name in self.server_docs_map:
|
||||||
files.append(self.server_docs_map[server_name])
|
files.append(self.server_docs_map[server_name])
|
||||||
return files
|
return files
|
||||||
|
|
||||||
def _detect_existing_mcp_servers_from_config(self) -> List[str]:
|
def _detect_existing_mcp_servers_from_config(self) -> List[str]:
|
||||||
"""Detect existing MCP servers from Claude Desktop config"""
|
"""Detect existing MCP servers from Claude Desktop config"""
|
||||||
detected_servers = []
|
detected_servers = []
|
||||||
@ -101,8 +105,16 @@ class MCPDocsComponent(Component):
|
|||||||
self.install_dir / "claude_desktop_config.json",
|
self.install_dir / "claude_desktop_config.json",
|
||||||
Path.home() / ".claude" / "claude_desktop_config.json",
|
Path.home() / ".claude" / "claude_desktop_config.json",
|
||||||
Path.home() / ".claude.json", # Claude CLI config
|
Path.home() / ".claude.json", # Claude CLI config
|
||||||
Path.home() / "AppData" / "Roaming" / "Claude" / "claude_desktop_config.json", # Windows
|
Path.home()
|
||||||
Path.home() / "Library" / "Application Support" / "Claude" / "claude_desktop_config.json", # macOS
|
/ "AppData"
|
||||||
|
/ "Roaming"
|
||||||
|
/ "Claude"
|
||||||
|
/ "claude_desktop_config.json", # Windows
|
||||||
|
Path.home()
|
||||||
|
/ "Library"
|
||||||
|
/ "Application Support"
|
||||||
|
/ "Claude"
|
||||||
|
/ "claude_desktop_config.json", # macOS
|
||||||
]
|
]
|
||||||
|
|
||||||
config_file = None
|
config_file = None
|
||||||
@ -116,7 +128,8 @@ class MCPDocsComponent(Component):
|
|||||||
return detected_servers
|
return detected_servers
|
||||||
|
|
||||||
import json
|
import json
|
||||||
with open(config_file, 'r') as f:
|
|
||||||
|
with open(config_file, "r") as f:
|
||||||
config = json.load(f)
|
config = json.load(f)
|
||||||
|
|
||||||
# Extract MCP server names from mcpServers section
|
# Extract MCP server names from mcpServers section
|
||||||
@ -128,7 +141,9 @@ class MCPDocsComponent(Component):
|
|||||||
detected_servers.append(normalized_name)
|
detected_servers.append(normalized_name)
|
||||||
|
|
||||||
if detected_servers:
|
if detected_servers:
|
||||||
self.logger.info(f"Detected existing MCP servers from config: {detected_servers}")
|
self.logger.info(
|
||||||
|
f"Detected existing MCP servers from config: {detected_servers}"
|
||||||
|
)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.warning(f"Could not read Claude Desktop config: {e}")
|
self.logger.warning(f"Could not read Claude Desktop config: {e}")
|
||||||
@ -152,7 +167,7 @@ class MCPDocsComponent(Component):
|
|||||||
"serena": "serena",
|
"serena": "serena",
|
||||||
"morphllm": "morphllm",
|
"morphllm": "morphllm",
|
||||||
"morphllm-fast-apply": "morphllm",
|
"morphllm-fast-apply": "morphllm",
|
||||||
"morph": "morphllm"
|
"morph": "morphllm",
|
||||||
}
|
}
|
||||||
|
|
||||||
return name_mappings.get(server_name)
|
return name_mappings.get(server_name)
|
||||||
@ -169,7 +184,9 @@ class MCPDocsComponent(Component):
|
|||||||
selected_servers = config.get("selected_mcp_servers", [])
|
selected_servers = config.get("selected_mcp_servers", [])
|
||||||
|
|
||||||
# Get previously documented servers from metadata
|
# Get previously documented servers from metadata
|
||||||
previous_servers = self.settings_manager.get_metadata_setting("components.mcp_docs.servers_documented", [])
|
previous_servers = self.settings_manager.get_metadata_setting(
|
||||||
|
"components.mcp_docs.servers_documented", []
|
||||||
|
)
|
||||||
|
|
||||||
# Merge all server lists
|
# Merge all server lists
|
||||||
all_servers = list(set(detected_servers + selected_servers + previous_servers))
|
all_servers = list(set(detected_servers + selected_servers + previous_servers))
|
||||||
@ -178,13 +195,17 @@ class MCPDocsComponent(Component):
|
|||||||
valid_servers = [s for s in all_servers if s in self.server_docs_map]
|
valid_servers = [s for s in all_servers if s in self.server_docs_map]
|
||||||
|
|
||||||
if not valid_servers:
|
if not valid_servers:
|
||||||
self.logger.info("No MCP servers detected or selected for documentation installation")
|
self.logger.info(
|
||||||
|
"No MCP servers detected or selected for documentation installation"
|
||||||
|
)
|
||||||
# Still proceed to update metadata
|
# Still proceed to update metadata
|
||||||
self.set_selected_servers([])
|
self.set_selected_servers([])
|
||||||
self.component_files = []
|
self.component_files = []
|
||||||
return self._post_install()
|
return self._post_install()
|
||||||
|
|
||||||
self.logger.info(f"Installing documentation for MCP servers: {', '.join(valid_servers)}")
|
self.logger.info(
|
||||||
|
f"Installing documentation for MCP servers: {', '.join(valid_servers)}"
|
||||||
|
)
|
||||||
if detected_servers:
|
if detected_servers:
|
||||||
self.logger.info(f" - Detected from config: {detected_servers}")
|
self.logger.info(f" - Detected from config: {detected_servers}")
|
||||||
if selected_servers:
|
if selected_servers:
|
||||||
@ -225,12 +246,16 @@ class MCPDocsComponent(Component):
|
|||||||
self.logger.error(f"Failed to copy {source.name}")
|
self.logger.error(f"Failed to copy {source.name}")
|
||||||
|
|
||||||
if success_count != len(files_to_install):
|
if success_count != len(files_to_install):
|
||||||
self.logger.error(f"Only {success_count}/{len(files_to_install)} documentation files copied successfully")
|
self.logger.error(
|
||||||
|
f"Only {success_count}/{len(files_to_install)} documentation files copied successfully"
|
||||||
|
)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# Update component_files to only include successfully copied files
|
# Update component_files to only include successfully copied files
|
||||||
self.component_files = successfully_copied_files
|
self.component_files = successfully_copied_files
|
||||||
self.logger.success(f"MCP documentation installed successfully ({success_count} files for {len(valid_servers)} servers)")
|
self.logger.success(
|
||||||
|
f"MCP documentation installed successfully ({success_count} files for {len(valid_servers)} servers)"
|
||||||
|
)
|
||||||
|
|
||||||
return self._post_install()
|
return self._post_install()
|
||||||
|
|
||||||
@ -244,36 +269,38 @@ class MCPDocsComponent(Component):
|
|||||||
"version": __version__,
|
"version": __version__,
|
||||||
"installed": True,
|
"installed": True,
|
||||||
"files_count": len(self.component_files),
|
"files_count": len(self.component_files),
|
||||||
"servers_documented": self.selected_servers
|
"servers_documented": self.selected_servers,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.settings_manager.update_metadata(metadata_mods)
|
self.settings_manager.update_metadata(metadata_mods)
|
||||||
self.logger.info("Updated metadata with MCP docs component registration")
|
self.logger.info("Updated metadata with MCP docs component registration")
|
||||||
|
|
||||||
# Update CLAUDE.md with MCP documentation imports
|
# Update CLAUDE.md with MCP documentation imports
|
||||||
try:
|
try:
|
||||||
manager = CLAUDEMdService(self.install_dir)
|
manager = CLAUDEMdService(self.install_dir)
|
||||||
manager.add_imports(self.component_files, category="MCP Documentation")
|
manager.add_imports(self.component_files, category="MCP Documentation")
|
||||||
self.logger.info("Updated CLAUDE.md with MCP documentation imports")
|
self.logger.info("Updated CLAUDE.md with MCP documentation imports")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.warning(f"Failed to update CLAUDE.md with MCP documentation imports: {e}")
|
self.logger.warning(
|
||||||
|
f"Failed to update CLAUDE.md with MCP documentation imports: {e}"
|
||||||
|
)
|
||||||
# Don't fail the whole installation for this
|
# Don't fail the whole installation for this
|
||||||
|
|
||||||
return True
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.error(f"Failed to update metadata: {e}")
|
self.logger.error(f"Failed to update metadata: {e}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def uninstall(self) -> bool:
|
def uninstall(self) -> bool:
|
||||||
"""Uninstall MCP documentation component"""
|
"""Uninstall MCP documentation component"""
|
||||||
try:
|
try:
|
||||||
self.logger.info("Uninstalling MCP documentation component...")
|
self.logger.info("Uninstalling MCP documentation component...")
|
||||||
|
|
||||||
# Remove all MCP documentation files
|
# Remove all MCP documentation files
|
||||||
removed_count = 0
|
removed_count = 0
|
||||||
source_dir = self._get_source_dir()
|
source_dir = self._get_source_dir()
|
||||||
|
|
||||||
if source_dir and source_dir.exists():
|
if source_dir and source_dir.exists():
|
||||||
# Remove all possible MCP doc files
|
# Remove all possible MCP doc files
|
||||||
for doc_file in self.server_docs_map.values():
|
for doc_file in self.server_docs_map.values():
|
||||||
@ -281,7 +308,7 @@ class MCPDocsComponent(Component):
|
|||||||
if self.file_manager.remove_file(file_path):
|
if self.file_manager.remove_file(file_path):
|
||||||
removed_count += 1
|
removed_count += 1
|
||||||
self.logger.debug(f"Removed {doc_file}")
|
self.logger.debug(f"Removed {doc_file}")
|
||||||
|
|
||||||
# Remove mcp directory if empty
|
# Remove mcp directory if empty
|
||||||
try:
|
try:
|
||||||
if self.install_component_subdir.exists():
|
if self.install_component_subdir.exists():
|
||||||
@ -291,7 +318,7 @@ class MCPDocsComponent(Component):
|
|||||||
self.logger.debug("Removed empty mcp directory")
|
self.logger.debug("Removed empty mcp directory")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.warning(f"Could not remove mcp directory: {e}")
|
self.logger.warning(f"Could not remove mcp directory: {e}")
|
||||||
|
|
||||||
# Update settings.json
|
# Update settings.json
|
||||||
try:
|
try:
|
||||||
if self.settings_manager.is_component_installed("mcp_docs"):
|
if self.settings_manager.is_component_installed("mcp_docs"):
|
||||||
@ -299,36 +326,40 @@ class MCPDocsComponent(Component):
|
|||||||
self.logger.info("Removed MCP docs component from settings.json")
|
self.logger.info("Removed MCP docs component from settings.json")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.warning(f"Could not update settings.json: {e}")
|
self.logger.warning(f"Could not update settings.json: {e}")
|
||||||
|
|
||||||
self.logger.success(f"MCP documentation uninstalled ({removed_count} files removed)")
|
self.logger.success(
|
||||||
|
f"MCP documentation uninstalled ({removed_count} files removed)"
|
||||||
|
)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.exception(f"Unexpected error during MCP docs uninstallation: {e}")
|
self.logger.exception(
|
||||||
|
f"Unexpected error during MCP docs uninstallation: {e}"
|
||||||
|
)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def get_dependencies(self) -> List[str]:
|
def get_dependencies(self) -> List[str]:
|
||||||
"""Get dependencies"""
|
"""Get dependencies"""
|
||||||
return ["core"]
|
return ["core"]
|
||||||
|
|
||||||
def _get_source_dir(self) -> Optional[Path]:
|
def _get_source_dir(self) -> Optional[Path]:
|
||||||
"""Get source directory for MCP documentation files"""
|
"""Get source directory for MCP documentation files"""
|
||||||
# Assume we're in SuperClaude/setup/components/mcp_docs.py
|
# Assume we're in superclaude/setup/components/mcp_docs.py
|
||||||
# and MCP docs are in SuperClaude/SuperClaude/MCP/
|
# and MCP docs are in superclaude/superclaude/MCP/
|
||||||
project_root = Path(__file__).parent.parent.parent
|
project_root = Path(__file__).parent.parent.parent
|
||||||
mcp_dir = project_root / "SuperClaude" / "MCP"
|
mcp_dir = project_root / "superclaude" / "mcp"
|
||||||
|
|
||||||
# Return None if directory doesn't exist to prevent warning
|
# Return None if directory doesn't exist to prevent warning
|
||||||
if not mcp_dir.exists():
|
if not mcp_dir.exists():
|
||||||
return None
|
return None
|
||||||
|
|
||||||
return mcp_dir
|
return mcp_dir
|
||||||
|
|
||||||
def get_size_estimate(self) -> int:
|
def get_size_estimate(self) -> int:
|
||||||
"""Get estimated installation size"""
|
"""Get estimated installation size"""
|
||||||
source_dir = self._get_source_dir()
|
source_dir = self._get_source_dir()
|
||||||
total_size = 0
|
total_size = 0
|
||||||
|
|
||||||
if source_dir and source_dir.exists() and self.selected_servers:
|
if source_dir and source_dir.exists() and self.selected_servers:
|
||||||
for server_name in self.selected_servers:
|
for server_name in self.selected_servers:
|
||||||
if server_name in self.server_docs_map:
|
if server_name in self.server_docs_map:
|
||||||
@ -336,8 +367,8 @@ class MCPDocsComponent(Component):
|
|||||||
file_path = source_dir / doc_file
|
file_path = source_dir / doc_file
|
||||||
if file_path.exists():
|
if file_path.exists():
|
||||||
total_size += file_path.stat().st_size
|
total_size += file_path.stat().st_size
|
||||||
|
|
||||||
# Minimum size estimate
|
# Minimum size estimate
|
||||||
total_size = max(total_size, 10240) # At least 10KB
|
total_size = max(total_size, 10240) # At least 10KB
|
||||||
|
|
||||||
return total_size
|
return total_size
|
||||||
|
|||||||
@ -12,20 +12,20 @@ from ..services.claude_md import CLAUDEMdService
|
|||||||
|
|
||||||
class ModesComponent(Component):
|
class ModesComponent(Component):
|
||||||
"""SuperClaude behavioral modes component"""
|
"""SuperClaude behavioral modes component"""
|
||||||
|
|
||||||
def __init__(self, install_dir: Optional[Path] = None):
|
def __init__(self, install_dir: Optional[Path] = None):
|
||||||
"""Initialize modes component"""
|
"""Initialize modes component"""
|
||||||
super().__init__(install_dir, Path(""))
|
super().__init__(install_dir, Path(""))
|
||||||
|
|
||||||
def get_metadata(self) -> Dict[str, str]:
|
def get_metadata(self) -> Dict[str, str]:
|
||||||
"""Get component metadata"""
|
"""Get component metadata"""
|
||||||
return {
|
return {
|
||||||
"name": "modes",
|
"name": "modes",
|
||||||
"version": __version__,
|
"version": __version__,
|
||||||
"description": "7 behavioral modes for enhanced Claude Code operation",
|
"description": "7 behavioral modes for enhanced Claude Code operation",
|
||||||
"category": "modes"
|
"category": "modes",
|
||||||
}
|
}
|
||||||
|
|
||||||
def _install(self, config: Dict[str, Any]) -> bool:
|
def _install(self, config: Dict[str, Any]) -> bool:
|
||||||
"""Install modes component"""
|
"""Install modes component"""
|
||||||
self.logger.info("Installing SuperClaude behavioral modes...")
|
self.logger.info("Installing SuperClaude behavioral modes...")
|
||||||
@ -48,7 +48,7 @@ class ModesComponent(Component):
|
|||||||
success_count = 0
|
success_count = 0
|
||||||
for source, target in files_to_install:
|
for source, target in files_to_install:
|
||||||
self.logger.debug(f"Copying {source.name} to {target}")
|
self.logger.debug(f"Copying {source.name} to {target}")
|
||||||
|
|
||||||
if self.file_manager.copy_file(source, target):
|
if self.file_manager.copy_file(source, target):
|
||||||
success_count += 1
|
success_count += 1
|
||||||
self.logger.debug(f"Successfully copied {source.name}")
|
self.logger.debug(f"Successfully copied {source.name}")
|
||||||
@ -56,10 +56,14 @@ class ModesComponent(Component):
|
|||||||
self.logger.error(f"Failed to copy {source.name}")
|
self.logger.error(f"Failed to copy {source.name}")
|
||||||
|
|
||||||
if success_count != len(files_to_install):
|
if success_count != len(files_to_install):
|
||||||
self.logger.error(f"Only {success_count}/{len(files_to_install)} mode files copied successfully")
|
self.logger.error(
|
||||||
|
f"Only {success_count}/{len(files_to_install)} mode files copied successfully"
|
||||||
|
)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
self.logger.success(f"Modes component installed successfully ({success_count} mode files)")
|
self.logger.success(
|
||||||
|
f"Modes component installed successfully ({success_count} mode files)"
|
||||||
|
)
|
||||||
|
|
||||||
return self._post_install()
|
return self._post_install()
|
||||||
|
|
||||||
@ -72,39 +76,41 @@ class ModesComponent(Component):
|
|||||||
"modes": {
|
"modes": {
|
||||||
"version": __version__,
|
"version": __version__,
|
||||||
"installed": True,
|
"installed": True,
|
||||||
"files_count": len(self.component_files)
|
"files_count": len(self.component_files),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.settings_manager.update_metadata(metadata_mods)
|
self.settings_manager.update_metadata(metadata_mods)
|
||||||
self.logger.info("Updated metadata with modes component registration")
|
self.logger.info("Updated metadata with modes component registration")
|
||||||
|
|
||||||
# Update CLAUDE.md with mode imports
|
# Update CLAUDE.md with mode imports
|
||||||
try:
|
try:
|
||||||
manager = CLAUDEMdService(self.install_dir)
|
manager = CLAUDEMdService(self.install_dir)
|
||||||
manager.add_imports(self.component_files, category="Behavioral Modes")
|
manager.add_imports(self.component_files, category="Behavioral Modes")
|
||||||
self.logger.info("Updated CLAUDE.md with mode imports")
|
self.logger.info("Updated CLAUDE.md with mode imports")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.warning(f"Failed to update CLAUDE.md with mode imports: {e}")
|
self.logger.warning(
|
||||||
|
f"Failed to update CLAUDE.md with mode imports: {e}"
|
||||||
|
)
|
||||||
# Don't fail the whole installation for this
|
# Don't fail the whole installation for this
|
||||||
|
|
||||||
return True
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.error(f"Failed to update metadata: {e}")
|
self.logger.error(f"Failed to update metadata: {e}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def uninstall(self) -> bool:
|
def uninstall(self) -> bool:
|
||||||
"""Uninstall modes component"""
|
"""Uninstall modes component"""
|
||||||
try:
|
try:
|
||||||
self.logger.info("Uninstalling SuperClaude modes component...")
|
self.logger.info("Uninstalling SuperClaude modes component...")
|
||||||
|
|
||||||
# Remove mode files
|
# Remove mode files
|
||||||
removed_count = 0
|
removed_count = 0
|
||||||
for _, target in self.get_files_to_install():
|
for _, target in self.get_files_to_install():
|
||||||
if self.file_manager.remove_file(target):
|
if self.file_manager.remove_file(target):
|
||||||
removed_count += 1
|
removed_count += 1
|
||||||
self.logger.debug(f"Removed {target.name}")
|
self.logger.debug(f"Removed {target.name}")
|
||||||
|
|
||||||
# Remove modes directory if empty
|
# Remove modes directory if empty
|
||||||
try:
|
try:
|
||||||
if self.install_component_subdir.exists():
|
if self.install_component_subdir.exists():
|
||||||
@ -114,7 +120,7 @@ class ModesComponent(Component):
|
|||||||
self.logger.debug("Removed empty modes directory")
|
self.logger.debug("Removed empty modes directory")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.warning(f"Could not remove modes directory: {e}")
|
self.logger.warning(f"Could not remove modes directory: {e}")
|
||||||
|
|
||||||
# Update settings.json
|
# Update settings.json
|
||||||
try:
|
try:
|
||||||
if self.settings_manager.is_component_installed("modes"):
|
if self.settings_manager.is_component_installed("modes"):
|
||||||
@ -122,43 +128,45 @@ class ModesComponent(Component):
|
|||||||
self.logger.info("Removed modes component from settings.json")
|
self.logger.info("Removed modes component from settings.json")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.warning(f"Could not update settings.json: {e}")
|
self.logger.warning(f"Could not update settings.json: {e}")
|
||||||
|
|
||||||
self.logger.success(f"Modes component uninstalled ({removed_count} files removed)")
|
self.logger.success(
|
||||||
|
f"Modes component uninstalled ({removed_count} files removed)"
|
||||||
|
)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.exception(f"Unexpected error during modes uninstallation: {e}")
|
self.logger.exception(f"Unexpected error during modes uninstallation: {e}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def get_dependencies(self) -> List[str]:
|
def get_dependencies(self) -> List[str]:
|
||||||
"""Get dependencies"""
|
"""Get dependencies"""
|
||||||
return ["core"]
|
return ["core"]
|
||||||
|
|
||||||
def _get_source_dir(self) -> Optional[Path]:
|
def _get_source_dir(self) -> Optional[Path]:
|
||||||
"""Get source directory for mode files"""
|
"""Get source directory for mode files"""
|
||||||
# Assume we're in SuperClaude/setup/components/modes.py
|
# Assume we're in superclaude/setup/components/modes.py
|
||||||
# and mode files are in SuperClaude/SuperClaude/Modes/
|
# and mode files are in superclaude/superclaude/Modes/
|
||||||
project_root = Path(__file__).parent.parent.parent
|
project_root = Path(__file__).parent.parent.parent
|
||||||
modes_dir = project_root / "SuperClaude" / "Modes"
|
modes_dir = project_root / "superclaude" / "modes"
|
||||||
|
|
||||||
# Return None if directory doesn't exist to prevent warning
|
# Return None if directory doesn't exist to prevent warning
|
||||||
if not modes_dir.exists():
|
if not modes_dir.exists():
|
||||||
return None
|
return None
|
||||||
|
|
||||||
return modes_dir
|
return modes_dir
|
||||||
|
|
||||||
def get_size_estimate(self) -> int:
|
def get_size_estimate(self) -> int:
|
||||||
"""Get estimated installation size"""
|
"""Get estimated installation size"""
|
||||||
source_dir = self._get_source_dir()
|
source_dir = self._get_source_dir()
|
||||||
total_size = 0
|
total_size = 0
|
||||||
|
|
||||||
if source_dir and source_dir.exists():
|
if source_dir and source_dir.exists():
|
||||||
for filename in self.component_files:
|
for filename in self.component_files:
|
||||||
file_path = source_dir / filename
|
file_path = source_dir / filename
|
||||||
if file_path.exists():
|
if file_path.exists():
|
||||||
total_size += file_path.stat().st_size
|
total_size += file_path.stat().st_size
|
||||||
|
|
||||||
# Minimum size estimate
|
# Minimum size estimate
|
||||||
total_size = max(total_size, 20480) # At least 20KB
|
total_size = max(total_size, 20480) # At least 20KB
|
||||||
|
|
||||||
return total_size
|
return total_size
|
||||||
|
|||||||
@ -3,7 +3,4 @@
|
|||||||
from .validator import Validator
|
from .validator import Validator
|
||||||
from .registry import ComponentRegistry
|
from .registry import ComponentRegistry
|
||||||
|
|
||||||
__all__ = [
|
__all__ = ["Validator", "ComponentRegistry"]
|
||||||
'Validator',
|
|
||||||
'ComponentRegistry'
|
|
||||||
]
|
|
||||||
|
|||||||
@ -14,15 +14,18 @@ from ..utils.security import SecurityValidator
|
|||||||
|
|
||||||
class Component(ABC):
|
class Component(ABC):
|
||||||
"""Base class for all installable components"""
|
"""Base class for all installable components"""
|
||||||
|
|
||||||
def __init__(self, install_dir: Optional[Path] = None, component_subdir: Path = Path('')):
|
def __init__(
|
||||||
|
self, install_dir: Optional[Path] = None, component_subdir: Path = Path("")
|
||||||
|
):
|
||||||
"""
|
"""
|
||||||
Initialize component with installation directory
|
Initialize component with installation directory
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
install_dir: Target installation directory (defaults to ~/.claude)
|
install_dir: Target installation directory (defaults to ~/.claude)
|
||||||
"""
|
"""
|
||||||
from .. import DEFAULT_INSTALL_DIR
|
from .. import DEFAULT_INSTALL_DIR
|
||||||
|
|
||||||
# Initialize logger first
|
# Initialize logger first
|
||||||
self.logger = get_logger()
|
self.logger = get_logger()
|
||||||
# Resolve path safely
|
# Resolve path safely
|
||||||
@ -31,12 +34,12 @@ class Component(ABC):
|
|||||||
self.component_files = self._discover_component_files()
|
self.component_files = self._discover_component_files()
|
||||||
self.file_manager = FileService()
|
self.file_manager = FileService()
|
||||||
self.install_component_subdir = self.install_dir / component_subdir
|
self.install_component_subdir = self.install_dir / component_subdir
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def get_metadata(self) -> Dict[str, str]:
|
def get_metadata(self) -> Dict[str, str]:
|
||||||
"""
|
"""
|
||||||
Return component metadata
|
Return component metadata
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Dict containing:
|
Dict containing:
|
||||||
- name: Component name
|
- name: Component name
|
||||||
@ -52,11 +55,13 @@ class Component(ABC):
|
|||||||
Useful for container-like components that can install sub-parts.
|
Useful for container-like components that can install sub-parts.
|
||||||
"""
|
"""
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def validate_prerequisites(self, installSubPath: Optional[Path] = None) -> Tuple[bool, List[str]]:
|
def validate_prerequisites(
|
||||||
|
self, installSubPath: Optional[Path] = None
|
||||||
|
) -> Tuple[bool, List[str]]:
|
||||||
"""
|
"""
|
||||||
Check prerequisites for this component
|
Check prerequisites for this component
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Tuple of (success: bool, error_messages: List[str])
|
Tuple of (success: bool, error_messages: List[str])
|
||||||
"""
|
"""
|
||||||
@ -80,13 +85,15 @@ class Component(ABC):
|
|||||||
|
|
||||||
# Check write permissions to install directory
|
# Check write permissions to install directory
|
||||||
has_perms, missing = SecurityValidator.check_permissions(
|
has_perms, missing = SecurityValidator.check_permissions(
|
||||||
self.install_dir, {'write'}
|
self.install_dir, {"write"}
|
||||||
)
|
)
|
||||||
if not has_perms:
|
if not has_perms:
|
||||||
errors.append(f"No write permissions to {self.install_dir}: {missing}")
|
errors.append(f"No write permissions to {self.install_dir}: {missing}")
|
||||||
|
|
||||||
# Validate installation target
|
# Validate installation target
|
||||||
is_safe, validation_errors = SecurityValidator.validate_installation_target(self.install_component_subdir)
|
is_safe, validation_errors = SecurityValidator.validate_installation_target(
|
||||||
|
self.install_component_subdir
|
||||||
|
)
|
||||||
if not is_safe:
|
if not is_safe:
|
||||||
errors.extend(validation_errors)
|
errors.extend(validation_errors)
|
||||||
|
|
||||||
@ -101,14 +108,16 @@ class Component(ABC):
|
|||||||
errors.extend(security_errors)
|
errors.extend(security_errors)
|
||||||
|
|
||||||
if not self.file_manager.ensure_directory(self.install_component_subdir):
|
if not self.file_manager.ensure_directory(self.install_component_subdir):
|
||||||
errors.append(f"Could not create install directory: {self.install_component_subdir}")
|
errors.append(
|
||||||
|
f"Could not create install directory: {self.install_component_subdir}"
|
||||||
|
)
|
||||||
|
|
||||||
return len(errors) == 0, errors
|
return len(errors) == 0, errors
|
||||||
|
|
||||||
def get_files_to_install(self) -> List[Tuple[Path, Path]]:
|
def get_files_to_install(self) -> List[Tuple[Path, Path]]:
|
||||||
"""
|
"""
|
||||||
Return list of files to install
|
Return list of files to install
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
List of tuples (source_path, target_path)
|
List of tuples (source_path, target_path)
|
||||||
"""
|
"""
|
||||||
@ -122,7 +131,7 @@ class Component(ABC):
|
|||||||
files.append((source, target))
|
files.append((source, target))
|
||||||
|
|
||||||
return files
|
return files
|
||||||
|
|
||||||
def get_settings_modifications(self) -> Dict[str, Any]:
|
def get_settings_modifications(self) -> Dict[str, Any]:
|
||||||
"""
|
"""
|
||||||
Return settings.json modifications to apply
|
Return settings.json modifications to apply
|
||||||
@ -133,22 +142,24 @@ class Component(ABC):
|
|||||||
"""
|
"""
|
||||||
# Return empty dict as we don't modify Claude Code settings
|
# Return empty dict as we don't modify Claude Code settings
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
def install(self, config: Dict[str, Any]) -> bool:
|
def install(self, config: Dict[str, Any]) -> bool:
|
||||||
try:
|
try:
|
||||||
return self._install(config)
|
return self._install(config)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.exception(f"Unexpected error during {repr(self)} installation: {e}")
|
self.logger.exception(
|
||||||
|
f"Unexpected error during {repr(self)} installation: {e}"
|
||||||
|
)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def _install(self, config: Dict[str, Any]) -> bool:
|
def _install(self, config: Dict[str, Any]) -> bool:
|
||||||
"""
|
"""
|
||||||
Perform component-specific installation logic
|
Perform component-specific installation logic
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
config: Installation configuration
|
config: Installation configuration
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
True if successful, False otherwise
|
True if successful, False otherwise
|
||||||
"""
|
"""
|
||||||
@ -174,34 +185,36 @@ class Component(ABC):
|
|||||||
self.logger.error(f"Failed to copy {source.name}")
|
self.logger.error(f"Failed to copy {source.name}")
|
||||||
|
|
||||||
if success_count != len(files_to_install):
|
if success_count != len(files_to_install):
|
||||||
self.logger.error(f"Only {success_count}/{len(files_to_install)} files copied successfully")
|
self.logger.error(
|
||||||
|
f"Only {success_count}/{len(files_to_install)} files copied successfully"
|
||||||
|
)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
self.logger.success(f"{repr(self)} component installed successfully ({success_count} files)")
|
self.logger.success(
|
||||||
|
f"{repr(self)} component installed successfully ({success_count} files)"
|
||||||
|
)
|
||||||
|
|
||||||
return self._post_install()
|
return self._post_install()
|
||||||
|
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def _post_install(self) -> bool:
|
def _post_install(self) -> bool:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def uninstall(self) -> bool:
|
def uninstall(self) -> bool:
|
||||||
"""
|
"""
|
||||||
Remove component
|
Remove component
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
True if successful, False otherwise
|
True if successful, False otherwise
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def get_dependencies(self) -> List[str]:
|
def get_dependencies(self) -> List[str]:
|
||||||
"""
|
"""
|
||||||
Return list of component dependencies
|
Return list of component dependencies
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
List of component names this component depends on
|
List of component names this component depends on
|
||||||
"""
|
"""
|
||||||
@ -211,14 +224,14 @@ class Component(ABC):
|
|||||||
def _get_source_dir(self) -> Optional[Path]:
|
def _get_source_dir(self) -> Optional[Path]:
|
||||||
"""Get source directory for component files"""
|
"""Get source directory for component files"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def update(self, config: Dict[str, Any]) -> bool:
|
def update(self, config: Dict[str, Any]) -> bool:
|
||||||
"""
|
"""
|
||||||
Update component (default: uninstall then install)
|
Update component (default: uninstall then install)
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
config: Installation configuration
|
config: Installation configuration
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
True if successful, False otherwise
|
True if successful, False otherwise
|
||||||
"""
|
"""
|
||||||
@ -226,11 +239,11 @@ class Component(ABC):
|
|||||||
if self.uninstall():
|
if self.uninstall():
|
||||||
return self.install(config)
|
return self.install(config)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def get_installed_version(self) -> Optional[str]:
|
def get_installed_version(self) -> Optional[str]:
|
||||||
"""
|
"""
|
||||||
Get currently installed version of component
|
Get currently installed version of component
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Version string if installed, None otherwise
|
Version string if installed, None otherwise
|
||||||
"""
|
"""
|
||||||
@ -239,10 +252,14 @@ class Component(ABC):
|
|||||||
if metadata_file.exists():
|
if metadata_file.exists():
|
||||||
self.logger.debug("Metadata file exists, reading version")
|
self.logger.debug("Metadata file exists, reading version")
|
||||||
try:
|
try:
|
||||||
with open(metadata_file, 'r') as f:
|
with open(metadata_file, "r") as f:
|
||||||
metadata = json.load(f)
|
metadata = json.load(f)
|
||||||
component_name = self.get_metadata()['name']
|
component_name = self.get_metadata()["name"]
|
||||||
version = metadata.get('components', {}).get(component_name, {}).get('version')
|
version = (
|
||||||
|
metadata.get("components", {})
|
||||||
|
.get(component_name, {})
|
||||||
|
.get("version")
|
||||||
|
)
|
||||||
self.logger.debug(f"Found version: {version}")
|
self.logger.debug(f"Found version: {version}")
|
||||||
return version
|
return version
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@ -250,40 +267,40 @@ class Component(ABC):
|
|||||||
else:
|
else:
|
||||||
self.logger.debug("Metadata file does not exist")
|
self.logger.debug("Metadata file does not exist")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def is_installed(self) -> bool:
|
def is_installed(self) -> bool:
|
||||||
"""
|
"""
|
||||||
Check if component is installed
|
Check if component is installed
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
True if installed, False otherwise
|
True if installed, False otherwise
|
||||||
"""
|
"""
|
||||||
return self.get_installed_version() is not None
|
return self.get_installed_version() is not None
|
||||||
|
|
||||||
def validate_installation(self) -> Tuple[bool, List[str]]:
|
def validate_installation(self) -> Tuple[bool, List[str]]:
|
||||||
"""
|
"""
|
||||||
Validate that component is correctly installed
|
Validate that component is correctly installed
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Tuple of (success: bool, error_messages: List[str])
|
Tuple of (success: bool, error_messages: List[str])
|
||||||
"""
|
"""
|
||||||
errors = []
|
errors = []
|
||||||
|
|
||||||
# Check if all files exist
|
# Check if all files exist
|
||||||
for _, target in self.get_files_to_install():
|
for _, target in self.get_files_to_install():
|
||||||
if not target.exists():
|
if not target.exists():
|
||||||
errors.append(f"Missing file: {target}")
|
errors.append(f"Missing file: {target}")
|
||||||
|
|
||||||
# Check version in metadata
|
# Check version in metadata
|
||||||
if not self.get_installed_version():
|
if not self.get_installed_version():
|
||||||
errors.append("Component not registered in .superclaude-metadata.json")
|
errors.append("Component not registered in .superclaude-metadata.json")
|
||||||
|
|
||||||
return len(errors) == 0, errors
|
return len(errors) == 0, errors
|
||||||
|
|
||||||
def get_size_estimate(self) -> int:
|
def get_size_estimate(self) -> int:
|
||||||
"""
|
"""
|
||||||
Estimate installed size in bytes
|
Estimate installed size in bytes
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Estimated size in bytes
|
Estimated size in bytes
|
||||||
"""
|
"""
|
||||||
@ -293,7 +310,9 @@ class Component(ABC):
|
|||||||
if source.is_file():
|
if source.is_file():
|
||||||
total_size += source.stat().st_size
|
total_size += source.stat().st_size
|
||||||
elif source.is_dir():
|
elif source.is_dir():
|
||||||
total_size += sum(f.stat().st_size for f in source.rglob('*') if f.is_file())
|
total_size += sum(
|
||||||
|
f.stat().st_size for f in source.rglob("*") if f.is_file()
|
||||||
|
)
|
||||||
return total_size
|
return total_size
|
||||||
|
|
||||||
def _discover_component_files(self) -> List[str]:
|
def _discover_component_files(self) -> List[str]:
|
||||||
@ -310,12 +329,16 @@ class Component(ABC):
|
|||||||
|
|
||||||
return self._discover_files_in_directory(
|
return self._discover_files_in_directory(
|
||||||
source_dir,
|
source_dir,
|
||||||
extension='.md',
|
extension=".md",
|
||||||
exclude_patterns=['README.md', 'CHANGELOG.md', 'LICENSE.md']
|
exclude_patterns=["README.md", "CHANGELOG.md", "LICENSE.md"],
|
||||||
)
|
)
|
||||||
|
|
||||||
def _discover_files_in_directory(self, directory: Path, extension: str = '.md',
|
def _discover_files_in_directory(
|
||||||
exclude_patterns: Optional[List[str]] = None) -> List[str]:
|
self,
|
||||||
|
directory: Path,
|
||||||
|
extension: str = ".md",
|
||||||
|
exclude_patterns: Optional[List[str]] = None,
|
||||||
|
) -> List[str]:
|
||||||
"""
|
"""
|
||||||
Shared utility for discovering files in a directory
|
Shared utility for discovering files in a directory
|
||||||
|
|
||||||
@ -342,15 +365,19 @@ class Component(ABC):
|
|||||||
# Discover files with the specified extension
|
# Discover files with the specified extension
|
||||||
files = []
|
files = []
|
||||||
for file_path in directory.iterdir():
|
for file_path in directory.iterdir():
|
||||||
if (file_path.is_file() and
|
if (
|
||||||
file_path.suffix.lower() == extension.lower() and
|
file_path.is_file()
|
||||||
file_path.name not in exclude_patterns):
|
and file_path.suffix.lower() == extension.lower()
|
||||||
|
and file_path.name not in exclude_patterns
|
||||||
|
):
|
||||||
files.append(file_path.name)
|
files.append(file_path.name)
|
||||||
|
|
||||||
# Sort for consistent ordering
|
# Sort for consistent ordering
|
||||||
files.sort()
|
files.sort()
|
||||||
|
|
||||||
self.logger.debug(f"Discovered {len(files)} {extension} files in {directory}")
|
self.logger.debug(
|
||||||
|
f"Discovered {len(files)} {extension} files in {directory}"
|
||||||
|
)
|
||||||
if files:
|
if files:
|
||||||
self.logger.debug(f"Files found: {files}")
|
self.logger.debug(f"Files found: {files}")
|
||||||
|
|
||||||
@ -362,65 +389,74 @@ class Component(ABC):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.error(f"Error discovering files in {directory}: {e}")
|
self.logger.error(f"Error discovering files in {directory}: {e}")
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
"""String representation of component"""
|
"""String representation of component"""
|
||||||
metadata = self.get_metadata()
|
metadata = self.get_metadata()
|
||||||
return f"{metadata['name']} v{metadata['version']}"
|
return f"{metadata['name']} v{metadata['version']}"
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
"""Developer representation of component"""
|
"""Developer representation of component"""
|
||||||
return f"<{self.__class__.__name__}({self.get_metadata()['name']})>"
|
return f"<{self.__class__.__name__}({self.get_metadata()['name']})>"
|
||||||
|
|
||||||
def _resolve_path_safely(self, path: Path) -> Path:
|
def _resolve_path_safely(self, path: Path) -> Path:
|
||||||
"""
|
"""
|
||||||
Safely resolve path with proper error handling and security validation
|
Safely resolve path with proper error handling and security validation
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
path: Path to resolve
|
path: Path to resolve
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Resolved path
|
Resolved path
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
ValueError: If path resolution fails or path is unsafe
|
ValueError: If path resolution fails or path is unsafe
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
# Expand user directory (~) and resolve path
|
# Expand user directory (~) and resolve path
|
||||||
resolved_path = path.expanduser().resolve()
|
resolved_path = path.expanduser().resolve()
|
||||||
|
|
||||||
# Basic security validation - only enforce for production directories
|
# Basic security validation - only enforce for production directories
|
||||||
path_str = str(resolved_path).lower()
|
path_str = str(resolved_path).lower()
|
||||||
|
|
||||||
# Check for most dangerous system patterns (but allow /tmp for testing)
|
# Check for most dangerous system patterns (but allow /tmp for testing)
|
||||||
dangerous_patterns = [
|
dangerous_patterns = [
|
||||||
'/etc/', '/bin/', '/sbin/', '/usr/bin/', '/usr/sbin/',
|
"/etc/",
|
||||||
'/var/log/', '/var/lib/', '/dev/', '/proc/', '/sys/',
|
"/bin/",
|
||||||
'c:\\windows\\', 'c:\\program files\\'
|
"/sbin/",
|
||||||
|
"/usr/bin/",
|
||||||
|
"/usr/sbin/",
|
||||||
|
"/var/log/",
|
||||||
|
"/var/lib/",
|
||||||
|
"/dev/",
|
||||||
|
"/proc/",
|
||||||
|
"/sys/",
|
||||||
|
"c:\\windows\\",
|
||||||
|
"c:\\program files\\",
|
||||||
]
|
]
|
||||||
|
|
||||||
# Allow temporary directories for testing
|
# Allow temporary directories for testing
|
||||||
if path_str.startswith('/tmp/') or 'temp' in path_str:
|
if path_str.startswith("/tmp/") or "temp" in path_str:
|
||||||
self.logger.debug(f"Allowing temporary directory: {resolved_path}")
|
self.logger.debug(f"Allowing temporary directory: {resolved_path}")
|
||||||
return resolved_path
|
return resolved_path
|
||||||
|
|
||||||
for pattern in dangerous_patterns:
|
for pattern in dangerous_patterns:
|
||||||
if path_str.startswith(pattern):
|
if path_str.startswith(pattern):
|
||||||
raise ValueError(f"Cannot use system directory: {resolved_path}")
|
raise ValueError(f"Cannot use system directory: {resolved_path}")
|
||||||
|
|
||||||
return resolved_path
|
return resolved_path
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.error(f"Failed to resolve path {path}: {e}")
|
self.logger.error(f"Failed to resolve path {path}: {e}")
|
||||||
raise ValueError(f"Invalid path: {path}")
|
raise ValueError(f"Invalid path: {path}")
|
||||||
|
|
||||||
def _resolve_source_path_safely(self, path: Path) -> Optional[Path]:
|
def _resolve_source_path_safely(self, path: Path) -> Optional[Path]:
|
||||||
"""
|
"""
|
||||||
Safely resolve source path with existence check
|
Safely resolve source path with existence check
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
path: Source path to resolve
|
path: Source path to resolve
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Resolved path if valid and exists, None otherwise
|
Resolved path if valid and exists, None otherwise
|
||||||
"""
|
"""
|
||||||
|
|||||||
@ -14,23 +14,25 @@ from ..utils.logger import get_logger
|
|||||||
class Installer:
|
class Installer:
|
||||||
"""Main installer orchestrator"""
|
"""Main installer orchestrator"""
|
||||||
|
|
||||||
def __init__(self,
|
def __init__(self, install_dir: Optional[Path] = None, dry_run: bool = False):
|
||||||
install_dir: Optional[Path] = None,
|
|
||||||
dry_run: bool = False):
|
|
||||||
"""
|
"""
|
||||||
Initialize installer
|
Initialize installer
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
install_dir: Target installation directory
|
install_dir: Target installation directory
|
||||||
dry_run: If True, only simulate installation
|
dry_run: If True, only simulate installation
|
||||||
"""
|
"""
|
||||||
from .. import DEFAULT_INSTALL_DIR
|
from .. import DEFAULT_INSTALL_DIR
|
||||||
|
|
||||||
self.install_dir = install_dir or DEFAULT_INSTALL_DIR
|
self.install_dir = install_dir or DEFAULT_INSTALL_DIR
|
||||||
self.dry_run = dry_run
|
self.dry_run = dry_run
|
||||||
self.components: Dict[str, Component] = {}
|
self.components: Dict[str, Component] = {}
|
||||||
from ..services.settings import SettingsService
|
from ..services.settings import SettingsService
|
||||||
|
|
||||||
settings_manager = SettingsService(self.install_dir)
|
settings_manager = SettingsService(self.install_dir)
|
||||||
self.installed_components: Set[str] = set(settings_manager.get_installed_components().keys())
|
self.installed_components: Set[str] = set(
|
||||||
|
settings_manager.get_installed_components().keys()
|
||||||
|
)
|
||||||
self.updated_components: Set[str] = set()
|
self.updated_components: Set[str] = set()
|
||||||
|
|
||||||
self.failed_components: Set[str] = set()
|
self.failed_components: Set[str] = set()
|
||||||
@ -41,17 +43,17 @@ class Installer:
|
|||||||
def register_component(self, component: Component) -> None:
|
def register_component(self, component: Component) -> None:
|
||||||
"""
|
"""
|
||||||
Register a component for installation
|
Register a component for installation
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
component: Component instance to register
|
component: Component instance to register
|
||||||
"""
|
"""
|
||||||
metadata = component.get_metadata()
|
metadata = component.get_metadata()
|
||||||
self.components[metadata['name']] = component
|
self.components[metadata["name"]] = component
|
||||||
|
|
||||||
def register_components(self, components: List[Component]) -> None:
|
def register_components(self, components: List[Component]) -> None:
|
||||||
"""
|
"""
|
||||||
Register multiple components
|
Register multiple components
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
components: List of component instances
|
components: List of component instances
|
||||||
"""
|
"""
|
||||||
@ -61,13 +63,13 @@ class Installer:
|
|||||||
def resolve_dependencies(self, component_names: List[str]) -> List[str]:
|
def resolve_dependencies(self, component_names: List[str]) -> List[str]:
|
||||||
"""
|
"""
|
||||||
Resolve component dependencies in correct installation order
|
Resolve component dependencies in correct installation order
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
component_names: List of component names to install
|
component_names: List of component names to install
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Ordered list of component names including dependencies
|
Ordered list of component names including dependencies
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
ValueError: If circular dependencies detected or unknown component
|
ValueError: If circular dependencies detected or unknown component
|
||||||
"""
|
"""
|
||||||
@ -79,8 +81,7 @@ class Installer:
|
|||||||
return
|
return
|
||||||
|
|
||||||
if name in resolving:
|
if name in resolving:
|
||||||
raise ValueError(
|
raise ValueError(f"Circular dependency detected involving {name}")
|
||||||
f"Circular dependency detected involving {name}")
|
|
||||||
|
|
||||||
if name not in self.components:
|
if name not in self.components:
|
||||||
raise ValueError(f"Unknown component: {name}")
|
raise ValueError(f"Unknown component: {name}")
|
||||||
@ -103,7 +104,7 @@ class Installer:
|
|||||||
def validate_system_requirements(self) -> Tuple[bool, List[str]]:
|
def validate_system_requirements(self) -> Tuple[bool, List[str]]:
|
||||||
"""
|
"""
|
||||||
Validate system requirements for all registered components
|
Validate system requirements for all registered components
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Tuple of (success: bool, error_messages: List[str])
|
Tuple of (success: bool, error_messages: List[str])
|
||||||
"""
|
"""
|
||||||
@ -134,7 +135,7 @@ class Installer:
|
|||||||
def create_backup(self) -> Optional[Path]:
|
def create_backup(self) -> Optional[Path]:
|
||||||
"""
|
"""
|
||||||
Create backup of existing installation
|
Create backup of existing installation
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Path to backup archive or None if no existing installation
|
Path to backup archive or None if no existing installation
|
||||||
"""
|
"""
|
||||||
@ -174,7 +175,7 @@ class Installer:
|
|||||||
|
|
||||||
# Always create an archive, even if empty, to ensure it's a valid tarball
|
# Always create an archive, even if empty, to ensure it's a valid tarball
|
||||||
base_path = backup_dir / backup_name
|
base_path = backup_dir / backup_name
|
||||||
shutil.make_archive(str(base_path), 'gztar', temp_backup)
|
shutil.make_archive(str(base_path), "gztar", temp_backup)
|
||||||
|
|
||||||
if not any(temp_backup.iterdir()):
|
if not any(temp_backup.iterdir()):
|
||||||
self.logger.warning(
|
self.logger.warning(
|
||||||
@ -184,15 +185,14 @@ class Installer:
|
|||||||
self.backup_path = backup_path
|
self.backup_path = backup_path
|
||||||
return backup_path
|
return backup_path
|
||||||
|
|
||||||
def install_component(self, component_name: str,
|
def install_component(self, component_name: str, config: Dict[str, Any]) -> bool:
|
||||||
config: Dict[str, Any]) -> bool:
|
|
||||||
"""
|
"""
|
||||||
Install a single component
|
Install a single component
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
component_name: Name of component to install
|
component_name: Name of component to install
|
||||||
config: Installation configuration
|
config: Installation configuration
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
True if successful, False otherwise
|
True if successful, False otherwise
|
||||||
"""
|
"""
|
||||||
@ -202,7 +202,11 @@ class Installer:
|
|||||||
component = self.components[component_name]
|
component = self.components[component_name]
|
||||||
|
|
||||||
# Skip if already installed and not in update mode, unless component is reinstallable
|
# Skip if already installed and not in update mode, unless component is reinstallable
|
||||||
if not component.is_reinstallable() and component_name in self.installed_components and not config.get("update_mode"):
|
if (
|
||||||
|
not component.is_reinstallable()
|
||||||
|
and component_name in self.installed_components
|
||||||
|
and not config.get("update_mode")
|
||||||
|
):
|
||||||
self.skipped_components.add(component_name)
|
self.skipped_components.add(component_name)
|
||||||
self.logger.info(f"Skipping already installed component: {component_name}")
|
self.logger.info(f"Skipping already installed component: {component_name}")
|
||||||
return True
|
return True
|
||||||
@ -237,16 +241,16 @@ class Installer:
|
|||||||
self.failed_components.add(component_name)
|
self.failed_components.add(component_name)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def install_components(self,
|
def install_components(
|
||||||
component_names: List[str],
|
self, component_names: List[str], config: Optional[Dict[str, Any]] = None
|
||||||
config: Optional[Dict[str, Any]] = None) -> bool:
|
) -> bool:
|
||||||
"""
|
"""
|
||||||
Install multiple components in dependency order
|
Install multiple components in dependency order
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
component_names: List of component names to install
|
component_names: List of component names to install
|
||||||
config: Installation configuration
|
config: Installation configuration
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
True if all successful, False if any failed
|
True if all successful, False if any failed
|
||||||
"""
|
"""
|
||||||
@ -296,7 +300,9 @@ class Installer:
|
|||||||
all_valid = True
|
all_valid = True
|
||||||
for name in self.updated_components:
|
for name in self.updated_components:
|
||||||
if name not in self.components:
|
if name not in self.components:
|
||||||
self.logger.warning(f"Cannot validate component '{name}' as it was not part of this installation session.")
|
self.logger.warning(
|
||||||
|
f"Cannot validate component '{name}' as it was not part of this installation session."
|
||||||
|
)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
component = self.components[name]
|
component = self.components[name]
|
||||||
@ -315,12 +321,13 @@ class Installer:
|
|||||||
else:
|
else:
|
||||||
self.logger.error("Some components failed validation. Check errors above.")
|
self.logger.error("Some components failed validation. Check errors above.")
|
||||||
|
|
||||||
def update_components(self, component_names: List[str], config: Dict[str, Any]) -> bool:
|
def update_components(
|
||||||
|
self, component_names: List[str], config: Dict[str, Any]
|
||||||
|
) -> bool:
|
||||||
"""Alias for update operation (uses install logic)"""
|
"""Alias for update operation (uses install logic)"""
|
||||||
config["update_mode"] = True
|
config["update_mode"] = True
|
||||||
return self.install_components(component_names, config)
|
return self.install_components(component_names, config)
|
||||||
|
|
||||||
|
|
||||||
def get_installation_summary(self) -> Dict[str, Any]:
|
def get_installation_summary(self) -> Dict[str, Any]:
|
||||||
"""
|
"""
|
||||||
Get summary of installation results
|
Get summary of installation results
|
||||||
@ -329,17 +336,17 @@ class Installer:
|
|||||||
Dict with installation statistics and results
|
Dict with installation statistics and results
|
||||||
"""
|
"""
|
||||||
return {
|
return {
|
||||||
'installed': list(self.installed_components),
|
"installed": list(self.installed_components),
|
||||||
'failed': list(self.failed_components),
|
"failed": list(self.failed_components),
|
||||||
'skipped': list(self.skipped_components),
|
"skipped": list(self.skipped_components),
|
||||||
'backup_path': str(self.backup_path) if self.backup_path else None,
|
"backup_path": str(self.backup_path) if self.backup_path else None,
|
||||||
'install_dir': str(self.install_dir),
|
"install_dir": str(self.install_dir),
|
||||||
'dry_run': self.dry_run
|
"dry_run": self.dry_run,
|
||||||
}
|
}
|
||||||
|
|
||||||
def get_update_summary(self) -> Dict[str, Any]:
|
def get_update_summary(self) -> Dict[str, Any]:
|
||||||
return {
|
return {
|
||||||
'updated': list(self.updated_components),
|
"updated": list(self.updated_components),
|
||||||
'failed': list(self.failed_components),
|
"failed": list(self.failed_components),
|
||||||
'backup_path': str(self.backup_path) if self.backup_path else None
|
"backup_path": str(self.backup_path) if self.backup_path else None,
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,11 +12,11 @@ from ..utils.logger import get_logger
|
|||||||
|
|
||||||
class ComponentRegistry:
|
class ComponentRegistry:
|
||||||
"""Auto-discovery and management of installable components"""
|
"""Auto-discovery and management of installable components"""
|
||||||
|
|
||||||
def __init__(self, components_dir: Path):
|
def __init__(self, components_dir: Path):
|
||||||
"""
|
"""
|
||||||
Initialize component registry
|
Initialize component registry
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
components_dir: Directory containing component modules
|
components_dir: Directory containing component modules
|
||||||
"""
|
"""
|
||||||
@ -26,54 +26,55 @@ class ComponentRegistry:
|
|||||||
self.dependency_graph: Dict[str, Set[str]] = {}
|
self.dependency_graph: Dict[str, Set[str]] = {}
|
||||||
self._discovered = False
|
self._discovered = False
|
||||||
self.logger = get_logger()
|
self.logger = get_logger()
|
||||||
|
|
||||||
def discover_components(self, force_reload: bool = False) -> None:
|
def discover_components(self, force_reload: bool = False) -> None:
|
||||||
"""
|
"""
|
||||||
Auto-discover all component classes in components directory
|
Auto-discover all component classes in components directory
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
force_reload: Force rediscovery even if already done
|
force_reload: Force rediscovery even if already done
|
||||||
"""
|
"""
|
||||||
if self._discovered and not force_reload:
|
if self._discovered and not force_reload:
|
||||||
return
|
return
|
||||||
|
|
||||||
self.component_classes.clear()
|
self.component_classes.clear()
|
||||||
self.component_instances.clear()
|
self.component_instances.clear()
|
||||||
self.dependency_graph.clear()
|
self.dependency_graph.clear()
|
||||||
|
|
||||||
if not self.components_dir.exists():
|
if not self.components_dir.exists():
|
||||||
return
|
return
|
||||||
|
|
||||||
# Add components directory to Python path temporarily
|
# Add components directory to Python path temporarily
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
original_path = sys.path.copy()
|
original_path = sys.path.copy()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Add parent directory to path so we can import setup.components
|
# Add parent directory to path so we can import setup.components
|
||||||
setup_dir = self.components_dir.parent
|
setup_dir = self.components_dir.parent
|
||||||
if str(setup_dir) not in sys.path:
|
if str(setup_dir) not in sys.path:
|
||||||
sys.path.insert(0, str(setup_dir))
|
sys.path.insert(0, str(setup_dir))
|
||||||
|
|
||||||
# Discover all Python files in components directory
|
# Discover all Python files in components directory
|
||||||
for py_file in self.components_dir.glob("*.py"):
|
for py_file in self.components_dir.glob("*.py"):
|
||||||
if py_file.name.startswith("__"):
|
if py_file.name.startswith("__"):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
module_name = py_file.stem
|
module_name = py_file.stem
|
||||||
self._load_component_module(module_name)
|
self._load_component_module(module_name)
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
# Restore original Python path
|
# Restore original Python path
|
||||||
sys.path = original_path
|
sys.path = original_path
|
||||||
|
|
||||||
# Build dependency graph
|
# Build dependency graph
|
||||||
self._build_dependency_graph()
|
self._build_dependency_graph()
|
||||||
self._discovered = True
|
self._discovered = True
|
||||||
|
|
||||||
def _load_component_module(self, module_name: str) -> None:
|
def _load_component_module(self, module_name: str) -> None:
|
||||||
"""
|
"""
|
||||||
Load component classes from a module
|
Load component classes from a module
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
module_name: Name of module to load
|
module_name: Name of module to load
|
||||||
"""
|
"""
|
||||||
@ -81,28 +82,32 @@ class ComponentRegistry:
|
|||||||
# Import the module
|
# Import the module
|
||||||
full_module_name = f"setup.components.{module_name}"
|
full_module_name = f"setup.components.{module_name}"
|
||||||
module = importlib.import_module(full_module_name)
|
module = importlib.import_module(full_module_name)
|
||||||
|
|
||||||
# Find all Component subclasses in the module
|
# Find all Component subclasses in the module
|
||||||
for name, obj in inspect.getmembers(module):
|
for name, obj in inspect.getmembers(module):
|
||||||
if (inspect.isclass(obj) and
|
if (
|
||||||
issubclass(obj, Component) and
|
inspect.isclass(obj)
|
||||||
obj is not Component):
|
and issubclass(obj, Component)
|
||||||
|
and obj is not Component
|
||||||
|
):
|
||||||
|
|
||||||
# Create instance to get metadata
|
# Create instance to get metadata
|
||||||
try:
|
try:
|
||||||
instance = obj()
|
instance = obj()
|
||||||
metadata = instance.get_metadata()
|
metadata = instance.get_metadata()
|
||||||
component_name = metadata["name"]
|
component_name = metadata["name"]
|
||||||
|
|
||||||
self.component_classes[component_name] = obj
|
self.component_classes[component_name] = obj
|
||||||
self.component_instances[component_name] = instance
|
self.component_instances[component_name] = instance
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.warning(f"Could not instantiate component {name}: {e}")
|
self.logger.warning(
|
||||||
|
f"Could not instantiate component {name}: {e}"
|
||||||
|
)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.warning(f"Could not load component module {module_name}: {e}")
|
self.logger.warning(f"Could not load component module {module_name}: {e}")
|
||||||
|
|
||||||
def _build_dependency_graph(self) -> None:
|
def _build_dependency_graph(self) -> None:
|
||||||
"""Build dependency graph for all discovered components"""
|
"""Build dependency graph for all discovered components"""
|
||||||
for name, instance in self.component_instances.items():
|
for name, instance in self.component_instances.items():
|
||||||
@ -112,33 +117,35 @@ class ComponentRegistry:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.warning(f"Could not get dependencies for {name}: {e}")
|
self.logger.warning(f"Could not get dependencies for {name}: {e}")
|
||||||
self.dependency_graph[name] = set()
|
self.dependency_graph[name] = set()
|
||||||
|
|
||||||
def get_component_class(self, component_name: str) -> Optional[Type[Component]]:
|
def get_component_class(self, component_name: str) -> Optional[Type[Component]]:
|
||||||
"""
|
"""
|
||||||
Get component class by name
|
Get component class by name
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
component_name: Name of component
|
component_name: Name of component
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Component class or None if not found
|
Component class or None if not found
|
||||||
"""
|
"""
|
||||||
self.discover_components()
|
self.discover_components()
|
||||||
return self.component_classes.get(component_name)
|
return self.component_classes.get(component_name)
|
||||||
|
|
||||||
def get_component_instance(self, component_name: str, install_dir: Optional[Path] = None) -> Optional[Component]:
|
def get_component_instance(
|
||||||
|
self, component_name: str, install_dir: Optional[Path] = None
|
||||||
|
) -> Optional[Component]:
|
||||||
"""
|
"""
|
||||||
Get component instance by name
|
Get component instance by name
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
component_name: Name of component
|
component_name: Name of component
|
||||||
install_dir: Installation directory (creates new instance with this dir)
|
install_dir: Installation directory (creates new instance with this dir)
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Component instance or None if not found
|
Component instance or None if not found
|
||||||
"""
|
"""
|
||||||
self.discover_components()
|
self.discover_components()
|
||||||
|
|
||||||
if install_dir is not None:
|
if install_dir is not None:
|
||||||
# Create new instance with specified install directory
|
# Create new instance with specified install directory
|
||||||
component_class = self.component_classes.get(component_name)
|
component_class = self.component_classes.get(component_name)
|
||||||
@ -146,28 +153,30 @@ class ComponentRegistry:
|
|||||||
try:
|
try:
|
||||||
return component_class(install_dir)
|
return component_class(install_dir)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.error(f"Error creating component instance {component_name}: {e}")
|
self.logger.error(
|
||||||
|
f"Error creating component instance {component_name}: {e}"
|
||||||
|
)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
return self.component_instances.get(component_name)
|
return self.component_instances.get(component_name)
|
||||||
|
|
||||||
def list_components(self) -> List[str]:
|
def list_components(self) -> List[str]:
|
||||||
"""
|
"""
|
||||||
Get list of all discovered component names
|
Get list of all discovered component names
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
List of component names
|
List of component names
|
||||||
"""
|
"""
|
||||||
self.discover_components()
|
self.discover_components()
|
||||||
return list(self.component_classes.keys())
|
return list(self.component_classes.keys())
|
||||||
|
|
||||||
def get_component_metadata(self, component_name: str) -> Optional[Dict[str, str]]:
|
def get_component_metadata(self, component_name: str) -> Optional[Dict[str, str]]:
|
||||||
"""
|
"""
|
||||||
Get metadata for a component
|
Get metadata for a component
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
component_name: Name of component
|
component_name: Name of component
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Component metadata dict or None if not found
|
Component metadata dict or None if not found
|
||||||
"""
|
"""
|
||||||
@ -179,121 +188,123 @@ class ComponentRegistry:
|
|||||||
except Exception:
|
except Exception:
|
||||||
return None
|
return None
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def resolve_dependencies(self, component_names: List[str]) -> List[str]:
|
def resolve_dependencies(self, component_names: List[str]) -> List[str]:
|
||||||
"""
|
"""
|
||||||
Resolve component dependencies in correct installation order
|
Resolve component dependencies in correct installation order
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
component_names: List of component names to install
|
component_names: List of component names to install
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Ordered list of component names including dependencies
|
Ordered list of component names including dependencies
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
ValueError: If circular dependencies detected or unknown component
|
ValueError: If circular dependencies detected or unknown component
|
||||||
"""
|
"""
|
||||||
self.discover_components()
|
self.discover_components()
|
||||||
|
|
||||||
resolved = []
|
resolved = []
|
||||||
resolving = set()
|
resolving = set()
|
||||||
|
|
||||||
def resolve(name: str):
|
def resolve(name: str):
|
||||||
if name in resolved:
|
if name in resolved:
|
||||||
return
|
return
|
||||||
|
|
||||||
if name in resolving:
|
if name in resolving:
|
||||||
raise ValueError(f"Circular dependency detected involving {name}")
|
raise ValueError(f"Circular dependency detected involving {name}")
|
||||||
|
|
||||||
if name not in self.dependency_graph:
|
if name not in self.dependency_graph:
|
||||||
raise ValueError(f"Unknown component: {name}")
|
raise ValueError(f"Unknown component: {name}")
|
||||||
|
|
||||||
resolving.add(name)
|
resolving.add(name)
|
||||||
|
|
||||||
# Resolve dependencies first
|
# Resolve dependencies first
|
||||||
for dep in self.dependency_graph[name]:
|
for dep in self.dependency_graph[name]:
|
||||||
resolve(dep)
|
resolve(dep)
|
||||||
|
|
||||||
resolving.remove(name)
|
resolving.remove(name)
|
||||||
resolved.append(name)
|
resolved.append(name)
|
||||||
|
|
||||||
# Resolve each requested component
|
# Resolve each requested component
|
||||||
for name in component_names:
|
for name in component_names:
|
||||||
resolve(name)
|
resolve(name)
|
||||||
|
|
||||||
return resolved
|
return resolved
|
||||||
|
|
||||||
def get_dependencies(self, component_name: str) -> Set[str]:
|
def get_dependencies(self, component_name: str) -> Set[str]:
|
||||||
"""
|
"""
|
||||||
Get direct dependencies for a component
|
Get direct dependencies for a component
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
component_name: Name of component
|
component_name: Name of component
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Set of dependency component names
|
Set of dependency component names
|
||||||
"""
|
"""
|
||||||
self.discover_components()
|
self.discover_components()
|
||||||
return self.dependency_graph.get(component_name, set())
|
return self.dependency_graph.get(component_name, set())
|
||||||
|
|
||||||
def get_dependents(self, component_name: str) -> Set[str]:
|
def get_dependents(self, component_name: str) -> Set[str]:
|
||||||
"""
|
"""
|
||||||
Get components that depend on the given component
|
Get components that depend on the given component
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
component_name: Name of component
|
component_name: Name of component
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Set of component names that depend on this component
|
Set of component names that depend on this component
|
||||||
"""
|
"""
|
||||||
self.discover_components()
|
self.discover_components()
|
||||||
dependents = set()
|
dependents = set()
|
||||||
|
|
||||||
for name, deps in self.dependency_graph.items():
|
for name, deps in self.dependency_graph.items():
|
||||||
if component_name in deps:
|
if component_name in deps:
|
||||||
dependents.add(name)
|
dependents.add(name)
|
||||||
|
|
||||||
return dependents
|
return dependents
|
||||||
|
|
||||||
def validate_dependency_graph(self) -> List[str]:
|
def validate_dependency_graph(self) -> List[str]:
|
||||||
"""
|
"""
|
||||||
Validate dependency graph for cycles and missing dependencies
|
Validate dependency graph for cycles and missing dependencies
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
List of validation errors (empty if valid)
|
List of validation errors (empty if valid)
|
||||||
"""
|
"""
|
||||||
self.discover_components()
|
self.discover_components()
|
||||||
errors = []
|
errors = []
|
||||||
|
|
||||||
# Check for missing dependencies
|
# Check for missing dependencies
|
||||||
all_components = set(self.dependency_graph.keys())
|
all_components = set(self.dependency_graph.keys())
|
||||||
for name, deps in self.dependency_graph.items():
|
for name, deps in self.dependency_graph.items():
|
||||||
missing_deps = deps - all_components
|
missing_deps = deps - all_components
|
||||||
if missing_deps:
|
if missing_deps:
|
||||||
errors.append(f"Component {name} has missing dependencies: {missing_deps}")
|
errors.append(
|
||||||
|
f"Component {name} has missing dependencies: {missing_deps}"
|
||||||
|
)
|
||||||
|
|
||||||
# Check for circular dependencies
|
# Check for circular dependencies
|
||||||
for name in all_components:
|
for name in all_components:
|
||||||
try:
|
try:
|
||||||
self.resolve_dependencies([name])
|
self.resolve_dependencies([name])
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
errors.append(str(e))
|
errors.append(str(e))
|
||||||
|
|
||||||
return errors
|
return errors
|
||||||
|
|
||||||
def get_components_by_category(self, category: str) -> List[str]:
|
def get_components_by_category(self, category: str) -> List[str]:
|
||||||
"""
|
"""
|
||||||
Get components filtered by category
|
Get components filtered by category
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
category: Component category to filter by
|
category: Component category to filter by
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
List of component names in the category
|
List of component names in the category
|
||||||
"""
|
"""
|
||||||
self.discover_components()
|
self.discover_components()
|
||||||
components = []
|
components = []
|
||||||
|
|
||||||
for name, instance in self.component_instances.items():
|
for name, instance in self.component_instances.items():
|
||||||
try:
|
try:
|
||||||
metadata = instance.get_metadata()
|
metadata = instance.get_metadata()
|
||||||
@ -301,80 +312,84 @@ class ComponentRegistry:
|
|||||||
components.append(name)
|
components.append(name)
|
||||||
except Exception:
|
except Exception:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
return components
|
return components
|
||||||
|
|
||||||
def get_installation_order(self, component_names: List[str]) -> List[List[str]]:
|
def get_installation_order(self, component_names: List[str]) -> List[List[str]]:
|
||||||
"""
|
"""
|
||||||
Get installation order grouped by dependency levels
|
Get installation order grouped by dependency levels
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
component_names: List of component names to install
|
component_names: List of component names to install
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
List of lists, where each inner list contains components
|
List of lists, where each inner list contains components
|
||||||
that can be installed in parallel at that dependency level
|
that can be installed in parallel at that dependency level
|
||||||
"""
|
"""
|
||||||
self.discover_components()
|
self.discover_components()
|
||||||
|
|
||||||
# Get all components including dependencies
|
# Get all components including dependencies
|
||||||
all_components = set(self.resolve_dependencies(component_names))
|
all_components = set(self.resolve_dependencies(component_names))
|
||||||
|
|
||||||
# Group by dependency level
|
# Group by dependency level
|
||||||
levels = []
|
levels = []
|
||||||
remaining = all_components.copy()
|
remaining = all_components.copy()
|
||||||
|
|
||||||
while remaining:
|
while remaining:
|
||||||
# Find components with no unresolved dependencies
|
# Find components with no unresolved dependencies
|
||||||
current_level = []
|
current_level = []
|
||||||
for name in list(remaining):
|
for name in list(remaining):
|
||||||
deps = self.dependency_graph.get(name, set())
|
deps = self.dependency_graph.get(name, set())
|
||||||
unresolved_deps = deps & remaining
|
unresolved_deps = deps & remaining
|
||||||
|
|
||||||
if not unresolved_deps:
|
if not unresolved_deps:
|
||||||
current_level.append(name)
|
current_level.append(name)
|
||||||
|
|
||||||
if not current_level:
|
if not current_level:
|
||||||
# This shouldn't happen if dependency graph is valid
|
# This shouldn't happen if dependency graph is valid
|
||||||
raise ValueError("Circular dependency detected in installation order calculation")
|
raise ValueError(
|
||||||
|
"Circular dependency detected in installation order calculation"
|
||||||
|
)
|
||||||
|
|
||||||
levels.append(current_level)
|
levels.append(current_level)
|
||||||
remaining -= set(current_level)
|
remaining -= set(current_level)
|
||||||
|
|
||||||
return levels
|
return levels
|
||||||
|
|
||||||
def create_component_instances(self, component_names: List[str], install_dir: Optional[Path] = None) -> Dict[str, Component]:
|
def create_component_instances(
|
||||||
|
self, component_names: List[str], install_dir: Optional[Path] = None
|
||||||
|
) -> Dict[str, Component]:
|
||||||
"""
|
"""
|
||||||
Create instances for multiple components
|
Create instances for multiple components
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
component_names: List of component names
|
component_names: List of component names
|
||||||
install_dir: Installation directory for instances
|
install_dir: Installation directory for instances
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Dict mapping component names to instances
|
Dict mapping component names to instances
|
||||||
"""
|
"""
|
||||||
self.discover_components()
|
self.discover_components()
|
||||||
instances = {}
|
instances = {}
|
||||||
|
|
||||||
for name in component_names:
|
for name in component_names:
|
||||||
instance = self.get_component_instance(name, install_dir)
|
instance = self.get_component_instance(name, install_dir)
|
||||||
if instance:
|
if instance:
|
||||||
instances[name] = instance
|
instances[name] = instance
|
||||||
else:
|
else:
|
||||||
self.logger.warning(f"Could not create instance for component {name}")
|
self.logger.warning(f"Could not create instance for component {name}")
|
||||||
|
|
||||||
return instances
|
return instances
|
||||||
|
|
||||||
def get_registry_info(self) -> Dict[str, any]:
|
def get_registry_info(self) -> Dict[str, any]:
|
||||||
"""
|
"""
|
||||||
Get comprehensive registry information
|
Get comprehensive registry information
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Dict with registry statistics and component info
|
Dict with registry statistics and component info
|
||||||
"""
|
"""
|
||||||
self.discover_components()
|
self.discover_components()
|
||||||
|
|
||||||
# Group components by category
|
# Group components by category
|
||||||
categories = {}
|
categories = {}
|
||||||
for name, instance in self.component_instances.items():
|
for name, instance in self.component_instances.items():
|
||||||
@ -388,10 +403,12 @@ class ComponentRegistry:
|
|||||||
if "unknown" not in categories:
|
if "unknown" not in categories:
|
||||||
categories["unknown"] = []
|
categories["unknown"] = []
|
||||||
categories["unknown"].append(name)
|
categories["unknown"].append(name)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"total_components": len(self.component_classes),
|
"total_components": len(self.component_classes),
|
||||||
"categories": categories,
|
"categories": categories,
|
||||||
"dependency_graph": {name: list(deps) for name, deps in self.dependency_graph.items()},
|
"dependency_graph": {
|
||||||
"validation_errors": self.validate_dependency_graph()
|
name: list(deps) for name, deps in self.dependency_graph.items()
|
||||||
}
|
},
|
||||||
|
"validation_errors": self.validate_dependency_graph(),
|
||||||
|
}
|
||||||
|
|||||||
@ -13,19 +13,20 @@ from ..utils.paths import get_home_directory
|
|||||||
# Handle packaging import - if not available, use a simple version comparison
|
# Handle packaging import - if not available, use a simple version comparison
|
||||||
try:
|
try:
|
||||||
from packaging import version
|
from packaging import version
|
||||||
|
|
||||||
PACKAGING_AVAILABLE = True
|
PACKAGING_AVAILABLE = True
|
||||||
except ImportError:
|
except ImportError:
|
||||||
PACKAGING_AVAILABLE = False
|
PACKAGING_AVAILABLE = False
|
||||||
|
|
||||||
class SimpleVersion:
|
class SimpleVersion:
|
||||||
def __init__(self, version_str: str):
|
def __init__(self, version_str: str):
|
||||||
self.version_str = version_str
|
self.version_str = version_str
|
||||||
# Simple version parsing: split by dots and convert to integers
|
# Simple version parsing: split by dots and convert to integers
|
||||||
try:
|
try:
|
||||||
self.parts = [int(x) for x in version_str.split('.')]
|
self.parts = [int(x) for x in version_str.split(".")]
|
||||||
except ValueError:
|
except ValueError:
|
||||||
self.parts = [0, 0, 0]
|
self.parts = [0, 0, 0]
|
||||||
|
|
||||||
def __lt__(self, other):
|
def __lt__(self, other):
|
||||||
if isinstance(other, str):
|
if isinstance(other, str):
|
||||||
other = SimpleVersion(other)
|
other = SimpleVersion(other)
|
||||||
@ -34,17 +35,17 @@ except ImportError:
|
|||||||
self_parts = self.parts + [0] * (max_len - len(self.parts))
|
self_parts = self.parts + [0] * (max_len - len(self.parts))
|
||||||
other_parts = other.parts + [0] * (max_len - len(other.parts))
|
other_parts = other.parts + [0] * (max_len - len(other.parts))
|
||||||
return self_parts < other_parts
|
return self_parts < other_parts
|
||||||
|
|
||||||
def __gt__(self, other):
|
def __gt__(self, other):
|
||||||
if isinstance(other, str):
|
if isinstance(other, str):
|
||||||
other = SimpleVersion(other)
|
other = SimpleVersion(other)
|
||||||
return not (self < other) and not (self == other)
|
return not (self < other) and not (self == other)
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
if isinstance(other, str):
|
if isinstance(other, str):
|
||||||
other = SimpleVersion(other)
|
other = SimpleVersion(other)
|
||||||
return self.parts == other.parts
|
return self.parts == other.parts
|
||||||
|
|
||||||
class version:
|
class version:
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def parse(version_str: str):
|
def parse(version_str: str):
|
||||||
@ -53,107 +54,127 @@ except ImportError:
|
|||||||
|
|
||||||
class Validator:
|
class Validator:
|
||||||
"""System requirements validator"""
|
"""System requirements validator"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
"""Initialize validator"""
|
"""Initialize validator"""
|
||||||
self.validation_cache: Dict[str, Any] = {}
|
self.validation_cache: Dict[str, Any] = {}
|
||||||
|
|
||||||
def check_python(self, min_version: str = "3.8", max_version: Optional[str] = None) -> Tuple[bool, str]:
|
def check_python(
|
||||||
|
self, min_version: str = "3.8", max_version: Optional[str] = None
|
||||||
|
) -> Tuple[bool, str]:
|
||||||
"""
|
"""
|
||||||
Check Python version requirements
|
Check Python version requirements
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
min_version: Minimum required Python version
|
min_version: Minimum required Python version
|
||||||
max_version: Maximum supported Python version (optional)
|
max_version: Maximum supported Python version (optional)
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Tuple of (success: bool, message: str)
|
Tuple of (success: bool, message: str)
|
||||||
"""
|
"""
|
||||||
cache_key = f"python_{min_version}_{max_version}"
|
cache_key = f"python_{min_version}_{max_version}"
|
||||||
if cache_key in self.validation_cache:
|
if cache_key in self.validation_cache:
|
||||||
return self.validation_cache[cache_key]
|
return self.validation_cache[cache_key]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Get current Python version
|
# Get current Python version
|
||||||
current_version = f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}"
|
current_version = f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}"
|
||||||
|
|
||||||
# Check minimum version
|
# Check minimum version
|
||||||
if version.parse(current_version) < version.parse(min_version):
|
if version.parse(current_version) < version.parse(min_version):
|
||||||
help_msg = self.get_installation_help("python")
|
help_msg = self.get_installation_help("python")
|
||||||
result = (False, f"Python {min_version}+ required, found {current_version}{help_msg}")
|
result = (
|
||||||
|
False,
|
||||||
|
f"Python {min_version}+ required, found {current_version}{help_msg}",
|
||||||
|
)
|
||||||
self.validation_cache[cache_key] = result
|
self.validation_cache[cache_key] = result
|
||||||
return result
|
return result
|
||||||
|
|
||||||
# Check maximum version if specified
|
# Check maximum version if specified
|
||||||
if max_version and version.parse(current_version) > version.parse(max_version):
|
if max_version and version.parse(current_version) > version.parse(
|
||||||
result = (False, f"Python version {current_version} exceeds maximum supported {max_version}")
|
max_version
|
||||||
|
):
|
||||||
|
result = (
|
||||||
|
False,
|
||||||
|
f"Python version {current_version} exceeds maximum supported {max_version}",
|
||||||
|
)
|
||||||
self.validation_cache[cache_key] = result
|
self.validation_cache[cache_key] = result
|
||||||
return result
|
return result
|
||||||
|
|
||||||
result = (True, f"Python {current_version} meets requirements")
|
result = (True, f"Python {current_version} meets requirements")
|
||||||
self.validation_cache[cache_key] = result
|
self.validation_cache[cache_key] = result
|
||||||
return result
|
return result
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
result = (False, f"Could not check Python version: {e}")
|
result = (False, f"Could not check Python version: {e}")
|
||||||
self.validation_cache[cache_key] = result
|
self.validation_cache[cache_key] = result
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def check_node(self, min_version: str = "16.0", max_version: Optional[str] = None) -> Tuple[bool, str]:
|
def check_node(
|
||||||
|
self, min_version: str = "16.0", max_version: Optional[str] = None
|
||||||
|
) -> Tuple[bool, str]:
|
||||||
"""
|
"""
|
||||||
Check Node.js version requirements
|
Check Node.js version requirements
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
min_version: Minimum required Node.js version
|
min_version: Minimum required Node.js version
|
||||||
max_version: Maximum supported Node.js version (optional)
|
max_version: Maximum supported Node.js version (optional)
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Tuple of (success: bool, message: str)
|
Tuple of (success: bool, message: str)
|
||||||
"""
|
"""
|
||||||
cache_key = f"node_{min_version}_{max_version}"
|
cache_key = f"node_{min_version}_{max_version}"
|
||||||
if cache_key in self.validation_cache:
|
if cache_key in self.validation_cache:
|
||||||
return self.validation_cache[cache_key]
|
return self.validation_cache[cache_key]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Check if node is installed - use shell=True on Windows for better PATH resolution
|
# Check if node is installed - use shell=True on Windows for better PATH resolution
|
||||||
result = subprocess.run(
|
result = subprocess.run(
|
||||||
['node', '--version'],
|
["node", "--version"],
|
||||||
capture_output=True,
|
capture_output=True,
|
||||||
text=True,
|
text=True,
|
||||||
timeout=10,
|
timeout=10,
|
||||||
shell=(sys.platform == "win32")
|
shell=(sys.platform == "win32"),
|
||||||
)
|
)
|
||||||
|
|
||||||
if result.returncode != 0:
|
if result.returncode != 0:
|
||||||
help_msg = self.get_installation_help("node")
|
help_msg = self.get_installation_help("node")
|
||||||
result_tuple = (False, f"Node.js not found in PATH{help_msg}")
|
result_tuple = (False, f"Node.js not found in PATH{help_msg}")
|
||||||
self.validation_cache[cache_key] = result_tuple
|
self.validation_cache[cache_key] = result_tuple
|
||||||
return result_tuple
|
return result_tuple
|
||||||
|
|
||||||
# Parse version (format: v18.17.0)
|
# Parse version (format: v18.17.0)
|
||||||
version_output = result.stdout.strip()
|
version_output = result.stdout.strip()
|
||||||
if version_output.startswith('v'):
|
if version_output.startswith("v"):
|
||||||
current_version = version_output[1:]
|
current_version = version_output[1:]
|
||||||
else:
|
else:
|
||||||
current_version = version_output
|
current_version = version_output
|
||||||
|
|
||||||
# Check minimum version
|
# Check minimum version
|
||||||
if version.parse(current_version) < version.parse(min_version):
|
if version.parse(current_version) < version.parse(min_version):
|
||||||
help_msg = self.get_installation_help("node")
|
help_msg = self.get_installation_help("node")
|
||||||
result_tuple = (False, f"Node.js {min_version}+ required, found {current_version}{help_msg}")
|
result_tuple = (
|
||||||
|
False,
|
||||||
|
f"Node.js {min_version}+ required, found {current_version}{help_msg}",
|
||||||
|
)
|
||||||
self.validation_cache[cache_key] = result_tuple
|
self.validation_cache[cache_key] = result_tuple
|
||||||
return result_tuple
|
return result_tuple
|
||||||
|
|
||||||
# Check maximum version if specified
|
# Check maximum version if specified
|
||||||
if max_version and version.parse(current_version) > version.parse(max_version):
|
if max_version and version.parse(current_version) > version.parse(
|
||||||
result_tuple = (False, f"Node.js version {current_version} exceeds maximum supported {max_version}")
|
max_version
|
||||||
|
):
|
||||||
|
result_tuple = (
|
||||||
|
False,
|
||||||
|
f"Node.js version {current_version} exceeds maximum supported {max_version}",
|
||||||
|
)
|
||||||
self.validation_cache[cache_key] = result_tuple
|
self.validation_cache[cache_key] = result_tuple
|
||||||
return result_tuple
|
return result_tuple
|
||||||
|
|
||||||
result_tuple = (True, f"Node.js {current_version} meets requirements")
|
result_tuple = (True, f"Node.js {current_version} meets requirements")
|
||||||
self.validation_cache[cache_key] = result_tuple
|
self.validation_cache[cache_key] = result_tuple
|
||||||
return result_tuple
|
return result_tuple
|
||||||
|
|
||||||
except subprocess.TimeoutExpired:
|
except subprocess.TimeoutExpired:
|
||||||
result_tuple = (False, "Node.js version check timed out")
|
result_tuple = (False, "Node.js version check timed out")
|
||||||
self.validation_cache[cache_key] = result_tuple
|
self.validation_cache[cache_key] = result_tuple
|
||||||
@ -167,58 +188,63 @@ class Validator:
|
|||||||
result_tuple = (False, f"Could not check Node.js version: {e}")
|
result_tuple = (False, f"Could not check Node.js version: {e}")
|
||||||
self.validation_cache[cache_key] = result_tuple
|
self.validation_cache[cache_key] = result_tuple
|
||||||
return result_tuple
|
return result_tuple
|
||||||
|
|
||||||
def check_claude_cli(self, min_version: Optional[str] = None) -> Tuple[bool, str]:
|
def check_claude_cli(self, min_version: Optional[str] = None) -> Tuple[bool, str]:
|
||||||
"""
|
"""
|
||||||
Check Claude CLI installation and version
|
Check Claude CLI installation and version
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
min_version: Minimum required Claude CLI version (optional)
|
min_version: Minimum required Claude CLI version (optional)
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Tuple of (success: bool, message: str)
|
Tuple of (success: bool, message: str)
|
||||||
"""
|
"""
|
||||||
cache_key = f"claude_cli_{min_version}"
|
cache_key = f"claude_cli_{min_version}"
|
||||||
if cache_key in self.validation_cache:
|
if cache_key in self.validation_cache:
|
||||||
return self.validation_cache[cache_key]
|
return self.validation_cache[cache_key]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Check if claude is installed - use shell=True on Windows for better PATH resolution
|
# Check if claude is installed - use shell=True on Windows for better PATH resolution
|
||||||
result = subprocess.run(
|
result = subprocess.run(
|
||||||
['claude', '--version'],
|
["claude", "--version"],
|
||||||
capture_output=True,
|
capture_output=True,
|
||||||
text=True,
|
text=True,
|
||||||
timeout=10,
|
timeout=10,
|
||||||
shell=(sys.platform == "win32")
|
shell=(sys.platform == "win32"),
|
||||||
)
|
)
|
||||||
|
|
||||||
if result.returncode != 0:
|
if result.returncode != 0:
|
||||||
help_msg = self.get_installation_help("claude_cli")
|
help_msg = self.get_installation_help("claude_cli")
|
||||||
result_tuple = (False, f"Claude CLI not found in PATH{help_msg}")
|
result_tuple = (False, f"Claude CLI not found in PATH{help_msg}")
|
||||||
self.validation_cache[cache_key] = result_tuple
|
self.validation_cache[cache_key] = result_tuple
|
||||||
return result_tuple
|
return result_tuple
|
||||||
|
|
||||||
# Parse version from output
|
# Parse version from output
|
||||||
version_output = result.stdout.strip()
|
version_output = result.stdout.strip()
|
||||||
version_match = re.search(r'(\d+\.\d+\.\d+)', version_output)
|
version_match = re.search(r"(\d+\.\d+\.\d+)", version_output)
|
||||||
|
|
||||||
if not version_match:
|
if not version_match:
|
||||||
result_tuple = (True, "Claude CLI found (version format unknown)")
|
result_tuple = (True, "Claude CLI found (version format unknown)")
|
||||||
self.validation_cache[cache_key] = result_tuple
|
self.validation_cache[cache_key] = result_tuple
|
||||||
return result_tuple
|
return result_tuple
|
||||||
|
|
||||||
current_version = version_match.group(1)
|
current_version = version_match.group(1)
|
||||||
|
|
||||||
# Check minimum version if specified
|
# Check minimum version if specified
|
||||||
if min_version and version.parse(current_version) < version.parse(min_version):
|
if min_version and version.parse(current_version) < version.parse(
|
||||||
result_tuple = (False, f"Claude CLI {min_version}+ required, found {current_version}")
|
min_version
|
||||||
|
):
|
||||||
|
result_tuple = (
|
||||||
|
False,
|
||||||
|
f"Claude CLI {min_version}+ required, found {current_version}",
|
||||||
|
)
|
||||||
self.validation_cache[cache_key] = result_tuple
|
self.validation_cache[cache_key] = result_tuple
|
||||||
return result_tuple
|
return result_tuple
|
||||||
|
|
||||||
result_tuple = (True, f"Claude CLI {current_version} found")
|
result_tuple = (True, f"Claude CLI {current_version} found")
|
||||||
self.validation_cache[cache_key] = result_tuple
|
self.validation_cache[cache_key] = result_tuple
|
||||||
return result_tuple
|
return result_tuple
|
||||||
|
|
||||||
except subprocess.TimeoutExpired:
|
except subprocess.TimeoutExpired:
|
||||||
result_tuple = (False, "Claude CLI version check timed out")
|
result_tuple = (False, "Claude CLI version check timed out")
|
||||||
self.validation_cache[cache_key] = result_tuple
|
self.validation_cache[cache_key] = result_tuple
|
||||||
@ -232,53 +258,58 @@ class Validator:
|
|||||||
result_tuple = (False, f"Could not check Claude CLI: {e}")
|
result_tuple = (False, f"Could not check Claude CLI: {e}")
|
||||||
self.validation_cache[cache_key] = result_tuple
|
self.validation_cache[cache_key] = result_tuple
|
||||||
return result_tuple
|
return result_tuple
|
||||||
|
|
||||||
def check_external_tool(self, tool_name: str, command: str, min_version: Optional[str] = None) -> Tuple[bool, str]:
|
def check_external_tool(
|
||||||
|
self, tool_name: str, command: str, min_version: Optional[str] = None
|
||||||
|
) -> Tuple[bool, str]:
|
||||||
"""
|
"""
|
||||||
Check external tool availability and version
|
Check external tool availability and version
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
tool_name: Display name of tool
|
tool_name: Display name of tool
|
||||||
command: Command to check version
|
command: Command to check version
|
||||||
min_version: Minimum required version (optional)
|
min_version: Minimum required version (optional)
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Tuple of (success: bool, message: str)
|
Tuple of (success: bool, message: str)
|
||||||
"""
|
"""
|
||||||
cache_key = f"tool_{tool_name}_{command}_{min_version}"
|
cache_key = f"tool_{tool_name}_{command}_{min_version}"
|
||||||
if cache_key in self.validation_cache:
|
if cache_key in self.validation_cache:
|
||||||
return self.validation_cache[cache_key]
|
return self.validation_cache[cache_key]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Split command into parts
|
# Split command into parts
|
||||||
cmd_parts = command.split()
|
cmd_parts = command.split()
|
||||||
|
|
||||||
result = subprocess.run(
|
result = subprocess.run(
|
||||||
cmd_parts,
|
cmd_parts,
|
||||||
capture_output=True,
|
capture_output=True,
|
||||||
text=True,
|
text=True,
|
||||||
timeout=10,
|
timeout=10,
|
||||||
shell=(sys.platform == "win32")
|
shell=(sys.platform == "win32"),
|
||||||
)
|
)
|
||||||
|
|
||||||
if result.returncode != 0:
|
if result.returncode != 0:
|
||||||
result_tuple = (False, f"{tool_name} not found or command failed")
|
result_tuple = (False, f"{tool_name} not found or command failed")
|
||||||
self.validation_cache[cache_key] = result_tuple
|
self.validation_cache[cache_key] = result_tuple
|
||||||
return result_tuple
|
return result_tuple
|
||||||
|
|
||||||
# Extract version if min_version specified
|
# Extract version if min_version specified
|
||||||
if min_version:
|
if min_version:
|
||||||
version_output = result.stdout + result.stderr
|
version_output = result.stdout + result.stderr
|
||||||
version_match = re.search(r'(\d+\.\d+(?:\.\d+)?)', version_output)
|
version_match = re.search(r"(\d+\.\d+(?:\.\d+)?)", version_output)
|
||||||
|
|
||||||
if version_match:
|
if version_match:
|
||||||
current_version = version_match.group(1)
|
current_version = version_match.group(1)
|
||||||
|
|
||||||
if version.parse(current_version) < version.parse(min_version):
|
if version.parse(current_version) < version.parse(min_version):
|
||||||
result_tuple = (False, f"{tool_name} {min_version}+ required, found {current_version}")
|
result_tuple = (
|
||||||
|
False,
|
||||||
|
f"{tool_name} {min_version}+ required, found {current_version}",
|
||||||
|
)
|
||||||
self.validation_cache[cache_key] = result_tuple
|
self.validation_cache[cache_key] = result_tuple
|
||||||
return result_tuple
|
return result_tuple
|
||||||
|
|
||||||
result_tuple = (True, f"{tool_name} {current_version} found")
|
result_tuple = (True, f"{tool_name} {current_version} found")
|
||||||
self.validation_cache[cache_key] = result_tuple
|
self.validation_cache[cache_key] = result_tuple
|
||||||
return result_tuple
|
return result_tuple
|
||||||
@ -290,7 +321,7 @@ class Validator:
|
|||||||
result_tuple = (True, f"{tool_name} found")
|
result_tuple = (True, f"{tool_name} found")
|
||||||
self.validation_cache[cache_key] = result_tuple
|
self.validation_cache[cache_key] = result_tuple
|
||||||
return result_tuple
|
return result_tuple
|
||||||
|
|
||||||
except subprocess.TimeoutExpired:
|
except subprocess.TimeoutExpired:
|
||||||
result_tuple = (False, f"{tool_name} check timed out")
|
result_tuple = (False, f"{tool_name} check timed out")
|
||||||
self.validation_cache[cache_key] = result_tuple
|
self.validation_cache[cache_key] = result_tuple
|
||||||
@ -303,206 +334,208 @@ class Validator:
|
|||||||
result_tuple = (False, f"Could not check {tool_name}: {e}")
|
result_tuple = (False, f"Could not check {tool_name}: {e}")
|
||||||
self.validation_cache[cache_key] = result_tuple
|
self.validation_cache[cache_key] = result_tuple
|
||||||
return result_tuple
|
return result_tuple
|
||||||
|
|
||||||
def check_disk_space(self, path: Path, required_mb: int = 500) -> Tuple[bool, str]:
|
def check_disk_space(self, path: Path, required_mb: int = 500) -> Tuple[bool, str]:
|
||||||
"""
|
"""
|
||||||
Check available disk space
|
Check available disk space
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
path: Path to check (file or directory)
|
path: Path to check (file or directory)
|
||||||
required_mb: Required free space in MB
|
required_mb: Required free space in MB
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Tuple of (success: bool, message: str)
|
Tuple of (success: bool, message: str)
|
||||||
"""
|
"""
|
||||||
cache_key = f"disk_{path}_{required_mb}"
|
cache_key = f"disk_{path}_{required_mb}"
|
||||||
if cache_key in self.validation_cache:
|
if cache_key in self.validation_cache:
|
||||||
return self.validation_cache[cache_key]
|
return self.validation_cache[cache_key]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Get parent directory if path is a file
|
# Get parent directory if path is a file
|
||||||
check_path = path.parent if path.is_file() else path
|
check_path = path.parent if path.is_file() else path
|
||||||
|
|
||||||
# Get disk usage
|
# Get disk usage
|
||||||
stat_result = shutil.disk_usage(check_path)
|
stat_result = shutil.disk_usage(check_path)
|
||||||
free_mb = stat_result.free / (1024 * 1024)
|
free_mb = stat_result.free / (1024 * 1024)
|
||||||
|
|
||||||
if free_mb < required_mb:
|
if free_mb < required_mb:
|
||||||
result = (False, f"Insufficient disk space: {free_mb:.1f}MB free, {required_mb}MB required")
|
result = (
|
||||||
|
False,
|
||||||
|
f"Insufficient disk space: {free_mb:.1f}MB free, {required_mb}MB required",
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
result = (True, f"Sufficient disk space: {free_mb:.1f}MB free")
|
result = (True, f"Sufficient disk space: {free_mb:.1f}MB free")
|
||||||
|
|
||||||
self.validation_cache[cache_key] = result
|
self.validation_cache[cache_key] = result
|
||||||
return result
|
return result
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
result = (False, f"Could not check disk space: {e}")
|
result = (False, f"Could not check disk space: {e}")
|
||||||
self.validation_cache[cache_key] = result
|
self.validation_cache[cache_key] = result
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def check_write_permissions(self, path: Path) -> Tuple[bool, str]:
|
def check_write_permissions(self, path: Path) -> Tuple[bool, str]:
|
||||||
"""
|
"""
|
||||||
Check write permissions for path
|
Check write permissions for path
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
path: Path to check
|
path: Path to check
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Tuple of (success: bool, message: str)
|
Tuple of (success: bool, message: str)
|
||||||
"""
|
"""
|
||||||
cache_key = f"write_{path}"
|
cache_key = f"write_{path}"
|
||||||
if cache_key in self.validation_cache:
|
if cache_key in self.validation_cache:
|
||||||
return self.validation_cache[cache_key]
|
return self.validation_cache[cache_key]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Create parent directories if needed
|
# Create parent directories if needed
|
||||||
if not path.exists():
|
if not path.exists():
|
||||||
path.mkdir(parents=True, exist_ok=True)
|
path.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
# Test write access
|
# Test write access
|
||||||
test_file = path / ".write_test"
|
test_file = path / ".write_test"
|
||||||
test_file.touch()
|
test_file.touch()
|
||||||
test_file.unlink()
|
test_file.unlink()
|
||||||
|
|
||||||
result = (True, f"Write access confirmed for {path}")
|
result = (True, f"Write access confirmed for {path}")
|
||||||
self.validation_cache[cache_key] = result
|
self.validation_cache[cache_key] = result
|
||||||
return result
|
return result
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
result = (False, f"No write access to {path}: {e}")
|
result = (False, f"No write access to {path}: {e}")
|
||||||
self.validation_cache[cache_key] = result
|
self.validation_cache[cache_key] = result
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def validate_requirements(self, requirements: Dict[str, Any]) -> Tuple[bool, List[str]]:
|
def validate_requirements(
|
||||||
|
self, requirements: Dict[str, Any]
|
||||||
|
) -> Tuple[bool, List[str]]:
|
||||||
"""
|
"""
|
||||||
Validate all system requirements
|
Validate all system requirements
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
requirements: Requirements configuration dict
|
requirements: Requirements configuration dict
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Tuple of (all_passed: bool, error_messages: List[str])
|
Tuple of (all_passed: bool, error_messages: List[str])
|
||||||
"""
|
"""
|
||||||
errors = []
|
errors = []
|
||||||
|
|
||||||
# Check Python requirements
|
# Check Python requirements
|
||||||
if "python" in requirements:
|
if "python" in requirements:
|
||||||
python_req = requirements["python"]
|
python_req = requirements["python"]
|
||||||
success, message = self.check_python(
|
success, message = self.check_python(
|
||||||
python_req["min_version"],
|
python_req["min_version"], python_req.get("max_version")
|
||||||
python_req.get("max_version")
|
|
||||||
)
|
)
|
||||||
if not success:
|
if not success:
|
||||||
errors.append(f"Python: {message}")
|
errors.append(f"Python: {message}")
|
||||||
|
|
||||||
# Check Node.js requirements
|
# Check Node.js requirements
|
||||||
if "node" in requirements:
|
if "node" in requirements:
|
||||||
node_req = requirements["node"]
|
node_req = requirements["node"]
|
||||||
success, message = self.check_node(
|
success, message = self.check_node(
|
||||||
node_req["min_version"],
|
node_req["min_version"], node_req.get("max_version")
|
||||||
node_req.get("max_version")
|
|
||||||
)
|
)
|
||||||
if not success:
|
if not success:
|
||||||
errors.append(f"Node.js: {message}")
|
errors.append(f"Node.js: {message}")
|
||||||
|
|
||||||
# Check disk space
|
# Check disk space
|
||||||
if "disk_space_mb" in requirements:
|
if "disk_space_mb" in requirements:
|
||||||
success, message = self.check_disk_space(
|
success, message = self.check_disk_space(
|
||||||
get_home_directory(),
|
get_home_directory(), requirements["disk_space_mb"]
|
||||||
requirements["disk_space_mb"]
|
|
||||||
)
|
)
|
||||||
if not success:
|
if not success:
|
||||||
errors.append(f"Disk space: {message}")
|
errors.append(f"Disk space: {message}")
|
||||||
|
|
||||||
# Check external tools
|
# Check external tools
|
||||||
if "external_tools" in requirements:
|
if "external_tools" in requirements:
|
||||||
for tool_name, tool_req in requirements["external_tools"].items():
|
for tool_name, tool_req in requirements["external_tools"].items():
|
||||||
# Skip optional tools that fail
|
# Skip optional tools that fail
|
||||||
is_optional = tool_req.get("optional", False)
|
is_optional = tool_req.get("optional", False)
|
||||||
|
|
||||||
success, message = self.check_external_tool(
|
success, message = self.check_external_tool(
|
||||||
tool_name,
|
tool_name, tool_req["command"], tool_req.get("min_version")
|
||||||
tool_req["command"],
|
|
||||||
tool_req.get("min_version")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if not success and not is_optional:
|
if not success and not is_optional:
|
||||||
errors.append(f"{tool_name}: {message}")
|
errors.append(f"{tool_name}: {message}")
|
||||||
|
|
||||||
return len(errors) == 0, errors
|
return len(errors) == 0, errors
|
||||||
|
|
||||||
def validate_component_requirements(self, component_names: List[str], all_requirements: Dict[str, Any]) -> Tuple[bool, List[str]]:
|
def validate_component_requirements(
|
||||||
|
self, component_names: List[str], all_requirements: Dict[str, Any]
|
||||||
|
) -> Tuple[bool, List[str]]:
|
||||||
"""
|
"""
|
||||||
Validate requirements for specific components
|
Validate requirements for specific components
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
component_names: List of component names to validate
|
component_names: List of component names to validate
|
||||||
all_requirements: Full requirements configuration
|
all_requirements: Full requirements configuration
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Tuple of (all_passed: bool, error_messages: List[str])
|
Tuple of (all_passed: bool, error_messages: List[str])
|
||||||
"""
|
"""
|
||||||
errors = []
|
errors = []
|
||||||
|
|
||||||
# Start with base requirements
|
# Start with base requirements
|
||||||
base_requirements = {
|
base_requirements = {
|
||||||
"python": all_requirements.get("python", {}),
|
"python": all_requirements.get("python", {}),
|
||||||
"disk_space_mb": all_requirements.get("disk_space_mb", 500)
|
"disk_space_mb": all_requirements.get("disk_space_mb", 500),
|
||||||
}
|
}
|
||||||
|
|
||||||
# Add conditional requirements based on components
|
# Add conditional requirements based on components
|
||||||
external_tools = {}
|
external_tools = {}
|
||||||
|
|
||||||
# Check if any component needs Node.js
|
# Check if any component needs Node.js
|
||||||
node_components = []
|
node_components = []
|
||||||
for component in component_names:
|
for component in component_names:
|
||||||
# This would be enhanced with actual component metadata
|
# This would be enhanced with actual component metadata
|
||||||
if component in ["mcp"]: # MCP component needs Node.js
|
if component in ["mcp"]: # MCP component needs Node.js
|
||||||
node_components.append(component)
|
node_components.append(component)
|
||||||
|
|
||||||
if node_components and "node" in all_requirements:
|
if node_components and "node" in all_requirements:
|
||||||
base_requirements["node"] = all_requirements["node"]
|
base_requirements["node"] = all_requirements["node"]
|
||||||
|
|
||||||
# Add external tools needed by components
|
# Add external tools needed by components
|
||||||
if "external_tools" in all_requirements:
|
if "external_tools" in all_requirements:
|
||||||
for tool_name, tool_req in all_requirements["external_tools"].items():
|
for tool_name, tool_req in all_requirements["external_tools"].items():
|
||||||
required_for = tool_req.get("required_for", [])
|
required_for = tool_req.get("required_for", [])
|
||||||
|
|
||||||
# Check if any of our components need this tool
|
# Check if any of our components need this tool
|
||||||
if any(comp in required_for for comp in component_names):
|
if any(comp in required_for for comp in component_names):
|
||||||
external_tools[tool_name] = tool_req
|
external_tools[tool_name] = tool_req
|
||||||
|
|
||||||
if external_tools:
|
if external_tools:
|
||||||
base_requirements["external_tools"] = external_tools
|
base_requirements["external_tools"] = external_tools
|
||||||
|
|
||||||
# Validate consolidated requirements
|
# Validate consolidated requirements
|
||||||
return self.validate_requirements(base_requirements)
|
return self.validate_requirements(base_requirements)
|
||||||
|
|
||||||
def get_system_info(self) -> Dict[str, Any]:
|
def get_system_info(self) -> Dict[str, Any]:
|
||||||
"""
|
"""
|
||||||
Get comprehensive system information
|
Get comprehensive system information
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Dict with system information
|
Dict with system information
|
||||||
"""
|
"""
|
||||||
info = {
|
info = {
|
||||||
"platform": sys.platform,
|
"platform": sys.platform,
|
||||||
"python_version": f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}",
|
"python_version": f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}",
|
||||||
"python_executable": sys.executable
|
"python_executable": sys.executable,
|
||||||
}
|
}
|
||||||
|
|
||||||
# Add Node.js info if available
|
# Add Node.js info if available
|
||||||
node_success, node_msg = self.check_node()
|
node_success, node_msg = self.check_node()
|
||||||
info["node_available"] = node_success
|
info["node_available"] = node_success
|
||||||
if node_success:
|
if node_success:
|
||||||
info["node_message"] = node_msg
|
info["node_message"] = node_msg
|
||||||
|
|
||||||
# Add Claude CLI info if available
|
# Add Claude CLI info if available
|
||||||
claude_success, claude_msg = self.check_claude_cli()
|
claude_success, claude_msg = self.check_claude_cli()
|
||||||
info["claude_cli_available"] = claude_success
|
info["claude_cli_available"] = claude_success
|
||||||
if claude_success:
|
if claude_success:
|
||||||
info["claude_cli_message"] = claude_msg
|
info["claude_cli_message"] = claude_msg
|
||||||
|
|
||||||
# Add disk space info
|
# Add disk space info
|
||||||
try:
|
try:
|
||||||
home_path = get_home_directory()
|
home_path = get_home_directory()
|
||||||
@ -510,76 +543,78 @@ class Validator:
|
|||||||
info["disk_space"] = {
|
info["disk_space"] = {
|
||||||
"total_gb": stat_result.total / (1024**3),
|
"total_gb": stat_result.total / (1024**3),
|
||||||
"free_gb": stat_result.free / (1024**3),
|
"free_gb": stat_result.free / (1024**3),
|
||||||
"used_gb": (stat_result.total - stat_result.free) / (1024**3)
|
"used_gb": (stat_result.total - stat_result.free) / (1024**3),
|
||||||
}
|
}
|
||||||
except Exception:
|
except Exception:
|
||||||
info["disk_space"] = {"error": "Could not determine disk space"}
|
info["disk_space"] = {"error": "Could not determine disk space"}
|
||||||
|
|
||||||
return info
|
return info
|
||||||
|
|
||||||
def get_platform(self) -> str:
|
def get_platform(self) -> str:
|
||||||
"""
|
"""
|
||||||
Get current platform for installation commands
|
Get current platform for installation commands
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Platform string (linux, darwin, win32)
|
Platform string (linux, darwin, win32)
|
||||||
"""
|
"""
|
||||||
return sys.platform
|
return sys.platform
|
||||||
|
|
||||||
def load_installation_commands(self) -> Dict[str, Any]:
|
def load_installation_commands(self) -> Dict[str, Any]:
|
||||||
"""
|
"""
|
||||||
Load installation commands from requirements configuration
|
Load installation commands from requirements configuration
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Installation commands dict
|
Installation commands dict
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
from ..services.config import ConfigService
|
from ..services.config import ConfigService
|
||||||
from .. import DATA_DIR
|
from .. import DATA_DIR
|
||||||
|
|
||||||
config_manager = ConfigService(DATA_DIR)
|
config_manager = ConfigService(DATA_DIR)
|
||||||
requirements = config_manager.load_requirements()
|
requirements = config_manager.load_requirements()
|
||||||
return requirements.get("installation_commands", {})
|
return requirements.get("installation_commands", {})
|
||||||
except Exception:
|
except Exception:
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
def get_installation_help(self, tool_name: str, platform: Optional[str] = None) -> str:
|
def get_installation_help(
|
||||||
|
self, tool_name: str, platform: Optional[str] = None
|
||||||
|
) -> str:
|
||||||
"""
|
"""
|
||||||
Get installation help for a specific tool
|
Get installation help for a specific tool
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
tool_name: Name of tool to get help for
|
tool_name: Name of tool to get help for
|
||||||
platform: Target platform (auto-detected if None)
|
platform: Target platform (auto-detected if None)
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Installation help string
|
Installation help string
|
||||||
"""
|
"""
|
||||||
if platform is None:
|
if platform is None:
|
||||||
platform = self.get_platform()
|
platform = self.get_platform()
|
||||||
|
|
||||||
commands = self.load_installation_commands()
|
commands = self.load_installation_commands()
|
||||||
tool_commands = commands.get(tool_name, {})
|
tool_commands = commands.get(tool_name, {})
|
||||||
|
|
||||||
if not tool_commands:
|
if not tool_commands:
|
||||||
return f"No installation instructions available for {tool_name}"
|
return f"No installation instructions available for {tool_name}"
|
||||||
|
|
||||||
# Get platform-specific command or fallback to 'all'
|
# Get platform-specific command or fallback to 'all'
|
||||||
install_cmd = tool_commands.get(platform, tool_commands.get("all", ""))
|
install_cmd = tool_commands.get(platform, tool_commands.get("all", ""))
|
||||||
description = tool_commands.get("description", "")
|
description = tool_commands.get("description", "")
|
||||||
|
|
||||||
if install_cmd:
|
if install_cmd:
|
||||||
help_text = f"\n💡 Installation Help for {tool_name}:\n"
|
help_text = f"\n💡 Installation Help for {tool_name}:\n"
|
||||||
if description:
|
if description:
|
||||||
help_text += f" {description}\n"
|
help_text += f" {description}\n"
|
||||||
help_text += f" Command: {install_cmd}\n"
|
help_text += f" Command: {install_cmd}\n"
|
||||||
return help_text
|
return help_text
|
||||||
|
|
||||||
return f"No installation instructions available for {tool_name} on {platform}"
|
return f"No installation instructions available for {tool_name} on {platform}"
|
||||||
|
|
||||||
def diagnose_system(self) -> Dict[str, Any]:
|
def diagnose_system(self) -> Dict[str, Any]:
|
||||||
"""
|
"""
|
||||||
Perform comprehensive system diagnostics
|
Perform comprehensive system diagnostics
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Diagnostic information dict
|
Diagnostic information dict
|
||||||
"""
|
"""
|
||||||
@ -587,66 +622,68 @@ class Validator:
|
|||||||
"platform": self.get_platform(),
|
"platform": self.get_platform(),
|
||||||
"checks": {},
|
"checks": {},
|
||||||
"issues": [],
|
"issues": [],
|
||||||
"recommendations": []
|
"recommendations": [],
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check Python
|
# Check Python
|
||||||
python_success, python_msg = self.check_python()
|
python_success, python_msg = self.check_python()
|
||||||
diagnostics["checks"]["python"] = {
|
diagnostics["checks"]["python"] = {
|
||||||
"status": "pass" if python_success else "fail",
|
"status": "pass" if python_success else "fail",
|
||||||
"message": python_msg
|
"message": python_msg,
|
||||||
}
|
}
|
||||||
if not python_success:
|
if not python_success:
|
||||||
diagnostics["issues"].append("Python version issue")
|
diagnostics["issues"].append("Python version issue")
|
||||||
diagnostics["recommendations"].append(self.get_installation_help("python"))
|
diagnostics["recommendations"].append(self.get_installation_help("python"))
|
||||||
|
|
||||||
# Check Node.js
|
# Check Node.js
|
||||||
node_success, node_msg = self.check_node()
|
node_success, node_msg = self.check_node()
|
||||||
diagnostics["checks"]["node"] = {
|
diagnostics["checks"]["node"] = {
|
||||||
"status": "pass" if node_success else "fail",
|
"status": "pass" if node_success else "fail",
|
||||||
"message": node_msg
|
"message": node_msg,
|
||||||
}
|
}
|
||||||
if not node_success:
|
if not node_success:
|
||||||
diagnostics["issues"].append("Node.js not found or version issue")
|
diagnostics["issues"].append("Node.js not found or version issue")
|
||||||
diagnostics["recommendations"].append(self.get_installation_help("node"))
|
diagnostics["recommendations"].append(self.get_installation_help("node"))
|
||||||
|
|
||||||
# Check Claude CLI
|
# Check Claude CLI
|
||||||
claude_success, claude_msg = self.check_claude_cli()
|
claude_success, claude_msg = self.check_claude_cli()
|
||||||
diagnostics["checks"]["claude_cli"] = {
|
diagnostics["checks"]["claude_cli"] = {
|
||||||
"status": "pass" if claude_success else "fail",
|
"status": "pass" if claude_success else "fail",
|
||||||
"message": claude_msg
|
"message": claude_msg,
|
||||||
}
|
}
|
||||||
if not claude_success:
|
if not claude_success:
|
||||||
diagnostics["issues"].append("Claude CLI not found")
|
diagnostics["issues"].append("Claude CLI not found")
|
||||||
diagnostics["recommendations"].append(self.get_installation_help("claude_cli"))
|
diagnostics["recommendations"].append(
|
||||||
|
self.get_installation_help("claude_cli")
|
||||||
|
)
|
||||||
|
|
||||||
# Check disk space
|
# Check disk space
|
||||||
disk_success, disk_msg = self.check_disk_space(get_home_directory())
|
disk_success, disk_msg = self.check_disk_space(get_home_directory())
|
||||||
diagnostics["checks"]["disk_space"] = {
|
diagnostics["checks"]["disk_space"] = {
|
||||||
"status": "pass" if disk_success else "fail",
|
"status": "pass" if disk_success else "fail",
|
||||||
"message": disk_msg
|
"message": disk_msg,
|
||||||
}
|
}
|
||||||
if not disk_success:
|
if not disk_success:
|
||||||
diagnostics["issues"].append("Insufficient disk space")
|
diagnostics["issues"].append("Insufficient disk space")
|
||||||
|
|
||||||
# Check common PATH issues
|
# Check common PATH issues
|
||||||
self._diagnose_path_issues(diagnostics)
|
self._diagnose_path_issues(diagnostics)
|
||||||
|
|
||||||
return diagnostics
|
return diagnostics
|
||||||
|
|
||||||
def _diagnose_path_issues(self, diagnostics: Dict[str, Any]) -> None:
|
def _diagnose_path_issues(self, diagnostics: Dict[str, Any]) -> None:
|
||||||
"""Add PATH-related diagnostics"""
|
"""Add PATH-related diagnostics"""
|
||||||
path_issues = []
|
path_issues = []
|
||||||
|
|
||||||
# Check if tools are in PATH, with alternatives for some tools
|
# Check if tools are in PATH, with alternatives for some tools
|
||||||
tool_checks = [
|
tool_checks = [
|
||||||
# For Python, check if either python3 OR python is available
|
# For Python, check if either python3 OR python is available
|
||||||
(["python3", "python"], "Python (python3 or python)"),
|
(["python3", "python"], "Python (python3 or python)"),
|
||||||
(["node"], "Node.js"),
|
(["node"], "Node.js"),
|
||||||
(["npm"], "npm"),
|
(["npm"], "npm"),
|
||||||
(["claude"], "Claude CLI")
|
(["claude"], "Claude CLI"),
|
||||||
]
|
]
|
||||||
|
|
||||||
for tool_alternatives, display_name in tool_checks:
|
for tool_alternatives, display_name in tool_checks:
|
||||||
tool_found = False
|
tool_found = False
|
||||||
for tool in tool_alternatives:
|
for tool in tool_alternatives:
|
||||||
@ -656,21 +693,21 @@ class Validator:
|
|||||||
capture_output=True,
|
capture_output=True,
|
||||||
text=True,
|
text=True,
|
||||||
timeout=5,
|
timeout=5,
|
||||||
shell=(sys.platform == "win32")
|
shell=(sys.platform == "win32"),
|
||||||
)
|
)
|
||||||
if result.returncode == 0:
|
if result.returncode == 0:
|
||||||
tool_found = True
|
tool_found = True
|
||||||
break
|
break
|
||||||
except Exception:
|
except Exception:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if not tool_found:
|
if not tool_found:
|
||||||
# Only report as missing if none of the alternatives were found
|
# Only report as missing if none of the alternatives were found
|
||||||
if len(tool_alternatives) > 1:
|
if len(tool_alternatives) > 1:
|
||||||
path_issues.append(f"{display_name} not found in PATH")
|
path_issues.append(f"{display_name} not found in PATH")
|
||||||
else:
|
else:
|
||||||
path_issues.append(f"{tool_alternatives[0]} not found in PATH")
|
path_issues.append(f"{tool_alternatives[0]} not found in PATH")
|
||||||
|
|
||||||
if path_issues:
|
if path_issues:
|
||||||
diagnostics["issues"].extend(path_issues)
|
diagnostics["issues"].extend(path_issues)
|
||||||
diagnostics["recommendations"].append(
|
diagnostics["recommendations"].append(
|
||||||
@ -680,7 +717,7 @@ class Validator:
|
|||||||
" - Check your shell configuration (.bashrc, .zshrc)\n"
|
" - Check your shell configuration (.bashrc, .zshrc)\n"
|
||||||
" - Use full paths to tools if needed\n"
|
" - Use full paths to tools if needed\n"
|
||||||
)
|
)
|
||||||
|
|
||||||
def clear_cache(self) -> None:
|
def clear_cache(self) -> None:
|
||||||
"""Clear validation cache"""
|
"""Clear validation cache"""
|
||||||
self.validation_cache.clear()
|
self.validation_cache.clear()
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
"""
|
"""
|
||||||
SuperClaude Data Module
|
SuperClaude Data Module
|
||||||
Static configuration and data files
|
Static configuration and data files
|
||||||
"""
|
"""
|
||||||
|
|||||||
@ -8,9 +8,4 @@ from .config import ConfigService
|
|||||||
from .files import FileService
|
from .files import FileService
|
||||||
from .settings import SettingsService
|
from .settings import SettingsService
|
||||||
|
|
||||||
__all__ = [
|
__all__ = ["CLAUDEMdService", "ConfigService", "FileService", "SettingsService"]
|
||||||
'CLAUDEMdService',
|
|
||||||
'ConfigService',
|
|
||||||
'FileService',
|
|
||||||
'SettingsService'
|
|
||||||
]
|
|
||||||
|
|||||||
@ -10,105 +10,107 @@ from ..utils.logger import get_logger
|
|||||||
|
|
||||||
class CLAUDEMdService:
|
class CLAUDEMdService:
|
||||||
"""Manages CLAUDE.md file updates while preserving user customizations"""
|
"""Manages CLAUDE.md file updates while preserving user customizations"""
|
||||||
|
|
||||||
def __init__(self, install_dir: Path):
|
def __init__(self, install_dir: Path):
|
||||||
"""
|
"""
|
||||||
Initialize CLAUDEMdService
|
Initialize CLAUDEMdService
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
install_dir: Installation directory (typically ~/.claude)
|
install_dir: Installation directory (typically ~/.claude)
|
||||||
"""
|
"""
|
||||||
self.install_dir = install_dir
|
self.install_dir = install_dir
|
||||||
self.claude_md_path = install_dir / "CLAUDE.md"
|
self.claude_md_path = install_dir / "CLAUDE.md"
|
||||||
self.logger = get_logger()
|
self.logger = get_logger()
|
||||||
|
|
||||||
def read_existing_imports(self) -> Set[str]:
|
def read_existing_imports(self) -> Set[str]:
|
||||||
"""
|
"""
|
||||||
Parse CLAUDE.md for existing @import statements
|
Parse CLAUDE.md for existing @import statements
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Set of already imported filenames (without @)
|
Set of already imported filenames (without @)
|
||||||
"""
|
"""
|
||||||
existing_imports = set()
|
existing_imports = set()
|
||||||
|
|
||||||
if not self.claude_md_path.exists():
|
if not self.claude_md_path.exists():
|
||||||
return existing_imports
|
return existing_imports
|
||||||
|
|
||||||
try:
|
try:
|
||||||
with open(self.claude_md_path, 'r', encoding='utf-8') as f:
|
with open(self.claude_md_path, "r", encoding="utf-8") as f:
|
||||||
content = f.read()
|
content = f.read()
|
||||||
|
|
||||||
# Find all @import statements using regex
|
# Find all @import statements using regex
|
||||||
import_pattern = r'^@([^\s\n]+\.md)\s*$'
|
import_pattern = r"^@([^\s\n]+\.md)\s*$"
|
||||||
matches = re.findall(import_pattern, content, re.MULTILINE)
|
matches = re.findall(import_pattern, content, re.MULTILINE)
|
||||||
existing_imports.update(matches)
|
existing_imports.update(matches)
|
||||||
|
|
||||||
self.logger.debug(f"Found existing imports: {existing_imports}")
|
self.logger.debug(f"Found existing imports: {existing_imports}")
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.warning(f"Could not read existing CLAUDE.md imports: {e}")
|
self.logger.warning(f"Could not read existing CLAUDE.md imports: {e}")
|
||||||
|
|
||||||
return existing_imports
|
return existing_imports
|
||||||
|
|
||||||
def read_existing_content(self) -> str:
|
def read_existing_content(self) -> str:
|
||||||
"""
|
"""
|
||||||
Read existing CLAUDE.md content
|
Read existing CLAUDE.md content
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Existing content or empty string if file doesn't exist
|
Existing content or empty string if file doesn't exist
|
||||||
"""
|
"""
|
||||||
if not self.claude_md_path.exists():
|
if not self.claude_md_path.exists():
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
with open(self.claude_md_path, 'r', encoding='utf-8') as f:
|
with open(self.claude_md_path, "r", encoding="utf-8") as f:
|
||||||
return f.read()
|
return f.read()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.warning(f"Could not read existing CLAUDE.md: {e}")
|
self.logger.warning(f"Could not read existing CLAUDE.md: {e}")
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
def extract_user_content(self, content: str) -> str:
|
def extract_user_content(self, content: str) -> str:
|
||||||
"""
|
"""
|
||||||
Extract user content (everything before framework imports section)
|
Extract user content (everything before framework imports section)
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
content: Full CLAUDE.md content
|
content: Full CLAUDE.md content
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
User content without framework imports
|
User content without framework imports
|
||||||
"""
|
"""
|
||||||
# Look for framework imports section marker
|
# Look for framework imports section marker
|
||||||
framework_marker = "# ===================================================\n# SuperClaude Framework Components"
|
framework_marker = "# ===================================================\n# SuperClaude Framework Components"
|
||||||
|
|
||||||
if framework_marker in content:
|
if framework_marker in content:
|
||||||
user_content = content.split(framework_marker)[0].rstrip()
|
user_content = content.split(framework_marker)[0].rstrip()
|
||||||
else:
|
else:
|
||||||
# If no framework section exists, preserve all content
|
# If no framework section exists, preserve all content
|
||||||
user_content = content.rstrip()
|
user_content = content.rstrip()
|
||||||
|
|
||||||
return user_content
|
return user_content
|
||||||
|
|
||||||
def organize_imports_by_category(self, files_by_category: Dict[str, List[str]]) -> str:
|
def organize_imports_by_category(
|
||||||
|
self, files_by_category: Dict[str, List[str]]
|
||||||
|
) -> str:
|
||||||
"""
|
"""
|
||||||
Organize imports into categorized sections
|
Organize imports into categorized sections
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
files_by_category: Dict mapping category names to lists of files
|
files_by_category: Dict mapping category names to lists of files
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Formatted import sections
|
Formatted import sections
|
||||||
"""
|
"""
|
||||||
if not files_by_category:
|
if not files_by_category:
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
sections = []
|
sections = []
|
||||||
|
|
||||||
# Framework imports section header
|
# Framework imports section header
|
||||||
sections.append("# ===================================================")
|
sections.append("# ===================================================")
|
||||||
sections.append("# SuperClaude Framework Components")
|
sections.append("# SuperClaude Framework Components")
|
||||||
sections.append("# ===================================================")
|
sections.append("# ===================================================")
|
||||||
sections.append("")
|
sections.append("")
|
||||||
|
|
||||||
# Add each category
|
# Add each category
|
||||||
for category, files in files_by_category.items():
|
for category, files in files_by_category.items():
|
||||||
if files:
|
if files:
|
||||||
@ -116,131 +118,139 @@ class CLAUDEMdService:
|
|||||||
for file in sorted(files):
|
for file in sorted(files):
|
||||||
sections.append(f"@{file}")
|
sections.append(f"@{file}")
|
||||||
sections.append("")
|
sections.append("")
|
||||||
|
|
||||||
return "\n".join(sections)
|
return "\n".join(sections)
|
||||||
|
|
||||||
def add_imports(self, files: List[str], category: str = "Framework") -> bool:
|
def add_imports(self, files: List[str], category: str = "Framework") -> bool:
|
||||||
"""
|
"""
|
||||||
Add new imports with duplicate checking and user content preservation
|
Add new imports with duplicate checking and user content preservation
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
files: List of filenames to import
|
files: List of filenames to import
|
||||||
category: Category name for organizing imports
|
category: Category name for organizing imports
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
True if successful, False otherwise
|
True if successful, False otherwise
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
# Ensure CLAUDE.md exists
|
# Ensure CLAUDE.md exists
|
||||||
self.ensure_claude_md_exists()
|
self.ensure_claude_md_exists()
|
||||||
|
|
||||||
# Read existing content and imports
|
# Read existing content and imports
|
||||||
existing_content = self.read_existing_content()
|
existing_content = self.read_existing_content()
|
||||||
existing_imports = self.read_existing_imports()
|
existing_imports = self.read_existing_imports()
|
||||||
|
|
||||||
# Filter out files already imported
|
# Filter out files already imported
|
||||||
new_files = [f for f in files if f not in existing_imports]
|
new_files = [f for f in files if f not in existing_imports]
|
||||||
|
|
||||||
if not new_files:
|
if not new_files:
|
||||||
self.logger.info("All files already imported, no changes needed")
|
self.logger.info("All files already imported, no changes needed")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
self.logger.info(f"Adding {len(new_files)} new imports to category '{category}': {new_files}")
|
self.logger.info(
|
||||||
|
f"Adding {len(new_files)} new imports to category '{category}': {new_files}"
|
||||||
|
)
|
||||||
|
|
||||||
# Extract user content (preserve everything before framework section)
|
# Extract user content (preserve everything before framework section)
|
||||||
user_content = self.extract_user_content(existing_content)
|
user_content = self.extract_user_content(existing_content)
|
||||||
|
|
||||||
# Parse existing framework imports by category
|
# Parse existing framework imports by category
|
||||||
existing_framework_imports = self._parse_existing_framework_imports(existing_content)
|
existing_framework_imports = self._parse_existing_framework_imports(
|
||||||
|
existing_content
|
||||||
|
)
|
||||||
|
|
||||||
# Add new files to the specified category
|
# Add new files to the specified category
|
||||||
if category not in existing_framework_imports:
|
if category not in existing_framework_imports:
|
||||||
existing_framework_imports[category] = []
|
existing_framework_imports[category] = []
|
||||||
existing_framework_imports[category].extend(new_files)
|
existing_framework_imports[category].extend(new_files)
|
||||||
|
|
||||||
# Build new content
|
# Build new content
|
||||||
new_content_parts = []
|
new_content_parts = []
|
||||||
|
|
||||||
# Add user content
|
# Add user content
|
||||||
if user_content.strip():
|
if user_content.strip():
|
||||||
new_content_parts.append(user_content)
|
new_content_parts.append(user_content)
|
||||||
new_content_parts.append("") # Add blank line before framework section
|
new_content_parts.append("") # Add blank line before framework section
|
||||||
|
|
||||||
# Add organized framework imports
|
# Add organized framework imports
|
||||||
framework_section = self.organize_imports_by_category(existing_framework_imports)
|
framework_section = self.organize_imports_by_category(
|
||||||
|
existing_framework_imports
|
||||||
|
)
|
||||||
if framework_section:
|
if framework_section:
|
||||||
new_content_parts.append(framework_section)
|
new_content_parts.append(framework_section)
|
||||||
|
|
||||||
# Write updated content
|
# Write updated content
|
||||||
new_content = "\n".join(new_content_parts)
|
new_content = "\n".join(new_content_parts)
|
||||||
|
|
||||||
with open(self.claude_md_path, 'w', encoding='utf-8') as f:
|
with open(self.claude_md_path, "w", encoding="utf-8") as f:
|
||||||
f.write(new_content)
|
f.write(new_content)
|
||||||
|
|
||||||
self.logger.success(f"Updated CLAUDE.md with {len(new_files)} new imports")
|
self.logger.success(f"Updated CLAUDE.md with {len(new_files)} new imports")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.error(f"Failed to update CLAUDE.md: {e}")
|
self.logger.error(f"Failed to update CLAUDE.md: {e}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def _parse_existing_framework_imports(self, content: str) -> Dict[str, List[str]]:
|
def _parse_existing_framework_imports(self, content: str) -> Dict[str, List[str]]:
|
||||||
"""
|
"""
|
||||||
Parse existing framework imports organized by category
|
Parse existing framework imports organized by category
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
content: Full CLAUDE.md content
|
content: Full CLAUDE.md content
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Dict mapping category names to lists of imported files
|
Dict mapping category names to lists of imported files
|
||||||
"""
|
"""
|
||||||
imports_by_category = {}
|
imports_by_category = {}
|
||||||
|
|
||||||
# Look for framework imports section
|
# Look for framework imports section
|
||||||
framework_marker = "# ===================================================\n# SuperClaude Framework Components"
|
framework_marker = "# ===================================================\n# SuperClaude Framework Components"
|
||||||
|
|
||||||
if framework_marker not in content:
|
if framework_marker not in content:
|
||||||
return imports_by_category
|
return imports_by_category
|
||||||
|
|
||||||
# Extract framework section
|
# Extract framework section
|
||||||
framework_section = content.split(framework_marker)[1] if framework_marker in content else ""
|
framework_section = (
|
||||||
|
content.split(framework_marker)[1] if framework_marker in content else ""
|
||||||
|
)
|
||||||
|
|
||||||
# Parse categories and imports
|
# Parse categories and imports
|
||||||
lines = framework_section.split('\n')
|
lines = framework_section.split("\n")
|
||||||
current_category = None
|
current_category = None
|
||||||
|
|
||||||
for line in lines:
|
for line in lines:
|
||||||
line = line.strip()
|
line = line.strip()
|
||||||
|
|
||||||
# Skip section header lines and empty lines
|
# Skip section header lines and empty lines
|
||||||
if line.startswith('# ===') or not line:
|
if line.startswith("# ===") or not line:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Category header (starts with # but not the section divider)
|
# Category header (starts with # but not the section divider)
|
||||||
if line.startswith('# ') and not line.startswith('# ==='):
|
if line.startswith("# ") and not line.startswith("# ==="):
|
||||||
current_category = line[2:].strip() # Remove "# "
|
current_category = line[2:].strip() # Remove "# "
|
||||||
if current_category not in imports_by_category:
|
if current_category not in imports_by_category:
|
||||||
imports_by_category[current_category] = []
|
imports_by_category[current_category] = []
|
||||||
|
|
||||||
# Import line (starts with @)
|
# Import line (starts with @)
|
||||||
elif line.startswith('@') and current_category:
|
elif line.startswith("@") and current_category:
|
||||||
import_file = line[1:].strip() # Remove "@"
|
import_file = line[1:].strip() # Remove "@"
|
||||||
if import_file not in imports_by_category[current_category]:
|
if import_file not in imports_by_category[current_category]:
|
||||||
imports_by_category[current_category].append(import_file)
|
imports_by_category[current_category].append(import_file)
|
||||||
|
|
||||||
return imports_by_category
|
return imports_by_category
|
||||||
|
|
||||||
def ensure_claude_md_exists(self) -> None:
|
def ensure_claude_md_exists(self) -> None:
|
||||||
"""
|
"""
|
||||||
Create CLAUDE.md with default content if it doesn't exist
|
Create CLAUDE.md with default content if it doesn't exist
|
||||||
"""
|
"""
|
||||||
if self.claude_md_path.exists():
|
if self.claude_md_path.exists():
|
||||||
return
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Create directory if it doesn't exist
|
# Create directory if it doesn't exist
|
||||||
self.claude_md_path.parent.mkdir(parents=True, exist_ok=True)
|
self.claude_md_path.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
# Default CLAUDE.md content
|
# Default CLAUDE.md content
|
||||||
default_content = """# SuperClaude Entry Point
|
default_content = """# SuperClaude Entry Point
|
||||||
|
|
||||||
@ -249,34 +259,36 @@ You can add your own custom instructions and configurations here.
|
|||||||
|
|
||||||
The SuperClaude framework components will be automatically imported below.
|
The SuperClaude framework components will be automatically imported below.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
with open(self.claude_md_path, 'w', encoding='utf-8') as f:
|
with open(self.claude_md_path, "w", encoding="utf-8") as f:
|
||||||
f.write(default_content)
|
f.write(default_content)
|
||||||
|
|
||||||
self.logger.info("Created CLAUDE.md with default content")
|
self.logger.info("Created CLAUDE.md with default content")
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.error(f"Failed to create CLAUDE.md: {e}")
|
self.logger.error(f"Failed to create CLAUDE.md: {e}")
|
||||||
raise
|
raise
|
||||||
|
|
||||||
def remove_imports(self, files: List[str]) -> bool:
|
def remove_imports(self, files: List[str]) -> bool:
|
||||||
"""
|
"""
|
||||||
Remove specific imports from CLAUDE.md
|
Remove specific imports from CLAUDE.md
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
files: List of filenames to remove from imports
|
files: List of filenames to remove from imports
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
True if successful, False otherwise
|
True if successful, False otherwise
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
if not self.claude_md_path.exists():
|
if not self.claude_md_path.exists():
|
||||||
return True # Nothing to remove
|
return True # Nothing to remove
|
||||||
|
|
||||||
existing_content = self.read_existing_content()
|
existing_content = self.read_existing_content()
|
||||||
user_content = self.extract_user_content(existing_content)
|
user_content = self.extract_user_content(existing_content)
|
||||||
existing_framework_imports = self._parse_existing_framework_imports(existing_content)
|
existing_framework_imports = self._parse_existing_framework_imports(
|
||||||
|
existing_content
|
||||||
|
)
|
||||||
|
|
||||||
# Remove files from all categories
|
# Remove files from all categories
|
||||||
removed_any = False
|
removed_any = False
|
||||||
for category, category_files in existing_framework_imports.items():
|
for category, category_files in existing_framework_imports.items():
|
||||||
@ -284,33 +296,37 @@ The SuperClaude framework components will be automatically imported below.
|
|||||||
if file in category_files:
|
if file in category_files:
|
||||||
category_files.remove(file)
|
category_files.remove(file)
|
||||||
removed_any = True
|
removed_any = True
|
||||||
|
|
||||||
# Remove empty categories
|
# Remove empty categories
|
||||||
existing_framework_imports = {k: v for k, v in existing_framework_imports.items() if v}
|
existing_framework_imports = {
|
||||||
|
k: v for k, v in existing_framework_imports.items() if v
|
||||||
|
}
|
||||||
|
|
||||||
if not removed_any:
|
if not removed_any:
|
||||||
return True # Nothing was removed
|
return True # Nothing was removed
|
||||||
|
|
||||||
# Rebuild content
|
# Rebuild content
|
||||||
new_content_parts = []
|
new_content_parts = []
|
||||||
|
|
||||||
if user_content.strip():
|
if user_content.strip():
|
||||||
new_content_parts.append(user_content)
|
new_content_parts.append(user_content)
|
||||||
new_content_parts.append("")
|
new_content_parts.append("")
|
||||||
|
|
||||||
framework_section = self.organize_imports_by_category(existing_framework_imports)
|
framework_section = self.organize_imports_by_category(
|
||||||
|
existing_framework_imports
|
||||||
|
)
|
||||||
if framework_section:
|
if framework_section:
|
||||||
new_content_parts.append(framework_section)
|
new_content_parts.append(framework_section)
|
||||||
|
|
||||||
# Write updated content
|
# Write updated content
|
||||||
new_content = "\n".join(new_content_parts)
|
new_content = "\n".join(new_content_parts)
|
||||||
|
|
||||||
with open(self.claude_md_path, 'w', encoding='utf-8') as f:
|
with open(self.claude_md_path, "w", encoding="utf-8") as f:
|
||||||
f.write(new_content)
|
f.write(new_content)
|
||||||
|
|
||||||
self.logger.info(f"Removed {len(files)} imports from CLAUDE.md")
|
self.logger.info(f"Removed {len(files)} imports from CLAUDE.md")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.error(f"Failed to remove imports from CLAUDE.md: {e}")
|
self.logger.error(f"Failed to remove imports from CLAUDE.md: {e}")
|
||||||
return False
|
return False
|
||||||
|
|||||||
@ -10,16 +10,18 @@ from pathlib import Path
|
|||||||
try:
|
try:
|
||||||
import jsonschema
|
import jsonschema
|
||||||
from jsonschema import validate, ValidationError
|
from jsonschema import validate, ValidationError
|
||||||
|
|
||||||
JSONSCHEMA_AVAILABLE = True
|
JSONSCHEMA_AVAILABLE = True
|
||||||
except ImportError:
|
except ImportError:
|
||||||
JSONSCHEMA_AVAILABLE = False
|
JSONSCHEMA_AVAILABLE = False
|
||||||
|
|
||||||
class ValidationError(Exception):
|
class ValidationError(Exception):
|
||||||
"""Simple validation error for when jsonschema is not available"""
|
"""Simple validation error for when jsonschema is not available"""
|
||||||
|
|
||||||
def __init__(self, message):
|
def __init__(self, message):
|
||||||
self.message = message
|
self.message = message
|
||||||
super().__init__(message)
|
super().__init__(message)
|
||||||
|
|
||||||
def validate(instance, schema):
|
def validate(instance, schema):
|
||||||
"""Dummy validation function"""
|
"""Dummy validation function"""
|
||||||
# Basic type checking only
|
# Basic type checking only
|
||||||
@ -32,17 +34,19 @@ except ImportError:
|
|||||||
elif expected_type == "string" and not isinstance(instance, str):
|
elif expected_type == "string" and not isinstance(instance, str):
|
||||||
raise ValidationError(f"Expected string, got {type(instance).__name__}")
|
raise ValidationError(f"Expected string, got {type(instance).__name__}")
|
||||||
elif expected_type == "integer" and not isinstance(instance, int):
|
elif expected_type == "integer" and not isinstance(instance, int):
|
||||||
raise ValidationError(f"Expected integer, got {type(instance).__name__}")
|
raise ValidationError(
|
||||||
|
f"Expected integer, got {type(instance).__name__}"
|
||||||
|
)
|
||||||
# Skip detailed validation if jsonschema not available
|
# Skip detailed validation if jsonschema not available
|
||||||
|
|
||||||
|
|
||||||
class ConfigService:
|
class ConfigService:
|
||||||
"""Manages configuration files and validation"""
|
"""Manages configuration files and validation"""
|
||||||
|
|
||||||
def __init__(self, config_dir: Path):
|
def __init__(self, config_dir: Path):
|
||||||
"""
|
"""
|
||||||
Initialize config manager
|
Initialize config manager
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
config_dir: Directory containing configuration files
|
config_dir: Directory containing configuration files
|
||||||
"""
|
"""
|
||||||
@ -51,7 +55,7 @@ class ConfigService:
|
|||||||
self.requirements_file = config_dir / "requirements.json"
|
self.requirements_file = config_dir / "requirements.json"
|
||||||
self._features_cache = None
|
self._features_cache = None
|
||||||
self._requirements_cache = None
|
self._requirements_cache = None
|
||||||
|
|
||||||
# Schema for features.json
|
# Schema for features.json
|
||||||
self.features_schema = {
|
self.features_schema = {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@ -68,24 +72,24 @@ class ConfigService:
|
|||||||
"category": {"type": "string"},
|
"category": {"type": "string"},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": {"type": "string"}
|
"items": {"type": "string"},
|
||||||
},
|
},
|
||||||
"enabled": {"type": "boolean"},
|
"enabled": {"type": "boolean"},
|
||||||
"required_tools": {
|
"required_tools": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": {"type": "string"}
|
"items": {"type": "string"},
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
"required": ["name", "version", "description", "category"],
|
"required": ["name", "version", "description", "category"],
|
||||||
"additionalProperties": False
|
"additionalProperties": False,
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["components"],
|
"required": ["components"],
|
||||||
"additionalProperties": False
|
"additionalProperties": False,
|
||||||
}
|
}
|
||||||
|
|
||||||
# Schema for requirements.json
|
# Schema for requirements.json
|
||||||
self.requirements_schema = {
|
self.requirements_schema = {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@ -94,21 +98,18 @@ class ConfigService:
|
|||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"min_version": {"type": "string"},
|
"min_version": {"type": "string"},
|
||||||
"max_version": {"type": "string"}
|
"max_version": {"type": "string"},
|
||||||
},
|
},
|
||||||
"required": ["min_version"]
|
"required": ["min_version"],
|
||||||
},
|
},
|
||||||
"node": {
|
"node": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"min_version": {"type": "string"},
|
"min_version": {"type": "string"},
|
||||||
"max_version": {"type": "string"},
|
"max_version": {"type": "string"},
|
||||||
"required_for": {
|
"required_for": {"type": "array", "items": {"type": "string"}},
|
||||||
"type": "array",
|
|
||||||
"items": {"type": "string"}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"required": ["min_version"]
|
"required": ["min_version"],
|
||||||
},
|
},
|
||||||
"disk_space_mb": {"type": "integer"},
|
"disk_space_mb": {"type": "integer"},
|
||||||
"external_tools": {
|
"external_tools": {
|
||||||
@ -121,14 +122,14 @@ class ConfigService:
|
|||||||
"min_version": {"type": "string"},
|
"min_version": {"type": "string"},
|
||||||
"required_for": {
|
"required_for": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": {"type": "string"}
|
"items": {"type": "string"},
|
||||||
},
|
},
|
||||||
"optional": {"type": "boolean"}
|
"optional": {"type": "boolean"},
|
||||||
},
|
},
|
||||||
"required": ["command"],
|
"required": ["command"],
|
||||||
"additionalProperties": False
|
"additionalProperties": False,
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
"installation_commands": {
|
"installation_commands": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@ -140,136 +141,138 @@ class ConfigService:
|
|||||||
"darwin": {"type": "string"},
|
"darwin": {"type": "string"},
|
||||||
"win32": {"type": "string"},
|
"win32": {"type": "string"},
|
||||||
"all": {"type": "string"},
|
"all": {"type": "string"},
|
||||||
"description": {"type": "string"}
|
"description": {"type": "string"},
|
||||||
},
|
},
|
||||||
"additionalProperties": False
|
"additionalProperties": False,
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
"required": ["python", "disk_space_mb"],
|
"required": ["python", "disk_space_mb"],
|
||||||
"additionalProperties": False
|
"additionalProperties": False,
|
||||||
}
|
}
|
||||||
|
|
||||||
def load_features(self) -> Dict[str, Any]:
|
def load_features(self) -> Dict[str, Any]:
|
||||||
"""
|
"""
|
||||||
Load and validate features configuration
|
Load and validate features configuration
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Features configuration dict
|
Features configuration dict
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
FileNotFoundError: If features.json not found
|
FileNotFoundError: If features.json not found
|
||||||
ValidationError: If features.json is invalid
|
ValidationError: If features.json is invalid
|
||||||
"""
|
"""
|
||||||
if self._features_cache is not None:
|
if self._features_cache is not None:
|
||||||
return self._features_cache
|
return self._features_cache
|
||||||
|
|
||||||
if not self.features_file.exists():
|
if not self.features_file.exists():
|
||||||
raise FileNotFoundError(f"Features config not found: {self.features_file}")
|
raise FileNotFoundError(f"Features config not found: {self.features_file}")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
with open(self.features_file, 'r') as f:
|
with open(self.features_file, "r") as f:
|
||||||
features = json.load(f)
|
features = json.load(f)
|
||||||
|
|
||||||
# Validate schema
|
# Validate schema
|
||||||
validate(instance=features, schema=self.features_schema)
|
validate(instance=features, schema=self.features_schema)
|
||||||
|
|
||||||
self._features_cache = features
|
self._features_cache = features
|
||||||
return features
|
return features
|
||||||
|
|
||||||
except json.JSONDecodeError as e:
|
except json.JSONDecodeError as e:
|
||||||
raise ValidationError(f"Invalid JSON in {self.features_file}: {e}")
|
raise ValidationError(f"Invalid JSON in {self.features_file}: {e}")
|
||||||
except ValidationError as e:
|
except ValidationError as e:
|
||||||
raise ValidationError(f"Invalid features schema: {str(e)}")
|
raise ValidationError(f"Invalid features schema: {str(e)}")
|
||||||
|
|
||||||
def load_requirements(self) -> Dict[str, Any]:
|
def load_requirements(self) -> Dict[str, Any]:
|
||||||
"""
|
"""
|
||||||
Load and validate requirements configuration
|
Load and validate requirements configuration
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Requirements configuration dict
|
Requirements configuration dict
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
FileNotFoundError: If requirements.json not found
|
FileNotFoundError: If requirements.json not found
|
||||||
ValidationError: If requirements.json is invalid
|
ValidationError: If requirements.json is invalid
|
||||||
"""
|
"""
|
||||||
if self._requirements_cache is not None:
|
if self._requirements_cache is not None:
|
||||||
return self._requirements_cache
|
return self._requirements_cache
|
||||||
|
|
||||||
if not self.requirements_file.exists():
|
if not self.requirements_file.exists():
|
||||||
raise FileNotFoundError(f"Requirements config not found: {self.requirements_file}")
|
raise FileNotFoundError(
|
||||||
|
f"Requirements config not found: {self.requirements_file}"
|
||||||
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
with open(self.requirements_file, 'r') as f:
|
with open(self.requirements_file, "r") as f:
|
||||||
requirements = json.load(f)
|
requirements = json.load(f)
|
||||||
|
|
||||||
# Validate schema
|
# Validate schema
|
||||||
validate(instance=requirements, schema=self.requirements_schema)
|
validate(instance=requirements, schema=self.requirements_schema)
|
||||||
|
|
||||||
self._requirements_cache = requirements
|
self._requirements_cache = requirements
|
||||||
return requirements
|
return requirements
|
||||||
|
|
||||||
except json.JSONDecodeError as e:
|
except json.JSONDecodeError as e:
|
||||||
raise ValidationError(f"Invalid JSON in {self.requirements_file}: {e}")
|
raise ValidationError(f"Invalid JSON in {self.requirements_file}: {e}")
|
||||||
except ValidationError as e:
|
except ValidationError as e:
|
||||||
raise ValidationError(f"Invalid requirements schema: {str(e)}")
|
raise ValidationError(f"Invalid requirements schema: {str(e)}")
|
||||||
|
|
||||||
def get_component_info(self, component_name: str) -> Optional[Dict[str, Any]]:
|
def get_component_info(self, component_name: str) -> Optional[Dict[str, Any]]:
|
||||||
"""
|
"""
|
||||||
Get information about a specific component
|
Get information about a specific component
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
component_name: Name of component
|
component_name: Name of component
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Component info dict or None if not found
|
Component info dict or None if not found
|
||||||
"""
|
"""
|
||||||
features = self.load_features()
|
features = self.load_features()
|
||||||
return features.get("components", {}).get(component_name)
|
return features.get("components", {}).get(component_name)
|
||||||
|
|
||||||
def get_enabled_components(self) -> List[str]:
|
def get_enabled_components(self) -> List[str]:
|
||||||
"""
|
"""
|
||||||
Get list of enabled component names
|
Get list of enabled component names
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
List of enabled component names
|
List of enabled component names
|
||||||
"""
|
"""
|
||||||
features = self.load_features()
|
features = self.load_features()
|
||||||
enabled = []
|
enabled = []
|
||||||
|
|
||||||
for name, info in features.get("components", {}).items():
|
for name, info in features.get("components", {}).items():
|
||||||
if info.get("enabled", True): # Default to enabled
|
if info.get("enabled", True): # Default to enabled
|
||||||
enabled.append(name)
|
enabled.append(name)
|
||||||
|
|
||||||
return enabled
|
return enabled
|
||||||
|
|
||||||
def get_components_by_category(self, category: str) -> List[str]:
|
def get_components_by_category(self, category: str) -> List[str]:
|
||||||
"""
|
"""
|
||||||
Get component names by category
|
Get component names by category
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
category: Component category
|
category: Component category
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
List of component names in category
|
List of component names in category
|
||||||
"""
|
"""
|
||||||
features = self.load_features()
|
features = self.load_features()
|
||||||
components = []
|
components = []
|
||||||
|
|
||||||
for name, info in features.get("components", {}).items():
|
for name, info in features.get("components", {}).items():
|
||||||
if info.get("category") == category:
|
if info.get("category") == category:
|
||||||
components.append(name)
|
components.append(name)
|
||||||
|
|
||||||
return components
|
return components
|
||||||
|
|
||||||
def get_component_dependencies(self, component_name: str) -> List[str]:
|
def get_component_dependencies(self, component_name: str) -> List[str]:
|
||||||
"""
|
"""
|
||||||
Get dependencies for a component
|
Get dependencies for a component
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
component_name: Name of component
|
component_name: Name of component
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
List of dependency component names
|
List of dependency component names
|
||||||
"""
|
"""
|
||||||
@ -277,82 +280,86 @@ class ConfigService:
|
|||||||
if component_info:
|
if component_info:
|
||||||
return component_info.get("dependencies", [])
|
return component_info.get("dependencies", [])
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def get_system_requirements(self) -> Dict[str, Any]:
|
def get_system_requirements(self) -> Dict[str, Any]:
|
||||||
"""
|
"""
|
||||||
Get system requirements
|
Get system requirements
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
System requirements dict
|
System requirements dict
|
||||||
"""
|
"""
|
||||||
return self.load_requirements()
|
return self.load_requirements()
|
||||||
|
|
||||||
def get_requirements_for_components(self, component_names: List[str]) -> Dict[str, Any]:
|
def get_requirements_for_components(
|
||||||
|
self, component_names: List[str]
|
||||||
|
) -> Dict[str, Any]:
|
||||||
"""
|
"""
|
||||||
Get consolidated requirements for specific components
|
Get consolidated requirements for specific components
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
component_names: List of component names
|
component_names: List of component names
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Consolidated requirements dict
|
Consolidated requirements dict
|
||||||
"""
|
"""
|
||||||
requirements = self.load_requirements()
|
requirements = self.load_requirements()
|
||||||
features = self.load_features()
|
features = self.load_features()
|
||||||
|
|
||||||
# Start with base requirements
|
# Start with base requirements
|
||||||
result = {
|
result = {
|
||||||
"python": requirements["python"],
|
"python": requirements["python"],
|
||||||
"disk_space_mb": requirements["disk_space_mb"],
|
"disk_space_mb": requirements["disk_space_mb"],
|
||||||
"external_tools": {}
|
"external_tools": {},
|
||||||
}
|
}
|
||||||
|
|
||||||
# Add Node.js requirements if needed
|
# Add Node.js requirements if needed
|
||||||
node_required = False
|
node_required = False
|
||||||
for component_name in component_names:
|
for component_name in component_names:
|
||||||
component_info = features.get("components", {}).get(component_name, {})
|
component_info = features.get("components", {}).get(component_name, {})
|
||||||
required_tools = component_info.get("required_tools", [])
|
required_tools = component_info.get("required_tools", [])
|
||||||
|
|
||||||
if "node" in required_tools:
|
if "node" in required_tools:
|
||||||
node_required = True
|
node_required = True
|
||||||
break
|
break
|
||||||
|
|
||||||
if node_required and "node" in requirements:
|
if node_required and "node" in requirements:
|
||||||
result["node"] = requirements["node"]
|
result["node"] = requirements["node"]
|
||||||
|
|
||||||
# Add external tool requirements
|
# Add external tool requirements
|
||||||
for component_name in component_names:
|
for component_name in component_names:
|
||||||
component_info = features.get("components", {}).get(component_name, {})
|
component_info = features.get("components", {}).get(component_name, {})
|
||||||
required_tools = component_info.get("required_tools", [])
|
required_tools = component_info.get("required_tools", [])
|
||||||
|
|
||||||
for tool in required_tools:
|
for tool in required_tools:
|
||||||
if tool in requirements.get("external_tools", {}):
|
if tool in requirements.get("external_tools", {}):
|
||||||
result["external_tools"][tool] = requirements["external_tools"][tool]
|
result["external_tools"][tool] = requirements["external_tools"][
|
||||||
|
tool
|
||||||
|
]
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def validate_config_files(self) -> List[str]:
|
def validate_config_files(self) -> List[str]:
|
||||||
"""
|
"""
|
||||||
Validate all configuration files
|
Validate all configuration files
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
List of validation errors (empty if all valid)
|
List of validation errors (empty if all valid)
|
||||||
"""
|
"""
|
||||||
errors = []
|
errors = []
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.load_features()
|
self.load_features()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
errors.append(f"Features config error: {e}")
|
errors.append(f"Features config error: {e}")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.load_requirements()
|
self.load_requirements()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
errors.append(f"Requirements config error: {e}")
|
errors.append(f"Requirements config error: {e}")
|
||||||
|
|
||||||
return errors
|
return errors
|
||||||
|
|
||||||
def clear_cache(self) -> None:
|
def clear_cache(self) -> None:
|
||||||
"""Clear cached configuration data"""
|
"""Clear cached configuration data"""
|
||||||
self._features_cache = None
|
self._features_cache = None
|
||||||
self._requirements_cache = None
|
self._requirements_cache = None
|
||||||
|
|||||||
@ -12,83 +12,87 @@ import hashlib
|
|||||||
|
|
||||||
class FileService:
|
class FileService:
|
||||||
"""Cross-platform file operations manager"""
|
"""Cross-platform file operations manager"""
|
||||||
|
|
||||||
def __init__(self, dry_run: bool = False):
|
def __init__(self, dry_run: bool = False):
|
||||||
"""
|
"""
|
||||||
Initialize file manager
|
Initialize file manager
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
dry_run: If True, only simulate file operations
|
dry_run: If True, only simulate file operations
|
||||||
"""
|
"""
|
||||||
self.dry_run = dry_run
|
self.dry_run = dry_run
|
||||||
self.copied_files: List[Path] = []
|
self.copied_files: List[Path] = []
|
||||||
self.created_dirs: List[Path] = []
|
self.created_dirs: List[Path] = []
|
||||||
|
|
||||||
def copy_file(self, source: Path, target: Path, preserve_permissions: bool = True) -> bool:
|
def copy_file(
|
||||||
|
self, source: Path, target: Path, preserve_permissions: bool = True
|
||||||
|
) -> bool:
|
||||||
"""
|
"""
|
||||||
Copy single file with permission preservation
|
Copy single file with permission preservation
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
source: Source file path
|
source: Source file path
|
||||||
target: Target file path
|
target: Target file path
|
||||||
preserve_permissions: Whether to preserve file permissions
|
preserve_permissions: Whether to preserve file permissions
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
True if successful, False otherwise
|
True if successful, False otherwise
|
||||||
"""
|
"""
|
||||||
if not source.exists():
|
if not source.exists():
|
||||||
raise FileNotFoundError(f"Source file not found: {source}")
|
raise FileNotFoundError(f"Source file not found: {source}")
|
||||||
|
|
||||||
if not source.is_file():
|
if not source.is_file():
|
||||||
raise ValueError(f"Source is not a file: {source}")
|
raise ValueError(f"Source is not a file: {source}")
|
||||||
|
|
||||||
if self.dry_run:
|
if self.dry_run:
|
||||||
print(f"[DRY RUN] Would copy {source} -> {target}")
|
print(f"[DRY RUN] Would copy {source} -> {target}")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Ensure target directory exists
|
# Ensure target directory exists
|
||||||
target.parent.mkdir(parents=True, exist_ok=True)
|
target.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
# Copy file
|
# Copy file
|
||||||
if preserve_permissions:
|
if preserve_permissions:
|
||||||
shutil.copy2(source, target)
|
shutil.copy2(source, target)
|
||||||
else:
|
else:
|
||||||
shutil.copy(source, target)
|
shutil.copy(source, target)
|
||||||
|
|
||||||
self.copied_files.append(target)
|
self.copied_files.append(target)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error copying {source} to {target}: {e}")
|
print(f"Error copying {source} to {target}: {e}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def copy_directory(self, source: Path, target: Path, ignore_patterns: Optional[List[str]] = None) -> bool:
|
def copy_directory(
|
||||||
|
self, source: Path, target: Path, ignore_patterns: Optional[List[str]] = None
|
||||||
|
) -> bool:
|
||||||
"""
|
"""
|
||||||
Recursively copy directory with gitignore-style patterns
|
Recursively copy directory with gitignore-style patterns
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
source: Source directory path
|
source: Source directory path
|
||||||
target: Target directory path
|
target: Target directory path
|
||||||
ignore_patterns: List of patterns to ignore (gitignore style)
|
ignore_patterns: List of patterns to ignore (gitignore style)
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
True if successful, False otherwise
|
True if successful, False otherwise
|
||||||
"""
|
"""
|
||||||
if not source.exists():
|
if not source.exists():
|
||||||
raise FileNotFoundError(f"Source directory not found: {source}")
|
raise FileNotFoundError(f"Source directory not found: {source}")
|
||||||
|
|
||||||
if not source.is_dir():
|
if not source.is_dir():
|
||||||
raise ValueError(f"Source is not a directory: {source}")
|
raise ValueError(f"Source is not a directory: {source}")
|
||||||
|
|
||||||
ignore_patterns = ignore_patterns or []
|
ignore_patterns = ignore_patterns or []
|
||||||
default_ignores = ['.git', '.gitignore', '__pycache__', '*.pyc', '.DS_Store']
|
default_ignores = [".git", ".gitignore", "__pycache__", "*.pyc", ".DS_Store"]
|
||||||
all_ignores = ignore_patterns + default_ignores
|
all_ignores = ignore_patterns + default_ignores
|
||||||
|
|
||||||
if self.dry_run:
|
if self.dry_run:
|
||||||
print(f"[DRY RUN] Would copy directory {source} -> {target}")
|
print(f"[DRY RUN] Would copy directory {source} -> {target}")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Create ignore function
|
# Create ignore function
|
||||||
def ignore_func(directory: str, contents: List[str]) -> List[str]:
|
def ignore_func(directory: str, contents: List[str]) -> List[str]:
|
||||||
@ -96,250 +100,258 @@ class FileService:
|
|||||||
for item in contents:
|
for item in contents:
|
||||||
item_path = Path(directory) / item
|
item_path = Path(directory) / item
|
||||||
rel_path = item_path.relative_to(source)
|
rel_path = item_path.relative_to(source)
|
||||||
|
|
||||||
# Check against ignore patterns
|
# Check against ignore patterns
|
||||||
for pattern in all_ignores:
|
for pattern in all_ignores:
|
||||||
if fnmatch.fnmatch(item, pattern) or fnmatch.fnmatch(str(rel_path), pattern):
|
if fnmatch.fnmatch(item, pattern) or fnmatch.fnmatch(
|
||||||
|
str(rel_path), pattern
|
||||||
|
):
|
||||||
ignored.append(item)
|
ignored.append(item)
|
||||||
break
|
break
|
||||||
|
|
||||||
return ignored
|
return ignored
|
||||||
|
|
||||||
# Copy tree
|
# Copy tree
|
||||||
shutil.copytree(source, target, ignore=ignore_func, dirs_exist_ok=True)
|
shutil.copytree(source, target, ignore=ignore_func, dirs_exist_ok=True)
|
||||||
|
|
||||||
# Track created directories and files
|
# Track created directories and files
|
||||||
for item in target.rglob('*'):
|
for item in target.rglob("*"):
|
||||||
if item.is_dir():
|
if item.is_dir():
|
||||||
self.created_dirs.append(item)
|
self.created_dirs.append(item)
|
||||||
else:
|
else:
|
||||||
self.copied_files.append(item)
|
self.copied_files.append(item)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error copying directory {source} to {target}: {e}")
|
print(f"Error copying directory {source} to {target}: {e}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def ensure_directory(self, directory: Path, mode: int = 0o755) -> bool:
|
def ensure_directory(self, directory: Path, mode: int = 0o755) -> bool:
|
||||||
"""
|
"""
|
||||||
Create directory and parents if they don't exist
|
Create directory and parents if they don't exist
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
directory: Directory path to create
|
directory: Directory path to create
|
||||||
mode: Directory permissions (Unix only)
|
mode: Directory permissions (Unix only)
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
True if successful, False otherwise
|
True if successful, False otherwise
|
||||||
"""
|
"""
|
||||||
if self.dry_run:
|
if self.dry_run:
|
||||||
print(f"[DRY RUN] Would create directory {directory}")
|
print(f"[DRY RUN] Would create directory {directory}")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
try:
|
try:
|
||||||
directory.mkdir(parents=True, exist_ok=True, mode=mode)
|
directory.mkdir(parents=True, exist_ok=True, mode=mode)
|
||||||
|
|
||||||
if directory not in self.created_dirs:
|
if directory not in self.created_dirs:
|
||||||
self.created_dirs.append(directory)
|
self.created_dirs.append(directory)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error creating directory {directory}: {e}")
|
print(f"Error creating directory {directory}: {e}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def remove_file(self, file_path: Path) -> bool:
|
def remove_file(self, file_path: Path) -> bool:
|
||||||
"""
|
"""
|
||||||
Remove single file
|
Remove single file
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
file_path: Path to file to remove
|
file_path: Path to file to remove
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
True if successful, False otherwise
|
True if successful, False otherwise
|
||||||
"""
|
"""
|
||||||
if not file_path.exists():
|
if not file_path.exists():
|
||||||
return True # Already gone
|
return True # Already gone
|
||||||
|
|
||||||
if self.dry_run:
|
if self.dry_run:
|
||||||
print(f"[DRY RUN] Would remove file {file_path}")
|
print(f"[DRY RUN] Would remove file {file_path}")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if file_path.is_file():
|
if file_path.is_file():
|
||||||
file_path.unlink()
|
file_path.unlink()
|
||||||
else:
|
else:
|
||||||
print(f"Warning: {file_path} is not a file, skipping")
|
print(f"Warning: {file_path} is not a file, skipping")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# Remove from tracking
|
# Remove from tracking
|
||||||
if file_path in self.copied_files:
|
if file_path in self.copied_files:
|
||||||
self.copied_files.remove(file_path)
|
self.copied_files.remove(file_path)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error removing file {file_path}: {e}")
|
print(f"Error removing file {file_path}: {e}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def remove_directory(self, directory: Path, recursive: bool = False) -> bool:
|
def remove_directory(self, directory: Path, recursive: bool = False) -> bool:
|
||||||
"""
|
"""
|
||||||
Remove directory
|
Remove directory
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
directory: Directory path to remove
|
directory: Directory path to remove
|
||||||
recursive: Whether to remove recursively
|
recursive: Whether to remove recursively
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
True if successful, False otherwise
|
True if successful, False otherwise
|
||||||
"""
|
"""
|
||||||
if not directory.exists():
|
if not directory.exists():
|
||||||
return True # Already gone
|
return True # Already gone
|
||||||
|
|
||||||
if self.dry_run:
|
if self.dry_run:
|
||||||
action = "recursively remove" if recursive else "remove"
|
action = "recursively remove" if recursive else "remove"
|
||||||
print(f"[DRY RUN] Would {action} directory {directory}")
|
print(f"[DRY RUN] Would {action} directory {directory}")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if recursive:
|
if recursive:
|
||||||
shutil.rmtree(directory)
|
shutil.rmtree(directory)
|
||||||
else:
|
else:
|
||||||
directory.rmdir() # Only works if empty
|
directory.rmdir() # Only works if empty
|
||||||
|
|
||||||
# Remove from tracking
|
# Remove from tracking
|
||||||
if directory in self.created_dirs:
|
if directory in self.created_dirs:
|
||||||
self.created_dirs.remove(directory)
|
self.created_dirs.remove(directory)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error removing directory {directory}: {e}")
|
print(f"Error removing directory {directory}: {e}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def resolve_home_path(self, path: str) -> Path:
|
def resolve_home_path(self, path: str) -> Path:
|
||||||
"""
|
"""
|
||||||
Convert path with ~ to actual home path on any OS
|
Convert path with ~ to actual home path on any OS
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
path: Path string potentially containing ~
|
path: Path string potentially containing ~
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Resolved Path object
|
Resolved Path object
|
||||||
"""
|
"""
|
||||||
return Path(path).expanduser().resolve()
|
return Path(path).expanduser().resolve()
|
||||||
|
|
||||||
def make_executable(self, file_path: Path) -> bool:
|
def make_executable(self, file_path: Path) -> bool:
|
||||||
"""
|
"""
|
||||||
Make file executable (Unix/Linux/macOS)
|
Make file executable (Unix/Linux/macOS)
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
file_path: Path to file to make executable
|
file_path: Path to file to make executable
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
True if successful, False otherwise
|
True if successful, False otherwise
|
||||||
"""
|
"""
|
||||||
if not file_path.exists():
|
if not file_path.exists():
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if self.dry_run:
|
if self.dry_run:
|
||||||
print(f"[DRY RUN] Would make {file_path} executable")
|
print(f"[DRY RUN] Would make {file_path} executable")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Get current permissions
|
# Get current permissions
|
||||||
current_mode = file_path.stat().st_mode
|
current_mode = file_path.stat().st_mode
|
||||||
|
|
||||||
# Add execute permissions for owner, group, and others
|
# Add execute permissions for owner, group, and others
|
||||||
new_mode = current_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH
|
new_mode = current_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH
|
||||||
|
|
||||||
file_path.chmod(new_mode)
|
file_path.chmod(new_mode)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error making {file_path} executable: {e}")
|
print(f"Error making {file_path} executable: {e}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def get_file_hash(self, file_path: Path, algorithm: str = 'sha256') -> Optional[str]:
|
def get_file_hash(
|
||||||
|
self, file_path: Path, algorithm: str = "sha256"
|
||||||
|
) -> Optional[str]:
|
||||||
"""
|
"""
|
||||||
Calculate file hash
|
Calculate file hash
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
file_path: Path to file
|
file_path: Path to file
|
||||||
algorithm: Hash algorithm (md5, sha1, sha256, etc.)
|
algorithm: Hash algorithm (md5, sha1, sha256, etc.)
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Hex hash string or None if error
|
Hex hash string or None if error
|
||||||
"""
|
"""
|
||||||
if not file_path.exists() or not file_path.is_file():
|
if not file_path.exists() or not file_path.is_file():
|
||||||
return None
|
return None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
hasher = hashlib.new(algorithm)
|
hasher = hashlib.new(algorithm)
|
||||||
|
|
||||||
with open(file_path, 'rb') as f:
|
with open(file_path, "rb") as f:
|
||||||
# Read in chunks for large files
|
# Read in chunks for large files
|
||||||
for chunk in iter(lambda: f.read(8192), b""):
|
for chunk in iter(lambda: f.read(8192), b""):
|
||||||
hasher.update(chunk)
|
hasher.update(chunk)
|
||||||
|
|
||||||
return hasher.hexdigest()
|
return hasher.hexdigest()
|
||||||
|
|
||||||
except Exception:
|
except Exception:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def verify_file_integrity(self, file_path: Path, expected_hash: str, algorithm: str = 'sha256') -> bool:
|
def verify_file_integrity(
|
||||||
|
self, file_path: Path, expected_hash: str, algorithm: str = "sha256"
|
||||||
|
) -> bool:
|
||||||
"""
|
"""
|
||||||
Verify file integrity using hash
|
Verify file integrity using hash
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
file_path: Path to file to verify
|
file_path: Path to file to verify
|
||||||
expected_hash: Expected hash value
|
expected_hash: Expected hash value
|
||||||
algorithm: Hash algorithm used
|
algorithm: Hash algorithm used
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
True if file matches expected hash, False otherwise
|
True if file matches expected hash, False otherwise
|
||||||
"""
|
"""
|
||||||
actual_hash = self.get_file_hash(file_path, algorithm)
|
actual_hash = self.get_file_hash(file_path, algorithm)
|
||||||
return actual_hash is not None and actual_hash.lower() == expected_hash.lower()
|
return actual_hash is not None and actual_hash.lower() == expected_hash.lower()
|
||||||
|
|
||||||
def get_directory_size(self, directory: Path) -> int:
|
def get_directory_size(self, directory: Path) -> int:
|
||||||
"""
|
"""
|
||||||
Calculate total size of directory in bytes
|
Calculate total size of directory in bytes
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
directory: Directory path
|
directory: Directory path
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Total size in bytes
|
Total size in bytes
|
||||||
"""
|
"""
|
||||||
if not directory.exists() or not directory.is_dir():
|
if not directory.exists() or not directory.is_dir():
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
total_size = 0
|
total_size = 0
|
||||||
try:
|
try:
|
||||||
for file_path in directory.rglob('*'):
|
for file_path in directory.rglob("*"):
|
||||||
if file_path.is_file():
|
if file_path.is_file():
|
||||||
total_size += file_path.stat().st_size
|
total_size += file_path.stat().st_size
|
||||||
except Exception:
|
except Exception:
|
||||||
pass # Skip files we can't access
|
pass # Skip files we can't access
|
||||||
|
|
||||||
return total_size
|
return total_size
|
||||||
|
|
||||||
def find_files(self, directory: Path, pattern: str = '*', recursive: bool = True) -> List[Path]:
|
def find_files(
|
||||||
|
self, directory: Path, pattern: str = "*", recursive: bool = True
|
||||||
|
) -> List[Path]:
|
||||||
"""
|
"""
|
||||||
Find files matching pattern
|
Find files matching pattern
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
directory: Directory to search
|
directory: Directory to search
|
||||||
pattern: Glob pattern to match
|
pattern: Glob pattern to match
|
||||||
recursive: Whether to search recursively
|
recursive: Whether to search recursively
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
List of matching file paths
|
List of matching file paths
|
||||||
"""
|
"""
|
||||||
if not directory.exists() or not directory.is_dir():
|
if not directory.exists() or not directory.is_dir():
|
||||||
return []
|
return []
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if recursive:
|
if recursive:
|
||||||
return list(directory.rglob(pattern))
|
return list(directory.rglob(pattern))
|
||||||
@ -347,52 +359,54 @@ class FileService:
|
|||||||
return list(directory.glob(pattern))
|
return list(directory.glob(pattern))
|
||||||
except Exception:
|
except Exception:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def backup_file(self, file_path: Path, backup_suffix: str = '.backup') -> Optional[Path]:
|
def backup_file(
|
||||||
|
self, file_path: Path, backup_suffix: str = ".backup"
|
||||||
|
) -> Optional[Path]:
|
||||||
"""
|
"""
|
||||||
Create backup copy of file
|
Create backup copy of file
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
file_path: Path to file to backup
|
file_path: Path to file to backup
|
||||||
backup_suffix: Suffix to add to backup file
|
backup_suffix: Suffix to add to backup file
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Path to backup file or None if failed
|
Path to backup file or None if failed
|
||||||
"""
|
"""
|
||||||
if not file_path.exists() or not file_path.is_file():
|
if not file_path.exists() or not file_path.is_file():
|
||||||
return None
|
return None
|
||||||
|
|
||||||
backup_path = file_path.with_suffix(file_path.suffix + backup_suffix)
|
backup_path = file_path.with_suffix(file_path.suffix + backup_suffix)
|
||||||
|
|
||||||
if self.copy_file(file_path, backup_path):
|
if self.copy_file(file_path, backup_path):
|
||||||
return backup_path
|
return backup_path
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get_free_space(self, path: Path) -> int:
|
def get_free_space(self, path: Path) -> int:
|
||||||
"""
|
"""
|
||||||
Get free disk space at path in bytes
|
Get free disk space at path in bytes
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
path: Path to check (can be file or directory)
|
path: Path to check (can be file or directory)
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Free space in bytes
|
Free space in bytes
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
if path.is_file():
|
if path.is_file():
|
||||||
path = path.parent
|
path = path.parent
|
||||||
|
|
||||||
stat_result = shutil.disk_usage(path)
|
stat_result = shutil.disk_usage(path)
|
||||||
return stat_result.free
|
return stat_result.free
|
||||||
except Exception:
|
except Exception:
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
def cleanup_tracked_files(self) -> None:
|
def cleanup_tracked_files(self) -> None:
|
||||||
"""Remove all files and directories created during this session"""
|
"""Remove all files and directories created during this session"""
|
||||||
if self.dry_run:
|
if self.dry_run:
|
||||||
print("[DRY RUN] Would cleanup tracked files")
|
print("[DRY RUN] Would cleanup tracked files")
|
||||||
return
|
return
|
||||||
|
|
||||||
# Remove files first
|
# Remove files first
|
||||||
for file_path in reversed(self.copied_files):
|
for file_path in reversed(self.copied_files):
|
||||||
try:
|
try:
|
||||||
@ -400,7 +414,7 @@ class FileService:
|
|||||||
file_path.unlink()
|
file_path.unlink()
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# Remove directories (in reverse order of creation)
|
# Remove directories (in reverse order of creation)
|
||||||
for directory in reversed(self.created_dirs):
|
for directory in reversed(self.created_dirs):
|
||||||
try:
|
try:
|
||||||
@ -408,21 +422,21 @@ class FileService:
|
|||||||
directory.rmdir()
|
directory.rmdir()
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
self.copied_files.clear()
|
self.copied_files.clear()
|
||||||
self.created_dirs.clear()
|
self.created_dirs.clear()
|
||||||
|
|
||||||
def get_operation_summary(self) -> Dict[str, Any]:
|
def get_operation_summary(self) -> Dict[str, Any]:
|
||||||
"""
|
"""
|
||||||
Get summary of file operations performed
|
Get summary of file operations performed
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Dict with operation statistics
|
Dict with operation statistics
|
||||||
"""
|
"""
|
||||||
return {
|
return {
|
||||||
'files_copied': len(self.copied_files),
|
"files_copied": len(self.copied_files),
|
||||||
'directories_created': len(self.created_dirs),
|
"directories_created": len(self.created_dirs),
|
||||||
'dry_run': self.dry_run,
|
"dry_run": self.dry_run,
|
||||||
'copied_files': [str(f) for f in self.copied_files],
|
"copied_files": [str(f) for f in self.copied_files],
|
||||||
'created_directories': [str(d) for d in self.created_dirs]
|
"created_directories": [str(d) for d in self.created_dirs],
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,11 +14,11 @@ import copy
|
|||||||
|
|
||||||
class SettingsService:
|
class SettingsService:
|
||||||
"""Manages settings.json file operations"""
|
"""Manages settings.json file operations"""
|
||||||
|
|
||||||
def __init__(self, install_dir: Path):
|
def __init__(self, install_dir: Path):
|
||||||
"""
|
"""
|
||||||
Initialize settings manager
|
Initialize settings manager
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
install_dir: Installation directory containing settings.json
|
install_dir: Installation directory containing settings.json
|
||||||
"""
|
"""
|
||||||
@ -26,27 +26,29 @@ class SettingsService:
|
|||||||
self.settings_file = install_dir / "settings.json"
|
self.settings_file = install_dir / "settings.json"
|
||||||
self.metadata_file = install_dir / ".superclaude-metadata.json"
|
self.metadata_file = install_dir / ".superclaude-metadata.json"
|
||||||
self.backup_dir = install_dir / "backups" / "settings"
|
self.backup_dir = install_dir / "backups" / "settings"
|
||||||
|
|
||||||
def load_settings(self) -> Dict[str, Any]:
|
def load_settings(self) -> Dict[str, Any]:
|
||||||
"""
|
"""
|
||||||
Load settings from settings.json
|
Load settings from settings.json
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Settings dict (empty if file doesn't exist)
|
Settings dict (empty if file doesn't exist)
|
||||||
"""
|
"""
|
||||||
if not self.settings_file.exists():
|
if not self.settings_file.exists():
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
with open(self.settings_file, 'r', encoding='utf-8') as f:
|
with open(self.settings_file, "r", encoding="utf-8") as f:
|
||||||
return json.load(f)
|
return json.load(f)
|
||||||
except (json.JSONDecodeError, IOError) as e:
|
except (json.JSONDecodeError, IOError) as e:
|
||||||
raise ValueError(f"Could not load settings from {self.settings_file}: {e}")
|
raise ValueError(f"Could not load settings from {self.settings_file}: {e}")
|
||||||
|
|
||||||
def save_settings(self, settings: Dict[str, Any], create_backup: bool = True) -> None:
|
def save_settings(
|
||||||
|
self, settings: Dict[str, Any], create_backup: bool = True
|
||||||
|
) -> None:
|
||||||
"""
|
"""
|
||||||
Save settings to settings.json with optional backup
|
Save settings to settings.json with optional backup
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
settings: Settings dict to save
|
settings: Settings dict to save
|
||||||
create_backup: Whether to create backup before saving
|
create_backup: Whether to create backup before saving
|
||||||
@ -54,46 +56,46 @@ class SettingsService:
|
|||||||
# Create backup if requested and file exists
|
# Create backup if requested and file exists
|
||||||
if create_backup and self.settings_file.exists():
|
if create_backup and self.settings_file.exists():
|
||||||
self._create_settings_backup()
|
self._create_settings_backup()
|
||||||
|
|
||||||
# Ensure directory exists
|
# Ensure directory exists
|
||||||
self.settings_file.parent.mkdir(parents=True, exist_ok=True)
|
self.settings_file.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
# Save with pretty formatting
|
# Save with pretty formatting
|
||||||
try:
|
try:
|
||||||
with open(self.settings_file, 'w', encoding='utf-8') as f:
|
with open(self.settings_file, "w", encoding="utf-8") as f:
|
||||||
json.dump(settings, f, indent=2, ensure_ascii=False, sort_keys=True)
|
json.dump(settings, f, indent=2, ensure_ascii=False, sort_keys=True)
|
||||||
except IOError as e:
|
except IOError as e:
|
||||||
raise ValueError(f"Could not save settings to {self.settings_file}: {e}")
|
raise ValueError(f"Could not save settings to {self.settings_file}: {e}")
|
||||||
|
|
||||||
def load_metadata(self) -> Dict[str, Any]:
|
def load_metadata(self) -> Dict[str, Any]:
|
||||||
"""
|
"""
|
||||||
Load SuperClaude metadata from .superclaude-metadata.json
|
Load SuperClaude metadata from .superclaude-metadata.json
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Metadata dict (empty if file doesn't exist)
|
Metadata dict (empty if file doesn't exist)
|
||||||
"""
|
"""
|
||||||
if not self.metadata_file.exists():
|
if not self.metadata_file.exists():
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
with open(self.metadata_file, 'r', encoding='utf-8') as f:
|
with open(self.metadata_file, "r", encoding="utf-8") as f:
|
||||||
return json.load(f)
|
return json.load(f)
|
||||||
except (json.JSONDecodeError, IOError) as e:
|
except (json.JSONDecodeError, IOError) as e:
|
||||||
raise ValueError(f"Could not load metadata from {self.metadata_file}: {e}")
|
raise ValueError(f"Could not load metadata from {self.metadata_file}: {e}")
|
||||||
|
|
||||||
def save_metadata(self, metadata: Dict[str, Any]) -> None:
|
def save_metadata(self, metadata: Dict[str, Any]) -> None:
|
||||||
"""
|
"""
|
||||||
Save SuperClaude metadata to .superclaude-metadata.json
|
Save SuperClaude metadata to .superclaude-metadata.json
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
metadata: Metadata dict to save
|
metadata: Metadata dict to save
|
||||||
"""
|
"""
|
||||||
# Ensure directory exists
|
# Ensure directory exists
|
||||||
self.metadata_file.parent.mkdir(parents=True, exist_ok=True)
|
self.metadata_file.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
# Save with pretty formatting
|
# Save with pretty formatting
|
||||||
try:
|
try:
|
||||||
with open(self.metadata_file, 'w', encoding='utf-8') as f:
|
with open(self.metadata_file, "w", encoding="utf-8") as f:
|
||||||
json.dump(metadata, f, indent=2, ensure_ascii=False, sort_keys=True)
|
json.dump(metadata, f, indent=2, ensure_ascii=False, sort_keys=True)
|
||||||
except IOError as e:
|
except IOError as e:
|
||||||
raise ValueError(f"Could not save metadata to {self.metadata_file}: {e}")
|
raise ValueError(f"Could not save metadata to {self.metadata_file}: {e}")
|
||||||
@ -125,128 +127,134 @@ class SettingsService:
|
|||||||
def migrate_superclaude_data(self) -> bool:
|
def migrate_superclaude_data(self) -> bool:
|
||||||
"""
|
"""
|
||||||
Migrate SuperClaude-specific data from settings.json to metadata file
|
Migrate SuperClaude-specific data from settings.json to metadata file
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
True if migration occurred, False if no data to migrate
|
True if migration occurred, False if no data to migrate
|
||||||
"""
|
"""
|
||||||
settings = self.load_settings()
|
settings = self.load_settings()
|
||||||
|
|
||||||
# SuperClaude-specific fields to migrate
|
# SuperClaude-specific fields to migrate
|
||||||
superclaude_fields = ["components", "framework", "superclaude", "mcp"]
|
superclaude_fields = ["components", "framework", "superclaude", "mcp"]
|
||||||
data_to_migrate = {}
|
data_to_migrate = {}
|
||||||
fields_found = False
|
fields_found = False
|
||||||
|
|
||||||
# Extract SuperClaude data
|
# Extract SuperClaude data
|
||||||
for field in superclaude_fields:
|
for field in superclaude_fields:
|
||||||
if field in settings:
|
if field in settings:
|
||||||
data_to_migrate[field] = settings[field]
|
data_to_migrate[field] = settings[field]
|
||||||
fields_found = True
|
fields_found = True
|
||||||
|
|
||||||
if not fields_found:
|
if not fields_found:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# Load existing metadata (if any) and merge
|
# Load existing metadata (if any) and merge
|
||||||
existing_metadata = self.load_metadata()
|
existing_metadata = self.load_metadata()
|
||||||
merged_metadata = self._deep_merge(existing_metadata, data_to_migrate)
|
merged_metadata = self._deep_merge(existing_metadata, data_to_migrate)
|
||||||
|
|
||||||
# Save to metadata file
|
# Save to metadata file
|
||||||
self.save_metadata(merged_metadata)
|
self.save_metadata(merged_metadata)
|
||||||
|
|
||||||
# Remove SuperClaude fields from settings
|
# Remove SuperClaude fields from settings
|
||||||
clean_settings = {k: v for k, v in settings.items() if k not in superclaude_fields}
|
clean_settings = {
|
||||||
|
k: v for k, v in settings.items() if k not in superclaude_fields
|
||||||
|
}
|
||||||
|
|
||||||
# Save cleaned settings
|
# Save cleaned settings
|
||||||
self.save_settings(clean_settings, create_backup=True)
|
self.save_settings(clean_settings, create_backup=True)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def merge_settings(self, modifications: Dict[str, Any]) -> Dict[str, Any]:
|
def merge_settings(self, modifications: Dict[str, Any]) -> Dict[str, Any]:
|
||||||
"""
|
"""
|
||||||
Deep merge modifications into existing settings
|
Deep merge modifications into existing settings
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
modifications: Settings modifications to merge
|
modifications: Settings modifications to merge
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Merged settings dict
|
Merged settings dict
|
||||||
"""
|
"""
|
||||||
existing = self.load_settings()
|
existing = self.load_settings()
|
||||||
return self._deep_merge(existing, modifications)
|
return self._deep_merge(existing, modifications)
|
||||||
|
|
||||||
def update_settings(self, modifications: Dict[str, Any], create_backup: bool = True) -> None:
|
def update_settings(
|
||||||
|
self, modifications: Dict[str, Any], create_backup: bool = True
|
||||||
|
) -> None:
|
||||||
"""
|
"""
|
||||||
Update settings with modifications
|
Update settings with modifications
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
modifications: Settings modifications to apply
|
modifications: Settings modifications to apply
|
||||||
create_backup: Whether to create backup before updating
|
create_backup: Whether to create backup before updating
|
||||||
"""
|
"""
|
||||||
merged = self.merge_settings(modifications)
|
merged = self.merge_settings(modifications)
|
||||||
self.save_settings(merged, create_backup)
|
self.save_settings(merged, create_backup)
|
||||||
|
|
||||||
def get_setting(self, key_path: str, default: Any = None) -> Any:
|
def get_setting(self, key_path: str, default: Any = None) -> Any:
|
||||||
"""
|
"""
|
||||||
Get setting value using dot-notation path
|
Get setting value using dot-notation path
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
key_path: Dot-separated path (e.g., "hooks.enabled")
|
key_path: Dot-separated path (e.g., "hooks.enabled")
|
||||||
default: Default value if key not found
|
default: Default value if key not found
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Setting value or default
|
Setting value or default
|
||||||
"""
|
"""
|
||||||
settings = self.load_settings()
|
settings = self.load_settings()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
value = settings
|
value = settings
|
||||||
for key in key_path.split('.'):
|
for key in key_path.split("."):
|
||||||
value = value[key]
|
value = value[key]
|
||||||
return value
|
return value
|
||||||
except (KeyError, TypeError):
|
except (KeyError, TypeError):
|
||||||
return default
|
return default
|
||||||
|
|
||||||
def set_setting(self, key_path: str, value: Any, create_backup: bool = True) -> None:
|
def set_setting(
|
||||||
|
self, key_path: str, value: Any, create_backup: bool = True
|
||||||
|
) -> None:
|
||||||
"""
|
"""
|
||||||
Set setting value using dot-notation path
|
Set setting value using dot-notation path
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
key_path: Dot-separated path (e.g., "hooks.enabled")
|
key_path: Dot-separated path (e.g., "hooks.enabled")
|
||||||
value: Value to set
|
value: Value to set
|
||||||
create_backup: Whether to create backup before updating
|
create_backup: Whether to create backup before updating
|
||||||
"""
|
"""
|
||||||
# Build nested dict structure
|
# Build nested dict structure
|
||||||
keys = key_path.split('.')
|
keys = key_path.split(".")
|
||||||
modification = {}
|
modification = {}
|
||||||
current = modification
|
current = modification
|
||||||
|
|
||||||
for key in keys[:-1]:
|
for key in keys[:-1]:
|
||||||
current[key] = {}
|
current[key] = {}
|
||||||
current = current[key]
|
current = current[key]
|
||||||
|
|
||||||
current[keys[-1]] = value
|
current[keys[-1]] = value
|
||||||
|
|
||||||
self.update_settings(modification, create_backup)
|
self.update_settings(modification, create_backup)
|
||||||
|
|
||||||
def remove_setting(self, key_path: str, create_backup: bool = True) -> bool:
|
def remove_setting(self, key_path: str, create_backup: bool = True) -> bool:
|
||||||
"""
|
"""
|
||||||
Remove setting using dot-notation path
|
Remove setting using dot-notation path
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
key_path: Dot-separated path to remove
|
key_path: Dot-separated path to remove
|
||||||
create_backup: Whether to create backup before updating
|
create_backup: Whether to create backup before updating
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
True if setting was removed, False if not found
|
True if setting was removed, False if not found
|
||||||
"""
|
"""
|
||||||
settings = self.load_settings()
|
settings = self.load_settings()
|
||||||
keys = key_path.split('.')
|
keys = key_path.split(".")
|
||||||
|
|
||||||
# Navigate to parent of target key
|
# Navigate to parent of target key
|
||||||
current = settings
|
current = settings
|
||||||
try:
|
try:
|
||||||
for key in keys[:-1]:
|
for key in keys[:-1]:
|
||||||
current = current[key]
|
current = current[key]
|
||||||
|
|
||||||
# Remove the target key
|
# Remove the target key
|
||||||
if keys[-1] in current:
|
if keys[-1] in current:
|
||||||
del current[keys[-1]]
|
del current[keys[-1]]
|
||||||
@ -254,14 +262,16 @@ class SettingsService:
|
|||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
except (KeyError, TypeError):
|
except (KeyError, TypeError):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def add_component_registration(self, component_name: str, component_info: Dict[str, Any]) -> None:
|
def add_component_registration(
|
||||||
|
self, component_name: str, component_info: Dict[str, Any]
|
||||||
|
) -> None:
|
||||||
"""
|
"""
|
||||||
Add component to registry in metadata
|
Add component to registry in metadata
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
component_name: Name of component
|
component_name: Name of component
|
||||||
component_info: Component metadata dict
|
component_info: Component metadata dict
|
||||||
@ -269,21 +279,21 @@ class SettingsService:
|
|||||||
metadata = self.load_metadata()
|
metadata = self.load_metadata()
|
||||||
if "components" not in metadata:
|
if "components" not in metadata:
|
||||||
metadata["components"] = {}
|
metadata["components"] = {}
|
||||||
|
|
||||||
metadata["components"][component_name] = {
|
metadata["components"][component_name] = {
|
||||||
**component_info,
|
**component_info,
|
||||||
"installed_at": datetime.now().isoformat()
|
"installed_at": datetime.now().isoformat(),
|
||||||
}
|
}
|
||||||
|
|
||||||
self.save_metadata(metadata)
|
self.save_metadata(metadata)
|
||||||
|
|
||||||
def remove_component_registration(self, component_name: str) -> bool:
|
def remove_component_registration(self, component_name: str) -> bool:
|
||||||
"""
|
"""
|
||||||
Remove component from registry in metadata
|
Remove component from registry in metadata
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
component_name: Name of component to remove
|
component_name: Name of component to remove
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
True if component was removed, False if not found
|
True if component was removed, False if not found
|
||||||
"""
|
"""
|
||||||
@ -293,64 +303,64 @@ class SettingsService:
|
|||||||
self.save_metadata(metadata)
|
self.save_metadata(metadata)
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def get_installed_components(self) -> Dict[str, Dict[str, Any]]:
|
def get_installed_components(self) -> Dict[str, Dict[str, Any]]:
|
||||||
"""
|
"""
|
||||||
Get all installed components from registry
|
Get all installed components from registry
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Dict of component_name -> component_info
|
Dict of component_name -> component_info
|
||||||
"""
|
"""
|
||||||
metadata = self.load_metadata()
|
metadata = self.load_metadata()
|
||||||
return metadata.get("components", {})
|
return metadata.get("components", {})
|
||||||
|
|
||||||
def is_component_installed(self, component_name: str) -> bool:
|
def is_component_installed(self, component_name: str) -> bool:
|
||||||
"""
|
"""
|
||||||
Check if component is registered as installed
|
Check if component is registered as installed
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
component_name: Name of component to check
|
component_name: Name of component to check
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
True if component is installed, False otherwise
|
True if component is installed, False otherwise
|
||||||
"""
|
"""
|
||||||
components = self.get_installed_components()
|
components = self.get_installed_components()
|
||||||
return component_name in components
|
return component_name in components
|
||||||
|
|
||||||
def get_component_version(self, component_name: str) -> Optional[str]:
|
def get_component_version(self, component_name: str) -> Optional[str]:
|
||||||
"""
|
"""
|
||||||
Get installed version of component
|
Get installed version of component
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
component_name: Name of component
|
component_name: Name of component
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Version string or None if not installed
|
Version string or None if not installed
|
||||||
"""
|
"""
|
||||||
components = self.get_installed_components()
|
components = self.get_installed_components()
|
||||||
component_info = components.get(component_name, {})
|
component_info = components.get(component_name, {})
|
||||||
return component_info.get("version")
|
return component_info.get("version")
|
||||||
|
|
||||||
def update_framework_version(self, version: str) -> None:
|
def update_framework_version(self, version: str) -> None:
|
||||||
"""
|
"""
|
||||||
Update SuperClaude framework version in metadata
|
Update SuperClaude framework version in metadata
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
version: Framework version string
|
version: Framework version string
|
||||||
"""
|
"""
|
||||||
metadata = self.load_metadata()
|
metadata = self.load_metadata()
|
||||||
if "framework" not in metadata:
|
if "framework" not in metadata:
|
||||||
metadata["framework"] = {}
|
metadata["framework"] = {}
|
||||||
|
|
||||||
metadata["framework"]["version"] = version
|
metadata["framework"]["version"] = version
|
||||||
metadata["framework"]["updated_at"] = datetime.now().isoformat()
|
metadata["framework"]["updated_at"] = datetime.now().isoformat()
|
||||||
|
|
||||||
self.save_metadata(metadata)
|
self.save_metadata(metadata)
|
||||||
|
|
||||||
def check_installation_exists(self) -> bool:
|
def check_installation_exists(self) -> bool:
|
||||||
"""
|
"""
|
||||||
Get SuperClaude framework version from metadata
|
Get SuperClaude framework version from metadata
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Version string or None if not set
|
Version string or None if not set
|
||||||
"""
|
"""
|
||||||
@ -364,152 +374,160 @@ class SettingsService:
|
|||||||
Version string or None if not set
|
Version string or None if not set
|
||||||
"""
|
"""
|
||||||
return self.settings_file.exists()
|
return self.settings_file.exists()
|
||||||
|
|
||||||
def get_metadata_setting(self, key_path: str, default: Any = None) -> Any:
|
def get_metadata_setting(self, key_path: str, default: Any = None) -> Any:
|
||||||
"""
|
"""
|
||||||
Get metadata value using dot-notation path
|
Get metadata value using dot-notation path
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
key_path: Dot-separated path (e.g., "framework.version")
|
key_path: Dot-separated path (e.g., "framework.version")
|
||||||
default: Default value if key not found
|
default: Default value if key not found
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Metadata value or default
|
Metadata value or default
|
||||||
"""
|
"""
|
||||||
metadata = self.load_metadata()
|
metadata = self.load_metadata()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
value = metadata
|
value = metadata
|
||||||
for key in key_path.split('.'):
|
for key in key_path.split("."):
|
||||||
value = value[key]
|
value = value[key]
|
||||||
return value
|
return value
|
||||||
except (KeyError, TypeError):
|
except (KeyError, TypeError):
|
||||||
return default
|
return default
|
||||||
|
|
||||||
def _deep_merge(self, base: Dict[str, Any], overlay: Dict[str, Any]) -> Dict[str, Any]:
|
def _deep_merge(
|
||||||
|
self, base: Dict[str, Any], overlay: Dict[str, Any]
|
||||||
|
) -> Dict[str, Any]:
|
||||||
"""
|
"""
|
||||||
Deep merge two dictionaries
|
Deep merge two dictionaries
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
base: Base dictionary
|
base: Base dictionary
|
||||||
overlay: Dictionary to merge on top
|
overlay: Dictionary to merge on top
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Merged dictionary
|
Merged dictionary
|
||||||
"""
|
"""
|
||||||
result = copy.deepcopy(base)
|
result = copy.deepcopy(base)
|
||||||
|
|
||||||
for key, value in overlay.items():
|
for key, value in overlay.items():
|
||||||
if key in result and isinstance(result[key], dict) and isinstance(value, dict):
|
if (
|
||||||
|
key in result
|
||||||
|
and isinstance(result[key], dict)
|
||||||
|
and isinstance(value, dict)
|
||||||
|
):
|
||||||
result[key] = self._deep_merge(result[key], value)
|
result[key] = self._deep_merge(result[key], value)
|
||||||
else:
|
else:
|
||||||
result[key] = copy.deepcopy(value)
|
result[key] = copy.deepcopy(value)
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def _create_settings_backup(self) -> Path:
|
def _create_settings_backup(self) -> Path:
|
||||||
"""
|
"""
|
||||||
Create timestamped backup of settings.json
|
Create timestamped backup of settings.json
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Path to backup file
|
Path to backup file
|
||||||
"""
|
"""
|
||||||
if not self.settings_file.exists():
|
if not self.settings_file.exists():
|
||||||
raise ValueError("Cannot backup non-existent settings file")
|
raise ValueError("Cannot backup non-existent settings file")
|
||||||
|
|
||||||
# Create backup directory
|
# Create backup directory
|
||||||
self.backup_dir.mkdir(parents=True, exist_ok=True)
|
self.backup_dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
# Create timestamped backup
|
# Create timestamped backup
|
||||||
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
||||||
backup_file = self.backup_dir / f"settings_{timestamp}.json"
|
backup_file = self.backup_dir / f"settings_{timestamp}.json"
|
||||||
|
|
||||||
shutil.copy2(self.settings_file, backup_file)
|
shutil.copy2(self.settings_file, backup_file)
|
||||||
|
|
||||||
# Keep only last 10 backups
|
# Keep only last 10 backups
|
||||||
self._cleanup_old_backups()
|
self._cleanup_old_backups()
|
||||||
|
|
||||||
return backup_file
|
return backup_file
|
||||||
|
|
||||||
def _cleanup_old_backups(self, keep_count: int = 10) -> None:
|
def _cleanup_old_backups(self, keep_count: int = 10) -> None:
|
||||||
"""
|
"""
|
||||||
Remove old backup files, keeping only the most recent
|
Remove old backup files, keeping only the most recent
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
keep_count: Number of backups to keep
|
keep_count: Number of backups to keep
|
||||||
"""
|
"""
|
||||||
if not self.backup_dir.exists():
|
if not self.backup_dir.exists():
|
||||||
return
|
return
|
||||||
|
|
||||||
# Get all backup files sorted by modification time
|
# Get all backup files sorted by modification time
|
||||||
backup_files = []
|
backup_files = []
|
||||||
for file in self.backup_dir.glob("settings_*.json"):
|
for file in self.backup_dir.glob("settings_*.json"):
|
||||||
backup_files.append((file.stat().st_mtime, file))
|
backup_files.append((file.stat().st_mtime, file))
|
||||||
|
|
||||||
backup_files.sort(reverse=True) # Most recent first
|
backup_files.sort(reverse=True) # Most recent first
|
||||||
|
|
||||||
# Remove old backups
|
# Remove old backups
|
||||||
for _, file in backup_files[keep_count:]:
|
for _, file in backup_files[keep_count:]:
|
||||||
try:
|
try:
|
||||||
file.unlink()
|
file.unlink()
|
||||||
except OSError:
|
except OSError:
|
||||||
pass # Ignore errors when cleaning up
|
pass # Ignore errors when cleaning up
|
||||||
|
|
||||||
def list_backups(self) -> List[Dict[str, Any]]:
|
def list_backups(self) -> List[Dict[str, Any]]:
|
||||||
"""
|
"""
|
||||||
List available settings backups
|
List available settings backups
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
List of backup info dicts with name, path, and timestamp
|
List of backup info dicts with name, path, and timestamp
|
||||||
"""
|
"""
|
||||||
if not self.backup_dir.exists():
|
if not self.backup_dir.exists():
|
||||||
return []
|
return []
|
||||||
|
|
||||||
backups = []
|
backups = []
|
||||||
for file in self.backup_dir.glob("settings_*.json"):
|
for file in self.backup_dir.glob("settings_*.json"):
|
||||||
try:
|
try:
|
||||||
stat = file.stat()
|
stat = file.stat()
|
||||||
backups.append({
|
backups.append(
|
||||||
"name": file.name,
|
{
|
||||||
"path": str(file),
|
"name": file.name,
|
||||||
"size": stat.st_size,
|
"path": str(file),
|
||||||
"created": datetime.fromtimestamp(stat.st_ctime).isoformat(),
|
"size": stat.st_size,
|
||||||
"modified": datetime.fromtimestamp(stat.st_mtime).isoformat()
|
"created": datetime.fromtimestamp(stat.st_ctime).isoformat(),
|
||||||
})
|
"modified": datetime.fromtimestamp(stat.st_mtime).isoformat(),
|
||||||
|
}
|
||||||
|
)
|
||||||
except OSError:
|
except OSError:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Sort by creation time, most recent first
|
# Sort by creation time, most recent first
|
||||||
backups.sort(key=lambda x: x["created"], reverse=True)
|
backups.sort(key=lambda x: x["created"], reverse=True)
|
||||||
return backups
|
return backups
|
||||||
|
|
||||||
def restore_backup(self, backup_name: str) -> bool:
|
def restore_backup(self, backup_name: str) -> bool:
|
||||||
"""
|
"""
|
||||||
Restore settings from backup
|
Restore settings from backup
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
backup_name: Name of backup file to restore
|
backup_name: Name of backup file to restore
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
True if successful, False otherwise
|
True if successful, False otherwise
|
||||||
"""
|
"""
|
||||||
backup_file = self.backup_dir / backup_name
|
backup_file = self.backup_dir / backup_name
|
||||||
|
|
||||||
if not backup_file.exists():
|
if not backup_file.exists():
|
||||||
return False
|
return False
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Validate backup file first
|
# Validate backup file first
|
||||||
with open(backup_file, 'r', encoding='utf-8') as f:
|
with open(backup_file, "r", encoding="utf-8") as f:
|
||||||
json.load(f) # Will raise exception if invalid
|
json.load(f) # Will raise exception if invalid
|
||||||
|
|
||||||
# Create backup of current settings
|
# Create backup of current settings
|
||||||
if self.settings_file.exists():
|
if self.settings_file.exists():
|
||||||
self._create_settings_backup()
|
self._create_settings_backup()
|
||||||
|
|
||||||
# Restore backup
|
# Restore backup
|
||||||
shutil.copy2(backup_file, self.settings_file)
|
shutil.copy2(backup_file, self.settings_file)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
except (json.JSONDecodeError, IOError):
|
except (json.JSONDecodeError, IOError):
|
||||||
return False
|
return False
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user