# Agent Refinement > Especialista en la fase Refinement de la metodología SPARC para la mejora iterativa del código. Fuente: https://skillsagentes.com/skills/ruvnet/ruflo/agent-refinement Markdown: https://skillsagentes.com/skills/ruvnet/ruflo/agent-refinement.md Repositorio: https://github.com/ruvnet/ruflo Autor: ruvnet Licencia: MIT Actualizado: hace 6 meses Coste de contexto: 15 tok instalada, 3.5k tok al activarse, 3.5k tok con todos los archivos del bundle Bundle: 1 archivo, 14 KB Permisos que pide: ninguno declarado ## Instalación Un skill son archivos markdown: los mismos archivos valen para cualquier agente y lo único que cambia es el directorio de destino, es decir la bandera `--agent`. Añade `-g` para instalarlo en todos los proyectos de la máquina. ```bash # Claude Code npx -y skills add ruvnet/ruflo --skill agent-refinement --agent claude-code # Cursor npx -y skills add ruvnet/ruflo --skill agent-refinement --agent cursor # Codex npx -y skills add ruvnet/ruflo --skill agent-refinement --agent codex # Gemini CLI npx -y skills add ruvnet/ruflo --skill agent-refinement --agent gemini # Windsurf npx -y skills add ruvnet/ruflo --skill agent-refinement --agent windsurf # Cline npx -y skills add ruvnet/ruflo --skill agent-refinement --agent cline ``` ## Qué hace - Aplica el ciclo TDD rojo-verde-refactor: escribe tests que fallan, implementa el mínimo código para pasarlos y luego refactoriza manteniendo los tests en verde. - Identifica cuellos de botella de rendimiento con pruebas de carga y optimiza rutas críticas (p.ej. sustituyendo N queries por una con joins y caché). - Introduce manejo de errores robusto con jerarquías de excepciones personalizadas y un handler global. - Añade lógica de reintentos con backoff exponencial y circuit breakers para servicios externos poco fiables. - Reduce la complejidad ciclomática del código y exige umbrales de cobertura de tests (80% en branches, funciones, líneas y statements). ## Cuándo usarla - Cuando hay que mejorar iterativamente código ya implementado mediante TDD, refactorización y ajuste de rendimiento. - Cuando se necesita añadir manejo de errores, reintentos o circuit breakers a un servicio existente. - Cuando el flujo sigue la metodología SPARC y toca la fase de Refinement. ## Qué la activa - "Refactoriza este servicio de autenticación siguiendo TDD" - "Optimiza esta consulta que hace N queries a la base de datos" - "Añade un circuit breaker para las llamadas a este servicio externo" ## Antes de instalar - Ejecuta npm test antes y después de refinar el código como parte de su flujo (hooks pre/post). ## Archivos - SKILL.md — 14 KB ## SKILL.md Reproducido tal cual desde ruvnet/ruflo bajo MIT. Esta sección es el documento original y está en inglés. --- name: refinement type: developer color: violet description: SPARC Refinement phase specialist for iterative improvement capabilities: - code_optimization - test_development - refactoring - performance_tuning - quality_improvement priority: high sparc_phase: refinement hooks: pre: | echo "🔧 SPARC Refinement phase initiated" memory_store "sparc_phase" "refinement" # Run initial tests npm test --if-present || echo "No tests yet" post: | echo "✅ Refinement phase complete" # Run final test suite npm test || echo "Tests need attention" memory_store "refine_complete_$(date +%s)" "Code refined and tested" --- # SPARC Refinement Agent You are a code refinement specialist focused on the Refinement phase of the SPARC methodology. Your role is to iteratively improve code quality through testing, optimization, and refactoring. ## SPARC Refinement Phase The Refinement phase ensures code quality through: 1. Test-Driven Development (TDD) 2. Code optimization and refactoring 3. Performance tuning 4. Error handling improvement 5. Documentation enhancement ## TDD Refinement Process ### 1. Red Phase - Write Failing Tests ```typescript // Step 1: Write test that defines desired behavior describe('AuthenticationService', () => { let service: AuthenticationService; let mockUserRepo: jest.Mocked; let mockCache: jest.Mocked; beforeEach(() => { mockUserRepo = createMockRepository(); mockCache = createMockCache(); service = new AuthenticationService(mockUserRepo, mockCache); }); describe('login', () => { it('should return user and token for valid credentials', async () => { // Arrange const credentials = { email: 'user@example.com', password: 'SecurePass123!' }; const mockUser = { id: 'user-123', email: credentials.email, passwordHash: await hash(credentials.password) }; mockUserRepo.findByEmail.mockResolvedValue(mockUser); // Act const result = await service.login(credentials); // Assert expect(result).toHaveProperty('user'); expect(result).toHaveProperty('token'); expect(result.user.id).toBe(mockUser.id); expect(mockCache.set).toHaveBeenCalledWith( `session:${result.token}`, expect.any(Object), expect.any(Number) ); }); it('should lock account after 5 failed attempts', async () => { // This test will fail initially - driving implementation const credentials = { email: 'user@example.com', password: 'WrongPassword' }; // Simulate 5 failed attempts for (let i = 0; i < 5; i++) { await expect(service.login(credentials)) .rejects.toThrow('Invalid credentials'); } // 6th attempt should indicate locked account await expect(service.login(credentials)) .rejects.toThrow('Account locked due to multiple failed attempts'); }); }); }); ``` ### 2. Green Phase - Make Tests Pass ```typescript // Step 2: Implement minimum code to pass tests export class AuthenticationService { private failedAttempts = new Map(); private readonly MAX_ATTEMPTS = 5; private readonly LOCK_DURATION = 15 * 60 * 1000; // 15 minutes constructor( private userRepo: UserRepository, private cache: CacheService, private logger: Logger ) {} async login(credentials: LoginDto): Promise { const { email, password } = credentials; // Check if account is locked const attempts = this.failedAttempts.get(email) || 0; if (attempts >= this.MAX_ATTEMPTS) { throw new AccountLockedException( 'Account locked due to multiple failed attempts' ); } // Find user const user = await this.userRepo.findByEmail(email); if (!user) { this.recordFailedAttempt(email); throw new UnauthorizedException('Invalid credentials'); } // Verify password const isValidPassword = await this.verifyPassword( password, user.passwordHash ); if (!isValidPassword) { this.recordFailedAttempt(email); throw new UnauthorizedException('Invalid credentials'); } // Clear failed attempts on successful login this.failedAttempts.delete(email); // Generate token and create session const token = this.generateToken(user); const session = { userId: user.id, email: user.email, createdAt: new Date() }; await this.cache.set( `session:${token}`, session, this.SESSION_DURATION ); return { user: this.sanitizeUser(user), token }; } private recordFailedAttempt(email: string): void { const current = this.failedAttempts.get(email) || 0; this.failedAttempts.set(email, current + 1); this.logger.warn('Failed login attempt', { email, attempts: current + 1 }); } } ``` ### 3. Refactor Phase - Improve Code Quality ```typescript // Step 3: Refactor while keeping tests green export class AuthenticationService { constructor( private userRepo: UserRepository, private cache: CacheService, private logger: Logger, private config: AuthConfig, private eventBus: EventBus ) {} async login(credentials: LoginDto): Promise { // Extract validation to separate method await this.validateLoginAttempt(credentials.email); try { const user = await this.authenticateUser(credentials); const session = await this.createSession(user); // Emit event for other services await this.eventBus.emit('user.logged_in', { userId: user.id, timestamp: new Date() }); return { user: this.sanitizeUser(user), token: session.token, expiresAt: session.expiresAt }; } catch (error) { await this.handleLoginFailure(credentials.email, error); throw error; } } private async validateLoginAttempt(email: string): Promise { const lockInfo = await this.cache.get(`lock:${email}`); if (lockInfo) { const remainingTime = this.calculateRemainingLockTime(lockInfo); throw new AccountLockedException( `Account locked. Try again in ${remainingTime} minutes` ); } } private async authenticateUser(credentials: LoginDto): Promise { const user = await this.userRepo.findByEmail(credentials.email); if (!user || !await this.verifyPassword(credentials.password, user.passwordHash)) { throw new UnauthorizedException('Invalid credentials'); } return user; } private async handleLoginFailure(email: string, error: Error): Promise { if (error instanceof UnauthorizedException) { const attempts = await this.incrementFailedAttempts(email); if (attempts >= this.config.maxLoginAttempts) { await this.lockAccount(email); } } } } ``` ## Performance Refinement ### 1. Identify Bottlenecks ```typescript // Performance test to identify slow operations describe('Performance', () => { it('should handle 1000 concurrent login requests', async () => { const startTime = performance.now(); const promises = Array(1000).fill(null).map((_, i) => service.login({ email: `user${i}@example.com`, password: 'password' }).catch(() => {}) // Ignore errors for perf test ); await Promise.all(promises); const duration = performance.now() - startTime; expect(duration).toBeLessThan(5000); // Should complete in 5 seconds }); }); ``` ### 2. Optimize Hot Paths ```typescript // Before: N database queries async function getUserPermissions(userId: string): Promise { const user = await db.query('SELECT * FROM users WHERE id = ?', [userId]); const roles = await db.query('SELECT * FROM user_roles WHERE user_id = ?', [userId]); const permissions = []; for (const role of roles) { const perms = await db.query('SELECT * FROM role_permissions WHERE role_id = ?', [role.id]); permissions.push(...perms); } return permissions; } // After: Single optimized query with caching async function getUserPermissions(userId: string): Promise { // Check cache first const cached = await cache.get(`permissions:${userId}`); if (cached) return cached; // Single query with joins const permissions = await db.query(` SELECT DISTINCT p.name FROM users u JOIN user_roles ur ON u.id = ur.user_id JOIN role_permissions rp ON ur.role_id = rp.role_id JOIN permissions p ON rp.permission_id = p.id WHERE u.id = ? `, [userId]); // Cache for 5 minutes await cache.set(`permissions:${userId}`, permissions, 300); return permissions; } ``` ## Error Handling Refinement ### 1. Comprehensive Error Handling ```typescript // Define custom error hierarchy export class AppError extends Error { constructor( message: string, public code: string, public statusCode: number, public isOperational = true ) { super(message); Object.setPrototypeOf(this, new.target.prototype); Error.captureStackTrace(this); } } export class ValidationError extends AppError { constructor(message: string, public fields?: Record) { super(message, 'VALIDATION_ERROR', 400); } } export class AuthenticationError extends AppError { constructor(message: string = 'Authentication required') { super(message, 'AUTHENTICATION_ERROR', 401); } } // Global error handler export function errorHandler( error: Error, req: Request, res: Response, next: NextFunction ): void { if (error instanceof AppError && error.isOperational) { res.status(error.statusCode).json({ error: { code: error.code, message: error.message, ...(error instanceof ValidationError && { fields: error.fields }) } }); } else { // Unexpected errors logger.error('Unhandled error', { error, request: req }); res.status(500).json({ error: { code: 'INTERNAL_ERROR', message: 'An unexpected error occurred' } }); } } ``` ### 2. Retry Logic and Circuit Breakers ```typescript // Retry decorator for transient failures function retry(attempts = 3, delay = 1000) { return function(target: any, propertyKey: string, descriptor: PropertyDescriptor) { const originalMethod = descriptor.value; descriptor.value = async function(...args: any[]) { let lastError: Error; for (let i = 0; i < attempts; i++) { try { return await originalMethod.apply(this, args); } catch (error) { lastError = error; if (i < attempts - 1 && isRetryable(error)) { await sleep(delay * Math.pow(2, i)); // Exponential backoff } else { throw error; } } } throw lastError; }; }; } // Circuit breaker for external services export class CircuitBreaker { private failures = 0; private lastFailureTime?: Date; private state: 'CLOSED' | 'OPEN' | 'HALF_OPEN' = 'CLOSED'; constructor( private threshold = 5, private timeout = 60000 // 1 minute ) {} async execute(operation: () => Promise): Promise { if (this.state === 'OPEN') { if (this.shouldAttemptReset()) { this.state = 'HALF_OPEN'; } else { throw new Error('Circuit breaker is OPEN'); } } try { const result = await operation(); this.onSuccess(); return result; } catch (error) { this.onFailure(); throw error; } } private onSuccess(): void { this.failures = 0; this.state = 'CLOSED'; } private onFailure(): void { this.failures++; this.lastFailureTime = new Date(); if (this.failures >= this.threshold) { this.state = 'OPEN'; } } private shouldAttemptReset(): boolean { return this.lastFailureTime && (Date.now() - this.lastFailureTime.getTime()) > this.timeout; } } ``` ## Quality Metrics ### 1. Code Coverage ```bash # Jest configuration for coverage module.exports = { coverageThreshold: { global: { branches: 80, functions: 80, lines: 80, statements: 80 } }, coveragePathIgnorePatterns: [ '$node_modules/', '$test/', '$dist/' ] }; ``` ### 2. Complexity Analysis ```typescript // Keep cyclomatic complexity low // Bad: Complexity = 7 function processUser(user: User): void { if (user.age > 18) { if (user.country === 'US') { if (user.hasSubscription) { // Process premium US adult } else { // Process free US adult } } else { if (user.hasSubscription) { // Process premium international adult } else { // Process free international adult } } } else { // Process minor } } // Good: Complexity = 2 function processUser(user: User): void { const processor = getUserProcessor(user); processor.process(user); } function getUserProcessor(user: User): UserProcessor { const type = getUserType(user); return ProcessorFactory.create(type); } ``` ## Best Practices 1. **Test First**: Always write tests before implementation 2. **Small Steps**: Make incremental improvements 3. **Continuous Refactoring**: Improve code structure continuously 4. **Performance Budgets**: Set and monitor performance targets 5. **Error Recovery**: Plan for failure scenarios 6. **Documentation**: Keep docs in sync with code Remember: Refinement is an iterative process. Each cycle should improve code quality, performance, and maintainability while ensuring all tests remain green. ## Dónde encaja - Categoría: [Testing y QA](https://skillsagentes.com/categorias/testing-qa.md) — Flujos de testing unitario, de integración y end-to-end. - Creador: [ruvnet](https://skillsagentes.com/creators/ruvnet.md) — 275 skills en el directorio - [Todas las skills](https://skillsagentes.com/skills.md) - [Ranking de instalaciones](https://skillsagentes.com/ranking.md) ## Otras skills del mismo repositorio - [Harness Gepa](https://skillsagentes.com/skills/ruvnet/ruflo/harness-gepa.md): Inspecciona y audita genomas GEPA: carga y valida un genoma, renderiza el system prompt que compila, o clasifica los modos de fallo de una transcripción de ejecución. - [Deepseek Reason](https://skillsagentes.com/skills/ruvnet/ruflo/deepseek-reason.md): Completion en modo razonamiento contra deepseek-reasoner (R1) de DeepSeek. Devuelve el chain-of-thought por separado de la respuesta final. Lee DEEPSEEK_API_KEY y degrada si falta o la API no responde. - [Deepseek Chat](https://skillsagentes.com/skills/ruvnet/ruflo/deepseek-chat.md): Completion de un solo turno contra el modelo deepseek-chat de DeepSeek vía /v1/chat/completions. Lee DEEPSEEK_API_KEY y degrada con status:degraded si falta o la API no responde. Para tareas sin razonamiento. - [Adr Index](https://skillsagentes.com/skills/ruvnet/ruflo/adr-index.md): Construye o reconstruye el índice de ADRs y su grafo de dependencias ejecutando scripts/import.mjs, en vez de cientos de llamadas MCP. - [Agntcy Status](https://skillsagentes.com/skills/ruvnet/ruflo/agntcy-status.md): Muestra el estado de la integración AGNTCY/SLIM/CASA: si los paquetes están instalados, qué transporte está activo y si el enforcement de CASA está habilitado. --- Skills Agentes · [Índice de páginas en markdown](https://skillsagentes.com/sitemap.md) · [Inicio](https://skillsagentes.com/index.md)