development-guide.md•25.5 kB
# EuConquisto Composer MCP - Development Guide
**Document**: Developer Guide for System Enhancement
**Version**: 1.0
**Date**: July 5, 2025
**Status**: Production Ready
**Author**: Claude Code Migration Team
## Table of Contents
1. [Development Environment Setup](#development-environment-setup)
2. [Architecture Overview](#architecture-overview)
3. [Code Organization](#code-organization)
4. [Development Workflow](#development-workflow)
5. [Adding New Features](#adding-new-features)
6. [Testing Guidelines](#testing-guidelines)
7. [Performance Optimization](#performance-optimization)
8. [Deployment Process](#deployment-process)
9. [Code Standards](#code-standards)
10. [Best Practices](#best-practices)
## Development Environment Setup
### Prerequisites
**System Requirements**:
- Node.js 18+ (LTS recommended)
- npm 9+ or yarn 3+
- Git 2.30+
- 8GB+ RAM (16GB recommended)
- 10GB+ free disk space
**Development Tools**:
- VS Code or similar IDE
- Docker (optional, for containerized development)
- Playwright browser dependencies
- TypeScript 5.0+
### Initial Setup
```bash
# Clone repository
git clone https://github.com/your-org/euconquisto-composer-mcp.git
cd euconquisto-composer-mcp
# Install dependencies
npm install
# Install Playwright browsers
npx playwright install
# Set up environment variables
cp .env.example .env
# Edit .env with your configuration
# Build project
npm run build
# Run tests
npm test
# Start development server
npm run dev
```
### Environment Configuration
**`.env` Configuration**:
```bash
# API Configuration
API_BASE_URL=https://composer.digitalpages.com.br/api/v4
COMPOSER_URL=https://composer.digitalpages.com.br
# Authentication
JWT_TOKEN_PATH=./correct-jwt-new.txt
AUTH_REDIRECT_PORT=3000
# Performance Settings
NODE_OPTIONS=--max-old-space-size=4096
MEMORY_WARNING_THRESHOLD=512
MEMORY_CRITICAL_THRESHOLD=1024
# Browser Configuration
BROWSER_HEADLESS=true
BROWSER_TIMEOUT=30000
BROWSER_POOL_MIN=2
BROWSER_POOL_MAX=5
# Development Settings
LOG_LEVEL=debug
ENABLE_PERFORMANCE_MONITORING=true
ENABLE_MEMORY_MONITORING=true
```
### VS Code Configuration
**`.vscode/settings.json`**:
```json
{
"typescript.preferences.importModuleSpecifier": "relative",
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true,
"source.organizeImports": true
},
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"files.exclude": {
"**/node_modules": true,
"**/dist": true,
"**/.git": true
}
}
```
## Architecture Overview
### System Architecture
The system follows a **4-phase content-first architecture**:
```
Phase 1: Infrastructure → Phase 2: Content Generation → Phase 3: Widget Mapping → Phase 4: Integration
```
### Core Principles
1. **Universal Topic Handling**: No pre-mapping required for new subjects
2. **Modular Design**: Each component can be developed and tested independently
3. **Performance First**: Optimization built into every component
4. **Educational Standards**: BNCC compliance and pedagogical best practices
5. **Error Resilience**: Graceful degradation and comprehensive error handling
## Code Organization
### Directory Structure
```
euconquisto-composer-mcp/
├── src/ # Source code
│ ├── infrastructure/ # Phase 1: Core infrastructure
│ │ ├── authentication/ # JWT and auth management
│ │ ├── browser/ # Browser automation
│ │ └── api/ # Composer API integration
│ ├── content-generation/ # Phase 2: Content creation
│ │ ├── base-adapter.ts # Universal content generator
│ │ ├── subject-adapters/ # Subject-specific enhancers
│ │ └── assessment/ # Assessment generation
│ ├── services/ # Phase 3: Widget mapping
│ │ ├── content-widget-mapper.ts
│ │ ├── image-selection-service.ts
│ │ └── educational-flow-optimizer.ts
│ ├── integration/ # Phase 4: System coordination
│ │ ├── main-integration-orchestrator.ts
│ │ └── performance/ # Performance optimization
│ └── types/ # TypeScript type definitions
├── tests/ # Test suites
│ ├── unit/ # Unit tests
│ ├── integration/ # Integration tests
│ ├── comprehensive/ # End-to-end tests
│ └── performance/ # Performance tests
├── docs/ # Documentation
│ ├── technical/ # Technical documentation
│ ├── user/ # User guides
│ └── planning/ # Project planning
├── tools/ # Development tools
│ ├── servers/ # Development servers
│ └── scripts/ # Build and deployment scripts
└── config/ # Configuration files
```
### Module Dependencies
```typescript
// Dependency flow (arrows show dependencies)
Infrastructure ← Content Generation ← Widget Mapping ← Integration
↑ ↑ ↑ ↑
Browser BaseAdapter ImageService Orchestrator
Authentication SubjectAdapters FlowOptimizer Performance
API AssessmentEngine WidgetMapper Testing
```
## Development Workflow
### Git Workflow
**Branch Strategy**:
```bash
main # Production-ready code
├── develop # Integration branch
├── feature/* # Feature development
├── bugfix/* # Bug fixes
└── hotfix/* # Production hotfixes
```
**Feature Development Process**:
```bash
# Create feature branch
git checkout develop
git pull origin develop
git checkout -b feature/new-subject-adapter
# Development cycle
git add .
git commit -m "feat: add support for biology subject adapter"
git push origin feature/new-subject-adapter
# Create pull request
gh pr create --title "Add Biology Subject Adapter" --body "..."
# After review and approval
git checkout develop
git pull origin develop
git branch -d feature/new-subject-adapter
```
### Commit Message Standards
Follow [Conventional Commits](https://www.conventionalcommits.org/):
```bash
# Format
<type>[optional scope]: <description>
# Examples
feat(content): add biology subject adapter
fix(auth): handle expired JWT tokens gracefully
docs(api): update endpoint documentation
perf(memory): optimize garbage collection
test(integration): add comprehensive subject testing
```
### Code Review Process
**Pull Request Requirements**:
- [ ] All tests passing
- [ ] Code coverage >90%
- [ ] Documentation updated
- [ ] Performance impact assessed
- [ ] Security review completed
**Review Checklist**:
- [ ] Follows coding standards
- [ ] Proper error handling
- [ ] Performance optimizations
- [ ] Educational standards compliance
- [ ] TypeScript types correct
## Adding New Features
### Adding a New Subject Adapter
**1. Create Subject Adapter**:
```typescript
// src/content-generation/subject-adapters/biology-adapter.ts
export class BiologyAdapter implements SubjectAdapter {
async enhance(content: BaseContent, context: EnhancementContext): Promise<EnhancedContent> {
return {
...content,
biology_features: {
scientific_nomenclature: this.addScientificNames(content.text),
biological_processes: this.identifyProcesses(content.text),
diagrams: this.suggestDiagrams(content.topic),
lab_procedures: this.generateLabProcedures(content.topic)
}
};
}
private addScientificNames(text: string): ScientificName[] {
// Implementation for adding scientific nomenclature
}
private identifyProcesses(text: string): BiologicalProcess[] {
// Implementation for identifying biological processes
}
}
```
**2. Register in Factory**:
```typescript
// src/content-generation/subject-adapters/subject-adapter-factory.ts
export class SubjectAdapterFactory {
private static adapters = new Map([
['física', () => new PhysicsAdapter()],
['química', () => new ChemistryAdapter()],
['história', () => new HistoryAdapter()],
['biologia', () => new BiologyAdapter()], // Add new adapter
]);
}
```
**3. Add Tests**:
```typescript
// tests/unit/subject-adapters/biology-adapter.test.ts
describe('BiologyAdapter', () => {
let adapter: BiologyAdapter;
beforeEach(() => {
adapter = new BiologyAdapter();
});
test('should enhance content with scientific nomenclature', async () => {
const content = { text: 'Células são unidades básicas da vida' };
const enhanced = await adapter.enhance(content, { grade_level: 'médio' });
expect(enhanced.biology_features.scientific_nomenclature).toBeDefined();
expect(enhanced.biology_features.scientific_nomenclature.length).toBeGreaterThan(0);
});
});
```
### Adding a New Widget Type
**1. Define Widget Type**:
```typescript
// src/types/widget-types.ts
export interface InteractiveSimulationWidget extends BaseWidget {
type: 'interactive-simulation';
simulation_type: 'physics' | 'chemistry' | 'biology';
parameters: SimulationParameters;
controls: ControlConfiguration[];
}
```
**2. Create Widget Mapper**:
```typescript
// src/services/widget-mappers/simulation-mapper.ts
export class SimulationMapper implements WidgetMapper {
canHandle(content: any, context: MappingContext): boolean {
return content.type === 'simulation' ||
context.subject_features?.includes('interactive_simulation');
}
async map(content: any, context: MappingContext): Promise<InteractiveSimulationWidget> {
return {
id: `simulation-${Date.now()}`,
type: 'interactive-simulation',
simulation_type: this.determineSimulationType(context.subject),
parameters: this.extractParameters(content),
controls: this.generateControls(content)
};
}
}
```
**3. Register in Widget Factory**:
```typescript
// src/services/widget-factory.ts
export class WidgetFactory {
private static mappers: WidgetMapper[] = [
new TextMapper(),
new ImageMapper(),
new QuizMapper(),
new SimulationMapper(), // Add new mapper
];
}
```
### Adding Performance Optimizations
**1. Create Optimization Strategy**:
```typescript
// src/performance/optimizations/content-optimization.ts
export class ContentOptimization implements OptimizationStrategy {
async optimize(operation: ContentGenerationOperation): Promise<OptimizationResult> {
const startTime = Date.now();
// Apply caching
const cacheKey = this.generateCacheKey(operation.request);
if (this.cache.has(cacheKey)) {
return { result: this.cache.get(cacheKey), fromCache: true };
}
// Apply parallel processing if applicable
const result = await this.executeOptimizedGeneration(operation);
// Cache result
this.cache.set(cacheKey, result);
return {
result,
executionTime: Date.now() - startTime,
optimizationsApplied: ['caching', 'parallel-processing']
};
}
}
```
**2. Integrate with Performance Manager**:
```typescript
// src/performance/performance-manager.ts
export class PerformanceManager {
private optimizations: OptimizationStrategy[] = [
new ContentOptimization(),
new MemoryOptimization(),
new BrowserOptimization()
];
async optimize(operation: any): Promise<any> {
for (const optimization of this.optimizations) {
if (optimization.canOptimize(operation)) {
return await optimization.optimize(operation);
}
}
return operation.execute();
}
}
```
## Testing Guidelines
### Testing Strategy
**Testing Pyramid**:
```
E2E Tests
(Comprehensive)
________________
/ \
/ Integration \
/ Tests \
/_____________________\
/ \
/ Unit Tests \
/_________________________\
```
### Unit Testing
**Test Structure**:
```typescript
// tests/unit/content-generation/base-adapter.test.ts
describe('BaseAdapter', () => {
let adapter: BaseAdapter;
let mockContext: ContentContext;
beforeEach(() => {
adapter = new BaseAdapter();
mockContext = {
topic: 'Test Topic',
subject: 'física',
grade_level: 'médio'
};
});
describe('generateContent', () => {
test('should generate content for physics topic', async () => {
const result = await adapter.generateContent(mockContext);
expect(result).toBeDefined();
expect(result.introduction).toContain('Test Topic');
expect(result.main_content).toBeTruthy();
expect(result.examples).toHaveLength(3);
});
test('should handle empty topic gracefully', async () => {
mockContext.topic = '';
await expect(adapter.generateContent(mockContext)).rejects.toThrow('Topic cannot be empty');
});
});
describe('performance', () => {
test('should complete generation within performance limits', async () => {
const startTime = Date.now();
await adapter.generateContent(mockContext);
const duration = Date.now() - startTime;
expect(duration).toBeLessThan(5000); // 5 seconds max
});
});
});
```
### Integration Testing
**Test Structure**:
```typescript
// tests/integration/end-to-end-workflow.test.ts
describe('End-to-End Workflow', () => {
let orchestrator: MainIntegrationOrchestrator;
beforeEach(() => {
orchestrator = new MainIntegrationOrchestrator(testConfig);
});
test('should generate complete composition for physics topic', async () => {
const request = {
topic: 'Movimento de Projéteis',
subject: 'física',
grade_level: 'médio',
author: 'Test Teacher'
};
const result = await orchestrator.orchestrateEducationalComposition(request);
expect(result.success).toBe(true);
expect(result.composition_data).toBeDefined();
expect(result.composition_data.composition.elements.length).toBeGreaterThan(3);
expect(result.execution_time).toBeLessThan(30000);
});
});
```
### Performance Testing
**Test Structure**:
```typescript
// tests/performance/load-testing.test.ts
describe('Load Testing', () => {
test('should handle concurrent requests efficiently', async () => {
const concurrentRequests = 10;
const requests = Array(concurrentRequests).fill(null).map(() =>
orchestrator.orchestrateEducationalComposition(standardRequest)
);
const startTime = Date.now();
const results = await Promise.all(requests);
const totalTime = Date.now() - startTime;
expect(results.every(r => r.success)).toBe(true);
expect(totalTime).toBeLessThan(10000); // 10 seconds for 10 requests
expect(totalTime / concurrentRequests).toBeLessThan(2000); // 2s average per request
});
});
```
### Test Commands
```bash
# Run all tests
npm test
# Run specific test suite
npm test -- tests/unit/
npm test -- tests/integration/
npm test -- tests/performance/
# Run tests with coverage
npm run test:coverage
# Run tests in watch mode
npm run test:watch
# Run performance tests
npm run test:performance
```
## Performance Optimization
### Profiling and Monitoring
**Performance Profiling**:
```typescript
// src/utils/profiler.ts
export class Profiler {
private static marks = new Map<string, number>();
static start(operation: string): void {
this.marks.set(operation, Date.now());
}
static end(operation: string): number {
const startTime = this.marks.get(operation);
if (!startTime) {
throw new Error(`No start mark for operation: ${operation}`);
}
const duration = Date.now() - startTime;
console.log(`[PERF] ${operation}: ${duration}ms`);
this.marks.delete(operation);
return duration;
}
static async measure<T>(operation: string, fn: () => Promise<T>): Promise<T> {
this.start(operation);
try {
const result = await fn();
this.end(operation);
return result;
} catch (error) {
this.marks.delete(operation);
throw error;
}
}
}
```
**Usage Example**:
```typescript
// Profile content generation
const content = await Profiler.measure('content-generation', async () => {
return await baseAdapter.generateContent(context);
});
// Profile with manual timing
Profiler.start('widget-mapping');
const widgets = await widgetMapper.mapContent(content);
Profiler.end('widget-mapping');
```
### Memory Optimization
**Memory Monitoring**:
```typescript
// src/utils/memory-monitor.ts
export class MemoryMonitor {
static logMemoryUsage(label: string = ''): void {
const usage = process.memoryUsage();
console.log(`[MEMORY] ${label}:`, {
heapUsed: `${Math.round(usage.heapUsed / 1024 / 1024)}MB`,
heapTotal: `${Math.round(usage.heapTotal / 1024 / 1024)}MB`,
external: `${Math.round(usage.external / 1024 / 1024)}MB`
});
}
static async trackMemory<T>(operation: string, fn: () => Promise<T>): Promise<T> {
this.logMemoryUsage(`Before ${operation}`);
const result = await fn();
this.logMemoryUsage(`After ${operation}`);
return result;
}
}
```
### Caching Strategies
**Content Caching**:
```typescript
// src/cache/content-cache.ts
export class ContentCache {
private cache = new Map<string, CachedContent>();
private readonly maxSize = 1000;
generateKey(topic: string, subject: string, gradeLevel: string): string {
return `${topic}:${subject}:${gradeLevel}`.toLowerCase();
}
get(key: string): CachedContent | null {
const cached = this.cache.get(key);
if (cached && !this.isExpired(cached)) {
cached.lastAccessed = Date.now();
return cached;
}
this.cache.delete(key);
return null;
}
set(key: string, content: any): void {
if (this.cache.size >= this.maxSize) {
this.evictOldest();
}
this.cache.set(key, {
content,
createdAt: Date.now(),
lastAccessed: Date.now()
});
}
private evictOldest(): void {
let oldestKey = '';
let oldestTime = Date.now();
for (const [key, cached] of this.cache.entries()) {
if (cached.lastAccessed < oldestTime) {
oldestTime = cached.lastAccessed;
oldestKey = key;
}
}
if (oldestKey) {
this.cache.delete(oldestKey);
}
}
}
```
## Deployment Process
### Build Process
```bash
# Clean build
npm run clean
npm run build
# Type checking
npm run type-check
# Linting
npm run lint
# Testing
npm run test:all
# Bundle analysis
npm run analyze
```
### Production Deployment
**Docker Deployment**:
```dockerfile
# Dockerfile
FROM node:18-alpine
WORKDIR /app
# Install dependencies
COPY package*.json ./
RUN npm ci --only=production
# Install Playwright browsers
RUN npx playwright install-deps
RUN npx playwright install
# Copy application
COPY dist/ ./dist/
COPY config/ ./config/
# Set environment
ENV NODE_ENV=production
ENV NODE_OPTIONS=--max-old-space-size=4096
# Health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=60s \
CMD curl -f http://localhost:3000/health || exit 1
EXPOSE 3000
CMD ["node", "dist/index.js"]
```
**Kubernetes Deployment**:
```yaml
# k8s/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: composer-mcp
spec:
replicas: 3
selector:
matchLabels:
app: composer-mcp
template:
metadata:
labels:
app: composer-mcp
spec:
containers:
- name: composer-mcp
image: composer-mcp:latest
ports:
- containerPort: 3000
env:
- name: NODE_OPTIONS
value: "--max-old-space-size=4096"
resources:
requests:
memory: "2Gi"
cpu: "500m"
limits:
memory: "4Gi"
cpu: "2000m"
livenessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 60
periodSeconds: 30
```
### Environment Management
**Environment-Specific Configuration**:
```typescript
// config/environments.ts
export const environments = {
development: {
api: {
baseUrl: 'http://localhost:3000/api/v4',
timeout: 30000
},
performance: {
enableCaching: true,
cacheSize: 500,
memoryThreshold: 256
},
logging: {
level: 'debug',
enablePerformanceLogs: true
}
},
production: {
api: {
baseUrl: 'https://composer.digitalpages.com.br/api/v4',
timeout: 15000
},
performance: {
enableCaching: true,
cacheSize: 2000,
memoryThreshold: 512
},
logging: {
level: 'info',
enablePerformanceLogs: false
}
}
};
```
## Code Standards
### TypeScript Standards
**Type Definitions**:
```typescript
// Always use explicit types for public APIs
export interface EducationalRequest {
topic: string;
subject: string;
grade_level: 'fundamental' | 'médio' | 'superior';
author: string;
learning_objectives?: string[];
}
// Use generic types appropriately
export interface ApiResponse<T> {
success: boolean;
data?: T;
error?: string;
}
// Use utility types when appropriate
export type PartialEducationalRequest = Partial<EducationalRequest>;
export type RequiredEducationalRequest = Required<EducationalRequest>;
```
**Error Handling**:
```typescript
// Custom error classes
export class ContentGenerationError extends Error {
constructor(
message: string,
public readonly cause?: Error,
public readonly context?: any
) {
super(message);
this.name = 'ContentGenerationError';
}
}
// Error handling pattern
async function generateContent(request: EducationalRequest): Promise<Content> {
try {
return await contentGenerator.generate(request);
} catch (error) {
if (error instanceof ValidationError) {
throw new ContentGenerationError(
'Invalid request parameters',
error,
{ request }
);
}
throw error;
}
}
```
### ESLint Configuration
**`.eslintrc.js`**:
```javascript
module.exports = {
parser: '@typescript-eslint/parser',
plugins: ['@typescript-eslint', 'import'],
extends: [
'eslint:recommended',
'@typescript-eslint/recommended',
'prettier'
],
rules: {
'@typescript-eslint/explicit-function-return-type': 'error',
'@typescript-eslint/no-explicit-any': 'warn',
'@typescript-eslint/no-unused-vars': 'error',
'import/order': ['error', { 'groups': ['builtin', 'external', 'internal'] }],
'prefer-const': 'error',
'no-var': 'error'
}
};
```
## Best Practices
### Performance Best Practices
1. **Always Profile Before Optimizing**:
```typescript
// Use profiler to identify bottlenecks
const result = await Profiler.measure('content-generation', async () => {
return await generateContent(request);
});
```
2. **Implement Caching Strategically**:
```typescript
// Cache expensive operations
const cacheKey = generateCacheKey(request);
if (cache.has(cacheKey)) {
return cache.get(cacheKey);
}
```
3. **Use Lazy Loading**:
```typescript
// Lazy load subject adapters
class SubjectAdapterFactory {
private static adapters = new Map([
['física', () => import('./physics-adapter').then(m => new m.PhysicsAdapter())],
]);
}
```
### Memory Management Best Practices
1. **Clean Up Resources**:
```typescript
class ResourceManager {
private resources: Resource[] = [];
async cleanup(): Promise<void> {
await Promise.all(this.resources.map(r => r.dispose()));
this.resources = [];
}
}
```
2. **Use WeakRef for Caching**:
```typescript
class WeakCache {
private cache = new Map<string, WeakRef<CachedItem>>();
get(key: string): CachedItem | null {
const ref = this.cache.get(key);
const item = ref?.deref();
if (!item) {
this.cache.delete(key);
return null;
}
return item;
}
}
```
### Educational Content Best Practices
1. **Follow BNCC Standards**:
```typescript
// Validate content against educational standards
const validator = new BNCCValidator();
const compliance = await validator.validate(content, {
subject: 'física',
gradeLevel: 'médio'
});
```
2. **Ensure Accessibility**:
```typescript
// Generate alt text for images
const imageElement = {
type: 'image-1',
src: imageUrl,
alt: generateAltText(imageContent, context),
caption: generateCaption(imageContent)
};
```
3. **Support Multiple Learning Styles**:
```typescript
// Include diverse content types
const lesson = {
visual: generateVisualContent(topic),
auditory: generateNarrativeContent(topic),
kinesthetic: generateInteractiveElements(topic)
};
```
---
**Development Guide Status**: ✅ **COMPREHENSIVE**
**Setup Instructions**: ✅ **COMPLETE** development environment setup
**Code Examples**: ✅ **PRACTICAL** real-world implementation patterns
**Best Practices**: ✅ **INDUSTRY-STANDARD** development guidelines
**Testing Coverage**: ✅ **THOROUGH** testing strategies and examples
**🎯 Key Strength: Complete development guide enabling efficient onboarding and consistent development practices for maintaining and extending the universal educational content generation system**