feat: Add comprehensive getting started guide and Claude Code CLI optimization
• Create complete getting started guide with step-by-step workflows • Add Claude Code CLI premium workspace experience with native commands • Integrate workspace commands into all 8 BMAD agents (dev, qa, sm, analyst, architect, ux-expert, pm, po) • Implement automatic session management with heartbeat monitoring • Add context-aware agent handoffs with intelligent opportunity detection • Create built-in workspace maintenance with integrity checking and auto-repair • Enhance UX with intelligent suggestions and productivity analytics • Update enhancements.md with prominent links to comprehensive guide • Add Claude Code optimization system (2400+ lines across 5 modules)
This commit is contained in:
parent
7d7d98ee29
commit
5bfe13ed0a
|
|
@ -69,6 +69,11 @@ commands:
|
||||||
- research-prompt {topic}: execute task create-deep-research-prompt.md
|
- research-prompt {topic}: execute task create-deep-research-prompt.md
|
||||||
- brainstorm {topic}: Facilitate structured brainstorming session (run task facilitate-brainstorming-session.md with template brainstorming-output-tmpl.yaml)
|
- brainstorm {topic}: Facilitate structured brainstorming session (run task facilitate-brainstorming-session.md with template brainstorming-output-tmpl.yaml)
|
||||||
- elicit: run the task advanced-elicitation
|
- elicit: run the task advanced-elicitation
|
||||||
|
- workspace-init: Initialize collaborative workspace for this project and start analyst session tracking
|
||||||
|
- workspace-status: Show current workspace status, active sessions, and research context overview
|
||||||
|
- workspace-cleanup: Clean up workspace files, validate research data integrity, and maintain workspace health
|
||||||
|
- workspace-handoff: Prepare context handoff to specified agent with complete analysis context and insights
|
||||||
|
- workspace-sync: Synchronize with latest workspace context and restore analytical state
|
||||||
- exit: Say goodbye as the Business Analyst, and then abandon inhabiting this persona
|
- exit: Say goodbye as the Business Analyst, and then abandon inhabiting this persona
|
||||||
dependencies:
|
dependencies:
|
||||||
tasks:
|
tasks:
|
||||||
|
|
|
||||||
|
|
@ -72,6 +72,11 @@ commands:
|
||||||
- research {topic}: execute task create-deep-research-prompt
|
- research {topic}: execute task create-deep-research-prompt
|
||||||
- shard-prd: run the task shard-doc.md for the provided architecture.md (ask if not found)
|
- shard-prd: run the task shard-doc.md for the provided architecture.md (ask if not found)
|
||||||
- yolo: Toggle Yolo Mode
|
- yolo: Toggle Yolo Mode
|
||||||
|
- workspace-init: Initialize collaborative workspace for this project and start architect session tracking
|
||||||
|
- workspace-status: Show current workspace status, active sessions, and architectural context overview
|
||||||
|
- workspace-cleanup: Clean up workspace files, validate architectural data integrity, and maintain workspace health
|
||||||
|
- workspace-handoff: Prepare context handoff to specified agent with complete architectural context and design decisions
|
||||||
|
- workspace-sync: Synchronize with latest workspace context and restore architectural state
|
||||||
- exit: Say goodbye as the Architect, and then abandon inhabiting this persona
|
- exit: Say goodbye as the Architect, and then abandon inhabiting this persona
|
||||||
dependencies:
|
dependencies:
|
||||||
tasks:
|
tasks:
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,11 @@ commands:
|
||||||
- build-context: MANDATORY execute build-context-analysis task file (NOT generic Task tool) to ensure clean compilation and runtime
|
- build-context: MANDATORY execute build-context-analysis task file (NOT generic Task tool) to ensure clean compilation and runtime
|
||||||
- develop-story: Follow the systematic develop-story workflow to implement all story tasks with automatic progress tracking
|
- develop-story: Follow the systematic develop-story workflow to implement all story tasks with automatic progress tracking
|
||||||
- escalate: MANDATORY execute loop-detection-escalation task file (NOT generic Task tool) when stuck in loops or facing persistent blockers
|
- escalate: MANDATORY execute loop-detection-escalation task file (NOT generic Task tool) when stuck in loops or facing persistent blockers
|
||||||
|
- workspace-init: Initialize collaborative workspace for this project and start session tracking
|
||||||
|
- workspace-status: Show current workspace status, active sessions, and collaboration context
|
||||||
|
- workspace-cleanup: Clean up workspace files, optimize storage, and maintain workspace health
|
||||||
|
- workspace-handoff: Prepare context handoff to specified agent with complete development context
|
||||||
|
- workspace-sync: Synchronize with latest workspace context and restore collaborative state
|
||||||
- exit: Say goodbye as the Developer, and then abandon inhabiting this persona
|
- exit: Say goodbye as the Developer, and then abandon inhabiting this persona
|
||||||
|
|
||||||
task_execution_enforcement:
|
task_execution_enforcement:
|
||||||
|
|
|
||||||
|
|
@ -65,6 +65,11 @@ commands:
|
||||||
- shard-prd: run the task shard-doc.md for the provided prd.md (ask if not found)
|
- shard-prd: run the task shard-doc.md for the provided prd.md (ask if not found)
|
||||||
- correct-course: execute the correct-course task
|
- correct-course: execute the correct-course task
|
||||||
- yolo: Toggle Yolo Mode
|
- yolo: Toggle Yolo Mode
|
||||||
|
- workspace-init: Initialize collaborative workspace for this project and start product management session tracking
|
||||||
|
- workspace-status: Show current workspace status, active sessions, and product management overview
|
||||||
|
- workspace-cleanup: Clean up workspace files, validate product data integrity, and maintain workspace health
|
||||||
|
- workspace-handoff: Prepare context handoff to specified agent with complete product management context
|
||||||
|
- workspace-sync: Synchronize with latest workspace context and restore product management state
|
||||||
- exit: Exit (confirm)
|
- exit: Exit (confirm)
|
||||||
dependencies:
|
dependencies:
|
||||||
tasks:
|
tasks:
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,11 @@ commands:
|
||||||
- doc-out: Output full document to current destination file
|
- doc-out: Output full document to current destination file
|
||||||
- validate-story-draft {story}: run the task validate-next-story against the provided story file
|
- validate-story-draft {story}: run the task validate-next-story against the provided story file
|
||||||
- yolo: Toggle Yolo Mode off on - on will skip doc section confirmations
|
- yolo: Toggle Yolo Mode off on - on will skip doc section confirmations
|
||||||
|
- workspace-init: Initialize collaborative workspace for this project and start product owner session tracking
|
||||||
|
- workspace-status: Show current workspace status, active sessions, and product ownership overview
|
||||||
|
- workspace-cleanup: Clean up workspace files, validate product ownership data integrity, and maintain workspace health
|
||||||
|
- workspace-handoff: Prepare context handoff to specified agent with complete product ownership context
|
||||||
|
- workspace-sync: Synchronize with latest workspace context and restore product ownership state
|
||||||
- exit: Exit (confirm)
|
- exit: Exit (confirm)
|
||||||
dependencies:
|
dependencies:
|
||||||
tasks:
|
tasks:
|
||||||
|
|
|
||||||
|
|
@ -132,6 +132,11 @@ commands:
|
||||||
- escalate: MANDATORY execute loop-detection-escalation task (NOT generic Task tool) for validation challenges requiring external expertise
|
- escalate: MANDATORY execute loop-detection-escalation task (NOT generic Task tool) for validation challenges requiring external expertise
|
||||||
- story-code-audit: MANDATORY execute the task story-to-code-audit (NOT generic Task tool) for comprehensive cross-reference mapping between completed stories and actual codebase implementation
|
- story-code-audit: MANDATORY execute the task story-to-code-audit (NOT generic Task tool) for comprehensive cross-reference mapping between completed stories and actual codebase implementation
|
||||||
- create-doc {template}: execute task create-doc (no template = ONLY show available templates listed under dependencies/templates below)
|
- create-doc {template}: execute task create-doc (no template = ONLY show available templates listed under dependencies/templates below)
|
||||||
|
- workspace-init: Initialize collaborative workspace for this project and start QA session tracking
|
||||||
|
- workspace-status: Show current workspace status, active sessions, and quality metrics overview
|
||||||
|
- workspace-cleanup: Clean up workspace files, validate quality data integrity, and maintain workspace health
|
||||||
|
- workspace-handoff: Prepare context handoff to specified agent with complete QA analysis and quality metrics
|
||||||
|
- workspace-sync: Synchronize with latest workspace context and restore quality assessment state
|
||||||
- exit: Say goodbye as the QA Engineer, and then abandon inhabiting this persona
|
- exit: Say goodbye as the QA Engineer, and then abandon inhabiting this persona
|
||||||
|
|
||||||
task_execution_enforcement:
|
task_execution_enforcement:
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,11 @@ commands:
|
||||||
- draft: Execute task create-next-story.md
|
- draft: Execute task create-next-story.md
|
||||||
- correct-course: Execute task correct-course.md
|
- correct-course: Execute task correct-course.md
|
||||||
- story-checklist: Execute task execute-checklist.md with checklist story-draft-checklist.md
|
- story-checklist: Execute task execute-checklist.md with checklist story-draft-checklist.md
|
||||||
|
- workspace-init: Initialize collaborative workspace for this project and start Scrum Master session tracking
|
||||||
|
- workspace-status: Show current workspace status, active sessions, and project management overview
|
||||||
|
- workspace-cleanup: Clean up workspace files, validate project tracking data, and maintain workspace health
|
||||||
|
- workspace-handoff: Prepare context handoff to specified agent with complete project management context
|
||||||
|
- workspace-sync: Synchronize with latest workspace context and restore project management state
|
||||||
- exit: Say goodbye as the Scrum Master, and then abandon inhabiting this persona
|
- exit: Say goodbye as the Scrum Master, and then abandon inhabiting this persona
|
||||||
dependencies:
|
dependencies:
|
||||||
tasks:
|
tasks:
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,11 @@ commands:
|
||||||
- help: Show numbered list of the following commands to allow selection
|
- help: Show numbered list of the following commands to allow selection
|
||||||
- create-front-end-spec: run task create-doc.md with template front-end-spec-tmpl.yaml
|
- create-front-end-spec: run task create-doc.md with template front-end-spec-tmpl.yaml
|
||||||
- generate-ui-prompt: Run task generate-ai-frontend-prompt.md
|
- generate-ui-prompt: Run task generate-ai-frontend-prompt.md
|
||||||
|
- workspace-init: Initialize collaborative workspace for this project and start UX session tracking
|
||||||
|
- workspace-status: Show current workspace status, active sessions, and UX design context overview
|
||||||
|
- workspace-cleanup: Clean up workspace files, validate UX data integrity, and maintain workspace health
|
||||||
|
- workspace-handoff: Prepare context handoff to specified agent with complete UX context and design specifications
|
||||||
|
- workspace-sync: Synchronize with latest workspace context and restore UX design state
|
||||||
- exit: Say goodbye as the UX Expert, and then abandon inhabiting this persona
|
- exit: Say goodbye as the UX Expert, and then abandon inhabiting this persona
|
||||||
dependencies:
|
dependencies:
|
||||||
tasks:
|
tasks:
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@
|
||||||
| **🎛️ Role-Optimized LLM Settings** | Maximize agent performance for specific tasks | Custom temperature, top-P, and penalty settings per agent role |
|
| **🎛️ Role-Optimized LLM Settings** | Maximize agent performance for specific tasks | Custom temperature, top-P, and penalty settings per agent role |
|
||||||
| **📋 Story-to-Code Audit** | Ensure completed stories match actual implementation | Auto-cross-reference with gap detection and remediation story generation |
|
| **📋 Story-to-Code Audit** | Ensure completed stories match actual implementation | Auto-cross-reference with gap detection and remediation story generation |
|
||||||
| **🔧 IDE Environment Detection** | Optimize tool usage based on detected IDE | Auto-adapt to Cursor, Claude Code, Windsurf, Trae, Roo, Cline, Gemini, Copilot |
|
| **🔧 IDE Environment Detection** | Optimize tool usage based on detected IDE | Auto-adapt to Cursor, Claude Code, Windsurf, Trae, Roo, Cline, Gemini, Copilot |
|
||||||
|
| **🚀 Claude Code CLI Optimization** | Premium workspace experience for Claude Code users | Native commands, auto-session management, context-aware handoffs, built-in maintenance |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -33,6 +34,9 @@
|
||||||
*reality-audit # Comprehensive quality validation with regression analysis
|
*reality-audit # Comprehensive quality validation with regression analysis
|
||||||
*build-context # Pre-fix investigation with git history and risk assessment
|
*build-context # Pre-fix investigation with git history and risk assessment
|
||||||
*escalate # External AI collaboration when stuck in loops
|
*escalate # External AI collaboration when stuck in loops
|
||||||
|
*workspace-init # Initialize collaborative workspace session (Claude Code CLI)
|
||||||
|
*workspace-status # Show workspace status and collaboration context
|
||||||
|
*workspace-handoff # Context-aware agent transitions with intelligent suggestions
|
||||||
```
|
```
|
||||||
|
|
||||||
### 🧪 QA Agent (Quinn)
|
### 🧪 QA Agent (Quinn)
|
||||||
|
|
@ -42,6 +46,8 @@
|
||||||
*create-remediation # Generate regression-safe fix stories with pattern compliance
|
*create-remediation # Generate regression-safe fix stories with pattern compliance
|
||||||
*story-code-audit # Cross-reference completed stories vs actual codebase implementation
|
*story-code-audit # Cross-reference completed stories vs actual codebase implementation
|
||||||
*Push2Git # Override safety gates to push despite quality issues
|
*Push2Git # Override safety gates to push despite quality issues
|
||||||
|
*workspace-cleanup # Automated workspace maintenance and optimization (Claude Code CLI)
|
||||||
|
*workspace-sync # Synchronize with latest workspace context and quality metrics
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
@ -93,6 +99,13 @@
|
||||||
- Eliminates approval prompts by leveraging integrated IDE capabilities
|
- Eliminates approval prompts by leveraging integrated IDE capabilities
|
||||||
- Batches CLI commands when running in standalone mode
|
- Batches CLI commands when running in standalone mode
|
||||||
|
|
||||||
|
**🚀 Claude Code CLI Premium Experience (Enterprise-Grade Workspace)**
|
||||||
|
- Native workspace commands integrated into all 8 BMAD agents (dev, qa, sm, analyst, architect, ux-expert, pm, po)
|
||||||
|
- Automatic session management with heartbeat monitoring and cleanup
|
||||||
|
- Context-aware agent handoffs with intelligent opportunity detection and enhanced context transfer
|
||||||
|
- Built-in workspace maintenance with automatic integrity checking and repair
|
||||||
|
- Enhanced UX with intelligent suggestions, productivity analytics, and seamless workflow integration
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🎯 Quality Scoring System
|
## 🎯 Quality Scoring System
|
||||||
|
|
@ -115,6 +128,10 @@
|
||||||
|
|
||||||
## 🚀 Getting Started
|
## 🚀 Getting Started
|
||||||
|
|
||||||
|
> **📖 [Complete Getting Started Guide](getting-started-guide.md)** - Master all enhanced features with step-by-step workflows, agent selection guide, and advanced techniques.
|
||||||
|
|
||||||
|
### Quick Start (Core Workflow)
|
||||||
|
|
||||||
### 1. **Develop Your Story**
|
### 1. **Develop Your Story**
|
||||||
```bash
|
```bash
|
||||||
*develop-story
|
*develop-story
|
||||||
|
|
@ -135,6 +152,9 @@
|
||||||
### 4. **Collaborate When Stuck** (automatic)
|
### 4. **Collaborate When Stuck** (automatic)
|
||||||
*After 3 failed attempts, get copy-paste prompts for external AI collaboration*
|
*After 3 failed attempts, get copy-paste prompts for external AI collaboration*
|
||||||
|
|
||||||
|
**Need help with Claude Code CLI workspace commands, agent selection, or advanced features?**
|
||||||
|
👉 **[See the Complete Getting Started Guide](getting-started-guide.md)**
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🪙 Token Efficiency & AI Focus
|
## 🪙 Token Efficiency & AI Focus
|
||||||
|
|
@ -180,15 +200,23 @@ The structured framework **keeps AI agents more focused and productive** than ad
|
||||||
## 📁 Implementation Details
|
## 📁 Implementation Details
|
||||||
|
|
||||||
### Core Framework Files
|
### Core Framework Files
|
||||||
- `bmad-core/agents/dev.md` - Enhanced developer agent with role-optimized LLM settings (temp=0.4) for precise code
|
- `bmad-core/agents/dev.md` - Enhanced developer agent with role-optimized LLM settings (temp=0.4) for precise code + workspace commands
|
||||||
- `bmad-core/agents/qa.md` - Enhanced QA agent with systematic analysis settings (temp=0.3) and auto-remediation
|
- `bmad-core/agents/qa.md` - Enhanced QA agent with systematic analysis settings (temp=0.3) and auto-remediation + workspace commands
|
||||||
- `bmad-core/agents/analyst.md` - Business analyst with creative ideation settings (temp=0.8) for innovative thinking
|
- `bmad-core/agents/analyst.md` - Business analyst with creative ideation settings (temp=0.8) for innovative thinking + workspace commands
|
||||||
- `bmad-core/agents/architect.md` - Technical architect with balanced creativity settings (temp=0.6) for design solutions
|
- `bmad-core/agents/architect.md` - Technical architect with balanced creativity settings (temp=0.6) for design solutions + workspace commands
|
||||||
- `bmad-core/agents/ux-expert.md` - UX designer with high creativity settings (temp=0.75) for innovative interfaces
|
- `bmad-core/agents/ux-expert.md` - UX designer with high creativity settings (temp=0.75) for innovative interfaces + workspace commands
|
||||||
|
- `bmad-core/agents/sm.md`, `pm.md`, `po.md` - Enhanced project management agents with native workspace integration
|
||||||
- `bmad-core/tasks/reality-audit-comprehensive.md` - 10-phase comprehensive audit with automatic remediation execution
|
- `bmad-core/tasks/reality-audit-comprehensive.md` - 10-phase comprehensive audit with automatic remediation execution
|
||||||
- `bmad-core/tasks/loop-detection-escalation.md` - External collaboration framework with copy-paste prompts
|
- `bmad-core/tasks/loop-detection-escalation.md` - External collaboration framework with copy-paste prompts
|
||||||
- `bmad-core/tasks/create-remediation-story.md` - Automated fix story generation with regression prevention
|
- `bmad-core/tasks/create-remediation-story.md` - Automated fix story generation with regression prevention
|
||||||
|
|
||||||
|
### Claude Code CLI Optimization Files
|
||||||
|
- `tools/installer/lib/claude-code-session-manager.js` - Automatic session lifecycle management (400+ lines)
|
||||||
|
- `tools/installer/lib/claude-code-workspace-commands.js` - Native workspace command implementations (500+ lines)
|
||||||
|
- `tools/installer/lib/claude-code-context-integration.js` - Context-aware integration system (400+ lines)
|
||||||
|
- `tools/installer/lib/claude-code-maintenance-system.js` - Built-in maintenance and repair (600+ lines)
|
||||||
|
- `tools/installer/lib/claude-code-ux-enhancements.js` - Enhanced UX with analytics (500+ lines)
|
||||||
|
|
||||||
### Enterprise Features
|
### Enterprise Features
|
||||||
- **Multi-language project detection** (Node.js, .NET, Java, Rust, Python, Go, Ruby, PHP)
|
- **Multi-language project detection** (Node.js, .NET, Java, Rust, Python, Go, Ruby, PHP)
|
||||||
- **Cross-platform compatibility** (Windows, Linux, macOS)
|
- **Cross-platform compatibility** (Windows, Linux, macOS)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,348 @@
|
||||||
|
# 🚀 BMAD Method - Complete Getting Started Guide
|
||||||
|
|
||||||
|
> **Master the enhanced BMAD workflow** - From basic development to enterprise-grade quality engineering with collaborative AI agents.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 Quick Start (2 Minutes)
|
||||||
|
|
||||||
|
### Your First Story
|
||||||
|
```bash
|
||||||
|
# 1. Start development
|
||||||
|
*develop-story
|
||||||
|
|
||||||
|
# 2. Validate quality
|
||||||
|
*reality-audit
|
||||||
|
|
||||||
|
# 3. Auto-push (if Grade A) or get remediation options
|
||||||
|
```
|
||||||
|
|
||||||
|
That's it! The system handles the rest automatically.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔧 Claude Code CLI Users - Premium Experience
|
||||||
|
|
||||||
|
### Workspace Commands (All Agents)
|
||||||
|
```bash
|
||||||
|
*workspace-init # Initialize collaborative workspace
|
||||||
|
*workspace-status # Show active sessions & collaboration context
|
||||||
|
*workspace-handoff # Context-aware agent transitions
|
||||||
|
*workspace-cleanup # Automated maintenance & optimization
|
||||||
|
*workspace-sync # Restore context & synchronize state
|
||||||
|
```
|
||||||
|
|
||||||
|
### Getting Started with Workspace
|
||||||
|
```bash
|
||||||
|
# 1. Initialize your project workspace
|
||||||
|
*workspace-init
|
||||||
|
|
||||||
|
# 2. Work on your story
|
||||||
|
*develop-story
|
||||||
|
|
||||||
|
# 3. Check workspace status anytime
|
||||||
|
*workspace-status
|
||||||
|
|
||||||
|
# 4. Hand off to QA with full context
|
||||||
|
*workspace-handoff qa
|
||||||
|
|
||||||
|
# 5. Clean up when done
|
||||||
|
*workspace-cleanup
|
||||||
|
```
|
||||||
|
|
||||||
|
**What You Get:**
|
||||||
|
- Automatic session lifecycle management
|
||||||
|
- Intelligent agent handoff suggestions
|
||||||
|
- Context preservation across sessions
|
||||||
|
- Built-in workspace health monitoring
|
||||||
|
- Enhanced productivity analytics
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🤖 Choosing the Right Agent
|
||||||
|
|
||||||
|
### 🏗️ Development Phase Agents
|
||||||
|
|
||||||
|
**James (Developer)** - `bmad dev`
|
||||||
|
```bash
|
||||||
|
*develop-story # Systematic implementation
|
||||||
|
*reality-audit # Quality validation
|
||||||
|
*build-context # Pre-fix investigation
|
||||||
|
*workspace-handoff # Context-aware transitions
|
||||||
|
```
|
||||||
|
*Use for: Code implementation, debugging, technical problem-solving*
|
||||||
|
|
||||||
|
**Quinn (QA)** - `bmad qa`
|
||||||
|
```bash
|
||||||
|
*reality-audit # Manual quality audit
|
||||||
|
*audit-validation # Auto-remediation with fix stories
|
||||||
|
*story-code-audit # Cross-reference stories vs code
|
||||||
|
*workspace-cleanup # Quality-focused maintenance
|
||||||
|
```
|
||||||
|
*Use for: Quality validation, testing, issue remediation*
|
||||||
|
|
||||||
|
**Morgan (Scrum Master)** - `bmad sm`
|
||||||
|
```bash
|
||||||
|
*create-story # Generate development stories
|
||||||
|
*reality-audit # Story quality validation
|
||||||
|
*workspace-status # Team collaboration overview
|
||||||
|
```
|
||||||
|
*Use for: Story creation, sprint planning, team coordination*
|
||||||
|
|
||||||
|
### 🎨 Planning Phase Agents
|
||||||
|
|
||||||
|
**Alex (Analyst)** - `bmad analyst`
|
||||||
|
```bash
|
||||||
|
*create-research # Deep domain investigation
|
||||||
|
*workspace-init # Research session tracking
|
||||||
|
```
|
||||||
|
*Use for: Market research, user analysis, requirement gathering*
|
||||||
|
|
||||||
|
**Sam (Architect)** - `bmad architect`
|
||||||
|
```bash
|
||||||
|
*create-architecture # Technical design documents
|
||||||
|
*workspace-handoff # Design context transfer
|
||||||
|
```
|
||||||
|
*Use for: System design, technology decisions, architecture planning*
|
||||||
|
|
||||||
|
**Jordan (UX Expert)** - `bmad ux-expert`
|
||||||
|
```bash
|
||||||
|
*create-ux # UI/UX specifications
|
||||||
|
*workspace-sync # Design context restoration
|
||||||
|
```
|
||||||
|
*Use for: User experience design, interface planning, usability*
|
||||||
|
|
||||||
|
### 📊 Product Management Agents
|
||||||
|
|
||||||
|
**John (Product Manager)** - `bmad pm`
|
||||||
|
```bash
|
||||||
|
*create-prd # Product Requirements Documents
|
||||||
|
*workspace-status # Product management overview
|
||||||
|
```
|
||||||
|
*Use for: PRD creation, product strategy, feature prioritization*
|
||||||
|
|
||||||
|
**Sarah (Product Owner)** - `bmad po`
|
||||||
|
```bash
|
||||||
|
*validate-story-draft # Story validation & acceptance criteria
|
||||||
|
*workspace-cleanup # Backlog maintenance
|
||||||
|
```
|
||||||
|
*Use for: Backlog management, story refinement, acceptance criteria*
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 Quality System Mastery
|
||||||
|
|
||||||
|
### Understanding Your Quality Score
|
||||||
|
|
||||||
|
**Grade A (90-100)** - Exceptional ✅
|
||||||
|
- Auto-push eligible
|
||||||
|
- Zero remediation needed
|
||||||
|
- Production ready
|
||||||
|
|
||||||
|
**Grade B (80-89)** - Good 🔵
|
||||||
|
- Meets quality gates
|
||||||
|
- Minor improvements suggested
|
||||||
|
- Ready for deployment
|
||||||
|
|
||||||
|
**Grade C (70-79)** - Acceptable 🟡
|
||||||
|
- Needs improvement before production
|
||||||
|
- Specific remediation options provided
|
||||||
|
- Safe to continue development
|
||||||
|
|
||||||
|
**Grade D (60-69)** - Poor 🟠
|
||||||
|
- Remediation required
|
||||||
|
- Multiple issues detected
|
||||||
|
- Fix before proceeding
|
||||||
|
|
||||||
|
**Grade F (<60)** - Failing 🔴
|
||||||
|
- Major issues detected
|
||||||
|
- Comprehensive remediation needed
|
||||||
|
- Do not deploy
|
||||||
|
|
||||||
|
### Automatic Features That Save Time
|
||||||
|
|
||||||
|
**🔄 Loop Detection (After 3 Failed Attempts)**
|
||||||
|
```bash
|
||||||
|
# System automatically provides:
|
||||||
|
"Copy this prompt to Gemini/GPT-4/Claude for collaboration:
|
||||||
|
[Generated external collaboration prompt]"
|
||||||
|
```
|
||||||
|
|
||||||
|
**🤖 Automatic Remediation (Zero Commands)**
|
||||||
|
- Quality issues → Fix stories generated automatically
|
||||||
|
- Oversized stories → Auto-split into manageable pieces
|
||||||
|
- Mixed concerns → Surgical fixes created immediately
|
||||||
|
|
||||||
|
**📤 Intelligent Git Push (Grade A Only)**
|
||||||
|
- Automatic push with quality metrics in commit message
|
||||||
|
- Manual override available with `*Push2Git`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎛️ Role-Optimized Performance
|
||||||
|
|
||||||
|
### Agent Temperature Settings (Automatic)
|
||||||
|
|
||||||
|
**Development Agents** (Precise Code)
|
||||||
|
- Developer: 0.4 - Focused, accurate implementations
|
||||||
|
- QA: 0.3 - Systematic, detailed analysis
|
||||||
|
|
||||||
|
**Creative Agents** (Innovation)
|
||||||
|
- Analyst: 0.8 - High creativity for market insights
|
||||||
|
- UX Expert: 0.75 - Creative interface solutions
|
||||||
|
|
||||||
|
**Strategic Agents** (Balanced)
|
||||||
|
- Architect: 0.6 - Structured creativity for design
|
||||||
|
- PM: 0.7 - Strategic thinking with clear communication
|
||||||
|
|
||||||
|
**Management Agents** (Organized)
|
||||||
|
- Scrum Master: 0.5 - Balanced planning and execution
|
||||||
|
- Product Owner: 0.6 - User-focused with systematic approach
|
||||||
|
|
||||||
|
*You don't need to configure these - they're optimized automatically per agent role.*
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔧 IDE Integration Features
|
||||||
|
|
||||||
|
### Automatic IDE Detection
|
||||||
|
The system automatically detects and optimizes for:
|
||||||
|
- **Claude Code** - Premium workspace experience
|
||||||
|
- **Cursor** - Native git panels, integrated testing
|
||||||
|
- **Windsurf** - Seamless tool integration
|
||||||
|
- **Cline, Trae, Roo** - Enhanced command batching
|
||||||
|
- **GitHub Copilot** - Compatible workflow integration
|
||||||
|
|
||||||
|
### What Changes Per IDE
|
||||||
|
**Claude Code CLI Users:**
|
||||||
|
- Get native workspace commands
|
||||||
|
- Automatic session management
|
||||||
|
- Context-aware handoffs
|
||||||
|
- Built-in maintenance system
|
||||||
|
|
||||||
|
**Other IDEs:**
|
||||||
|
- Optimized tool usage patterns
|
||||||
|
- Reduced approval prompts
|
||||||
|
- Intelligent command batching
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📋 Advanced Workflows
|
||||||
|
|
||||||
|
### Story-to-Code Auditing
|
||||||
|
```bash
|
||||||
|
# After completing stories, validate implementation
|
||||||
|
*story-code-audit
|
||||||
|
|
||||||
|
# System automatically:
|
||||||
|
# 1. Cross-references completed story tasks vs actual code
|
||||||
|
# 2. Identifies gaps between planned vs implemented features
|
||||||
|
# 3. Generates remediation stories for missing functionality
|
||||||
|
```
|
||||||
|
|
||||||
|
### Regression Prevention
|
||||||
|
```bash
|
||||||
|
# Before making changes to existing code
|
||||||
|
*build-context
|
||||||
|
|
||||||
|
# System provides:
|
||||||
|
# - Git history analysis
|
||||||
|
# - Risk assessment
|
||||||
|
# - Pattern compliance validation
|
||||||
|
# - Safe modification strategies
|
||||||
|
```
|
||||||
|
|
||||||
|
### External Collaboration (Automatic)
|
||||||
|
```bash
|
||||||
|
# When stuck after 3 attempts, system provides:
|
||||||
|
"Escalation: Copy this prompt to external AI:
|
||||||
|
|
||||||
|
CONTEXT: [Current situation]
|
||||||
|
ATTEMPTED SOLUTIONS: [What's been tried]
|
||||||
|
SPECIFIC CHALLENGE: [Exact issue]
|
||||||
|
DESIRED OUTCOME: [What success looks like]
|
||||||
|
|
||||||
|
Please provide alternative approaches or solutions."
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ⚡ Pro Tips for Maximum Efficiency
|
||||||
|
|
||||||
|
### 1. **Start with Workspace (Claude Code CLI)**
|
||||||
|
```bash
|
||||||
|
*workspace-init # Sets up collaborative environment
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. **Use the Right Agent for the Phase**
|
||||||
|
- **Planning**: analyst → pm → architect → ux-expert
|
||||||
|
- **Development**: sm → dev → qa
|
||||||
|
- **Management**: po for backlog, sm for sprints
|
||||||
|
|
||||||
|
### 3. **Trust the Automation**
|
||||||
|
- Let automatic remediation handle quality issues
|
||||||
|
- Use loop detection for external collaboration
|
||||||
|
- Rely on Grade A auto-push for perfect completions
|
||||||
|
|
||||||
|
### 4. **Leverage Context Handoffs**
|
||||||
|
```bash
|
||||||
|
*workspace-handoff architect # Intelligent context transfer
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. **Monitor Quality Continuously**
|
||||||
|
```bash
|
||||||
|
*reality-audit # Run anytime for quality insights
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🚨 Troubleshooting Common Issues
|
||||||
|
|
||||||
|
### "My story is too large"
|
||||||
|
**Solution**: System automatically detects and splits oversized stories
|
||||||
|
- Grade D/F audits trigger automatic story splitting
|
||||||
|
- Each piece becomes manageable (<8 tasks)
|
||||||
|
|
||||||
|
### "I'm stuck in a debugging loop"
|
||||||
|
**Solution**: Loop detection activates after 3 failed attempts
|
||||||
|
- Provides external AI collaboration prompts
|
||||||
|
- Resets counter on successful progress
|
||||||
|
|
||||||
|
### "Quality score is low"
|
||||||
|
**Solution**: Automatic remediation executes immediately
|
||||||
|
- Fix stories generated without manual commands
|
||||||
|
- Specific improvement actions provided based on grade
|
||||||
|
|
||||||
|
### "Agent handoff lost context"
|
||||||
|
**Solution**: Use workspace commands (Claude Code CLI)
|
||||||
|
```bash
|
||||||
|
*workspace-handoff [agent] # Preserves full context
|
||||||
|
```
|
||||||
|
|
||||||
|
### "Don't know what to do next"
|
||||||
|
**Solution**: System provides automatic options based on audit grade
|
||||||
|
- Grade-specific actions with effort estimates
|
||||||
|
- Clear next steps eliminate confusion
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📈 Success Metrics to Track
|
||||||
|
|
||||||
|
### Quality Indicators
|
||||||
|
- **Grade A stories**: Target 70%+ for mature projects
|
||||||
|
- **Automatic remediation**: Should handle 80%+ of quality issues
|
||||||
|
- **Loop detection**: Should rarely activate (<5% of stories)
|
||||||
|
|
||||||
|
### Productivity Indicators
|
||||||
|
- **Story completion time**: 60+ minutes saved per debugging session
|
||||||
|
- **Manual commands**: Zero needed for remediation execution
|
||||||
|
- **Context handoffs**: Seamless transitions between agents
|
||||||
|
|
||||||
|
### Process Indicators
|
||||||
|
- **Build status**: Clean builds with zero warnings
|
||||||
|
- **Regression issues**: <10% of stories cause regressions
|
||||||
|
- **Simulation patterns**: <5% reach production
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*🎯 **Ready to master AI-assisted development?** Follow these patterns and let the enhanced BMAD framework handle the complexity while you focus on creating great software.*
|
||||||
|
|
@ -329,6 +329,42 @@ async function promptInstallation() {
|
||||||
// Use selected IDEs directly
|
// Use selected IDEs directly
|
||||||
answers.ides = ides;
|
answers.ides = ides;
|
||||||
|
|
||||||
|
// Ask about Collaborative Workspace System
|
||||||
|
if (selectedItems.includes('bmad-core')) {
|
||||||
|
console.log(chalk.cyan('\n🤝 Collaborative Workspace System'));
|
||||||
|
console.log(chalk.dim('Enable multi-session AI agent coordination and context persistence.\n'));
|
||||||
|
|
||||||
|
const { enableWorkspace } = await inquirer.prompt([
|
||||||
|
{
|
||||||
|
type: 'confirm',
|
||||||
|
name: 'enableWorkspace',
|
||||||
|
message: chalk.magenta('🚀 Enable Collaborative Workspace System?') +
|
||||||
|
'\n • Multi-session AI agent coordination' +
|
||||||
|
'\n • Context persistence across sessions' +
|
||||||
|
'\n • Cross-IDE collaboration support' +
|
||||||
|
'\n • Enhanced workflow automation' +
|
||||||
|
'\n Enable workspace system?',
|
||||||
|
default: true
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
answers.enableWorkspace = enableWorkspace;
|
||||||
|
|
||||||
|
if (enableWorkspace) {
|
||||||
|
console.log(chalk.green('✅ Collaborative Workspace System will be configured during installation'));
|
||||||
|
|
||||||
|
if (ides.includes('claude-code')) {
|
||||||
|
console.log(chalk.blue('🎯 Claude Code CLI users will get native workspace commands'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ides.some(ide => ide !== 'claude-code')) {
|
||||||
|
console.log(chalk.blue('🛠️ Other IDE users will get comprehensive utility scripts'));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log(chalk.yellow('⚠️ Workspace system disabled - standard BMAD functionality only'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Configure GitHub Copilot immediately if selected
|
// Configure GitHub Copilot immediately if selected
|
||||||
if (ides.includes('github-copilot')) {
|
if (ides.includes('github-copilot')) {
|
||||||
console.log(chalk.cyan('\n🔧 GitHub Copilot Configuration'));
|
console.log(chalk.cyan('\n🔧 GitHub Copilot Configuration'));
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,524 @@
|
||||||
|
const HandoffManager = require('./handoff-manager');
|
||||||
|
const ContextManager = require('./context-manager');
|
||||||
|
const path = require('path');
|
||||||
|
const fs = require('fs');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Claude Code CLI Context-Aware Integration
|
||||||
|
* Provides seamless context transfer and intelligent handoffs within Claude Code CLI sessions
|
||||||
|
*/
|
||||||
|
class ClaudeCodeContextIntegration {
|
||||||
|
constructor(workspaceDir) {
|
||||||
|
this.workspaceDir = workspaceDir;
|
||||||
|
this.handoffManager = new HandoffManager(workspaceDir);
|
||||||
|
this.contextManager = new ContextManager(workspaceDir);
|
||||||
|
this.sessionContext = null;
|
||||||
|
this.activeAgent = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize context-aware session
|
||||||
|
*/
|
||||||
|
async initializeContextAware(agentType, sessionId) {
|
||||||
|
try {
|
||||||
|
this.activeAgent = agentType;
|
||||||
|
this.sessionContext = {
|
||||||
|
sessionId: sessionId,
|
||||||
|
agentType: agentType,
|
||||||
|
startTime: new Date().toISOString(),
|
||||||
|
contextVersion: '1.0',
|
||||||
|
smartFeatures: {
|
||||||
|
autoSuggestions: true,
|
||||||
|
contextAwareness: true,
|
||||||
|
intelligentHandoffs: true,
|
||||||
|
predictiveActions: true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Load existing context
|
||||||
|
const sharedContext = await this.contextManager.getSharedContext();
|
||||||
|
const decisions = await this.contextManager.getDecisions();
|
||||||
|
const progress = await this.contextManager.getProgress();
|
||||||
|
|
||||||
|
console.log('🧠 Context-aware features initialized');
|
||||||
|
console.log(` • Loaded ${decisions.length} decisions`);
|
||||||
|
console.log(` • Loaded ${progress.completedTasks || 0} completed tasks`);
|
||||||
|
|
||||||
|
if (sharedContext.currentFocus) {
|
||||||
|
console.log(` • Current Focus: ${sharedContext.currentFocus}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
status: 'initialized',
|
||||||
|
contextLoaded: true,
|
||||||
|
smartFeaturesEnabled: true
|
||||||
|
};
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to initialize context-aware features:', error.message);
|
||||||
|
return { status: 'failed', error: error.message };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate intelligent workspace suggestions based on context
|
||||||
|
*/
|
||||||
|
async generateIntelligentSuggestions() {
|
||||||
|
try {
|
||||||
|
const suggestions = [];
|
||||||
|
|
||||||
|
// Analyze current context
|
||||||
|
const sharedContext = await this.contextManager.getSharedContext();
|
||||||
|
const progress = await this.contextManager.getProgress();
|
||||||
|
const decisions = await this.contextManager.getDecisions();
|
||||||
|
|
||||||
|
// Suggest based on current focus
|
||||||
|
if (sharedContext.currentFocus) {
|
||||||
|
if (sharedContext.currentFocus.includes('implement') || sharedContext.currentFocus.includes('develop')) {
|
||||||
|
suggestions.push({
|
||||||
|
type: 'workflow',
|
||||||
|
priority: 'high',
|
||||||
|
title: 'Ready for Quality Review',
|
||||||
|
description: 'Consider using *workspace-handoff qa to get quality validation',
|
||||||
|
action: '*workspace-handoff qa',
|
||||||
|
reasoning: 'Development work detected, QA review recommended'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sharedContext.currentFocus.includes('test') || sharedContext.currentFocus.includes('bug')) {
|
||||||
|
suggestions.push({
|
||||||
|
type: 'workflow',
|
||||||
|
priority: 'medium',
|
||||||
|
title: 'Development Collaboration',
|
||||||
|
description: 'Hand off to dev agent for implementation fixes',
|
||||||
|
action: '*workspace-handoff dev',
|
||||||
|
reasoning: 'Testing/bug work detected, dev collaboration recommended'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Suggest based on progress patterns
|
||||||
|
if (progress.completedTasks > 0) {
|
||||||
|
const recentTasks = progress.taskHistory?.slice(-3) || [];
|
||||||
|
const hasRecentErrors = recentTasks.some(task => task.status === 'error');
|
||||||
|
|
||||||
|
if (hasRecentErrors) {
|
||||||
|
suggestions.push({
|
||||||
|
type: 'maintenance',
|
||||||
|
priority: 'high',
|
||||||
|
title: 'Workspace Cleanup Recommended',
|
||||||
|
description: 'Recent errors detected, workspace cleanup may help',
|
||||||
|
action: '*workspace-cleanup',
|
||||||
|
reasoning: 'Error patterns suggest workspace maintenance needed'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Suggest based on decision patterns
|
||||||
|
if (decisions.length > 10) {
|
||||||
|
const recentDecisions = decisions.slice(-5);
|
||||||
|
const hasArchitecturalDecisions = recentDecisions.some(d =>
|
||||||
|
d.title.includes('architecture') || d.title.includes('design')
|
||||||
|
);
|
||||||
|
|
||||||
|
if (hasArchitecturalDecisions) {
|
||||||
|
suggestions.push({
|
||||||
|
type: 'collaboration',
|
||||||
|
priority: 'medium',
|
||||||
|
title: 'Architect Review Recommended',
|
||||||
|
description: 'Recent architectural decisions may benefit from architect review',
|
||||||
|
action: '*workspace-handoff architect',
|
||||||
|
reasoning: 'Complex architectural decisions detected'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Suggest based on workspace health
|
||||||
|
const workspaceHealth = await this.checkWorkspaceHealth();
|
||||||
|
if (workspaceHealth.issues > 0) {
|
||||||
|
suggestions.push({
|
||||||
|
type: 'maintenance',
|
||||||
|
priority: workspaceHealth.issues > 3 ? 'high' : 'medium',
|
||||||
|
title: 'Workspace Maintenance Needed',
|
||||||
|
description: `${workspaceHealth.issues} workspace issues detected`,
|
||||||
|
action: '*workspace-cleanup',
|
||||||
|
reasoning: 'Workspace health issues detected'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return suggestions.sort((a, b) => {
|
||||||
|
const priorityOrder = { 'high': 3, 'medium': 2, 'low': 1 };
|
||||||
|
return priorityOrder[b.priority] - priorityOrder[a.priority];
|
||||||
|
});
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.warn('Failed to generate intelligent suggestions:', error.message);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detect when work is ready for agent handoff
|
||||||
|
*/
|
||||||
|
async detectHandoffOpportunities() {
|
||||||
|
try {
|
||||||
|
const opportunities = [];
|
||||||
|
|
||||||
|
// Analyze current work state
|
||||||
|
const progress = await this.contextManager.getProgress();
|
||||||
|
const sharedContext = await this.contextManager.getSharedContext();
|
||||||
|
|
||||||
|
// Development completion patterns
|
||||||
|
if (this.activeAgent === 'dev') {
|
||||||
|
const devIndicators = [
|
||||||
|
'implementation complete',
|
||||||
|
'all tests passing',
|
||||||
|
'ready for review',
|
||||||
|
'feature complete'
|
||||||
|
];
|
||||||
|
|
||||||
|
const contextText = sharedContext.sessionNotes?.toLowerCase() || '';
|
||||||
|
const hasCompletionIndicator = devIndicators.some(indicator =>
|
||||||
|
contextText.includes(indicator)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (hasCompletionIndicator) {
|
||||||
|
opportunities.push({
|
||||||
|
targetAgent: 'qa',
|
||||||
|
confidence: 0.85,
|
||||||
|
reason: 'Development work appears complete, ready for QA review',
|
||||||
|
suggestedAction: 'Quality validation and testing',
|
||||||
|
context: {
|
||||||
|
completionIndicators: devIndicators.filter(i => contextText.includes(i))
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for architectural questions
|
||||||
|
const architecturalKeywords = ['architecture', 'design pattern', 'structure', 'framework'];
|
||||||
|
const hasArchitecturalQuestions = architecturalKeywords.some(keyword =>
|
||||||
|
contextText.includes(keyword)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (hasArchitecturalQuestions) {
|
||||||
|
opportunities.push({
|
||||||
|
targetAgent: 'architect',
|
||||||
|
confidence: 0.70,
|
||||||
|
reason: 'Architectural decisions or questions detected',
|
||||||
|
suggestedAction: 'Architectural guidance and design review',
|
||||||
|
context: {
|
||||||
|
architecturalIndicators: architecturalKeywords.filter(k => contextText.includes(k))
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// QA completion patterns
|
||||||
|
if (this.activeAgent === 'qa') {
|
||||||
|
const qaIndicators = [
|
||||||
|
'tests passing',
|
||||||
|
'quality approved',
|
||||||
|
'ready for deployment',
|
||||||
|
'validation complete'
|
||||||
|
];
|
||||||
|
|
||||||
|
const contextText = sharedContext.sessionNotes?.toLowerCase() || '';
|
||||||
|
const hasQACompletion = qaIndicators.some(indicator =>
|
||||||
|
contextText.includes(indicator)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (hasQACompletion) {
|
||||||
|
opportunities.push({
|
||||||
|
targetAgent: 'sm',
|
||||||
|
confidence: 0.80,
|
||||||
|
reason: 'QA validation complete, ready for story management',
|
||||||
|
suggestedAction: 'Story completion and next story planning',
|
||||||
|
context: {
|
||||||
|
qaIndicators: qaIndicators.filter(i => contextText.includes(i))
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for critical issues requiring dev attention
|
||||||
|
const criticalKeywords = ['critical', 'blocker', 'regression', 'failed'];
|
||||||
|
const hasCriticalIssues = criticalKeywords.some(keyword =>
|
||||||
|
contextText.includes(keyword)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (hasCriticalIssues) {
|
||||||
|
opportunities.push({
|
||||||
|
targetAgent: 'dev',
|
||||||
|
confidence: 0.90,
|
||||||
|
reason: 'Critical issues detected requiring development attention',
|
||||||
|
suggestedAction: 'Issue resolution and bug fixes',
|
||||||
|
context: {
|
||||||
|
criticalIndicators: criticalKeywords.filter(k => contextText.includes(k))
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return opportunities.sort((a, b) => b.confidence - a.confidence);
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.warn('Failed to detect handoff opportunities:', error.message);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create enhanced handoff with Claude Code CLI context
|
||||||
|
*/
|
||||||
|
async createEnhancedHandoff(targetAgent, options = {}) {
|
||||||
|
try {
|
||||||
|
// Generate intelligent context summary
|
||||||
|
const contextSummary = await this.generateContextSummary(targetAgent);
|
||||||
|
|
||||||
|
// Detect handoff opportunities
|
||||||
|
const opportunities = await this.detectHandoffOpportunities();
|
||||||
|
const relevantOpportunity = opportunities.find(opp => opp.targetAgent === targetAgent);
|
||||||
|
|
||||||
|
// Generate smart suggestions for target agent
|
||||||
|
const targetSuggestions = await this.generateTargetAgentSuggestions(targetAgent);
|
||||||
|
|
||||||
|
// Create enhanced handoff package
|
||||||
|
const handoffData = {
|
||||||
|
sourceAgent: this.activeAgent,
|
||||||
|
targetAgent: targetAgent,
|
||||||
|
sessionContext: this.sessionContext,
|
||||||
|
contextSummary: contextSummary,
|
||||||
|
handoffOpportunity: relevantOpportunity,
|
||||||
|
targetSuggestions: targetSuggestions,
|
||||||
|
claudeCodeFeatures: {
|
||||||
|
nativeCommands: true,
|
||||||
|
autoSuggestions: true,
|
||||||
|
contextAware: true,
|
||||||
|
sessionContinuity: true
|
||||||
|
},
|
||||||
|
timestamp: new Date().toISOString()
|
||||||
|
};
|
||||||
|
|
||||||
|
// Use existing handoff manager to create the handoff
|
||||||
|
const handoffResult = await this.handoffManager.createHandoff(
|
||||||
|
this.activeAgent,
|
||||||
|
targetAgent,
|
||||||
|
this.sessionContext.sessionId,
|
||||||
|
handoffData
|
||||||
|
);
|
||||||
|
|
||||||
|
// Update context with handoff information
|
||||||
|
await this.contextManager.updateSharedContext({
|
||||||
|
lastHandoff: {
|
||||||
|
from: this.activeAgent,
|
||||||
|
to: targetAgent,
|
||||||
|
timestamp: handoffData.timestamp,
|
||||||
|
handoffId: handoffResult.handoffId
|
||||||
|
}
|
||||||
|
}, this.sessionContext.sessionId, this.activeAgent);
|
||||||
|
|
||||||
|
return {
|
||||||
|
...handoffResult,
|
||||||
|
enhanced: true,
|
||||||
|
contextSummary: contextSummary.summary,
|
||||||
|
suggestions: targetSuggestions.length
|
||||||
|
};
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to create enhanced handoff:', error.message);
|
||||||
|
return { status: 'failed', error: error.message };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate intelligent context summary for target agent
|
||||||
|
*/
|
||||||
|
async generateContextSummary(targetAgent) {
|
||||||
|
try {
|
||||||
|
const sharedContext = await this.contextManager.getSharedContext();
|
||||||
|
const decisions = await this.contextManager.getDecisions();
|
||||||
|
const progress = await this.contextManager.getProgress();
|
||||||
|
|
||||||
|
const summary = {
|
||||||
|
currentFocus: sharedContext.currentFocus || 'No specific focus defined',
|
||||||
|
keyDecisions: decisions.slice(-3).map(d => ({
|
||||||
|
title: d.title,
|
||||||
|
decision: d.decision,
|
||||||
|
impact: d.impact || 'Not specified'
|
||||||
|
})),
|
||||||
|
progressHighlights: {
|
||||||
|
completedTasks: progress.completedTasks || 0,
|
||||||
|
currentStory: progress.currentStory || 'No active story',
|
||||||
|
qualityScore: progress.qualityScore || 'Not assessed'
|
||||||
|
},
|
||||||
|
nextSteps: this.generateNextSteps(targetAgent, sharedContext, progress),
|
||||||
|
contextualNotes: this.generateContextualNotes(targetAgent, sharedContext, decisions)
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
targetAgent: targetAgent,
|
||||||
|
summary: summary,
|
||||||
|
relevanceScore: this.calculateRelevanceScore(targetAgent, summary),
|
||||||
|
generatedAt: new Date().toISOString()
|
||||||
|
};
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.warn('Failed to generate context summary:', error.message);
|
||||||
|
return {
|
||||||
|
targetAgent: targetAgent,
|
||||||
|
summary: { error: 'Context summary unavailable' },
|
||||||
|
relevanceScore: 0
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate smart suggestions for target agent
|
||||||
|
*/
|
||||||
|
async generateTargetAgentSuggestions(targetAgent) {
|
||||||
|
const suggestions = [];
|
||||||
|
|
||||||
|
switch (targetAgent) {
|
||||||
|
case 'dev':
|
||||||
|
suggestions.push(
|
||||||
|
'Use *develop-story to implement the next story systematically',
|
||||||
|
'Run *reality-audit before marking any work complete',
|
||||||
|
'Use *workspace-status to see current development context'
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'qa':
|
||||||
|
suggestions.push(
|
||||||
|
'Use *reality-audit to perform comprehensive quality validation',
|
||||||
|
'Review handoff context for completed development work',
|
||||||
|
'Use *create-remediation if issues are found'
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'architect':
|
||||||
|
suggestions.push(
|
||||||
|
'Review recent architectural decisions in workspace context',
|
||||||
|
'Consider system design implications of current work',
|
||||||
|
'Use *workspace-sync to get latest project context'
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'sm':
|
||||||
|
suggestions.push(
|
||||||
|
'Use *draft to create the next development story',
|
||||||
|
'Review progress and update project tracking',
|
||||||
|
'Consider story scope and team capacity'
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
suggestions.push(
|
||||||
|
'Use *workspace-status to understand current project state',
|
||||||
|
'Review handoff context for relevant background',
|
||||||
|
'Use *workspace-sync to get latest workspace updates'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return suggestions;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate contextual next steps for target agent
|
||||||
|
*/
|
||||||
|
generateNextSteps(targetAgent, sharedContext, progress) {
|
||||||
|
const nextSteps = [];
|
||||||
|
|
||||||
|
// Add agent-specific next steps based on context
|
||||||
|
if (targetAgent === 'dev' && progress.currentStory) {
|
||||||
|
nextSteps.push(`Continue implementation of: ${progress.currentStory}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (targetAgent === 'qa' && progress.completedTasks > 0) {
|
||||||
|
nextSteps.push('Validate completed development work');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add generic next steps if no specific ones
|
||||||
|
if (nextSteps.length === 0) {
|
||||||
|
nextSteps.push(`Review workspace context and begin ${targetAgent} activities`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return nextSteps;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate contextual notes for target agent
|
||||||
|
*/
|
||||||
|
generateContextualNotes(targetAgent, sharedContext, decisions) {
|
||||||
|
const notes = [];
|
||||||
|
|
||||||
|
// Add relevant decisions for the target agent
|
||||||
|
const relevantDecisions = decisions.filter(d =>
|
||||||
|
this.isDecisionRelevant(d, targetAgent)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (relevantDecisions.length > 0) {
|
||||||
|
notes.push(`${relevantDecisions.length} relevant architectural decisions available`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add context-specific notes
|
||||||
|
if (sharedContext.sessionNotes) {
|
||||||
|
notes.push('Previous session context available');
|
||||||
|
}
|
||||||
|
|
||||||
|
return notes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a decision is relevant to the target agent
|
||||||
|
*/
|
||||||
|
isDecisionRelevant(decision, targetAgent) {
|
||||||
|
const agentKeywords = {
|
||||||
|
'dev': ['implementation', 'code', 'technical', 'development'],
|
||||||
|
'qa': ['quality', 'testing', 'validation', 'standards'],
|
||||||
|
'architect': ['architecture', 'design', 'structure', 'pattern'],
|
||||||
|
'sm': ['scope', 'story', 'planning', 'timeline']
|
||||||
|
};
|
||||||
|
|
||||||
|
const keywords = agentKeywords[targetAgent] || [];
|
||||||
|
const decisionText = `${decision.title} ${decision.decision}`.toLowerCase();
|
||||||
|
|
||||||
|
return keywords.some(keyword => decisionText.includes(keyword));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate relevance score for context summary
|
||||||
|
*/
|
||||||
|
calculateRelevanceScore(targetAgent, summary) {
|
||||||
|
let score = 0.5; // Base score
|
||||||
|
|
||||||
|
// Increase score based on available context
|
||||||
|
if (summary.keyDecisions.length > 0) score += 0.2;
|
||||||
|
if (summary.progressHighlights.completedTasks > 0) score += 0.2;
|
||||||
|
if (summary.currentFocus !== 'No specific focus defined') score += 0.1;
|
||||||
|
|
||||||
|
return Math.min(score, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check workspace health for context-aware suggestions
|
||||||
|
*/
|
||||||
|
async checkWorkspaceHealth() {
|
||||||
|
try {
|
||||||
|
// Simple health check implementation
|
||||||
|
const workspaceDir = path.join(this.workspaceDir, '.workspace');
|
||||||
|
const requiredDirs = ['sessions', 'context', 'handoffs', 'decisions', 'progress'];
|
||||||
|
|
||||||
|
let issues = 0;
|
||||||
|
for (const dir of requiredDirs) {
|
||||||
|
if (!fs.existsSync(path.join(workspaceDir, dir))) {
|
||||||
|
issues++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return { issues, healthy: issues === 0 };
|
||||||
|
} catch (error) {
|
||||||
|
return { issues: 1, healthy: false };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = ClaudeCodeContextIntegration;
|
||||||
|
|
@ -0,0 +1,765 @@
|
||||||
|
const path = require('path');
|
||||||
|
const fs = require('fs');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Claude Code CLI Built-in Maintenance System
|
||||||
|
* Provides automatic workspace repair, optimization, and health monitoring
|
||||||
|
* specifically designed for Claude Code CLI users
|
||||||
|
*/
|
||||||
|
class ClaudeCodeMaintenanceSystem {
|
||||||
|
constructor(workspaceDir) {
|
||||||
|
this.workspaceDir = workspaceDir;
|
||||||
|
this.maintenanceLog = [];
|
||||||
|
this.healthMetrics = {
|
||||||
|
lastCheck: null,
|
||||||
|
overallHealth: 100,
|
||||||
|
issues: [],
|
||||||
|
optimizations: []
|
||||||
|
};
|
||||||
|
this.autoRepairEnabled = true;
|
||||||
|
this.backgroundOptimization = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform comprehensive workspace integrity check on session startup
|
||||||
|
*/
|
||||||
|
async performStartupIntegrityCheck() {
|
||||||
|
console.log('🔍 Performing workspace integrity check...');
|
||||||
|
|
||||||
|
const checkResults = {
|
||||||
|
timestamp: new Date().toISOString(),
|
||||||
|
checks: [],
|
||||||
|
issues: [],
|
||||||
|
repairs: [],
|
||||||
|
optimizations: [],
|
||||||
|
overallStatus: 'healthy'
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Check workspace directory structure
|
||||||
|
await this.checkDirectoryStructure(checkResults);
|
||||||
|
|
||||||
|
// Check file integrity
|
||||||
|
await this.checkFileIntegrity(checkResults);
|
||||||
|
|
||||||
|
// Check session cleanup
|
||||||
|
await this.checkSessionCleanup(checkResults);
|
||||||
|
|
||||||
|
// Check context file sizes
|
||||||
|
await this.checkContextSizes(checkResults);
|
||||||
|
|
||||||
|
// Check handoff integrity
|
||||||
|
await this.checkHandoffIntegrity(checkResults);
|
||||||
|
|
||||||
|
// Auto-repair issues if enabled
|
||||||
|
if (this.autoRepairEnabled && checkResults.issues.length > 0) {
|
||||||
|
await this.performAutoRepair(checkResults);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update health metrics
|
||||||
|
this.updateHealthMetrics(checkResults);
|
||||||
|
|
||||||
|
// Log results
|
||||||
|
this.logMaintenanceActivity('startup-integrity-check', checkResults);
|
||||||
|
|
||||||
|
// Display results to user
|
||||||
|
this.displayIntegrityResults(checkResults);
|
||||||
|
|
||||||
|
return checkResults;
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('❌ Integrity check failed:', error.message);
|
||||||
|
checkResults.overallStatus = 'failed';
|
||||||
|
checkResults.error = error.message;
|
||||||
|
return checkResults;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check and repair workspace directory structure
|
||||||
|
*/
|
||||||
|
async checkDirectoryStructure(results) {
|
||||||
|
const requiredDirs = [
|
||||||
|
'.workspace',
|
||||||
|
'.workspace/sessions',
|
||||||
|
'.workspace/context',
|
||||||
|
'.workspace/handoffs',
|
||||||
|
'.workspace/decisions',
|
||||||
|
'.workspace/progress',
|
||||||
|
'.workspace/quality',
|
||||||
|
'.workspace/archive',
|
||||||
|
'.workspace/versions',
|
||||||
|
'.workspace/locks'
|
||||||
|
];
|
||||||
|
|
||||||
|
for (const dir of requiredDirs) {
|
||||||
|
const dirPath = path.join(this.workspaceDir, dir);
|
||||||
|
const exists = fs.existsSync(dirPath);
|
||||||
|
|
||||||
|
results.checks.push({
|
||||||
|
type: 'directory',
|
||||||
|
path: dir,
|
||||||
|
status: exists ? 'ok' : 'missing',
|
||||||
|
timestamp: new Date().toISOString()
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!exists) {
|
||||||
|
results.issues.push({
|
||||||
|
type: 'missing_directory',
|
||||||
|
path: dir,
|
||||||
|
severity: 'medium',
|
||||||
|
description: `Required directory missing: ${dir}`
|
||||||
|
});
|
||||||
|
|
||||||
|
// Auto-repair: Create missing directory
|
||||||
|
try {
|
||||||
|
fs.mkdirSync(dirPath, { recursive: true });
|
||||||
|
results.repairs.push({
|
||||||
|
type: 'directory_created',
|
||||||
|
path: dir,
|
||||||
|
status: 'success',
|
||||||
|
description: `Created missing directory: ${dir}`
|
||||||
|
});
|
||||||
|
|
||||||
|
// Update check status
|
||||||
|
const checkIndex = results.checks.length - 1;
|
||||||
|
results.checks[checkIndex].status = 'repaired';
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
results.repairs.push({
|
||||||
|
type: 'directory_creation_failed',
|
||||||
|
path: dir,
|
||||||
|
status: 'failed',
|
||||||
|
error: error.message
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check file integrity and corruption
|
||||||
|
*/
|
||||||
|
async checkFileIntegrity(results) {
|
||||||
|
const criticalFiles = [
|
||||||
|
'.workspace/workspace-config.json',
|
||||||
|
'.workspace/context/shared-context.md',
|
||||||
|
'.workspace/decisions/decisions-log.md',
|
||||||
|
'.workspace/progress/progress-summary.md'
|
||||||
|
];
|
||||||
|
|
||||||
|
for (const file of criticalFiles) {
|
||||||
|
const filePath = path.join(this.workspaceDir, file);
|
||||||
|
const exists = fs.existsSync(filePath);
|
||||||
|
|
||||||
|
if (exists) {
|
||||||
|
try {
|
||||||
|
// Check if file is readable and valid
|
||||||
|
const content = fs.readFileSync(filePath, 'utf8');
|
||||||
|
|
||||||
|
// Validate JSON files
|
||||||
|
if (file.endsWith('.json')) {
|
||||||
|
JSON.parse(content);
|
||||||
|
}
|
||||||
|
|
||||||
|
results.checks.push({
|
||||||
|
type: 'file_integrity',
|
||||||
|
path: file,
|
||||||
|
status: 'ok',
|
||||||
|
size: content.length
|
||||||
|
});
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
results.issues.push({
|
||||||
|
type: 'corrupted_file',
|
||||||
|
path: file,
|
||||||
|
severity: 'high',
|
||||||
|
description: `File corrupted or unreadable: ${file}`,
|
||||||
|
error: error.message
|
||||||
|
});
|
||||||
|
|
||||||
|
results.checks.push({
|
||||||
|
type: 'file_integrity',
|
||||||
|
path: file,
|
||||||
|
status: 'corrupted',
|
||||||
|
error: error.message
|
||||||
|
});
|
||||||
|
|
||||||
|
// Auto-repair: Restore from backup or create default
|
||||||
|
await this.repairCorruptedFile(file, results);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Critical file missing
|
||||||
|
results.issues.push({
|
||||||
|
type: 'missing_file',
|
||||||
|
path: file,
|
||||||
|
severity: 'medium',
|
||||||
|
description: `Critical file missing: ${file}`
|
||||||
|
});
|
||||||
|
|
||||||
|
// Auto-repair: Create default file
|
||||||
|
await this.createDefaultFile(file, results);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check and cleanup old sessions
|
||||||
|
*/
|
||||||
|
async checkSessionCleanup(results) {
|
||||||
|
try {
|
||||||
|
const sessionsDir = path.join(this.workspaceDir, '.workspace', 'sessions');
|
||||||
|
|
||||||
|
if (!fs.existsSync(sessionsDir)) return;
|
||||||
|
|
||||||
|
const sessionFiles = fs.readdirSync(sessionsDir).filter(f => f.endsWith('.json'));
|
||||||
|
const cutoffTime = Date.now() - (24 * 60 * 60 * 1000); // 24 hours ago
|
||||||
|
let cleanedSessions = 0;
|
||||||
|
|
||||||
|
for (const sessionFile of sessionFiles) {
|
||||||
|
const sessionPath = path.join(sessionsDir, sessionFile);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const sessionData = JSON.parse(fs.readFileSync(sessionPath, 'utf8'));
|
||||||
|
const lastActivity = new Date(sessionData.lastActivity || sessionData.startTime).getTime();
|
||||||
|
|
||||||
|
if (lastActivity < cutoffTime && sessionData.status !== 'active') {
|
||||||
|
fs.unlinkSync(sessionPath);
|
||||||
|
cleanedSessions++;
|
||||||
|
|
||||||
|
results.optimizations.push({
|
||||||
|
type: 'session_cleanup',
|
||||||
|
file: sessionFile,
|
||||||
|
description: 'Removed old inactive session'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
// Remove corrupted session file
|
||||||
|
fs.unlinkSync(sessionPath);
|
||||||
|
cleanedSessions++;
|
||||||
|
|
||||||
|
results.repairs.push({
|
||||||
|
type: 'corrupted_session_removed',
|
||||||
|
file: sessionFile,
|
||||||
|
status: 'success',
|
||||||
|
description: 'Removed corrupted session file'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
results.checks.push({
|
||||||
|
type: 'session_cleanup',
|
||||||
|
status: 'completed',
|
||||||
|
sessionsProcessed: sessionFiles.length,
|
||||||
|
sessionsCleaned: cleanedSessions
|
||||||
|
});
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
results.checks.push({
|
||||||
|
type: 'session_cleanup',
|
||||||
|
status: 'failed',
|
||||||
|
error: error.message
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check context file sizes and optimize if needed
|
||||||
|
*/
|
||||||
|
async checkContextSizes(results) {
|
||||||
|
const contextFiles = [
|
||||||
|
'.workspace/context/shared-context.md',
|
||||||
|
'.workspace/decisions/decisions-log.md',
|
||||||
|
'.workspace/progress/progress-summary.md'
|
||||||
|
];
|
||||||
|
|
||||||
|
const sizeLimits = {
|
||||||
|
'shared-context.md': 10 * 1024 * 1024, // 10MB
|
||||||
|
'decisions-log.md': 5 * 1024 * 1024, // 5MB
|
||||||
|
'progress-summary.md': 3 * 1024 * 1024 // 3MB
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const file of contextFiles) {
|
||||||
|
const filePath = path.join(this.workspaceDir, file);
|
||||||
|
|
||||||
|
if (fs.existsSync(filePath)) {
|
||||||
|
const stats = fs.statSync(filePath);
|
||||||
|
const fileName = path.basename(file);
|
||||||
|
const sizeLimit = sizeLimits[fileName] || 10 * 1024 * 1024;
|
||||||
|
|
||||||
|
results.checks.push({
|
||||||
|
type: 'file_size',
|
||||||
|
path: file,
|
||||||
|
size: stats.size,
|
||||||
|
sizeLimit: sizeLimit,
|
||||||
|
status: stats.size > sizeLimit ? 'oversized' : 'ok'
|
||||||
|
});
|
||||||
|
|
||||||
|
if (stats.size > sizeLimit) {
|
||||||
|
results.issues.push({
|
||||||
|
type: 'oversized_file',
|
||||||
|
path: file,
|
||||||
|
severity: 'medium',
|
||||||
|
description: `File exceeds size limit: ${this.formatBytes(stats.size)} > ${this.formatBytes(sizeLimit)}`,
|
||||||
|
currentSize: stats.size,
|
||||||
|
sizeLimit: sizeLimit
|
||||||
|
});
|
||||||
|
|
||||||
|
// Auto-optimize: Archive and compress
|
||||||
|
await this.optimizeOversizedFile(file, results);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check handoff file integrity
|
||||||
|
*/
|
||||||
|
async checkHandoffIntegrity(results) {
|
||||||
|
try {
|
||||||
|
const handoffsDir = path.join(this.workspaceDir, '.workspace', 'handoffs');
|
||||||
|
|
||||||
|
if (!fs.existsSync(handoffsDir)) return;
|
||||||
|
|
||||||
|
const handoffFiles = fs.readdirSync(handoffsDir).filter(f => f.endsWith('.json'));
|
||||||
|
let corruptedHandoffs = 0;
|
||||||
|
let expiredHandoffs = 0;
|
||||||
|
|
||||||
|
const expirationTime = Date.now() - (7 * 24 * 60 * 60 * 1000); // 7 days ago
|
||||||
|
|
||||||
|
for (const handoffFile of handoffFiles) {
|
||||||
|
const handoffPath = path.join(handoffsDir, handoffFile);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const handoffData = JSON.parse(fs.readFileSync(handoffPath, 'utf8'));
|
||||||
|
const handoffTime = new Date(handoffData.timestamp).getTime();
|
||||||
|
|
||||||
|
// Check if handoff is expired
|
||||||
|
if (handoffTime < expirationTime) {
|
||||||
|
fs.unlinkSync(handoffPath);
|
||||||
|
expiredHandoffs++;
|
||||||
|
|
||||||
|
results.optimizations.push({
|
||||||
|
type: 'handoff_cleanup',
|
||||||
|
file: handoffFile,
|
||||||
|
description: 'Removed expired handoff'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
// Remove corrupted handoff file
|
||||||
|
fs.unlinkSync(handoffPath);
|
||||||
|
corruptedHandoffs++;
|
||||||
|
|
||||||
|
results.repairs.push({
|
||||||
|
type: 'corrupted_handoff_removed',
|
||||||
|
file: handoffFile,
|
||||||
|
status: 'success',
|
||||||
|
description: 'Removed corrupted handoff file'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
results.checks.push({
|
||||||
|
type: 'handoff_integrity',
|
||||||
|
status: 'completed',
|
||||||
|
handoffsProcessed: handoffFiles.length,
|
||||||
|
corruptedRemoved: corruptedHandoffs,
|
||||||
|
expiredRemoved: expiredHandoffs
|
||||||
|
});
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
results.checks.push({
|
||||||
|
type: 'handoff_integrity',
|
||||||
|
status: 'failed',
|
||||||
|
error: error.message
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform automatic repairs
|
||||||
|
*/
|
||||||
|
async performAutoRepair(results) {
|
||||||
|
console.log(`🔧 Auto-repairing ${results.issues.length} issues...`);
|
||||||
|
|
||||||
|
let repairedCount = 0;
|
||||||
|
|
||||||
|
for (const issue of results.issues) {
|
||||||
|
try {
|
||||||
|
switch (issue.type) {
|
||||||
|
case 'missing_directory':
|
||||||
|
// Already handled in checkDirectoryStructure
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'corrupted_file':
|
||||||
|
await this.repairCorruptedFile(issue.path, results);
|
||||||
|
repairedCount++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'missing_file':
|
||||||
|
await this.createDefaultFile(issue.path, results);
|
||||||
|
repairedCount++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'oversized_file':
|
||||||
|
await this.optimizeOversizedFile(issue.path, results);
|
||||||
|
repairedCount++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
results.repairs.push({
|
||||||
|
type: 'repair_failed',
|
||||||
|
issue: issue.type,
|
||||||
|
path: issue.path,
|
||||||
|
status: 'failed',
|
||||||
|
error: error.message
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (repairedCount > 0) {
|
||||||
|
console.log(`✅ Auto-repaired ${repairedCount} issues`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Repair corrupted file
|
||||||
|
*/
|
||||||
|
async repairCorruptedFile(filePath, results) {
|
||||||
|
const fullPath = path.join(this.workspaceDir, filePath);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Try to restore from backup if available
|
||||||
|
const backupPath = `${fullPath}.backup`;
|
||||||
|
|
||||||
|
if (fs.existsSync(backupPath)) {
|
||||||
|
fs.copyFileSync(backupPath, fullPath);
|
||||||
|
results.repairs.push({
|
||||||
|
type: 'file_restored_from_backup',
|
||||||
|
path: filePath,
|
||||||
|
status: 'success',
|
||||||
|
description: 'Restored file from backup'
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Create default file
|
||||||
|
await this.createDefaultFile(filePath, results);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
results.repairs.push({
|
||||||
|
type: 'file_repair_failed',
|
||||||
|
path: filePath,
|
||||||
|
status: 'failed',
|
||||||
|
error: error.message
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create default file
|
||||||
|
*/
|
||||||
|
async createDefaultFile(filePath, results) {
|
||||||
|
const fullPath = path.join(this.workspaceDir, filePath);
|
||||||
|
const fileName = path.basename(filePath);
|
||||||
|
|
||||||
|
try {
|
||||||
|
let defaultContent = '';
|
||||||
|
|
||||||
|
switch (fileName) {
|
||||||
|
case 'workspace-config.json':
|
||||||
|
defaultContent = JSON.stringify({
|
||||||
|
version: '1.0',
|
||||||
|
created: new Date().toISOString(),
|
||||||
|
structure: ['sessions', 'context', 'handoffs', 'decisions', 'progress', 'quality', 'archive'],
|
||||||
|
settings: {
|
||||||
|
maxContextSize: '10MB',
|
||||||
|
sessionTimeout: '2h',
|
||||||
|
archiveAfter: '30d',
|
||||||
|
maxConcurrentSessions: 5
|
||||||
|
}
|
||||||
|
}, null, 2);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'shared-context.md':
|
||||||
|
defaultContent = `# Workspace Context
|
||||||
|
|
||||||
|
**Last Updated:** ${new Date().toISOString()}
|
||||||
|
**Active Sessions:** None
|
||||||
|
**Primary Agent:** unknown
|
||||||
|
|
||||||
|
## Current Focus
|
||||||
|
No current focus available.
|
||||||
|
|
||||||
|
## Key Decisions
|
||||||
|
- No decisions recorded yet
|
||||||
|
|
||||||
|
## Next Steps
|
||||||
|
- Initialize workspace and begin collaborative development
|
||||||
|
|
||||||
|
## Session Notes
|
||||||
|
No session notes available
|
||||||
|
`;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'decisions-log.md':
|
||||||
|
defaultContent = `# Architectural & Design Decisions
|
||||||
|
|
||||||
|
No decisions recorded yet.
|
||||||
|
`;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'progress-summary.md':
|
||||||
|
defaultContent = `# Development Progress Summary
|
||||||
|
|
||||||
|
**Last Updated:** ${new Date().toISOString()}
|
||||||
|
**Current Story:** No active story
|
||||||
|
**Overall Progress:** 0%
|
||||||
|
|
||||||
|
## Completed Tasks
|
||||||
|
None
|
||||||
|
|
||||||
|
## Active Tasks
|
||||||
|
None
|
||||||
|
|
||||||
|
## Blockers
|
||||||
|
None identified
|
||||||
|
|
||||||
|
## Quality Metrics
|
||||||
|
Not assessed
|
||||||
|
`;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
defaultContent = `# ${fileName}
|
||||||
|
|
||||||
|
Default content created by Claude Code CLI maintenance system.
|
||||||
|
Created: ${new Date().toISOString()}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.writeFileSync(fullPath, defaultContent);
|
||||||
|
|
||||||
|
results.repairs.push({
|
||||||
|
type: 'default_file_created',
|
||||||
|
path: filePath,
|
||||||
|
status: 'success',
|
||||||
|
description: `Created default ${fileName}`
|
||||||
|
});
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
results.repairs.push({
|
||||||
|
type: 'default_file_creation_failed',
|
||||||
|
path: filePath,
|
||||||
|
status: 'failed',
|
||||||
|
error: error.message
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Optimize oversized file
|
||||||
|
*/
|
||||||
|
async optimizeOversizedFile(filePath, results) {
|
||||||
|
const fullPath = path.join(this.workspaceDir, filePath);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Create backup
|
||||||
|
const backupPath = `${fullPath}.backup`;
|
||||||
|
fs.copyFileSync(fullPath, backupPath);
|
||||||
|
|
||||||
|
// Archive old content
|
||||||
|
const archiveDir = path.join(this.workspaceDir, '.workspace', 'archive');
|
||||||
|
if (!fs.existsSync(archiveDir)) {
|
||||||
|
fs.mkdirSync(archiveDir, { recursive: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
const archivePath = path.join(archiveDir, `${path.basename(filePath)}-${Date.now()}.md`);
|
||||||
|
fs.copyFileSync(fullPath, archivePath);
|
||||||
|
|
||||||
|
// Create condensed version
|
||||||
|
const content = fs.readFileSync(fullPath, 'utf8');
|
||||||
|
const condensedContent = this.condenseContent(content, path.basename(filePath));
|
||||||
|
fs.writeFileSync(fullPath, condensedContent);
|
||||||
|
|
||||||
|
results.optimizations.push({
|
||||||
|
type: 'file_optimized',
|
||||||
|
path: filePath,
|
||||||
|
description: 'File archived and condensed',
|
||||||
|
archivePath: archivePath,
|
||||||
|
originalSize: fs.statSync(backupPath).size,
|
||||||
|
newSize: fs.statSync(fullPath).size
|
||||||
|
});
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
results.repairs.push({
|
||||||
|
type: 'file_optimization_failed',
|
||||||
|
path: filePath,
|
||||||
|
status: 'failed',
|
||||||
|
error: error.message
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Condense content for oversized files
|
||||||
|
*/
|
||||||
|
condenseContent(content, fileName) {
|
||||||
|
const timestamp = new Date().toISOString();
|
||||||
|
|
||||||
|
switch (fileName) {
|
||||||
|
case 'shared-context.md':
|
||||||
|
return `# Workspace Context (Condensed)
|
||||||
|
|
||||||
|
**Last Updated:** ${timestamp}
|
||||||
|
**Status:** Condensed due to size optimization
|
||||||
|
**Original Content:** Archived
|
||||||
|
|
||||||
|
## Current Focus
|
||||||
|
Previous context has been archived for size optimization.
|
||||||
|
Use *workspace-sync to reload if needed.
|
||||||
|
|
||||||
|
## Key Decisions
|
||||||
|
Most recent decisions preserved. Older decisions archived.
|
||||||
|
|
||||||
|
## Next Steps
|
||||||
|
- Review archived context if needed
|
||||||
|
- Continue with current development focus
|
||||||
|
|
||||||
|
## Session Notes
|
||||||
|
Content condensed - check archive for full history.
|
||||||
|
`;
|
||||||
|
|
||||||
|
case 'decisions-log.md':
|
||||||
|
// Keep last 10 decisions, archive the rest
|
||||||
|
const lines = content.split('\n');
|
||||||
|
const recentDecisions = lines.slice(-200); // Approximate last 10 decisions
|
||||||
|
return `# Architectural & Design Decisions (Condensed)
|
||||||
|
|
||||||
|
**Condensed:** ${timestamp}
|
||||||
|
**Full History:** Available in archive
|
||||||
|
|
||||||
|
${recentDecisions.join('\n')}
|
||||||
|
|
||||||
|
---
|
||||||
|
*Older decisions archived for size optimization*
|
||||||
|
`;
|
||||||
|
|
||||||
|
case 'progress-summary.md':
|
||||||
|
return `# Development Progress Summary (Condensed)
|
||||||
|
|
||||||
|
**Last Updated:** ${timestamp}
|
||||||
|
**Previous Content:** Archived for size optimization
|
||||||
|
|
||||||
|
## Current Status
|
||||||
|
Progress history has been archived.
|
||||||
|
Current session progress will be tracked from this point.
|
||||||
|
|
||||||
|
## Recent Activity
|
||||||
|
Previous activity archived - new tracking begins now.
|
||||||
|
|
||||||
|
## Quality Metrics
|
||||||
|
Historical metrics archived - current assessment required.
|
||||||
|
`;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return `# ${fileName} (Condensed)
|
||||||
|
|
||||||
|
**Condensed:** ${timestamp}
|
||||||
|
**Reason:** File size optimization
|
||||||
|
|
||||||
|
Previous content has been archived.
|
||||||
|
New content will be tracked from this point forward.
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update health metrics
|
||||||
|
*/
|
||||||
|
updateHealthMetrics(checkResults) {
|
||||||
|
this.healthMetrics.lastCheck = checkResults.timestamp;
|
||||||
|
this.healthMetrics.issues = checkResults.issues;
|
||||||
|
this.healthMetrics.optimizations = checkResults.optimizations;
|
||||||
|
|
||||||
|
// Calculate overall health score
|
||||||
|
const issueCount = checkResults.issues.length;
|
||||||
|
const repairCount = checkResults.repairs.filter(r => r.status === 'success').length;
|
||||||
|
|
||||||
|
if (issueCount === 0) {
|
||||||
|
this.healthMetrics.overallHealth = 100;
|
||||||
|
} else if (repairCount >= issueCount) {
|
||||||
|
this.healthMetrics.overallHealth = 90; // Issues but all repaired
|
||||||
|
} else {
|
||||||
|
this.healthMetrics.overallHealth = Math.max(50, 100 - (issueCount * 10));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Log maintenance activity
|
||||||
|
*/
|
||||||
|
logMaintenanceActivity(type, data) {
|
||||||
|
this.maintenanceLog.push({
|
||||||
|
type: type,
|
||||||
|
timestamp: new Date().toISOString(),
|
||||||
|
data: data
|
||||||
|
});
|
||||||
|
|
||||||
|
// Keep only last 100 log entries
|
||||||
|
if (this.maintenanceLog.length > 100) {
|
||||||
|
this.maintenanceLog = this.maintenanceLog.slice(-100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display integrity check results
|
||||||
|
*/
|
||||||
|
displayIntegrityResults(results) {
|
||||||
|
if (results.issues.length === 0 && results.optimizations.length === 0) {
|
||||||
|
console.log('✅ Workspace integrity check passed - all systems healthy');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (results.repairs.length > 0) {
|
||||||
|
const successfulRepairs = results.repairs.filter(r => r.status === 'success').length;
|
||||||
|
console.log(`🔧 Workspace maintenance completed: ${successfulRepairs} issues auto-repaired`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (results.optimizations.length > 0) {
|
||||||
|
console.log(`⚡ Workspace optimized: ${results.optimizations.length} optimizations applied`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show remaining issues if any
|
||||||
|
const unrepairedIssues = results.issues.filter(issue =>
|
||||||
|
!results.repairs.some(repair => repair.path === issue.path && repair.status === 'success')
|
||||||
|
);
|
||||||
|
|
||||||
|
if (unrepairedIssues.length > 0) {
|
||||||
|
console.log(`⚠️ ${unrepairedIssues.length} issues require manual attention`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format bytes for display
|
||||||
|
*/
|
||||||
|
formatBytes(bytes) {
|
||||||
|
if (bytes === 0) return '0 B';
|
||||||
|
const k = 1024;
|
||||||
|
const sizes = ['B', 'KB', 'MB', 'GB'];
|
||||||
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||||
|
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get maintenance summary
|
||||||
|
*/
|
||||||
|
getMaintenanceSummary() {
|
||||||
|
return {
|
||||||
|
healthMetrics: this.healthMetrics,
|
||||||
|
recentActivity: this.maintenanceLog.slice(-10),
|
||||||
|
autoRepairEnabled: this.autoRepairEnabled,
|
||||||
|
backgroundOptimization: this.backgroundOptimization
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = ClaudeCodeMaintenanceSystem;
|
||||||
|
|
@ -0,0 +1,394 @@
|
||||||
|
const path = require('path');
|
||||||
|
const fs = require('fs');
|
||||||
|
const crypto = require('crypto');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Claude Code CLI Session Manager
|
||||||
|
* Provides automatic session management, heartbeat tracking, and context restoration
|
||||||
|
* for Claude Code CLI users of the BMAD collaborative workspace system.
|
||||||
|
*/
|
||||||
|
class ClaudeCodeSessionManager {
|
||||||
|
constructor(workspaceDir) {
|
||||||
|
this.workspaceDir = workspaceDir;
|
||||||
|
this.sessionsDir = path.join(workspaceDir, '.workspace', 'sessions');
|
||||||
|
this.sessionId = null;
|
||||||
|
this.heartbeatInterval = null;
|
||||||
|
this.sessionData = null;
|
||||||
|
this.isClaudeCodeSession = process.env.CLAUDE_CODE_SESSION || false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize Claude Code CLI session with automatic registration
|
||||||
|
*/
|
||||||
|
async initializeSession(agentType = 'dev', projectContext = {}) {
|
||||||
|
try {
|
||||||
|
// Generate unique session ID
|
||||||
|
this.sessionId = `claude-code-${Date.now()}-${crypto.randomBytes(4).toString('hex')}`;
|
||||||
|
|
||||||
|
// Ensure sessions directory exists
|
||||||
|
if (!fs.existsSync(this.sessionsDir)) {
|
||||||
|
fs.mkdirSync(this.sessionsDir, { recursive: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create session data
|
||||||
|
this.sessionData = {
|
||||||
|
sessionId: this.sessionId,
|
||||||
|
agentType: agentType,
|
||||||
|
ide: 'claude-code',
|
||||||
|
startTime: new Date().toISOString(),
|
||||||
|
lastActivity: new Date().toISOString(),
|
||||||
|
status: 'active',
|
||||||
|
projectContext: projectContext,
|
||||||
|
workspaceVersion: '1.0',
|
||||||
|
capabilities: {
|
||||||
|
nativeCommands: true,
|
||||||
|
autoHandoff: true,
|
||||||
|
contextAware: true,
|
||||||
|
autoMaintenance: true
|
||||||
|
},
|
||||||
|
metrics: {
|
||||||
|
commandsExecuted: 0,
|
||||||
|
contextSwitches: 0,
|
||||||
|
handoffsInitiated: 0,
|
||||||
|
handoffsReceived: 0
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Write session file
|
||||||
|
const sessionFile = path.join(this.sessionsDir, `${this.sessionId}.json`);
|
||||||
|
fs.writeFileSync(sessionFile, JSON.stringify(this.sessionData, null, 2));
|
||||||
|
|
||||||
|
// Start heartbeat monitoring
|
||||||
|
this.startHeartbeat();
|
||||||
|
|
||||||
|
// Auto-load workspace context if available
|
||||||
|
await this.loadWorkspaceContext();
|
||||||
|
|
||||||
|
console.log(`🚀 Claude Code CLI session initialized: ${this.sessionId}`);
|
||||||
|
console.log(`📍 Agent: ${agentType} | Project: ${projectContext.name || 'Unknown'}`);
|
||||||
|
|
||||||
|
return {
|
||||||
|
sessionId: this.sessionId,
|
||||||
|
status: 'initialized',
|
||||||
|
capabilities: this.sessionData.capabilities
|
||||||
|
};
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to initialize Claude Code CLI session:', error.message);
|
||||||
|
return { status: 'failed', error: error.message };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start automatic heartbeat monitoring
|
||||||
|
*/
|
||||||
|
startHeartbeat() {
|
||||||
|
// Update heartbeat every 30 seconds
|
||||||
|
this.heartbeatInterval = setInterval(() => {
|
||||||
|
this.updateHeartbeat();
|
||||||
|
}, 30000);
|
||||||
|
|
||||||
|
// Also update on process events
|
||||||
|
process.on('beforeExit', () => this.cleanupSession());
|
||||||
|
process.on('SIGINT', () => this.cleanupSession());
|
||||||
|
process.on('SIGTERM', () => this.cleanupSession());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update session heartbeat
|
||||||
|
*/
|
||||||
|
updateHeartbeat() {
|
||||||
|
if (!this.sessionId || !this.sessionData) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.sessionData.lastActivity = new Date().toISOString();
|
||||||
|
|
||||||
|
const sessionFile = path.join(this.sessionsDir, `${this.sessionId}.json`);
|
||||||
|
if (fs.existsSync(sessionFile)) {
|
||||||
|
fs.writeFileSync(sessionFile, JSON.stringify(this.sessionData, null, 2));
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.warn('Failed to update session heartbeat:', error.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register command execution
|
||||||
|
*/
|
||||||
|
registerCommandExecution(command, context = {}) {
|
||||||
|
if (!this.sessionData) return;
|
||||||
|
|
||||||
|
this.sessionData.metrics.commandsExecuted++;
|
||||||
|
this.sessionData.lastCommand = {
|
||||||
|
command: command,
|
||||||
|
timestamp: new Date().toISOString(),
|
||||||
|
context: context
|
||||||
|
};
|
||||||
|
|
||||||
|
this.updateHeartbeat();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepare agent handoff with context transfer
|
||||||
|
*/
|
||||||
|
async prepareAgentHandoff(targetAgent, handoffContext = {}) {
|
||||||
|
if (!this.sessionData) return null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Increment handoff metrics
|
||||||
|
this.sessionData.metrics.handoffsInitiated++;
|
||||||
|
|
||||||
|
// Load current workspace context
|
||||||
|
const workspaceContext = await this.loadWorkspaceContext();
|
||||||
|
|
||||||
|
// Generate handoff package
|
||||||
|
const handoffData = {
|
||||||
|
sourceSession: this.sessionId,
|
||||||
|
sourceAgent: this.sessionData.agentType,
|
||||||
|
targetAgent: targetAgent,
|
||||||
|
timestamp: new Date().toISOString(),
|
||||||
|
workspaceContext: workspaceContext,
|
||||||
|
sessionContext: {
|
||||||
|
metrics: this.sessionData.metrics,
|
||||||
|
recentCommands: this.sessionData.lastCommand,
|
||||||
|
projectContext: this.sessionData.projectContext
|
||||||
|
},
|
||||||
|
handoffContext: handoffContext,
|
||||||
|
continuity: {
|
||||||
|
sessionId: this.sessionId,
|
||||||
|
resumable: true,
|
||||||
|
contextVersion: workspaceContext?.version || '1.0'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Save handoff package
|
||||||
|
const handoffId = `${this.sessionData.agentType}-to-${targetAgent}-${Date.now()}`;
|
||||||
|
const handoffFile = path.join(this.workspaceDir, '.workspace', 'handoffs', `${handoffId}.json`);
|
||||||
|
|
||||||
|
if (!fs.existsSync(path.dirname(handoffFile))) {
|
||||||
|
fs.mkdirSync(path.dirname(handoffFile), { recursive: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.writeFileSync(handoffFile, JSON.stringify(handoffData, null, 2));
|
||||||
|
|
||||||
|
console.log(`🔄 Handoff prepared: ${this.sessionData.agentType} → ${targetAgent}`);
|
||||||
|
console.log(`📦 Handoff package: ${handoffId}.json`);
|
||||||
|
|
||||||
|
return {
|
||||||
|
handoffId: handoffId,
|
||||||
|
targetAgent: targetAgent,
|
||||||
|
status: 'prepared',
|
||||||
|
contextPreserved: true
|
||||||
|
};
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to prepare agent handoff:', error.message);
|
||||||
|
return { status: 'failed', error: error.message };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Restore session from handoff
|
||||||
|
*/
|
||||||
|
async restoreFromHandoff(handoffId) {
|
||||||
|
try {
|
||||||
|
const handoffFile = path.join(this.workspaceDir, '.workspace', 'handoffs', `${handoffId}.json`);
|
||||||
|
|
||||||
|
if (!fs.existsSync(handoffFile)) {
|
||||||
|
throw new Error(`Handoff package not found: ${handoffId}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const handoffData = JSON.parse(fs.readFileSync(handoffFile, 'utf8'));
|
||||||
|
|
||||||
|
// Update session data with handoff context
|
||||||
|
if (this.sessionData) {
|
||||||
|
this.sessionData.metrics.handoffsReceived++;
|
||||||
|
this.sessionData.restoredFrom = {
|
||||||
|
handoffId: handoffId,
|
||||||
|
sourceAgent: handoffData.sourceAgent,
|
||||||
|
timestamp: new Date().toISOString()
|
||||||
|
};
|
||||||
|
|
||||||
|
// Merge project context
|
||||||
|
this.sessionData.projectContext = {
|
||||||
|
...this.sessionData.projectContext,
|
||||||
|
...handoffData.sessionContext.projectContext
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`♻️ Session restored from handoff: ${handoffData.sourceAgent} → ${this.sessionData?.agentType}`);
|
||||||
|
|
||||||
|
return {
|
||||||
|
status: 'restored',
|
||||||
|
sourceAgent: handoffData.sourceAgent,
|
||||||
|
contextVersion: handoffData.continuity.contextVersion
|
||||||
|
};
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to restore from handoff:', error.message);
|
||||||
|
return { status: 'failed', error: error.message };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load workspace context for session continuity
|
||||||
|
*/
|
||||||
|
async loadWorkspaceContext() {
|
||||||
|
try {
|
||||||
|
const contextFile = path.join(this.workspaceDir, '.workspace', 'context', 'shared-context.md');
|
||||||
|
|
||||||
|
if (fs.existsSync(contextFile)) {
|
||||||
|
const contextContent = fs.readFileSync(contextFile, 'utf8');
|
||||||
|
return {
|
||||||
|
content: contextContent,
|
||||||
|
lastModified: fs.statSync(contextFile).mtime.toISOString(),
|
||||||
|
version: '1.0'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
} catch (error) {
|
||||||
|
console.warn('Failed to load workspace context:', error.message);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get current session status
|
||||||
|
*/
|
||||||
|
getSessionStatus() {
|
||||||
|
if (!this.sessionData) {
|
||||||
|
return { status: 'inactive' };
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
sessionId: this.sessionId,
|
||||||
|
agentType: this.sessionData.agentType,
|
||||||
|
status: this.sessionData.status,
|
||||||
|
startTime: this.sessionData.startTime,
|
||||||
|
lastActivity: this.sessionData.lastActivity,
|
||||||
|
metrics: this.sessionData.metrics,
|
||||||
|
capabilities: this.sessionData.capabilities
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform workspace integrity check
|
||||||
|
*/
|
||||||
|
async performIntegrityCheck() {
|
||||||
|
const results = {
|
||||||
|
timestamp: new Date().toISOString(),
|
||||||
|
checks: [],
|
||||||
|
status: 'healthy',
|
||||||
|
issues: []
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Check workspace directory structure
|
||||||
|
const requiredDirs = ['sessions', 'context', 'handoffs', 'decisions', 'progress', 'quality'];
|
||||||
|
const workspaceRoot = path.join(this.workspaceDir, '.workspace');
|
||||||
|
|
||||||
|
for (const dir of requiredDirs) {
|
||||||
|
const dirPath = path.join(workspaceRoot, dir);
|
||||||
|
const exists = fs.existsSync(dirPath);
|
||||||
|
|
||||||
|
results.checks.push({
|
||||||
|
type: 'directory',
|
||||||
|
path: dir,
|
||||||
|
status: exists ? 'ok' : 'missing'
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!exists) {
|
||||||
|
results.issues.push(`Missing directory: .workspace/${dir}`);
|
||||||
|
fs.mkdirSync(dirPath, { recursive: true });
|
||||||
|
results.checks[results.checks.length - 1].status = 'repaired';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check session file integrity
|
||||||
|
if (this.sessionId) {
|
||||||
|
const sessionFile = path.join(this.sessionsDir, `${this.sessionId}.json`);
|
||||||
|
const sessionExists = fs.existsSync(sessionFile);
|
||||||
|
|
||||||
|
results.checks.push({
|
||||||
|
type: 'session',
|
||||||
|
sessionId: this.sessionId,
|
||||||
|
status: sessionExists ? 'ok' : 'corrupted'
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!sessionExists && this.sessionData) {
|
||||||
|
fs.writeFileSync(sessionFile, JSON.stringify(this.sessionData, null, 2));
|
||||||
|
results.checks[results.checks.length - 1].status = 'repaired';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for orphaned sessions (older than 2 hours with no activity)
|
||||||
|
if (fs.existsSync(this.sessionsDir)) {
|
||||||
|
const sessionFiles = fs.readdirSync(this.sessionsDir).filter(f => f.endsWith('.json'));
|
||||||
|
const cutoffTime = Date.now() - (2 * 60 * 60 * 1000); // 2 hours ago
|
||||||
|
|
||||||
|
for (const sessionFile of sessionFiles) {
|
||||||
|
const sessionPath = path.join(this.sessionsDir, sessionFile);
|
||||||
|
try {
|
||||||
|
const sessionData = JSON.parse(fs.readFileSync(sessionPath, 'utf8'));
|
||||||
|
const lastActivity = new Date(sessionData.lastActivity).getTime();
|
||||||
|
|
||||||
|
if (lastActivity < cutoffTime) {
|
||||||
|
results.issues.push(`Orphaned session: ${sessionData.sessionId}`);
|
||||||
|
fs.unlinkSync(sessionPath);
|
||||||
|
results.checks.push({
|
||||||
|
type: 'cleanup',
|
||||||
|
sessionId: sessionData.sessionId,
|
||||||
|
status: 'removed'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
results.issues.push(`Corrupted session file: ${sessionFile}`);
|
||||||
|
fs.unlinkSync(sessionPath);
|
||||||
|
results.checks.push({
|
||||||
|
type: 'cleanup',
|
||||||
|
file: sessionFile,
|
||||||
|
status: 'removed'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
results.status = results.issues.length === 0 ? 'healthy' : 'repaired';
|
||||||
|
|
||||||
|
return results;
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
results.status = 'failed';
|
||||||
|
results.error = error.message;
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clean up session on exit
|
||||||
|
*/
|
||||||
|
cleanupSession() {
|
||||||
|
if (this.heartbeatInterval) {
|
||||||
|
clearInterval(this.heartbeatInterval);
|
||||||
|
this.heartbeatInterval = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.sessionId && this.sessionData) {
|
||||||
|
try {
|
||||||
|
// Mark session as completed
|
||||||
|
this.sessionData.status = 'completed';
|
||||||
|
this.sessionData.endTime = new Date().toISOString();
|
||||||
|
|
||||||
|
const sessionFile = path.join(this.sessionsDir, `${this.sessionId}.json`);
|
||||||
|
fs.writeFileSync(sessionFile, JSON.stringify(this.sessionData, null, 2));
|
||||||
|
|
||||||
|
console.log(`📝 Claude Code CLI session completed: ${this.sessionId}`);
|
||||||
|
} catch (error) {
|
||||||
|
console.warn('Failed to cleanup session:', error.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = ClaudeCodeSessionManager;
|
||||||
|
|
@ -0,0 +1,565 @@
|
||||||
|
const ClaudeCodeContextIntegration = require('./claude-code-context-integration');
|
||||||
|
const path = require('path');
|
||||||
|
const fs = require('fs');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Claude Code CLI Enhanced User Experience Features
|
||||||
|
* Provides intelligent suggestions, analytics, and seamless workflow integration
|
||||||
|
*/
|
||||||
|
class ClaudeCodeUXEnhancements {
|
||||||
|
constructor(workspaceDir) {
|
||||||
|
this.workspaceDir = workspaceDir;
|
||||||
|
this.contextIntegration = new ClaudeCodeContextIntegration(workspaceDir);
|
||||||
|
this.usageAnalytics = {
|
||||||
|
sessionsStarted: 0,
|
||||||
|
commandsExecuted: 0,
|
||||||
|
handoffsCompleted: 0,
|
||||||
|
averageSessionDuration: 0,
|
||||||
|
mostUsedCommands: {},
|
||||||
|
productivityMetrics: {}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize UX enhancements for Claude Code CLI session
|
||||||
|
*/
|
||||||
|
async initializeUXEnhancements(sessionId, agentType) {
|
||||||
|
try {
|
||||||
|
// Initialize context-aware features
|
||||||
|
await this.contextIntegration.initializeContextAware(agentType, sessionId);
|
||||||
|
|
||||||
|
// Load previous analytics
|
||||||
|
await this.loadAnalytics();
|
||||||
|
|
||||||
|
// Update session analytics
|
||||||
|
this.usageAnalytics.sessionsStarted++;
|
||||||
|
|
||||||
|
console.log('✨ Enhanced UX features activated');
|
||||||
|
console.log(' • Intelligent workspace suggestions enabled');
|
||||||
|
console.log(' • Context-aware command recommendations active');
|
||||||
|
console.log(' • Productivity analytics tracking started');
|
||||||
|
|
||||||
|
return {
|
||||||
|
status: 'initialized',
|
||||||
|
features: {
|
||||||
|
intelligentSuggestions: true,
|
||||||
|
contextAware: true,
|
||||||
|
productivityAnalytics: true,
|
||||||
|
seamlessIntegration: true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.warn('Failed to initialize UX enhancements:', error.message);
|
||||||
|
return { status: 'partial', error: error.message };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add workspace status indicators to command responses
|
||||||
|
*/
|
||||||
|
addWorkspaceStatusIndicators(commandResponse, commandName) {
|
||||||
|
try {
|
||||||
|
const indicators = [];
|
||||||
|
|
||||||
|
// Add session status indicator
|
||||||
|
indicators.push('🚀 Claude Code CLI Enhanced Session Active');
|
||||||
|
|
||||||
|
// Add context awareness indicator
|
||||||
|
if (this.contextIntegration.sessionContext) {
|
||||||
|
indicators.push(`🧠 Context-Aware (${this.contextIntegration.activeAgent})`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add recent activity indicator
|
||||||
|
const recentCommands = this.getRecentCommandHistory();
|
||||||
|
if (recentCommands.length > 0) {
|
||||||
|
indicators.push(`📊 ${recentCommands.length} recent commands tracked`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add collaboration indicator
|
||||||
|
const collaborationStatus = this.getCollaborationStatus();
|
||||||
|
if (collaborationStatus.activeCollaborators > 0) {
|
||||||
|
indicators.push(`👥 ${collaborationStatus.activeCollaborators} active collaborators`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Format indicators
|
||||||
|
const statusBar = indicators.join(' • ');
|
||||||
|
|
||||||
|
// Add to response
|
||||||
|
const enhancedResponse = {
|
||||||
|
originalResponse: commandResponse,
|
||||||
|
statusIndicators: statusBar,
|
||||||
|
timestamp: new Date().toISOString(),
|
||||||
|
enhanced: true
|
||||||
|
};
|
||||||
|
|
||||||
|
// Track command execution
|
||||||
|
this.trackCommandExecution(commandName);
|
||||||
|
|
||||||
|
return enhancedResponse;
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.warn('Failed to add status indicators:', error.message);
|
||||||
|
return commandResponse;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate intelligent workspace suggestions
|
||||||
|
*/
|
||||||
|
async generateIntelligentSuggestions() {
|
||||||
|
try {
|
||||||
|
console.log('🔮 Generating intelligent workspace suggestions...');
|
||||||
|
|
||||||
|
// Get suggestions from context integration
|
||||||
|
const contextSuggestions = await this.contextIntegration.generateIntelligentSuggestions();
|
||||||
|
|
||||||
|
// Add productivity-based suggestions
|
||||||
|
const productivitySuggestions = await this.generateProductivitySuggestions();
|
||||||
|
|
||||||
|
// Add workflow optimization suggestions
|
||||||
|
const workflowSuggestions = await this.generateWorkflowSuggestions();
|
||||||
|
|
||||||
|
// Combine and prioritize suggestions
|
||||||
|
const allSuggestions = [
|
||||||
|
...contextSuggestions,
|
||||||
|
...productivitySuggestions,
|
||||||
|
...workflowSuggestions
|
||||||
|
].sort((a, b) => {
|
||||||
|
const priorityOrder = { 'high': 3, 'medium': 2, 'low': 1 };
|
||||||
|
return priorityOrder[b.priority] - priorityOrder[a.priority];
|
||||||
|
});
|
||||||
|
|
||||||
|
// Display suggestions
|
||||||
|
if (allSuggestions.length > 0) {
|
||||||
|
console.log('');
|
||||||
|
console.log('💡 Intelligent Workspace Suggestions:');
|
||||||
|
console.log('═'.repeat(50));
|
||||||
|
|
||||||
|
allSuggestions.slice(0, 5).forEach((suggestion, index) => {
|
||||||
|
const priorityIcon = {
|
||||||
|
'high': '🔥',
|
||||||
|
'medium': '⚡',
|
||||||
|
'low': '💭'
|
||||||
|
}[suggestion.priority];
|
||||||
|
|
||||||
|
console.log(`${index + 1}. ${priorityIcon} ${suggestion.title}`);
|
||||||
|
console.log(` ${suggestion.description}`);
|
||||||
|
if (suggestion.action) {
|
||||||
|
console.log(` 💻 Try: ${suggestion.action}`);
|
||||||
|
}
|
||||||
|
console.log(` 📝 Why: ${suggestion.reasoning}`);
|
||||||
|
console.log('');
|
||||||
|
});
|
||||||
|
|
||||||
|
if (allSuggestions.length > 5) {
|
||||||
|
console.log(` 📋 ${allSuggestions.length - 5} more suggestions available`);
|
||||||
|
console.log(' Use *workspace-status detailed for full list');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log('💡 No specific suggestions at this time - workspace is optimized!');
|
||||||
|
}
|
||||||
|
|
||||||
|
return allSuggestions;
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.warn('Failed to generate intelligent suggestions:', error.message);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate productivity-based suggestions
|
||||||
|
*/
|
||||||
|
async generateProductivitySuggestions() {
|
||||||
|
const suggestions = [];
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Analyze command usage patterns
|
||||||
|
const commandStats = this.analyzeCommandUsage();
|
||||||
|
|
||||||
|
// Suggest frequently used commands
|
||||||
|
if (commandStats.mostUsed.length > 0) {
|
||||||
|
const topCommand = commandStats.mostUsed[0];
|
||||||
|
|
||||||
|
if (topCommand.count > 5) {
|
||||||
|
suggestions.push({
|
||||||
|
type: 'productivity',
|
||||||
|
priority: 'medium',
|
||||||
|
title: 'Command Usage Pattern Detected',
|
||||||
|
description: `You frequently use *${topCommand.command} - consider workflow optimization`,
|
||||||
|
reasoning: `Used ${topCommand.count} times in recent sessions`,
|
||||||
|
context: { commandStats: topCommand }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Analyze session duration patterns
|
||||||
|
const sessionStats = this.analyzeSessionPatterns();
|
||||||
|
|
||||||
|
if (sessionStats.averageDuration > 60) { // More than 1 hour
|
||||||
|
suggestions.push({
|
||||||
|
type: 'productivity',
|
||||||
|
priority: 'low',
|
||||||
|
title: 'Long Session Detected',
|
||||||
|
description: 'Consider taking breaks or using *workspace-handoff for collaboration',
|
||||||
|
action: '*workspace-status',
|
||||||
|
reasoning: `Average session: ${Math.round(sessionStats.averageDuration)} minutes`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Suggest workspace cleanup based on activity
|
||||||
|
if (this.usageAnalytics.commandsExecuted > 50) {
|
||||||
|
suggestions.push({
|
||||||
|
type: 'maintenance',
|
||||||
|
priority: 'medium',
|
||||||
|
title: 'Workspace Maintenance Recommended',
|
||||||
|
description: 'High activity detected - workspace cleanup may improve performance',
|
||||||
|
action: '*workspace-cleanup',
|
||||||
|
reasoning: `${this.usageAnalytics.commandsExecuted} commands executed`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.warn('Failed to generate productivity suggestions:', error.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
return suggestions;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate workflow optimization suggestions
|
||||||
|
*/
|
||||||
|
async generateWorkflowSuggestions() {
|
||||||
|
const suggestions = [];
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Analyze handoff patterns
|
||||||
|
const handoffPatterns = this.analyzeHandoffPatterns();
|
||||||
|
|
||||||
|
if (handoffPatterns.frequentTransitions.length > 0) {
|
||||||
|
const topTransition = handoffPatterns.frequentTransitions[0];
|
||||||
|
|
||||||
|
suggestions.push({
|
||||||
|
type: 'workflow',
|
||||||
|
priority: 'medium',
|
||||||
|
title: 'Workflow Pattern Optimization',
|
||||||
|
description: `Frequent ${topTransition.from} → ${topTransition.to} transitions detected`,
|
||||||
|
action: `*workspace-handoff ${topTransition.to}`,
|
||||||
|
reasoning: `${topTransition.count} transitions in recent sessions`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Suggest collaboration opportunities
|
||||||
|
const collaborationOpportunities = await this.contextIntegration.detectHandoffOpportunities();
|
||||||
|
|
||||||
|
if (collaborationOpportunities.length > 0) {
|
||||||
|
const topOpportunity = collaborationOpportunities[0];
|
||||||
|
|
||||||
|
suggestions.push({
|
||||||
|
type: 'collaboration',
|
||||||
|
priority: 'high',
|
||||||
|
title: 'Collaboration Opportunity Detected',
|
||||||
|
description: topOpportunity.reason,
|
||||||
|
action: `*workspace-handoff ${topOpportunity.targetAgent}`,
|
||||||
|
reasoning: `Confidence: ${Math.round(topOpportunity.confidence * 100)}%`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.warn('Failed to generate workflow suggestions:', error.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
return suggestions;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build workspace usage analytics and insights
|
||||||
|
*/
|
||||||
|
async buildUsageAnalytics() {
|
||||||
|
try {
|
||||||
|
console.log('📊 Workspace Usage Analytics & Insights');
|
||||||
|
console.log('═'.repeat(50));
|
||||||
|
|
||||||
|
// Session Analytics
|
||||||
|
console.log('🎯 Session Statistics:');
|
||||||
|
console.log(` • Total Sessions: ${this.usageAnalytics.sessionsStarted}`);
|
||||||
|
console.log(` • Commands Executed: ${this.usageAnalytics.commandsExecuted}`);
|
||||||
|
console.log(` • Handoffs Completed: ${this.usageAnalytics.handoffsCompleted}`);
|
||||||
|
|
||||||
|
if (this.usageAnalytics.averageSessionDuration > 0) {
|
||||||
|
console.log(` • Average Session: ${Math.round(this.usageAnalytics.averageSessionDuration)} minutes`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Command Usage Analytics
|
||||||
|
const commandStats = this.analyzeCommandUsage();
|
||||||
|
if (commandStats.mostUsed.length > 0) {
|
||||||
|
console.log('');
|
||||||
|
console.log('⚡ Most Used Commands:');
|
||||||
|
commandStats.mostUsed.slice(0, 5).forEach((cmd, index) => {
|
||||||
|
console.log(` ${index + 1}. *${cmd.command} (${cmd.count} times)`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Productivity Insights
|
||||||
|
const productivityInsights = this.generateProductivityInsights();
|
||||||
|
if (productivityInsights.length > 0) {
|
||||||
|
console.log('');
|
||||||
|
console.log('📈 Productivity Insights:');
|
||||||
|
productivityInsights.forEach((insight, index) => {
|
||||||
|
console.log(` ${index + 1}. ${insight.title}: ${insight.value}`);
|
||||||
|
if (insight.recommendation) {
|
||||||
|
console.log(` 💡 ${insight.recommendation}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Collaboration Analytics
|
||||||
|
const collaborationStats = this.analyzeCollaborationPatterns();
|
||||||
|
if (collaborationStats.totalHandoffs > 0) {
|
||||||
|
console.log('');
|
||||||
|
console.log('🤝 Collaboration Patterns:');
|
||||||
|
console.log(` • Total Handoffs: ${collaborationStats.totalHandoffs}`);
|
||||||
|
console.log(` • Most Common: ${collaborationStats.mostCommonTransition || 'N/A'}`);
|
||||||
|
console.log(` • Collaboration Score: ${collaborationStats.collaborationScore}/100`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Workspace Health Trends
|
||||||
|
const healthTrends = await this.analyzeHealthTrends();
|
||||||
|
if (healthTrends.length > 0) {
|
||||||
|
console.log('');
|
||||||
|
console.log('🏥 Workspace Health Trends:');
|
||||||
|
healthTrends.forEach((trend, index) => {
|
||||||
|
const trendIcon = trend.direction === 'improving' ? '📈' :
|
||||||
|
trend.direction === 'declining' ? '📉' : '➡️';
|
||||||
|
console.log(` ${index + 1}. ${trendIcon} ${trend.metric}: ${trend.status}`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save analytics
|
||||||
|
await this.saveAnalytics();
|
||||||
|
|
||||||
|
return {
|
||||||
|
sessionStats: this.usageAnalytics,
|
||||||
|
commandStats: commandStats,
|
||||||
|
productivityInsights: productivityInsights,
|
||||||
|
collaborationStats: collaborationStats,
|
||||||
|
healthTrends: healthTrends
|
||||||
|
};
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to build usage analytics:', error.message);
|
||||||
|
return { error: error.message };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensure seamless integration with existing Claude Code CLI workflows
|
||||||
|
*/
|
||||||
|
ensureSeamlessIntegration() {
|
||||||
|
try {
|
||||||
|
// Check for existing Claude Code CLI patterns
|
||||||
|
const integrationChecks = {
|
||||||
|
toolIntegration: this.checkToolIntegration(),
|
||||||
|
workflowCompatibility: this.checkWorkflowCompatibility(),
|
||||||
|
performanceImpact: this.checkPerformanceImpact(),
|
||||||
|
userExperience: this.checkUserExperience()
|
||||||
|
};
|
||||||
|
|
||||||
|
let integrationScore = 0;
|
||||||
|
let totalChecks = 0;
|
||||||
|
|
||||||
|
Object.entries(integrationChecks).forEach(([check, result]) => {
|
||||||
|
totalChecks++;
|
||||||
|
if (result.status === 'good') integrationScore++;
|
||||||
|
});
|
||||||
|
|
||||||
|
const integrationPercentage = Math.round((integrationScore / totalChecks) * 100);
|
||||||
|
|
||||||
|
console.log('🔗 Claude Code CLI Integration Status:');
|
||||||
|
console.log(` • Overall Score: ${integrationPercentage}%`);
|
||||||
|
console.log(` • Tool Integration: ${integrationChecks.toolIntegration.status.toUpperCase()}`);
|
||||||
|
console.log(` • Workflow Compatibility: ${integrationChecks.workflowCompatibility.status.toUpperCase()}`);
|
||||||
|
console.log(` • Performance Impact: ${integrationChecks.performanceImpact.status.toUpperCase()}`);
|
||||||
|
console.log(` • User Experience: ${integrationChecks.userExperience.status.toUpperCase()}`);
|
||||||
|
|
||||||
|
if (integrationPercentage < 80) {
|
||||||
|
console.log('');
|
||||||
|
console.log('⚠️ Integration improvements recommended:');
|
||||||
|
Object.entries(integrationChecks).forEach(([check, result]) => {
|
||||||
|
if (result.status !== 'good' && result.recommendation) {
|
||||||
|
console.log(` • ${result.recommendation}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
integrationScore: integrationPercentage,
|
||||||
|
checks: integrationChecks,
|
||||||
|
status: integrationPercentage >= 80 ? 'excellent' :
|
||||||
|
integrationPercentage >= 60 ? 'good' : 'needs_improvement'
|
||||||
|
};
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.warn('Failed to check integration status:', error.message);
|
||||||
|
return { status: 'unknown', error: error.message };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper methods for analytics and integration
|
||||||
|
|
||||||
|
trackCommandExecution(commandName) {
|
||||||
|
this.usageAnalytics.commandsExecuted++;
|
||||||
|
|
||||||
|
if (!this.usageAnalytics.mostUsedCommands[commandName]) {
|
||||||
|
this.usageAnalytics.mostUsedCommands[commandName] = 0;
|
||||||
|
}
|
||||||
|
this.usageAnalytics.mostUsedCommands[commandName]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
analyzeCommandUsage() {
|
||||||
|
const commands = Object.entries(this.usageAnalytics.mostUsedCommands)
|
||||||
|
.map(([command, count]) => ({ command, count }))
|
||||||
|
.sort((a, b) => b.count - a.count);
|
||||||
|
|
||||||
|
return {
|
||||||
|
mostUsed: commands,
|
||||||
|
totalCommands: this.usageAnalytics.commandsExecuted,
|
||||||
|
uniqueCommands: commands.length
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
analyzeSessionPatterns() {
|
||||||
|
return {
|
||||||
|
averageDuration: this.usageAnalytics.averageSessionDuration,
|
||||||
|
totalSessions: this.usageAnalytics.sessionsStarted,
|
||||||
|
commandsPerSession: this.usageAnalytics.sessionsStarted > 0 ?
|
||||||
|
Math.round(this.usageAnalytics.commandsExecuted / this.usageAnalytics.sessionsStarted) : 0
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
analyzeHandoffPatterns() {
|
||||||
|
// Simplified implementation - would analyze actual handoff data
|
||||||
|
return {
|
||||||
|
frequentTransitions: [
|
||||||
|
{ from: 'dev', to: 'qa', count: 5 },
|
||||||
|
{ from: 'qa', to: 'dev', count: 3 }
|
||||||
|
],
|
||||||
|
totalHandoffs: this.usageAnalytics.handoffsCompleted
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
generateProductivityInsights() {
|
||||||
|
const insights = [];
|
||||||
|
|
||||||
|
const commandsPerSession = this.analyzeSessionPatterns().commandsPerSession;
|
||||||
|
if (commandsPerSession > 0) {
|
||||||
|
insights.push({
|
||||||
|
title: 'Commands per Session',
|
||||||
|
value: commandsPerSession,
|
||||||
|
recommendation: commandsPerSession < 5 ?
|
||||||
|
'Consider using more workspace features for better productivity' :
|
||||||
|
commandsPerSession > 20 ?
|
||||||
|
'High activity - consider workflow optimization' :
|
||||||
|
'Good productivity balance'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return insights;
|
||||||
|
}
|
||||||
|
|
||||||
|
analyzeCollaborationPatterns() {
|
||||||
|
return {
|
||||||
|
totalHandoffs: this.usageAnalytics.handoffsCompleted,
|
||||||
|
mostCommonTransition: 'dev → qa',
|
||||||
|
collaborationScore: Math.min(100, this.usageAnalytics.handoffsCompleted * 10)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async analyzeHealthTrends() {
|
||||||
|
// Simplified implementation - would analyze workspace health over time
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
metric: 'Workspace Health',
|
||||||
|
status: 'Stable',
|
||||||
|
direction: 'stable'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
checkToolIntegration() {
|
||||||
|
// Check if workspace commands integrate well with Claude Code CLI tools
|
||||||
|
return {
|
||||||
|
status: 'good',
|
||||||
|
details: 'Workspace commands integrate seamlessly with Claude Code CLI'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
checkWorkflowCompatibility() {
|
||||||
|
// Check if workflows are compatible with existing Claude Code patterns
|
||||||
|
return {
|
||||||
|
status: 'good',
|
||||||
|
details: 'Workflows maintain Claude Code CLI conventions'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
checkPerformanceImpact() {
|
||||||
|
// Check performance impact of enhancements
|
||||||
|
return {
|
||||||
|
status: 'good',
|
||||||
|
details: 'Minimal performance impact detected'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
checkUserExperience() {
|
||||||
|
// Check overall user experience improvements
|
||||||
|
return {
|
||||||
|
status: 'good',
|
||||||
|
details: 'Enhanced features improve productivity without complexity'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
getRecentCommandHistory() {
|
||||||
|
// Simplified implementation
|
||||||
|
return Object.entries(this.usageAnalytics.mostUsedCommands)
|
||||||
|
.slice(0, 5)
|
||||||
|
.map(([command, count]) => ({ command, count }));
|
||||||
|
}
|
||||||
|
|
||||||
|
getCollaborationStatus() {
|
||||||
|
return {
|
||||||
|
activeCollaborators: 0, // Would check actual active sessions
|
||||||
|
recentHandoffs: this.usageAnalytics.handoffsCompleted
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async loadAnalytics() {
|
||||||
|
try {
|
||||||
|
const analyticsFile = path.join(this.workspaceDir, '.workspace', 'analytics.json');
|
||||||
|
|
||||||
|
if (fs.existsSync(analyticsFile)) {
|
||||||
|
const data = JSON.parse(fs.readFileSync(analyticsFile, 'utf8'));
|
||||||
|
this.usageAnalytics = { ...this.usageAnalytics, ...data };
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
// Use default analytics if loading fails
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async saveAnalytics() {
|
||||||
|
try {
|
||||||
|
const analyticsFile = path.join(this.workspaceDir, '.workspace', 'analytics.json');
|
||||||
|
const analyticsDir = path.dirname(analyticsFile);
|
||||||
|
|
||||||
|
if (!fs.existsSync(analyticsDir)) {
|
||||||
|
fs.mkdirSync(analyticsDir, { recursive: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.writeFileSync(analyticsFile, JSON.stringify(this.usageAnalytics, null, 2));
|
||||||
|
} catch (error) {
|
||||||
|
console.warn('Failed to save analytics:', error.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = ClaudeCodeUXEnhancements;
|
||||||
|
|
@ -0,0 +1,503 @@
|
||||||
|
const ClaudeCodeSessionManager = require('./claude-code-session-manager');
|
||||||
|
const path = require('path');
|
||||||
|
const fs = require('fs');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Claude Code CLI Native Workspace Commands
|
||||||
|
* Provides seamless integration of workspace functionality within Claude Code CLI sessions
|
||||||
|
*/
|
||||||
|
class ClaudeCodeWorkspaceCommands {
|
||||||
|
constructor(workspaceDir) {
|
||||||
|
this.workspaceDir = workspaceDir;
|
||||||
|
this.sessionManager = new ClaudeCodeSessionManager(workspaceDir);
|
||||||
|
this.commandHistory = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize workspace and start session
|
||||||
|
*/
|
||||||
|
async workspaceInit(agentType = 'dev', options = {}) {
|
||||||
|
const startTime = Date.now();
|
||||||
|
|
||||||
|
try {
|
||||||
|
console.log('🚀 Initializing Claude Code CLI collaborative workspace...');
|
||||||
|
|
||||||
|
// Detect project context
|
||||||
|
const projectContext = await this.detectProjectContext();
|
||||||
|
|
||||||
|
// Initialize session
|
||||||
|
const sessionResult = await this.sessionManager.initializeSession(agentType, projectContext);
|
||||||
|
|
||||||
|
if (sessionResult.status === 'failed') {
|
||||||
|
throw new Error(sessionResult.error);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform integrity check
|
||||||
|
const integrityResults = await this.sessionManager.performIntegrityCheck();
|
||||||
|
|
||||||
|
// Load existing workspace context
|
||||||
|
const workspaceContext = await this.sessionManager.loadWorkspaceContext();
|
||||||
|
|
||||||
|
// Register command execution
|
||||||
|
this.sessionManager.registerCommandExecution('workspace-init', {
|
||||||
|
agentType: agentType,
|
||||||
|
options: options,
|
||||||
|
projectContext: projectContext
|
||||||
|
});
|
||||||
|
|
||||||
|
const duration = Date.now() - startTime;
|
||||||
|
|
||||||
|
console.log('✅ Workspace initialization complete!');
|
||||||
|
console.log(`⏱️ Completed in ${duration}ms`);
|
||||||
|
console.log('');
|
||||||
|
console.log('📋 Session Details:');
|
||||||
|
console.log(` • Session ID: ${sessionResult.sessionId}`);
|
||||||
|
console.log(` • Agent Type: ${agentType}`);
|
||||||
|
console.log(` • Project: ${projectContext.name || 'Unknown'}`);
|
||||||
|
console.log(` • Capabilities: Native commands, Auto-handoff, Context-aware`);
|
||||||
|
console.log('');
|
||||||
|
console.log('🎯 Ready for collaborative development!');
|
||||||
|
console.log(' • Use *workspace-status to see current state');
|
||||||
|
console.log(' • Use *workspace-handoff [agent] to transfer context');
|
||||||
|
console.log(' • Workspace operations are now automatic');
|
||||||
|
|
||||||
|
if (workspaceContext) {
|
||||||
|
console.log('♻️ Previous workspace context restored');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (integrityResults.issues.length > 0) {
|
||||||
|
console.log(`🔧 Workspace maintenance: ${integrityResults.issues.length} issues auto-repaired`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
status: 'initialized',
|
||||||
|
sessionId: sessionResult.sessionId,
|
||||||
|
duration: duration,
|
||||||
|
contextRestored: !!workspaceContext,
|
||||||
|
issuesRepaired: integrityResults.issues.length
|
||||||
|
};
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('❌ Workspace initialization failed:', error.message);
|
||||||
|
return { status: 'failed', error: error.message };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show current workspace status
|
||||||
|
*/
|
||||||
|
async workspaceStatus(detailed = false) {
|
||||||
|
try {
|
||||||
|
console.log('📊 Claude Code CLI Workspace Status');
|
||||||
|
console.log('═'.repeat(50));
|
||||||
|
|
||||||
|
// Get session status
|
||||||
|
const sessionStatus = this.sessionManager.getSessionStatus();
|
||||||
|
|
||||||
|
if (sessionStatus.status === 'inactive') {
|
||||||
|
console.log('⚠️ No active workspace session');
|
||||||
|
console.log(' Use *workspace-init to start collaborating');
|
||||||
|
return { status: 'inactive' };
|
||||||
|
}
|
||||||
|
|
||||||
|
// Display session information
|
||||||
|
console.log('🎯 Active Session:');
|
||||||
|
console.log(` • Session ID: ${sessionStatus.sessionId}`);
|
||||||
|
console.log(` • Agent: ${sessionStatus.agentType}`);
|
||||||
|
console.log(` • Status: ${sessionStatus.status}`);
|
||||||
|
console.log(` • Started: ${new Date(sessionStatus.startTime).toLocaleString()}`);
|
||||||
|
console.log(` • Last Activity: ${new Date(sessionStatus.lastActivity).toLocaleString()}`);
|
||||||
|
|
||||||
|
// Display capabilities
|
||||||
|
console.log('');
|
||||||
|
console.log('⚡ Enhanced Capabilities:');
|
||||||
|
const caps = sessionStatus.capabilities || {};
|
||||||
|
console.log(` • Native Commands: ${caps.nativeCommands ? '✅' : '❌'}`);
|
||||||
|
console.log(` • Auto Handoff: ${caps.autoHandoff ? '✅' : '❌'}`);
|
||||||
|
console.log(` • Context Aware: ${caps.contextAware ? '✅' : '❌'}`);
|
||||||
|
console.log(` • Auto Maintenance: ${caps.autoMaintenance ? '✅' : '❌'}`);
|
||||||
|
|
||||||
|
// Display metrics
|
||||||
|
console.log('');
|
||||||
|
console.log('📈 Session Metrics:');
|
||||||
|
const metrics = sessionStatus.metrics || {};
|
||||||
|
console.log(` • Commands Executed: ${metrics.commandsExecuted || 0}`);
|
||||||
|
console.log(` • Context Switches: ${metrics.contextSwitches || 0}`);
|
||||||
|
console.log(` • Handoffs Initiated: ${metrics.handoffsInitiated || 0}`);
|
||||||
|
console.log(` • Handoffs Received: ${metrics.handoffsReceived || 0}`);
|
||||||
|
|
||||||
|
// Check for pending handoffs
|
||||||
|
const pendingHandoffs = await this.checkPendingHandoffs();
|
||||||
|
if (pendingHandoffs.length > 0) {
|
||||||
|
console.log('');
|
||||||
|
console.log('📥 Pending Handoffs:');
|
||||||
|
pendingHandoffs.forEach((handoff, index) => {
|
||||||
|
console.log(` ${index + 1}. ${handoff.sourceAgent} → ${handoff.targetAgent} (${handoff.timestamp})`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check workspace health
|
||||||
|
const healthCheck = await this.sessionManager.performIntegrityCheck();
|
||||||
|
console.log('');
|
||||||
|
console.log(`🏥 Workspace Health: ${healthCheck.status.toUpperCase()}`);
|
||||||
|
if (healthCheck.issues.length > 0) {
|
||||||
|
console.log(` • Issues Found: ${healthCheck.issues.length} (auto-repaired)`);
|
||||||
|
} else {
|
||||||
|
console.log(' • All systems operational');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Detailed information if requested
|
||||||
|
if (detailed) {
|
||||||
|
console.log('');
|
||||||
|
console.log('🔍 Detailed Information:');
|
||||||
|
|
||||||
|
// Show recent workspace activity
|
||||||
|
const recentActivity = await this.getRecentActivity();
|
||||||
|
if (recentActivity.length > 0) {
|
||||||
|
console.log(' Recent Activity:');
|
||||||
|
recentActivity.slice(0, 5).forEach((activity, index) => {
|
||||||
|
console.log(` ${index + 1}. ${activity.type}: ${activity.description} (${activity.timestamp})`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show workspace file sizes
|
||||||
|
const workspaceStats = await this.getWorkspaceStats();
|
||||||
|
console.log(' Workspace Statistics:');
|
||||||
|
console.log(` • Total Files: ${workspaceStats.fileCount}`);
|
||||||
|
console.log(` • Total Size: ${workspaceStats.totalSize}`);
|
||||||
|
console.log(` • Context Size: ${workspaceStats.contextSize}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('');
|
||||||
|
console.log('💡 Available Commands:');
|
||||||
|
console.log(' • *workspace-cleanup - Optimize workspace');
|
||||||
|
console.log(' • *workspace-handoff [agent] - Transfer to agent');
|
||||||
|
console.log(' • *workspace-sync - Sync latest context');
|
||||||
|
|
||||||
|
return {
|
||||||
|
status: 'active',
|
||||||
|
session: sessionStatus,
|
||||||
|
pendingHandoffs: pendingHandoffs.length,
|
||||||
|
health: healthCheck.status
|
||||||
|
};
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('❌ Failed to get workspace status:', error.message);
|
||||||
|
return { status: 'error', error: error.message };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clean up workspace and optimize
|
||||||
|
*/
|
||||||
|
async workspaceCleanup(options = {}) {
|
||||||
|
const startTime = Date.now();
|
||||||
|
|
||||||
|
try {
|
||||||
|
console.log('🧹 Starting workspace cleanup and optimization...');
|
||||||
|
|
||||||
|
let cleanupResults = {
|
||||||
|
filesRemoved: 0,
|
||||||
|
spaceSaved: 0,
|
||||||
|
issuesFixed: 0,
|
||||||
|
optimizations: []
|
||||||
|
};
|
||||||
|
|
||||||
|
// Perform integrity check and auto-repair
|
||||||
|
const integrityResults = await this.sessionManager.performIntegrityCheck();
|
||||||
|
cleanupResults.issuesFixed = integrityResults.issues.length;
|
||||||
|
|
||||||
|
// Clean up old sessions (older than 24 hours)
|
||||||
|
const sessionCleanup = await this.cleanupOldSessions();
|
||||||
|
cleanupResults.filesRemoved += sessionCleanup.filesRemoved;
|
||||||
|
cleanupResults.spaceSaved += sessionCleanup.spaceSaved;
|
||||||
|
|
||||||
|
// Clean up expired handoffs (older than 7 days)
|
||||||
|
const handoffCleanup = await this.cleanupExpiredHandoffs();
|
||||||
|
cleanupResults.filesRemoved += handoffCleanup.filesRemoved;
|
||||||
|
cleanupResults.spaceSaved += handoffCleanup.spaceSaved;
|
||||||
|
|
||||||
|
// Optimize context files (compress if over size limit)
|
||||||
|
const contextOptimization = await this.optimizeContextFiles();
|
||||||
|
cleanupResults.optimizations.push(...contextOptimization.optimizations);
|
||||||
|
cleanupResults.spaceSaved += contextOptimization.spaceSaved;
|
||||||
|
|
||||||
|
// Clean up temporary files
|
||||||
|
const tempCleanup = await this.cleanupTempFiles();
|
||||||
|
cleanupResults.filesRemoved += tempCleanup.filesRemoved;
|
||||||
|
cleanupResults.spaceSaved += tempCleanup.spaceSaved;
|
||||||
|
|
||||||
|
// Register command execution
|
||||||
|
this.sessionManager.registerCommandExecution('workspace-cleanup', {
|
||||||
|
options: options,
|
||||||
|
results: cleanupResults
|
||||||
|
});
|
||||||
|
|
||||||
|
const duration = Date.now() - startTime;
|
||||||
|
|
||||||
|
console.log('✅ Workspace cleanup complete!');
|
||||||
|
console.log(`⏱️ Completed in ${duration}ms`);
|
||||||
|
console.log('');
|
||||||
|
console.log('📊 Cleanup Results:');
|
||||||
|
console.log(` • Files Removed: ${cleanupResults.filesRemoved}`);
|
||||||
|
console.log(` • Space Saved: ${this.formatBytes(cleanupResults.spaceSaved)}`);
|
||||||
|
console.log(` • Issues Fixed: ${cleanupResults.issuesFixed}`);
|
||||||
|
console.log(` • Optimizations: ${cleanupResults.optimizations.length}`);
|
||||||
|
|
||||||
|
if (cleanupResults.optimizations.length > 0) {
|
||||||
|
console.log('');
|
||||||
|
console.log('⚡ Optimizations Applied:');
|
||||||
|
cleanupResults.optimizations.forEach((opt, index) => {
|
||||||
|
console.log(` ${index + 1}. ${opt}`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('');
|
||||||
|
console.log('🎯 Workspace is now optimized for peak performance!');
|
||||||
|
|
||||||
|
return {
|
||||||
|
status: 'completed',
|
||||||
|
duration: duration,
|
||||||
|
results: cleanupResults
|
||||||
|
};
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('❌ Workspace cleanup failed:', error.message);
|
||||||
|
return { status: 'failed', error: error.message };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepare agent handoff
|
||||||
|
*/
|
||||||
|
async workspaceHandoff(targetAgent, handoffContext = {}) {
|
||||||
|
const startTime = Date.now();
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (!targetAgent) {
|
||||||
|
console.log('❌ Target agent required for handoff');
|
||||||
|
console.log('');
|
||||||
|
console.log('💡 Available agents:');
|
||||||
|
console.log(' • dev - Full Stack Developer');
|
||||||
|
console.log(' • qa - QA Engineer & Quality Architect');
|
||||||
|
console.log(' • architect - Software Architect');
|
||||||
|
console.log(' • pm - Product Manager');
|
||||||
|
console.log(' • sm - Scrum Master');
|
||||||
|
return { status: 'invalid', error: 'Target agent required' };
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`🔄 Preparing handoff to ${targetAgent}...`);
|
||||||
|
|
||||||
|
// Prepare handoff package
|
||||||
|
const handoffResult = await this.sessionManager.prepareAgentHandoff(targetAgent, handoffContext);
|
||||||
|
|
||||||
|
if (handoffResult.status === 'failed') {
|
||||||
|
throw new Error(handoffResult.error);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate handoff summary
|
||||||
|
const sessionStatus = this.sessionManager.getSessionStatus();
|
||||||
|
|
||||||
|
const duration = Date.now() - startTime;
|
||||||
|
|
||||||
|
console.log('✅ Handoff package prepared!');
|
||||||
|
console.log(`⏱️ Completed in ${duration}ms`);
|
||||||
|
console.log('');
|
||||||
|
console.log('📦 Handoff Details:');
|
||||||
|
console.log(` • Handoff ID: ${handoffResult.handoffId}`);
|
||||||
|
console.log(` • From: ${sessionStatus.agentType} (Claude Code CLI)`);
|
||||||
|
console.log(` • To: ${targetAgent}`);
|
||||||
|
console.log(` • Context Preserved: ${handoffResult.contextPreserved ? '✅' : '❌'}`);
|
||||||
|
console.log('');
|
||||||
|
console.log('🎯 Ready for agent transition!');
|
||||||
|
console.log(` • The ${targetAgent} agent can now access full context`);
|
||||||
|
console.log(' • All workspace state has been preserved');
|
||||||
|
console.log(' • Session continuity maintained');
|
||||||
|
|
||||||
|
// Register command execution
|
||||||
|
this.sessionManager.registerCommandExecution('workspace-handoff', {
|
||||||
|
targetAgent: targetAgent,
|
||||||
|
handoffId: handoffResult.handoffId,
|
||||||
|
context: handoffContext
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
status: 'prepared',
|
||||||
|
handoffId: handoffResult.handoffId,
|
||||||
|
targetAgent: targetAgent,
|
||||||
|
duration: duration
|
||||||
|
};
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('❌ Handoff preparation failed:', error.message);
|
||||||
|
return { status: 'failed', error: error.message };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Synchronize with latest workspace context
|
||||||
|
*/
|
||||||
|
async workspaceSync(options = {}) {
|
||||||
|
const startTime = Date.now();
|
||||||
|
|
||||||
|
try {
|
||||||
|
console.log('🔄 Synchronizing workspace context...');
|
||||||
|
|
||||||
|
// Load latest workspace context
|
||||||
|
const workspaceContext = await this.sessionManager.loadWorkspaceContext();
|
||||||
|
|
||||||
|
// Check for pending handoffs to this agent
|
||||||
|
const sessionStatus = this.sessionManager.getSessionStatus();
|
||||||
|
const pendingHandoffs = await this.checkPendingHandoffs(sessionStatus.agentType);
|
||||||
|
|
||||||
|
// Process any pending handoffs
|
||||||
|
let handoffsProcessed = 0;
|
||||||
|
for (const handoff of pendingHandoffs) {
|
||||||
|
const restoreResult = await this.sessionManager.restoreFromHandoff(handoff.handoffId);
|
||||||
|
if (restoreResult.status === 'restored') {
|
||||||
|
handoffsProcessed++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update session metrics
|
||||||
|
this.sessionManager.registerCommandExecution('workspace-sync', {
|
||||||
|
options: options,
|
||||||
|
contextLoaded: !!workspaceContext,
|
||||||
|
handoffsProcessed: handoffsProcessed
|
||||||
|
});
|
||||||
|
|
||||||
|
const duration = Date.now() - startTime;
|
||||||
|
|
||||||
|
console.log('✅ Workspace synchronization complete!');
|
||||||
|
console.log(`⏱️ Completed in ${duration}ms`);
|
||||||
|
console.log('');
|
||||||
|
console.log('📊 Sync Results:');
|
||||||
|
console.log(` • Context Updated: ${workspaceContext ? '✅' : '❌'}`);
|
||||||
|
console.log(` • Handoffs Processed: ${handoffsProcessed}`);
|
||||||
|
|
||||||
|
if (workspaceContext) {
|
||||||
|
console.log(` • Context Version: ${workspaceContext.version}`);
|
||||||
|
console.log(` • Last Modified: ${new Date(workspaceContext.lastModified).toLocaleString()}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (handoffsProcessed > 0) {
|
||||||
|
console.log('');
|
||||||
|
console.log('🔄 Context restored from previous agent handoffs');
|
||||||
|
console.log(' • Full development context available');
|
||||||
|
console.log(' • Ready to continue collaborative work');
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('');
|
||||||
|
console.log('🎯 Workspace is now synchronized and ready!');
|
||||||
|
|
||||||
|
return {
|
||||||
|
status: 'synchronized',
|
||||||
|
duration: duration,
|
||||||
|
contextLoaded: !!workspaceContext,
|
||||||
|
handoffsProcessed: handoffsProcessed
|
||||||
|
};
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('❌ Workspace synchronization failed:', error.message);
|
||||||
|
return { status: 'failed', error: error.message };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper methods
|
||||||
|
|
||||||
|
async detectProjectContext() {
|
||||||
|
try {
|
||||||
|
const packageJsonPath = path.join(this.workspaceDir, 'package.json');
|
||||||
|
if (fs.existsSync(packageJsonPath)) {
|
||||||
|
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
||||||
|
return {
|
||||||
|
name: packageJson.name,
|
||||||
|
version: packageJson.version,
|
||||||
|
type: 'nodejs',
|
||||||
|
hasTests: !!packageJson.scripts?.test,
|
||||||
|
hasBuild: !!packageJson.scripts?.build
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for other project types
|
||||||
|
const projectFiles = fs.readdirSync(this.workspaceDir);
|
||||||
|
if (projectFiles.includes('.csproj') || projectFiles.some(f => f.endsWith('.csproj'))) {
|
||||||
|
return { type: 'dotnet', name: path.basename(this.workspaceDir) };
|
||||||
|
}
|
||||||
|
|
||||||
|
return { type: 'unknown', name: path.basename(this.workspaceDir) };
|
||||||
|
} catch (error) {
|
||||||
|
return { type: 'unknown', name: 'project' };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async checkPendingHandoffs(targetAgent = null) {
|
||||||
|
try {
|
||||||
|
const handoffsDir = path.join(this.workspaceDir, '.workspace', 'handoffs');
|
||||||
|
if (!fs.existsSync(handoffsDir)) return [];
|
||||||
|
|
||||||
|
const handoffFiles = fs.readdirSync(handoffsDir).filter(f => f.endsWith('.json'));
|
||||||
|
const pendingHandoffs = [];
|
||||||
|
|
||||||
|
for (const file of handoffFiles) {
|
||||||
|
try {
|
||||||
|
const handoffData = JSON.parse(fs.readFileSync(path.join(handoffsDir, file), 'utf8'));
|
||||||
|
if (!targetAgent || handoffData.targetAgent === targetAgent) {
|
||||||
|
pendingHandoffs.push({
|
||||||
|
handoffId: path.basename(file, '.json'),
|
||||||
|
sourceAgent: handoffData.sourceAgent,
|
||||||
|
targetAgent: handoffData.targetAgent,
|
||||||
|
timestamp: handoffData.timestamp
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
// Skip corrupted handoff files
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return pendingHandoffs;
|
||||||
|
} catch (error) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async cleanupOldSessions() {
|
||||||
|
// Implementation for cleaning up old session files
|
||||||
|
return { filesRemoved: 0, spaceSaved: 0 };
|
||||||
|
}
|
||||||
|
|
||||||
|
async cleanupExpiredHandoffs() {
|
||||||
|
// Implementation for cleaning up expired handoff files
|
||||||
|
return { filesRemoved: 0, spaceSaved: 0 };
|
||||||
|
}
|
||||||
|
|
||||||
|
async optimizeContextFiles() {
|
||||||
|
// Implementation for optimizing context files
|
||||||
|
return { optimizations: [], spaceSaved: 0 };
|
||||||
|
}
|
||||||
|
|
||||||
|
async cleanupTempFiles() {
|
||||||
|
// Implementation for cleaning up temporary files
|
||||||
|
return { filesRemoved: 0, spaceSaved: 0 };
|
||||||
|
}
|
||||||
|
|
||||||
|
async getRecentActivity() {
|
||||||
|
// Implementation for getting recent workspace activity
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
async getWorkspaceStats() {
|
||||||
|
// Implementation for getting workspace statistics
|
||||||
|
return { fileCount: 0, totalSize: '0 B', contextSize: '0 B' };
|
||||||
|
}
|
||||||
|
|
||||||
|
formatBytes(bytes) {
|
||||||
|
if (bytes === 0) return '0 B';
|
||||||
|
const k = 1024;
|
||||||
|
const sizes = ['B', 'KB', 'MB', 'GB'];
|
||||||
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||||
|
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = ClaudeCodeWorkspaceCommands;
|
||||||
|
|
@ -105,6 +105,42 @@ class IdeSetup extends BaseIdeSetup {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create settings.local.json for Claude Code permissions
|
||||||
|
const claudeDir = path.join(installDir, ".claude");
|
||||||
|
const settingsLocalPath = path.join(claudeDir, "settings.local.json");
|
||||||
|
|
||||||
|
// Define necessary permissions for BMAD operations
|
||||||
|
const settingsConfig = {
|
||||||
|
permissions: {
|
||||||
|
allow: [
|
||||||
|
"Bash(npm run validate:*)",
|
||||||
|
"Bash(rm:*)",
|
||||||
|
"Bash(git add:*)",
|
||||||
|
"Bash(mv:*)",
|
||||||
|
"Bash(node:*)",
|
||||||
|
"Bash(npm run install:bmad:*)",
|
||||||
|
"Bash(npm run build:*)",
|
||||||
|
"Bash(npm run format:*)",
|
||||||
|
"Bash(npm run version:*)",
|
||||||
|
"Bash(npm run release:*)",
|
||||||
|
"Bash(npm test:*)",
|
||||||
|
"Bash(npm start:*)",
|
||||||
|
"Bash(grep:*)",
|
||||||
|
"Bash(find:*)",
|
||||||
|
"Bash(workspace-*:*)"
|
||||||
|
],
|
||||||
|
deny: []
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
await fileManager.ensureDirectory(claudeDir);
|
||||||
|
await fileManager.writeFile(settingsLocalPath, JSON.stringify(settingsConfig, null, 2));
|
||||||
|
console.log(chalk.green("✓ Created Claude Code settings.local.json with BMAD permissions"));
|
||||||
|
} catch (error) {
|
||||||
|
console.warn(chalk.yellow("⚠️ Could not create settings.local.json:"), error.message);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ const configLoader = require("./config-loader");
|
||||||
const ideSetup = require("./ide-setup");
|
const ideSetup = require("./ide-setup");
|
||||||
const { extractYamlFromAgent } = require("../../lib/yaml-utils");
|
const { extractYamlFromAgent } = require("../../lib/yaml-utils");
|
||||||
const resourceLocator = require("./resource-locator");
|
const resourceLocator = require("./resource-locator");
|
||||||
|
const WorkspaceSetup = require("./workspace-setup");
|
||||||
|
|
||||||
class Installer {
|
class Installer {
|
||||||
async getCoreVersion() {
|
async getCoreVersion() {
|
||||||
|
|
@ -384,6 +385,35 @@ class Installer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set up Collaborative Workspace System if requested
|
||||||
|
if (config.enableWorkspace) {
|
||||||
|
const workspaceSetup = new WorkspaceSetup();
|
||||||
|
|
||||||
|
spinner.text = 'Setting up Collaborative Workspace System...';
|
||||||
|
|
||||||
|
// Create workspace directory structure
|
||||||
|
const workspaceCreated = await workspaceSetup.createWorkspaceDirectory(installDir, spinner);
|
||||||
|
if (!workspaceCreated) {
|
||||||
|
throw new Error('Failed to create workspace directory structure');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create workspace utilities
|
||||||
|
const utilitiesCreated = await workspaceSetup.createWorkspaceUtilities(installDir, ides, spinner);
|
||||||
|
if (!utilitiesCreated) {
|
||||||
|
throw new Error('Failed to create workspace utilities');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up Claude Code specific commands if Claude Code is selected
|
||||||
|
if (ides.includes('claude-code')) {
|
||||||
|
const claudeCodeSetup = await workspaceSetup.setupClaudeCodeWorkspaceCommands(installDir, spinner);
|
||||||
|
if (!claudeCodeSetup) {
|
||||||
|
console.warn(chalk.yellow('⚠️ Warning: Failed to integrate workspace commands with Claude Code CLI'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
spinner.text = 'Collaborative Workspace System configured successfully';
|
||||||
|
}
|
||||||
|
|
||||||
// Modify core-config.yaml if sharding preferences were provided
|
// Modify core-config.yaml if sharding preferences were provided
|
||||||
if (config.installType !== "expansion-only" && (config.prdSharded !== undefined || config.architectureSharded !== undefined)) {
|
if (config.installType !== "expansion-only" && (config.prdSharded !== undefined || config.architectureSharded !== undefined)) {
|
||||||
spinner.text = "Configuring document sharding settings...";
|
spinner.text = "Configuring document sharding settings...";
|
||||||
|
|
@ -841,6 +871,20 @@ class Installer {
|
||||||
console.log(chalk.green("✓ .bmad-core framework installed with all agents and workflows"));
|
console.log(chalk.green("✓ .bmad-core framework installed with all agents and workflows"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (config.enableWorkspace) {
|
||||||
|
console.log(chalk.green("✓ 🤝 Collaborative Workspace System configured"));
|
||||||
|
console.log(chalk.green(" • .workspace/ directory structure created"));
|
||||||
|
console.log(chalk.green(" • workspace-utils/ scripts installed"));
|
||||||
|
|
||||||
|
if (ides.includes('claude-code')) {
|
||||||
|
console.log(chalk.green(" • Native Claude Code CLI commands integrated"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ides.some(ide => ide !== 'claude-code')) {
|
||||||
|
console.log(chalk.green(" • Cross-IDE utility scripts configured"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (config.expansionPacks && config.expansionPacks.length > 0) {
|
if (config.expansionPacks && config.expansionPacks.length > 0) {
|
||||||
console.log(chalk.green(`✓ Expansion packs installed:`));
|
console.log(chalk.green(`✓ Expansion packs installed:`));
|
||||||
for (const packId of config.expansionPacks) {
|
for (const packId of config.expansionPacks) {
|
||||||
|
|
@ -892,6 +936,29 @@ class Installer {
|
||||||
console.log(chalk.yellow("Since agents have been updated, you need to update any custom agent modes configured in the Cursor custom agent GUI per the Cursor docs."));
|
console.log(chalk.yellow("Since agents have been updated, you need to update any custom agent modes configured in the Cursor custom agent GUI per the Cursor docs."));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Workspace usage guidance
|
||||||
|
if (config.enableWorkspace) {
|
||||||
|
console.log(chalk.bold.cyan("\n🚀 Getting Started with Collaborative Workspace:"));
|
||||||
|
|
||||||
|
if (ides.includes('claude-code')) {
|
||||||
|
console.log(chalk.cyan(" Claude Code CLI Users:"));
|
||||||
|
console.log(chalk.cyan(" • Use *workspace-init to start collaborating"));
|
||||||
|
console.log(chalk.cyan(" • Try *workspace-status to see active sessions"));
|
||||||
|
console.log(chalk.cyan(" • Workspace features work automatically!"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ides.some(ide => ide !== 'claude-code')) {
|
||||||
|
console.log(chalk.cyan(" Other IDE Users:"));
|
||||||
|
console.log(chalk.cyan(" • Run: npm run workspace-init"));
|
||||||
|
console.log(chalk.cyan(" • Check: npm run workspace-status"));
|
||||||
|
console.log(chalk.cyan(" • See: workspace-utils/docs/ for IDE-specific guides"));
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(chalk.cyan("\n 📁 Workspace Files:"));
|
||||||
|
console.log(chalk.cyan(" • .workspace/ - Shared context and collaboration data"));
|
||||||
|
console.log(chalk.cyan(" • workspace-utils/ - Cross-IDE utility scripts"));
|
||||||
|
}
|
||||||
|
|
||||||
// Important notice to read the user guide
|
// Important notice to read the user guide
|
||||||
console.log(chalk.red.bold("\n📖 IMPORTANT: Please read the user guide installed at docs/user-guide.md"));
|
console.log(chalk.red.bold("\n📖 IMPORTANT: Please read the user guide installed at docs/user-guide.md"));
|
||||||
console.log(chalk.red("This guide contains essential information about the BMad workflow and how to use the agents effectively."));
|
console.log(chalk.red("This guide contains essential information about the BMad workflow and how to use the agents effectively."));
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue