chore: tasks iniciales

This commit is contained in:
2026-02-17 04:08:12 +00:00
parent 48080a66e7
commit 5ebc6e218d

722
tasks.json Normal file
View File

@@ -0,0 +1,722 @@
{
"meta": {
"proyecto": "PymesBot",
"repo_url": "https://gitea.cbcren.online/renato97",
"version": "1.0",
"creado": "2026-02-17",
"descripcion": "Cola de tareas para construcción automática de PymesBot por bots IA. Procesar en orden de sprint y prioridad. No saltar tareas con dependencias pendientes."
},
"tareas": [
{
"id": "P1-T01",
"proyecto": "pymesbot-backend",
"sprint": 1,
"prioridad": 1,
"titulo": "Crear estructura base del proyecto backend",
"descripcion": "Crear todos los archivos vacíos con la estructura de carpetas definida en la sección 6 del spec. Crear: requirements.txt con las dependencias exactas de la sección 11, Dockerfile del backend de la sección 11, .gitignore apropiado para Python/Docker.",
"archivo_destino": "pymesbot-backend/",
"archivos_a_crear": [
"pymesbot-backend/requirements.txt",
"pymesbot-backend/Dockerfile",
"pymesbot-backend/.gitignore",
"pymesbot-backend/backend/templates/.gitkeep",
"pymesbot-backend/data/uploads/.gitkeep"
],
"contexto_spec": "Secciones 6 y 11 de 01_PYMESBOT_PROJECT_SPEC.md",
"dependencias": [],
"status": "pending",
"intentos": 0,
"modelo_preferido": "minimax",
"modelo_usado": null,
"completada_el": null,
"notas_error": null
},
{
"id": "P1-T02",
"proyecto": "pymesbot-backend",
"sprint": 1,
"prioridad": 2,
"titulo": "Implementar db.py — helpers de SQLite",
"descripcion": "Crear pymesbot-backend/backend/db.py con: función get_db() que devuelve conexión aiosqlite, función init_db() que crea las tablas si no existen usando el schema completo de la sección 7, función get_config(clave) que lee de la tabla config. Usar aiosqlite para todas las operaciones. El path de la DB es /app/data/stock.db.",
"archivo_destino": "pymesbot-backend/backend/db.py",
"archivos_a_crear": [
"pymesbot-backend/backend/db.py"
],
"contexto_spec": "Sección 7 de 01_PYMESBOT_PROJECT_SPEC.md — esquema SQL completo con las 4 tablas: productos, ventas, promociones, config",
"dependencias": [
"P1-T01"
],
"status": "pending",
"intentos": 0,
"modelo_preferido": "glm",
"modelo_usado": null,
"completada_el": null,
"notas_error": null
},
{
"id": "P1-T03",
"proyecto": "pymesbot-backend",
"sprint": 1,
"prioridad": 3,
"titulo": "Implementar models.py — Pydantic models",
"descripcion": "Crear pymesbot-backend/backend/models.py con todos los modelos Pydantic necesarios para los endpoints: ProductoResponse, VentaConfirmarRequest, VentaConfirmarResponse, StockSearchResponse, ComboArmarRequest, ComboArmarResponse, PromoResponse, StatsResponse, ConfigUpdate. Basarse en los schemas JSON de la sección 8 del spec.",
"archivo_destino": "pymesbot-backend/backend/models.py",
"archivos_a_crear": [
"pymesbot-backend/backend/models.py"
],
"contexto_spec": "Sección 8 de 01_PYMESBOT_PROJECT_SPEC.md — todos los request/response JSON de cada endpoint",
"dependencias": [
"P1-T01"
],
"status": "pending",
"intentos": 0,
"modelo_preferido": "glm",
"modelo_usado": null,
"completada_el": null,
"notas_error": null
},
{
"id": "P1-T04",
"proyecto": "pymesbot-backend",
"sprint": 1,
"prioridad": 4,
"titulo": "Implementar auth.py — autenticación PIN y admin",
"descripcion": "Crear pymesbot-backend/backend/auth.py con: función verify_vendor_pin(pin) que compara con la config de la DB, función verify_admin_password(password), dependencia FastAPI get_current_vendor() para proteger rutas del chat, dependencia get_current_admin() para proteger rutas admin. Autenticación simple sin JWT — usar cookies de sesión o Basic Auth.",
"archivo_destino": "pymesbot-backend/backend/auth.py",
"archivos_a_crear": [
"pymesbot-backend/backend/auth.py"
],
"contexto_spec": "Sección 10 de 01_PYMESBOT_PROJECT_SPEC.md — Vista Vendedor: acceso con PIN 4 dígitos. Vista Admin: usuario admin + contraseña.",
"dependencias": [
"P1-T02"
],
"status": "pending",
"intentos": 0,
"modelo_preferido": "glm",
"modelo_usado": null,
"completada_el": null,
"notas_error": null
},
{
"id": "P1-T05",
"proyecto": "pymesbot-backend",
"sprint": 1,
"prioridad": 5,
"titulo": "Implementar tools.py — endpoint GET /stock/search",
"descripcion": "Crear pymesbot-backend/backend/tools.py con el router de stock. Implementar GET /stock/search con parámetros q (string) y limit (int, default 5). Lógica de búsqueda en 3 pasos: 1) LIKE exacto, 2) AND de palabras, 3) OR de palabras. Solo productos activos. Devolver formato exacto de la sección 8. Incluir campo sugerencias cuando no hay resultados.",
"archivo_destino": "pymesbot-backend/backend/tools.py",
"archivos_a_crear": [
"pymesbot-backend/backend/tools.py"
],
"contexto_spec": "Sección 8 de 01_PYMESBOT_PROJECT_SPEC.md — endpoint GET /stock/search con la lógica de búsqueda de 3 pasos y el formato de respuesta JSON exacto",
"dependencias": [
"P1-T02",
"P1-T03"
],
"status": "pending",
"intentos": 0,
"modelo_preferido": "minimax",
"modelo_usado": null,
"completada_el": null,
"notas_error": null
},
{
"id": "P1-T06",
"proyecto": "pymesbot-backend",
"sprint": 1,
"prioridad": 6,
"titulo": "Implementar tools.py — endpoint POST /venta/confirmar",
"descripcion": "Agregar al router de ventas en tools.py el endpoint POST /venta/confirmar. Validaciones obligatorias: producto existe y activo, cantidad > 0, stock >= cantidad. Si pasa: INSERT en ventas, UPDATE stock en productos. Devolver formato exacto de la sección 8 incluyendo stock_anterior y stock_nuevo.",
"archivo_destino": "pymesbot-backend/backend/tools.py",
"archivos_a_crear": [],
"contexto_spec": "Sección 8 de 01_PYMESBOT_PROJECT_SPEC.md — endpoint POST /venta/confirmar con todas las validaciones y el formato de respuesta",
"dependencias": [
"P1-T05"
],
"status": "pending",
"intentos": 0,
"modelo_preferido": "glm",
"modelo_usado": null,
"completada_el": null,
"notas_error": null
},
{
"id": "P1-T07",
"proyecto": "pymesbot-backend",
"sprint": 1,
"prioridad": 7,
"titulo": "Implementar tools.py — endpoint GET /health",
"descripcion": "Agregar endpoint GET /health al main.py. Devolver: {status: 'ok', negocio: nombre_negocio_de_config}. Este endpoint NO requiere autenticación. Es el que usa el healthcheck de Docker.",
"archivo_destino": "pymesbot-backend/backend/main.py",
"archivos_a_crear": [
"pymesbot-backend/backend/main.py"
],
"contexto_spec": "Sección 8 de 01_PYMESBOT_PROJECT_SPEC.md — /health endpoint. Sección 11 — healthcheck en docker-compose.",
"dependencias": [
"P1-T02",
"P1-T03",
"P1-T04",
"P1-T05"
],
"status": "pending",
"intentos": 0,
"modelo_preferido": "minimax",
"modelo_usado": null,
"completada_el": null,
"notas_error": null
},
{
"id": "P1-T08",
"proyecto": "pymesbot-backend",
"sprint": 1,
"prioridad": 8,
"titulo": "Implementar WebSocket /chat/ws/{session_id}",
"descripcion": "Agregar en main.py el endpoint WebSocket /chat/ws/{session_id}. El handler recibe mensajes del frontend, mantiene historial en memoria (dict session_id → lista de mensajes, máximo 20 turnos, expirar después de 30 min de inactividad). Por ahora el bot puede ser un echo simple o respuesta hardcodeada — la integración real con PicoClaw es P2-T01. Enviar {typing: true} al recibir, {msg: '...', typing: false} al responder.",
"archivo_destino": "pymesbot-backend/backend/main.py",
"archivos_a_crear": [],
"contexto_spec": "Sección 8 de 01_PYMESBOT_PROJECT_SPEC.md — WebSocket /chat/ws/{session_id} con el protocolo de mensajes exacto",
"dependencias": [
"P1-T07"
],
"status": "pending",
"intentos": 0,
"modelo_preferido": "minimax",
"modelo_usado": null,
"completada_el": null,
"notas_error": null
},
{
"id": "P1-T09",
"proyecto": "pymesbot-backend",
"sprint": 1,
"prioridad": 9,
"titulo": "Implementar parser de Excel/CSV para importar stock",
"descripcion": "Agregar en tools.py el endpoint POST /stock/importar. Aceptar archivos .xlsx y .csv. Detección automática de columnas case-insensitive: nombre/producto/descripcion → nombre, precio/precio_venta/price → precio, stock/cantidad/qty → stock (default 0), categoria/rubro/category → categoria (default 'general'), marca/brand → marca, codigo/ean/barcode → codigo. Modos: 'reemplazar' borra todo primero, 'actualizar' hace upsert. Devolver {importados, actualizados, errores, errores_detalle}.",
"archivo_destino": "pymesbot-backend/backend/tools.py",
"archivos_a_crear": [],
"contexto_spec": "Sección 8 de 01_PYMESBOT_PROJECT_SPEC.md — endpoint POST /stock/importar con la lógica de detección de columnas y los modos reemplazar/actualizar",
"dependencias": [
"P1-T05"
],
"status": "pending",
"intentos": 0,
"modelo_preferido": "glm",
"modelo_usado": null,
"completada_el": null,
"notas_error": null
},
{
"id": "P1-T10",
"proyecto": "pymesbot-backend",
"sprint": 1,
"prioridad": 10,
"titulo": "Crear template HTML base y vista vendedor (chat)",
"descripcion": "Crear pymesbot-backend/backend/templates/base.html con el layout base: navbar con nombre del negocio, CSS variables para colores, responsive. Crear templates/chat.html extendiendo base.html: layout dividido (chat izquierda + resumen del día derecha), área de mensajes del chat, input de texto + botón enviar, panel de resumen (ventas del día + alertas de stock bajo). El JS del chat conecta al WebSocket /chat/ws/{session_id} y maneja los eventos typing/msg.",
"archivo_destino": "pymesbot-backend/backend/templates/",
"archivos_a_crear": [
"pymesbot-backend/backend/templates/base.html",
"pymesbot-backend/backend/templates/chat.html"
],
"contexto_spec": "Sección 10 de 01_PYMESBOT_PROJECT_SPEC.md — Vista Vendedor con el layout ASCII y las características detalladas del chat",
"dependencias": [
"P1-T08"
],
"status": "pending",
"intentos": 0,
"modelo_preferido": "minimax",
"modelo_usado": null,
"completada_el": null,
"notas_error": null
},
{
"id": "P1-T11",
"proyecto": "pymesbot-backend",
"sprint": 1,
"prioridad": 11,
"titulo": "Crear dashboard.py y vista admin básica",
"descripcion": "Crear pymesbot-backend/backend/dashboard.py con las rutas del panel admin. Ruta GET /admin sirve el template admin.html con autenticación. La vista admin básica solo necesita: sección de estadísticas del día (llamar a /stats/ventas?periodo=hoy) y sección de upload de Excel (formulario que llama a POST /stock/importar). Las secciones avanzadas (promociones, historial) son del sprint 2.",
"archivo_destino": "pymesbot-backend/backend/dashboard.py",
"archivos_a_crear": [
"pymesbot-backend/backend/dashboard.py",
"pymesbot-backend/backend/templates/admin.html"
],
"contexto_spec": "Sección 10 de 01_PYMESBOT_PROJECT_SPEC.md — Vista Dueño/Admin, primeras dos secciones: Dashboard principal y Gestión de stock",
"dependencias": [
"P1-T04",
"P1-T10"
],
"status": "pending",
"intentos": 0,
"modelo_preferido": "minimax",
"modelo_usado": null,
"completada_el": null,
"notas_error": null
},
{
"id": "P1-T12",
"proyecto": "pymesbot-backend",
"sprint": 1,
"prioridad": 12,
"titulo": "Implementar GET /stats/ventas",
"descripcion": "Agregar endpoint GET /stats/ventas en tools.py con parámetro periodo ('hoy'|'semana'|'mes'). Calcular: total_ventas (count), total_pesos (sum), ticket_promedio, top 5 productos más vendidos con cantidad y total, comparación con período anterior (misma duración hacia atrás). Devolver formato exacto de la sección 8.",
"archivo_destino": "pymesbot-backend/backend/tools.py",
"archivos_a_crear": [],
"contexto_spec": "Sección 8 de 01_PYMESBOT_PROJECT_SPEC.md — endpoint GET /stats/ventas con el formato de respuesta JSON completo",
"dependencias": [
"P1-T06"
],
"status": "pending",
"intentos": 0,
"modelo_preferido": "glm",
"modelo_usado": null,
"completada_el": null,
"notas_error": null
},
{
"id": "P1-T13",
"proyecto": "pymesbot-backend",
"sprint": 1,
"prioridad": 13,
"titulo": "Crear docker-compose.yml template del cliente",
"descripcion": "Crear pymesbot-backend/docker-compose.template.yml con el docker-compose del cliente según la sección 11 del spec. También crear el schema.sql con el SQL completo de la sección 7 para inicialización de la DB.",
"archivo_destino": "pymesbot-backend/",
"archivos_a_crear": [
"pymesbot-backend/docker-compose.template.yml",
"pymesbot-backend/schema.sql"
],
"contexto_spec": "Secciones 7 y 11 de 01_PYMESBOT_PROJECT_SPEC.md — docker-compose completo con healthcheck y schema SQL completo con índices e inserts iniciales",
"dependencias": [
"P1-T01"
],
"status": "pending",
"intentos": 0,
"modelo_preferido": "glm",
"modelo_usado": null,
"completada_el": null,
"notas_error": null
},
{
"id": "P2-T01",
"proyecto": "pymesbot-backend",
"sprint": 2,
"prioridad": 1,
"titulo": "Integrar PicoClaw en el WebSocket de chat",
"descripcion": "Reemplazar el echo del WebSocket por la integración real con PicoClaw. El backend llama internamente al proceso PicoClaw pasándole: el historial de conversación, el system prompt desde la config de la DB, las 4 herramientas definidas en la sección 9. Cuando PicoClaw llama una herramienta, el backend ejecuta el endpoint correspondiente (/stock/search, /venta/confirmar, /combo/armar, /promo/activas) y devuelve el resultado a PicoClaw. El formato del system prompt es el de la sección 9.",
"archivo_destino": "pymesbot-backend/backend/main.py",
"archivos_a_crear": [
"pymesbot-backend/backend/picoclaw_bridge.py"
],
"contexto_spec": "Sección 9 de 01_PYMESBOT_PROJECT_SPEC.md — config completa de PicoClaw, system prompt, y las 4 herramientas con sus schemas JSON",
"dependencias": [
"P1-T08",
"P1-T05",
"P1-T06"
],
"status": "pending",
"intentos": 0,
"modelo_preferido": "glm",
"modelo_usado": null,
"completada_el": null,
"notas_error": null
},
{
"id": "P2-T02",
"proyecto": "pymesbot-backend",
"sprint": 2,
"prioridad": 2,
"titulo": "Implementar POST /combo/armar",
"descripcion": "Crear endpoint POST /combo/armar en tools.py. Recibe presupuesto (required), edad (optional int), genero (optional: 'nena'|'neno'|null). Lógica: filtrar productos por categorías configuradas en config combo_categorias y stock > 0. Aplicar criterios de edad: <=6 = inicial, 7-10 = primaria, 11-13 = primaria sup, >=14 = secundaria. Aplicar preferencia de género en nombres/colores. Ordenar por esencialidad hardcodeada. Armar combo hasta 95% del presupuesto. Devolver formato exacto de sección 8 incluyendo campo incluido y esencial por producto.",
"archivo_destino": "pymesbot-backend/backend/tools.py",
"archivos_a_crear": [],
"contexto_spec": "Sección 8 de 01_PYMESBOT_PROJECT_SPEC.md — endpoint POST /combo/armar con toda la lógica de edad, género y armado hasta el 95% del presupuesto",
"dependencias": [
"P1-T05"
],
"status": "pending",
"intentos": 0,
"modelo_preferido": "minimax",
"modelo_usado": null,
"completada_el": null,
"notas_error": null
},
{
"id": "P2-T03",
"proyecto": "pymesbot-backend",
"sprint": 2,
"prioridad": 3,
"titulo": "Implementar endpoints de promociones",
"descripcion": "Agregar en tools.py: GET /promo/activas (devuelve promos donde activa=1 y fecha_fin >= hoy o fecha_fin es null), POST /promo/crear (solo admin, valida body con Pydantic, inserta en DB), PUT /promo/{id}/toggle (activa/desactiva). Aplicar promociones activas automáticamente en /stock/search: si hay promo para el producto, incluir campo promo_activa en la respuesta.",
"archivo_destino": "pymesbot-backend/backend/tools.py",
"archivos_a_crear": [],
"contexto_spec": "Sección 8 de 01_PYMESBOT_PROJECT_SPEC.md — endpoints GET /promo/activas y POST /promo/crear con los formatos JSON",
"dependencias": [
"P1-T05",
"P1-T04"
],
"status": "pending",
"intentos": 0,
"modelo_preferido": "glm",
"modelo_usado": null,
"completada_el": null,
"notas_error": null
},
{
"id": "P2-T04",
"proyecto": "pymesbot-backend",
"sprint": 2,
"prioridad": 4,
"titulo": "Implementar GET /stock/alertas y GET /venta/historial",
"descripcion": "Agregar en tools.py: GET /stock/alertas que devuelve productos con stock < alerta_stock_minimo de la config. GET /venta/historial con filtros fecha_desde, fecha_hasta, producto_id, vendedor, limit (max 1000), offset. JOIN con productos para incluir nombre del producto en cada venta. Devolver suma_total del período.",
"archivo_destino": "pymesbot-backend/backend/tools.py",
"archivos_a_crear": [],
"contexto_spec": "Sección 8 de 01_PYMESBOT_PROJECT_SPEC.md — endpoints GET /stock/alertas y GET /venta/historial",
"dependencias": [
"P1-T06"
],
"status": "pending",
"intentos": 0,
"modelo_preferido": "glm",
"modelo_usado": null,
"completada_el": null,
"notas_error": null
},
{
"id": "P2-T05",
"proyecto": "pymesbot-backend",
"sprint": 2,
"prioridad": 5,
"titulo": "Completar vista admin — promociones e historial",
"descripcion": "Agregar a admin.html las secciones de Promociones e Historial de ventas. Promociones: lista con toggle activo/inactivo, formulario de nueva promo con todos los campos. Historial: tabla con filtros de fecha (date picker nativo HTML), botón exportar CSV que llama al backend. Agregar sección Configuración: formulario para cambiar PIN del vendedor, contraseña admin, nombre del negocio, umbral de alertas.",
"archivo_destino": "pymesbot-backend/backend/templates/admin.html",
"archivos_a_crear": [],
"contexto_spec": "Sección 10 de 01_PYMESBOT_PROJECT_SPEC.md — Vista Admin, secciones Promociones, Historial de ventas y Configuración",
"dependencias": [
"P1-T11",
"P2-T03",
"P2-T04"
],
"status": "pending",
"intentos": 0,
"modelo_preferido": "minimax",
"modelo_usado": null,
"completada_el": null,
"notas_error": null
},
{
"id": "P2-T06",
"proyecto": "pymesbot-backend",
"sprint": 2,
"prioridad": 6,
"titulo": "Hacer la UI responsive para tablet y móvil",
"descripcion": "Revisar base.html, chat.html y admin.html para que funcionen bien en pantallas desde 768px. En chat.html móvil: el panel de resumen se colapsa con un botón. En admin.html móvil: las tablas hacen scroll horizontal. Usar media queries CSS, sin frameworks. Testear mentalmente con 768px, 1024px y 1280px de ancho.",
"archivo_destino": "pymesbot-backend/backend/templates/",
"archivos_a_crear": [],
"contexto_spec": "Sección 10 de 01_PYMESBOT_PROJECT_SPEC.md — Consideraciones de diseño: funcionar en tablet 10\" y PC de escritorio",
"dependencias": [
"P1-T10",
"P1-T11",
"P2-T05"
],
"status": "pending",
"intentos": 0,
"modelo_preferido": "minimax",
"modelo_usado": null,
"completada_el": null,
"notas_error": null
},
{
"id": "I1-T01",
"proyecto": "pymesbot-installer",
"sprint": 1,
"prioridad": 1,
"titulo": "Crear estructura base del proyecto installer",
"descripcion": "Crear la estructura de carpetas completa del instalador según la sección 3 del spec del instalador. Crear: Dockerfile, .dockerignore, requirements.txt con las dependencias de la sección 4, archivos __init__.py vacíos en app/. NO implementar lógica aún, solo la estructura.",
"archivo_destino": "pymesbot-installer/",
"archivos_a_crear": [
"pymesbot-installer/Dockerfile",
"pymesbot-installer/.dockerignore",
"pymesbot-installer/requirements.txt",
"pymesbot-installer/app/__init__.py",
"pymesbot-installer/static/.gitkeep"
],
"contexto_spec": "Secciones 3, 4 y 5 de 02_PYMESBOT_INSTALLER_SPEC.md — estructura de archivos, stack y Dockerfile completo",
"dependencias": [],
"status": "pending",
"intentos": 0,
"modelo_preferido": "minimax",
"modelo_usado": null,
"completada_el": null,
"notas_error": null
},
{
"id": "I1-T02",
"proyecto": "pymesbot-installer",
"sprint": 1,
"prioridad": 2,
"titulo": "Implementar state.py y security.py",
"descripcion": "Crear app/state.py con las funciones save_session, get_session, clear_session exactamente como están definidas en la sección 13 del spec. SESSION_TIMEOUT = 1800. Crear app/security.py con: generación del INSTALL_TOKEN al importar el módulo (secrets.token_urlsafe(16)), función async validar_sudo(password) que ejecuta 'echo PASSWORD | sudo -S whoami' y devuelve (bool, str). Manejar los 3 casos de error: incorrect password, not in sudoers, otro error.",
"archivo_destino": "pymesbot-installer/app/",
"archivos_a_crear": [
"pymesbot-installer/app/state.py",
"pymesbot-installer/app/security.py"
],
"contexto_spec": "Sección 13 de 02_PYMESBOT_INSTALLER_SPEC.md — código exacto de state.py y security.py",
"dependencias": [
"I1-T01"
],
"status": "pending",
"intentos": 0,
"modelo_preferido": "glm",
"modelo_usado": null,
"completada_el": null,
"notas_error": null
},
{
"id": "I1-T03",
"proyecto": "pymesbot-installer",
"sprint": 1,
"prioridad": 3,
"titulo": "Implementar detect.py — detección del entorno",
"descripcion": "Crear app/detect.py con: función async run_cmd(cmd, timeout) exactamente como está en la sección 6, dataclasses ComponentStatus/ClienteExistente/DetectionResult, función async detectar_entorno() que verifica en orden: Docker (docker --version), Nginx (nginx -v 2>&1), Certbot (certbot --version), /opt/pymesbot (os.path.exists), red pymesbot_net (docker network ls). Listar clientes leyendo subdirectorios de /opt/pymesbot excluyendo nginx/scripts/archivos. Para cada cliente leer su .env. Determinar modo A o B. Calcular siguiente puerto disponible desde 8200.",
"archivo_destino": "pymesbot-installer/app/detect.py",
"archivos_a_crear": [
"pymesbot-installer/app/detect.py"
],
"contexto_spec": "Sección 6 completa de 02_PYMESBOT_INSTALLER_SPEC.md — todas las funciones, dataclasses y lógica de detección",
"dependencias": [
"I1-T01"
],
"status": "pending",
"intentos": 0,
"modelo_preferido": "minimax",
"modelo_usado": null,
"completada_el": null,
"notas_error": null
},
{
"id": "I1-T04",
"proyecto": "pymesbot-installer",
"sprint": 1,
"prioridad": 4,
"titulo": "Implementar main.py — FastAPI esqueleto + token de seguridad",
"descripcion": "Crear app/main.py con: FastAPI app, evento startup que imprime el token en la terminal (formato exacto de la sección 10), dependencia verificar_token que revisa query param o cookie, ruta GET /install que verifica token y sirve static/index.html, ruta GET /install/detect que llama detectar_entorno() y devuelve JSON, ruta POST /install/validate-sudo, ruta POST /install/check-slug con regex validación, ruta POST /install/start. Sin WebSocket aún (eso es I1-T06).",
"archivo_destino": "pymesbot-installer/app/main.py",
"archivos_a_crear": [
"pymesbot-installer/app/main.py"
],
"contexto_spec": "Sección 10 de 02_PYMESBOT_INSTALLER_SPEC.md — código completo de main.py con todas las rutas excepto el WebSocket",
"dependencias": [
"I1-T02",
"I1-T03"
],
"status": "pending",
"intentos": 0,
"modelo_preferido": "minimax",
"modelo_usado": null,
"completada_el": null,
"notas_error": null
},
{
"id": "I1-T05",
"proyecto": "pymesbot-installer",
"sprint": 1,
"prioridad": 5,
"titulo": "Crear el wizard HTML completo (pasos 0 a 6)",
"descripcion": "Crear static/index.html con el wizard completo de 6 pasos. Diseño oscuro con la paleta de colores exacta de la sección 11: --bg #080E1A, --accent #00D4FF, --accent2 #00FF9D. Fuentes: Space Grotesk (body) + IBM Plex Mono (código/slugs). Layout: header + sidebar con pasos + panel de contenido. Los 6 pasos con toda la lógica JS: auto-detect al cargar, formularios con validación, auto-generación del slug (función nombreASlug de la sección 11), check de slug disponible al perder el foco, checkbox de confirmación habilita botón. Por ahora el paso 5 (progreso) puede ser mock — el WebSocket real es I1-T06.",
"archivo_destino": "pymesbot-installer/static/index.html",
"archivos_a_crear": [
"pymesbot-installer/static/index.html",
"pymesbot-installer/static/style.css",
"pymesbot-installer/static/wizard.js"
],
"contexto_spec": "Sección 11 completa de 02_PYMESBOT_INSTALLER_SPEC.md — paleta de colores, fuentes, layout, los 6 pasos con todos los campos y lógica JS",
"dependencias": [
"I1-T04"
],
"status": "pending",
"intentos": 0,
"modelo_preferido": "minimax",
"modelo_usado": null,
"completada_el": null,
"notas_error": null
},
{
"id": "I1-T06",
"proyecto": "pymesbot-installer",
"sprint": 1,
"prioridad": 6,
"titulo": "Implementar WebSocket /install/ws/{session_id} en main.py",
"descripcion": "Agregar a main.py el endpoint WebSocket /install/ws/{session_id} exactamente como está en la sección 10. El handler recupera la sesión, determina el modo (A o B), llama instalar_infraestructura si es modo A, luego llama setup_cliente. Usa progress_callback para enviar eventos. Envía evento 'done' al finalizar con url y credentials. En caso de excepción: intenta rollback y cierra el WebSocket.",
"archivo_destino": "pymesbot-installer/app/main.py",
"archivos_a_crear": [],
"contexto_spec": "Sección 10 de 02_PYMESBOT_INSTALLER_SPEC.md — código completo del WebSocket handler",
"dependencias": [
"I1-T04",
"I1-T05"
],
"status": "pending",
"intentos": 0,
"modelo_preferido": "glm",
"modelo_usado": null,
"completada_el": null,
"notas_error": null
},
{
"id": "I2-T01",
"proyecto": "pymesbot-installer",
"sprint": 2,
"prioridad": 1,
"titulo": "Implementar templates_engine.py",
"descripcion": "Crear app/templates_engine.py con las 4 funciones: generar_env_cliente, generar_docker_compose_cliente, generar_picoclaw_config, generar_nginx_conf, más la función escribir_archivo. Crear los 4 archivos Jinja2 en app/config_templates/ con el contenido exacto de la sección 12: env_client.j2, docker-compose.client.yml.j2, picoclaw_config.json.j2 (con el system prompt completo de la sección 9 del spec principal), nginx_site.conf.j2. También crear config_templates/schema.sql con el SQL completo de la sección 7 del spec principal.",
"archivo_destino": "pymesbot-installer/app/",
"archivos_a_crear": [
"pymesbot-installer/app/templates_engine.py",
"pymesbot-installer/app/config_templates/env_client.j2",
"pymesbot-installer/app/config_templates/docker-compose.client.yml.j2",
"pymesbot-installer/app/config_templates/picoclaw_config.json.j2",
"pymesbot-installer/app/config_templates/nginx_site.conf.j2",
"pymesbot-installer/app/config_templates/schema.sql"
],
"contexto_spec": "Sección 9 de 02_PYMESBOT_INSTALLER_SPEC.md — código de templates_engine.py. Sección 12 — contenido de los 4 templates Jinja2. Sección 7 de 01_PYMESBOT_PROJECT_SPEC.md — schema SQL completo.",
"dependencias": [
"I1-T01"
],
"status": "pending",
"intentos": 0,
"modelo_preferido": "minimax",
"modelo_usado": null,
"completada_el": null,
"notas_error": null
},
{
"id": "I2-T02",
"proyecto": "pymesbot-installer",
"sprint": 2,
"prioridad": 2,
"titulo": "Implementar client_setup.py — alta de cliente (pasos C1 a C9)",
"descripcion": "Crear app/client_setup.py con: dataclass ClientConfig, función async setup_cliente(config, progress_callback) con los 9 pasos (C1 mkdir, C2 generar configs, C3 init DB con sqlite3, C4 copiar backend, C5 nginx conf + reload, C6 certbot SSL con manejo de errores específicos de DNS y rate limit, C7 docker compose up, C8 health check con 5 reintentos de 10s, C9 guardar credentials.json), función async rollback_cliente(slug, sudo_password, progress_callback). Cada paso envía step_start al inicio y step_done o step_error al terminar.",
"archivo_destino": "pymesbot-installer/app/client_setup.py",
"archivos_a_crear": [
"pymesbot-installer/app/client_setup.py"
],
"contexto_spec": "Sección 8 completa de 02_PYMESBOT_INSTALLER_SPEC.md — todos los pasos C1 a C9, los comandos exactos, los timeouts, los mensajes de error específicos de certbot, y la función de rollback",
"dependencias": [
"I2-T01",
"I1-T02"
],
"status": "pending",
"intentos": 0,
"modelo_preferido": "glm",
"modelo_usado": null,
"completada_el": null,
"notas_error": null
},
{
"id": "I2-T03",
"proyecto": "pymesbot-installer",
"sprint": 2,
"prioridad": 3,
"titulo": "Implementar installer.py — instalación de infraestructura base (Modo A)",
"descripcion": "Crear app/installer.py con función async instalar_infraestructura(config, progress_callback) con los 5 pasos: A1 apt-get update (timeout 120s), A2 apt-get install nginx certbot python3-certbot-nginx (timeout 300s), A3 mkdir /opt/pymesbot (idempotente), A4 docker network create pymesbot_net (manejar error 'already exists' como éxito), A5 verificar nginx base config + systemctl enable + start. Cada paso con step_start/step_done/step_error y el hint apropiado.",
"archivo_destino": "pymesbot-installer/app/installer.py",
"archivos_a_crear": [
"pymesbot-installer/app/installer.py"
],
"contexto_spec": "Sección 7 completa de 02_PYMESBOT_INSTALLER_SPEC.md — los 5 pasos A1 a A5 con comandos exactos, timeouts y mensajes de hint",
"dependencias": [
"I1-T02",
"I2-T01"
],
"status": "pending",
"intentos": 0,
"modelo_preferido": "glm",
"modelo_usado": null,
"completada_el": null,
"notas_error": null
},
{
"id": "I2-T04",
"proyecto": "pymesbot-installer",
"sprint": 2,
"prioridad": 4,
"titulo": "Conectar el wizard con el backend real (reemplazar mocks)",
"descripcion": "Actualizar wizard.js para conectar todos los pasos con las APIs reales: paso 0 llama GET /install/detect y renderiza las tarjetas con datos reales, paso 1 llama POST /install/validate-sudo, paso 3 llama POST /install/check-slug al perder el foco del slug, paso 4 llama POST /install/start al hacer click en Ejecutar, paso 5 conecta WebSocket real y maneja todos los eventos (step_start, output, step_done, step_error, done, fatal_error). Expandir/colapsar output del paso al hacer click en 'ver detalles'.",
"archivo_destino": "pymesbot-installer/static/wizard.js",
"archivos_a_crear": [],
"contexto_spec": "Secciones 10 y 11 de 02_PYMESBOT_INSTALLER_SPEC.md — las APIs de cada paso y el manejo de eventos WebSocket en el paso 5",
"dependencias": [
"I1-T05",
"I1-T06",
"I2-T02",
"I2-T03"
],
"status": "pending",
"intentos": 0,
"modelo_preferido": "minimax",
"modelo_usado": null,
"completada_el": null,
"notas_error": null
},
{
"id": "I2-T05",
"proyecto": "pymesbot-installer",
"sprint": 2,
"prioridad": 5,
"titulo": "Crear docker-compose.yml del instalador (el que descarga el operador)",
"descripcion": "Crear el docker-compose.yml raíz del instalador exactamente como está en la sección 5 del spec. Con los 4 volúmenes críticos: /var/run/docker.sock, /usr/bin/docker:ro, /opt/pymesbot, /etc/nginx. Puerto 80:8000. restart: 'no'. Crear también un README.md con instrucciones de uso de 4 pasos: curl -O, docker compose up -d, abrir URL con token, docker compose down.",
"archivo_destino": "pymesbot-installer/",
"archivos_a_crear": [
"pymesbot-installer/docker-compose.yml",
"pymesbot-installer/README.md"
],
"contexto_spec": "Secciones 2 y 5 de 02_PYMESBOT_INSTALLER_SPEC.md — el docker-compose.yml completo con todos los volúmenes y el README de uso",
"dependencias": [
"I1-T01"
],
"status": "pending",
"intentos": 0,
"modelo_preferido": "glm",
"modelo_usado": null,
"completada_el": null,
"notas_error": null
}
],
"key_pool": [
{
"id": "glm_1",
"servicio": "glm",
"api_base": "https://api.z.ai/api/paas/v4",
"modelo": "glm-4.7",
"key": "GLM_KEY_1",
"ultimo_uso": null,
"cooldown_segundos": 20,
"disponible": true,
"usos_hoy": 0
},
{
"id": "minimax_1",
"servicio": "minimax",
"api_base": "https://api.minimax.io/v1",
"modelo": "MiniMax-M2.5",
"key": "MINIMAX_KEY_1",
"ultimo_uso": null,
"cooldown_segundos": 20,
"disponible": true,
"usos_hoy": 0
}
],
"config": {
"repo_backend": "https://gitea.cbcren.online/renato97/pymesbot-backend",
"repo_installer": "https://gitea.cbcren.online/renato97/pymesbot-installer",
"branch": "main",
"commit_author_name": "PymesBot Bot",
"commit_author_email": "bot@rvconsultas.com",
"max_intentos_por_tarea": 3,
"espera_entre_reintentos_segundos": 120,
"loop_interval_segundos": 300,
"spec_backend_path": "/repo/specs/01_PYMESBOT_PROJECT_SPEC.md",
"spec_installer_path": "/repo/specs/02_PYMESBOT_INSTALLER_SPEC.md",
"dominio_demo": "demo2.cbcren.online",
"dominio_n8n": "n8n.cbcren.online"
}
}