Complete documentation for future sessions
- CLAUDE.md for AI agents to understand the codebase - GITEA-GUIDE.md centralizes all Gitea operations (API, Registry, Auth) - DEVELOPMENT-WORKFLOW.md explains complete dev process - ROADMAP.md, NEXT-SESSION.md for planning - QUICK-REFERENCE.md, TROUBLESHOOTING.md for daily use - 40+ detailed docs in /docs folder - Backend as submodule from Gitea Everything documented for autonomous operation. Co-Authored-By: Claude Sonnet 4.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
316
docs/01-arquitectura/flujo-de-datos.md
Normal file
316
docs/01-arquitectura/flujo-de-datos.md
Normal file
@@ -0,0 +1,316 @@
|
||||
# Flujo de Datos
|
||||
|
||||
## Arquitectura de Comunicación
|
||||
|
||||
```
|
||||
┌──────────┐ ┌──────────┐ ┌──────────┐
|
||||
│ Frontend │ ◄─────► │ Backend │ ◄─────► │ MySQL │
|
||||
└──────────┘ └──────────┘ └──────────┘
|
||||
│ │ │
|
||||
│ ├──────────────────────┤
|
||||
│ │ Redis │
|
||||
│ └──────────────────────┘
|
||||
│ │
|
||||
│ ┌─────┴─────┐
|
||||
│ │ │
|
||||
│ ┌────▼────┐ ┌───▼────┐
|
||||
│ │ Gitea │ │ K8s │
|
||||
│ └─────────┘ └───┬────┘
|
||||
│ │
|
||||
│ ┌────▼────────┐
|
||||
└────────────────────┤ Claude Code │
|
||||
WebSocket │ Agents │
|
||||
└─────────────┘
|
||||
```
|
||||
|
||||
## 1. Flujo Completo: Creación de Tarea
|
||||
|
||||
### 1.1 Usuario Crea Tarea
|
||||
|
||||
```
|
||||
Frontend Backend MySQL Redis
|
||||
│ │ │ │
|
||||
│ POST /api/tasks │ │ │
|
||||
├──────────────────────►│ │ │
|
||||
│ │ INSERT task │ │
|
||||
│ ├──────────────────►│ │
|
||||
│ │ │ │
|
||||
│ │ PUBLISH task.new │ │
|
||||
│ ├───────────────────┼────────────────►│
|
||||
│ │ │ │
|
||||
│ { taskId, status } │ │ │
|
||||
│◄──────────────────────┤ │ │
|
||||
│ │ │ │
|
||||
│ WS: task_created │ │ │
|
||||
│◄──────────────────────┤ │ │
|
||||
```
|
||||
|
||||
**Detalle**:
|
||||
1. Frontend envía POST a `/api/tasks` con JSON:
|
||||
```json
|
||||
{
|
||||
"projectId": "uuid",
|
||||
"title": "Implementar login",
|
||||
"description": "Crear sistema de autenticación..."
|
||||
}
|
||||
```
|
||||
|
||||
2. Backend:
|
||||
- Valida datos
|
||||
- Inserta en MySQL tabla `tasks`
|
||||
- Publica evento en Redis: `task:new`
|
||||
- Añade job a cola BullMQ: `task-queue`
|
||||
- Responde con task creada
|
||||
|
||||
3. WebSocket notifica a todos los clientes conectados
|
||||
|
||||
### 1.2 Agente Toma Tarea
|
||||
|
||||
```
|
||||
Agent (K8s) Backend (MCP) MySQL BullMQ
|
||||
│ │ │ │
|
||||
│ MCP: get_next_task │ │ │
|
||||
├──────────────────────►│ │ │
|
||||
│ │ SELECT task │ │
|
||||
│ ├──────────────────►│ │
|
||||
│ │ │ │
|
||||
│ │ UPDATE status │ │
|
||||
│ ├──────────────────►│ │
|
||||
│ │ │ │
|
||||
│ { task details } │ DEQUEUE job │ │
|
||||
│◄──────────────────────┤◄─────────────────┼─────────────────┤
|
||||
│ │ │ │
|
||||
```
|
||||
|
||||
**Detalle**:
|
||||
1. Agente llama herramienta MCP `get_next_task`
|
||||
2. Backend:
|
||||
- Query: `SELECT * FROM tasks WHERE state='backlog' ORDER BY created_at LIMIT 1`
|
||||
- Actualiza: `UPDATE tasks SET state='in_progress', assigned_agent_id=?`
|
||||
- Elimina job de BullMQ
|
||||
3. Responde con detalles completos de la tarea
|
||||
|
||||
## 2. Flujo: Agente Pide Información
|
||||
|
||||
```
|
||||
Agent Backend (MCP) MySQL Frontend (WS)
|
||||
│ │ │ │
|
||||
│ ask_user_question │ │ │
|
||||
├─────────────────────►│ │ │
|
||||
│ │ UPDATE task │ │
|
||||
│ ├──────────────────►│ │
|
||||
│ │ state=needs_input │ │
|
||||
│ │ │ │
|
||||
│ │ INSERT question │ │
|
||||
│ ├──────────────────►│ │
|
||||
│ │ │ │
|
||||
│ { success: true } │ WS: needs_input │ │
|
||||
│◄─────────────────────┤──────────────────┼───────────────────►│
|
||||
│ │ │ │
|
||||
│ │ │ [Usuario ve] │
|
||||
│ │ │ [notificación] │
|
||||
│ │ │ │
|
||||
│ │ POST /api/tasks/ │ │
|
||||
│ │ :id/respond │ │
|
||||
│ │◄──────────────────┼────────────────────┤
|
||||
│ │ │ │
|
||||
│ MCP: check_response │ UPDATE response │ │
|
||||
├─────────────────────►├──────────────────►│ │
|
||||
│ │ state=in_progress │ │
|
||||
│ { response: "..." } │ │ │
|
||||
│◄─────────────────────┤ │ │
|
||||
```
|
||||
|
||||
**Detalle**:
|
||||
1. Agente detecta necesita info (ej: "¿Qué librería usar para auth?")
|
||||
2. Llama `ask_user_question(taskId, question)`
|
||||
3. Backend:
|
||||
- Actualiza `tasks.state = 'needs_input'`
|
||||
- Inserta en tabla `task_questions`
|
||||
- Emite WebSocket `task:needs_input`
|
||||
4. Frontend muestra notificación y badge en kanban
|
||||
5. Usuario responde vía UI
|
||||
6. Backend guarda respuesta
|
||||
7. Agente hace polling o recibe notificación vía MCP
|
||||
|
||||
## 3. Flujo: Completar Tarea y Deploy Preview
|
||||
|
||||
```
|
||||
Agent Backend(MCP) Gitea API MySQL K8s API Frontend
|
||||
│ │ │ │ │ │
|
||||
│ create_branch │ │ │ │ │
|
||||
├─────────────────►│ │ │ │ │
|
||||
│ │ POST /repos/│ │ │ │
|
||||
│ │ :owner/:repo│ │ │ │
|
||||
│ │ /branches │ │ │ │
|
||||
│ ├────────────►│ │ │ │
|
||||
│ { branch } │ │ │ │ │
|
||||
│◄─────────────────┤ │ │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ [agent works] │ │ │ │ │
|
||||
│ [commits code] │ │ │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ create_pr │ │ │ │ │
|
||||
├─────────────────►│ │ │ │ │
|
||||
│ │ POST /pulls │ │ │ │
|
||||
│ ├────────────►│ │ │ │
|
||||
│ { pr_url } │ │ │ │ │
|
||||
│◄─────────────────┤ │ │ │ │
|
||||
│ │ │ │ │ │
|
||||
│ trigger_preview │ │ │ │ │
|
||||
├─────────────────►│ │ │ │ │
|
||||
│ │ UPDATE task │ │ │ │
|
||||
│ ├────────────┼────────────►│ │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ CREATE │ │ CREATE │ │
|
||||
│ │ namespace │ │ Deployment │
|
||||
│ ├────────────┼────────────┼──────────►│ │
|
||||
│ │ │ │ │ │
|
||||
│ { preview_url } │ │ WS:ready_to_test │ │
|
||||
│◄─────────────────┤─────────────┼───────────┼───────────┼───────────►│
|
||||
```
|
||||
|
||||
**Detalle**:
|
||||
1. **create_branch**: Backend usa Gitea API para crear rama `task-{id}-feature`
|
||||
2. **Agente trabaja**: Clone, cambios, commits, push
|
||||
3. **create_pr**: Crea PR con descripción generada
|
||||
4. **trigger_preview**:
|
||||
- Backend crea namespace K8s: `preview-task-{id}`
|
||||
- Aplica deployment con imagen del proyecto
|
||||
- Configura ingress con URL: `task-{id}.preview.aiworker.dev`
|
||||
- Actualiza `tasks.state = 'ready_to_test'`
|
||||
5. Frontend muestra botón "Ver Preview" con URL
|
||||
|
||||
## 4. Flujo: Merge a Staging
|
||||
|
||||
```
|
||||
User (Frontend) Backend Gitea API K8s API ArgoCD
|
||||
│ │ │ │ │
|
||||
│ POST /merge │ │ │ │
|
||||
│ taskIds[] │ │ │ │
|
||||
├──────────────►│ │ │ │
|
||||
│ │ Validate │ │ │
|
||||
│ │ all approved │ │ │
|
||||
│ │ │ │ │
|
||||
│ │ POST /pulls │ │ │
|
||||
│ │ (merge PRs) │ │ │
|
||||
│ ├──────────────►│ │ │
|
||||
│ │ │ │ │
|
||||
│ │ POST /branches│ │ │
|
||||
│ │ staging │ │ │
|
||||
│ ├──────────────►│ │ │
|
||||
│ │ │ │ │
|
||||
│ │ Trigger │ Apply │ │
|
||||
│ │ ArgoCD sync │ manifests │ │
|
||||
│ ├───────────────┼──────────────┼────────────►│
|
||||
│ │ │ │ │
|
||||
│ { status } │ │ │ [Deploys] │
|
||||
│◄──────────────┤ │ │ │
|
||||
```
|
||||
|
||||
**Detalle**:
|
||||
1. Usuario selecciona 2-3 tareas aprobadas
|
||||
2. Click "Merge a Staging"
|
||||
3. Backend:
|
||||
- Valida todas están en estado `approved`
|
||||
- Mergea cada PR a `staging` branch
|
||||
- Actualiza estado a `staging`
|
||||
- Triggerea ArgoCD sync
|
||||
4. ArgoCD detecta cambios y deploya a namespace `staging`
|
||||
|
||||
## 5. Comunicación Real-Time (WebSocket)
|
||||
|
||||
### Eventos emitidos por Backend:
|
||||
|
||||
```typescript
|
||||
// Usuario se conecta
|
||||
socket.on('connect', () => {
|
||||
socket.emit('auth', { userId, token })
|
||||
})
|
||||
|
||||
// Backend emite eventos
|
||||
socket.emit('task:created', { taskId, projectId })
|
||||
socket.emit('task:status_changed', { taskId, oldState, newState })
|
||||
socket.emit('task:needs_input', { taskId, question })
|
||||
socket.emit('task:ready_to_test', { taskId, previewUrl })
|
||||
socket.emit('agent:status', { agentId, status, currentTaskId })
|
||||
socket.emit('deploy:started', { environment, taskIds })
|
||||
socket.emit('deploy:completed', { environment, url })
|
||||
```
|
||||
|
||||
### Cliente subscribe:
|
||||
|
||||
```typescript
|
||||
socket.on('task:status_changed', (data) => {
|
||||
// Actualiza UI del kanban
|
||||
queryClient.invalidateQueries(['tasks'])
|
||||
})
|
||||
|
||||
socket.on('task:needs_input', (data) => {
|
||||
// Muestra notificación
|
||||
toast.info('Un agente necesita tu ayuda')
|
||||
// Mueve card a columna "Needs Input"
|
||||
})
|
||||
```
|
||||
|
||||
## 6. Caching Strategy
|
||||
|
||||
### Redis Cache Keys:
|
||||
|
||||
```
|
||||
task:{id} → TTL 5min (task details)
|
||||
task:list:{projectId} → TTL 2min (lista de tareas)
|
||||
agent:{id}:status → TTL 30s (estado agente)
|
||||
project:{id} → TTL 10min (config proyecto)
|
||||
```
|
||||
|
||||
### Invalidación:
|
||||
|
||||
```typescript
|
||||
// Al actualizar tarea
|
||||
await redis.del(`task:${taskId}`)
|
||||
await redis.del(`task:list:${projectId}`)
|
||||
|
||||
// Al cambiar estado agente
|
||||
await redis.setex(`agent:${agentId}:status`, 30, status)
|
||||
```
|
||||
|
||||
## 7. Queue System (BullMQ)
|
||||
|
||||
### Colas:
|
||||
|
||||
```
|
||||
task-queue → Tareas pendientes de asignar
|
||||
deploy-queue → Deploys a ejecutar
|
||||
merge-queue → Merges programados
|
||||
cleanup-queue → Limpieza de preview envs antiguos
|
||||
```
|
||||
|
||||
### Workers:
|
||||
|
||||
```typescript
|
||||
// task-worker.ts
|
||||
taskQueue.process(async (job) => {
|
||||
const { taskId } = job.data
|
||||
// Notifica agentes disponibles vía MCP
|
||||
await notifyAgents({ taskId })
|
||||
})
|
||||
|
||||
// deploy-worker.ts
|
||||
deployQueue.process(async (job) => {
|
||||
const { taskId, environment } = job.data
|
||||
await k8sClient.createDeployment(...)
|
||||
})
|
||||
```
|
||||
|
||||
## Resumen de Protocolos
|
||||
|
||||
| Comunicación | Protocolo | Uso |
|
||||
|--------------|-----------|-----|
|
||||
| Frontend ↔ Backend | HTTP REST + WebSocket | CRUD + Real-time |
|
||||
| Backend ↔ MySQL | TCP/MySQL Protocol | Persistencia |
|
||||
| Backend ↔ Redis | RESP | Cache + PubSub |
|
||||
| Backend ↔ Gitea | HTTP REST | Git operations |
|
||||
| Backend ↔ K8s | HTTP + Kubernetes API | Orquestación |
|
||||
| Backend ↔ Agents | MCP (stdio/HTTP) | Herramientas |
|
||||
| Agents ↔ Gitea | Git Protocol (SSH) | Clone/Push |
|
||||
430
docs/01-arquitectura/modelo-datos.md
Normal file
430
docs/01-arquitectura/modelo-datos.md
Normal file
@@ -0,0 +1,430 @@
|
||||
# Modelo de Datos (MySQL)
|
||||
|
||||
## Diagrama ER
|
||||
|
||||
```
|
||||
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
||||
│ Projects │───────│ Tasks │───────│ Agents │
|
||||
└─────────────┘ 1:N └─────────────┘ N:1 └─────────────┘
|
||||
│ 1:N
|
||||
│
|
||||
┌────▼────────┐
|
||||
│ Questions │
|
||||
└─────────────┘
|
||||
|
||||
┌─────────────┐ ┌─────────────┐
|
||||
│ TaskGroups │───────│ Deploys │
|
||||
└─────────────┘ 1:N └─────────────┘
|
||||
```
|
||||
|
||||
## Schema SQL
|
||||
|
||||
### Tabla: projects
|
||||
|
||||
```sql
|
||||
CREATE TABLE projects (
|
||||
id VARCHAR(36) PRIMARY KEY,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
description TEXT,
|
||||
|
||||
-- Gitea integration
|
||||
gitea_repo_id INT,
|
||||
gitea_repo_url VARCHAR(512),
|
||||
gitea_owner VARCHAR(100),
|
||||
gitea_repo_name VARCHAR(100),
|
||||
default_branch VARCHAR(100) DEFAULT 'main',
|
||||
|
||||
-- Kubernetes
|
||||
k8s_namespace VARCHAR(63) NOT NULL UNIQUE,
|
||||
|
||||
-- Infrastructure config (JSON)
|
||||
docker_image VARCHAR(512),
|
||||
env_vars JSON,
|
||||
replicas INT DEFAULT 1,
|
||||
cpu_limit VARCHAR(20) DEFAULT '500m',
|
||||
memory_limit VARCHAR(20) DEFAULT '512Mi',
|
||||
|
||||
-- MCP config (JSON)
|
||||
mcp_tools JSON,
|
||||
mcp_permissions JSON,
|
||||
|
||||
-- Status
|
||||
status ENUM('active', 'paused', 'archived') DEFAULT 'active',
|
||||
|
||||
-- Timestamps
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
|
||||
INDEX idx_status (status),
|
||||
INDEX idx_k8s_namespace (k8s_namespace)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
```
|
||||
|
||||
### Tabla: tasks
|
||||
|
||||
```sql
|
||||
CREATE TABLE tasks (
|
||||
id VARCHAR(36) PRIMARY KEY,
|
||||
project_id VARCHAR(36) NOT NULL,
|
||||
|
||||
-- Task info
|
||||
title VARCHAR(255) NOT NULL,
|
||||
description TEXT,
|
||||
priority ENUM('low', 'medium', 'high', 'urgent') DEFAULT 'medium',
|
||||
|
||||
-- State machine
|
||||
state ENUM(
|
||||
'backlog',
|
||||
'in_progress',
|
||||
'needs_input',
|
||||
'ready_to_test',
|
||||
'approved',
|
||||
'staging',
|
||||
'production',
|
||||
'cancelled'
|
||||
) DEFAULT 'backlog',
|
||||
|
||||
-- Assignment
|
||||
assigned_agent_id VARCHAR(36),
|
||||
assigned_at TIMESTAMP NULL,
|
||||
|
||||
-- Git info
|
||||
branch_name VARCHAR(255),
|
||||
pr_number INT,
|
||||
pr_url VARCHAR(512),
|
||||
|
||||
-- Preview deployment
|
||||
preview_namespace VARCHAR(63),
|
||||
preview_url VARCHAR(512),
|
||||
preview_deployed_at TIMESTAMP NULL,
|
||||
|
||||
-- Metadata
|
||||
estimated_complexity ENUM('trivial', 'simple', 'medium', 'complex') DEFAULT 'medium',
|
||||
actual_duration_minutes INT,
|
||||
|
||||
-- Timestamps
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
started_at TIMESTAMP NULL,
|
||||
completed_at TIMESTAMP NULL,
|
||||
deployed_staging_at TIMESTAMP NULL,
|
||||
deployed_production_at TIMESTAMP NULL,
|
||||
|
||||
FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (assigned_agent_id) REFERENCES agents(id) ON DELETE SET NULL,
|
||||
|
||||
INDEX idx_project_state (project_id, state),
|
||||
INDEX idx_state (state),
|
||||
INDEX idx_assigned_agent (assigned_agent_id),
|
||||
INDEX idx_created_at (created_at)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
```
|
||||
|
||||
### Tabla: task_questions
|
||||
|
||||
```sql
|
||||
CREATE TABLE task_questions (
|
||||
id VARCHAR(36) PRIMARY KEY,
|
||||
task_id VARCHAR(36) NOT NULL,
|
||||
|
||||
-- Question
|
||||
question TEXT NOT NULL,
|
||||
context TEXT,
|
||||
asked_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
-- Response
|
||||
response TEXT,
|
||||
responded_at TIMESTAMP NULL,
|
||||
responded_by VARCHAR(36),
|
||||
|
||||
-- Status
|
||||
status ENUM('pending', 'answered', 'skipped') DEFAULT 'pending',
|
||||
|
||||
FOREIGN KEY (task_id) REFERENCES tasks(id) ON DELETE CASCADE,
|
||||
|
||||
INDEX idx_task_status (task_id, status),
|
||||
INDEX idx_status (status)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
```
|
||||
|
||||
### Tabla: agents
|
||||
|
||||
```sql
|
||||
CREATE TABLE agents (
|
||||
id VARCHAR(36) PRIMARY KEY,
|
||||
|
||||
-- K8s info
|
||||
pod_name VARCHAR(253) NOT NULL UNIQUE,
|
||||
k8s_namespace VARCHAR(63) DEFAULT 'agents',
|
||||
node_name VARCHAR(253),
|
||||
|
||||
-- Status
|
||||
status ENUM('idle', 'busy', 'error', 'offline', 'initializing') DEFAULT 'initializing',
|
||||
current_task_id VARCHAR(36),
|
||||
|
||||
-- Capabilities
|
||||
capabilities JSON, -- ['javascript', 'python', 'react', ...]
|
||||
max_concurrent_tasks INT DEFAULT 1,
|
||||
|
||||
-- Health
|
||||
last_heartbeat TIMESTAMP NULL,
|
||||
error_message TEXT,
|
||||
restarts_count INT DEFAULT 0,
|
||||
|
||||
-- Metrics
|
||||
tasks_completed INT DEFAULT 0,
|
||||
total_runtime_minutes INT DEFAULT 0,
|
||||
|
||||
-- Timestamps
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
|
||||
FOREIGN KEY (current_task_id) REFERENCES tasks(id) ON DELETE SET NULL,
|
||||
|
||||
INDEX idx_status (status),
|
||||
INDEX idx_pod_name (pod_name),
|
||||
INDEX idx_last_heartbeat (last_heartbeat)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
```
|
||||
|
||||
### Tabla: task_groups
|
||||
|
||||
```sql
|
||||
CREATE TABLE task_groups (
|
||||
id VARCHAR(36) PRIMARY KEY,
|
||||
project_id VARCHAR(36) NOT NULL,
|
||||
|
||||
-- Grouping
|
||||
task_ids JSON NOT NULL, -- ['task-id-1', 'task-id-2', ...]
|
||||
|
||||
-- Staging
|
||||
staging_branch VARCHAR(255),
|
||||
staging_pr_number INT,
|
||||
staging_pr_url VARCHAR(512),
|
||||
staging_deployed_at TIMESTAMP NULL,
|
||||
|
||||
-- Production
|
||||
production_deployed_at TIMESTAMP NULL,
|
||||
production_rollback_available BOOLEAN DEFAULT TRUE,
|
||||
|
||||
-- Status
|
||||
status ENUM('pending', 'staging', 'production', 'rolled_back') DEFAULT 'pending',
|
||||
|
||||
-- Metadata
|
||||
created_by VARCHAR(36),
|
||||
notes TEXT,
|
||||
|
||||
-- Timestamps
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
|
||||
FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,
|
||||
|
||||
INDEX idx_project_status (project_id, status),
|
||||
INDEX idx_status (status)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
```
|
||||
|
||||
### Tabla: deployments
|
||||
|
||||
```sql
|
||||
CREATE TABLE deployments (
|
||||
id VARCHAR(36) PRIMARY KEY,
|
||||
project_id VARCHAR(36) NOT NULL,
|
||||
task_group_id VARCHAR(36),
|
||||
|
||||
-- Deployment info
|
||||
environment ENUM('preview', 'staging', 'production') NOT NULL,
|
||||
deployment_type ENUM('manual', 'automatic', 'rollback') DEFAULT 'manual',
|
||||
|
||||
-- Git info
|
||||
branch VARCHAR(255),
|
||||
commit_hash VARCHAR(40),
|
||||
|
||||
-- K8s info
|
||||
k8s_namespace VARCHAR(63),
|
||||
k8s_deployment_name VARCHAR(253),
|
||||
image_tag VARCHAR(255),
|
||||
|
||||
-- Status
|
||||
status ENUM('pending', 'in_progress', 'completed', 'failed', 'rolled_back') DEFAULT 'pending',
|
||||
|
||||
-- Results
|
||||
url VARCHAR(512),
|
||||
error_message TEXT,
|
||||
logs TEXT,
|
||||
|
||||
-- Timing
|
||||
started_at TIMESTAMP NULL,
|
||||
completed_at TIMESTAMP NULL,
|
||||
duration_seconds INT,
|
||||
|
||||
-- Metadata
|
||||
triggered_by VARCHAR(36),
|
||||
|
||||
-- Timestamps
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (task_group_id) REFERENCES task_groups(id) ON DELETE SET NULL,
|
||||
|
||||
INDEX idx_project_env (project_id, environment),
|
||||
INDEX idx_status (status),
|
||||
INDEX idx_created_at (created_at)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
```
|
||||
|
||||
### Tabla: agent_logs
|
||||
|
||||
```sql
|
||||
CREATE TABLE agent_logs (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
agent_id VARCHAR(36) NOT NULL,
|
||||
task_id VARCHAR(36),
|
||||
|
||||
-- Log entry
|
||||
level ENUM('debug', 'info', 'warn', 'error') DEFAULT 'info',
|
||||
message TEXT NOT NULL,
|
||||
metadata JSON,
|
||||
|
||||
-- Timestamp
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
FOREIGN KEY (agent_id) REFERENCES agents(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (task_id) REFERENCES tasks(id) ON DELETE SET NULL,
|
||||
|
||||
INDEX idx_agent_created (agent_id, created_at),
|
||||
INDEX idx_task_created (task_id, created_at),
|
||||
INDEX idx_level (level)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
```
|
||||
|
||||
## Índices y Optimizaciones
|
||||
|
||||
### Índices Compuestos Importantes
|
||||
|
||||
```sql
|
||||
-- Búsqueda de tareas por proyecto y estado
|
||||
CREATE INDEX idx_tasks_project_state ON tasks(project_id, state, created_at);
|
||||
|
||||
-- Búsqueda de agentes disponibles
|
||||
CREATE INDEX idx_agents_available ON agents(status, last_heartbeat)
|
||||
WHERE status = 'idle';
|
||||
|
||||
-- Logs recientes por agente
|
||||
CREATE INDEX idx_agent_logs_recent ON agent_logs(agent_id, created_at DESC)
|
||||
USING BTREE;
|
||||
```
|
||||
|
||||
### Particionamiento (para logs)
|
||||
|
||||
```sql
|
||||
-- Particionar agent_logs por mes
|
||||
ALTER TABLE agent_logs PARTITION BY RANGE (YEAR(created_at) * 100 + MONTH(created_at)) (
|
||||
PARTITION p202601 VALUES LESS THAN (202602),
|
||||
PARTITION p202602 VALUES LESS THAN (202603),
|
||||
PARTITION p202603 VALUES LESS THAN (202604),
|
||||
-- ... auto-crear con script
|
||||
PARTITION p_future VALUES LESS THAN MAXVALUE
|
||||
);
|
||||
```
|
||||
|
||||
## Queries Comunes
|
||||
|
||||
### Obtener siguiente tarea disponible
|
||||
|
||||
```sql
|
||||
SELECT * FROM tasks
|
||||
WHERE state = 'backlog'
|
||||
AND project_id = ?
|
||||
ORDER BY
|
||||
priority DESC,
|
||||
created_at ASC
|
||||
LIMIT 1
|
||||
FOR UPDATE SKIP LOCKED;
|
||||
```
|
||||
|
||||
### Agentes disponibles
|
||||
|
||||
```sql
|
||||
SELECT * FROM agents
|
||||
WHERE status = 'idle'
|
||||
AND last_heartbeat > DATE_SUB(NOW(), INTERVAL 60 SECOND)
|
||||
ORDER BY tasks_completed ASC
|
||||
LIMIT 1;
|
||||
```
|
||||
|
||||
### Dashboard: Métricas de proyecto
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
COUNT(*) as total_tasks,
|
||||
SUM(CASE WHEN state = 'backlog' THEN 1 ELSE 0 END) as backlog,
|
||||
SUM(CASE WHEN state = 'in_progress' THEN 1 ELSE 0 END) as in_progress,
|
||||
SUM(CASE WHEN state = 'needs_input' THEN 1 ELSE 0 END) as needs_input,
|
||||
SUM(CASE WHEN state = 'ready_to_test' THEN 1 ELSE 0 END) as ready_to_test,
|
||||
SUM(CASE WHEN state = 'production' THEN 1 ELSE 0 END) as completed,
|
||||
AVG(actual_duration_minutes) as avg_duration
|
||||
FROM tasks
|
||||
WHERE project_id = ?;
|
||||
```
|
||||
|
||||
### Historial de deployments
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
d.*,
|
||||
tg.task_ids,
|
||||
COUNT(t.id) as tasks_count
|
||||
FROM deployments d
|
||||
LEFT JOIN task_groups tg ON d.task_group_id = tg.id
|
||||
LEFT JOIN tasks t ON JSON_CONTAINS(tg.task_ids, CONCAT('"', t.id, '"'))
|
||||
WHERE d.project_id = ?
|
||||
AND d.environment = 'production'
|
||||
GROUP BY d.id
|
||||
ORDER BY d.created_at DESC
|
||||
LIMIT 20;
|
||||
```
|
||||
|
||||
## Migraciones con Drizzle
|
||||
|
||||
```typescript
|
||||
// drizzle/schema.ts
|
||||
import { mysqlTable, varchar, text, timestamp, json, int, mysqlEnum } from 'drizzle-orm/mysql-core'
|
||||
|
||||
export const projects = mysqlTable('projects', {
|
||||
id: varchar('id', { length: 36 }).primaryKey(),
|
||||
name: varchar('name', { length: 255 }).notNull(),
|
||||
description: text('description'),
|
||||
giteaRepoId: int('gitea_repo_id'),
|
||||
giteaRepoUrl: varchar('gitea_repo_url', { length: 512 }),
|
||||
// ... resto campos
|
||||
createdAt: timestamp('created_at').defaultNow(),
|
||||
updatedAt: timestamp('updated_at').defaultNow().onUpdateNow(),
|
||||
})
|
||||
|
||||
export const tasks = mysqlTable('tasks', {
|
||||
id: varchar('id', { length: 36 }).primaryKey(),
|
||||
projectId: varchar('project_id', { length: 36 }).notNull().references(() => projects.id),
|
||||
title: varchar('title', { length: 255 }).notNull(),
|
||||
state: mysqlEnum('state', [
|
||||
'backlog', 'in_progress', 'needs_input',
|
||||
'ready_to_test', 'approved', 'staging', 'production', 'cancelled'
|
||||
]).default('backlog'),
|
||||
// ... resto campos
|
||||
})
|
||||
```
|
||||
|
||||
## Backup Strategy
|
||||
|
||||
```bash
|
||||
# Daily backup
|
||||
mysqldump -u root -p aiworker \
|
||||
--single-transaction \
|
||||
--quick \
|
||||
--lock-tables=false \
|
||||
> backup-$(date +%Y%m%d).sql
|
||||
|
||||
# Restore
|
||||
mysql -u root -p aiworker < backup-20260119.sql
|
||||
```
|
||||
140
docs/01-arquitectura/overview.md
Normal file
140
docs/01-arquitectura/overview.md
Normal file
@@ -0,0 +1,140 @@
|
||||
# Overview General - AiWorker
|
||||
|
||||
## Concepto
|
||||
|
||||
AiWorker es un sistema de orquestación de agentes IA que automatiza el ciclo completo de desarrollo de software mediante:
|
||||
|
||||
1. **Dashboard Web**: Interfaz central para gestionar proyectos y tareas
|
||||
2. **Consolas Web Persistentes**: Terminales web conectadas a pods de Claude Code en K8s
|
||||
3. **Kanban Board Inteligente**: Gestión visual de tareas con estados automáticos
|
||||
4. **Agentes Autónomos**: Claude Code trabajando en tareas asignadas
|
||||
5. **Deployments Automatizados**: Preview, staging y producción orquestados
|
||||
|
||||
## Arquitectura de Alto Nivel
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Dashboard Web │
|
||||
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
|
||||
│ │ Kanban │ │ Consolas │ │ Project │ │
|
||||
│ │ Board │ │ Web │ │ Manager │ │
|
||||
│ └─────────────┘ └─────────────┘ └─────────────┘ │
|
||||
└────────────────────────┬────────────────────────────────────────┘
|
||||
│ HTTP/WebSocket
|
||||
┌────────────────────────▼────────────────────────────────────────┐
|
||||
│ Backend (Bun + Express) │
|
||||
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
|
||||
│ │ API │ │ MCP │ │ Gitea │ │ K8s │ │
|
||||
│ │ Server │ │ Server │ │ Client │ │ Client │ │
|
||||
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
|
||||
└────────┬───────────────┬─────────────┬─────────────┬───────────┘
|
||||
│ │ │ │
|
||||
┌────▼────┐ ┌───▼────┐ ┌───▼────┐ ┌────▼─────┐
|
||||
│ MySQL │ │ Redis │ │ Gitea │ │ K8s │
|
||||
└─────────┘ └────────┘ └────────┘ └──────────┘
|
||||
│
|
||||
┌───────────────────────────────┘
|
||||
│
|
||||
┌──────────▼──────────────────────────────────────┐
|
||||
│ Kubernetes Cluster │
|
||||
│ ┌──────────────┐ ┌─────────────────────────┐ │
|
||||
│ │ Agents │ │ Project Namespaces │ │
|
||||
│ │ Namespace │ │ ├── dev │ │
|
||||
│ │ │ │ ├── preview/<task-id> │ │
|
||||
│ │ Claude Code │ │ ├── staging │ │
|
||||
│ │ Pods │ │ └── production │ │
|
||||
│ └──────────────┘ └─────────────────────────┘ │
|
||||
└─────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Componentes Principales
|
||||
|
||||
### 1. Dashboard Web (Frontend)
|
||||
- **Tecnología**: React 19.2 + TailwindCSS + Vite
|
||||
- **Funciones**:
|
||||
- Kanban board para gestión de tareas
|
||||
- Consolas web interactivas (xterm.js)
|
||||
- Gestión de proyectos
|
||||
- Monitoring en tiempo real
|
||||
|
||||
### 2. Backend API
|
||||
- **Tecnología**: Bun 1.3.6 + Express + TypeScript
|
||||
- **Funciones**:
|
||||
- API REST para frontend
|
||||
- MCP Server para agentes
|
||||
- Orquestación de tareas
|
||||
- Integración con Gitea y K8s
|
||||
|
||||
### 3. Base de Datos
|
||||
- **MySQL 8.0**: Almacenamiento persistente
|
||||
- **Redis**: Colas, cache, pub/sub
|
||||
|
||||
### 4. Gitea
|
||||
- **Servidor Git auto-alojado**
|
||||
- **API compatible con GitHub**
|
||||
- **Gestión de repos, branches, PRs**
|
||||
|
||||
### 5. Kubernetes Cluster
|
||||
- **Orquestación de contenedores**
|
||||
- **Namespaces por proyecto y entorno**
|
||||
- **Auto-scaling de agentes**
|
||||
|
||||
### 6. Claude Code Agents
|
||||
- **Pods persistentes en K8s**
|
||||
- **Conectados vía MCP Server**
|
||||
- **Workspace aislado por agente**
|
||||
|
||||
## Estados de Tareas
|
||||
|
||||
```
|
||||
Backlog → En Progreso → Necesita Respuestas
|
||||
↓
|
||||
Usuario responde
|
||||
↓
|
||||
┌───────────────┘
|
||||
↓
|
||||
Listo para Probar
|
||||
↓
|
||||
(Preview deploy)
|
||||
↓
|
||||
Aprobado
|
||||
↓
|
||||
Staging (merge grupal)
|
||||
↓
|
||||
Producción
|
||||
```
|
||||
|
||||
## Flujo de Trabajo Típico
|
||||
|
||||
1. **Usuario crea proyecto** → Sistema crea repo en Gitea + namespace en K8s
|
||||
2. **Usuario crea tareas** → Se añaden al backlog del kanban
|
||||
3. **Agente disponible** → Toma siguiente tarea vía MCP
|
||||
4. **Agente trabaja** → Clone, branch, código, commits
|
||||
5. **¿Necesita info?** → Cambia estado a "Necesita Respuestas"
|
||||
6. **Completa tarea** → Push + PR + deploy preview
|
||||
7. **Usuario prueba** → En ambiente preview aislado
|
||||
8. **Aprueba** → Marca para staging
|
||||
9. **Merge grupal** → Agrega 2-3 tareas + merge a staging
|
||||
10. **Deploy staging** → Tests automáticos
|
||||
11. **Deploy producción** → Aprobación final
|
||||
|
||||
## Ventajas del Sistema
|
||||
|
||||
✅ **Automatización completa**: Desde tarea hasta producción
|
||||
✅ **Aislamiento**: Cada tarea en su propio preview environment
|
||||
✅ **Trazabilidad**: Todo cambio vinculado a tarea y PR
|
||||
✅ **Escalabilidad**: Agentes auto-escalables en K8s
|
||||
✅ **Flexibilidad**: Agentes pueden pedir ayuda al usuario
|
||||
✅ **Control**: Usuario aprueba cada fase importante
|
||||
|
||||
## Seguridad
|
||||
|
||||
- Namespaces aislados en K8s
|
||||
- RBAC por agente
|
||||
- Secrets management
|
||||
- Network policies
|
||||
- Auditoría de acciones
|
||||
|
||||
## Próximos Pasos
|
||||
|
||||
Ver documentación específica de cada componente en las secciones correspondientes.
|
||||
208
docs/01-arquitectura/stack-tecnologico.md
Normal file
208
docs/01-arquitectura/stack-tecnologico.md
Normal file
@@ -0,0 +1,208 @@
|
||||
# Stack Tecnológico
|
||||
|
||||
## Frontend
|
||||
|
||||
### Core
|
||||
- **React 19.2**: Framework UI principal
|
||||
- **Vite**: Build tool y dev server
|
||||
- **TypeScript**: Type safety
|
||||
- **TailwindCSS 4.x**: Styling utility-first
|
||||
|
||||
### Librerías UI
|
||||
- **@dnd-kit/core**: Drag and drop para kanban
|
||||
- **xterm.js**: Emulador de terminal web
|
||||
- **lucide-react**: Iconos modernos
|
||||
- **react-hot-toast**: Notificaciones
|
||||
- **recharts**: Gráficas y métricas
|
||||
|
||||
### Estado y Data Fetching
|
||||
- **@tanstack/react-query**: Server state management
|
||||
- **zustand**: Client state management (ligero y simple)
|
||||
- **socket.io-client**: WebSocket para real-time
|
||||
|
||||
### Routing
|
||||
- **react-router-dom**: Navegación SPA
|
||||
|
||||
## Backend
|
||||
|
||||
### Core
|
||||
- **Bun 1.3.6**: Runtime JavaScript ultra-rápido
|
||||
- **Express**: Framework HTTP
|
||||
- **TypeScript**: Type safety
|
||||
|
||||
### Database
|
||||
- **MySQL 8.0**: Base de datos relacional principal
|
||||
- **mysql2**: Driver MySQL para Node.js
|
||||
- **Drizzle ORM**: ORM TypeScript-first moderno
|
||||
- Type-safe
|
||||
- Ligero
|
||||
- Excelente DX con Bun
|
||||
|
||||
### Cache y Colas
|
||||
- **Redis 7.x**: Cache y message broker
|
||||
- **BullMQ**: Sistema de colas robusto
|
||||
- **ioredis**: Cliente Redis
|
||||
|
||||
### Comunicación con Agentes
|
||||
- **@modelcontextprotocol/sdk**: SDK oficial MCP
|
||||
- **socket.io**: WebSocket server
|
||||
|
||||
### Integraciones
|
||||
- **@kubernetes/client-node**: Cliente oficial K8s
|
||||
- **octokit** (adaptado): Cliente API Gitea
|
||||
- **axios**: HTTP client
|
||||
|
||||
### Desarrollo
|
||||
- **tsx**: TypeScript execution
|
||||
- **nodemon**: Hot reload
|
||||
- **prettier**: Code formatting
|
||||
- **eslint**: Linting
|
||||
|
||||
## Infrastructure
|
||||
|
||||
### Containerización
|
||||
- **Docker 24.x**: Containerización
|
||||
- **Docker Compose**: Orquestación local
|
||||
|
||||
### Orchestration
|
||||
- **Kubernetes 1.28+**: Orquestación de contenedores
|
||||
- **kubectl**: CLI
|
||||
- **helm**: Package manager
|
||||
- **kustomize**: Configuration management
|
||||
|
||||
### Git Server
|
||||
- **Gitea latest**: Servidor Git auto-alojado
|
||||
- Ligero (~100MB)
|
||||
- API REST compatible GitHub
|
||||
- Webhooks nativos
|
||||
|
||||
### CI/CD y GitOps
|
||||
- **ArgoCD**: GitOps continuous delivery
|
||||
- **GitHub Actions** (o Gitea Actions): CI pipelines
|
||||
|
||||
### Monitoring y Logging
|
||||
- **Prometheus**: Métricas
|
||||
- **Grafana**: Visualización
|
||||
- **Loki**: Logs aggregation
|
||||
- **Jaeger**: Distributed tracing (opcional)
|
||||
|
||||
### Networking
|
||||
- **Nginx Ingress Controller**: Routing
|
||||
- **cert-manager**: TLS certificates
|
||||
|
||||
## Agentes
|
||||
|
||||
### Claude Code
|
||||
- **Claude Code CLI**: Herramienta oficial de Anthropic
|
||||
- **Model**: Claude Sonnet 4.5
|
||||
- **MCP Tools**: Comunicación con backend
|
||||
|
||||
## Development Tools
|
||||
|
||||
### Package Management
|
||||
- **bun**: Package manager principal
|
||||
- **npm**: Fallback para compatibilidad
|
||||
|
||||
### Testing
|
||||
- **Vitest**: Unit testing (compatible con Bun)
|
||||
- **@testing-library/react**: React testing
|
||||
- **Playwright**: E2E testing
|
||||
|
||||
### Code Quality
|
||||
- **TypeScript 5.x**: Type checking
|
||||
- **ESLint**: Linting
|
||||
- **Prettier**: Formatting
|
||||
- **husky**: Git hooks
|
||||
|
||||
## Versiones Específicas
|
||||
|
||||
```json
|
||||
{
|
||||
"frontend": {
|
||||
"react": "19.2.0",
|
||||
"vite": "^6.0.0",
|
||||
"typescript": "^5.6.0",
|
||||
"tailwindcss": "^4.0.0"
|
||||
},
|
||||
"backend": {
|
||||
"bun": "1.3.6",
|
||||
"express": "^4.19.0",
|
||||
"mysql2": "^3.11.0",
|
||||
"drizzle-orm": "^0.36.0",
|
||||
"bullmq": "^5.23.0",
|
||||
"@modelcontextprotocol/sdk": "^1.0.0"
|
||||
},
|
||||
"infrastructure": {
|
||||
"kubernetes": "1.28+",
|
||||
"docker": "24.0+",
|
||||
"gitea": "1.22+",
|
||||
"redis": "7.2+",
|
||||
"mysql": "8.0+"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Justificación de Tecnologías
|
||||
|
||||
### ¿Por qué Bun?
|
||||
- **Velocidad**: 3-4x más rápido que Node.js
|
||||
- **TypeScript nativo**: Sin configuración adicional
|
||||
- **APIs modernas**: Compatibilidad Web Standard
|
||||
- **Tooling integrado**: Bundler, test runner, package manager
|
||||
|
||||
### ¿Por qué MySQL?
|
||||
- **Madurez**: Batalla-probado en producción
|
||||
- **Rendimiento**: Excelente para lecturas/escrituras
|
||||
- **Transacciones**: ACID compliance
|
||||
- **Ecosistema**: Herramientas maduras (backup, replicación)
|
||||
|
||||
### ¿Por qué Drizzle ORM?
|
||||
- **Type-safety**: Inferencia total de tipos
|
||||
- **Performance**: Query builder sin overhead
|
||||
- **DX**: Migraciones automáticas
|
||||
- **Bun compatible**: Primera clase
|
||||
|
||||
### ¿Por qué Gitea?
|
||||
- **Ligero**: Binario único, bajo consumo
|
||||
- **Auto-alojado**: Control total
|
||||
- **API familiar**: Compatible con GitHub
|
||||
- **Simple**: Instalación en minutos
|
||||
|
||||
### ¿Por qué React 19.2 sin Next.js?
|
||||
- **Simplicidad**: SPA sin server-side complexity
|
||||
- **Control total**: Sin abstracciones extra
|
||||
- **Rendimiento**: Nuevo compilador React
|
||||
- **Features**: Transitions, Server Actions cliente-side
|
||||
|
||||
## Alternativas Consideradas
|
||||
|
||||
| Necesidad | Elegido | Alternativas | Razón |
|
||||
|-----------|---------|--------------|-------|
|
||||
| Runtime | Bun | Node, Deno | Velocidad + DX |
|
||||
| DB | MySQL | PostgreSQL, MongoDB | Familiaridad + Madurez |
|
||||
| ORM | Drizzle | Prisma, TypeORM | Type-safety + Performance |
|
||||
| Git | Gitea | GitLab, Gogs | Simplicidad + Features |
|
||||
| Frontend | React | Vue, Svelte | Ecosistema + React 19 |
|
||||
| Orchestration | K8s | Docker Swarm, Nomad | Industry standard |
|
||||
|
||||
## Dependencias Críticas
|
||||
|
||||
```bash
|
||||
# Backend
|
||||
bun add express mysql2 drizzle-orm ioredis bullmq
|
||||
bun add @modelcontextprotocol/sdk socket.io
|
||||
bun add @kubernetes/client-node axios
|
||||
|
||||
# Frontend
|
||||
bun add react@19.2.0 react-dom@19.2.0
|
||||
bun add @tanstack/react-query zustand
|
||||
bun add socket.io-client xterm
|
||||
bun add @dnd-kit/core react-router-dom
|
||||
```
|
||||
|
||||
## Roadmap Tecnológico
|
||||
|
||||
**Fase 1 (MVP)**: Stack actual
|
||||
**Fase 2**: Añadir Prometheus + Grafana
|
||||
**Fase 3**: Implementar tracing con Jaeger
|
||||
**Fase 4**: Multi-tenancy y sharding de DB
|
||||
Reference in New Issue
Block a user