{"id":"cs-1782352435233-k24imk99","status":"done","createdAt":1782352435233,"finishedAt":1782352468858,"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":1782352435236},{"event":"status","data":{"text":"Agente"},"at":1782352435237},{"event":"agent","data":{"agentId":"agent-a452860d-6ca9-456e-ad1c-93e7d2e9ca87","projectPath":"C:\\xampp\\htdocs\\ALimpiezas"},"at":1782352435237},{"event":"changes","data":{"sessionId":"cs-1782352435236-0hxo55","pending":0},"at":1782352435237},{"event":"status","data":{"text":"Procesando…"},"at":1782352435289},{"event":"tool_activity","data":{"activity":{"id":"tool_2ede747e-1799-4ab9-ba63-2b52d790318","name":"glob","status":"running","summary":"glob: ","detail":"","at":"2026-06-25T01:53:58.649Z"}},"at":1782352438649},{"event":"tool_activity","data":{"activity":{"id":"tool_5bf97b0f-6a9d-4640-a654-55d35c57da3","name":"glob","status":"running","summary":"glob: ","detail":"","at":"2026-06-25T01:53:58.650Z"}},"at":1782352438650},{"event":"tool_activity","data":{"activity":{"id":"tool_a170125c-bff1-4c5d-8dc1-f97a70ba401","name":"glob","status":"running","summary":"glob: ","detail":"","at":"2026-06-25T01:53:58.741Z"}},"at":1782352438741},{"event":"tool_activity","data":{"activity":{"id":"tool_21058f78-04ac-4fe0-a104-d9236219dd3","name":"glob","status":"running","summary":"glob: ","detail":"","at":"2026-06-25T01:53:58.857Z"}},"at":1782352438857},{"event":"text","data":{"chunk":"Consolidando el conocimiento del proyecto leyendo archivos clave en la raíz, `Plugins/`, `tools/`, `docs/` y `ai-service/`.\n"},"at":1782352468858},{"event":"tool_activity","data":{"activity":{"id":"tool_20c0e6a9-5a99-4317-a318-0a8ba3ce58b","name":"glob","status":"running","summary":"glob: ","detail":"","at":"2026-06-25T01:53:58.896Z"}},"at":1782352438896},{"event":"tool_activity","data":{"activity":{"id":"tool_5bf97b0f-6a9d-4640-a654-55d35c57da3","name":"glob","status":"completed","summary":"glob: ","detail":"","at":"2026-06-25T01:53:58.920Z"}},"at":1782352438920},{"event":"tool_activity","data":{"activity":{"id":"tool_20c0e6a9-5a99-4317-a318-0a8ba3ce58b","name":"glob","status":"completed","summary":"glob: ","detail":"","at":"2026-06-25T01:53:59.122Z"}},"at":1782352439122},{"event":"tool_activity","data":{"activity":{"id":"tool_a170125c-bff1-4c5d-8dc1-f97a70ba401","name":"glob","status":"completed","summary":"glob: ","detail":"","at":"2026-06-25T01:53:59.185Z"}},"at":1782352439185},{"event":"tool_activity","data":{"activity":{"id":"tool_21058f78-04ac-4fe0-a104-d9236219dd3","name":"glob","status":"completed","summary":"glob: ","detail":"","at":"2026-06-25T01:53:59.238Z"}},"at":1782352439238},{"event":"tool_activity","data":{"activity":{"id":"tool_2ede747e-1799-4ab9-ba63-2b52d790318","name":"glob","status":"completed","summary":"glob: ","detail":"","at":"2026-06-25T01:54:00.384Z"}},"at":1782352440384},{"event":"tool_activity","data":{"activity":{"id":"tool_f40d05f5-f0c3-45a7-a805-f297521e841","name":"read","status":"running","summary":"read: C:\\xampp\\htdocs\\ALimpiezas\\composer.json","detail":"","at":"2026-06-25T01:54:01.983Z"}},"at":1782352441983},{"event":"tool_activity","data":{"activity":{"id":"tool_86bccb1b-b1a8-483a-989d-b682c7cfa61","name":"read","status":"completed","summary":"read: C:\\xampp\\htdocs\\ALimpiezas\\docs\\MANUAL-AGENTE-IA.md","detail":"","at":"2026-06-25T01:54:02.097Z"}},"at":1782352442097},{"event":"tool_activity","data":{"activity":{"id":"tool_f40d05f5-f0c3-45a7-a805-f297521e841","name":"read","status":"completed","summary":"read: C:\\xampp\\htdocs\\ALimpiezas\\composer.json","detail":"","at":"2026-06-25T01:54:02.099Z"}},"at":1782352442099},{"event":"tool_activity","data":{"activity":{"id":"tool_57d22f14-bbfb-48ee-8e5c-07751c7cc68","name":"read","status":"completed","summary":"read: C:\\xampp\\htdocs\\ALimpiezas\\docs\\MOBILE-BRIDGE-TEST.md","detail":"","at":"2026-06-25T01:54:05.057Z"}},"at":1782352445057},{"event":"tool_activity","data":{"activity":{"id":"tool_057f7380-42a5-4295-90c1-f1439e731a7","name":"read","status":"completed","summary":"read: C:\\xampp\\htdocs\\ALimpiezas\\docs\\MANUAL-USUARIO.md","detail":"","at":"2026-06-25T01:54:07.745Z"}},"at":1782352447745},{"event":"tool_activity","data":{"activity":{"id":"tool_f1b47cbb-c83a-4e2a-a75b-e6d2c128ecd","name":"read","status":"completed","summary":"read: C:\\xampp\\htdocs\\ALimpiezas\\.cursor-bridge\\knowledge.json","detail":"","at":"2026-06-25T01:54:07.895Z"}},"at":1782352447895},{"event":"tool_activity","data":{"activity":{"id":"tool_7c786222-4a0e-4c8e-aa73-5cc25ae9082","name":"read","status":"running","summary":"read: C:\\xampp\\htdocs\\ALimpiezas\\Plugins\\ALimpiezasMobile\\Init.php","detail":"","at":"2026-06-25T01:54:07.918Z"}},"at":1782352447918},{"event":"tool_activity","data":{"activity":{"id":"tool_8e8aaa34-ac79-4688-a801-9fee6d2c033","name":"read","status":"running","summary":"read: C:\\xampp\\htdocs\\ALimpiezas\\Plugins\\ALimpiezasMobile\\facturascripts.ini","detail":"","at":"2026-06-25T01:54:07.919Z"}},"at":1782352447919},{"event":"tool_activity","data":{"activity":{"id":"tool_9fa84c67-d126-4fc7-8db9-2ff050142a2","name":"read","status":"running","summary":"read: C:\\xampp\\htdocs\\ALimpiezas\\ai-service\\main.py","detail":"","at":"2026-06-25T01:54:07.993Z"}},"at":1782352447993},{"event":"tool_activity","data":{"activity":{"id":"tool_7c786222-4a0e-4c8e-aa73-5cc25ae9082","name":"read","status":"completed","summary":"read: C:\\xampp\\htdocs\\ALimpiezas\\Plugins\\ALimpiezasMobile\\Init.php","detail":"","at":"2026-06-25T01:54:08.021Z"}},"at":1782352448021},{"event":"tool_activity","data":{"activity":{"id":"tool_8e8aaa34-ac79-4688-a801-9fee6d2c033","name":"read","status":"completed","summary":"read: C:\\xampp\\htdocs\\ALimpiezas\\Plugins\\ALimpiezasMobile\\facturascripts.ini","detail":"","at":"2026-06-25T01:54:08.022Z"}},"at":1782352448022},{"event":"tool_activity","data":{"activity":{"id":"tool_5bfeb3ea-034a-45c5-b392-188fde60b67","name":"read","status":"running","summary":"read: C:\\xampp\\htdocs\\ALimpiezas\\ai-service\\requirements.txt","detail":"","at":"2026-06-25T01:54:08.036Z"}},"at":1782352448036},{"event":"tool_activity","data":{"activity":{"id":"tool_9fa84c67-d126-4fc7-8db9-2ff050142a2","name":"read","status":"completed","summary":"read: C:\\xampp\\htdocs\\ALimpiezas\\ai-service\\main.py","detail":"","at":"2026-06-25T01:54:08.105Z"}},"at":1782352448105},{"event":"tool_activity","data":{"activity":{"id":"tool_5bfeb3ea-034a-45c5-b392-188fde60b67","name":"read","status":"completed","summary":"read: C:\\xampp\\htdocs\\ALimpiezas\\ai-service\\requirements.txt","detail":"","at":"2026-06-25T01:54:08.172Z"}},"at":1782352448172},{"event":"tool_activity","data":{"activity":{"id":"tool_94bd08f9-5933-42ee-896e-74d2a95ef48","name":"read","status":"running","summary":"read: C:\\xampp\\htdocs\\ALimpiezas\\tools\\bootstrap-plugin.php","detail":"","at":"2026-06-25T01:54:15.031Z"}},"at":1782352455031},{"event":"tool_activity","data":{"activity":{"id":"tool_b9709efe-c5c2-4e12-9ba7-ac6787abd29","name":"read","status":"running","summary":"read: C:\\xampp\\htdocs\\ALimpiezas\\tools\\start-stack.ps1","detail":"","at":"2026-06-25T01:54:15.048Z"}},"at":1782352455048},{"event":"tool_activity","data":{"activity":{"id":"tool_31983864-6472-4e53-a77c-435778ffa32","name":"read","status":"running","summary":"read: C:\\xampp\\htdocs\\ALimpiezas\\.htaccess","detail":"","at":"2026-06-25T01:54:15.082Z"}},"at":1782352455082},{"event":"tool_activity","data":{"activity":{"id":"tool_94bd08f9-5933-42ee-896e-74d2a95ef48","name":"read","status":"completed","summary":"read: C:\\xampp\\htdocs\\ALimpiezas\\tools\\bootstrap-plugin.php","detail":"","at":"2026-06-25T01:54:15.132Z"}},"at":1782352455132},{"event":"tool_activity","data":{"activity":{"id":"tool_b9709efe-c5c2-4e12-9ba7-ac6787abd29","name":"read","status":"completed","summary":"read: C:\\xampp\\htdocs\\ALimpiezas\\tools\\start-stack.ps1","detail":"","at":"2026-06-25T01:54:15.149Z"}},"at":1782352455149},{"event":"tool_activity","data":{"activity":{"id":"tool_31983864-6472-4e53-a77c-435778ffa32","name":"read","status":"completed","summary":"read: C:\\xampp\\htdocs\\ALimpiezas\\.htaccess","detail":"","at":"2026-06-25T01:54:15.234Z"}},"at":1782352455234},{"event":"text","data":{"chunk":"# ALimpiezas — Base de conocimiento del proyecto\n\n> **Proyecto:** `C:\\xampp\\htdocs\\ALimpiezas`  \n> **Actualizado:** 2026-06-25 · Referencia técnica: `docs/MANUAL-AGENTE-IA.md`  \n> **Formato:** optimizado para memoria Serena / knowledge local\n\n---\n\n## 1. Resumen ejecutivo\n\n**ALimpiezas** es un ERP basado en **FacturaScripts 2026.4** (PHP 8.1, Twig, Bootstrap 5) desplegado en **XAMPP** con ruta web `/ALimpiezas` y base de datos MariaDB `alimpiezas_fs`. La personalización principal es el plugin **ALimpiezasMobile**: PWA mobile-first para autónomos (gastos, fiscal 303/130, voz). El código editable vive en `Plugins/`; `Dinamic/` es generado por `Plugins::deploy()` — no editar directamente. Un microservicio **FastAPI v0.3.0** en puerto **8090** (`ai-service/`) ofrece OCR (Tesseract/PyMuPDF), extracción fiscal ES, Ollama opcional y Whisper. El flujo de gastos usa cola `ai_expense_queue` → confirmación humana → `FacturaProveedor` vía `ExpenseInvoiceCreator`. Scripts en `tools/` automatizan arranque (Apache, MySQL, IA, bandeja sistema).\n\n---\n\n## 2. Glosario\n\n| Término | Significado |\n|---------|-------------|\n| **FacturaScripts (FS)** | ERP open source LGPL; núcleo en `Core/`, capa dinámica en `Dinamic/` |\n| **Dinamic/** | Copia/symlink desplegada de plugins activos; clases `FacturaScripts\\Dinamic\\...` |\n| **Plugin** | Extensión en `Plugins/<Nombre>/`; se activa y despliega con `Plugins::enable` + `deploy` |\n| **ALimpiezasMobile** | Plugin PWA móvil: gastos, fiscal, voz, configuración independiente |\n| **FacturaProveedor** | Factura de compra/gasto recibida de un proveedor |\n| **Proveedor** | Tercero emisor de facturas de gasto; se crea/busca por CIF en el flujo IA |\n| **ai_expense_queue** | Tabla/cola de revisión: OCR/manual → usuario confirma → factura |\n| **expense_mode** | Modo gastos: `manual` (sin IA), `ocr` (Tesseract local), `ai` (OCR + Ollama) |\n| **303 / 130** | Modelos fiscales trimestrales (IVA y pago fraccionado IRPF autónomo) |\n| **MobileConfig** | Lib que lee settings grupo `alimpiezas` (modo, URL servicio, régimen) |\n| **ExpenseInvoiceCreator** | Crea `FacturaProveedor` + línea IVA + adjunto desde cola aprobada |\n| **AiExpenseProcessor** | Upload, OCR vía servicio, CRUD cola, confirm/reject |\n| **VoiceCommandBridge** | Parsea texto voz → intención navegación (`MobileExpenses`, etc.) |\n| **FiscalModels / FiscalCalendar** | Borradores 303/130 y vencimientos AEAT |\n| **PWA** | App instalable: `manifest.json`, `sw.js` en `Dinamic/Assets/` |\n| **bootstrap-plugin.php** | CLI: activa ALimpiezasMobile + rebuild Dinamic + limpia caché |\n| **ai-service-manager.ps1** | Start/stop/restart Uvicorn :8090 |\n| **start-stack.ps1** | Arranque completo: Apache, MySQL, IA, bandeja tray |\n| **Tools::settings('alimpiezas', ...)** | API FacturaScripts para configuración persistente en BD |\n| **AttachedFileRelation** | Vincula imagen/PDF original a la factura creada |\n| **Ollama** | LLM local (default `192.168.1.16:11434`, modelo `qwen2.5:7b`) usado en modo `ai` |\n| **Cursor Bridge** | Sincronización agente IDE ↔ iPhone vía `.cursor-bridge/` |\n\n---\n\n## 3. FAQ dev\n\n### ¿Dónde edito código móvil vs ERP core?\n\nEdita **solo** `Plugins/ALimpiezasMobile/` (Controller, Lib, View, Assets, Model, Table). Tras cambios ejecuta `php tools/bootstrap-plugin.php`. **No** modifiques `Dinamic/` a mano — se sobrescribe en cada deploy.\n\n### ¿Por qué los CSS/JS dan 403 Forbidden?\n\nApache reescribe todo a `index.php` excepto `Dinamic/Assets/` y `node_modules/`. Las URLs públicas deben ser `asset('Dinamic/Assets/...')`, nunca `Plugins/.../Assets/`. Tras cambiar Assets del plugin → bootstrap.\n\n### ¿Cuándo necesito el puerto 8090?\n\nSolo si `expense_mode` es `ocr` o `ai`, o si `voice_use_service=1`. Modo **manual**, fiscal y voz local **no** requieren el microservicio. Comprobar: `curl http://127.0.0.1:8090/health`.\n\n### ¿Cómo funciona el flujo de un gasto con foto?\n\nPOST `upload` → archivo guardado → si OCR/AI, llamada `/api/v1/extract-invoice` → fila en `ai_expense_queue` (pending) → modal confirmación → POST `confirm` → `ExpenseInvoiceCreator::createFromQueue` → `FacturaProveedor` + adjunto → cola `approved`.\n\n### ¿Cómo añado un setting nuevo?\n\n1. Default en `Init::update()` con `Tools::settingsSet('alimpiezas', ...)`.  \n2. Lectura en `MobileConfig` o Lib correspondiente.  \n3. UI en `MobileSettings` (form POST separado de Gastos).  \n4. Bootstrap plugin.\n\n### ¿Qué hace `Plugins::deploy(true, true)`?\n\nRegenera `Dinamic/` (clases, vistas, assets copiados), ejecuta `Init::update()` (tablas + settings) y limpia caché Twig/campos. Obligatorio tras cambiar estructura plugin o assets.\n\n### Error Errno 10048 / puerto 8090 ocupado\n\nProceso zombie Uvicorn. Usar `.\\tools\\ai-service-manager.ps1 -Restart` o `.\\tools\\port-services.ps1 -Port 8090` para identificar PID y liberar.\n\n### ¿Cómo pruebo desde iPhone en LAN?\n\nEn móvil usar `http://<IP-PC>/ALimpiezas/MobileHome`, **nunca** `localhost`. PC con XAMPP + stack arrancado (`.\\tools\\start-stack.ps1`). PWA: Safari → Compartir → Añadir a pantalla de inicio.\n\n---\n\n## 4. Checklist onboarding\n\n- [ ] **Entorno:** XAMPP (Apache + MySQL), PHP ≥8.1, Composer, Python 3 + venv para `ai-service/`\n- [ ] **Clonar/abrir:** `C:\\xampp\\htdocs\\ALimpiezas`\n- [ ] **Dependencias PHP:** `composer install --ignore-platform-req=ext-pgsql`\n- [ ] **Config:** revisar `config.php` (BD `alimpiezas_fs`, ruta `/ALimpiezas`); no commitear secretos\n- [ ] **Plugin:** `php tools/bootstrap-plugin.php` → URL móvil en salida\n- [ ] **IA (opcional):** instalar Tesseract OCR; `pip install -r ai-service/requirements.txt`; `.\\tools\\ai-service-manager.ps1 -Start`\n- [ ] **Stack completo:** `.\\tools\\start-stack.ps1` (Apache, MySQL, IA, bandeja)\n- [ ] **Smoke test:** login `http://localhost/ALimpiezas/MobileHome`, `curl :8090/health`, CSS `Dinamic/Assets/CSS/mobile.css`\n- [ ] **Leer docs:** `docs/MANUAL-AGENTE-IA.md`, `docs/MANUAL-USUARIO.md`\n- [ ] **Convención edit:** `Plugins/ALimpiezasMobile/` → bootstrap → probar en móvil y escritorio\n- [ ] **Agente:** preferir archivos concretos; evitar grep masivo en `Core/`, `Dinamic/`, `vendor/`\n- [ ] **Bridge móvil:** restricciones modo ligero/completo en prompts desde iPhone (`.cursor-bridge/`)\n\n---\n\n## 5. Prompts guardados\n\n### Bugfix\n\n```\n[Bugfix] En ALimpiezas, al confirmar un gasto en MobileExpenses aparece error X.\nRevisa Plugins/ALimpiezasMobile/Lib/ExpenseInvoiceCreator.php y AiExpenseProcessor.php.\nLee archivos concretos antes de editar. Tras fix: php tools/bootstrap-plugin.php.\nNo escanees Core/ ni Dinamic/ salvo referencia.\n```\n\n```\n[Bugfix] Assets móvil 403 Forbidden en /ALimpiezas/Dinamic/Assets/...\nVerifica .htaccess, rutas asset() en View/Master/MobileLayout.html.twig,\ny que bootstrap-plugin haya copiado Assets a Dinamic/.\n```\n\n```\n[Bugfix] Microservicio IA puerto 8090 no responde /health.\nDiagnostica con tools/port-services.ps1 y ai-service-manager.ps1 -Restart.\nRevisa Tesseract en ai-service/main.py si OCR falla.\n```\n\n### Feature\n\n```\n[Feature] Añadir campo Y al formulario confirmación gastos móvil.\nArchivos: View/MobileExpenses.html.twig, Assets/JS/mobile.js,\nModel/Table ai_expense_queue, Init.php migración, AiExpenseProcessor confirm.\nDeploy: bootstrap-plugin.php. Mantén modo manual sin depender de 8090.\n```\n\n```\n[Feature] Nueva intención de voz \"ir a ayuda\" en VoiceCommandBridge.\nActualiza VoiceCommandBridge.php, MobileVoice.php, voice.js y Translation/es_ES.json.\nFallback localParse debe funcionar sin servicio IA.\n```\n\n```\n[Feature] Mejorar extracción OCR de facturas ES en ai-service/main.py.\nReglas regex/NIF en main.py; probar con PDF/imagen de ejemplo.\nNo romper contrato JSON de /api/v1/extract-invoice (validation_errors, field_status).\n```\n\n### Refactor\n\n```\n[Refactor] Extraer lógica fiscal duplicada en FiscalModels.php sin cambiar cálculos 303/130.\nScope mínimo; no tocar Dinamic/. Tests manuales: MobileFiscal borradores trimestre actual.\n```\n\n```\n[Refactor] Unificar lectura settings alimpiezas en MobileConfig.\nBusca Tools::settings('alimpiezas' solo en Plugins/ALimpiezasMobile/.\nMantén compatibilidad expense_mode manual|ocr|ai.\n```\n\n### Deploy\n\n```\n[Deploy] Arrancar stack ALimpiezas en Windows limpio.\nEjecuta tools/start-stack.ps1, verifica Apache/MySQL, curl :8090/health y /ALimpiezas.\nDocumenta IP LAN para iPhone. Opcional: tools/install-autostart.ps1.\n```\n\n```\n[Deploy] Rebuild completo plugin tras merge.\nSecuencia: composer install, php tools/bootstrap-plugin.php,\nai-service-manager -Restart, limpiar MyFiles/Cache/Twig si vistas rotas.\n```\n\n### QA\n\n```\n[QA] Checklist regresión móvil ALimpiezasMobile.\nProbar: login, MobileHome, gasto manual, gasto OCR (8090 up), MobileFiscal 303,\nMobileVoice comando local, MobileSettings cambio modo, PWA manifest/sw.js.\nReportar rutas y capturas de error.\n```\n\n```\n[QA] Verificar flujo cola ai_expense_queue end-to-end.\nupload → pending → get_item JSON → confirm → FacturaProveedor en ERP escritorio.\nreject debe marcar rejected sin crear factura.\n```\n\n---\n\n## Mapa rápido de archivos clave\n\n| Tarea | Ruta |\n|-------|------|\n| Settings / modos | `Plugins/ALimpiezasMobile/Lib/MobileConfig.php` |\n| Cola y upload | `Plugins/ALimpiezasMobile/Lib/AiExpenseProcessor.php` |\n| Crear factura gasto | `Plugins/ALimpiezasMobile/Lib/ExpenseInvoiceCreator.php` |\n| OCR / API Python | `ai-service/main.py` |\n| UI layout móvil | `Plugins/ALimpiezasMobile/View/Master/MobileLayout.html.twig` |\n| JS gastos | `Plugins/ALimpiezasMobile/Assets/JS/mobile.js` |\n| Deploy plugin | `tools/bootstrap-plugin.php` |\n| Arranque stack | `tools/start-stack.ps1` |\n| Manual agente | `docs/MANUAL-AGENTE-IA.md` |\n\n---\n\n## Restricciones agente (Bridge móvil)\n\n- Preguntas simples → responder sin herramientas.\n- No grep/glob recursivo en `vendor/`, `node_modules/`, `Core/`, `Dinamic/` salvo petición explícita.\n- Preferir archivos concretos y herramientas simbólicas (Serena).\n- Editar `Plugins/`, desplegar con bootstrap; assets públicos solo vía `Dinamic/Assets/`.\n\n---\n\n## Convenciones críticas (resumen)\n\n| Regla | Detalle |\n|-------|---------|\n| Namespace plugin | `FacturaScripts\\Plugins\\ALimpiezasMobile\\...` |\n| Modelos ERP en plugin | Importar `FacturaScripts\\Dinamic\\Model\\*`, no `Core\\Model` |\n| Settings runtime | `Tools::settings('alimpiezas', 'clave')` — grupo fijo `alimpiezas` |\n| POST móvil | Parámetro `action`: `upload`, `confirm`, `reject`, `manual`, `get_item` |\n| Respuestas JSON | `['ok' => bool, 'message' => string, ...]` |\n| Tras cada cambio plugin | `php tools/bootstrap-plugin.php` |\n\n---\n\n*Documento consolidado para sesiones futuras del agente. Fuente canónica extendida: `docs/MANUAL-AGENTE-IA.md`.*"},"at":1782352468858},{"event":"status","data":{"text":"Procesando…"},"at":1782352468850},{"event":"phase_saved","data":{"phaseId":"knowledge","progress":{"status":"done","completedAt":"2026-06-25T01:54:28.853Z","name":"Conocimiento","summary":"Consolidando el conocimiento del proyecto leyendo archivos clave en la raíz, `Plugins/`, `tools/`, `docs/` y `ai-service/`.\n# ALimpiezas — Base de conocimiento del proyecto\n\n> **Proyecto:** `C:\\xampp\\htdocs\\ALimpiezas`  \n> **Actualizado:** 2026-06-25 · Referencia técnica: `docs/MANUAL-AGENTE-IA.md`  \n> **Formato:** optimizado para memoria Serena / knowledge local\n\n---\n\n## 1. Resumen ejecutivo\n\n**ALimpiezas** es un ERP basado en **FacturaScripts 2026.4** (PHP 8.1, Twig, Bootstrap 5) desplegado en **XAMPP** con ruta web `/ALimpiezas` y base de datos MariaDB `alimpiezas_fs`. La personalización pr","fullText":"Consolidando el conocimiento del proyecto leyendo archivos clave en la raíz, `Plugins/`, `tools/`, `docs/` y `ai-service/`.\n# ALimpiezas — Base de conocimiento del proyecto\n\n> **Proyecto:** `C:\\xampp\\htdocs\\ALimpiezas`  \n> **Actualizado:** 2026-06-25 · Referencia técnica: `docs/MANUAL-AGENTE-IA.md`  \n> **Formato:** optimizado para memoria Serena / knowledge local\n\n---\n\n## 1. Resumen ejecutivo\n\n**ALimpiezas** es un ERP basado en **FacturaScripts 2026.4** (PHP 8.1, Twig, Bootstrap 5) desplegado en **XAMPP** con ruta web `/ALimpiezas` y base de datos MariaDB `alimpiezas_fs`. La personalización principal es el plugin **ALimpiezasMobile**: PWA mobile-first para autónomos (gastos, fiscal 303/130, voz). El código editable vive en `Plugins/`; `Dinamic/` es generado por `Plugins::deploy()` — no editar directamente. Un microservicio **FastAPI v0.3.0** en puerto **8090** (`ai-service/`) ofrece OCR (Tesseract/PyMuPDF), extracción fiscal ES, Ollama opcional y Whisper. El flujo de gastos usa cola `ai_expense_queue` → confirmación humana → `FacturaProveedor` vía `ExpenseInvoiceCreator`. Scripts en `tools/` automatizan arranque (Apache, MySQL, IA, bandeja sistema).\n\n---\n\n## 2. Glosario\n\n| Término | Significado |\n|---------|-------------|\n| **FacturaScripts (FS)** | ERP open source LGPL; núcleo en `Core/`, capa dinámica en `Dinamic/` |\n| **Dinamic/** | Copia/symlink desplegada de plugins activos; clases `FacturaScripts\\Dinamic\\...` |\n| **Plugin** | Extensión en `Plugins/<Nombre>/`; se activa y despliega con `Plugins::enable` + `deploy` |\n| **ALimpiezasMobile** | Plugin PWA móvil: gastos, fiscal, voz, configuración independiente |\n| **FacturaProveedor** | Factura de compra/gasto recibida de un proveedor |\n| **Proveedor** | Tercero emisor de facturas de gasto; se crea/busca por CIF en el flujo IA |\n| **ai_expense_queue** | Tabla/cola de revisión: OCR/manual → usuario confirma → factura |\n| **expense_mode** | Modo gastos: `manual` (sin IA), `ocr` (Tesseract local), `ai` (OCR + Ollama) |\n| **303 / 130** | Modelos fiscales trimestrales (IVA y pago fraccionado IRPF autónomo) |\n| **MobileConfig** | Lib que lee settings grupo `alimpiezas` (modo, URL servicio, régimen) |\n| **ExpenseInvoiceCreator** | Crea `FacturaProveedor` + línea IVA + adjunto desde cola aprobada |\n| **AiExpenseProcessor** | Upload, OCR vía servicio, CRUD cola, confirm/reject |\n| **VoiceCommandBridge** | Parsea texto voz → intención navegación (`MobileExpenses`, etc.) |\n| **FiscalModels / FiscalCalendar** | Borradores 303/130 y vencimientos AEAT |\n| **PWA** | App instalable: `manifest.json`, `sw.js` en `Dinamic/Assets/` |\n| **bootstrap-plugin.php** | CLI: activa ALimpiezasMobile + rebuild Dinamic + limpia caché |\n| **ai-service-manager.ps1** | Start/stop/restart Uvicorn :8090 |\n| **start-stack.ps1** | Arranque completo: Apache, MySQL, IA, bandeja tray |\n| **Tools::settings('alimpiezas', ...)** | API FacturaScripts para configuración persistente en BD |\n| **AttachedFileRelation** | Vincula imagen/PDF original a la factura creada |\n| **Ollama** | LLM local (default `192.168.1.16:11434`, modelo `qwen2.5:7b`) usado en modo `ai` |\n| **Cursor Bridge** | Sincronización agente IDE ↔ iPhone vía `.cursor-bridge/` |\n\n---\n\n## 3. FAQ dev\n\n### ¿Dónde edito código móvil vs ERP core?\n\nEdita **solo** `Plugins/ALimpiezasMobile/` (Controller, Lib, View, Assets, Model, Table). Tras cambios ejecuta `php tools/bootstrap-plugin.php`. **No** modifiques `Dinamic/` a mano — se sobrescribe en cada deploy.\n\n### ¿Por qué los CSS/JS dan 403 Forbidden?\n\nApache reescribe todo a `index.php` excepto `Dinamic/Assets/` y `node_modules/`. Las URLs públicas deben ser `asset('Dinamic/Assets/...')`, nunca `Plugins/.../Assets/`. Tras cambiar Assets del plugin → bootstrap.\n\n### ¿Cuándo necesito el puerto 8090?\n\nSolo si `expense_mode` es `ocr` o `ai`, o si `voice_use_service=1`. Modo **manual**, fiscal y voz local **no** requieren el microservicio. Comprobar: `curl http://127.0.0.1:8090/health`.\n\n### ¿Cómo funciona el flujo de un gasto con foto?\n\nPOST `upload` → archivo guardado → si OCR/AI, llamada `/api/v1/extract-invoice` → fila en `ai_expense_queue` (pending) → modal confirmación → POST `confirm` → `ExpenseInvoiceCreator::createFromQueue` → `FacturaProveedor` + adjunto → cola `approved`.\n\n### ¿Cómo añado un setting nuevo?\n\n1. Default en `Init::update()` con `Tools::settingsSet('alimpiezas', ...)`.  \n2. Lectura en `MobileConfig` o Lib correspondiente.  \n3. UI en `MobileSettings` (form POST separado de Gastos).  \n4. Bootstrap plugin.\n\n### ¿Qué hace `Plugins::deploy(true, true)`?\n\nRegenera `Dinamic/` (clases, vistas, assets copiados), ejecuta `Init::update()` (tablas + settings) y limpia caché Twig/campos. Obligatorio tras cambiar estructura plugin o assets.\n\n### Error Errno 10048 / puerto 8090 ocupado\n\nProceso zombie Uvicorn. Usar `.\\tools\\ai-service-manager.ps1 -Restart` o `.\\tools\\port-services.ps1 -Port 8090` para identificar PID y liberar.\n\n### ¿Cómo pruebo desde iPhone en LAN?\n\nEn móvil usar `http://<IP-PC>/ALimpiezas/MobileHome`, **nunca** `localhost`. PC con XAMPP + stack arrancado (`.\\tools\\start-stack.ps1`). PWA: Safari → Compartir → Añadir a pantalla de inicio.\n\n---\n\n## 4. Checklist onboarding\n\n- [ ] **Entorno:** XAMPP (Apache + MySQL), PHP ≥8.1, Composer, Python 3 + venv para `ai-service/`\n- [ ] **Clonar/abrir:** `C:\\xampp\\htdocs\\ALimpiezas`\n- [ ] **Dependencias PHP:** `composer install --ignore-platform-req=ext-pgsql`\n- [ ] **Config:** revisar `config.php` (BD `alimpiezas_fs`, ruta `/ALimpiezas`); no commitear secretos\n- [ ] **Plugin:** `php tools/bootstrap-plugin.php` → URL móvil en salida\n- [ ] **IA (opcional):** instalar Tesseract OCR; `pip install -r ai-service/requirements.txt`; `.\\tools\\ai-service-manager.ps1 -Start`\n- [ ] **Stack completo:** `.\\tools\\start-stack.ps1` (Apache, MySQL, IA, bandeja)\n- [ ] **Smoke test:** login `http://localhost/ALimpiezas/MobileHome`, `curl :8090/health`, CSS `Dinamic/Assets/CSS/mobile.css`\n- [ ] **Leer docs:** `docs/MANUAL-AGENTE-IA.md`, `docs/MANUAL-USUARIO.md`\n- [ ] **Convención edit:** `Plugins/ALimpiezasMobile/` → bootstrap → probar en móvil y escritorio\n- [ ] **Agente:** preferir archivos concretos; evitar grep masivo en `Core/`, `Dinamic/`, `vendor/`\n- [ ] **Bridge móvil:** restricciones modo ligero/completo en prompts desde iPhone (`.cursor-bridge/`)\n\n---\n\n## 5. Prompts guardados\n\n### Bugfix\n\n```\n[Bugfix] En ALimpiezas, al confirmar un gasto en MobileExpenses aparece error X.\nRevisa Plugins/ALimpiezasMobile/Lib/ExpenseInvoiceCreator.php y AiExpenseProcessor.php.\nLee archivos concretos antes de editar. Tras fix: php tools/bootstrap-plugin.php.\nNo escanees Core/ ni Dinamic/ salvo referencia.\n```\n\n```\n[Bugfix] Assets móvil 403 Forbidden en /ALimpiezas/Dinamic/Assets/...\nVerifica .htaccess, rutas asset() en View/Master/MobileLayout.html.twig,\ny que bootstrap-plugin haya copiado Assets a Dinamic/.\n```\n\n```\n[Bugfix] Microservicio IA puerto 8090 no responde /health.\nDiagnostica con tools/port-services.ps1 y ai-service-manager.ps1 -Restart.\nRevisa Tesseract en ai-service/main.py si OCR falla.\n```\n\n### Feature\n\n```\n[Feature] Añadir campo Y al formulario confirmación gastos móvil.\nArchivos: View/MobileExpenses.html.twig, Assets/JS/mobile.js,\nModel/Table ai_expense_queue, Init.php migración, AiExpenseProcessor confirm.\nDeploy: bootstrap-plugin.php. Mantén modo manual sin depender de 8090.\n```\n\n```\n[Feature] Nueva intención de voz \"ir a ayuda\" en VoiceCommandBridge.\nActualiza VoiceCommandBridge.php, MobileVoice.php, voice.js y Translation/es_ES.json.\nFallback localParse debe funcionar sin servicio IA.\n```\n\n```\n[Feature] Mejorar extracción OCR de facturas ES en ai-service/main.py.\nReglas regex/NIF en main.py; probar con PDF/imagen de ejemplo.\nNo romper contrato JSON de /api/v1/extract-invoice (validation_errors, field_status).\n```\n\n### Refactor\n\n```\n[Refactor] Extraer lógica fiscal duplicada en FiscalModels.php sin cambiar cálculos 303/130.\nScope mínimo; no tocar Dinamic/. Tests manuales: MobileFiscal borradores trimestre actual.\n```\n\n```\n[Refactor] Unificar lectura settings alimpiezas en MobileConfig.\nBusca Tools::settings('alimpiezas' solo en Plugins/ALimpiezasMobile/.\nMantén compatibilidad expense_mode manual|ocr|ai.\n```\n\n### Deploy\n\n```\n[Deploy] Arrancar stack ALimpiezas en Windows limpio.\nEjecuta tools/start-stack.ps1, verifica Apache/MySQL, curl :8090/health y /ALimpiezas.\nDocumenta IP LAN para iPhone. Opcional: tools/install-autostart.ps1.\n```\n\n```\n[Deploy] Rebuild completo plugin tras merge.\nSecuencia: composer install, php tools/bootstrap-plugin.php,\nai-service-manager -Restart, limpiar MyFiles/Cache/Twig si vistas rotas.\n```\n\n### QA\n\n```\n[QA] Checklist regresión móvil ALimpiezasMobile.\nProbar: login, MobileHome, gasto manual, gasto OCR (8090 up), MobileFiscal 303,\nMobileVoice comando local, MobileSettings cambio modo, PWA manifest/sw.js.\nReportar rutas y capturas de error.\n```\n\n```\n[QA] Verificar flujo cola ai_expense_queue end-to-end.\nupload → pending → get_item JSON → confirm → FacturaProveedor en ERP escritorio.\nreject debe marcar rejected sin crear factura.\n```\n\n---\n\n## Mapa rápido de archivos clave\n\n| Tarea | Ruta |\n|-------|------|\n| Settings / modos | `Plugins/ALimpiezasMobile/Lib/MobileConfig.php` |\n| Cola y upload | `Plugins/ALimpiezasMobile/Lib/AiExpenseProcessor.php` |\n| Crear factura gasto | `Plugins/ALimpiezasMobile/Lib/ExpenseInvoiceCreator.php` |\n| OCR / API Python | `ai-service/main.py` |\n| UI layout móvil | `Plugins/ALimpiezasMobile/View/Master/MobileLayout.html.twig` |\n| JS gastos | `Plugins/ALimpiezasMobile/Assets/JS/mobile.js` |\n| Deploy plugin | `tools/bootstrap-plugin.php` |\n| Arranque stack | `tools/start-stack.ps1` |\n| Manual agente | `docs/MANUAL-AGENTE-IA.md` |\n\n---\n\n## Restricciones agente (Bridge móvil)\n\n- Preguntas simples → responder sin herramientas.\n- No grep/glob recursivo en `vendor/`, `node_modules/`, `Core/`, `Dinamic/` salvo petición explícita.\n- Preferir archivos concretos y herramientas simbólicas (Serena).\n- Editar `Plugins/`, desplegar con bootstrap; assets públicos solo vía `Dinamic/Assets/`.\n\n---\n\n## Convenciones críticas (resumen)\n\n| Regla | Detalle |\n|-------|---------|\n| Namespace plugin | `FacturaScripts\\Plugins\\ALimpiezasMobile\\...` |\n| Modelos ERP en plugin | Importar `FacturaScripts\\Dinamic\\Model\\*`, no `Core\\Model` |\n| Settings runtime | `Tools::settings('alimpiezas', 'clave')` — grupo fijo `alimpiezas` |\n| POST móvil | Parámetro `action`: `upload`, `confirm`, `reject`, `manual`, `get_item` |\n| Respuestas JSON | `['ok' => bool, 'message' => string, ...]` |\n| Tras cada cambio plugin | `php tools/bootstrap-plugin.php` |\n\n---\n\n*Documento consolidado para sesiones futuras del agente. Fuente canónica extendida: `docs/MANUAL-AGENTE-IA.md`.*"}},"at":1782352468855},{"event":"done","data":{"ok":true,"bridgeSessionId":"bs-1782352468851-m53d5a","agentId":"agent-a452860d-6ca9-456e-ad1c-93e7d2e9ca87","runId":"run-aed79dd4-5948-4d4d-a3b5-84e94a5e5f92","status":"finished","result":"# ALimpiezas — Base de conocimiento del proyecto\n\n> **Proyecto:** `C:\\xampp\\htdocs\\ALimpiezas`  \n> **Actualizado:** 2026-06-25 · Referencia técnica: `docs/MANUAL-AGENTE-IA.md`  \n> **Formato:** optimizado para memoria Serena / knowledge local\n\n---\n\n## 1. Resumen ejecutivo\n\n**ALimpiezas** es un ERP basado en **FacturaScripts 2026.4** (PHP 8.1, Twig, Bootstrap 5) desplegado en **XAMPP** con ruta web `/ALimpiezas` y base de datos MariaDB `alimpiezas_fs`. La personalización principal es el plugin **ALimpiezasMobile**: PWA mobile-first para autónomos (gastos, fiscal 303/130, voz). El código editable vive en `Plugins/`; `Dinamic/` es generado por `Plugins::deploy()` — no editar directamente. Un microservicio **FastAPI v0.3.0** en puerto **8090** (`ai-service/`) ofrece OCR (Tesseract/PyMuPDF), extracción fiscal ES, Ollama opcional y Whisper. El flujo de gastos usa cola `ai_expense_queue` → confirmación humana → `FacturaProveedor` vía `ExpenseInvoiceCreator`. Scripts en `tools/` automatizan arranque (Apache, MySQL, IA, bandeja sistema).\n\n---\n\n## 2. Glosario\n\n| Término | Significado |\n|---------|-------------|\n| **FacturaScripts (FS)** | ERP open source LGPL; núcleo en `Core/`, capa dinámica en `Dinamic/` |\n| **Dinamic/** | Copia/symlink desplegada de plugins activos; clases `FacturaScripts\\Dinamic\\...` |\n| **Plugin** | Extensión en `Plugins/<Nombre>/`; se activa y despliega con `Plugins::enable` + `deploy` |\n| **ALimpiezasMobile** | Plugin PWA móvil: gastos, fiscal, voz, configuración independiente |\n| **FacturaProveedor** | Factura de compra/gasto recibida de un proveedor |\n| **Proveedor** | Tercero emisor de facturas de gasto; se crea/busca por CIF en el flujo IA |\n| **ai_expense_queue** | Tabla/cola de revisión: OCR/manual → usuario confirma → factura |\n| **expense_mode** | Modo gastos: `manual` (sin IA), `ocr` (Tesseract local), `ai` (OCR + Ollama) |\n| **303 / 130** | Modelos fiscales trimestrales (IVA y pago fraccionado IRPF autónomo) |\n| **MobileConfig** | Lib que lee settings grupo `alimpiezas` (modo, URL servicio, régimen) |\n| **ExpenseInvoiceCreator** | Crea `FacturaProveedor` + línea IVA + adjunto desde cola aprobada |\n| **AiExpenseProcessor** | Upload, OCR vía servicio, CRUD cola, confirm/reject |\n| **VoiceCommandBridge** | Parsea texto voz → intención navegación (`MobileExpenses`, etc.) |\n| **FiscalModels / FiscalCalendar** | Borradores 303/130 y vencimientos AEAT |\n| **PWA** | App instalable: `manifest.json`, `sw.js` en `Dinamic/Assets/` |\n| **bootstrap-plugin.php** | CLI: activa ALimpiezasMobile + rebuild Dinamic + limpia caché |\n| **ai-service-manager.ps1** | Start/stop/restart Uvicorn :8090 |\n| **start-stack.ps1** | Arranque completo: Apache, MySQL, IA, bandeja tray |\n| **Tools::settings('alimpiezas', ...)** | API FacturaScripts para configuración persistente en BD |\n| **AttachedFileRelation** | Vincula imagen/PDF original a la factura creada |\n| **Ollama** | LLM local (default `192.168.1.16:11434`, modelo `qwen2.5:7b`) usado en modo `ai` |\n| **Cursor Bridge** | Sincronización agente IDE ↔ iPhone vía `.cursor-bridge/` |\n\n---\n\n## 3. FAQ dev\n\n### ¿Dónde edito código móvil vs ERP core?\n\nEdita **solo** `Plugins/ALimpiezasMobile/` (Controller, Lib, View, Assets, Model, Table). Tras cambios ejecuta `php tools/bootstrap-plugin.php`. **No** modifiques `Dinamic/` a mano — se sobrescribe en cada deploy.\n\n### ¿Por qué los CSS/JS dan 403 Forbidden?\n\nApache reescribe todo a `index.php` excepto `Dinamic/Assets/` y `node_modules/`. Las URLs públicas deben ser `asset('Dinamic/Assets/...')`, nunca `Plugins/.../Assets/`. Tras cambiar Assets del plugin → bootstrap.\n\n### ¿Cuándo necesito el puerto 8090?\n\nSolo si `expense_mode` es `ocr` o `ai`, o si `voice_use_service=1`. Modo **manual**, fiscal y voz local **no** requieren el microservicio. Comprobar: `curl http://127.0.0.1:8090/health`.\n\n### ¿Cómo funciona el flujo de un gasto con foto?\n\nPOST `upload` → archivo guardado → si OCR/AI, llamada `/api/v1/extract-invoice` → fila en `ai_expense_queue` (pending) → modal confirmación → POST `confirm` → `ExpenseInvoiceCreator::createFromQueue` → `FacturaProveedor` + adjunto → cola `approved`.\n\n### ¿Cómo añado un setting nuevo?\n\n1. Default en `Init::update()` con `Tools::settingsSet('alimpiezas', ...)`.  \n2. Lectura en `MobileConfig` o Lib correspondiente.  \n3. UI en `MobileSettings` (form POST separado de Gastos).  \n4. Bootstrap plugin.\n\n### ¿Qué hace `Plugins::deploy(true, true)`?\n\nRegenera `Dinamic/` (clases, vistas, assets copiados), ejecuta `Init::update()` (tablas + settings) y limpia caché Twig/campos. Obligatorio tras cambiar estructura plugin o assets.\n\n### Error Errno 10048 / puerto 8090 ocupado\n\nProceso zombie Uvicorn. Usar `.\\tools\\ai-service-manager.ps1 -Restart` o `.\\tools\\port-services.ps1 -Port 8090` para identificar PID y liberar.\n\n### ¿Cómo pruebo desde iPhone en LAN?\n\nEn móvil usar `http://<IP-PC>/ALimpiezas/MobileHome`, **nunca** `localhost`. PC con XAMPP + stack arrancado (`.\\tools\\start-stack.ps1`). PWA: Safari → Compartir → Añadir a pantalla de inicio.\n\n---\n\n## 4. Checklist onboarding\n\n- [ ] **Entorno:** XAMPP (Apache + MySQL), PHP ≥8.1, Composer, Python 3 + venv para `ai-service/`\n- [ ] **Clonar/abrir:** `C:\\xampp\\htdocs\\ALimpiezas`\n- [ ] **Dependencias PHP:** `composer install --ignore-platform-req=ext-pgsql`\n- [ ] **Config:** revisar `config.php` (BD `alimpiezas_fs`, ruta `/ALimpiezas`); no commitear secretos\n- [ ] **Plugin:** `php tools/bootstrap-plugin.php` → URL móvil en salida\n- [ ] **IA (opcional):** instalar Tesseract OCR; `pip install -r ai-service/requirements.txt`; `.\\tools\\ai-service-manager.ps1 -Start`\n- [ ] **Stack completo:** `.\\tools\\start-stack.ps1` (Apache, MySQL, IA, bandeja)\n- [ ] **Smoke test:** login `http://localhost/ALimpiezas/MobileHome`, `curl :8090/health`, CSS `Dinamic/Assets/CSS/mobile.css`\n- [ ] **Leer docs:** `docs/MANUAL-AGENTE-IA.md`, `docs/MANUAL-USUARIO.md`\n- [ ] **Convención edit:** `Plugins/ALimpiezasMobile/` → bootstrap → probar en móvil y escritorio\n- [ ] **Agente:** preferir archivos concretos; evitar grep masivo en `Core/`, `Dinamic/`, `vendor/`\n- [ ] **Bridge móvil:** restricciones modo ligero/completo en prompts desde iPhone (`.cursor-bridge/`)\n\n---\n\n## 5. Prompts guardados\n\n### Bugfix\n\n```\n[Bugfix] En ALimpiezas, al confirmar un gasto en MobileExpenses aparece error X.\nRevisa Plugins/ALimpiezasMobile/Lib/ExpenseInvoiceCreator.php y AiExpenseProcessor.php.\nLee archivos concretos antes de editar. Tras fix: php tools/bootstrap-plugin.php.\nNo escanees Core/ ni Dinamic/ salvo referencia.\n```\n\n```\n[Bugfix] Assets móvil 403 Forbidden en /ALimpiezas/Dinamic/Assets/...\nVerifica .htaccess, rutas asset() en View/Master/MobileLayout.html.twig,\ny que bootstrap-plugin haya copiado Assets a Dinamic/.\n```\n\n```\n[Bugfix] Microservicio IA puerto 8090 no responde /health.\nDiagnostica con tools/port-services.ps1 y ai-service-manager.ps1 -Restart.\nRevisa Tesseract en ai-service/main.py si OCR falla.\n```\n\n### Feature\n\n```\n[Feature] Añadir campo Y al formulario confirmación gastos móvil.\nArchivos: View/MobileExpenses.html.twig, Assets/JS/mobile.js,\nModel/Table ai_expense_queue, Init.php migración, AiExpenseProcessor confirm.\nDeploy: bootstrap-plugin.php. Mantén modo manual sin depender de 8090.\n```\n\n```\n[Feature] Nueva intención de voz \"ir a ayuda\" en VoiceCommandBridge.\nActualiza VoiceCommandBridge.php, MobileVoice.php, voice.js y Translation/es_ES.json.\nFallback localParse debe funcionar sin servicio IA.\n```\n\n```\n[Feature] Mejorar extracción OCR de facturas ES en ai-service/main.py.\nReglas regex/NIF en main.py; probar con PDF/imagen de ejemplo.\nNo romper contrato JSON de /api/v1/extract-invoice (validation_errors, field_status).\n```\n\n### Refactor\n\n```\n[Refactor] Extraer lógica fiscal duplicada en FiscalModels.php sin cambiar cálculos 303/130.\nScope mínimo; no tocar Dinamic/. Tests manuales: MobileFiscal borradores trimestre actual.\n```\n\n```\n[Refactor] Unificar lectura settings alimpiezas en MobileConfig.\nBusca Tools::settings('alimpiezas' solo en Plugins/ALimpiezasMobile/.\nMantén compatibilidad expense_mode manual|ocr|ai.\n```\n\n### Deploy\n\n```\n[Deploy] Arrancar stack ALimpiezas en Windows limpio.\nEjecuta tools/start-stack.ps1, verifica Apache/MySQL, curl :8090/health y /ALimpiezas.\nDocumenta IP LAN para iPhone. Opcional: tools/install-autostart.ps1.\n```\n\n```\n[Deploy] Rebuild completo plugin tras merge.\nSecuencia: composer install, php tools/bootstrap-plugin.php,\nai-service-manager -Restart, limpiar MyFiles/Cache/Twig si vistas rotas.\n```\n\n### QA\n\n```\n[QA] Checklist regresión móvil ALimpiezasMobile.\nProbar: login, MobileHome, gasto manual, gasto OCR (8090 up), MobileFiscal 303,\nMobileVoice comando local, MobileSettings cambio modo, PWA manifest/sw.js.\nReportar rutas y capturas de error.\n```\n\n```\n[QA] Verificar flujo cola ai_expense_queue end-to-end.\nupload → pending → get_item JSON → confirm → FacturaProveedor en ERP escritorio.\nreject debe marcar rejected sin crear factura.\n```\n\n---\n\n## Mapa rápido de archivos clave\n\n| Tarea | Ruta |\n|-------|------|\n| Settings / modos | `Plugins/ALimpiezasMobile/Lib/MobileConfig.php` |\n| Cola y upload | `Plugins/ALimpiezasMobile/Lib/AiExpenseProcessor.php` |\n| Crear factura gasto | `Plugins/ALimpiezasMobile/Lib/ExpenseInvoiceCreator.php` |\n| OCR / API Python | `ai-service/main.py` |\n| UI layout móvil | `Plugins/ALimpiezasMobile/View/Master/MobileLayout.html.twig` |\n| JS gastos | `Plugins/ALimpiezasMobile/Assets/JS/mobile.js` |\n| Deploy plugin | `tools/bootstrap-plugin.php` |\n| Arranque stack | `tools/start-stack.ps1` |\n| Manual agente | `docs/MANUAL-AGENTE-IA.md` |\n\n---\n\n## Restricciones agente (Bridge móvil)\n\n- Preguntas simples → responder sin herramientas.\n- No grep/glob recursivo en `vendor/`, `node_modules/`, `Core/`, `Dinamic/` salvo petición explícita.\n- Preferir archivos concretos y herramientas simbólicas (Serena).\n- Editar `Plugins/`, desplegar con bootstrap; assets públicos solo vía `Dinamic/Assets/`.\n\n---\n\n## Convenciones críticas (resumen)\n\n| Regla | Detalle |\n|-------|---------|\n| Namespace plugin | `FacturaScripts\\Plugins\\ALimpiezasMobile\\...` |\n| Modelos ERP en plugin | Importar `FacturaScripts\\Dinamic\\Model\\*`, no `Core\\Model` |\n| Settings runtime | `Tools::settings('alimpiezas', 'clave')` — grupo fijo `alimpiezas` |\n| POST móvil | Parámetro `action`: `upload`, `confirm`, `reject`, `manual`, `get_item` |\n| Respuestas JSON | `['ok' => bool, 'message' => string, ...]` |\n| Tras cada cambio plugin | `php tools/bootstrap-plugin.php` |\n\n---\n\n*Documento consolidado para sesiones futuras del agente. Fuente canónica extendida: `docs/MANUAL-AGENTE-IA.md`.*","changeSessionId":"cs-1782352435236-0hxo55","pendingChanges":0,"changes":[],"transcriptPath":null,"notifyTitle":"Agente terminado","notifyBody":"Consolidando el conocimiento del proyecto leyendo archivos clave en la raíz, `Plugins/`, `tools/`, `docs/` y `ai-service"},"at":1782352468856}]}
