{"id":"cs-1782441325767-yx4a1vhh","status":"done","createdAt":1782441325767,"finishedAt":1782441365273,"meta":{"projectName":"ALimpiezas","projectPath":"C:\\xampp\\htdocs\\ALimpiezas","messagePreview":"Consolida el CONOCIMIENTO del proyecto para uso futuro del agente.\n\nEntrega en Markdown:\n1. **Resumen ejecutivo** (5 lín","phaseId":"knowledge"},"events":[{"event":"status","data":{"text":"Modo completo — hasta 80 herramientas, usa solo las necesarias"},"at":1782441325772},{"event":"status","data":{"text":"Agente"},"at":1782441327287},{"event":"agent","data":{"agentId":"agent-cfab63c5-0604-4c27-bc50-a4c2ce83d7e9","projectPath":"C:\\xampp\\htdocs\\ALimpiezas"},"at":1782441327287},{"event":"changes","data":{"sessionId":"cs-1782441325772-pjwvgf","pending":0},"at":1782441327287},{"event":"status","data":{"text":"Procesando…"},"at":1782441329270},{"event":"tool_activity","data":{"activity":{"id":"tool_2da9bfe8-ff41-49ed-9b82-28758acb975","name":"glob","status":"running","summary":"glob: ","detail":"","at":"2026-06-26T02:35:34.328Z"}},"at":1782441334328},{"event":"tool_activity","data":{"activity":{"id":"tool_7bda4599-4321-4402-94bb-20379e2fa44","name":"read","status":"running","summary":"read: C:\\xampp\\htdocs\\ALimpiezas\\composer.json","detail":"","at":"2026-06-26T02:35:34.330Z"}},"at":1782441334330},{"event":"tool_activity","data":{"activity":{"id":"tool_35b574a6-fca8-48ca-b7e1-9ded2004aa9","name":"glob","status":"running","summary":"glob: ","detail":"","at":"2026-06-26T02:35:34.414Z"}},"at":1782441334414},{"event":"tool_activity","data":{"activity":{"id":"tool_55590e3f-4c04-4a89-8e51-018a8f5ef68","name":"glob","status":"running","summary":"glob: ","detail":"","at":"2026-06-26T02:35:34.479Z"}},"at":1782441334479},{"event":"tool_activity","data":{"activity":{"id":"tool_7bda4599-4321-4402-94bb-20379e2fa44","name":"read","status":"completed","summary":"read: C:\\xampp\\htdocs\\ALimpiezas\\composer.json","detail":"","at":"2026-06-26T02:35:34.510Z"}},"at":1782441334510},{"event":"text","data":{"chunk":"Consolidando el conocimiento del proyecto leyendo archivos clave sin escanear Core/Dinamic en profundidad.\n"},"at":1782441365273},{"event":"tool_activity","data":{"activity":{"id":"tool_f5e244d3-71f9-45c7-8105-25aed470d79","name":"glob","status":"running","summary":"glob: ","detail":"","at":"2026-06-26T02:35:34.563Z"}},"at":1782441334563},{"event":"tool_activity","data":{"activity":{"id":"tool_35b574a6-fca8-48ca-b7e1-9ded2004aa9","name":"glob","status":"completed","summary":"glob: ","detail":"","at":"2026-06-26T02:35:34.621Z"}},"at":1782441334621},{"event":"tool_activity","data":{"activity":{"id":"tool_55590e3f-4c04-4a89-8e51-018a8f5ef68","name":"glob","status":"completed","summary":"glob: ","detail":"","at":"2026-06-26T02:35:34.785Z"}},"at":1782441334785},{"event":"tool_activity","data":{"activity":{"id":"tool_f5e244d3-71f9-45c7-8105-25aed470d79","name":"glob","status":"completed","summary":"glob: ","detail":"","at":"2026-06-26T02:35:34.804Z"}},"at":1782441334804},{"event":"tool_activity","data":{"activity":{"id":"tool_2da9bfe8-ff41-49ed-9b82-28758acb975","name":"glob","status":"completed","summary":"glob: ","detail":"","at":"2026-06-26T02:35:37.152Z"}},"at":1782441337152},{"event":"tool_activity","data":{"activity":{"id":"tool_0ed3e103-50d0-4894-bb36-8297ab637fc","name":"read","status":"running","summary":"read: C:\\xampp\\htdocs\\ALimpiezas\\docs\\MANUAL-AGENTE-IA.md","detail":"","at":"2026-06-26T02:35:38.367Z"}},"at":1782441338367},{"event":"tool_activity","data":{"activity":{"id":"tool_5fca127d-3ef8-40e0-b4dd-922a0e93ca5","name":"read","status":"running","summary":"read: C:\\xampp\\htdocs\\ALimpiezas\\docs\\MOBILE-BRIDGE-TEST.md","detail":"","at":"2026-06-26T02:35:38.368Z"}},"at":1782441338368},{"event":"tool_activity","data":{"activity":{"id":"tool_696cb613-876e-45c3-9f63-1704da9a35f","name":"read","status":"running","summary":"read: C:\\xampp\\htdocs\\ALimpiezas\\Plugins\\ALimpiezasMobile\\Init.php","detail":"","at":"2026-06-26T02:35:38.469Z"}},"at":1782441338469},{"event":"tool_activity","data":{"activity":{"id":"tool_0ed3e103-50d0-4894-bb36-8297ab637fc","name":"read","status":"completed","summary":"read: C:\\xampp\\htdocs\\ALimpiezas\\docs\\MANUAL-AGENTE-IA.md","detail":"","at":"2026-06-26T02:35:38.502Z"}},"at":1782441338502},{"event":"tool_activity","data":{"activity":{"id":"tool_5fca127d-3ef8-40e0-b4dd-922a0e93ca5","name":"read","status":"completed","summary":"read: C:\\xampp\\htdocs\\ALimpiezas\\docs\\MOBILE-BRIDGE-TEST.md","detail":"","at":"2026-06-26T02:35:38.503Z"}},"at":1782441338503},{"event":"tool_activity","data":{"activity":{"id":"tool_600c4019-996c-46a5-8ac2-dc510ca28a9","name":"read","status":"running","summary":"read: C:\\xampp\\htdocs\\ALimpiezas\\Plugins\\ALimpiezasMobile\\facturascripts.ini","detail":"","at":"2026-06-26T02:35:38.541Z"}},"at":1782441338541},{"event":"tool_activity","data":{"activity":{"id":"tool_696cb613-876e-45c3-9f63-1704da9a35f","name":"read","status":"completed","summary":"read: C:\\xampp\\htdocs\\ALimpiezas\\Plugins\\ALimpiezasMobile\\Init.php","detail":"","at":"2026-06-26T02:35:38.568Z"}},"at":1782441338568},{"event":"tool_activity","data":{"activity":{"id":"tool_600c4019-996c-46a5-8ac2-dc510ca28a9","name":"read","status":"completed","summary":"read: C:\\xampp\\htdocs\\ALimpiezas\\Plugins\\ALimpiezasMobile\\facturascripts.ini","detail":"","at":"2026-06-26T02:35:38.656Z"}},"at":1782441338656},{"event":"tool_activity","data":{"activity":{"id":"tool_b534b233-6ce4-4e0c-a3cb-868edd32369","name":"glob","status":"completed","summary":"glob: ","detail":"","at":"2026-06-26T02:35:38.845Z"}},"at":1782441338845},{"event":"tool_activity","data":{"activity":{"id":"tool_f1991b70-7987-465c-894c-0bd897dbb83","name":"read","status":"completed","summary":"read: C:\\xampp\\htdocs\\ALimpiezas\\ai-service\\main.py","detail":"","at":"2026-06-26T02:35:40.033Z"}},"at":1782441340033},{"event":"tool_activity","data":{"activity":{"id":"tool_fc5d14b5-c3a6-44bf-8887-4db2bd8871a","name":"read","status":"running","summary":"read: C:\\xampp\\htdocs\\ALimpiezas\\tools\\start-stack.ps1","detail":"","at":"2026-06-26T02:35:40.041Z"}},"at":1782441340041},{"event":"tool_activity","data":{"activity":{"id":"tool_204e4a03-e71c-4cea-9ff1-20b1e96d3e0","name":"read","status":"running","summary":"read: C:\\xampp\\htdocs\\ALimpiezas\\tools\\bootstrap-plugin.php","detail":"","at":"2026-06-26T02:35:40.117Z"}},"at":1782441340117},{"event":"tool_activity","data":{"activity":{"id":"tool_fc5d14b5-c3a6-44bf-8887-4db2bd8871a","name":"read","status":"completed","summary":"read: C:\\xampp\\htdocs\\ALimpiezas\\tools\\start-stack.ps1","detail":"","at":"2026-06-26T02:35:40.141Z"}},"at":1782441340141},{"event":"tool_activity","data":{"activity":{"id":"tool_06c7f362-0edb-4865-aa61-e34e281d20c","name":"read","status":"running","summary":"read: C:\\xampp\\htdocs\\ALimpiezas\\MyFiles\\plugins.json","detail":"","at":"2026-06-26T02:35:40.204Z"}},"at":1782441340204},{"event":"tool_activity","data":{"activity":{"id":"tool_204e4a03-e71c-4cea-9ff1-20b1e96d3e0","name":"read","status":"completed","summary":"read: C:\\xampp\\htdocs\\ALimpiezas\\tools\\bootstrap-plugin.php","detail":"","at":"2026-06-26T02:35:40.215Z"}},"at":1782441340215},{"event":"tool_activity","data":{"activity":{"id":"tool_54363182-daae-48aa-a478-cdefd02dd5d","name":"read","status":"running","summary":"read: C:\\xampp\\htdocs\\ALimpiezas\\.htaccess","detail":"","at":"2026-06-26T02:35:40.276Z"}},"at":1782441340277},{"event":"tool_activity","data":{"activity":{"id":"tool_06c7f362-0edb-4865-aa61-e34e281d20c","name":"read","status":"completed","summary":"read: C:\\xampp\\htdocs\\ALimpiezas\\MyFiles\\plugins.json","detail":"","at":"2026-06-26T02:35:40.305Z"}},"at":1782441340305},{"event":"tool_activity","data":{"activity":{"id":"tool_54363182-daae-48aa-a478-cdefd02dd5d","name":"read","status":"completed","summary":"read: C:\\xampp\\htdocs\\ALimpiezas\\.htaccess","detail":"","at":"2026-06-26T02:35:40.377Z"}},"at":1782441340377},{"event":"tool_activity","data":{"activity":{"id":"tool_6b2b3f37-598c-4d86-ba81-b2509d7a63b","name":"read","status":"completed","summary":"read: C:\\xampp\\htdocs\\ALimpiezas\\docs\\MANUAL-USUARIO.md","detail":"","at":"2026-06-26T02:35:40.491Z"}},"at":1782441340491},{"event":"tool_activity","data":{"activity":{"id":"tool_659055a0-f029-4d38-a742-06bfd5e7e91","name":"read","status":"running","summary":"read: C:\\xampp\\htdocs\\ALimpiezas\\Plugins\\ALimpiezasMobile\\Lib\\MobileConfig.php","detail":"","at":"2026-06-26T02:35:42.105Z"}},"at":1782441342105},{"event":"tool_activity","data":{"activity":{"id":"tool_423a9a05-3dc8-4236-b8a7-f2cd9d935cd","name":"read","status":"running","summary":"read: C:\\xampp\\htdocs\\ALimpiezas\\ai-service\\requirements.txt","detail":"","at":"2026-06-26T02:35:42.106Z"}},"at":1782441342106},{"event":"tool_activity","data":{"activity":{"id":"tool_f04b9250-91a2-47ca-873b-5c46d6c00a8","name":"glob","status":"running","summary":"glob: ","detail":"","at":"2026-06-26T02:35:42.121Z"}},"at":1782441342121},{"event":"tool_activity","data":{"activity":{"id":"tool_423a9a05-3dc8-4236-b8a7-f2cd9d935cd","name":"read","status":"completed","summary":"read: C:\\xampp\\htdocs\\ALimpiezas\\ai-service\\requirements.txt","detail":"","at":"2026-06-26T02:35:42.203Z"}},"at":1782441342203},{"event":"tool_activity","data":{"activity":{"id":"tool_659055a0-f029-4d38-a742-06bfd5e7e91","name":"read","status":"completed","summary":"read: C:\\xampp\\htdocs\\ALimpiezas\\Plugins\\ALimpiezasMobile\\Lib\\MobileConfig.php","detail":"","at":"2026-06-26T02:35:42.206Z"}},"at":1782441342206},{"event":"tool_activity","data":{"activity":{"id":"tool_d748fbe6-fef5-45f8-80f5-e1f01aa71ad","name":"read","status":"running","summary":"read: C:\\xampp\\htdocs\\ALimpiezas\\mobile.html","detail":"","at":"2026-06-26T02:35:42.265Z"}},"at":1782441342265},{"event":"tool_activity","data":{"activity":{"id":"tool_f04b9250-91a2-47ca-873b-5c46d6c00a8","name":"glob","status":"completed","summary":"glob: ","detail":"","at":"2026-06-26T02:35:42.275Z"}},"at":1782441342275},{"event":"tool_activity","data":{"activity":{"id":"tool_d748fbe6-fef5-45f8-80f5-e1f01aa71ad","name":"read","status":"completed","summary":"read: C:\\xampp\\htdocs\\ALimpiezas\\mobile.html","detail":"","at":"2026-06-26T02:35:42.368Z"}},"at":1782441342368},{"event":"tool_activity","data":{"activity":{"id":"tool_eefa15ff-48c4-4af6-b26f-3915f71be97","name":"read","status":"completed","summary":"read: C:\\xampp\\htdocs\\ALimpiezas\\Plugins\\NeoTheme\\README.md","detail":"","at":"2026-06-26T02:35:42.560Z"}},"at":1782441342560},{"event":"tool_activity","data":{"activity":{"id":"tool_54850552-a823-4d94-8057-0889f87e196","name":"read","status":"completed","summary":"read: C:\\xampp\\htdocs\\ALimpiezas\\.serena\\memories\\alimpiezas\\project-knowledge.md","detail":"","at":"2026-06-26T02:35:43.614Z"}},"at":1782441343614},{"event":"tool_activity","data":{"activity":{"id":"tool_9cdd51d4-d720-4ce7-a646-ff8a19bee58","name":"read","status":"completed","summary":"read: C:\\xampp\\htdocs\\ALimpiezas\\.serena\\project.yml","detail":"","at":"2026-06-26T02:35:43.715Z"}},"at":1782441343715},{"event":"tool_activity","data":{"activity":{"id":"tool_612833b1-a42e-4197-8585-0ac4b415a77","name":"grep","status":"running","summary":"grep: C:\\xampp\\htdocs\\ALimpiezas","detail":"","at":"2026-06-26T02:35:43.788Z"}},"at":1782441343788},{"event":"tool_activity","data":{"activity":{"id":"tool_e46cf387-2df2-40c9-986a-732ca4bb27a","name":"read","status":"running","summary":"read: C:\\xampp\\htdocs\\ALimpiezas\\tools\\ai-service-manager.ps1","detail":"","at":"2026-06-26T02:35:43.955Z"}},"at":1782441343955},{"event":"tool_activity","data":{"activity":{"id":"tool_612833b1-a42e-4197-8585-0ac4b415a77","name":"grep","status":"completed","summary":"grep: C:\\xampp\\htdocs\\ALimpiezas","detail":"","at":"2026-06-26T02:35:43.962Z"}},"at":1782441343962},{"event":"tool_activity","data":{"activity":{"id":"tool_e46cf387-2df2-40c9-986a-732ca4bb27a","name":"read","status":"completed","summary":"read: C:\\xampp\\htdocs\\ALimpiezas\\tools\\ai-service-manager.ps1","detail":"","at":"2026-06-26T02:35:44.088Z"}},"at":1782441344088},{"event":"tool_activity","data":{"activity":{"id":"tool_576b4c7e-6fc0-44e8-bdaf-344d4d03a0d","name":"read","status":"completed","summary":"read: C:\\xampp\\htdocs\\ALimpiezas\\Plugins\\ALimpiezasMobile\\Table\\ai_expense_queue.xml","detail":"","at":"2026-06-26T02:35:45.882Z"}},"at":1782441345882},{"event":"tool_activity","data":{"activity":{"id":"tool_c435254e-54f9-4dad-9c7b-56ba44fb98f","name":"grep","status":"completed","summary":"grep: C:\\xampp\\htdocs\\ALimpiezas\\Core","detail":"","at":"2026-06-26T02:35:46.074Z"}},"at":1782441346074},{"event":"tool_activity","data":{"activity":{"id":"tool_0bb000dc-6fdf-447f-b216-cd61b02db5d","name":"read","status":"completed","summary":"read: …ampp\\htdocs\\ALimpiezas\\Plugins\\ALimpiezasMobile\\Lib\\ExpenseInvoiceCreator.php","detail":"","at":"2026-06-26T02:35:46.375Z"}},"at":1782441346375},{"event":"text","data":{"chunk":"# ALimpiezas — Conocimiento consolidado del proyecto\n\n> **Proyecto:** `C:\\xampp\\htdocs\\ALimpiezas` · **Serena:** `project_name: ALimpiezas` · **Docs:** `docs/MANUAL-AGENTE-IA.md`, `docs/MANUAL-USUARIO.md`\n\n---\n\n## 1. Resumen ejecutivo\n\nERP **FacturaScripts 2026.4** (PHP 8.1+, MariaDB `alimpiezas_fs`) desplegado en **XAMPP**, acceso web `/ALimpiezas`. El valor custom está en el plugin **ALimpiezasMobile** (PWA móvil para autónomos: gastos, fiscal 303/130, voz). El código fuente del plugin vive en `Plugins/`; tras deploy se materializa en `Dinamic/` (no editar `Dinamic/` ni `Core/` directamente). Microservicio **FastAPI** en `ai-service/` (puerto **8090**) para OCR (Tesseract), extracción fiscal y Ollama/Whisper. Operación local vía `tools/start-stack.ps1`, `tools/ai-service-manager.ps1` y `php tools/bootstrap-plugin.php`. Assets públicos solo bajo `Dinamic/Assets/` (Apache rewrite en `.htaccess`).\n\n---\n\n## 2. Glosario\n\n| Término | Definición |\n|---------|------------|\n| **FacturaScripts** | ERP open source (LGPL). Framework en `Core/`; capa dinámica en `Dinamic/`. |\n| **Dinamic** | Carpeta generada por `Plugins::deploy()`: symlinks/copias de plugins activos. Runtime real del código custom. |\n| **Plugin** | Extensión en `Plugins/<Nombre>/` con `facturascripts.ini`, `Init.php`, controladores, modelos. |\n| **ALimpiezasMobile** | Plugin principal (v2): PWA, gastos, fiscal, voz. Grupo settings `alimpiezas`. |\n| **PWA** | App instalable en iPhone/Android. `manifest.json` + `sw.js` en `Dinamic/Assets/`. |\n| **FacturaProveedor** | Factura de compra/gasto en FS. Destino final al confirmar un gasto móvil. |\n| **Proveedor** | Tercero emisor del gasto; se busca/crea por CIF en `ExpenseInvoiceCreator`. |\n| **ai_expense_queue** | Tabla/cola de gastos pendientes de revisión (OCR, manual o IA). |\n| **expense_mode** | Modo de registro: `manual` (sin 8090), `ocr` (Tesseract local), `ai` (OCR + Ollama). |\n| **303 / 130** | Modelos AEAT trimestrales: IVA repercutido/soportado (303) e IRPF estimación directa (130). Borradores en `FiscalModels`. |\n| **Autónomo** | Perfil fiscal objetivo; régimen por defecto `fiscal_regime=autonomo`. |\n| **ai-service** | Microservicio Python (`main.py`): `/health`, `/api/v1/extract-invoice`, `/api/v1/parse-intent`, `/api/v1/transcribe`. |\n| **Ollama** | LLM local (por defecto `qwen2.5:3b`); URL en settings `ollama_url` o env `OLLAMA_URL`. |\n| **Deploy / bootstrap** | `php tools/bootstrap-plugin.php` → `Plugins::enable` + `Plugins::deploy(true, true)` + limpia caché. |\n| **NeoTheme** | Plugin de tema escritorio (instalado, **desactivado**). No afecta la PWA móvil. |\n| **Bridge móvil** | Flujo Cursor desde iPhone/PWA; ver `docs/MOBILE-BRIDGE-TEST.md`. |\n| **AttachedFile** | Archivo adjunto FS; la imagen del ticket se vincula a `FacturaProveedor` al confirmar. |\n\n---\n\n## 3. FAQ dev\n\n### 1. ¿Dónde edito código custom?\nEn `Plugins/ALimpiezasMobile/` (y `ai-service/` para Python). **Nunca** editar `Dinamic/` manualmente: se regenera con deploy.\n\n### 2. ¿Cómo activo cambios del plugin tras editar?\n```powershell\ncd C:\\xampp\\htdocs\\ALimpiezas\nphp tools/bootstrap-plugin.php\n```\nEquivale a activar plugin + reconstruir `Dinamic/` + `Cache::clear()`.\n\n### 3. ¿Por qué 403 en CSS/JS del móvil?\nLas URLs deben apuntar a `Dinamic/Assets/...`, no a `Plugins/.../Assets/`. Twig: `{{ asset('Dinamic/Assets/CSS/mobile.css') }}`. Tras cambiar assets → bootstrap.\n\n### 4. ¿El móvil necesita siempre el puerto 8090?\n**No.** Modo `manual` funciona sin microservicio. OCR/IA requieren `ai-service` en `8090` y `expense_mode` ≠ `manual`. Fiscal, voz local y ayuda no dependen de 8090.\n\n### 5. ¿Cómo arranco todo el stack local?\n```powershell\n.\\tools\\start-stack.ps1          # Apache + MySQL + IA + bandeja\n.\\tools\\ai-service-manager.ps1 -Start   # solo IA\n.\\tools\\ai-service-manager.ps1 -Status  # health check\n```\n\n### 6. Error Errno 10048 / puerto 8090 ocupado\n```powershell\n.\\tools\\ai-service-manager.ps1 -Restart\n.\\tools\\port-services.ps1 -Port 8090\n```\n\n### 7. ¿Flujo completo de un gasto con foto?\n`MobileExpenses` POST `upload` → `AiExpenseProcessor` llama `8090/api/v1/extract-invoice` (si OCR/IA) → fila en `ai_expense_queue` (`pending`) → usuario edita modal → POST `confirm` → `ExpenseInvoiceCreator` crea `Proveedor` + `FacturaProveedor` + adjunto → `status=approved`, `idfacturaprov` relleno.\n\n### 8. ¿Settings del plugin y cómo leerlos?\nGrupo `alimpiezas` en tabla `settings`. PHP: `Tools::settings('alimpiezas', 'expense_mode')`. UI: `MobileSettings`. Claves: `expense_mode`, `ai_service_url`, `fiscal_regime`, `voice_use_service`, `mobile_theme`, `ollama_url`, `ollama_model`.\n\n---\n\n## 4. Checklist onboarding (nuevo dev)\n\n- [ ] **Requisitos:** XAMPP (Apache 2.4 + MariaDB), PHP ≥8.1, Composer, Python 3.10+ para `ai-service`, Tesseract OCR (Windows: `C:\\Program Files\\Tesseract-OCR\\`).\n- [ ] **Clonar/abrir** `C:\\xampp\\htdocs\\ALimpiezas`.\n- [ ] **Composer:** `composer install --ignore-platform-req=ext-pgsql` (PostgreSQL no usado en local).\n- [ ] **Config:** revisar `config.php` (DB `alimpiezas_fs`, `FS_INITIAL_USER`/`PASS`); no commitear secretos.\n- [ ] **Plugins:** `php tools/bootstrap-plugin.php` (activa ALimpiezasMobile).\n- [ ] **IA (opcional):** `pip install -r ai-service/requirements.txt` → `.\\tools\\ai-service-manager.ps1 -Start`.\n- [ ] **Verificar HTTP:** `http://localhost/ALimpiezas/MobileHome` (PC) · `curl http://127.0.0.1:8090/health`.\n- [ ] **Verificar assets:** `curl -I http://localhost/ALimpiezas/Dinamic/Assets/CSS/mobile.css` → 200.\n- [ ] **Leer docs:** `docs/MANUAL-AGENTE-IA.md` (técnico), `docs/MANUAL-USUARIO.md` (UX/PWA).\n- [ ] **Convención de trabajo:** editar `Plugins/` → bootstrap → probar en móvil vía IP LAN (`http://192.168.x.x/ALimpiezas/MobileHome`, no `localhost` en iPhone).\n- [ ] **Tests PHP:** `composer test` (suite FacturaScripts en `Test/`).\n- [ ] **Serena:** proyecto `ALimpiezas`, memoria en `.serena/memories/alimpiezas/project-knowledge.md`.\n\n---\n\n## 5. Prompts guardados\n\n### Bugfix\n```\n[Bugfix ALimpiezas] Tras confirmar gasto en MobileExpenses, la FacturaProveedor no se crea o queda sin IVA.\nContexto: Plugins/ALimpiezasMobile/Lib/ExpenseInvoiceCreator.php, AiExpenseProcessor.php.\nRepro: subir ticket → confirm → revisar ai_expense_queue.status e idfacturaprov.\nNo editar Dinamic/. Tras fix: php tools/bootstrap-plugin.php.\n```\n\n### Bugfix\n```\n[Bugfix assets 403] mobile.css o manifest.json devuelven 403/404 en /ALimpiezas.\nRevisar .htaccess RewriteCond Dinamic/Assets/, rutas Twig asset('Dinamic/Assets/...'), y ejecutar bootstrap-plugin.php.\n```\n\n### Feature\n```\n[Feature gastos] Añadir campo/concepto X al modal de confirmación de MobileExpenses.\nArchivos: View/MobileExpenses.html.twig, Assets/JS/mobile.js, AiExpenseQueue model, ExpenseInvoiceCreator.\nPersistir en ai_expense_queue si hace falta nueva columna en Table/ai_expense_queue.xml + Init::update().\n```\n\n### Feature\n```\n[Feature fiscal] Mejorar borrador modelo 303/130 en MobileFiscal.\nArchivos: Lib/FiscalModels.php, FiscalCalendar.php, View/MobileFiscal.html.twig.\nMantener disclaimer: no sustituye AEAT ni asesor.\n```\n\n### Refactor\n```\n[Refactor MobileConfig] Centralizar lectura de settings alimpiezas y modos expense_mode.\nSolo Plugins/ALimpiezasMobile/Lib/MobileConfig.php y consumidores; sin cambiar comportamiento observable.\n```\n\n### Refactor\n```\n[Refactor ai-service] Extraer reglas OCR/regex de main.py a módulo separado sin cambiar respuesta JSON de /api/v1/extract-invoice.\nMantener compatibilidad con AiExpenseProcessor.php.\n```\n\n### Deploy / ops\n```\n[Deploy local] Arrancar stack ALimpiezas completo y validar salud.\nEjecutar tools/start-stack.ps1, verificar Apache/MySQL, curl :8090/health y /ALimpiezas/MobileHome.\nSi 8090 ocupado: ai-service-manager.ps1 -Restart.\n```\n\n### Deploy / ops\n```\n[Deploy plugin] Cambios en Plugins/ALimpiezasMobile listos para probar.\nEjecutar php tools/bootstrap-plugin.php, limpiar caché Twig si UI rara, verificar Dinamic/Assets copiados.\n```\n\n### QA\n```\n[QA móvil PWA] Checklist iPhone: login MobileHome, Gastos manual+OCR, confirm→FacturaProveedor, Fiscal 303 preview, Voz command local.\nURL LAN, no localhost. Modo manual sin :8090; OCR con health OK.\n```\n\n### QA\n```\n[QA ai-service] Probar endpoints FastAPI: GET /health, POST /api/v1/extract-invoice (multipart PDF/JPG), POST /api/v1/parse-intent, POST /api/v1/transcribe.\nDocumentar Tesseract/Ollama/Whisper en respuesta health.\n```\n\n---\n\n## Mapa rápido de archivos\n\n| Tarea | Archivo |\n|-------|---------|\n| Settings / modos | `Plugins/ALimpiezasMobile/Lib/MobileConfig.php`, `Init.php` |\n| Cola y upload | `Lib/AiExpenseProcessor.php`, `Controller/MobileExpenses.php` |\n| Crear factura gasto | `Lib/ExpenseInvoiceCreator.php` |\n| OCR / LLM | `ai-service/main.py` |\n| Layout PWA | `View/Master/MobileLayout.html.twig` |\n| JS gastos | `Assets/JS/mobile.js` → deploy a Dinamic |\n| Ops | `tools/bootstrap-plugin.php`, `tools/start-stack.ps1`, `tools/ai-service-manager.ps1` |\n\n---\n\n## Restricciones para el agente\n\n- **Editar:** `Plugins/`, `ai-service/`, `tools/`, `docs/` (si se pide).\n- **No escanear masivamente:** `vendor/`, `node_modules/`, `Core/`, `Dinamic/` (salvo petición explícita).\n- **Shell:** timeouts en comandos; sin bucles infinitos.\n- **Commits:** solo si el usuario lo pide explícitamente.\n\n---\n\nPuedes copiar este bloque completo a Serena con `write_memory` en `alimpiezas/project-knowledge` o pegarlo en memoria local del agente. Si quieres que lo guarde en `.serena/memories/alimpiezas/project-knowledge.md` en el repo, indícalo."},"at":1782441365273},{"event":"status","data":{"text":"Procesando…"},"at":1782441365260},{"event":"phase_saved","data":{"phaseId":"knowledge","progress":{"status":"done","completedAt":"2026-06-26T02:36:05.266Z","name":"Conocimiento","summary":"Consolidando el conocimiento del proyecto leyendo archivos clave sin escanear Core/Dinamic en profundidad.\n# ALimpiezas — Conocimiento consolidado del proyecto\n\n> **Proyecto:** `C:\\xampp\\htdocs\\ALimpiezas` · **Serena:** `project_name: ALimpiezas` · **Docs:** `docs/MANUAL-AGENTE-IA.md`, `docs/MANUAL-USUARIO.md`\n\n---\n\n## 1. Resumen ejecutivo\n\nERP **FacturaScripts 2026.4** (PHP 8.1+, MariaDB `alimpiezas_fs`) desplegado en **XAMPP**, acceso web `/ALimpiezas`. El valor custom está en el plugin **ALimpiezasMobile** (PWA móvil para autónomos: gastos, fiscal 303/130, voz). El código fuente del plugin ","fullText":"Consolidando el conocimiento del proyecto leyendo archivos clave sin escanear Core/Dinamic en profundidad.\n# ALimpiezas — Conocimiento consolidado del proyecto\n\n> **Proyecto:** `C:\\xampp\\htdocs\\ALimpiezas` · **Serena:** `project_name: ALimpiezas` · **Docs:** `docs/MANUAL-AGENTE-IA.md`, `docs/MANUAL-USUARIO.md`\n\n---\n\n## 1. Resumen ejecutivo\n\nERP **FacturaScripts 2026.4** (PHP 8.1+, MariaDB `alimpiezas_fs`) desplegado en **XAMPP**, acceso web `/ALimpiezas`. El valor custom está en el plugin **ALimpiezasMobile** (PWA móvil para autónomos: gastos, fiscal 303/130, voz). El código fuente del plugin vive en `Plugins/`; tras deploy se materializa en `Dinamic/` (no editar `Dinamic/` ni `Core/` directamente). Microservicio **FastAPI** en `ai-service/` (puerto **8090**) para OCR (Tesseract), extracción fiscal y Ollama/Whisper. Operación local vía `tools/start-stack.ps1`, `tools/ai-service-manager.ps1` y `php tools/bootstrap-plugin.php`. Assets públicos solo bajo `Dinamic/Assets/` (Apache rewrite en `.htaccess`).\n\n---\n\n## 2. Glosario\n\n| Término | Definición |\n|---------|------------|\n| **FacturaScripts** | ERP open source (LGPL). Framework en `Core/`; capa dinámica en `Dinamic/`. |\n| **Dinamic** | Carpeta generada por `Plugins::deploy()`: symlinks/copias de plugins activos. Runtime real del código custom. |\n| **Plugin** | Extensión en `Plugins/<Nombre>/` con `facturascripts.ini`, `Init.php`, controladores, modelos. |\n| **ALimpiezasMobile** | Plugin principal (v2): PWA, gastos, fiscal, voz. Grupo settings `alimpiezas`. |\n| **PWA** | App instalable en iPhone/Android. `manifest.json` + `sw.js` en `Dinamic/Assets/`. |\n| **FacturaProveedor** | Factura de compra/gasto en FS. Destino final al confirmar un gasto móvil. |\n| **Proveedor** | Tercero emisor del gasto; se busca/crea por CIF en `ExpenseInvoiceCreator`. |\n| **ai_expense_queue** | Tabla/cola de gastos pendientes de revisión (OCR, manual o IA). |\n| **expense_mode** | Modo de registro: `manual` (sin 8090), `ocr` (Tesseract local), `ai` (OCR + Ollama). |\n| **303 / 130** | Modelos AEAT trimestrales: IVA repercutido/soportado (303) e IRPF estimación directa (130). Borradores en `FiscalModels`. |\n| **Autónomo** | Perfil fiscal objetivo; régimen por defecto `fiscal_regime=autonomo`. |\n| **ai-service** | Microservicio Python (`main.py`): `/health`, `/api/v1/extract-invoice`, `/api/v1/parse-intent`, `/api/v1/transcribe`. |\n| **Ollama** | LLM local (por defecto `qwen2.5:3b`); URL en settings `ollama_url` o env `OLLAMA_URL`. |\n| **Deploy / bootstrap** | `php tools/bootstrap-plugin.php` → `Plugins::enable` + `Plugins::deploy(true, true)` + limpia caché. |\n| **NeoTheme** | Plugin de tema escritorio (instalado, **desactivado**). No afecta la PWA móvil. |\n| **Bridge móvil** | Flujo Cursor desde iPhone/PWA; ver `docs/MOBILE-BRIDGE-TEST.md`. |\n| **AttachedFile** | Archivo adjunto FS; la imagen del ticket se vincula a `FacturaProveedor` al confirmar. |\n\n---\n\n## 3. FAQ dev\n\n### 1. ¿Dónde edito código custom?\nEn `Plugins/ALimpiezasMobile/` (y `ai-service/` para Python). **Nunca** editar `Dinamic/` manualmente: se regenera con deploy.\n\n### 2. ¿Cómo activo cambios del plugin tras editar?\n```powershell\ncd C:\\xampp\\htdocs\\ALimpiezas\nphp tools/bootstrap-plugin.php\n```\nEquivale a activar plugin + reconstruir `Dinamic/` + `Cache::clear()`.\n\n### 3. ¿Por qué 403 en CSS/JS del móvil?\nLas URLs deben apuntar a `Dinamic/Assets/...`, no a `Plugins/.../Assets/`. Twig: `{{ asset('Dinamic/Assets/CSS/mobile.css') }}`. Tras cambiar assets → bootstrap.\n\n### 4. ¿El móvil necesita siempre el puerto 8090?\n**No.** Modo `manual` funciona sin microservicio. OCR/IA requieren `ai-service` en `8090` y `expense_mode` ≠ `manual`. Fiscal, voz local y ayuda no dependen de 8090.\n\n### 5. ¿Cómo arranco todo el stack local?\n```powershell\n.\\tools\\start-stack.ps1          # Apache + MySQL + IA + bandeja\n.\\tools\\ai-service-manager.ps1 -Start   # solo IA\n.\\tools\\ai-service-manager.ps1 -Status  # health check\n```\n\n### 6. Error Errno 10048 / puerto 8090 ocupado\n```powershell\n.\\tools\\ai-service-manager.ps1 -Restart\n.\\tools\\port-services.ps1 -Port 8090\n```\n\n### 7. ¿Flujo completo de un gasto con foto?\n`MobileExpenses` POST `upload` → `AiExpenseProcessor` llama `8090/api/v1/extract-invoice` (si OCR/IA) → fila en `ai_expense_queue` (`pending`) → usuario edita modal → POST `confirm` → `ExpenseInvoiceCreator` crea `Proveedor` + `FacturaProveedor` + adjunto → `status=approved`, `idfacturaprov` relleno.\n\n### 8. ¿Settings del plugin y cómo leerlos?\nGrupo `alimpiezas` en tabla `settings`. PHP: `Tools::settings('alimpiezas', 'expense_mode')`. UI: `MobileSettings`. Claves: `expense_mode`, `ai_service_url`, `fiscal_regime`, `voice_use_service`, `mobile_theme`, `ollama_url`, `ollama_model`.\n\n---\n\n## 4. Checklist onboarding (nuevo dev)\n\n- [ ] **Requisitos:** XAMPP (Apache 2.4 + MariaDB), PHP ≥8.1, Composer, Python 3.10+ para `ai-service`, Tesseract OCR (Windows: `C:\\Program Files\\Tesseract-OCR\\`).\n- [ ] **Clonar/abrir** `C:\\xampp\\htdocs\\ALimpiezas`.\n- [ ] **Composer:** `composer install --ignore-platform-req=ext-pgsql` (PostgreSQL no usado en local).\n- [ ] **Config:** revisar `config.php` (DB `alimpiezas_fs`, `FS_INITIAL_USER`/`PASS`); no commitear secretos.\n- [ ] **Plugins:** `php tools/bootstrap-plugin.php` (activa ALimpiezasMobile).\n- [ ] **IA (opcional):** `pip install -r ai-service/requirements.txt` → `.\\tools\\ai-service-manager.ps1 -Start`.\n- [ ] **Verificar HTTP:** `http://localhost/ALimpiezas/MobileHome` (PC) · `curl http://127.0.0.1:8090/health`.\n- [ ] **Verificar assets:** `curl -I http://localhost/ALimpiezas/Dinamic/Assets/CSS/mobile.css` → 200.\n- [ ] **Leer docs:** `docs/MANUAL-AGENTE-IA.md` (técnico), `docs/MANUAL-USUARIO.md` (UX/PWA).\n- [ ] **Convención de trabajo:** editar `Plugins/` → bootstrap → probar en móvil vía IP LAN (`http://192.168.x.x/ALimpiezas/MobileHome`, no `localhost` en iPhone).\n- [ ] **Tests PHP:** `composer test` (suite FacturaScripts en `Test/`).\n- [ ] **Serena:** proyecto `ALimpiezas`, memoria en `.serena/memories/alimpiezas/project-knowledge.md`.\n\n---\n\n## 5. Prompts guardados\n\n### Bugfix\n```\n[Bugfix ALimpiezas] Tras confirmar gasto en MobileExpenses, la FacturaProveedor no se crea o queda sin IVA.\nContexto: Plugins/ALimpiezasMobile/Lib/ExpenseInvoiceCreator.php, AiExpenseProcessor.php.\nRepro: subir ticket → confirm → revisar ai_expense_queue.status e idfacturaprov.\nNo editar Dinamic/. Tras fix: php tools/bootstrap-plugin.php.\n```\n\n### Bugfix\n```\n[Bugfix assets 403] mobile.css o manifest.json devuelven 403/404 en /ALimpiezas.\nRevisar .htaccess RewriteCond Dinamic/Assets/, rutas Twig asset('Dinamic/Assets/...'), y ejecutar bootstrap-plugin.php.\n```\n\n### Feature\n```\n[Feature gastos] Añadir campo/concepto X al modal de confirmación de MobileExpenses.\nArchivos: View/MobileExpenses.html.twig, Assets/JS/mobile.js, AiExpenseQueue model, ExpenseInvoiceCreator.\nPersistir en ai_expense_queue si hace falta nueva columna en Table/ai_expense_queue.xml + Init::update().\n```\n\n### Feature\n```\n[Feature fiscal] Mejorar borrador modelo 303/130 en MobileFiscal.\nArchivos: Lib/FiscalModels.php, FiscalCalendar.php, View/MobileFiscal.html.twig.\nMantener disclaimer: no sustituye AEAT ni asesor.\n```\n\n### Refactor\n```\n[Refactor MobileConfig] Centralizar lectura de settings alimpiezas y modos expense_mode.\nSolo Plugins/ALimpiezasMobile/Lib/MobileConfig.php y consumidores; sin cambiar comportamiento observable.\n```\n\n### Refactor\n```\n[Refactor ai-service] Extraer reglas OCR/regex de main.py a módulo separado sin cambiar respuesta JSON de /api/v1/extract-invoice.\nMantener compatibilidad con AiExpenseProcessor.php.\n```\n\n### Deploy / ops\n```\n[Deploy local] Arrancar stack ALimpiezas completo y validar salud.\nEjecutar tools/start-stack.ps1, verificar Apache/MySQL, curl :8090/health y /ALimpiezas/MobileHome.\nSi 8090 ocupado: ai-service-manager.ps1 -Restart.\n```\n\n### Deploy / ops\n```\n[Deploy plugin] Cambios en Plugins/ALimpiezasMobile listos para probar.\nEjecutar php tools/bootstrap-plugin.php, limpiar caché Twig si UI rara, verificar Dinamic/Assets copiados.\n```\n\n### QA\n```\n[QA móvil PWA] Checklist iPhone: login MobileHome, Gastos manual+OCR, confirm→FacturaProveedor, Fiscal 303 preview, Voz command local.\nURL LAN, no localhost. Modo manual sin :8090; OCR con health OK.\n```\n\n### QA\n```\n[QA ai-service] Probar endpoints FastAPI: GET /health, POST /api/v1/extract-invoice (multipart PDF/JPG), POST /api/v1/parse-intent, POST /api/v1/transcribe.\nDocumentar Tesseract/Ollama/Whisper en respuesta health.\n```\n\n---\n\n## Mapa rápido de archivos\n\n| Tarea | Archivo |\n|-------|---------|\n| Settings / modos | `Plugins/ALimpiezasMobile/Lib/MobileConfig.php`, `Init.php` |\n| Cola y upload | `Lib/AiExpenseProcessor.php`, `Controller/MobileExpenses.php` |\n| Crear factura gasto | `Lib/ExpenseInvoiceCreator.php` |\n| OCR / LLM | `ai-service/main.py` |\n| Layout PWA | `View/Master/MobileLayout.html.twig` |\n| JS gastos | `Assets/JS/mobile.js` → deploy a Dinamic |\n| Ops | `tools/bootstrap-plugin.php`, `tools/start-stack.ps1`, `tools/ai-service-manager.ps1` |\n\n---\n\n## Restricciones para el agente\n\n- **Editar:** `Plugins/`, `ai-service/`, `tools/`, `docs/` (si se pide).\n- **No escanear masivamente:** `vendor/`, `node_modules/`, `Core/`, `Dinamic/` (salvo petición explícita).\n- **Shell:** timeouts en comandos; sin bucles infinitos.\n- **Commits:** solo si el usuario lo pide explícitamente.\n\n---\n\nPuedes copiar este bloque completo a Serena con `write_memory` en `alimpiezas/project-knowledge` o pegarlo en memoria local del agente. Si quieres que lo guarde en `.serena/memories/alimpiezas/project-knowledge.md` en el repo, indícalo."}},"at":1782441365269},{"event":"done","data":{"ok":true,"bridgeSessionId":"bs-1782441365264-rsn2z9","agentId":"agent-cfab63c5-0604-4c27-bc50-a4c2ce83d7e9","runId":"run-0b8dd531-6706-4835-a0db-f3cfd6384ab5","status":"finished","result":"# ALimpiezas — Conocimiento consolidado del proyecto\n\n> **Proyecto:** `C:\\xampp\\htdocs\\ALimpiezas` · **Serena:** `project_name: ALimpiezas` · **Docs:** `docs/MANUAL-AGENTE-IA.md`, `docs/MANUAL-USUARIO.md`\n\n---\n\n## 1. Resumen ejecutivo\n\nERP **FacturaScripts 2026.4** (PHP 8.1+, MariaDB `alimpiezas_fs`) desplegado en **XAMPP**, acceso web `/ALimpiezas`. El valor custom está en el plugin **ALimpiezasMobile** (PWA móvil para autónomos: gastos, fiscal 303/130, voz). El código fuente del plugin vive en `Plugins/`; tras deploy se materializa en `Dinamic/` (no editar `Dinamic/` ni `Core/` directamente). Microservicio **FastAPI** en `ai-service/` (puerto **8090**) para OCR (Tesseract), extracción fiscal y Ollama/Whisper. Operación local vía `tools/start-stack.ps1`, `tools/ai-service-manager.ps1` y `php tools/bootstrap-plugin.php`. Assets públicos solo bajo `Dinamic/Assets/` (Apache rewrite en `.htaccess`).\n\n---\n\n## 2. Glosario\n\n| Término | Definición |\n|---------|------------|\n| **FacturaScripts** | ERP open source (LGPL). Framework en `Core/`; capa dinámica en `Dinamic/`. |\n| **Dinamic** | Carpeta generada por `Plugins::deploy()`: symlinks/copias de plugins activos. Runtime real del código custom. |\n| **Plugin** | Extensión en `Plugins/<Nombre>/` con `facturascripts.ini`, `Init.php`, controladores, modelos. |\n| **ALimpiezasMobile** | Plugin principal (v2): PWA, gastos, fiscal, voz. Grupo settings `alimpiezas`. |\n| **PWA** | App instalable en iPhone/Android. `manifest.json` + `sw.js` en `Dinamic/Assets/`. |\n| **FacturaProveedor** | Factura de compra/gasto en FS. Destino final al confirmar un gasto móvil. |\n| **Proveedor** | Tercero emisor del gasto; se busca/crea por CIF en `ExpenseInvoiceCreator`. |\n| **ai_expense_queue** | Tabla/cola de gastos pendientes de revisión (OCR, manual o IA). |\n| **expense_mode** | Modo de registro: `manual` (sin 8090), `ocr` (Tesseract local), `ai` (OCR + Ollama). |\n| **303 / 130** | Modelos AEAT trimestrales: IVA repercutido/soportado (303) e IRPF estimación directa (130). Borradores en `FiscalModels`. |\n| **Autónomo** | Perfil fiscal objetivo; régimen por defecto `fiscal_regime=autonomo`. |\n| **ai-service** | Microservicio Python (`main.py`): `/health`, `/api/v1/extract-invoice`, `/api/v1/parse-intent`, `/api/v1/transcribe`. |\n| **Ollama** | LLM local (por defecto `qwen2.5:3b`); URL en settings `ollama_url` o env `OLLAMA_URL`. |\n| **Deploy / bootstrap** | `php tools/bootstrap-plugin.php` → `Plugins::enable` + `Plugins::deploy(true, true)` + limpia caché. |\n| **NeoTheme** | Plugin de tema escritorio (instalado, **desactivado**). No afecta la PWA móvil. |\n| **Bridge móvil** | Flujo Cursor desde iPhone/PWA; ver `docs/MOBILE-BRIDGE-TEST.md`. |\n| **AttachedFile** | Archivo adjunto FS; la imagen del ticket se vincula a `FacturaProveedor` al confirmar. |\n\n---\n\n## 3. FAQ dev\n\n### 1. ¿Dónde edito código custom?\nEn `Plugins/ALimpiezasMobile/` (y `ai-service/` para Python). **Nunca** editar `Dinamic/` manualmente: se regenera con deploy.\n\n### 2. ¿Cómo activo cambios del plugin tras editar?\n```powershell\ncd C:\\xampp\\htdocs\\ALimpiezas\nphp tools/bootstrap-plugin.php\n```\nEquivale a activar plugin + reconstruir `Dinamic/` + `Cache::clear()`.\n\n### 3. ¿Por qué 403 en CSS/JS del móvil?\nLas URLs deben apuntar a `Dinamic/Assets/...`, no a `Plugins/.../Assets/`. Twig: `{{ asset('Dinamic/Assets/CSS/mobile.css') }}`. Tras cambiar assets → bootstrap.\n\n### 4. ¿El móvil necesita siempre el puerto 8090?\n**No.** Modo `manual` funciona sin microservicio. OCR/IA requieren `ai-service` en `8090` y `expense_mode` ≠ `manual`. Fiscal, voz local y ayuda no dependen de 8090.\n\n### 5. ¿Cómo arranco todo el stack local?\n```powershell\n.\\tools\\start-stack.ps1          # Apache + MySQL + IA + bandeja\n.\\tools\\ai-service-manager.ps1 -Start   # solo IA\n.\\tools\\ai-service-manager.ps1 -Status  # health check\n```\n\n### 6. Error Errno 10048 / puerto 8090 ocupado\n```powershell\n.\\tools\\ai-service-manager.ps1 -Restart\n.\\tools\\port-services.ps1 -Port 8090\n```\n\n### 7. ¿Flujo completo de un gasto con foto?\n`MobileExpenses` POST `upload` → `AiExpenseProcessor` llama `8090/api/v1/extract-invoice` (si OCR/IA) → fila en `ai_expense_queue` (`pending`) → usuario edita modal → POST `confirm` → `ExpenseInvoiceCreator` crea `Proveedor` + `FacturaProveedor` + adjunto → `status=approved`, `idfacturaprov` relleno.\n\n### 8. ¿Settings del plugin y cómo leerlos?\nGrupo `alimpiezas` en tabla `settings`. PHP: `Tools::settings('alimpiezas', 'expense_mode')`. UI: `MobileSettings`. Claves: `expense_mode`, `ai_service_url`, `fiscal_regime`, `voice_use_service`, `mobile_theme`, `ollama_url`, `ollama_model`.\n\n---\n\n## 4. Checklist onboarding (nuevo dev)\n\n- [ ] **Requisitos:** XAMPP (Apache 2.4 + MariaDB), PHP ≥8.1, Composer, Python 3.10+ para `ai-service`, Tesseract OCR (Windows: `C:\\Program Files\\Tesseract-OCR\\`).\n- [ ] **Clonar/abrir** `C:\\xampp\\htdocs\\ALimpiezas`.\n- [ ] **Composer:** `composer install --ignore-platform-req=ext-pgsql` (PostgreSQL no usado en local).\n- [ ] **Config:** revisar `config.php` (DB `alimpiezas_fs`, `FS_INITIAL_USER`/`PASS`); no commitear secretos.\n- [ ] **Plugins:** `php tools/bootstrap-plugin.php` (activa ALimpiezasMobile).\n- [ ] **IA (opcional):** `pip install -r ai-service/requirements.txt` → `.\\tools\\ai-service-manager.ps1 -Start`.\n- [ ] **Verificar HTTP:** `http://localhost/ALimpiezas/MobileHome` (PC) · `curl http://127.0.0.1:8090/health`.\n- [ ] **Verificar assets:** `curl -I http://localhost/ALimpiezas/Dinamic/Assets/CSS/mobile.css` → 200.\n- [ ] **Leer docs:** `docs/MANUAL-AGENTE-IA.md` (técnico), `docs/MANUAL-USUARIO.md` (UX/PWA).\n- [ ] **Convención de trabajo:** editar `Plugins/` → bootstrap → probar en móvil vía IP LAN (`http://192.168.x.x/ALimpiezas/MobileHome`, no `localhost` en iPhone).\n- [ ] **Tests PHP:** `composer test` (suite FacturaScripts en `Test/`).\n- [ ] **Serena:** proyecto `ALimpiezas`, memoria en `.serena/memories/alimpiezas/project-knowledge.md`.\n\n---\n\n## 5. Prompts guardados\n\n### Bugfix\n```\n[Bugfix ALimpiezas] Tras confirmar gasto en MobileExpenses, la FacturaProveedor no se crea o queda sin IVA.\nContexto: Plugins/ALimpiezasMobile/Lib/ExpenseInvoiceCreator.php, AiExpenseProcessor.php.\nRepro: subir ticket → confirm → revisar ai_expense_queue.status e idfacturaprov.\nNo editar Dinamic/. Tras fix: php tools/bootstrap-plugin.php.\n```\n\n### Bugfix\n```\n[Bugfix assets 403] mobile.css o manifest.json devuelven 403/404 en /ALimpiezas.\nRevisar .htaccess RewriteCond Dinamic/Assets/, rutas Twig asset('Dinamic/Assets/...'), y ejecutar bootstrap-plugin.php.\n```\n\n### Feature\n```\n[Feature gastos] Añadir campo/concepto X al modal de confirmación de MobileExpenses.\nArchivos: View/MobileExpenses.html.twig, Assets/JS/mobile.js, AiExpenseQueue model, ExpenseInvoiceCreator.\nPersistir en ai_expense_queue si hace falta nueva columna en Table/ai_expense_queue.xml + Init::update().\n```\n\n### Feature\n```\n[Feature fiscal] Mejorar borrador modelo 303/130 en MobileFiscal.\nArchivos: Lib/FiscalModels.php, FiscalCalendar.php, View/MobileFiscal.html.twig.\nMantener disclaimer: no sustituye AEAT ni asesor.\n```\n\n### Refactor\n```\n[Refactor MobileConfig] Centralizar lectura de settings alimpiezas y modos expense_mode.\nSolo Plugins/ALimpiezasMobile/Lib/MobileConfig.php y consumidores; sin cambiar comportamiento observable.\n```\n\n### Refactor\n```\n[Refactor ai-service] Extraer reglas OCR/regex de main.py a módulo separado sin cambiar respuesta JSON de /api/v1/extract-invoice.\nMantener compatibilidad con AiExpenseProcessor.php.\n```\n\n### Deploy / ops\n```\n[Deploy local] Arrancar stack ALimpiezas completo y validar salud.\nEjecutar tools/start-stack.ps1, verificar Apache/MySQL, curl :8090/health y /ALimpiezas/MobileHome.\nSi 8090 ocupado: ai-service-manager.ps1 -Restart.\n```\n\n### Deploy / ops\n```\n[Deploy plugin] Cambios en Plugins/ALimpiezasMobile listos para probar.\nEjecutar php tools/bootstrap-plugin.php, limpiar caché Twig si UI rara, verificar Dinamic/Assets copiados.\n```\n\n### QA\n```\n[QA móvil PWA] Checklist iPhone: login MobileHome, Gastos manual+OCR, confirm→FacturaProveedor, Fiscal 303 preview, Voz command local.\nURL LAN, no localhost. Modo manual sin :8090; OCR con health OK.\n```\n\n### QA\n```\n[QA ai-service] Probar endpoints FastAPI: GET /health, POST /api/v1/extract-invoice (multipart PDF/JPG), POST /api/v1/parse-intent, POST /api/v1/transcribe.\nDocumentar Tesseract/Ollama/Whisper en respuesta health.\n```\n\n---\n\n## Mapa rápido de archivos\n\n| Tarea | Archivo |\n|-------|---------|\n| Settings / modos | `Plugins/ALimpiezasMobile/Lib/MobileConfig.php`, `Init.php` |\n| Cola y upload | `Lib/AiExpenseProcessor.php`, `Controller/MobileExpenses.php` |\n| Crear factura gasto | `Lib/ExpenseInvoiceCreator.php` |\n| OCR / LLM | `ai-service/main.py` |\n| Layout PWA | `View/Master/MobileLayout.html.twig` |\n| JS gastos | `Assets/JS/mobile.js` → deploy a Dinamic |\n| Ops | `tools/bootstrap-plugin.php`, `tools/start-stack.ps1`, `tools/ai-service-manager.ps1` |\n\n---\n\n## Restricciones para el agente\n\n- **Editar:** `Plugins/`, `ai-service/`, `tools/`, `docs/` (si se pide).\n- **No escanear masivamente:** `vendor/`, `node_modules/`, `Core/`, `Dinamic/` (salvo petición explícita).\n- **Shell:** timeouts en comandos; sin bucles infinitos.\n- **Commits:** solo si el usuario lo pide explícitamente.\n\n---\n\nPuedes copiar este bloque completo a Serena con `write_memory` en `alimpiezas/project-knowledge` o pegarlo en memoria local del agente. Si quieres que lo guarde en `.serena/memories/alimpiezas/project-knowledge.md` en el repo, indícalo.","changeSessionId":"cs-1782441325772-pjwvgf","pendingChanges":0,"changes":[],"transcriptPath":null,"notifyTitle":"Agente terminado","notifyBody":"Consolidando el conocimiento del proyecto leyendo archivos clave sin escanear Core/Dinamic en profundidad.\n# ALimpiezas "},"at":1782441365271}]}
