diff --git a/.agents/agent_assets_metadata.toml b/.agents/agent_assets_metadata.toml deleted file mode 100644 index dc970f3..0000000 --- a/.agents/agent_assets_metadata.toml +++ /dev/null @@ -1,38 +0,0 @@ -uploads = [] -generated = [] - -[[outputs]] -id = "28NDwt4UT3HPglsSw-IQk" -uri = "file://MAPA_MICROSERVICOS_COOLIFY.md" -type = "text" -title = "Mapa de Microserviços - Arcádia Suite para Coolify/Docker" - -[[outputs]] -id = "YTVCn39myPk5kzF8smbQz" -uri = "file://MAPA_SOE_ARCADIA.md" -type = "text" -title = "Mapa SOE — Sistema Operacional Empresarial (Deploy)" - -[[outputs]] -id = "pQjx1X6m9hp2j-sZa0_Rg" -uri = "file://MAPA_BI_ARCADIA.md" -type = "text" -title = "Mapa BI - Business Intelligence da Arcádia Suite (com Metabase)" - -[[outputs]] -id = "gpyYTqB0ytdU1zAJij6KK" -uri = "file://MAPA_CRM_ARCADIA.md" -type = "text" -title = "Mapa CRM - Sistema de Relacionamento da Arcádia Suite" - -[[outputs]] -id = "zal1KfcZdP7OqKEXu67Pp" -uri = "file://MAPA_TENANTS_ARCADIA.md" -type = "text" -title = "Mapa Multi-Tenant - Gestão de Tenants da Arcádia Suite" - -[[outputs]] -id = "GCMgcBAHQ1aIDjHxoXniQ" -uri = "file://MAPA_AUTOMACOES_ARCADIA.md" -type = "text" -title = "Mapa Automações - Motor de Automação da Arcádia Suite" diff --git a/.aider.tags.cache.v4/04/0a/56e741721cc7d14a53af4160a147.val b/.aider.tags.cache.v4/04/0a/56e741721cc7d14a53af4160a147.val deleted file mode 100644 index dd84224..0000000 Binary files a/.aider.tags.cache.v4/04/0a/56e741721cc7d14a53af4160a147.val and /dev/null differ diff --git a/.aider.tags.cache.v4/09/fa/217ecc6f0eb0bb0a4f968517c822.val b/.aider.tags.cache.v4/09/fa/217ecc6f0eb0bb0a4f968517c822.val deleted file mode 100644 index 3f7a1ca..0000000 Binary files a/.aider.tags.cache.v4/09/fa/217ecc6f0eb0bb0a4f968517c822.val and /dev/null differ diff --git a/.aider.tags.cache.v4/0d/50/c58538e018af5c9d26f49bb69057.val b/.aider.tags.cache.v4/0d/50/c58538e018af5c9d26f49bb69057.val deleted file mode 100644 index 61d8213..0000000 Binary files a/.aider.tags.cache.v4/0d/50/c58538e018af5c9d26f49bb69057.val and /dev/null differ diff --git a/.aider.tags.cache.v4/0f/db/bc4de463cf9c89747b336c456858.val b/.aider.tags.cache.v4/0f/db/bc4de463cf9c89747b336c456858.val deleted file mode 100644 index 3e44d6b..0000000 Binary files a/.aider.tags.cache.v4/0f/db/bc4de463cf9c89747b336c456858.val and /dev/null differ diff --git a/.aider.tags.cache.v4/0f/e6/d44e933c2500aae3b62c1536762b.val b/.aider.tags.cache.v4/0f/e6/d44e933c2500aae3b62c1536762b.val deleted file mode 100644 index 2695a72..0000000 Binary files a/.aider.tags.cache.v4/0f/e6/d44e933c2500aae3b62c1536762b.val and /dev/null differ diff --git a/.aider.tags.cache.v4/13/b5/6d1060fd3e8bcaaeb7de34d2ab7c.val b/.aider.tags.cache.v4/13/b5/6d1060fd3e8bcaaeb7de34d2ab7c.val deleted file mode 100644 index c977fee..0000000 Binary files a/.aider.tags.cache.v4/13/b5/6d1060fd3e8bcaaeb7de34d2ab7c.val and /dev/null differ diff --git a/.aider.tags.cache.v4/14/82/4d18ac13422b15864a52c87d7d8c.val b/.aider.tags.cache.v4/14/82/4d18ac13422b15864a52c87d7d8c.val deleted file mode 100644 index f4c01c3..0000000 Binary files a/.aider.tags.cache.v4/14/82/4d18ac13422b15864a52c87d7d8c.val and /dev/null differ diff --git a/.aider.tags.cache.v4/17/19/dd00985533dd295bbfae553a3152.val b/.aider.tags.cache.v4/17/19/dd00985533dd295bbfae553a3152.val deleted file mode 100644 index 1e01a0b..0000000 Binary files a/.aider.tags.cache.v4/17/19/dd00985533dd295bbfae553a3152.val and /dev/null differ diff --git a/.aider.tags.cache.v4/18/c0/3bec0aeee65de49ca1ca92e61532.val b/.aider.tags.cache.v4/18/c0/3bec0aeee65de49ca1ca92e61532.val deleted file mode 100644 index 87ae23a..0000000 Binary files a/.aider.tags.cache.v4/18/c0/3bec0aeee65de49ca1ca92e61532.val and /dev/null differ diff --git a/.aider.tags.cache.v4/1b/51/815a4a61a2850cb0c02b56a5cafb.val b/.aider.tags.cache.v4/1b/51/815a4a61a2850cb0c02b56a5cafb.val deleted file mode 100644 index 1738373..0000000 Binary files a/.aider.tags.cache.v4/1b/51/815a4a61a2850cb0c02b56a5cafb.val and /dev/null differ diff --git a/.aider.tags.cache.v4/1c/93/122f8ca3087e56f45d95cebe406a.val b/.aider.tags.cache.v4/1c/93/122f8ca3087e56f45d95cebe406a.val deleted file mode 100644 index 19c2c6d..0000000 Binary files a/.aider.tags.cache.v4/1c/93/122f8ca3087e56f45d95cebe406a.val and /dev/null differ diff --git a/.aider.tags.cache.v4/26/8c/4eb3b82f3b577d49ceaf3a3ec775.val b/.aider.tags.cache.v4/26/8c/4eb3b82f3b577d49ceaf3a3ec775.val deleted file mode 100644 index 836c454..0000000 Binary files a/.aider.tags.cache.v4/26/8c/4eb3b82f3b577d49ceaf3a3ec775.val and /dev/null differ diff --git a/.aider.tags.cache.v4/29/75/4030891a4ad5e6ea07267725263c.val b/.aider.tags.cache.v4/29/75/4030891a4ad5e6ea07267725263c.val deleted file mode 100644 index 194d0e8..0000000 Binary files a/.aider.tags.cache.v4/29/75/4030891a4ad5e6ea07267725263c.val and /dev/null differ diff --git a/.aider.tags.cache.v4/30/ef/e7f29ad8e7e378aabfae83b03438.val b/.aider.tags.cache.v4/30/ef/e7f29ad8e7e378aabfae83b03438.val deleted file mode 100644 index 5163248..0000000 Binary files a/.aider.tags.cache.v4/30/ef/e7f29ad8e7e378aabfae83b03438.val and /dev/null differ diff --git a/.aider.tags.cache.v4/31/33/e4e848bda29b71f87b6b38e34857.val b/.aider.tags.cache.v4/31/33/e4e848bda29b71f87b6b38e34857.val deleted file mode 100644 index b709ef8..0000000 Binary files a/.aider.tags.cache.v4/31/33/e4e848bda29b71f87b6b38e34857.val and /dev/null differ diff --git a/.aider.tags.cache.v4/32/a5/0892c4750166195a4d1370cf63de.val b/.aider.tags.cache.v4/32/a5/0892c4750166195a4d1370cf63de.val deleted file mode 100644 index 315a445..0000000 Binary files a/.aider.tags.cache.v4/32/a5/0892c4750166195a4d1370cf63de.val and /dev/null differ diff --git a/.aider.tags.cache.v4/3c/f3/bd102d29d474a8f331f1100e86c3.val b/.aider.tags.cache.v4/3c/f3/bd102d29d474a8f331f1100e86c3.val deleted file mode 100644 index 6843f9a..0000000 Binary files a/.aider.tags.cache.v4/3c/f3/bd102d29d474a8f331f1100e86c3.val and /dev/null differ diff --git a/.aider.tags.cache.v4/3f/50/9cf8d09b60b997bfeff893c1828f.val b/.aider.tags.cache.v4/3f/50/9cf8d09b60b997bfeff893c1828f.val deleted file mode 100644 index 007f9ee..0000000 Binary files a/.aider.tags.cache.v4/3f/50/9cf8d09b60b997bfeff893c1828f.val and /dev/null differ diff --git a/.aider.tags.cache.v4/46/b9/cfac7e0f47e570867baadd776bcb.val b/.aider.tags.cache.v4/46/b9/cfac7e0f47e570867baadd776bcb.val deleted file mode 100644 index cabaea5..0000000 Binary files a/.aider.tags.cache.v4/46/b9/cfac7e0f47e570867baadd776bcb.val and /dev/null differ diff --git a/.aider.tags.cache.v4/4f/69/0910baaf7f1b43fa0b15f7c0b6de.val b/.aider.tags.cache.v4/4f/69/0910baaf7f1b43fa0b15f7c0b6de.val deleted file mode 100644 index 787f5bd..0000000 Binary files a/.aider.tags.cache.v4/4f/69/0910baaf7f1b43fa0b15f7c0b6de.val and /dev/null differ diff --git a/.aider.tags.cache.v4/55/5e/ba38cff96b31229ce65f440d8b52.val b/.aider.tags.cache.v4/55/5e/ba38cff96b31229ce65f440d8b52.val deleted file mode 100644 index 7727479..0000000 Binary files a/.aider.tags.cache.v4/55/5e/ba38cff96b31229ce65f440d8b52.val and /dev/null differ diff --git a/.aider.tags.cache.v4/5b/7b/0da050ff318168e57b892569a635.val b/.aider.tags.cache.v4/5b/7b/0da050ff318168e57b892569a635.val deleted file mode 100644 index f0d9a0d..0000000 Binary files a/.aider.tags.cache.v4/5b/7b/0da050ff318168e57b892569a635.val and /dev/null differ diff --git a/.aider.tags.cache.v4/5c/0e/2bf4d6a7e26a1c43db4c2a440994.val b/.aider.tags.cache.v4/5c/0e/2bf4d6a7e26a1c43db4c2a440994.val deleted file mode 100644 index 5a70685..0000000 Binary files a/.aider.tags.cache.v4/5c/0e/2bf4d6a7e26a1c43db4c2a440994.val and /dev/null differ diff --git a/.aider.tags.cache.v4/69/be/366757bc3cccaf126da7af024f2d.val b/.aider.tags.cache.v4/69/be/366757bc3cccaf126da7af024f2d.val deleted file mode 100644 index 6d470d1..0000000 Binary files a/.aider.tags.cache.v4/69/be/366757bc3cccaf126da7af024f2d.val and /dev/null differ diff --git a/.aider.tags.cache.v4/79/5e/778abad461c84a21208d10441dca.val b/.aider.tags.cache.v4/79/5e/778abad461c84a21208d10441dca.val deleted file mode 100644 index f73e981..0000000 Binary files a/.aider.tags.cache.v4/79/5e/778abad461c84a21208d10441dca.val and /dev/null differ diff --git a/.aider.tags.cache.v4/81/ec/23e6639729439dbaa3cdc3e0823b.val b/.aider.tags.cache.v4/81/ec/23e6639729439dbaa3cdc3e0823b.val deleted file mode 100644 index fb5130f..0000000 Binary files a/.aider.tags.cache.v4/81/ec/23e6639729439dbaa3cdc3e0823b.val and /dev/null differ diff --git a/.aider.tags.cache.v4/82/51/d89a9bc47195fa59470c6a8485cd.val b/.aider.tags.cache.v4/82/51/d89a9bc47195fa59470c6a8485cd.val deleted file mode 100644 index f6256a2..0000000 Binary files a/.aider.tags.cache.v4/82/51/d89a9bc47195fa59470c6a8485cd.val and /dev/null differ diff --git a/.aider.tags.cache.v4/83/c2/261c6b887f14d2ad36e6d103b6e2.val b/.aider.tags.cache.v4/83/c2/261c6b887f14d2ad36e6d103b6e2.val deleted file mode 100644 index 8fff6b0..0000000 Binary files a/.aider.tags.cache.v4/83/c2/261c6b887f14d2ad36e6d103b6e2.val and /dev/null differ diff --git a/.aider.tags.cache.v4/8d/b9/85105439f87928166f18f47189f8.val b/.aider.tags.cache.v4/8d/b9/85105439f87928166f18f47189f8.val deleted file mode 100644 index 655a886..0000000 Binary files a/.aider.tags.cache.v4/8d/b9/85105439f87928166f18f47189f8.val and /dev/null differ diff --git a/.aider.tags.cache.v4/92/29/e77e9b65add077b8df7012108dc4.val b/.aider.tags.cache.v4/92/29/e77e9b65add077b8df7012108dc4.val deleted file mode 100644 index 0a28da2..0000000 Binary files a/.aider.tags.cache.v4/92/29/e77e9b65add077b8df7012108dc4.val and /dev/null differ diff --git a/.aider.tags.cache.v4/9c/5b/c5b2b0b93503d81eb891ca075604.val b/.aider.tags.cache.v4/9c/5b/c5b2b0b93503d81eb891ca075604.val deleted file mode 100644 index cad5978..0000000 Binary files a/.aider.tags.cache.v4/9c/5b/c5b2b0b93503d81eb891ca075604.val and /dev/null differ diff --git a/.aider.tags.cache.v4/a1/8c/cb66cace3f0744ecfc4b7307641e.val b/.aider.tags.cache.v4/a1/8c/cb66cace3f0744ecfc4b7307641e.val deleted file mode 100644 index 246df22..0000000 Binary files a/.aider.tags.cache.v4/a1/8c/cb66cace3f0744ecfc4b7307641e.val and /dev/null differ diff --git a/.aider.tags.cache.v4/a3/ef/c05b0292f4443000b216af479170.val b/.aider.tags.cache.v4/a3/ef/c05b0292f4443000b216af479170.val deleted file mode 100644 index 40ee93c..0000000 Binary files a/.aider.tags.cache.v4/a3/ef/c05b0292f4443000b216af479170.val and /dev/null differ diff --git a/.aider.tags.cache.v4/a4/21/f129f49fa539e1c89ae92f7f2293.val b/.aider.tags.cache.v4/a4/21/f129f49fa539e1c89ae92f7f2293.val deleted file mode 100644 index 942ac09..0000000 Binary files a/.aider.tags.cache.v4/a4/21/f129f49fa539e1c89ae92f7f2293.val and /dev/null differ diff --git a/.aider.tags.cache.v4/a4/88/b2fbe12664e632e0bae55ab6e21e.val b/.aider.tags.cache.v4/a4/88/b2fbe12664e632e0bae55ab6e21e.val deleted file mode 100644 index b5b62d8..0000000 Binary files a/.aider.tags.cache.v4/a4/88/b2fbe12664e632e0bae55ab6e21e.val and /dev/null differ diff --git a/.aider.tags.cache.v4/b0/f2/0634148f84268d5e4cd8ea884081.val b/.aider.tags.cache.v4/b0/f2/0634148f84268d5e4cd8ea884081.val deleted file mode 100644 index 3a7f56f..0000000 Binary files a/.aider.tags.cache.v4/b0/f2/0634148f84268d5e4cd8ea884081.val and /dev/null differ diff --git a/.aider.tags.cache.v4/b8/fa/a1fb4a8b3c9583d434a1dc4e3876.val b/.aider.tags.cache.v4/b8/fa/a1fb4a8b3c9583d434a1dc4e3876.val deleted file mode 100644 index 603ddd3..0000000 Binary files a/.aider.tags.cache.v4/b8/fa/a1fb4a8b3c9583d434a1dc4e3876.val and /dev/null differ diff --git a/.aider.tags.cache.v4/bf/81/17dec31d9e5bf018072a79235980.val b/.aider.tags.cache.v4/bf/81/17dec31d9e5bf018072a79235980.val deleted file mode 100644 index f578fa8..0000000 Binary files a/.aider.tags.cache.v4/bf/81/17dec31d9e5bf018072a79235980.val and /dev/null differ diff --git a/.aider.tags.cache.v4/c9/79/a8e8304455c79b1d74714c61e050.val b/.aider.tags.cache.v4/c9/79/a8e8304455c79b1d74714c61e050.val deleted file mode 100644 index a405c55..0000000 Binary files a/.aider.tags.cache.v4/c9/79/a8e8304455c79b1d74714c61e050.val and /dev/null differ diff --git a/.aider.tags.cache.v4/cache.db b/.aider.tags.cache.v4/cache.db deleted file mode 100644 index 1e4b288..0000000 Binary files a/.aider.tags.cache.v4/cache.db and /dev/null differ diff --git a/.aider.tags.cache.v4/d7/9d/01388e731b3eee1bc92740d54ac8.val b/.aider.tags.cache.v4/d7/9d/01388e731b3eee1bc92740d54ac8.val deleted file mode 100644 index a85a557..0000000 Binary files a/.aider.tags.cache.v4/d7/9d/01388e731b3eee1bc92740d54ac8.val and /dev/null differ diff --git a/.aider.tags.cache.v4/de/19/b39c424d0ccbe43e0804d7ec3b93.val b/.aider.tags.cache.v4/de/19/b39c424d0ccbe43e0804d7ec3b93.val deleted file mode 100644 index 3e2e8e5..0000000 Binary files a/.aider.tags.cache.v4/de/19/b39c424d0ccbe43e0804d7ec3b93.val and /dev/null differ diff --git a/.aider.tags.cache.v4/de/74/33d92075a0b903af0383a1afd876.val b/.aider.tags.cache.v4/de/74/33d92075a0b903af0383a1afd876.val deleted file mode 100644 index 3ec395b..0000000 Binary files a/.aider.tags.cache.v4/de/74/33d92075a0b903af0383a1afd876.val and /dev/null differ diff --git a/.aider.tags.cache.v4/e1/f9/a6ac8bec72efedbc47f37445f708.val b/.aider.tags.cache.v4/e1/f9/a6ac8bec72efedbc47f37445f708.val deleted file mode 100644 index 6928a59..0000000 Binary files a/.aider.tags.cache.v4/e1/f9/a6ac8bec72efedbc47f37445f708.val and /dev/null differ diff --git a/.aider.tags.cache.v4/e9/88/e2d00e3216475c082352ec29d9dc.val b/.aider.tags.cache.v4/e9/88/e2d00e3216475c082352ec29d9dc.val deleted file mode 100644 index 90fdc2e..0000000 Binary files a/.aider.tags.cache.v4/e9/88/e2d00e3216475c082352ec29d9dc.val and /dev/null differ diff --git a/.aider.tags.cache.v4/eb/2c/ec0a15182aba76606379a331cbef.val b/.aider.tags.cache.v4/eb/2c/ec0a15182aba76606379a331cbef.val deleted file mode 100644 index b023684..0000000 Binary files a/.aider.tags.cache.v4/eb/2c/ec0a15182aba76606379a331cbef.val and /dev/null differ diff --git a/.aider.tags.cache.v4/ed/9a/cc93dd654f4df41aaf8c1c5a0648.val b/.aider.tags.cache.v4/ed/9a/cc93dd654f4df41aaf8c1c5a0648.val deleted file mode 100644 index 03488df..0000000 Binary files a/.aider.tags.cache.v4/ed/9a/cc93dd654f4df41aaf8c1c5a0648.val and /dev/null differ diff --git a/.aider.tags.cache.v4/f1/38/a2433640827ba366adf8754760df.val b/.aider.tags.cache.v4/f1/38/a2433640827ba366adf8754760df.val deleted file mode 100644 index 48fd456..0000000 Binary files a/.aider.tags.cache.v4/f1/38/a2433640827ba366adf8754760df.val and /dev/null differ diff --git a/.aider.tags.cache.v4/f4/1f/35d37baa81cdeec9f405735a44bb.val b/.aider.tags.cache.v4/f4/1f/35d37baa81cdeec9f405735a44bb.val deleted file mode 100644 index 0e62505..0000000 Binary files a/.aider.tags.cache.v4/f4/1f/35d37baa81cdeec9f405735a44bb.val and /dev/null differ diff --git a/.aider.tags.cache.v4/f7/50/38a53a3613379c46470069e8a3a5.val b/.aider.tags.cache.v4/f7/50/38a53a3613379c46470069e8a3a5.val deleted file mode 100644 index 2dc9418..0000000 Binary files a/.aider.tags.cache.v4/f7/50/38a53a3613379c46470069e8a3a5.val and /dev/null differ diff --git a/.aider.tags.cache.v4/f9/b6/e94ea8427af652e2973c0c77654f.val b/.aider.tags.cache.v4/f9/b6/e94ea8427af652e2973c0c77654f.val deleted file mode 100644 index bd5b387..0000000 Binary files a/.aider.tags.cache.v4/f9/b6/e94ea8427af652e2973c0c77654f.val and /dev/null differ diff --git a/.aider.tags.cache.v4/fa/f2/26679f3eb3b6f8e3439d180f424a.val b/.aider.tags.cache.v4/fa/f2/26679f3eb3b6f8e3439d180f424a.val deleted file mode 100644 index c91e98e..0000000 Binary files a/.aider.tags.cache.v4/fa/f2/26679f3eb3b6f8e3439d180f424a.val and /dev/null differ diff --git a/.planning/FASE_4_OPENCLAW_PLAN.md b/.planning/FASE_4_OPENCLAW_PLAN.md deleted file mode 100644 index b42b49d..0000000 --- a/.planning/FASE_4_OPENCLAW_PLAN.md +++ /dev/null @@ -1,475 +0,0 @@ -# Fase 4: OpenClaw Embutido — Plano de Implementação - -**Fase:** 4 -**Data Início:** 2026-03-26 -**Prazo:** 2026-04-08 (Semanas 7-8) -**Status:** 🔄 Sprint 3 Pendente (Sprint 1 e 2 concluídos) - ---- - -## 1. OBJETIVO DA FASE - -Implementar **detecção proativa de padrões** e **sugestão emergente de skills**, transformando comportamentos repetitivos do usuário em automações reutilizáveis através de um widget conversacional flutuante. - -### Entregável Final -✅ Skills emergentes funcionando end-to-end: -- Usuário executa ação repetida → PatternDetector detecta → OpenClawWidget sugere → Blackboard gera DRAFT → Dev Center aprova → Skill disponível - ---- - -## 2. ARQUITETURA - -``` -FLUXO OPENCCLAW: - -1. USER INTERACTION - └─ Usuário usa Arcádia - └─ Learning API registra evento (já existe) - └─ Neo4j armazena interação - -2. PATTERN DETECTION (NOVO) - └─ PatternDetector analisa Learning API - └─ Identifica: 3+ ocorrências em 30 dias - └─ Calcula confiança (threshold 0.8+) - └─ Dispara evento no Socket.IO - -3. WIDGET SUGGESTION (NOVO) - └─ OpenClawWidget fica "ouvindo" - └─ Recebe evento de padrão detectado - └─ Exibe notificação flutuante - └─ Modal SkillSuggestion mostra preview - -4. SKILL GENERATION (NOVO) - └─ Usuário confirma - └─ OpenClawEngine chama Blackboard - └─ Blackboard gera código (DRAFT) - └─ Armazena em database - -5. APPROVAL FLOW (EXISTENTE - Dev Center) - └─ Skill DRAFT aparece em Dev Center - └─ Admin/Lead revisa e aprova - └─ Publica no tenant - └─ Skill fica disponível para reutilização -``` - -### Componentes para Implementar - -``` -BACKEND: -server/modules/openclaw/ -├── PatternDetector.ts ← [NOVO] Detecta padrões -├── SkillEmergence.ts ← [NOVO] Coordena criação -├── OpenClawEngine.ts ← [NOVO] Lógica central -├── config/ -│ └── arcadia.config.yaml ← [NOVO] Configuração - -FRONTEND: -client/src/components/openclaw/ -├── OpenClawWidget.tsx ← [NOVO] Widget flutuante -├── PatternDetector.ts ← [NOVO] Hook de detecção -├── SkillSuggestion.tsx ← [NOVO] Modal de sugestão -└── useAgentEmergence.ts ← [NOVO] Lógica de emergência -``` - ---- - -## 3. DEPENDÊNCIAS VERIFICADAS - -| Componente | Status | Localização | -|-----------|--------|-----------| -| **Skills Engine** | ✅ Pronto | `server/skills/engine.ts` | -| **Blackboard** | ✅ Pronto | `server/blackboard/service.ts` | -| **Dev Center** | ✅ Pronto | `client/src/pages/DevCenter.tsx` | -| **Learning API** | ✅ Existe | `/api/learning/*` | -| **Neo4j (KG)** | ✅ Running | Docker | -| **Socket.IO** | ✅ Configurado | `server/socket-io.ts` | -| **PostgreSQL** | ✅ Rodando | Docker | -| **Scientist (MiroFlow)** | ✅ Existe | `/api/manus/scientist/*` | - -**Conclusão:** Todas as dependências estão prontas ✅ - ---- - -## 4. TASKS DETALHADAS - -### SPRINT 1 (26-27/03): PatternDetector Backend — ✅ COMPLETO - -#### Task 1.1: Criar PatternDetector.ts ✅ -**Arquivo:** `server/modules/openclaw/PatternDetector.ts` -**Objetivo:** Analisar eventos de usuário e detectar padrões - -```typescript -// Pseudocódigo da estrutura -export class PatternDetector { - // Config - min_occurrences: 3; - time_window_days: 30; - confidence_threshold: 0.8; - - // Métodos - detectPattern(userId: string, action: string): Pattern | null - calculateConfidence(interactions: Interaction[]): number - storePattern(pattern: Pattern): Promise - emitEvent(pattern: Pattern): void -} -``` - -**Entrada:** Eventos do Learning API (`/api/learning/interactions`) -**Saída:** Pattern objects armazenados em Neo4j + Socket.IO event -**Dependência:** Learning API funcionando ✅ - -#### Task 1.2: Criar OpenClawEngine.ts ✅ -**Arquivo:** `server/modules/openclaw/OpenClawEngine.ts` -**Objetivo:** Orquestração central de OpenClaw - -```typescript -export class OpenClawEngine { - patternDetector: PatternDetector; - skillEmergence: SkillEmergence; - - // Métodos - async suggestSkill(pattern: Pattern): Promise - async onUserConfirmation(suggestion: SkillSuggestion): Promise - async checkPatternsPeriodicly(): Promise -} -``` - -**Entrada:** Padrões detectados -**Saída:** Sugestões + Skills gerados -**Evento:** Socket.IO broadcast `/openclaw/pattern-detected` - -#### Task 1.3: Criar SkillEmergence.ts ✅ -**Arquivo:** `server/modules/openclaw/SkillEmergence.ts` -**Objetivo:** Integração com Blackboard para codegen - -```typescript -export class SkillEmergence { - async generateSkillDraft(pattern: Pattern): Promise { - // 1. Montar prompt baseado no padrão - // 2. Chamar POST /api/blackboard/generate-skill - // 3. Receber código gerado - // 4. Salvar como DRAFT no database - // 5. Notificar Dev Center - // 6. Retornar skill DRAFT - } -} -``` - -**Integração:** POST `/api/blackboard/generate-skill` -**Database:** skills table (com status: 'draft') - -#### Task 1.4: Criar rotas OpenClaw ✅ -**Arquivo:** `server/modules/openclaw/routes.ts` -**Rotas:** -``` -POST /api/openclaw/detect-patterns ← Trigger manual de análise -GET /api/openclaw/patterns ← Listar padrões detectados -POST /api/openclaw/confirm-skill ← Usuário confirma sugestão -GET /api/openclaw/suggestions ← Histórico de sugestões -``` - -#### Task 1.5: Integrar em server/index.ts ✅ -**Arquivo:** `server/index.ts` -**Ação:** Importar rotas OpenClaw e carregá-las - -```typescript -import openclawRoutes from "./modules/openclaw/routes"; -app.use("/api/openclaw", openclawRoutes); -``` - -### SPRINT 2 (28-29/03): Frontend Widgets — ✅ COMPLETO (commit 5231166) - -#### Task 2.1: Criar OpenClawWidget.tsx ✅ -**Arquivo:** `client/src/components/openclaw/OpenClawWidget.tsx` -**Objetivo:** Widget flutuante que recebe notificações de padrões - -```typescript -export function OpenClawWidget() { - // Escutar Socket.IO event: /openclaw/pattern-detected - // Exibir notificação flutuante (canto inferior direito) - // Mostrar padrão detectado - // Botão "Ver Sugestão" abre modal - // Botão "Ignorar" descarta - - return ( -
- {/* Widget flutuante */} -
- ); -} -``` - -**Socket.IO:** Escuta evento `/openclaw/pattern-detected` -**Trigger:** Modal SkillSuggestion - -#### Task 2.2: Criar SkillSuggestion.tsx ✅ -**Arquivo:** `client/src/components/openclaw/SkillSuggestion.tsx` -**Objetivo:** Modal com preview da skill sugerida - -```typescript -export function SkillSuggestion({ pattern, suggestion }) { - // Modal mostra: - // 1. "Detectamos um padrão na sua utilização:" - // 2. Preview do padrão (ações repetidas) - // 3. Preview da automação gerada - // 4. Campo de nome (auto-preenchido) - // 5. Descrição (auto-gerada) - // 6. Botão "Criar Skill" ou "Cancelar" - - const handleCreate = async () => { - // POST /api/openclaw/confirm-skill - // Esperar resposta (skill DRAFT) - // Toast: "Skill criada! Vá para Dev Center para publicar" - }; -} -``` - -**Integração:** Chama `POST /api/openclaw/confirm-skill` -**Feedback:** Toast notification - -#### Task 2.3: Hook useAgentEmergence.ts ✅ -**Arquivo:** `client/src/hooks/useAgentEmergence.ts` -**Objetivo:** Lógica de emergência de agentes - -```typescript -export function useAgentEmergence(userId: string) { - const [suggestions, setSuggestions] = useState([]); - - useEffect(() => { - // Socket.IO listener - socket.on("openclaw:pattern-detected", (pattern) => { - // Filtrar por tenant, user prefs - // Atualizar suggestions state - setSuggestions([...suggestions, pattern]); - }); - }, []); - - return { suggestions, dismiss, confirm }; -} -``` - -#### Task 2.4: Integrar Widget em layout principal ✅ -**Arquivo:** `client/src/App.tsx` ou `client/src/layouts/MainLayout.tsx` -**Ação:** Adicionar OpenClawWidget ao layout persistente - -```typescript -import { OpenClawWidget } from "@/components/openclaw/OpenClawWidget"; - -export default function App() { - return ( - <> - {/* Conteúdo existente */} - {/* ← Adicionar aqui */} - - ); -} -``` - -### SPRINT 3 (30-31/03): Configuração e Integração — ⏳ PRÓXIMO - -#### Task 3.1: Criar arcadia.config.yaml -**Arquivo:** `server/modules/openclaw/config/arcadia.config.yaml` - -```yaml -openclaw: - enabled: true - - # Endpoints - arcadia_api_url: http://localhost:3000/api - arcadia_kg_url: http://localhost:7474 - blackboard_url: http://localhost:3000/api/blackboard - - # Tenant awareness - tenant_aware: true - - # Detecção de padrões - pattern_detection: - enabled: true - min_occurrences: 3 - time_window_days: 30 - confidence_threshold: 0.8 - scheduled_check_interval_minutes: 60 - - # Sugestões - suggestions: - enabled: true - auto_suggest: false # Sempre pedir confirmação do usuário - channels: ['widget', 'chat'] - priority_threshold: 0.85 - - # Skills emergentes - emergence: - create_as_draft: true # Sempre requer aprovação - auto_publish: false - notify_admins: true - skill_prefix: "emergent_" # Prefixo para skills auto-geradas - - # Logging - logging: - enabled: true - store_patterns: true - store_in_kg: true - audit_trail: true -``` - -#### Task 3.2: Integrar Socket.IO events -**Arquivo:** `server/socket-io.ts` -**Ação:** Adicionar listeners e emitters para OpenClaw - -```typescript -socket.on("openclaw:confirm-skill", async (data) => { - // Receber confirmação do usuário - // Chamar SkillEmergence.generateSkillDraft() - // Emitir "openclaw:skill-created" -}); - -// Emitter no PatternDetector -io.emit("openclaw:pattern-detected", pattern); -``` - -#### Task 3.3: Database schema para OpenClaw -**Arquivo:** `shared/schema.ts` (Drizzle ORM) -**Adicionar tabelas:** - -```typescript -// Padrões detectados -export const detectedPatterns = pgTable("detected_patterns", { - id: serial().primaryKey(), - tenant_id: uuid().notNull(), - user_id: uuid().notNull(), - action_type: varchar(255).notNull(), - occurrences: integer().notNull(), - confidence: numeric(3, 2).notNull(), - time_window_days: integer().notNull(), - created_at: timestamp().defaultNow(), - metadata: jsonb(), -}); - -// Sugestões geradas -export const skillSuggestions = pgTable("skill_suggestions", { - id: serial().primaryKey(), - pattern_id: integer().references(() => detectedPatterns.id), - skill_draft_id: uuid().references(() => skills.id), - status: varchar(50).notNull(), // 'suggested', 'accepted', 'rejected' - created_at: timestamp().defaultNow(), -}); -``` - -#### Task 3.4: Migration SQL -**Arquivo:** `migrations/0004_openclaw_tables.sql` - -```sql -CREATE TABLE detected_patterns ( - id SERIAL PRIMARY KEY, - tenant_id UUID NOT NULL, - user_id UUID NOT NULL, - action_type VARCHAR(255) NOT NULL, - occurrences INTEGER NOT NULL, - confidence NUMERIC(3,2) NOT NULL, - time_window_days INTEGER NOT NULL, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - metadata JSONB -); - -CREATE TABLE skill_suggestions ( - id SERIAL PRIMARY KEY, - pattern_id INTEGER REFERENCES detected_patterns(id), - skill_draft_id UUID REFERENCES skills(id), - status VARCHAR(50) NOT NULL, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP -); - -CREATE INDEX idx_detected_patterns_user_tenant - ON detected_patterns(user_id, tenant_id); -``` - -#### Task 3.5: Testes unitários -**Arquivo:** `tests/openclaw.test.ts` -- PatternDetector detecta padrão corretamente -- OpenClawEngine orquestra fluxo correto -- SkillEmergence integra com Blackboard -- Socket.IO emite eventos corretamente - -#### Task 3.6: Documentação -**Arquivo:** `DOCUMENTATION.md` (adicionar seção) -- Como OpenClaw funciona -- Configuração por tenant -- Troubleshooting - ---- - -## 5. TIMELINE - -| Data | Sprint | Tasks | Status | -|------|--------|-------|--------| -| 26-27/03 | 1 | PatternDetector backend | ✅ Completo | -| 26/03 | 2 | OpenClawWidget frontend | ✅ Completo (commit 5231166) | -| 26/03 | 3 | Migration DB + testes | ⏳ Próximo | -| 01-08/04 | Buffer | Refinamento, testes E2E | ⏳ Próximo | - -**Nota:** Trabalho em `/opt/arcadia_merged/` (diretório canônico do projeto). - ---- - -## 6. CRITÉRIOS DE SUCESSO - -✅ **PatternDetector funciona:** -- Detecta padrão após 3 ocorrências em 30 dias -- Confiança calculada corretamente -- Eventos emitidos para Socket.IO - -✅ **OpenClawWidget funciona:** -- Widget aparece quando padrão é detectado -- Modal mostra sugestão corretamente -- Usuário pode confirmar ou rejeitar - -✅ **SkillEmergence funciona:** -- Integra com Blackboard -- Gera skill como DRAFT -- Aparece em Dev Center para aprovação - -✅ **E2E funciona:** -- User faz ação 3x -- Widget sugere -- Approva -- Skill publicada -- Skill disponível para reutilização - ---- - -## 7. RISCOS E MITIGAÇÕES - -| Risco | Probabilidade | Mitigação | -|-------|--------------|-----------| -| Blackboard não retorna código correto | Média | Testar integração antes, ter fallback | -| Padrões detectados incorretamente | Média | Validar threshold, testes no KG | -| Socket.IO não emite em tempo real | Baixa | Já funciona em outras partes | -| Performance com muitos eventos | Média | Usar índices em PG, cache em Redis | - ---- - -## 8. BRANCH E COMMITS - -**Branch:** `Servidor` (deploy branch, conforme feedback anterior) -**Commit pattern:** -``` -feat(openclaw): PatternDetector backend -feat(openclaw): OpenClawWidget frontend -feat(openclaw): Integração Blackboard + esquema DB -docs(openclaw): Documentação e testes -``` - ---- - -## 9. PRÓXIMAS AÇÕES - -1. ✅ **26/03:** Sprint 1 concluído (PatternDetector, OpenClawEngine, SkillEmergence, routes, config) -2. ✅ **26/03:** Sprint 2 concluído (OpenClawWidget, SkillSuggestion, useAgentEmergence, App.tsx — commit 5231166) -3. ⏳ **Agora:** Sprint 3 — migration SQL + vitest + testes unitários em `/opt/arcadia_merged/` -4. ⏳ **01-08/04:** Refinamento e testes E2E - ---- - -*Fase 4: OpenClaw Embutido — Plano Executável* -*Data: 2026-03-26* -*Pronto para implementação ✅* diff --git a/.planning/PROJECT.md b/.planning/PROJECT.md deleted file mode 100644 index b2c1945..0000000 --- a/.planning/PROJECT.md +++ /dev/null @@ -1,27 +0,0 @@ -# Arcádia Agentic Suite - -## Vision - -Evoluir o Arcádia Suite de ERP tradicional para um **Sistema Agêntico Orientado a Objetos**, onde Skills são objetos reutilizáveis, Agentes instanciam Skills para objetivos específicos, Automações são composições orquestradas, e o Dev Center é a fábrica de agentes. - -## Stack - -- **Backend:** Node.js + TypeScript, PostgreSQL, Neo4j (Knowledge Graph) -- **Frontend:** React + TypeScript, Monaco Editor -- **IA:** Ollama local (modelos até 14B — ex: deepseek-r1:14b padrão, llama3.1:8b rápido) -- **BI:** Apache Superset (externo, integrado via bridge) -- **Módulos embutidos:** MiroFlow (`server/modules/miroflow/`), OpenClaw (`server/modules/openclaw/`) - -## Princípios - -- Skills são o primitivo de execução universal -- Soberania tecnológica — eliminar dependências externas para lógica de negócio -- Multi-tenant: System → Tenant → Company → User -- Auditoria imutável em todas as execuções -- Backend-first em cada fase — API definida antes do frontend - -## Non-negotiables - -- Confirmar com João antes de executar qualquer migração de dados ou alteração de sistemas ativos -- Nunca sobrescrever configurações existentes do Superset (RLS já configurado em produção) -- Branch de deploy: `Servidor` diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md deleted file mode 100644 index ca95410..0000000 --- a/.planning/ROADMAP.md +++ /dev/null @@ -1,116 +0,0 @@ -# Roadmap: Arcádia Agentic Suite - -## Overview - -Evolução do Arcádia Suite de ERP tradicional para Sistema Agêntico Orientado a Objetos. Skills são objetos reutilizáveis (POO), Agentes instanciam Skills, Automações são composições orquestradas, Dev Center é a fábrica de agentes. - -## Phases - -- [x] **Phase 1: Fundação** - Infraestrutura base: submodules MiroFlow/OpenClaw, tabelas skills, Neo4j, ReferenceParser -- [x] **Phase 2: Skills Engine** - Skills criáveis e executáveis com editor Monaco e Marketplace -- [x] **Phase 3: MiroFlow Embutido** - Análises científicas via agentes especializados + bridge Superset -- [ ] **Phase 4: OpenClaw Embutido** - Skills emergentes com detecção de padrões -- [ ] **Phase 5: Automation Fabric** - Automações unificadas (XOS + Central) -- [ ] **Phase 6: Dev Center Completo** - Fábrica de agentes: Design → Assemble → Deploy - -## Phase Details - -### Phase 1: Fundação -**Goal**: Infraestrutura base funcionando com submodules, banco, KG e parser de referências -**Depends on**: Nothing -**Success Criteria** (what must be TRUE): - 1. Submodules MiroFlow e OpenClaw clonados e inicializados - 2. Tabelas arcadia_skills e skill_executions existem no banco - 3. Neo4j rodando via docker-compose - 4. ReferenceParser parseia referências /skill/, /kg/, /file/ etc. - -Plans: -- [x] 01-01: Submodules MiroFlow + OpenClaw -- [x] 01-02: Schema tabelas skills + migration -- [x] 01-03: Neo4j docker-compose + ReferenceParser - -### Phase 2: Skills Engine -**Goal**: Skills criáveis, editáveis e executáveis com marketplace -**Depends on**: Phase 1 -**Success Criteria** (what must be TRUE): - 1. SkillEngine.ts suporta herança, composição e polimorfismo - 2. API REST /skills CRUD funcionando - 3. Editor Monaco com autocomplete de referências (/) - 4. Skill Marketplace lista e filtra skills disponíveis - 5. Versionamento Git-like de skills implementado - -Plans: -- [x] 02-01: SkillEngine + API REST -- [x] 02-02: Editor Monaco + autocomplete + rota /skills -- [x] 02-03: Skill Marketplace (Biblioteca) -- [x] 02-04: Versionamento Git-like de skills - -### Phase 3: MiroFlow Embutido -**Goal**: Análises científicas disponíveis via agentes especializados integrados ao Superset -**Depends on**: Phase 2 -**Success Criteria** (what must be TRUE): - 1. MiroFlow configurado para Ollama local com modelos até 14B - 2. Agente Statistician analisa dados SQL com deepseek-r1:14b - 3. Agente Fiscal Auditor valida NFe/SPED com deepseek-r1:14b - 4. Agente Researcher consulta KG com llama3.1:8b - 5. Endpoint POST /api/miroflow/analyze retorna análise estruturada - 6. MiroFlowControl.tsx toggle "Modo Científico" aparece no Superset - 7. Execuções registradas com imutabilidade no KG - -**Plans**: 3 planos - -Plans: -- [x] 03-01-PLAN.md — Setup (ollama pull llama3.1:8b) + miroflow_service.py FastAPI porta 8006 com 3 agentes -- [x] 03-02-PLAN.md — Node bridge (engine-proxy.ts + routes.ts) + KG logging SHA-256 -- [x] 03-03-PLAN.md — Frontend MiroFlowControl.tsx + tab "Científico" em BiWorkspace.tsx - -### Phase 4: OpenClaw Embutido -**Goal**: Skills emergentes criadas automaticamente a partir de padrões detectados -**Depends on**: Phase 3 -**Success Criteria** (what must be TRUE): - 1. PatternDetector detecta padrões (min 3 ocorrências, 30 dias, 80% confiança) - 2. Skills emergentes criadas como DRAFT aguardando aprovação - 3. Widget flutuante notifica usuário de sugestões - 4. Fluxo completo: Padrão → DRAFT → Dev Center aprovação -**Plans**: TBD - -### Phase 5: Automation Fabric -**Goal**: Automações unificadas sob runtime único substituindo XOS + Central -**Depends on**: Phase 4 -**Success Criteria** (what must be TRUE): - 1. 5 runtimes funcionando: WorkflowEngine, RuleEngine, AgentExecutor, ScheduleEngine, EventEngine - 2. Automações existentes do XOS migradas sem perda de dados - 3. Automações existentes do /automations Central migradas - 4. AutomationCenter.tsx lista todas as automações unificadas -**Plans**: TBD - -### Phase 6: Dev Center Completo -**Goal**: Fábrica completa de agentes: Design → Assemble → Deploy -**Depends on**: Phase 5 -**Success Criteria** (what must be TRUE): - 1. DesignStudio com modos UML, Visual Flow, Markdown Spec, Code Editor - 2. AssembleLine gera código via Blackboard (GeneratorAgent) - 3. OrchestrateCenter faz deploy, versionamento e monitoramento - 4. Galeria de agentes por tenant funcional -**Plans**: TBD - -## Progress - -| Phase | Plans Complete | Status | Completed | -|-------|----------------|--------|-----------| -| 1. Fundação | 3/3 | Complete | 2026-03-25 | -| 2. Skills Engine | 4/4 | Complete | 2026-03-26 | -| 3. MiroFlow Embutido | 3/3 | Complete | 2026-03-26 | -| 4. OpenClaw Embutido | 0/TBD | Not started | - | -| 5. Automation Fabric | 0/TBD | Not started | - | -| 6. Dev Center Completo | 0/TBD | Not started | - | - -### Phase 7: Skill Fabric Expandido: Compiladores, Sandbox Executor, Visual/Code/Markdown Editors com Validation Pipeline - -**Goal:** [To be planned] -**Requirements**: TBD -**Depends on:** Phase 6 -**Plans:** 0 plans - -Plans: -- [ ] TBD (run /gsd:plan-phase 7 to break down) diff --git a/.planning/STATE.md b/.planning/STATE.md deleted file mode 100644 index ee04b20..0000000 --- a/.planning/STATE.md +++ /dev/null @@ -1,22 +0,0 @@ -# State - -## Current Phase: 6 — Dev Center Completo - -## Completed -- Phase 1: submodules, tabelas, Neo4j, ReferenceParser -- Phase 2: SkillEngine, API REST, Monaco Editor, /skills, autocomplete, Marketplace, versionamento Git-like -- Phase 3: miroflow_service.py, bridge TS + KG logging, MiroFlowControl.tsx + tab Científico -- Phase 4: PatternDetector (cron 1h), OpenClaw routes (suggestions/patterns/accept/reject), tab Sugestões em /skills + badge contador -- Phase 5: 5 runtimes (WorkflowEngine/RuleEngine/AgentExecutor/ScheduleEngine/EventEngine), AutomationFabricService, /api/automation-fabric, AutomationCenter.tsx em /automations-center -- Phase 6: arcadia_agent_defs (schema+migration+API CRUD+assemble/deploy/run/fork), 4 tabs no DevCenter (Design/Montar/Deploy/Galeria) - -## In Progress -- (nenhum — Phase 6 concluída, iniciar Phase 7) - -## Roadmap Evolution -- Phase 7 added: Skill Fabric Expandido (compiladores, sandbox, 3 editor modes, validation pipeline) - -## Notes -- Superset em produção com RLS configurado — não alterar sem confirmação -- Branch de deploy: `Servidor` -- Modelos Ollama precisam ser baixados: deepseek-r1:14b, llama3.1:8b (máximo 14B) diff --git a/.planning/config.json b/.planning/config.json deleted file mode 100644 index 89c1b67..0000000 --- a/.planning/config.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "workflow": { - "research": false, - "plan_check": false, - "verifier": false, - "nyquist_validation": false - }, - "model_profile": "budget" -} \ No newline at end of file diff --git a/.planning/phases/03-miroflow-embutido/03-01-PLAN.md b/.planning/phases/03-miroflow-embutido/03-01-PLAN.md deleted file mode 100644 index f7c44e3..0000000 --- a/.planning/phases/03-miroflow-embutido/03-01-PLAN.md +++ /dev/null @@ -1,329 +0,0 @@ ---- -id: "03-01" -phase: 03-miroflow-embutido -plan: 01 -type: execute -wave: 0 -depends_on: [] -files_modified: - - server/python/miroflow_service.py - - server/python/test_miroflow_service.py -autonomous: true -requirements: - - REQ-3.1 - - REQ-3.2 - - REQ-3.3 - - REQ-3.4 - -must_haves: - truths: - - "ollama pull llama3.1:8b completa sem erro" - - "miroflow_service.py sobe na porta 8006 sem ModuleNotFoundError" - - "GET http://localhost:8006/health retorna {status: ok}" - - "Agente statistician instanciado com deepseek-r1:14b via UnifiedOpenAIClient" - - "Agente fiscal_auditor instanciado com deepseek-r1:14b via UnifiedOpenAIClient" - - "Agente researcher instanciado com llama3.1:8b via UnifiedOpenAIClient" - artifacts: - - path: "server/python/miroflow_service.py" - provides: "FastAPI microserviço porta 8006 com 3 agentes MiroFlow" - exports: ["app", "AnalyzeRequest", "AnalyzeResponse", "make_agent_cfg", "run_agent"] - - path: "server/python/test_miroflow_service.py" - provides: "Testes pytest para REQ-3.1 a REQ-3.4" - contains: "test_health, test_statistician_model, test_fiscal_auditor_model, test_researcher_model" - key_links: - - from: "miroflow_service.py" - to: "http://localhost:11434/v1/chat/completions" - via: "UnifiedOpenAIClient base_url=OLLAMA_BASE_URL/v1" - pattern: "OLLAMA_BASE_URL.*v1" - - from: "miroflow_service.py" - to: "server/modules/miroflow" - via: "sys.path.insert(0, /app/server/modules/miroflow)" - pattern: "sys.path.insert" ---- - - -Preparar o ambiente e criar o microserviço Python MiroFlow (FastAPI, porta 8006) com os 3 agentes especializados configurados para Ollama local. - -Purpose: Fundação do Phase 3 — sem esse microserviço rodando, os planos 02 e 03 não têm backend para chamar. -Output: miroflow_service.py funcional + testes pytest cobrindo REQ-3.1 a REQ-3.4 + llama3.1:8b instalado. - - - -@$HOME/.claude/get-shit-done/workflows/execute-plan.md -@$HOME/.claude/get-shit-done/templates/summary.md - - - -@.planning/PROJECT.md -@.planning/ROADMAP.md -@.planning/STATE.md -@.planning/phases/03-miroflow-embutido/03-RESEARCH.md - - - - -app = FastAPI(title="...", version="1.0.0") -app.add_middleware(CORSMiddleware, allow_origins=["*"], ...) - -@app.get("/health") -async def health_check(): return {"status": "ok", "service": "..."} - -@app.post("/analyze", response_model=AnalysisResult) -async def analyze_data(request: AnalysisRequest): ... - -if __name__ == "__main__": - port = int(os.environ.get("SERVICE_PORT", 8003)) - uvicorn.run(app, host="0.0.0.0", port=port) - - -from miroflow.agents.factory import build_agent # build_agent(config_dict) -> BaseAgent -from miroflow.agents.context import AgentContext # AgentContext(task_description="...") -# agent.run(ctx) -> dict com chave "summary" ou texto direto - - -{ - "type": "IterativeAgentWithToolAndRollback", - "name": "arcadia_deepseek_r1_14b", - "max_turns": 10, - "llm": { - "provider_class": "UnifiedOpenAIClient", - "model_name": "deepseek-r1:14b", # ou llama3.1:8b - "api_key": "ollama", - "base_url": "{OLLAMA_BASE_URL}/v1", - "max_tokens": 8192, - "temperature": 0.7, - "top_p": 1.0, "min_p": 0.0, "top_k": -1, - "reasoning_effort": None, "repetition_penalty": 1.0, - "max_context_length": -1, "async_client": True, - "disable_cache_control": True, "keep_tool_result": -1, - "use_tool_calls": False, "oai_tool_thinking": False, - } -} - - - - - - - Task 1: Setup — baixar llama3.1:8b e instalar dependências MiroFlow - server/modules/miroflow/ (sem modificar), .env (adicionar MIROFLOW_PORT) - - - - /opt/arcadia_merged/.env (verificar se OLLAMA_BASE_URL e MIROFLOW_PORT já existem) - - /opt/arcadia_merged/server/modules/miroflow/pyproject.toml (confirmar deps necessárias) - - - - 1. Baixar o modelo llama3.1:8b no Ollama (necessário para o agente Researcher): - ```bash - ollama pull llama3.1:8b - ``` - Se o download demorar muito, continuar e validar após. O fallback é llama3.2:3b já instalado. - - 2. Instalar dependências Python necessárias para o microserviço (o sistema Python 3.12 já tem fastapi/uvicorn, faltam as deps do MiroFlow): - ```bash - cd /opt/arcadia_merged/server/modules/miroflow && uv sync --frozen 2>/dev/null || pip3 install omegaconf hydra-core openai python-dotenv pydantic - ``` - - 3. Verificar se MIROFLOW_PORT=8006 existe no .env. Se não existir, adicionar a linha `MIROFLOW_PORT=8006` ao arquivo .env. NÃO alterar OLLAMA_BASE_URL existente. - - 4. Verificar se OLLAMA_BASE_URL está presente no .env. Se não, adicionar `OLLAMA_BASE_URL=http://localhost:11434`. - - - - ollama list | grep "llama3.1:8b" && python3 -c "import omegaconf; print('omegaconf ok')" && python3 -c "from miroflow.agents.factory import build_agent; print('miroflow importado')" 2>/dev/null || echo "PENDENTE: llama3.1:8b pode estar baixando" - - - - - `ollama list` contém "llama3.1:8b" OU download em andamento (verificar com `ollama ps`) - - `python3 -c "import omegaconf"` não gera ImportError - - `python3 -c "from miroflow.agents.factory import build_agent"` não gera ImportError (executado do diretório com o venv ativo ou com sys.path configurado) - - .env contém linha MIROFLOW_PORT=8006 - - - Modelo llama3.1:8b disponível no Ollama, deps MiroFlow instaladas, MIROFLOW_PORT configurado no .env - - - - Task 2: Criar test_miroflow_service.py + miroflow_service.py (FastAPI porta 8006) - server/python/test_miroflow_service.py, server/python/miroflow_service.py - - - - /opt/arcadia_merged/server/python/bi_analysis_service.py (padrão de estrutura FastAPI a seguir) - - /opt/arcadia_merged/server/modules/miroflow/miroflow/agents/base.py (API do BaseAgent) - - /opt/arcadia_merged/server/modules/miroflow/miroflow/agents/factory.py (build_agent signature) - - /opt/arcadia_merged/server/modules/miroflow/miroflow/agents/context.py (AgentContext fields) - - /opt/arcadia_merged/.env (OLLAMA_BASE_URL atual) - - - - - test_health: GET /health retorna {"status": "ok", "service": "miroflow"} - - test_statistician_config: make_agent_cfg("statistician") retorna dict com model_name="deepseek-r1:14b" e base_url terminando em "/v1" - - test_fiscal_auditor_config: make_agent_cfg("fiscal_auditor") retorna dict com model_name="deepseek-r1:14b" - - test_researcher_config: make_agent_cfg("researcher") retorna dict com model_name="llama3.1:8b" (fallback "llama3.2:3b" se llama3.1:8b ausente) - - test_analyze_request_validation: POST /analyze com agent="invalid" retorna 422 Unprocessable Entity - - test_analyze_request_schema: AnalyzeRequest aceita {agent, task, context, tenant_id} e AnalyzeResponse tem {agent, model, result, execution_id, duration_ms} - - - - PASSO 1 (RED): Criar server/python/test_miroflow_service.py com os 6 testes listados em . Rodar pytest — DEVE falhar (miroflow_service.py não existe). - - PASSO 2 (GREEN): Criar server/python/miroflow_service.py seguindo o padrão de bi_analysis_service.py: - - ```python - """ - Arcádia MiroFlow Service — Agentes científicos via MiroFlow + Ollama local - FastAPI microserviço porta 8006 - """ - import os, sys, time, uuid - from typing import Optional - from fastapi import FastAPI, HTTPException - from fastapi.middleware.cors import CORSMiddleware - from pydantic import BaseModel - - # Adicionar o submodule MiroFlow ao path - MIROFLOW_MODULE_PATH = os.path.join( - os.path.dirname(__file__), "..", "modules", "miroflow" - ) - sys.path.insert(0, os.path.abspath(MIROFLOW_MODULE_PATH)) - - from miroflow.agents.factory import build_agent - from miroflow.agents.context import AgentContext - - OLLAMA_BASE_URL = os.getenv("OLLAMA_BASE_URL", "http://localhost:11434") - - # Verificar se llama3.1:8b está disponível; senão usar fallback - RESEARCHER_MODEL = os.getenv("MIROFLOW_RESEARCHER_MODEL", "llama3.1:8b") - - AGENT_MODELS = { - "statistician": "deepseek-r1:14b", - "fiscal_auditor": "deepseek-r1:14b", - "researcher": RESEARCHER_MODEL, - } - - def make_agent_cfg(agent_type: str) -> dict: - model = AGENT_MODELS.get(agent_type, "deepseek-r1:14b") - return { - "type": "IterativeAgentWithToolAndRollback", - "name": f"arcadia_{agent_type}", - "max_turns": 10, - "llm": { - "provider_class": "UnifiedOpenAIClient", - "model_name": model, - "api_key": "ollama", - "base_url": f"{OLLAMA_BASE_URL}/v1", - "max_tokens": 8192, - "temperature": 0.7, - "top_p": 1.0, "min_p": 0.0, "top_k": -1, - "reasoning_effort": None, "repetition_penalty": 1.0, - "max_context_length": -1, "async_client": True, - "disable_cache_control": True, "keep_tool_result": -1, - "use_tool_calls": False, "oai_tool_thinking": False, - }, - } - - async def run_agent(agent_type: str, task: str) -> tuple[str, str]: - """Retorna (result_text, model_name)""" - if agent_type not in AGENT_MODELS: - raise ValueError(f"Agente desconhecido: {agent_type}. Use: {list(AGENT_MODELS.keys())}") - cfg = make_agent_cfg(agent_type) - agent = build_agent(cfg) - ctx = AgentContext(task_description=task) - result = await agent.run(ctx) - text = result.get("summary", str(result)) if isinstance(result, dict) else str(result) - return text, cfg["llm"]["model_name"] - - app = FastAPI(title="Arcádia MiroFlow Service", version="1.0.0") - app.add_middleware(CORSMiddleware, allow_origins=["*"], allow_credentials=True, - allow_methods=["*"], allow_headers=["*"]) - - class AnalyzeRequest(BaseModel): - agent: str # "statistician" | "fiscal_auditor" | "researcher" - task: str - context: dict = {} - tenant_id: Optional[int] = None - - class AnalyzeResponse(BaseModel): - agent: str - model: str - result: str - execution_id: str - duration_ms: int - - @app.get("/health") - async def health_check(): - return {"status": "ok", "service": "miroflow", "agents": list(AGENT_MODELS.keys())} - - @app.post("/analyze", response_model=AnalyzeResponse) - async def analyze(req: AnalyzeRequest): - if req.agent not in AGENT_MODELS: - raise HTTPException(status_code=422, detail=f"Agente inválido: {req.agent}") - start = time.time() - try: - result_text, model_name = await run_agent(req.agent, req.task) - except Exception as e: - raise HTTPException(status_code=500, detail=str(e)) - return AnalyzeResponse( - agent=req.agent, - model=model_name, - result=result_text, - execution_id=str(uuid.uuid4()), - duration_ms=int((time.time() - start) * 1000), - ) - - if __name__ == "__main__": - import uvicorn - port = int(os.environ.get("MIROFLOW_PORT", 8006)) - uvicorn.run(app, host="0.0.0.0", port=port) - ``` - - PASSO 3 (REFACTOR): Rodar pytest novamente — TODOS devem passar. Não alterar lógica, apenas organizar se necessário. - - IMPORTANTE: Não usar modelos acima de 14B. Não criar arquivos YAML externos para config do MiroFlow — usar dict inline conforme padrão. - - - - cd /opt/arcadia_merged && python3 -m pytest server/python/test_miroflow_service.py -x -v 2>&1 | tail -20 - - - - - `pytest server/python/test_miroflow_service.py -x` passa com 0 falhas - - test_health verifica {"status": "ok", "service": "miroflow"} - - test_statistician_config e test_fiscal_auditor_config verificam model_name="deepseek-r1:14b" - - test_researcher_config verifica model_name em ["llama3.1:8b", "llama3.2:3b"] (aceita ambos) - - test_analyze_request_validation verifica que agent="invalid" retorna 422 - - miroflow_service.py tem menos de 150 linhas - - Nenhuma referência a modelos acima de 14B no código - - - miroflow_service.py criado e testado. Microserviço pode ser iniciado com `python3 server/python/miroflow_service.py` na porta 8006. Todos os testes passam. - - - - - -```bash -# Verificar que o serviço sobe: -cd /opt/arcadia_merged && MIROFLOW_PORT=8006 python3 server/python/miroflow_service.py & -sleep 3 -curl -s http://localhost:8006/health | python3 -m json.tool -# Esperado: {"status": "ok", "service": "miroflow", "agents": ["statistician", "fiscal_auditor", "researcher"]} -kill %1 -``` - - - -- `pytest server/python/test_miroflow_service.py -x` passa (0 falhas) -- GET http://localhost:8006/health retorna {"status": "ok"} quando o serviço está rodando -- .env contém MIROFLOW_PORT=8006 -- llama3.1:8b disponível no Ollama (ou download iniciado) -- Nenhum modelo acima de 14B referenciado - - - -Após conclusão, criar `.planning/phases/03-miroflow-embutido/03-01-SUMMARY.md` com: -- Arquivos criados/modificados -- Resultado dos testes -- Status do download do llama3.1:8b -- Modelo de fallback usado para Researcher (se aplicável) - diff --git a/.planning/phases/03-miroflow-embutido/03-01-SUMMARY.md b/.planning/phases/03-miroflow-embutido/03-01-SUMMARY.md deleted file mode 100644 index 21a7142..0000000 --- a/.planning/phases/03-miroflow-embutido/03-01-SUMMARY.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -plan: "03-01" -phase: "03-miroflow-embutido" -status: complete -completed: 2026-03-25 ---- - -# Summary: 03-01 — Python MiroFlow Microservice - -## What was built - -Microserviço FastAPI porta 8006 com 3 agentes científicos MiroFlow configurados para Ollama local, mais testes pytest cobrindo REQ-3.1 a REQ-3.4. - -## Files created/modified - -### Created -- `server/python/miroflow_service.py` — FastAPI app com make_agent_cfg(), run_agent(), GET /health, POST /analyze -- `server/python/test_miroflow_service.py` — 6 testes: health, statistician/fiscal_auditor/researcher config, request schema, 422 validation - -## Test results - -Todos os testes passaram (validados inline via python3): -- test_health OK (status: ok, service: miroflow) -- test_statistician_config OK (deepseek-r1:14b, base_url ends /v1) -- test_fiscal_auditor_config OK (deepseek-r1:14b) -- test_researcher_config OK (llama3.1:8b ou llama3.2:3b) -- test_analyze_request_validation OK (422 para agent invalido) -- test_analyze_request_schema OK - -## Modelo Researcher - -llama3.1:8b nao disponivel no Ollama local — fallback automatico para llama3.2:3b (ja instalado). Configuravel via MIROFLOW_RESEARCHER_MODEL no .env. - -## Deps instaladas - -omegaconf 2.3.0, hydra-core 1.3.2, mcp 1.26.0 instalados via pip3 --break-system-packages. - -## Self-Check: PASSED - -## Commits (03-01 execution) - -- 60f1c5c: feat(03-01): criar miroflow_service.py FastAPI porta 8006 com 3 agentes + testes pytest -- 76e1d34: fix(03-01): adicionar conftest.py para resolver imports em pytest do root - -## Deviations - -- [Rule 2] conftest.py adicionado: pytest da raiz falhava sem sys.path fix -- [Documentado] llama3.2:3b usado como fallback para researcher (llama3.1:8b nao instalado) diff --git a/.planning/phases/03-miroflow-embutido/03-02-PLAN.md b/.planning/phases/03-miroflow-embutido/03-02-PLAN.md deleted file mode 100644 index 1b20967..0000000 --- a/.planning/phases/03-miroflow-embutido/03-02-PLAN.md +++ /dev/null @@ -1,331 +0,0 @@ ---- -id: "03-02" -phase: 03-miroflow-embutido -plan: 02 -type: execute -wave: 1 -depends_on: ["03-01"] -files_modified: - - server/miroflow/routes.ts - - server/miroflow/engine-proxy.ts - - server/routes.ts -autonomous: true -requirements: - - REQ-3.5 - - REQ-3.7 - -must_haves: - truths: - - "POST /api/miroflow/analyze retorna JSON com {agent, model, result, execution_id, duration_ms}" - - "GET /api/miroflow/health retorna {online: true} quando microserviço está rodando" - - "Requisição não autenticada retorna 401" - - "Cada execução cria um nó graph_nodes com type='miroflow_execution' e auditHash SHA-256" - - "Timeout de 5 minutos no proxy (adequado para deepseek-r1:14b)" - artifacts: - - path: "server/miroflow/engine-proxy.ts" - provides: "Função proxyToMiroFlow() com timeout 300s" - exports: ["proxyToMiroFlow"] - - path: "server/miroflow/routes.ts" - provides: "Express router: POST /api/miroflow/analyze, GET /api/miroflow/health" - exports: ["registerMiroFlowRoutes"] - key_links: - - from: "server/miroflow/routes.ts" - to: "server/python/miroflow_service.py" - via: "fetch() para http://localhost:8006/analyze" - pattern: "MIROFLOW_PORT.*8006" - - from: "server/miroflow/routes.ts" - to: "server/graph/service.ts" - via: "createNode({type: 'miroflow_execution', ...})" - pattern: "createNode.*miroflow_execution" - - from: "server/routes.ts" - to: "server/miroflow/routes.ts" - via: "registerMiroFlowRoutes(app)" - pattern: "registerMiroFlowRoutes" ---- - - -Criar o bridge Node.js → Python para o MiroFlow: proxy TypeScript (engine-proxy.ts), rotas Express (routes.ts) e registro imutável de execuções no KG via graph_nodes. - -Purpose: Expõe POST /api/miroflow/analyze como endpoint autenticado do Arcádia Suite, conectando o frontend ao microserviço Python do Plano 01. -Output: Rotas Express registradas, cada chamada proxiada para :8006 e auditada no KG PostgreSQL. - - - -@$HOME/.claude/get-shit-done/workflows/execute-plan.md -@$HOME/.claude/get-shit-done/templates/summary.md - - - -@.planning/PROJECT.md -@.planning/ROADMAP.md -@.planning/phases/03-miroflow-embutido/03-01-SUMMARY.md -@.planning/phases/03-miroflow-embutido/03-RESEARCH.md - - - -// TIMEOUT padrão atual: 30000ms — MiroFlow PRECISA de 300000ms (5min) -async function proxyToEngine(path: string, options: RequestInit = {}): Promise { - const controller = new AbortController(); - const timeout = setTimeout(() => controller.abort(), BI_ENGINE_TIMEOUT); - const response = await fetch(`${BI_ENGINE_URL}${path}`, { ...options, signal: controller.signal }); - if (!response.ok) { - const error = await response.json().catch(() => ({ detail: response.statusText })); - throw new Error(error.detail || `BI Engine error: ${response.status}`); - } - return await response.json(); -} - -export function registerBiEngineRoutes(app: Express): void { - app.post("/api/bi-engine/analyze", async (req, res) => { - if (!req.isAuthenticated()) return res.status(401).json({ error: "Not authenticated" }); - ... - }); -} - - -export async function createNode(data: InsertGraphNode): Promise -// InsertGraphNode: { type: string, tenantId?: number, data: object } -// graph_nodes tabela PostgreSQL — NÃO usar Neo4j direto - - -import { registerBiEngineRoutes } from "./bi/engine-proxy"; // padrão a seguir -registerBiEngineRoutes(app); // linha ~105 - - -{ - agent: string, // "statistician" | "fiscal_auditor" | "researcher" - model: string, // "deepseek-r1:14b" | "llama3.1:8b" - result: string, - execution_id: string, // UUID v4 - duration_ms: number -} - - - - - - - Task 1: Criar server/miroflow/engine-proxy.ts e server/miroflow/routes.ts - server/miroflow/engine-proxy.ts, server/miroflow/routes.ts - - - - /opt/arcadia_merged/server/bi/engine-proxy.ts (padrão completo de proxy a seguir) - - /opt/arcadia_merged/server/graph/service.ts (createNode signature, linhas 41-49) - - /opt/arcadia_merged/server/graph/routes.ts (confirmar que /api/graph/nodes aceita POST) - - /opt/arcadia_merged/server/auth.ts (confirmar req.isAuthenticated() e req.user shape) - - - - - proxyToMiroFlow("/health", "GET") faz fetch para MIROFLOW_URL/health com timeout 5s - - proxyToMiroFlow("/analyze", "POST", body) faz fetch para MIROFLOW_URL/analyze com timeout 300000ms - - POST /api/miroflow/analyze sem autenticação retorna 401 {"error": "Não autenticado"} - - POST /api/miroflow/analyze autenticado encaminha body + tenant_id para :8006/analyze - - Após resposta bem-sucedida, registerExecutionInKG cria nó com type="miroflow_execution" - - auditHash é SHA-256 do JSON.stringify({execution_id, agent, model, input, output}) - - GET /api/miroflow/health não requer autenticação, retorna {online: bool, url: string} - - - - Criar diretório server/miroflow/ se não existir. - - Criar server/miroflow/engine-proxy.ts: - ```typescript - import type { Express, Request, Response } from "express"; - import crypto from "crypto"; - import { createNode } from "../graph/service"; - - const MIROFLOW_HOST = process.env.MIROFLOW_HOST || "localhost"; - const MIROFLOW_PORT = parseInt(process.env.MIROFLOW_PORT || "8006", 10); - const MIROFLOW_URL = `http://${MIROFLOW_HOST}:${MIROFLOW_PORT}`; - const MIROFLOW_TIMEOUT = 300_000; // 5 minutos — deepseek-r1:14b pode levar 60-120s - - async function proxyToMiroFlow(path: string, method: string = "GET", body?: object): Promise { - const controller = new AbortController(); - const timeout = setTimeout(() => controller.abort(), MIROFLOW_TIMEOUT); - try { - const response = await fetch(`${MIROFLOW_URL}${path}`, { - method, - headers: { "Content-Type": "application/json" }, - body: body ? JSON.stringify(body) : undefined, - signal: controller.signal, - }); - clearTimeout(timeout); - if (!response.ok) { - const err = await response.json().catch(() => ({ detail: response.statusText })); - throw new Error(err.detail || `MiroFlow error: ${response.status}`); - } - return await response.json(); - } catch (err: any) { - clearTimeout(timeout); - if (err.name === "AbortError") throw new Error("MiroFlow timeout (300s)"); - throw err; - } - } - - async function registerExecutionInKG(req: Request, execData: any, inputBody: any): Promise { - try { - const auditHash = crypto - .createHash("sha256") - .update(JSON.stringify({ - execution_id: execData.execution_id, - agent: execData.agent, - model: execData.model, - input: inputBody, - output: execData.result, - })) - .digest("hex"); - - await createNode({ - type: "miroflow_execution", - tenantId: (req.user as any)?.tenantId ?? null, - data: { - ...execData, - input: inputBody, - auditHash, - immutable: true, - registeredAt: new Date().toISOString(), - }, - }); - } catch (kgErr: any) { - // KG failure não deve bloquear a resposta ao cliente - console.error("[MiroFlow] Falha ao registrar no KG:", kgErr.message); - } - } - - export function registerMiroFlowRoutes(app: Express): void { - app.get("/api/miroflow/health", async (_req: Request, res: Response) => { - try { - const data = await proxyToMiroFlow("/health", "GET"); - res.json({ online: true, url: MIROFLOW_URL, ...data }); - } catch { - res.json({ online: false, url: MIROFLOW_URL }); - } - }); - - app.post("/api/miroflow/analyze", async (req: Request, res: Response) => { - if (!req.isAuthenticated()) { - return res.status(401).json({ error: "Não autenticado" }); - } - try { - const inputBody = { - ...req.body, - tenant_id: (req.user as any)?.tenantId ?? null, - }; - const data = await proxyToMiroFlow("/analyze", "POST", inputBody); - // Registrar no KG de forma assíncrona (não bloqueia a resposta) - registerExecutionInKG(req, data, req.body).catch(() => {}); - res.json(data); - } catch (err: any) { - res.status(502).json({ error: err.message }); - } - }); - - console.log(`[MiroFlow Proxy] Rotas registradas -> ${MIROFLOW_URL}`); - } - ``` - - Criar server/miroflow/routes.ts como re-export limpo (manter compatibilidade com o loader de módulos): - ```typescript - export { registerMiroFlowRoutes } from "./engine-proxy"; - ``` - - IMPORTANTE: - - Timeout de 300_000ms (5 minutos) — NÃO usar o padrão de 30s do bi/engine-proxy.ts - - registerExecutionInKG usa createNode do graph/service.ts, NÃO faz fetch para /api/graph/nodes - - Falha no KG não retorna erro ao cliente (try/catch com log) - - auditHash cobre: execution_id + agent + model + input + output - - - - cd /opt/arcadia_merged && npx tsc --noEmit --project tsconfig.json 2>&1 | grep -i "miroflow" | head -10 || echo "TypeScript OK (nenhum erro em miroflow)" - - - - - server/miroflow/engine-proxy.ts existe e compila sem erros TypeScript - - server/miroflow/routes.ts existe (re-export ou implementação direta) - - MIROFLOW_TIMEOUT = 300_000 está definido (não 30000) - - Função registerExecutionInKG usa createNode importado de "../graph/service" - - auditHash calculado com crypto.createHash("sha256") - - POST /api/miroflow/analyze faz verificação req.isAuthenticated() antes de proxiar - - grep -n "300_000\|300000" server/miroflow/engine-proxy.ts retorna resultado - - grep -n "miroflow_execution" server/miroflow/engine-proxy.ts retorna resultado - - - Arquivos TypeScript criados sem erros de compilação. Funções exportadas: registerMiroFlowRoutes. Timeout de 5min configurado. KG logging com SHA-256 implementado. - - - - Task 2: Registrar MiroFlow em server/routes.ts - server/routes.ts - - - - /opt/arcadia_merged/server/routes.ts (ARQUIVO INTEIRO — verificar imports e onde registerBiEngineRoutes é chamado para inserir MiroFlow no mesmo padrão) - - - - Adicionar import e registro das rotas MiroFlow em server/routes.ts, seguindo o padrão exato de registerBiEngineRoutes: - - 1. Adicionar import após a linha que importa registerBiEngineRoutes (linha ~19): - ```typescript - import { registerMiroFlowRoutes } from "./miroflow/engine-proxy"; - ``` - - 2. Adicionar chamada após registerBiEngineRoutes(app) (linha ~105): - ```typescript - registerMiroFlowRoutes(app); - ``` - - NÃO alterar nenhuma outra linha do arquivo. NÃO mover, reordenar ou reformatar código existente. - NÃO modificar configurações do Superset ou rotas existentes. - - - - cd /opt/arcadia_merged && grep -n "registerMiroFlowRoutes" server/routes.ts && npx tsc --noEmit --project tsconfig.json 2>&1 | grep -c "error" || echo "0 erros" - - - - - `grep "registerMiroFlowRoutes" server/routes.ts` retorna 2 linhas (import + chamada) - - `npx tsc --noEmit` não retorna erros relacionados a miroflow - - A linha de import está próxima de registerBiEngineRoutes (mesma região do arquivo) - - A chamada registerMiroFlowRoutes(app) está próxima de registerBiEngineRoutes(app) - - Nenhuma linha existente do arquivo foi modificada (verificar com git diff) - - - server/routes.ts registra as rotas MiroFlow. POST /api/miroflow/analyze e GET /api/miroflow/health estarão disponíveis quando o servidor Node iniciar. - - - - - -```bash -# Compilação TypeScript limpa: -cd /opt/arcadia_merged && npx tsc --noEmit 2>&1 | grep -i "error" | head -5 - -# Confirmar registro no KG: -grep -n "miroflow_execution\|auditHash\|createNode" /opt/arcadia_merged/server/miroflow/engine-proxy.ts - -# Confirmar timeout correto: -grep -n "300" /opt/arcadia_merged/server/miroflow/engine-proxy.ts - -# Confirmar rotas registradas: -grep -n "registerMiroFlowRoutes" /opt/arcadia_merged/server/routes.ts -``` - - - -- server/miroflow/engine-proxy.ts e server/miroflow/routes.ts existem -- TypeScript compila sem erros nos novos arquivos -- server/routes.ts inclui import e chamada registerMiroFlowRoutes -- Timeout de 300s configurado no proxy -- auditHash SHA-256 calculado e salvo via createNode -- GET /api/miroflow/health acessível sem autenticação -- POST /api/miroflow/analyze requer autenticação (401 sem sessão) - - - -Após conclusão, criar `.planning/phases/03-miroflow-embutido/03-02-SUMMARY.md` com: -- Arquivos criados/modificados -- Resultado da compilação TypeScript -- Confirmação do padrão de timeout (300s) -- Confirmação do KG logging com auditHash - diff --git a/.planning/phases/03-miroflow-embutido/03-02-SUMMARY.md b/.planning/phases/03-miroflow-embutido/03-02-SUMMARY.md deleted file mode 100644 index d08762e..0000000 --- a/.planning/phases/03-miroflow-embutido/03-02-SUMMARY.md +++ /dev/null @@ -1,40 +0,0 @@ ---- -plan: "03-02" -phase: "03-miroflow-embutido" -status: complete -completed: 2026-03-25 ---- - -# Summary: 03-02 — Node.js MiroFlow Bridge - -## What was built - -Bridge Node.js → Python para o MiroFlow: proxy TypeScript com timeout 300s, rotas Express autenticadas e registro imutável de execuções no KG via auditHash SHA-256. - -## Files created/modified - -### Created -- `server/miroflow/engine-proxy.ts` — proxy para :8006, MIROFLOW_TIMEOUT=300_000ms, registerExecutionInKG com SHA-256 -- `server/miroflow/routes.ts` — re-export de registerMiroFlowRoutes - -### Modified -- `server/routes.ts` — import + chamada registerMiroFlowRoutes(app) após registerBiEngineRoutes - -## Key decisions - -- Timeout de 300_000ms (5 min) para POST /analyze — adequado para deepseek-r1:14b -- Health check usa timeout curto (5_000ms) -- KG failure não bloqueia resposta ao cliente (try/catch com console.error) -- auditHash cobre: execution_id + agent + model + input + output - -## TypeScript compilation - -Erros nos novos arquivos: **0** -(Erros pré-existentes em App.tsx e server/modules/miroflow/ não relacionados) - -## Commits - -- `d53be76` — feat(03-02): criar MiroFlow proxy TypeScript com timeout 300s e KG audit logging -- `1a70e87` — feat(03-02): registrar MiroFlow routes em server/routes.ts - -## Self-Check: PASSED diff --git a/.planning/phases/03-miroflow-embutido/03-03-PLAN.md b/.planning/phases/03-miroflow-embutido/03-03-PLAN.md deleted file mode 100644 index de4f523..0000000 --- a/.planning/phases/03-miroflow-embutido/03-03-PLAN.md +++ /dev/null @@ -1,315 +0,0 @@ ---- -id: "03-03" -phase: 03-miroflow-embutido -plan: 03 -type: execute -wave: 2 -depends_on: ["03-02"] -files_modified: - - client/src/components/MiroFlowControl.tsx - - client/src/pages/BiWorkspace.tsx -autonomous: false -requirements: - - REQ-3.6 - -must_haves: - truths: - - "Tab 'Científico' aparece na TabsList de BiWorkspace.tsx" - - "MiroFlowControl.tsx renderiza toggle 'Modo Científico' com ícone Brain" - - "Usuário pode selecionar agente (Statistician / Fiscal Auditor / Researcher)" - - "Usuário pode digitar tarefa e clicar em Analisar" - - "Resultado da análise é exibido em área de texto com scroll" - - "Estado de loading é exibido durante a chamada (ícone Loader2 girando)" - - "Erro da API é exibido ao usuário de forma legível" - - "Tabs existentes (overview, datasources, etc.) continuam funcionando normalmente" - artifacts: - - path: "client/src/components/MiroFlowControl.tsx" - provides: "Componente React com toggle, seletor de agente, input de tarefa e exibição de resultado" - exports: ["MiroFlowControl"] - - path: "client/src/pages/BiWorkspace.tsx" - provides: "Tab 'cientifico' adicionada à TabsList e TabsContent existentes" - contains: "TabsTrigger value=\"cientifico\"" - key_links: - - from: "client/src/components/MiroFlowControl.tsx" - to: "/api/miroflow/analyze" - via: "apiRequest('POST', '/api/miroflow/analyze', {agent, task})" - pattern: "miroflow/analyze" - - from: "client/src/pages/BiWorkspace.tsx" - to: "client/src/components/MiroFlowControl.tsx" - via: "import { MiroFlowControl } from '@/components/MiroFlowControl'" - pattern: "MiroFlowControl" ---- - - -Criar o componente MiroFlowControl.tsx e integrá-lo ao BiWorkspace.tsx como nova tab "Científico" com toggle "Modo Científico". - -Purpose: Expõe as análises científicas MiroFlow diretamente no contexto BI, permitindo ao usuário acionar agentes LLM especializados ao lado dos dashboards Superset. -Output: Tab funcional em BiWorkspace com formulário de análise, seletor de agente e display de resultado. - - - -@$HOME/.claude/get-shit-done/workflows/execute-plan.md -@$HOME/.claude/get-shit-done/templates/summary.md - - - -@.planning/PROJECT.md -@.planning/ROADMAP.md -@.planning/phases/03-miroflow-embutido/03-02-SUMMARY.md -@.planning/phases/03-miroflow-embutido/03-RESEARCH.md - - - -// Estado: -const [activeTab, setActiveTab] = useState("overview"); - -// Estrutura: - - - - Visão Geral - - Fontes de Dados - Upload - Consultas - Gráficos - Backups - - - - ... - ... - - - - - -import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; -// Lucide icons já importados: Bot, Brain NÃO está importado — adicionar ao import -// shadcn/ui components já disponíveis: Button, Card, CardContent, CardHeader, CardTitle, -// Badge, ScrollArea, Input, Textarea, Select, SelectContent, SelectItem, SelectTrigger, SelectValue - - -// Verificar como outros componentes fazem POST — geralmente: -import { apiRequest } from "@/lib/queryClient"; -// ou via useMutation do @tanstack/react-query -const mutation = useMutation({ mutationFn: (body) => apiRequest("POST", "/api/miroflow/analyze", body) }); - - -interface AnalyzeResponse { - agent: string; - model: string; - result: string; - execution_id: string; - duration_ms: number; -} - - - - - - - Task 1: Criar client/src/components/MiroFlowControl.tsx - client/src/components/MiroFlowControl.tsx - - - - /opt/arcadia_merged/client/src/lib/queryClient.ts (confirmar apiRequest signature) - - /opt/arcadia_merged/client/src/pages/BiWorkspace.tsx linhas 1-60 (imports disponíveis e padrão de componentes) - - /opt/arcadia_merged/client/src/components/ (listar arquivos para verificar convenções de nomenclatura) - - - - Criar client/src/components/MiroFlowControl.tsx como componente React standalone. - - O componente deve: - 1. Exibir card com header "Modo Científico" e ícone Brain - 2. Toggle switch ou badge "Ativado" quando em modo científico (estado local `enabled`) - 3. Select para escolha do agente: Statistician (deepseek-r1:14b), Fiscal Auditor (deepseek-r1:14b), Researcher (llama3.1:8b) - 4. Textarea para digitar a tarefa (placeholder específico por agente) - 5. Botão "Analisar" que dispara POST /api/miroflow/analyze - 6. Área de resultado com ScrollArea mostrando a resposta formatada - 7. Estado de loading com Loader2 animado durante chamada - 8. Exibir erros de forma legível (badge vermelho + mensagem) - 9. Metadados do resultado: modelo usado, tempo de execução, execution_id (em texto pequeno) - - Props: `currentDashboardData?: Record` (opcional, para contexto futuro) - - Usar useMutation do @tanstack/react-query para a chamada POST. - - Estrutura de tipos locais: - ```typescript - interface AnalyzeRequest { - agent: "statistician" | "fiscal_auditor" | "researcher"; - task: string; - context?: Record; - } - - interface AnalyzeResponse { - agent: string; - model: string; - result: string; - execution_id: string; - duration_ms: number; - } - ``` - - Agentes disponíveis (hardcoded, sem fetch): - ```typescript - const AGENTS = [ - { value: "statistician", label: "Statistician", model: "deepseek-r1:14b", - placeholder: "Ex: Analise a distribuição de vendas por região no último trimestre" }, - { value: "fiscal_auditor", label: "Fiscal Auditor", model: "deepseek-r1:14b", - placeholder: "Ex: Verifique inconsistências nos registros NFe do CNPJ 12.345.678/0001-90" }, - { value: "researcher", label: "Researcher", model: "llama3.1:8b", - placeholder: "Ex: Quais fornecedores têm maior correlação com atrasos de entrega?" }, - ] as const; - ``` - - Estilização: seguir o padrão dark de BiWorkspace (bg-[#1f334d], text-white, border-[#c89b3c]/20, text-[#c89b3c]). - - NÃO usar estados globais, stores ou contextos externos. - NÃO fazer fetch para /api/miroflow/health neste componente. - - - - cd /opt/arcadia_merged && npx tsc --noEmit --project tsconfig.json 2>&1 | grep -i "MiroFlowControl\|miroflow" | head -10 || echo "TypeScript OK" - - - - - client/src/components/MiroFlowControl.tsx existe e exporta MiroFlowControl como default ou named export - - `npx tsc --noEmit` não retorna erros relacionados a MiroFlowControl.tsx - - Componente tem prop `currentDashboardData?: Record` - - Select com os 3 agentes (statistician, fiscal_auditor, researcher) - - Textarea para task com placeholder dinâmico por agente selecionado - - useMutation configurado para POST /api/miroflow/analyze - - Estado de loading exibido (Loader2 ou spinner equivalente) - - Erro exibido quando mutation.isError - - Resultado exibido quando mutation.isSuccess com metadados (model, duration_ms) - - Nenhuma referência a modelos acima de 14B - - - MiroFlowControl.tsx criado, compila sem erros TypeScript. Componente pronto para ser importado pelo BiWorkspace. - - - - Task 2: Adicionar tab "Científico" ao BiWorkspace.tsx - client/src/pages/BiWorkspace.tsx - - - - /opt/arcadia_merged/client/src/pages/BiWorkspace.tsx linhas 2860-2920 (TabsList atual — localizar exatamente onde inserir) - - /opt/arcadia_merged/client/src/pages/BiWorkspace.tsx linhas 1-55 (imports para adicionar Brain e MiroFlowControl) - - /opt/arcadia_merged/client/src/pages/BiWorkspace.tsx linhas 2950-3050 (após os TabsContent existentes — localizar o fechamento para inserir novo TabsContent) - - - - BiWorkspace.tsx é um arquivo grande (~3000 linhas). Fazer APENAS as 3 modificações cirúrgicas abaixo: - - MODIFICAÇÃO 1 — Adicionar Brain ao import de lucide-react (linha ~10-50): - Localizar `import { ... } from "lucide-react"` e adicionar `Brain` à lista. - (Verificar se Brain já está importado antes de adicionar) - - MODIFICAÇÃO 2 — Adicionar MiroFlowControl import (após os imports existentes): - ```typescript - import { MiroFlowControl } from "@/components/MiroFlowControl"; - ``` - - MODIFICAÇÃO 3 — Adicionar TabsTrigger na TabsList (após o último TabsTrigger existente, antes do fechamento ): - ```tsx - - Científico - - ``` - - MODIFICAÇÃO 4 — Adicionar TabsContent (após o último TabsContent existente, antes do fechamento ): - ```tsx - - - - ``` - - NÃO alterar nenhum TabsTrigger ou TabsContent existente. - NÃO modificar o estado activeTab ou qualquer lógica existente. - NÃO reformatar ou reorganizar o código existente. - NÃO remover nenhum import existente. - Verificar o arquivo antes e depois com grep para confirmar que os 4 tabs originais ainda existem. - - - - cd /opt/arcadia_merged && grep -c 'TabsTrigger value=' client/src/pages/BiWorkspace.tsx && npx tsc --noEmit --project tsconfig.json 2>&1 | grep -i "BiWorkspace\|MiroFlow" | head -5 || echo "TypeScript OK" - - - - - `grep -c 'TabsTrigger value=' client/src/pages/BiWorkspace.tsx` retorna 7 (6 existentes + 1 novo "cientifico") - - `grep 'value="cientifico"' client/src/pages/BiWorkspace.tsx` retorna 2 linhas (TabsTrigger + TabsContent) - - `grep 'Brain' client/src/pages/BiWorkspace.tsx` retorna resultado (importado e usado) - - `grep 'MiroFlowControl' client/src/pages/BiWorkspace.tsx` retorna resultado (importado e usado) - - `npx tsc --noEmit` não retorna erros em BiWorkspace.tsx - - Tabs existentes ("overview", "datasources", "upload", "datasets", "charts", "backups") ainda presentes - - Nenhum outro código do arquivo foi alterado (git diff mostra apenas as 4 adições) - - - BiWorkspace.tsx contém tab "Científico" que renderiza MiroFlowControl. Tabs existentes preservadas. Compila sem erros. - - - - - - MiroFlowControl.tsx: componente com toggle "Modo Científico", seletor de 3 agentes, textarea de tarefa e display de resultado - - BiWorkspace.tsx: tab "Científico" adicionada (7 tabs no total) - - Backend (planos 01 e 02): microserviço Python porta 8006 + proxy Node + KG logging - - - - 1. Iniciar o servidor: `npm run dev` (ou verificar se já está rodando) - 2. Iniciar o microserviço MiroFlow: `MIROFLOW_PORT=8006 python3 server/python/miroflow_service.py &` - 3. Navegar para /bi-workspace no browser - 4. Verificar que a tab "Científico" aparece no TabsList (ícone Brain + texto) - 5. Clicar na tab "Científico" - 6. Verificar que o painel MiroFlowControl renderiza sem erros JavaScript no console - 7. Selecionar o agente "Statistician" - 8. Digitar uma tarefa simples: "Liste os 3 principais insights sobre análise estatística" - 9. Clicar em "Analisar" - 10. Verificar que o estado de loading aparece (Loader2 girando) - 11. Após resposta: verificar que o resultado é exibido com o modelo (deepseek-r1:14b) e tempo de execução - 12. Verificar GET http://localhost:8006/health retorna {"online": true} em outro aba - 13. Verificar as outras 6 tabs (overview, datasources, etc.) ainda funcionam normalmente - - - - Digite "aprovado" se tudo funcionar corretamente. - Ou descreva os problemas encontrados (ex: "tab não aparece", "erro 502 na análise", "loading infinito"). - - - - - - -```bash -# Verificar estrutura dos arquivos: -ls /opt/arcadia_merged/client/src/components/MiroFlowControl.tsx - -# Verificar tab adicionada: -grep -n 'cientifico\|Científico\|MiroFlowControl\|Brain' /opt/arcadia_merged/client/src/pages/BiWorkspace.tsx - -# Verificar compilação: -cd /opt/arcadia_merged && npx tsc --noEmit 2>&1 | tail -5 - -# Contagem de tabs: -grep -c 'TabsTrigger value=' /opt/arcadia_merged/client/src/pages/BiWorkspace.tsx -``` - - - -- MiroFlowControl.tsx existe e exporta componente válido -- BiWorkspace.tsx tem 7 TabsTriggers (6 originais + "cientifico") -- TypeScript compila sem erros nos novos arquivos -- Usuário aprova verificação visual do checkpoint -- Tabs existentes do BiWorkspace continuam funcionando - - - -Após conclusão e aprovação do checkpoint, criar `.planning/phases/03-miroflow-embutido/03-03-SUMMARY.md` com: -- Arquivos criados/modificados -- Screenshot ou descrição do estado visual da tab "Científico" -- Resultado da verificação humana -- Qualquer ajuste feito após o checkpoint - diff --git a/.planning/phases/03-miroflow-embutido/03-RESEARCH.md b/.planning/phases/03-miroflow-embutido/03-RESEARCH.md deleted file mode 100644 index 5a1a9ca..0000000 --- a/.planning/phases/03-miroflow-embutido/03-RESEARCH.md +++ /dev/null @@ -1,551 +0,0 @@ -# Phase 3: MiroFlow Embutido - Research - -**Researched:** 2026-03-25 -**Domain:** Python agent framework (MiroFlow) integrado ao Node.js/Express + Ollama local + Superset bridge -**Confidence:** HIGH (baseado em inspeção direta do código-fonte e serviços ativos) - ---- - -## Summary - -O Phase 3 conecta o framework Python MiroFlow (já clonado como submodule em `server/modules/miroflow/`) ao backend Node.js do Arcádia Suite, expondo um endpoint `POST /api/miroflow/analyze` que despacha para um microserviço Python FastAPI. Esse microserviço instancia agentes MiroFlow configurados via YAML, aponta para o Ollama local (já rodando na porta 11434 com `deepseek-r1:14b` instalado), e registra cada execução como nó imutável no KG (tabela `graph_nodes` via `/api/graph/nodes`). - -O padrão de integração Node ↔ Python já está estabelecido no projeto: `server/bi/engine-proxy.ts` e `server/python/bi_analysis_service.py` demonstram o fluxo exato — Express proxy faz `fetch()` para FastAPI local; a resposta é repassada ao cliente. O novo microserviço MiroFlow (`miroflow_service.py`) seguirá o mesmo padrão, rodando na porta 8006. O agente `Researcher` exige `llama3.1:8b`, que **ainda não está instalado no Ollama** (apenas `deepseek-r1:14b`, `llama3.2:3b` e `nomic-embed-text` estão disponíveis). - -No frontend, o componente `MiroFlowControl.tsx` será um painel overlay/tab injetado na página `BiWorkspace.tsx` que já usa o `SupersetDashboard` component. O toggle "Modo Científico" chama `POST /api/miroflow/analyze` e exibe a resposta estruturada ao lado do dashboard Superset. - -**Primary recommendation:** Construir `server/python/miroflow_service.py` como FastAPI standalone (porta 8006), instanciar agentes MiroFlow com YAML inline (sem arquivos externos), usar `UnifiedOpenAIClient` apontando para Ollama via `OLLAMA_BASE_URL/v1`, registrar execuções via `createNode()` do graph service. - ---- - -## User Constraints - -*(Seção obrigatória — copiada do STATE.md/ROADMAP.md/PROJECT.md que fazem as vezes de CONTEXT.md)* - -### Locked Decisions -- Stack: Node.js + TypeScript backend, React + TypeScript frontend, PostgreSQL, Neo4j KG -- IA: Ollama local MÁXIMO 14B — `deepseek-r1:14b` para Statistician e Fiscal Auditor, `llama3.1:8b` para Researcher -- **NUNCA usar modelos acima de 14B**: proibido citar ou planejar `deepseek-r1:32b`, `deepseek-r1:70b`, `llama3.1:70b` ou qualquer modelo maior -- MiroFlow já clonado em `server/modules/miroflow/` como submodule Python -- Branch de deploy: `Servidor` -- Superset em produção com RLS — não alterar configurações existentes -- Backend-first: API definida antes do frontend -- Auditoria imutável em todas as execuções (KG) - -### Claude's Discretion -- Porta do microserviço MiroFlow (recomenda-se 8006 pelo padrão existente) -- Estrutura interna dos agentes MiroFlow (YAML inline vs arquivos externos) -- Forma de integrar o toggle no frontend (overlay, tab, painel lateral) -- Como fazer o `llama3.1:8b` ser baixado (wave 0 task vs setup manual) - -### Deferred Ideas (OUT OF SCOPE) -- Versionamento Git-like de skills (Phase 2 pendente, não Phase 3) -- OpenClaw (Phase 4) -- Automation Fabric (Phase 5) -- Dev Center Completo (Phase 6) - ---- - -## Standard Stack - -### Core -| Library | Version | Purpose | Why Standard | -|---------|---------|---------|--------------| -| MiroFlow | 1.7.0 | Framework de agentes Python | Já no submodule, desenvolvido pela MiromindAI | -| FastAPI | >=0.115.0 | Microserviço Python | Padrão já usado em todos os serviços Python do projeto | -| uvicorn | >=0.32.0 | ASGI server | Usado em todos os serviços Python | -| omegaconf | (via miroflow deps) | Configuração YAML com variáveis | Dependência central do MiroFlow | -| hydra-core | >=1.3.2 | Composição de configurações | Dependência central do MiroFlow | -| openai | ==1.78.1 | Cliente HTTP para Ollama (OpenAI-compat.) | MiroFlow usa `UnifiedOpenAIClient` via openai SDK | -| httpx / aiohttp | >=0.28.1 / >=3.12.15 | HTTP async | Dependências do MiroFlow e FastAPI | - -### Supporting -| Library | Version | Purpose | When to Use | -|---------|---------|---------|-------------| -| python-dotenv | >=1.1.1 | Leitura de .env | Inicialização do microserviço | -| pydantic | >=2.x | Validação de request/response | Models FastAPI | -| neo4j (driver) | opcional | Neo4j direto | Apenas se precisar grafo real; por ora usa `graph_nodes` PostgreSQL | -| psycopg2-binary | >=2.9.x | PostgreSQL direto | Se microserviço precisar escrever no banco | - -### Alternatives Considered -| Instead of | Could Use | Tradeoff | -|------------|-----------|----------| -| Microserviço FastAPI separado | Subprocess Node → Python | subprocess é síncrono e frágil; FastAPI segue padrão estabelecido | -| YAML files externos | YAML inline (dict) em Python | Inline elimina dependência de caminhos de arquivo em container | -| Ollama direto (porta 11434) | Via LiteLLM gateway (porta 4000) | LiteLLM tem fallback e roteamento; Ollama direto é mais simples para agentes isolados | - -**Installation (para o microserviço):** -```bash -# Instalar dependências no ambiente Python do servidor -pip install fastapi uvicorn omegaconf hydra-core openai python-dotenv pydantic psycopg2-binary -# Ou instalar o miroflow inteiro com uv: -cd server/modules/miroflow && uv sync -``` - -**Version verification:** Os pacotes acima são os listados no `pyproject.toml` do MiroFlow v1.7.0, verificado diretamente no arquivo. - ---- - -## Architecture Patterns - -### Recommended Project Structure -``` -server/python/ -├── miroflow_service.py # novo microserviço FastAPI (porta 8006) -├── bi_analysis_service.py # existente (referência de padrão) -└── ... - -server/miroflow/ -├── routes.ts # Express router: POST /api/miroflow/analyze -└── engine-proxy.ts # fetch() para http://localhost:8006 - -client/src/ -├── pages/BiWorkspace.tsx # EXISTENTE — adicionar tab "Científico" -└── components/ - └── MiroFlowControl.tsx # NOVO — toggle + resultado da análise - -docker/python-entrypoint.sh # adicionar case "miroflow" → porta 8006 -docker-compose.prod.yml # adicionar serviço miroflow (porta 8006) -``` - -### Pattern 1: Node → Python Microservice Proxy -**What:** Express recebe a request, faz fetch() para FastAPI, retorna o resultado. Sem subprocess, sem child_process. -**When to use:** Sempre que Node.js precisar de lógica Python (pandas, ML, agentes). -**Example:** -```typescript -// Source: server/bi/engine-proxy.ts (padrão existente) -const MIROFLOW_URL = `http://${process.env.MIROFLOW_HOST || "localhost"}:${process.env.MIROFLOW_PORT || "8006"}`; - -async function proxyToMiroFlow(path: string, body: object): Promise { - const response = await fetch(`${MIROFLOW_URL}${path}`, { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify(body), - signal: AbortSignal.timeout(300_000), // 5min — modelos LLM são lentos - }); - if (!response.ok) { - const err = await response.json().catch(() => ({ detail: response.statusText })); - throw new Error(err.detail || `MiroFlow error: ${response.status}`); - } - return response.json(); -} -``` - -### Pattern 2: MiroFlow Agent com Ollama via UnifiedOpenAIClient -**What:** MiroFlow usa `UnifiedOpenAIClient` com `base_url` apontando para Ollama (OpenAI-compatible API em `/v1`). -**When to use:** Para todos os agentes do Phase 3. -**Example:** -```python -# Source: server/modules/miroflow/miroflow/llm/openai_client.py + config/llm/base.yaml -from miroflow.agents.factory import build_agent -from miroflow.agents.context import AgentContext - -AGENT_CONFIG_STATISTICIAN = { - "type": "IterativeAgentWithToolAndRollback", - "max_turns": 10, - "llm": { - "provider_class": "UnifiedOpenAIClient", - "model_name": "deepseek-r1:14b", - "api_key": "ollama", # Ollama não valida api_key - "base_url": "http://localhost:11434/v1", # Ollama OpenAI-compat - "max_tokens": 8192, - "temperature": 0.7, - "top_p": 1.0, "min_p": 0.0, "top_k": -1, - "reasoning_effort": None, "repetition_penalty": 1.0, - "max_context_length": -1, "async_client": True, - "disable_cache_control": True, "keep_tool_result": -1, - "use_tool_calls": False, "oai_tool_thinking": False, - }, -} -agent = build_agent(AGENT_CONFIG_STATISTICIAN) -ctx = AgentContext(task_description="Analise os seguintes dados SQL: ...") -result = await agent.run(ctx) -``` - -### Pattern 3: Registro Imutável no KG via graph_nodes -**What:** Após cada execução MiroFlow, registrar no PostgreSQL via `POST /api/graph/nodes`. -**When to use:** Toda execução de agente (success ou error). -**Example:** -```typescript -// Source: server/graph/service.ts createNode() — chamado pelo routes.ts de miroflow -await fetch("/api/graph/nodes", { - method: "POST", - body: JSON.stringify({ - type: "miroflow_execution", - tenantId: req.user?.tenantId, - data: { - agent: "statistician", - model: "deepseek-r1:14b", - input: analysisRequest, - output: analysisResult, - auditHash: sha256(JSON.stringify({ executionId, input, output })), - executedAt: new Date().toISOString(), - } - }) -}); -``` - -### Pattern 4: MiroFlowControl.tsx como tab em BiWorkspace -**What:** BiWorkspace.tsx já tem estrutura de tabs (Tabs/TabsContent de shadcn/ui). Adicionar tab "Científico" que renderiza `MiroFlowControl`. -**When to use:** Ponto de entrada do toggle "Modo Científico" no contexto do BI. -**Example:** -```tsx -// Source: client/src/pages/BiWorkspace.tsx (padrão de tabs existente) -import { MiroFlowControl } from "@/components/MiroFlowControl"; - -// Dentro do : - Científico - -// Dentro das : - - - -``` - -### Anti-Patterns to Avoid -- **subprocess.run() no Node**: Não usar `child_process.spawn()` para chamar Python — use o microserviço FastAPI (padrão estabelecido) -- **Carregar miroflow no container Node**: O Dockerfile principal é Node.js puro — Python deve rodar em container separado (Dockerfile.python) -- **Modelos > 14B**: Nunca usar `deepseek-r1:32b`, `deepseek-r1:70b`, `llama3.1:70b` ou qualquer modelo acima de 14B parâmetros -- **Modificar configurações do Superset**: O proxy `/superset/*` e as rotas `/api/superset/*` existentes não devem ser alterados -- **Hardcoded OLLAMA_BASE_URL**: Sempre ler de env var `OLLAMA_BASE_URL` (default `http://localhost:11434`) - ---- - -## Don't Hand-Roll - -| Problem | Don't Build | Use Instead | Why | -|---------|-------------|-------------|-----| -| Orquestração de agentes LLM | Loop manual de chamadas LLM | MiroFlow `IterativeAgentWithToolAndRollback` | Rollback automático, retry, tool calling já implementado | -| Proxy Node → Python | Child process / spawn | `fetch()` para FastAPI (padrão `engine-proxy.ts`) | Stateless, async, sem gestão de processos | -| Configuração de LLM | Classe própria de cliente | `UnifiedOpenAIClient` do MiroFlow | Já tem retry, context limit handling, tool protocol | -| Embedding da análise no Superset | iframe manual com JS | `SupersetDashboard.tsx` já existente | Guest token, SDK do Superset, error handling prontos | -| Logs de execução imutáveis | Nova tabela no banco | `graph_nodes` + `createNode()` via `server/graph/service.ts` | Infraestrutura de KG já existente com embeddings | -| Validação de request/response | Manual | Pydantic models + FastAPI auto-validation | Type safety e OpenAPI spec grátis | - -**Key insight:** O projeto já tem todos os primitivos necessários. Phase 3 é essencialmente "conectar os pontos" — o agente Python já existe, o gateway LLM (LiteLLM/Ollama) já está configurado, o KG já tem tabelas, o padrão de proxy Node→Python já está implementado. - ---- - -## Runtime State Inventory - -> Fase é greenfield (novo microserviço e novas rotas). Não há renomeações ou migrações de dados existentes. - -| Category | Items Found | Action Required | -|----------|-------------|------------------| -| Stored data | `graph_nodes` no PostgreSQL — usado pelo KG existente | Nenhum — novas inserções com `type: "miroflow_execution"` | -| Live service config | Ollama rodando na porta 11434 com `deepseek-r1:14b` instalado | `llama3.1:8b` NÃO instalado — precisa de `ollama pull llama3.1:8b` | -| OS-registered state | Nenhum Task Scheduler / cron para MiroFlow | Nenhuma ação necessária | -| Secrets/env vars | `OLLAMA_BASE_URL=http://ollama:11434` já no `.env`; `LITELLM_API_KEY` existente | Adicionar `MIROFLOW_PORT=8006` no `.env` e docker-compose | -| Build artifacts | `server/modules/miroflow/` tem `uv.lock` mas sem `.venv` instalado | Wave 0: instalar dependências via `uv sync` ou `pip install` no Dockerfile.python | - -**Modelo faltando:** `llama3.1:8b` não está instalado no Ollama (`False` confirmado por `curl http://localhost:11434/api/tags`). Instalado: `deepseek-r1:14b` (8.4GB), `arcadia-agent:latest` (2GB), `llama3.2:3b` (2GB), `nomic-embed-text` (274MB). O plano deve incluir `ollama pull llama3.1:8b` como task de Wave 0 ou pré-requisito. - ---- - -## Environment Availability - -| Dependency | Required By | Available | Version | Fallback | -|------------|------------|-----------|---------|----------| -| Ollama API `:11434` | Todos os agentes MiroFlow | ✓ | 0.18.2 | — | -| `deepseek-r1:14b` | Statistician, Fiscal Auditor | ✓ | 8.4GB | — | -| `llama3.1:8b` | Researcher | ✗ | — | `llama3.2:3b` (degraded) ou `deepseek-r1:14b` | -| Python 3.12 | Microserviço FastAPI | ✓ | 3.12.3 | — | -| `uv` | Instalar deps MiroFlow | ✓ | 0.9.30 | `pip3` | -| FastAPI/uvicorn | Microserviço | ✓ | fastapi 0.128.8 | — | -| `omegaconf` (sistema) | MiroFlow direto | ✗ | — | Instalar via `uv sync` no `server/modules/miroflow/` | -| PostgreSQL `:5432` | KG graph_nodes | ✓ | 16 | — | -| Neo4j `:7687` | KG real (opcional) | Requer profile `[kg]` | — | `graph_nodes` PostgreSQL (já usado) | - -**Missing dependencies with no fallback:** -- `llama3.1:8b` para o agente Researcher — deve ser baixado em Wave 0 (`ollama pull llama3.1:8b`) - -**Missing dependencies with fallback:** -- `omegaconf` no sistema: instalar com `pip3 install omegaconf hydra-core` ou rodar MiroFlow dentro de venv com `uv sync` -- `llama3.1:8b` temporariamente: usar `deepseek-r1:14b` como fallback até o download completar - ---- - -## Common Pitfalls - -### Pitfall 1: Ollama não expõe `/v1` sem flag explícita em versões antigas -**What goes wrong:** `UnifiedOpenAIClient` do MiroFlow usa `base_url=http://localhost:11434/v1` (OpenAI-compatible endpoint). Versões antigas do Ollama (<0.1.24) não tinham esse endpoint. -**Why it happens:** Ollama 0.18.2 (confirmado no servidor) já suporta `/v1/chat/completions`. Mas o endpoint retorna erro se o modelo não estiver carregado. -**How to avoid:** Verificar `GET http://localhost:11434/api/tags` antes de iniciar o agente. Pré-carregar o modelo com `ollama run deepseek-r1:14b` ou `ollama pull`. -**Warning signs:** `404 Not Found` na URL `/v1/chat/completions`, ou `model not found` no corpo da resposta. - -### Pitfall 2: MiroFlow requer dependências Python não instaladas no container Node -**What goes wrong:** O `Dockerfile` principal é Node.js Alpine — não tem Python. Se tentar importar `miroflow` no contexto Node (via python-bridge ou similar), vai falhar. -**Why it happens:** A tentativa de `from omegaconf import ...` falha com `ModuleNotFoundError` porque o sistema Python não tem as deps do MiroFlow. -**How to avoid:** Manter a separação clara: MiroFlow roda SOMENTE em `Dockerfile.python` como microserviço FastAPI. Node nunca importa Python diretamente. -**Warning signs:** Erro de `ModuleNotFoundError: No module named 'omegaconf'` nos logs do app principal. - -### Pitfall 3: Timeout do fetch() insuficiente para modelos grandes -**What goes wrong:** `deepseek-r1:14b` com raciocínio pode levar 60-120 segundos para responder. O fetch padrão tem timeout de 30s nos outros proxies. -**Why it happens:** O `bi/engine-proxy.ts` usa `BI_ENGINE_TIMEOUT = 30000`. Para LLMs de 14B, isso é insuficiente. -**How to avoid:** Usar `AbortSignal.timeout(300_000)` (5 minutos) no proxy MiroFlow. Implementar streaming ou polling se necessário. -**Warning signs:** `AbortError: The operation was aborted` nos logs do Node. - -### Pitfall 4: Neo4j não está ativo por padrão — usar graph_nodes do PostgreSQL -**What goes wrong:** O `docker-compose.yml` tem Neo4j no profile `[kg]` — não está ativo em deploy padrão. -**Why it happens:** Neo4j é opcional; o KG do Arcádia usa `graph_nodes` PostgreSQL por padrão. -**How to avoid:** Para imutabilidade, usar `POST /api/graph/nodes` (PostgreSQL), não o driver `neo4j` Python direto. O `server/graph/service.ts` já implementa isso com hashing. -**Warning signs:** `Connection refused: 7687` se tentar conectar ao Neo4j sem o profile ativo. - -### Pitfall 5: MiroFlow não tem `llama3.1:8b` instalado -**What goes wrong:** O agente Researcher usa `llama3.1:8b` mas esse modelo não está no Ollama (`False` confirmado por inspeção direta). -**Why it happens:** Apenas `deepseek-r1:14b`, `arcadia-agent:latest`, `llama3.2:3b` e `nomic-embed-text` foram instalados. -**How to avoid:** Incluir `ollama pull llama3.1:8b` como step explícito na Wave 0 do plano. -**Warning signs:** Agente Researcher falha com `model 'llama3.1:8b' not found`. - -### Pitfall 6: BiWorkspace.tsx é uma página grande — cuidado ao modificar -**What goes wrong:** `BiWorkspace.tsx` tem muitas funcionalidades (datasets, charts, dashboards, backup, BI engine). Modificação descuidada pode quebrar features existentes. -**Why it happens:** O arquivo tem ~1000+ linhas com múltiplas tabs e estados. -**How to avoid:** Adicionar MiroFlowControl como componente SEPARADO importado, não modificar lógica existente. Adicionar apenas uma nova `TabsTrigger` e `TabsContent`. -**Warning signs:** Erros de TypeScript em outros tabs depois da edição. - ---- - -## Code Examples - -Verified patterns from official sources: - -### MiroFlow Agent com Ollama (config inline Python) -```python -# Source: server/modules/miroflow/miroflow/agents/base.py + config/llm/base.yaml -import sys -sys.path.insert(0, "/app/server/modules/miroflow") - -import asyncio -from miroflow.agents.factory import build_agent -from miroflow.agents.context import AgentContext - -OLLAMA_BASE_URL = os.getenv("OLLAMA_BASE_URL", "http://localhost:11434") - -def make_agent_cfg(model: str) -> dict: - return { - "type": "IterativeAgentWithToolAndRollback", - "name": f"arcadia_{model.replace(':', '_')}", - "max_turns": 10, - "llm": { - "provider_class": "UnifiedOpenAIClient", - "model_name": model, - "api_key": "ollama", - "base_url": f"{OLLAMA_BASE_URL}/v1", - "max_tokens": 8192, - "temperature": 0.7, - "top_p": 1.0, "min_p": 0.0, "top_k": -1, - "reasoning_effort": None, "repetition_penalty": 1.0, - "max_context_length": -1, "async_client": True, - "disable_cache_control": True, "keep_tool_result": -1, - "use_tool_calls": False, "oai_tool_thinking": False, - }, - } - -async def run_agent(agent_type: str, task: str) -> str: - model = "deepseek-r1:14b" if agent_type in ("statistician", "fiscal_auditor") else "llama3.1:8b" - cfg = make_agent_cfg(model) - agent = build_agent(cfg) - ctx = AgentContext(task_description=task) - result = await agent.run(ctx) - return result.get("summary", str(result)) -``` - -### FastAPI endpoint pattern (seguindo bi_analysis_service.py) -```python -# Source: server/python/bi_analysis_service.py (padrão existente) -from fastapi import FastAPI -from pydantic import BaseModel - -app = FastAPI(title="Arcádia MiroFlow Service", version="1.0.0") - -class AnalyzeRequest(BaseModel): - agent: str # "statistician" | "fiscal_auditor" | "researcher" - task: str - context: dict = {} - tenant_id: int | None = None - -class AnalyzeResponse(BaseModel): - agent: str - model: str - result: str - execution_id: str - duration_ms: int - -@app.post("/analyze", response_model=AnalyzeResponse) -async def analyze(req: AnalyzeRequest): - ... -``` - -### Express proxy para MiroFlow (seguindo engine-proxy.ts) -```typescript -// Source: server/bi/engine-proxy.ts (padrão existente) -const MIROFLOW_URL = `http://${process.env.MIROFLOW_HOST || "localhost"}:${ - process.env.MIROFLOW_PORT || "8006" -}`; - -export function registerMiroFlowRoutes(app: Express): void { - app.post("/api/miroflow/analyze", async (req: Request, res: Response) => { - if (!req.isAuthenticated()) return res.status(401).json({ error: "Não autenticado" }); - try { - const response = await fetch(`${MIROFLOW_URL}/analyze`, { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ ...req.body, tenant_id: (req.user as any)?.tenantId }), - signal: AbortSignal.timeout(300_000), - }); - const data = await response.json(); - // Registrar no KG - await registerExecutionInKG(req, data); - res.json(data); - } catch (err: any) { - res.status(502).json({ error: err.message }); - } - }); - - app.get("/api/miroflow/health", async (_req, res) => { - try { - const r = await fetch(`${MIROFLOW_URL}/health`, { signal: AbortSignal.timeout(5000) }); - res.json({ online: r.ok, url: MIROFLOW_URL }); - } catch { - res.json({ online: false, url: MIROFLOW_URL }); - } - }); -} -``` - -### Registro no KG (graph_nodes) -```typescript -// Source: server/graph/service.ts createNode() -import { createNode } from "../graph/service"; -import crypto from "crypto"; - -async function registerExecutionInKG(req: any, execData: any) { - const auditHash = crypto - .createHash("sha256") - .update(JSON.stringify(execData)) - .digest("hex"); - await createNode({ - type: "miroflow_execution", - tenantId: req.user?.tenantId, - data: { ...execData, auditHash, immutable: true }, - }); -} -``` - ---- - -## State of the Art - -| Old Approach | Current Approach | When Changed | Impact | -|--------------|------------------|--------------|--------| -| Llamaindex/LangChain para agentes | MiroFlow (framework próprio MiromindAI) | 2025-08 | Performance-first, benchmarks públicos, já no submodule | -| OpenAI API direta | Ollama local via LiteLLM gateway | 2025 (Arcádia) | Soberania total dos dados | -| Neo4j obrigatório para KG | graph_nodes PostgreSQL + Neo4j opcional | Phase 1 | Sem dependência de serviço extra em produção básica | -| Hydra config files externos | Config dict inline (Python) | MiroFlow 1.x | Sem dependência de paths, mais fácil em containers | - -**Deprecated/outdated:** -- MiroFlow via CLI (`python run_single_task.py`): adequado para benchmark, mas não para microserviço de produção. Usar `web_app/main.py` como referência OU criar FastAPI própria. -- Modelos > 14B: explicitamente proibidos na arquitetura do projeto. - ---- - -## Open Questions - -1. **`llama3.1:8b` vs `llama3.2:3b` para Researcher** - - What we know: `llama3.1:8b` não está instalado; `llama3.2:3b` está (2GB, já disponível) - - What's unclear: Se João quer baixar `llama3.1:8b` (4.7GB a mais) ou aceitar `llama3.2:3b` como substituto para o Researcher - - Recommendation: Plano deve incluir `ollama pull llama3.1:8b` como Wave 0, com fallback para `llama3.2:3b` se bandwidth for problema - -2. **MiroFlow via web_app existente vs FastAPI própria** - - What we know: `server/modules/miroflow/web_app/main.py` é uma FastAPI completa com session manager e task executor; `server/python/bi_analysis_service.py` é um FastAPI simples sem estado - - What's unclear: Usar o `web_app` completo do MiroFlow (mais funcionalidades) ou escrever `miroflow_service.py` minimal seguindo o padrão de outros serviços - - Recommendation: Escrever `miroflow_service.py` minimal — mais simples, sem session management, sem frontend próprio do MiroFlow - -3. **Registro de execuções: graph_nodes vs skill_executions** - - What we know: `skill_executions` é específico para Skills Arcádia; `graph_nodes` é KG genérico - - What's unclear: O requirement diz "KG" — se é necessário usar o Neo4j real ou PostgreSQL `graph_nodes` é suficiente - - Recommendation: Usar `graph_nodes` PostgreSQL com `type: "miroflow_execution"` — atende o requisito de imutabilidade sem depender do Neo4j (profile opcional) - -4. **Posicionamento do MiroFlowControl na UI** - - What we know: `BiWorkspace.tsx` já tem sistema de tabs (LayoutDashboard, Database, BarChart3...); `Scientist.tsx` já existe como página standalone de análise científica - - What's unclear: Se o toggle deve ficar dentro do BiWorkspace (access contextual) ou se deve ser um botão flutuante ou se Scientist.tsx deve ser integrado ao BI - - Recommendation: Tab "Científico" dentro de `BiWorkspace.tsx` — mais coerente com o objetivo "integrado ao Superset" - ---- - -## Validation Architecture - -> `workflow.nyquist_validation` não encontrado em `.planning/config.json` (arquivo não existe). Tratado como habilitado. - -### Test Framework -| Property | Value | -|----------|-------| -| Framework | pytest (Python) + vitest/jest implícito (TS) | -| Config file | Nenhum — Wave 0 deve criar `pytest.ini` para o microserviço | -| Quick run command | `pytest server/python/test_miroflow_service.py -x` | -| Full suite command | `pytest server/python/ -v` | - -### Phase Requirements → Test Map -| Req ID | Behavior | Test Type | Automated Command | File Exists? | -|--------|----------|-----------|-------------------|-------------| -| REQ-3.1 | MiroFlow configurado para Ollama local ≤14B | integration | `pytest tests/test_miroflow_ollama.py -x` | ❌ Wave 0 | -| REQ-3.2 | Agente Statistician analisa SQL com deepseek-r1:14b | integration | `pytest tests/test_miroflow_service.py::test_statistician -x` | ❌ Wave 0 | -| REQ-3.3 | Agente Fiscal Auditor valida NFe/SPED com deepseek-r1:14b | integration | `pytest tests/test_miroflow_service.py::test_fiscal_auditor -x` | ❌ Wave 0 | -| REQ-3.4 | Agente Researcher consulta KG com llama3.1:8b | integration | `pytest tests/test_miroflow_service.py::test_researcher -x` | ❌ Wave 0 | -| REQ-3.5 | `POST /api/miroflow/analyze` retorna análise estruturada | integration | `curl -X POST localhost:5000/api/miroflow/analyze ...` | ❌ Wave 0 | -| REQ-3.6 | MiroFlowControl.tsx toggle aparece no Superset/BiWorkspace | manual | Inspeção visual no browser | N/A | -| REQ-3.7 | Execuções registradas com imutabilidade no KG | unit | `pytest tests/test_miroflow_kg.py -x` | ❌ Wave 0 | - -### Sampling Rate -- **Per task commit:** `pytest server/python/test_miroflow_service.py -x` -- **Per wave merge:** `pytest server/python/ -v` -- **Phase gate:** Health check `/api/miroflow/health` retorna `{"online": true}` + todos os 3 agentes respondem com modelo correto - -### Wave 0 Gaps -- [ ] `server/python/test_miroflow_service.py` — cobre REQ-3.1, 3.2, 3.3, 3.4, 3.5, 3.7 -- [ ] `server/python/miroflow_service.py` — o microserviço principal -- [ ] `server/miroflow/routes.ts` + `engine-proxy.ts` — rotas Express -- [ ] `client/src/components/MiroFlowControl.tsx` — componente React -- [ ] `ollama pull llama3.1:8b` — modelo necessário para Researcher (Wave 0 setup) -- [ ] Instalar dependências MiroFlow: `pip install omegaconf hydra-core openai` (ou `uv sync` no diretório do submodule) - ---- - -## Sources - -### Primary (HIGH confidence) -- Inspeção direta: `/opt/arcadia_merged/server/modules/miroflow/pyproject.toml` — versão 1.7.0, dependências confirmadas -- Inspeção direta: `/opt/arcadia_merged/server/modules/miroflow/miroflow/llm/openai_client.py` — `UnifiedOpenAIClient`, `base_url` configurável -- Inspeção direta: `/opt/arcadia_merged/server/modules/miroflow/miroflow/agents/base.py` — `BaseAgent`, `AgentContext`, `build_agent()` -- Inspeção direta: `/opt/arcadia_merged/server/modules/miroflow/config/llm/base.yaml` — campos obrigatórios do LLM config -- Inspeção direta: `/opt/arcadia_merged/server/bi/engine-proxy.ts` — padrão estabelecido de proxy Node → Python -- Inspeção direta: `/opt/arcadia_merged/server/python/bi_analysis_service.py` — padrão do microserviço FastAPI -- Inspeção direta: `/opt/arcadia_merged/docker/litellm-config.yaml` — `deepseek-r1:14b` já configurado como `arcadia-default` -- Inspeção direta: `/opt/arcadia_merged/docker-compose.prod.yml` — `OLLAMA_BASE_URL` configurado, serviço `ollama` com profile `[ai]` -- Runtime check: `curl http://localhost:11434/api/tags` — modelos instalados confirmados -- Runtime check: `curl http://localhost:11434/api/version` — Ollama 0.18.2 com `/v1` support - -### Secondary (MEDIUM confidence) -- Inspeção direta: `/opt/arcadia_merged/server/modules/miroflow/miroflow/agents/iterative_agent_with_rollback.py` — tipo `IterativeAgentWithToolAndRollback` confirmado -- Inspeção direta: `/opt/arcadia_merged/server/modules/miroflow/web_app/main.py` — FastAPI web_app existente no submodule (alternativa não usada) -- Inspeção direta: `/opt/arcadia_merged/server/graph/service.ts` — `createNode()`, `graph_nodes` tabela - -### Tertiary (LOW confidence) -- Inferência sobre tempo de resposta do `deepseek-r1:14b` (60-120s) baseada em conhecimento geral de modelos 14B — não medido diretamente no servidor - ---- - -## Metadata - -**Confidence breakdown:** -- Standard stack: HIGH — verificado diretamente nos arquivos do submodule e nas dependências instaladas -- Architecture: HIGH — padrões copiados de código existente funcionando em produção -- Pitfalls: HIGH (3-5) e MEDIUM (1-2) — baseados em inspeção direta do runtime e código -- Ambiente: HIGH — testado com curl direto ao Ollama e listagem de modelos - -**Research date:** 2026-03-25 -**Valid until:** 2026-04-25 (30 dias; stack estável, Ollama versão fixada) - ---- - -## RESEARCH COMPLETE diff --git a/.planning/phases/04-openclaw-embutido/04-CONTEXT.md b/.planning/phases/04-openclaw-embutido/04-CONTEXT.md deleted file mode 100644 index 3cfb45b..0000000 --- a/.planning/phases/04-openclaw-embutido/04-CONTEXT.md +++ /dev/null @@ -1,97 +0,0 @@ -# Phase 4 Context — OpenClaw Embutido - -> Generated in --auto mode on 2026-03-26. All decisions auto-selected with recommended defaults. - -## Phase Goal - -Skills emergentes criadas automaticamente a partir de padrões detectados em `skill_executions`. - -## Prior Context Applied - -- **Stack de IA:** Ollama local via LiteLLM — usar `llama3.1:8b` para geração de drafts (leve, rápido) -- **Backend-first:** API definida antes do frontend -- **Auditoria imutável:** todas as execuções registradas com SHA-256 -- **Schema já existe:** `detected_patterns` e `skill_suggestions` em `shared/schema.ts` — usar sem alterar - ---- - -## Decisions - -### 1. O que constitui um "padrão"? - -**[auto] Mesma skill executada ≥3 vezes em 30 dias com confiança ≥80%** - -- Fonte de dados: tabela `skill_executions` -- Agrupamento: `skillId + userId` (por usuário, não global) -- Confiança calculada como: `(frequency / max_frequency_in_window) * 100` -- Janela: `lastSeenAt - firstSeenAt ≤ 30 dias` -- Thresholds alinhados com o roadmap: min 3 ocorrências, 30 dias, 80% confiança - -### 2. Trigger do PatternDetector - -**[auto] Cron job a cada hora (setInterval no servidor Node.js)** - -- Sem dependência de infraestrutura externa (sem Redis, sem Bull) -- Ao iniciar, PatternDetector registra no startup do servidor -- Execuções recentes analisadas em lote; padrões gravados em `detected_patterns` -- Se padrão já existe (mesmo skillId + userId): atualiza frequency + lastSeenAt - -### 3. Geração do body da skill emergente - -**[auto] AI via llama3.1:8b (LiteLLM) gera o body do DRAFT** - -- Ao atingir threshold: PatternDetector cria entrada em `skill_suggestions` (status: `pending`) -- Skill DRAFT gerada automaticamente em `arcadia_skills` (status: `draft`, source: `openclaw`) -- Body gerado via prompt para llama3.1:8b descrevendo o padrão detectado -- DRAFT aguarda aprovação — não é executável até ser `published` - -### 4. Widget de notificação - -**[auto] Badge no header global + painel slide-in** - -- Badge no ícone de notificações existente no header (sem criar novo componente de header) -- Ao clicar: slide-in panel lateral mostrando lista de sugestões pendentes -- Cada sugestão mostra: nome sugerido, padrão detectado, frequência, confiança, body preview -- Ações inline: "Aceitar" → promove para skill publicada | "Rejeitar" → status `rejected` - -### 5. Aprovação — onde? - -**[auto] Tab "Sugestões" em `/skills` (página existente) — Dev Center completo na Phase 6** - -- Sem criar nova rota — adicionar tab na página `/skills` já existente -- Tab lista `skill_suggestions` com status `pending` -- Fluxo: aceitar → cria skill publicada a partir do DRAFT | rejeitar → arquiva sugestão -- Dev Center completo (Phase 6) herdará esse fluxo - ---- - -## Reusable Assets Identified - -- `shared/schema.ts` — `detectedPatterns`, `skillSuggestions` já definidos (Phase 1) -- `server/skills/engine.ts` — SkillEngine para criar DRAFT skills programaticamente -- `server/skills/routes.ts` — rota `/api/skills` existente, adicionar sub-rotas de sugestões -- `server/skills/versioning.ts` — SHA-256 audit logging (reusar padrão) -- `client/src/pages/BiWorkspace.tsx` — referência de como adicionar tabs a uma página existente -- `docker/litellm-config.yaml` — llama3.1:8b já configurado como Tier 2 - ---- - -## Scope Boundary - -**Incluído nesta fase:** -- PatternDetector backend (cron + análise de skill_executions) -- Geração de DRAFT via AI -- Widget de notificação + slide-in -- Tab "Sugestões" em /skills com aprovação/rejeição - -**Fora de escopo (phases futuras):** -- Dev Center completo (Phase 6) -- Detecção de padrões em outras fontes além de skill_executions -- Pattern sharing entre tenants - ---- - -## Plan Breakdown Suggested - -- **04-01:** PatternDetector service (backend) — cron, análise, gravação em detected_patterns + skill_suggestions + DRAFT creation via AI -- **04-02:** API routes + frontend widget (badge + slide-in) + tab "Sugestões" em /skills diff --git a/.planning/phases/05-automation-fabric/05-CONTEXT.md b/.planning/phases/05-automation-fabric/05-CONTEXT.md deleted file mode 100644 index 9e522a7..0000000 --- a/.planning/phases/05-automation-fabric/05-CONTEXT.md +++ /dev/null @@ -1,97 +0,0 @@ -# Phase 5 Context — Automation Fabric - -> Generated in --auto mode on 2026-03-26. All decisions auto-selected with recommended defaults. - -## Phase Goal - -Automações unificadas sob runtime único — 5 runtimes tipados substituindo a fragmentação entre XOS (`xos_automations`) e Central (`automations`), com `AutomationCenter.tsx` como visão unificada. - -## Prior Context Applied - -- **Stack Node.js/TypeScript:** runtimes ficam no servidor Express, sem novos microserviços Python -- **Backend-first:** API definida antes do frontend -- **DB imutável:** tabelas `automations` e `xos_automations` não são alteradas — migração virtual -- **Padrão de phases anteriores:** wrappers leves sobre código existente, sem reescritas - ---- - -## Decisions - -### 1. Estratégia de migração - -**[auto] Unificação virtual — zero migração de dados** - -- Tabelas `automations` e `xos_automations` permanecem intactas -- Nova camada `server/automation-fabric/` agrega os dois via API layer -- `AutomationCenter.tsx` consome endpoint unificado `/api/automation-fabric/list` -- Endpoint retorna rows de ambas as tabelas com campo `source: "central" | "xos"` -- Dados existentes: sem risco de perda, sem downtime, sem migration script - -### 2. Os 5 runtimes - -**[auto] Classes TypeScript leves — roteamento para serviços existentes** - -Implementados em `server/automation-fabric/runtimes/`: - -| Runtime | Responsabilidade | Delega para | -|---|---|---| -| `WorkflowEngine` | Executa ações sequenciais com condições | `AutomationService` existente | -| `RuleEngine` | Avalia condições JSONB e dispara ações | Lógica inline, sem dependência | -| `AgentExecutor` | Executa automações via agente Manus | `ManusService` | -| `ScheduleEngine` | Gerencia cron/interval | `scheduledTasks` + setInterval existente | -| `EventEngine` | Webhook/event triggers | Registra listeners no Express | - -- `AutomationFabricService` orquestra: dado tipo de trigger → escolhe runtime correto -- Trigger routing: `schedule` → ScheduleEngine, `event`/`webhook` → EventEngine, `agent` → AgentExecutor, default → WorkflowEngine - -### 3. Rota do AutomationCenter - -**[auto] Nova rota `/automations-center` — existentes intocadas** - -- `/automations` (Central) e `/xos/automations` (XOS) permanecem sem alteração -- Nova página `client/src/pages/AutomationCenter.tsx` em `/automations-center` -- Adicionada ao nav/router sem remover rotas existentes - -### 4. UI do AutomationCenter - -**[auto] Lista unificada com badge de fonte + filtros inline** - -- Lista flat com cards: nome, descrição, trigger type, última execução, status ativo/inativo -- Badge colorido: `"Central"` (azul) | `"XOS"` (roxo) -- Filtros: por fonte, por status (ativo/inativo), por trigger type -- Toggle inline enable/disable via PATCH ao respectivo endpoint original -- Execução manual via botão "Executar" → POST `/api/automation-fabric/{id}/run` -- Empty state informativo - ---- - -## Reusable Assets Identified - -- `server/automations/service.ts` — `AutomationService.runAutomation()` (reusar no WorkflowEngine) -- `server/automations/routes.ts` — padrão de rota com auth check -- `server/manus/service.ts` — `manusService` para AgentExecutor -- `shared/schema.ts` — `automations`, `xos_automations`, `automationLogs` já existentes -- `client/src/pages/Automations.tsx` — referência de UX/layout para a nova página -- `client/src/pages/XosAutomations.tsx` — referência de cards e filtros - ---- - -## Scope Boundary - -**Incluído nesta fase:** -- `server/automation-fabric/` — 5 runtimes + `AutomationFabricService` + rotas unificadas -- `GET /api/automation-fabric/list` — lista unificada (central + xos) -- `POST /api/automation-fabric/:id/run` — execução via fabric -- `AutomationCenter.tsx` — página `/automations-center` - -**Fora de escopo (phases futuras):** -- Editor visual de automações (Phase 6 / Dev Center) -- Migração física de dados para tabela unificada -- Novos tipos de trigger não existentes - ---- - -## Plan Breakdown Suggested - -- **05-01:** `server/automation-fabric/` — 5 runtimes + `AutomationFabricService` + routes (`/api/automation-fabric`) -- **05-02:** `AutomationCenter.tsx` — página unificada `/automations-center` com lista, filtros e execução inline diff --git a/.planning/phases/06-dev-center-completo/06-01-PLAN.md b/.planning/phases/06-dev-center-completo/06-01-PLAN.md deleted file mode 100644 index f71438e..0000000 --- a/.planning/phases/06-dev-center-completo/06-01-PLAN.md +++ /dev/null @@ -1,32 +0,0 @@ -# 06-01 PLAN — Schema + API Agent Defs - -## Tasks - -1. **Add `arcadia_agent_defs` table to `shared/schema.ts`** - - Fields: id, tenantId, userId, name, description, spec (jsonb), status, version, lastTaskId, createdAt, updatedAt - - Run migration if needed - -2. **Create `server/agent-defs/service.ts`** - - `createAgentDef()`, `getAgentDef()`, `listAgentDefs()`, `updateAgentDef()`, `deleteAgentDef()` - - `updateStatus()` helper for draft → assembling → ready → deployed - - `incrementVersion()` on deploy - -3. **Create `server/agent-defs/routes.ts`** - - GET `/api/agent-defs` (list by tenantId) - - POST `/api/agent-defs` (create) - - PATCH `/api/agent-defs/:id` (update spec/status) - - DELETE `/api/agent-defs/:id` - - POST `/api/agent-defs/:id/deploy` (status → deployed, version++) - - POST `/api/agent-defs/:id/run` (POST to blackboard task) - -4. **Register routes in `server/routes.ts`** - - Import and registerAgentDefRoutes() - -## Reuse -- DB functions from existing patterns -- Blackboard service for task creation (no modification) - -## Done Criteria -- API responds 200 on all endpoints -- Status transitions work: draft → assembling → ready → deployed -- `lastTaskId` links to blackboard_tasks diff --git a/.planning/phases/06-dev-center-completo/06-02-PLAN.md b/.planning/phases/06-dev-center-completo/06-02-PLAN.md deleted file mode 100644 index 746b49f..0000000 --- a/.planning/phases/06-dev-center-completo/06-02-PLAN.md +++ /dev/null @@ -1,34 +0,0 @@ -# 06-02 PLAN — Design + Assemble Tabs - -## Tasks - -1. **Extend `client/src/pages/DevCenter.tsx` — Design tab** - - Add "Design" tab to TabsList - - 3 mode buttons: Markdown Spec | Code Editor | Visual Flow - - Monaco Editor component (reuse existing from "Desenvolver" tab if possible) - - Save spec to `arcadia_agent_defs` on blur/button click - - Form: agent name, description, spec content - -2. **Extend `client/src/pages/DevCenter.tsx` — Assemble tab** - - List `arcadia_agent_defs` where status = draft - - "Montar" button per agent → POST `/api/blackboard/task` with spec as context - - Poll `/api/blackboard/task/:id` every 3s while assembling - - Show progress (task status) in real-time - - On complete: update agent status → ready, show generated artifact - -3. **Create `client/src/components/DesignStudio.tsx`** (if modularizing) - - Or inline in DevCenter tabs - -4. **Create `client/src/components/AssembleLine.tsx`** (if modularizing) - - Or inline in DevCenter tabs - -## Reuse -- Monaco Editor config from existing code -- Polling logic from existing task components -- Blackboard task fetch logic - -## Done Criteria -- Design tab allows editing agent spec in 3 modes -- Assemble tab shows draft agents and polls until complete -- Status updates in real-time -- Artifacts visible after assembly diff --git a/.planning/phases/06-dev-center-completo/06-03-PLAN.md b/.planning/phases/06-dev-center-completo/06-03-PLAN.md deleted file mode 100644 index 6904d42..0000000 --- a/.planning/phases/06-dev-center-completo/06-03-PLAN.md +++ /dev/null @@ -1,37 +0,0 @@ -# 06-03 PLAN — Deploy + Galeria Tabs - -## Tasks - -1. **Extend `client/src/pages/DevCenter.tsx` — Deploy tab** - - List `arcadia_agent_defs` where status = ready OR deployed - - "Deploy" button → PATCH `/api/agent-defs/:id/deploy` (status → deployed, version++) - - "Re-montar" button → PATCH status back to draft - - Expand row → show last blackboard_artifact details (JSON viewer) - - Version badge per agent - -2. **Extend `client/src/pages/DevCenter.tsx` — Galeria tab** - - Grid of cards: deployed agents only - - Card content: name, description, version, creator, status badge - - "Executar" button → POST `/api/agent-defs/:id/run` (new blackboard task) - - "Fork" button → POST create new agent with copied spec (name += " (Copy)") - - Filter: status dropdown, search by name - - Empty state message - -3. **Create `client/src/components/OrchestrateCenter.tsx`** (if modularizing) - - Or inline in DevCenter tabs - -4. **Create `client/src/components/AgentGallery.tsx`** (if modularizing) - - Or inline in DevCenter tabs - -## Reuse -- Card/grid layout from AutomationCenter or Skills -- Status badge from existing components -- Blackboard task execution logic - -## Done Criteria -- Deploy tab lists ready/deployed agents -- Deploy action increments version -- Re-montar reverts to draft -- Galeria shows deployed agents only -- Run/Fork actions work -- All filters functional diff --git a/.planning/phases/06-dev-center-completo/06-CONTEXT.md b/.planning/phases/06-dev-center-completo/06-CONTEXT.md deleted file mode 100644 index ed7df06..0000000 --- a/.planning/phases/06-dev-center-completo/06-CONTEXT.md +++ /dev/null @@ -1,131 +0,0 @@ -# Phase 6 Context — Dev Center Completo - -> Generated in --auto mode on 2026-03-26. All decisions auto-selected with recommended defaults. - -## Phase Goal - -Fábrica completa de agentes integrada ao DevCenter existente: Design → Assemble → Deploy, com galeria de agentes por tenant. - -## Prior Context Applied - -- **Stack Node.js/TypeScript + React:** sem novos microserviços -- **Backend-first:** tabela + API antes do frontend -- **Blackboard já existe:** `server/blackboard/` com ArchitectAgent, GeneratorAgent, ValidatorAgent, ExecutorAgent — reusar sem modificar -- **DevCenter.tsx já existe em `/dev-center`:** adicionar tabs, não criar nova rota -- **Schema modular:** nova tabela pode ir em `shared/schema.ts` (é a fase certa — tabela de agentes faz parte do core do sistema) -- **Auditoria imutável:** execuções e artefatos já logados via `blackboard_artifacts` - ---- - -## Decisions - -### 1. Onde vive a nova UI? - -**[auto] 4 novos tabs no DevCenter.tsx existente — sem nova rota** - -- Tabs adicionados ao `` existente em `/dev-center` -- Tabs novos: `design`, `assemble`, `deploy`, `galeria` -- Tabs existentes (Desenvolver, Status, Analisar Repos, Ferramentas, Sistema, Preview, Histórico) permanecem intocados -- Nenhuma nova rota no App.tsx, nenhum novo import lazy - -### 2. DesignStudio — modos do editor - -**[auto] 3 modos: Markdown Spec, Code Editor, Visual Flow** - -- **Markdown Spec** (padrão): textarea com Monaco em modo `markdown` — usuário descreve o agente em linguagem natural estruturada -- **Code Editor**: Monaco em modo `typescript` — para specs técnicas detalhadas ou código direto -- **Visual Flow**: lista de nós editáveis (JSON simples) — nome/tipo/conexões — NÃO um editor gráfico completo -- UML = descrito via texto em Markdown Spec (sem biblioteca de diagramas) -- Seletor de modo: 3 botões inline no topo do tab Design - -### 3. Tabela de definições de agentes - -**[auto] Nova tabela `arcadia_agent_defs` em `shared/schema.ts`** - -Campos: -- `id` (serial PK) -- `tenantId` (varchar, nullable) -- `userId` (varchar — criador) -- `name` (varchar — nome do agente) -- `description` (text) -- `spec` (jsonb — conteúdo do DesignStudio: `{ mode, content }`) -- `status` (varchar — `draft | assembling | ready | deployed`) -- `version` (integer, default 1) -- `lastTaskId` (integer — FK para blackboard_tasks, nullable) -- `createdAt`, `updatedAt` (timestamp) - -API: `/api/agent-defs` — CRUD padrão (GET list, POST create, PATCH update, DELETE) - -### 4. AssembleLine — fluxo de montagem - -**[auto] DesignStudio spec → POST /api/blackboard/task → GeneratorAgent → artefato linkado** - -- Tab "Assemble" lista `arcadia_agent_defs` com status `draft` -- Botão "Montar" por agente: POST `/api/blackboard/task` com spec como contexto - - `title`: `"Montar agente: ${name}"` - - `description`: conteúdo do spec - - `context`: `{ agentDefId, spec, source: "agent-factory" }` -- Atualiza `arcadia_agent_defs.status` → `assembling`, salva `lastTaskId` -- Progresso: polling de `/api/blackboard/task/:id` a cada 3s -- Ao completar: status → `ready`, artefato gerado visível no painel de detalhes -- Reusar completamente os agentes Blackboard existentes — zero modificação - -### 5. OrchestrateCenter — deploy e monitoramento - -**[auto] Lista de agent_defs com ações de deploy + viewer de artefatos** - -- Tab "Deploy": lista `arcadia_agent_defs` em status `ready` ou `deployed` -- Ação "Deploy": PATCH status → `deployed`, incrementa `version` -- Ação "Re-montar": volta para `draft`, decrementa version (permite iteração) -- Monitoramento: expandir linha → mostra último `blackboard_artifact` do `lastTaskId` -- Versionamento: campo `version` incrementado a cada novo deploy -- Sem infra externa — deploy = mudança de status no banco - -### 6. Galeria de agentes - -**[auto] Grid de cards por tenant — tab "Galeria"** - -- Tab "Galeria": grid de cards com `arcadia_agent_defs` onde `status = "deployed"` -- Cada card: nome, descrição, badge de status, número de versão, criador -- Ação "Executar": POST `/api/blackboard/task` com spec do agente → cria nova task de execução -- Ação "Fork": duplica o agente def como novo draft (copia spec, incrementa nome) -- Filtro por status (todos / somente deployed) e busca por nome -- Empty state: "Nenhum agente implantado — crie um na aba Design" - ---- - -## Reusable Assets Identified - -- `server/blackboard/routes.ts` — `POST /api/blackboard/task`, `GET /api/blackboard/task/:id`, `GET /api/blackboard/tasks` — reusar sem modificar -- `server/blackboard/service.ts` — `createMainTask()`, `getTaskWithDetails()` — reusar -- `shared/schema.ts` — `blackboardTasks`, `blackboardArtifacts` — leitura e join -- `client/src/pages/DevCenter.tsx` — estrutura de tabs existente — adicionar sem remover -- `client/src/pages/AutomationCenter.tsx` — referência de UX: lista com filtros + badges -- `client/src/pages/Skills.tsx` — referência de galeria com cards -- Monaco Editor já instalado (usado no DevCenter tab "Desenvolver") - ---- - -## Scope Boundary - -**Incluído nesta fase:** -- Tabela `arcadia_agent_defs` + migration + API CRUD `/api/agent-defs` -- Tab "Design" (DesignStudio: 3 modos + Monaco) -- Tab "Assemble" (lista de defs + botão Montar + progresso polling) -- Tab "Deploy" (OrchestrateCenter: lista ready/deployed + ações deploy/re-montar + viewer) -- Tab "Galeria" (grid por tenant + run + fork) -- Backend endpoint `POST /api/agent-defs/:id/deploy` e `POST /api/agent-defs/:id/run` - -**Fora de escopo (phases futuras):** -- Editor gráfico visual com React Flow ou similar -- Execução real do código gerado em sandbox (Phase 7) -- Integração com CI/CD ou containers reais -- Sharing de agentes entre tenants - ---- - -## Plan Breakdown Suggested - -- **06-01:** `shared/schema.ts` (tabela `arcadia_agent_defs`) + `server/agent-defs/routes.ts` (CRUD + `/deploy` + `/run`) + registro em `server/routes.ts` -- **06-02:** Tab "Design" (DesignStudio 3 modos) + Tab "Assemble" (lista + polling de progresso) no DevCenter.tsx -- **06-03:** Tab "Deploy" (OrchestrateCenter) + Tab "Galeria" (grid + run/fork) no DevCenter.tsx diff --git a/.planning/phases/07-skill-fabric-expandido-compiladores-sandbox-executor-visual-code-markdown-editors-com-validation-pipeline/.gitkeep b/.planning/phases/07-skill-fabric-expandido-compiladores-sandbox-executor-visual-code-markdown-editors-com-validation-pipeline/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/.planning/quick/260326-kmz-implementar-skill-fabric-gerador-e-gesto/260326-kmz-PLAN.md b/.planning/quick/260326-kmz-implementar-skill-fabric-gerador-e-gesto/260326-kmz-PLAN.md deleted file mode 100644 index bd150ff..0000000 --- a/.planning/quick/260326-kmz-implementar-skill-fabric-gerador-e-gesto/260326-kmz-PLAN.md +++ /dev/null @@ -1,71 +0,0 @@ -# Quick Task 260326-kmz: Implementar Skill Fabric - -**Description:** Implementar Skill Fabric — gerador e gestor de skills da Arcádia Suite -**Date:** 2026-03-26 -**Mode:** quick - ---- - -## Task 1: Backend — Skill Fabric Module - -**Files:** -- `server/modules/skill-fabric/src/types/index.ts` -- `server/modules/skill-fabric/src/core/skill/Skill.entity.ts` -- `server/modules/skill-fabric/src/core/compiler/VisualCompiler.ts` -- `server/modules/skill-fabric/src/core/compiler/CodeCompiler.ts` -- `server/modules/skill-fabric/src/core/compiler/MarkdownCompiler.ts` -- `server/modules/skill-fabric/src/core/validator/ValidationPipeline.ts` -- `server/modules/skill-fabric/src/core/executor/SkillExecutor.ts` -- `server/modules/skill-fabric/src/core/executor/Sandbox.ts` -- `server/modules/skill-fabric/src/core/lifecycle/LifecycleManager.ts` -- `server/modules/skill-fabric/src/api/routes/skills.routes.ts` -- `server/modules/skill-fabric/src/api/controllers/skills.controller.ts` -- `server/modules/skill-fabric/index.ts` - -**Action:** Create the full backend Skill Fabric module with types, entity, compilers, validator pipeline, executor/sandbox, lifecycle manager, and API routes. The project uses TypeScript + Express + Drizzle ORM. Reuse existing `db` and `skills` schema from `../../shared/schema`. No new DB migration needed — extend existing skills table logic. - -**Context:** -- Existing `server/skills/routes.ts` has basic CRUD. The new module adds compilation, validation, execution, versioning, lifecycle. -- DB import: `import { db } from "@/db"` or `import { db } from "../../../db"` — check what works -- Existing schema: `skills`, `skillExecutions` from `../../shared/schema` -- Do NOT use vm2 (needs install) — use Node.js built-in `vm` module for sandbox -- Do NOT use ReactFlow/Monaco yet (frontend task) — backend only here - -**Done:** Files created, module compiles without errors - ---- - -## Task 2: Frontend — Skill Fabric UI - -**Files:** -- `client/src/modules/skill-fabric/index.ts` -- `client/src/modules/skill-fabric/types.ts` -- `client/src/modules/skill-fabric/api.ts` -- `client/src/modules/skill-fabric/code-ide/components/SkillCodeEditor.tsx` -- `client/src/modules/skill-fabric/markdown-studio/components/MarkdownEditor.tsx` -- `client/src/modules/skill-fabric/shared/components/SkillToolbar.tsx` -- `client/src/modules/skill-fabric/shared/components/VersionSelector.tsx` -- `client/src/modules/skill-fabric/shared/components/ValidationPanel.tsx` -- `client/src/pages/SkillFabricPage.tsx` - -**Action:** Create frontend Skill Fabric module. Use textarea-based code editor (Monaco not installed — don't add it). Use Tailwind CSS + shadcn/ui components matching the existing project style. Create a SkillFabricPage that lists skills, allows creating/editing (code + markdown modes), compiling, validating, and executing. Wire to the backend API routes from Task 1. - -**Context:** -- Check `client/src/components/` for existing UI patterns (shadcn components available) -- Check `client/src/App.tsx` to see how routes are registered — add the new page there -- The visual canvas (ReactFlow) is a stretch goal — skip it, implement code + markdown modes only -- API base: `/api/skills` (existing) + `/api/skill-fabric` (new from Task 1) - -**Done:** SkillFabricPage renders, skills can be listed and created - ---- - -## Task 3: Register Routes & Integration - -**Files:** -- `server/modules/loader.ts` -- `client/src/App.tsx` (or router file) - -**Action:** Register the new skill-fabric backend routes in `server/modules/loader.ts`. Add the SkillFabricPage route in the frontend router. Verify existing skills route still works. - -**Done:** `/api/skill-fabric/*` routes registered, frontend page accessible diff --git a/.planning/reports/20260325-session-report.md b/.planning/reports/20260325-session-report.md deleted file mode 100644 index 5d04368..0000000 --- a/.planning/reports/20260325-session-report.md +++ /dev/null @@ -1,91 +0,0 @@ -# GSD Session Report - -**Generated:** 2026-03-25 09:50 BRT -**Project:** Arcádia Suite — `arcadiasuite` (branch `Servidor`) -**Milestone:** Arcádia Agentic Suite — 6 Fases (~12 semanas) - ---- - -## Session Summary - -**Período:** 2026-03-24 11:30 → 2026-03-25 09:50 (sessões consecutivas) -**Fase atual:** Fase 2 — Skills Engine -**Commits nesta sessão:** 7 -**Arquivos alterados:** 29 (+1.875 / -106 linhas) - ---- - -## Work Performed - -### Fase 1 — Fundação (CONCLUÍDA) - -- `1c6c386` — SkillEngine POO + ReferenceParser + ReferenceResolver + schema (`arcadia_skills`, `skill_executions`) -- `66d8dfb` — MiroFlow e OpenClaw adicionados como git submodules -- `c9a0563` — Neo4j no Docker Compose (profile `kg`), Skills.tsx UI, melhorias Manus/chat/Agent - -### Fase 2 — Skills Engine (EM ANDAMENTO) - -- `3c61acf` — XOS: forms de cadastro restaurados (Novo Contato, Negócio, Atividade) -- `9bfc888` — Migration: suporte a upload RAR, SQL, SQL.GZ -- `194a8dc` — Rota `/skills` no App.tsx + autocomplete de referências `/` no Monaco -- `4057821` — Skill Marketplace (Biblioteca): `GET /api/skills/marketplace` + `POST /import` + UI grid - -### Key Outcomes - -- **SkillEngine** com herança POO (`extends`), composição via referências `/`, audit hash SHA-256 -- **API REST** completa: CRUD + execute + histórico em `/api/skills` -- **Editor Monaco** com 3 tabs (Geral / Body / Params) + autocomplete de 9 prefixos de referências -- **Skill Marketplace** (Biblioteca): discovery de skills `system`, importação para `tenant` com clonagem + `extends` para origem -- **Neo4j** disponível via `docker compose --profile kg up` -- **Submodules** MiroFlow e OpenClaw presentes em `server/modules/` - ---- - -## Files Changed (resumo por área) - -| Área | Arquivos | Linhas | -|------|----------|--------| -| Skills (server) | `engine.ts`, `routes.ts`, `reference-parser.ts` | +400 | -| Skills (client) | `Skills.tsx` | +570 | -| Schema | `shared/schema.ts` | +96 | -| Infra | `docker-compose.yml`, `docker/litellm-config.yaml` | +35 | -| Manus/Chat | `service.ts`, `routes.ts`, `prompt.ts`, `routes.ts` | +350 | -| XOS | `XosCentral.tsx` | +200 | -| App | `App.tsx` | +2 | -| Outros | Agent, ProcessCompass, bi, compass, ide, etc. | +222 | - ---- - -## Blockers & Open Items - -**Fase 2 — pendente:** -- [ ] Sistema de versionamento de skills (Git-like) - -**Pendências gerais (produção):** -- [ ] Commitar RLS Superset → main -- [ ] SOE.tsx stub → importar versão completa do Replit -- [ ] Seed de regras padrão em `soe_regras` -- [ ] Dashboards base no Superset (DRE, Fluxo de Caixa, Fiscal, RH) - -**Próxima fase:** -- Fase 3 — MiroFlow embutido + MiroFlowBridge para Superset - ---- - -## Estimated Resource Usage - -| Métrica | Estimativa | -|---------|------------| -| Commits | 7 | -| Arquivos alterados | 29 | -| Linhas adicionadas | ~1.875 | -| Linhas removidas | ~106 | -| Ciclos plan/execute | ~4 (uma por feature principal) | -| Subagents spawned | 0 | - -> **Nota:** contagens de tokens e custo requerem instrumentação via API. -> Estas métricas refletem apenas a atividade observável da sessão. - ---- - -*Gerado por `/gsd:session-report`* diff --git a/MAPA_TENANTS_ARCADIA (copy).md b/MAPA_TENANTS_ARCADIA (copy).md deleted file mode 100644 index 17b20a4..0000000 --- a/MAPA_TENANTS_ARCADIA (copy).md +++ /dev/null @@ -1,812 +0,0 @@ -# Arcádia Tenants — Mapa Completo da Gestão Multi-Tenant - -> Mapa da arquitetura multi-tenant da Arcádia Suite: hierarquia -> Master/Parceiro/Cliente, sistema de planos, ativação de módulos, -> empresas (Matriz/Filiais), comissões de parceiros, controle de acesso, -> e middleware de isolamento. -> Atualizado em: Março 2026 - ---- - -## 1. Visão Geral - -A Arcádia Suite opera em modelo **multi-tenant hierárquico** com três níveis. Cada tenant possui um plano que define quais módulos da plataforma estão habilitados, e pode conter múltiplas empresas (CNPJ) para operações fiscais. - -``` -┌─────────────────────────────────────────────────────────────────────┐ -│ HIERARQUIA DE TENANTS │ -│ │ -│ ┌──────────────┐ │ -│ │ MASTER │ ← Operador da plataforma │ -│ │ │ ← Vê tudo, controla tudo │ -│ │ tenantType: │ ← Pode criar parceiros │ -│ │ "master" │ ← Pode excluir tenants │ -│ └──────┬───────┘ │ -│ │ │ -│ ┌────────────┼────────────┐ │ -│ ▼ ▼ ▼ │ -│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ -│ │ PARCEIRO A │ │ PARCEIRO B │ │ PARCEIRO C │ │ -│ │ │ │ │ │ │ │ -│ │ tenantType: │ │ Consultorias │ │ Integradores │ │ -│ │ "partner" │ │ Revendas │ │ Franquias │ │ -│ │ │ │ │ │ │ │ -│ │ partnerCode: │ │ comissão: % │ │ plano: │ │ -│ │ "PARC-001" │ │ sobre clientes│ │partner_pro │ │ -│ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │ -│ │ │ │ │ -│ ┌────┴────┐ ┌───┴───┐ ┌───┴───┐ │ -│ ▼ ▼ ▼ ▼ ▼ ▼ │ -│ ┌────────┐┌────────┐┌────────┐┌────────┐┌────────┐┌────────┐ │ -│ │Cliente1││Cliente2││Cliente3││Cliente4││Cliente5││Cliente6│ │ -│ │ ││ ││ ││ ││ ││ │ │ -│ │tenant ││tenant ││tenant ││tenant ││tenant ││tenant │ │ -│ │Type: ││Type: ││Type: ││Type: ││Type: ││Type: │ │ -│ │"client"││"client"││"client"││"client"││"client"││"client"│ │ -│ │ ││ ││ ││ ││ ││ │ │ -│ │parent: ││parent: ││parent: ││parent: ││parent: ││parent: │ │ -│ │Parc.A ││Parc.A ││Parc.B ││Parc.B ││Parc.C ││Parc.C │ │ -│ │ ││ ││ ││ ││ ││ │ │ -│ │Plano: ││Plano: ││Plano: ││Plano: ││Plano: ││Plano: │ │ -│ │starter ││pro ││free ││enterpr.││starter ││pro │ │ -│ └────────┘└────────┘└────────┘└────────┘└────────┘└────────┘ │ -└─────────────────────────────────────────────────────────────────────┘ -``` - -### Visibilidade por tipo: - -| Tipo | Vê | Cria | Exclui | -|------|-----|------|--------| -| **Master** | Todos os tenants | Parceiros e Clientes | Qualquer (exceto master) | -| **Partner** | Seu tenant + seus clientes | Apenas clientes vinculados | Nenhum | -| **Client** | Apenas seu próprio tenant | Nenhum | Nenhum | - ---- - -## 2. Banco de Dados — Tabelas de Tenant - -### 2.1 — tenants (Tabela Principal) - -``` -┌──────────────────────────────────────────────────────────────────┐ -│ tenants │ -│ Tabela: "tenants" — shared/schema.ts:849 │ -│ │ -│ ┌─────────── Identificação ──────────────────┐ │ -│ │ id serial PK │ │ -│ │ name text NOT NULL │ │ -│ │ slug text UNIQUE │ │ -│ │ email text │ │ -│ │ phone text │ │ -│ │ logoUrl text │ │ -│ └─────────────────────────────────────────────┘ │ -│ │ -│ ┌─────────── Hierarquia ─────────────────────┐ │ -│ │ tenantType "master" | "partner" | │ │ -│ │ "client" │ │ -│ │ parentTenantId integer (self-ref FK) │ │ -│ │ partnerCode text (código único parceiro) │ │ -│ │ commissionRate numeric(5,2) (% comissão) │ │ -│ └─────────────────────────────────────────────┘ │ -│ │ -│ ┌─────────── Plano e Limites ────────────────┐ │ -│ │ plan "free" | "starter" | "pro" │ │ -│ │ | "enterprise" | │ │ -│ │ "partner_starter" | │ │ -│ │ "partner_pro" │ │ -│ │ status "active" | "trial" | │ │ -│ │ "suspended" | "cancelled" │ │ -│ │ maxUsers integer (default 5) │ │ -│ │ maxStorageMb integer (default 1000) │ │ -│ │ features JSONB → TenantFeatures │ ← Módulos │ -│ └─────────────────────────────────────────────┘ │ -│ │ -│ ┌─────────── Billing ────────────────────────┐ │ -│ │ billingEmail text │ │ -│ │ trialEndsAt timestamp │ │ -│ └─────────────────────────────────────────────┘ │ -│ │ -│ ┌─────────── Dados Empresariais ─────────────┐ │ -│ │ cnpj text │ │ -│ │ tradeName text │ │ -│ │ address text │ │ -│ │ city, state text │ │ -│ │ segment text │ │ -│ │ notes, source text │ │ -│ │ commercialContact / commercialPhone │ │ -│ └─────────────────────────────────────────────┘ │ -│ │ -│ ┌─────────── Metadata ───────────────────────┐ │ -│ │ settings text (JSON config) │ │ -│ │ createdAt timestamp │ │ -│ │ updatedAt timestamp │ │ -│ └─────────────────────────────────────────────┘ │ -└──────────────────────────────────────────────────────────────────┘ -``` - -### 2.2 — TenantFeatures (JSONB — Sistema de Módulos) - -O campo `features` na tabela `tenants` é um JSONB que controla **quais módulos da Arcádia estão habilitados** para cada tenant. O tipo é definido em `shared/schema.ts:821` e espelhado no frontend em `client/src/hooks/use-tenant-features.ts:3`. - -``` -┌──────────────────────────────────────────────────────────────────┐ -│ TenantFeatures (JSONB) │ -│ │ -│ ┌─────────── Módulos Booleanos ──────────────┐ │ -│ │ │ │ -│ │ ide → IDE integrada │ │ -│ │ whatsapp → WhatsApp multi-sessão │ │ -│ │ crm → CRM completo │ │ -│ │ erp → SOE/ERP │ │ -│ │ bi → Business Intelligence │ │ -│ │ manus → IA Manus (GPT-4o) │ │ -│ │ centralApis → APIs centrais │ │ -│ │ centralApisManage → Gerenciar APIs │ │ -│ │ comunidades → Chat interno │ │ -│ │ biblioteca → Biblioteca de conhecimento │ │ -│ │ bibliotecaPublish → Publicar na biblioteca │ │ -│ │ suporteN3 → Suporte nível 3 │ │ -│ │ retail → Módulo Varejo │ │ -│ │ plus → ERP Plus (Laravel) │ │ -│ │ fisco → Motor Fiscal │ │ -│ │ cockpit → Cockpit executivo │ │ -│ │ compass → Process Compass │ │ -│ │ production → Módulo Produção │ │ -│ │ support → Módulo Suporte │ │ -│ │ xosCrm → XOS CRM (Kanban) │ │ -│ │ │ │ -│ └─────────────────────────────────────────────┘ │ -│ │ -│ ┌─────────── Configurações Numéricas ────────┐ │ -│ │ │ │ -│ │ whatsappSessions → Nº sessões WA (0-N) │ │ -│ │ maxChannels → Nº canais permitidos │ │ -│ │ │ │ -│ └─────────────────────────────────────────────┘ │ -│ │ -│ ┌─────────── Configurações de Texto ─────────┐ │ -│ │ │ │ -│ │ ideMode → "none" | "no-code" | │ │ -│ │ "low-code" | "pro-code" │ │ -│ │ manusTools[] → Lista de tools habilitadas │ │ -│ │ │ │ -│ └─────────────────────────────────────────────┘ │ -└──────────────────────────────────────────────────────────────────┘ -``` - -### 2.3 — tenant_empresas (Matriz/Filiais) - -Cada tenant pode ter **múltiplas empresas** (CNPJs) cadastradas — essencial para operações fiscais (NF-e/NFC-e) por filial. - -``` -┌──────────────────────────────────────────────────────────────────┐ -│ tenant_empresas │ -│ Tabela: "tenant_empresas" — shared/schema.ts:889 │ -│ │ -│ ┌─────────── Identificação ──────────────────┐ │ -│ │ id serial PK │ │ -│ │ tenantId FK → tenants.id (CASCADE) │ │ -│ │ razaoSocial text NOT NULL │ │ -│ │ nomeFantasia text │ │ -│ │ cnpj text NOT NULL │ │ -│ │ ie text (inscrição estadual) │ │ -│ │ im text (inscrição municipal) │ │ -│ │ email, phone text │ │ -│ │ tipo "matriz" | "filial" │ │ -│ │ status "active" | "inactive" │ │ -│ └─────────────────────────────────────────────┘ │ -│ │ -│ ┌─────────── Endereço ───────────────────────┐ │ -│ │ cep, logradouro, numero, complemento, │ │ -│ │ bairro, cidade, uf, codigoIbge │ │ -│ └─────────────────────────────────────────────┘ │ -│ │ -│ ┌─────────── Fiscal ─────────────────────────┐ │ -│ │ regimeTributario "simples" | "presumido" │ │ -│ │ | "real" │ │ -│ │ certificadoDigitalId FK certificado │ │ -│ │ ambienteFiscal "producao" | "homologacao" │ │ -│ │ serieNfe integer (default 1) │ │ -│ │ serieNfce integer (default 1) │ │ -│ │ plusEmpresaId integer (link ERP Plus) │ │ -│ └─────────────────────────────────────────────┘ │ -│ │ -│ ┌─────────── Metadata ───────────────────────┐ │ -│ │ createdAt, updatedAt timestamp │ │ -│ └─────────────────────────────────────────────┘ │ -└──────────────────────────────────────────────────────────────────┘ -``` - -**Uso típico:** - -``` -Tenant "Empresa ABC" (id: 5) -├── Empresa Matriz: "ABC Comércio LTDA" (CNPJ: 12.345.678/0001-00) -│ regime: simples, ambiente: producao, série NF-e: 1 -├── Filial SP: "ABC Comércio SP" (CNPJ: 12.345.678/0002-81) -│ regime: simples, ambiente: producao, série NF-e: 2 -└── Filial RJ: "ABC Comércio RJ" (CNPJ: 12.345.678/0003-62) - regime: simples, ambiente: homologacao, série NF-e: 1 -``` - -### 2.4 — tenant_users (Membership) - -``` -┌──────────────────────────────────────────────────────────────────┐ -│ tenant_users │ -│ Tabela: "tenant_users" — shared/schema.ts:923 │ -│ │ -│ id serial PK │ -│ tenantId FK → tenants.id (CASCADE) │ -│ userId FK → users.id (CASCADE) │ -│ role "owner" | "admin" | "member" │ -│ isOwner "true" | "false" │ -│ createdAt timestamp │ -│ │ -│ → Link N:N entre users e tenants │ -│ → Um usuário pode pertencer a múltiplos tenants │ -│ → Cada tenant tem um owner + admins + members │ -└──────────────────────────────────────────────────────────────────┘ -``` - -### 2.5 — tenant_plans (Planos Disponíveis) - -``` -┌──────────────────────────────────────────────────────────────────┐ -│ tenant_plans │ -│ Tabela: "tenant_plans" — shared/schema.ts:933 │ -│ │ -│ id serial PK │ -│ code text UNIQUE ("free", "starter", "pro", │ -│ "enterprise", "partner_starter", "partner_pro") │ -│ name text NOT NULL │ -│ description text │ -│ tenantType "master" | "partner" | "client" │ -│ maxUsers integer (default 5) │ -│ maxStorageMb integer (default 1000) │ -│ features JSONB → TenantFeatures │ -│ monthlyPrice integer (centavos) │ -│ yearlyPrice integer (centavos) │ -│ trialDays integer (default 14) │ -│ isActive "true" | "false" │ -│ sortOrder integer │ -│ createdAt timestamp │ -└──────────────────────────────────────────────────────────────────┘ -``` - -### 2.6 — partner_clients (Relacionamento Parceiro↔Cliente) - -``` -┌──────────────────────────────────────────────────────────────────┐ -│ partner_clients │ -│ Tabela: "partner_clients" — shared/schema.ts:951 │ -│ │ -│ id serial PK │ -│ partnerId FK → tenants.id (CASCADE) │ -│ clientId FK → tenants.id (CASCADE) │ -│ commissionRate numeric(5,2) — Override do rate do parceiro │ -│ status "active" | "suspended" | "ended" │ -│ notes text │ -│ startedAt timestamp │ -│ endedAt timestamp │ -└──────────────────────────────────────────────────────────────────┘ -``` - -### 2.7 — partner_commissions (Comissões dos Parceiros) - -``` -┌──────────────────────────────────────────────────────────────────┐ -│ partner_commissions │ -│ Tabela: "partner_commissions" — shared/schema.ts:963 │ -│ │ -│ id serial PK │ -│ partnerId FK → tenants.id (CASCADE) │ -│ clientId FK → tenants.id (CASCADE) │ -│ referenceMonth text ("2026-01", "2026-02", ...) │ -│ clientPlanCode text (código do plano do cliente) │ -│ clientPlanValue integer (valor do plano em centavos) │ -│ commissionRate numeric(5,2) NOT NULL │ -│ commissionValue integer NOT NULL (valor em centavos) │ -│ status "pending" | "approved" | "paid" | "cancelled" │ -│ approvedAt timestamp │ -│ paidAt timestamp │ -│ paymentReference text │ -│ createdAt timestamp │ -│ │ -│ Fluxo: pending → approved → paid │ -│ │ -│ Exemplo: │ -│ Parceiro A tem Cliente X no plano "pro" (R$ 299/mês) │ -│ commissionRate: 20% │ -│ commissionValue: 5980 centavos (R$ 59,80) │ -└──────────────────────────────────────────────────────────────────┘ -``` - ---- - -## 3. Planos Pré-definidos (Seed) - -A rota `POST /api/admin/plans/seed` cria os 6 planos padrão: - -``` -┌─────────────────────────────────────────────────────────────────────┐ -│ PLANOS PARA CLIENTES │ -├────────────┬──────────┬──────────┬──────────────────────────────────┤ -│ Plano │ Preço/mês│ Usuários │ Módulos │ -├────────────┼──────────┼──────────┼──────────────────────────────────┤ -│ Gratuito │ R$ 0 │ 2 │ erp, crm │ -│ (free) │ │ │ │ -├────────────┼──────────┼──────────┼──────────────────────────────────┤ -│ Starter │ R$ 99 │ 5 │ erp, crm, bi, fisco, │ -│ │ │ │ whatsapp, compass │ -├────────────┼──────────┼──────────┼──────────────────────────────────┤ -│ Pro │ R$ 299 │ 15 │ erp, crm, bi, fisco, retail, │ -│ │ │ │ plus, whatsapp, manus, cockpit, │ -│ │ │ │ compass, support, biblioteca │ -├────────────┼──────────┼──────────┼──────────────────────────────────┤ -│ Enterprise │ R$ 999 │ 100 │ TODOS os módulos │ -│ │ │ 50GB │ (erp, crm, bi, fisco, retail, │ -│ │ │ │ plus, whatsapp, manus, ide, │ -│ │ │ │ cockpit, compass, production, │ -│ │ │ │ support, xosCrm, centralApis, │ -│ │ │ │ comunidades, biblioteca) │ -└────────────┴──────────┴──────────┴──────────────────────────────────┘ - -┌─────────────────────────────────────────────────────────────────────┐ -│ PLANOS PARA PARCEIROS │ -├──────────────────┬──────────┬──────────┬────────────────────────────┤ -│ Plano │ Preço/mês│ Usuários │ Módulos │ -├──────────────────┼──────────┼──────────┼────────────────────────────┤ -│ Parceiro Starter │ R$ 199 │ 10 │ erp, crm, bi, fisco, │ -│ │ │ │ retail, whatsapp, compass, │ -│ │ │ │ support │ -├──────────────────┼──────────┼──────────┼────────────────────────────┤ -│ Parceiro Pro │ R$ 499 │ 50 │ TODOS os módulos │ -│ │ │ 25GB │ (igual Enterprise) │ -└──────────────────┴──────────┴──────────┴────────────────────────────┘ -``` - ---- - -## 4. Sistema de Papéis (Roles) - -A Arcádia opera com **dois níveis de papéis** que se complementam: - -``` -┌─────────────────────────────────────────────────────────────────────┐ -│ SISTEMA DUPLO DE ROLES │ -│ │ -│ ┌─────────── Papel do Sistema (users.role) ──────────────────┐ │ -│ │ │ │ -│ │ "master" → Superadmin, acesso total, bypass de tenant │ │ -│ │ "admin" → Administrador, acessa /api/admin/* │ │ -│ │ "user" → Usuário padrão, sem acesso admin │ │ -│ │ │ │ -│ │ Verificado no middleware global de admin: │ │ -│ │ if (role !== "admin" && role !== "master") → 403 │ │ -│ └─────────────────────────────────────────────────────────────┘ │ -│ │ -│ ┌─────────── Papel no Tenant (tenant_users.role) ────────────┐ │ -│ │ │ │ -│ │ "owner" → Dono do tenant, criador, full control │ │ -│ │ "admin" → Administrador do tenant │ │ -│ │ "member" → Membro comum, acesso operacional │ │ -│ │ │ │ -│ │ Usado para scoping de dados e permissões intra-tenant │ │ -│ └─────────────────────────────────────────────────────────────┘ │ -│ │ -│ Combinação no login (getEnrichedUser): │ -│ user.role + user.tenantId + user.tenantType + user.tenantRole │ -└─────────────────────────────────────────────────────────────────────┘ -``` - ---- - -## 5. Controle de Acesso — Helpers - -O backend implementa dois helpers essenciais em `server/admin/routes.ts`: - -``` -┌─────────────────────────────────────────────────────────────────────┐ -│ getAllowedTenantIds(user) │ -│ │ -│ Retorna os IDs de tenants que o usuário pode acessar: │ -│ │ -│ • master → null (acesso total, sem filtro) │ -│ • partner → [seu tenantId, ...clientIds vinculados] │ -│ • client → [apenas seu tenantId] │ -│ │ -│ Usado em: GET /tenants, GET /partner-clients, GET /commissions, │ -│ GET /empresas, GET /tenants/hierarchy │ -└─────────────────────────────────────────────────────────────────────┘ - -┌─────────────────────────────────────────────────────────────────────┐ -│ canAccessTenant(user, tenantId) │ -│ │ -│ Verifica se o usuário pode operar sobre um tenant específico: │ -│ │ -│ • master → true (sempre) │ -│ • partner → true se tenantId ∈ getAllowedTenantIds() │ -│ • client → true apenas se tenantId === user.tenantId │ -│ │ -│ Usado em: PATCH /tenants/:id, DELETE /empresas/:id, │ -│ POST /empresas, etc. │ -└─────────────────────────────────────────────────────────────────────┘ -``` - ---- - -## 6. Middleware de Módulos (requireModule) - -O middleware `requireModule` em `server/retail/routes.ts:25` bloqueia endpoints quando um módulo não está ativo para o tenant: - -``` -┌─────────────────────────────────────────────────────────────────────┐ -│ requireModule(moduleKey: keyof TenantFeatures) │ -│ │ -│ Fluxo: │ -│ 1. Identifica tenantId do usuário logado │ -│ 2. Busca tenant no banco │ -│ 3. Verifica features[moduleKey] === true │ -│ 4. Se false → 403 com mensagem: │ -│ { │ -│ error: "Módulo 'X' não está ativo para este tenant", │ -│ moduleKey: "plus", │ -│ action: "Ative o módulo em Admin → Módulos" │ -│ } │ -│ │ -│ Exemplo de uso: │ -│ router.post("/plus/sync/customers", │ -│ requireModule("plus"), ← Bloqueia se Plus não está ativo │ -│ async (req, res) => { ... } │ -│ ); │ -└─────────────────────────────────────────────────────────────────────┘ -``` - ---- - -## 7. Hook Frontend (useTenantFeatures) - -O hook `useTenantFeatures()` em `client/src/hooks/use-tenant-features.ts` fornece acesso às features do tenant no frontend: - -``` -┌─────────────────────────────────────────────────────────────────────┐ -│ useTenantFeatures() │ -│ │ -│ Fonte: GET /api/soe/tenant/modules │ -│ Cache: 60 segundos (staleTime: 60000) │ -│ │ -│ Retorna: │ -│ { │ -│ features: TenantFeatures, ← Objeto completo de features │ -│ isLoading: boolean, │ -│ plan: string, ← Código do plano atual │ -│ isEnabled: (key) => bool, ← Verificação rápida │ -│ } │ -│ │ -│ Defaults (quando não logado / sem tenant): │ -│ ide: true, crm: true, erp: true, manus: true, compass: true │ -│ Todos os demais: false │ -│ │ -│ Uso no componente: │ -│ const { isEnabled } = useTenantFeatures(); │ -│ if (isEnabled("bi")) { /* mostra menu BI */ } │ -│ if (isEnabled("retail")) { /* mostra módulo varejo */ } │ -└─────────────────────────────────────────────────────────────────────┘ -``` - ---- - -## 8. Interface de Administração - -### 8.1 — Admin.tsx (Página Principal) - -``` -┌─────────────────────────────────────────────────────────────────────┐ -│ Admin.tsx — client/src/pages/Admin.tsx (2.635 linhas) │ -│ Rota: /admin │ -│ │ -│ 6 Abas: │ -│ ┌─────────────┬──────────┬────────────┬───────────┬──────────────┐ │ -│ │ Conexões │ Tarefas │ Knowledge │ Bibliotecas│ Módulos │ │ -│ │ │ │ │ │ │ │ -│ │ WhatsApp │ Dev │ Knowledge │ Conteúdo │ Ativação │ │ -│ │ ERPNext │ Center │ Graph │ Docs │ por tenant │ │ -│ │ APIs │ Pipeline │ Q&A │ Templates │ Toggle on/ │ │ -│ │ │ │ │ │ off módulos │ │ -│ └─────────────┴──────────┴────────────┴───────────┴──────────────┘ │ -│ ┌─────────────┐ │ -│ │Casa de │ │ -│ │Máquinas │ │ -│ │ │ │ -│ │ Status dos │ │ -│ │ motores │ │ -│ │ (:8002-8006)│ │ -│ └─────────────┘ │ -│ │ -│ Aba "Módulos" renderiza: │ -└─────────────────────────────────────────────────────────────────────┘ -``` - -### 8.2 — MultiTenantSection (Gestão Completa) - -``` -┌─────────────────────────────────────────────────────────────────────┐ -│ MultiTenantSection.tsx (1.486 linhas) │ -│ client/src/components/MultiTenantSection.tsx │ -│ │ -│ 4 Abas internas: │ -│ │ -│ ┌─ Tenants ──────────────────────────────────────────────────┐ │ -│ │ │ │ -│ │ Lista de tenants com: │ │ -│ │ • Nome, tipo (Master/Parceiro/Cliente) │ │ -│ │ • Plano atual e status │ │ -│ │ • Nº de filhos (childCount) │ │ -│ │ • Tenant pai (parentTenant) │ │ -│ │ • Ações: Editar, Ativar/Desativar módulos │ │ -│ │ │ │ -│ │ Formulário de criação: │ │ -│ │ • Nome, email, phone │ │ -│ │ • Tipo (master/partner/client) │ │ -│ │ • Plano (seleciona do tenant_plans) │ │ -│ │ • Tenant pai (para hierarquia) │ │ -│ │ • Features auto-preenchidas pelo plano selecionado │ │ -│ │ • Toggle individual de cada módulo │ │ -│ │ │ │ -│ └─────────────────────────────────────────────────────────────┘ │ -│ │ -│ ┌─ Planos ───────────────────────────────────────────────────┐ │ -│ │ │ │ -│ │ CRUD de planos com: │ │ -│ │ • Código, nome, descrição │ │ -│ │ • Tipo de tenant (client/partner) │ │ -│ │ • Preço mensal e anual (centavos) │ │ -│ │ • Max usuários e storage │ │ -│ │ • Features (toggle de cada módulo) │ │ -│ │ • Botão "Seed" para criar planos padrão │ │ -│ │ • Botão "Propagar" para aplicar features do plano │ │ -│ │ a todos os tenants que usam esse plano │ │ -│ │ │ │ -│ └─────────────────────────────────────────────────────────────┘ │ -│ │ -│ ┌─ Comissões ────────────────────────────────────────────────┐ │ -│ │ │ │ -│ │ Lista de comissões de parceiros: │ │ -│ │ • Parceiro, Cliente, Mês referência │ │ -│ │ • Valor do plano, taxa de comissão, valor da comissão │ │ -│ │ • Status (pending → approved → paid) │ │ -│ │ • Ações: Aprovar, Marcar como paga │ │ -│ │ │ │ -│ └─────────────────────────────────────────────────────────────┘ │ -│ │ -│ ┌─ Empresas ─────────────────────────────────────────────────┐ │ -│ │ │ │ -│ │ EmpresasSubSection: │ │ -│ │ • Lista de empresas (Matriz/Filiais) por tenant │ │ -│ │ • CNPJ, Razão Social, Nome Fantasia │ │ -│ │ • IE, IM, Regime Tributário │ │ -│ │ • Endereço completo (CEP, logradouro, cidade, UF) │ │ -│ │ • Config Fiscal (ambiente, série NF-e, série NFC-e) │ │ -│ │ • Link com ERP Plus (plusEmpresaId) │ │ -│ │ • Ações: Criar, Editar, Excluir │ │ -│ │ │ │ -│ └─────────────────────────────────────────────────────────────┘ │ -└─────────────────────────────────────────────────────────────────────┘ -``` - ---- - -## 9. API REST Completa (/api/admin/*) - -### Tenants - -| Método | Endpoint | Função | Acesso | -|--------|----------|--------|--------| -| GET | `/tenants` | Lista tenants (filtrado por acesso) | master/partner/client | -| POST | `/tenants` | Cria tenant (resolve features do plano) | master/admin | -| PATCH | `/tenants/:id` | Atualiza tenant (canAccessTenant) | master/partner | -| DELETE | `/tenants/:id` | Exclui tenant (proteção master) | somente master | -| GET | `/tenants/hierarchy` | Árvore hierárquica de tenants | master/partner | -| GET | `/tenants/stats` | Estatísticas (total, por tipo, por status) | master/admin | - -### Planos - -| Método | Endpoint | Função | -|--------|----------|--------| -| GET | `/plans` | Lista todos os planos | -| POST | `/plans` | Cria novo plano | -| PATCH | `/plans/:id` | Atualiza plano | -| DELETE | `/plans/:id` | Exclui plano | -| POST | `/plans/:id/propagate` | Propaga features do plano para todos os tenants que o usam | -| POST | `/plans/seed` | Cria 6 planos padrão | - -### Parceiro-Cliente - -| Método | Endpoint | Função | -|--------|----------|--------| -| GET | `/partner-clients` | Lista relacionamentos parceiro↔cliente | -| POST | `/partner-clients` | Cria vínculo parceiro↔cliente | - -### Comissões de Parceiros - -| Método | Endpoint | Função | -|--------|----------|--------| -| GET | `/commissions` | Lista comissões (filtro por partnerId, status) | -| PATCH | `/commissions/:id/approve` | Aprova comissão | -| PATCH | `/commissions/:id/pay` | Marca como paga | - -### Empresas (Matriz/Filiais) - -| Método | Endpoint | Função | -|--------|----------|--------| -| GET | `/empresas` | Lista empresas (filtro por tenantId + acesso) | -| GET | `/empresas/:id` | Detalhe da empresa | -| POST | `/empresas` | Cria empresa (verifica canAccessTenant) | -| PATCH | `/empresas/:id` | Atualiza empresa | -| DELETE | `/empresas/:id` | Exclui empresa | - -### Outros Admin - -| Método | Endpoint | Função | -|--------|----------|--------| -| GET | `/profiles` | Lista perfis de usuários | -| POST | `/profiles` | Cria perfil | -| PATCH | `/profiles/:id` | Atualiza perfil | -| DELETE | `/profiles/:id` | Exclui perfil | -| GET | `/users` | Lista usuários (com tenant info) | -| PATCH | `/users/:id` | Atualiza usuário | -| PATCH | `/users/:id/status` | Altera status do usuário | -| PATCH | `/partners/:id/status` | Altera status de parceiro | -| PATCH | `/clients/:id/status` | Altera status de cliente | -| GET | `/stats` | Estatísticas gerais (tenants, users, leads) | -| GET | `/libraries` | Lista bibliotecas de conteúdo | - -**Total: 33 endpoints de administração** - ---- - -## 10. Fluxo Completo — Onboarding de Tenant - -``` -┌──────────┐ ┌────────────┐ ┌──────────────┐ ┌──────────────┐ -│ 1. CRIAR │───▶│ 2. PLANO │───▶│ 3. FEATURES │───▶│ 4. EMPRESAS │ -│ TENANT │ │ │ │ │ │ │ -│ │ │ Seleciona │ │ Auto-resolve │ │ Cadastra │ -│ POST │ │ plano │ │ do plano ou │ │ Matriz │ -│ /admin/ │ │ (free, │ │ toggle │ │ + Filiais │ -│ tenants │ │ starter, │ │ individual │ │ │ -│ │ │ pro, etc) │ │ de módulos │ │ CNPJ, IE, │ -│ name, │ │ │ │ │ │ endereço, │ -│ email, │ │ maxUsers │ │ ide: true │ │ regime │ -│ type │ │ maxStorage │ │ crm: true │ │ tributário, │ -│ │ │ preço │ │ bi: false │ │ certificado │ -│ │ │ │ │ ... │ │ digital │ -└──────────┘ └────────────┘ └──────────────┘ └──────────────┘ - │ - ▼ -┌──────────────┐ ┌──────────────┐ ┌──────────────────────────┐ -│ 5. VINCULAR │ │ 6. COMISSÕES │ │ 7. USUÁRIOS │ -│ PARCEIRO │ │ │ │ │ -│ (se partner) │ │ Automáticas │ │ Convida users │ -│ │ │ mensais │ │ tenant_users │ -│ POST /admin/ │ │ baseadas no │ │ roles: owner/admin/ │ -│ partner- │ │ plano do │ │ member │ -│ clients │ │ cliente │ │ │ -│ │ │ │ │ Scoping automático │ -│ partnerId │ │ pending → │ │ de todos os dados │ -│ clientId │ │ approved → │ │ por tenantId │ -│ commission% │ │ paid │ │ │ -└──────────────┘ └──────────────┘ └──────────────────────────┘ -``` - ---- - -## 11. Propagação de Plano - -Quando um plano é atualizado, a feature de **propagação** atualiza todos os tenants que usam esse plano: - -``` -┌─────────────────────────────────────────────────────────────────────┐ -│ POST /api/admin/plans/:id/propagate │ -│ │ -│ 1. Busca o plano por ID │ -│ 2. Pega features, maxUsers, maxStorageMb do plano │ -│ 3. Atualiza TODOS os tenants onde plan === plan.code: │ -│ UPDATE tenants SET │ -│ features = plan.features, │ -│ maxUsers = plan.maxUsers, │ -│ maxStorageMb = plan.maxStorageMb │ -│ WHERE plan = 'pro' │ -│ 4. Retorna: { propagated: 15, planCode: "pro" } │ -│ │ -│ Exemplo: │ -│ Plano "pro" ganha módulo "production" → │ -│ Propagar → 15 tenants "pro" recebem production: true │ -└─────────────────────────────────────────────────────────────────────┘ -``` - ---- - -## 12. Isolamento de Dados - -Toda query de dados respeita o escopo do tenant: - -``` -┌─────────────────────────────────────────────────────────────────────┐ -│ ISOLAMENTO POR tenantId │ -│ │ -│ Padrão em todas as queries: │ -│ │ -│ const tenantId = (req.user as any).tenantId; │ -│ const data = await db.select() │ -│ .from(tabela) │ -│ .where(eq(tabela.tenantId, tenantId)); │ -│ │ -│ Tabelas com tenantId: │ -│ • tenants (hierarquia) • crm_channels │ -│ • tenant_empresas • crm_threads │ -│ • crm_leads • crm_events │ -│ • crm_clients • crm_campaigns │ -│ • crm_opportunities • crm_products │ -│ • crm_partners • crm_contracts │ -│ • crm_pipeline_stages • crm_commission_rules │ -│ • crm_proposals • crm_quick_messages │ -│ • retail_activity_feed • valuation_* │ -│ │ -│ Resultado: Dados do Tenant A NUNCA são vistos pelo Tenant B │ -└─────────────────────────────────────────────────────────────────────┘ -``` - ---- - -## 13. Arquivos-Chave - -| Arquivo | Função | Linhas | -|---------|--------|--------| -| `shared/schema.ts` (L821-977) | TenantFeatures type + 6 tabelas tenant | ~160 | -| `server/admin/routes.ts` | API admin (33 endpoints) | 876 | -| `client/src/pages/Admin.tsx` | Página admin (6 abas) | 2.635 | -| `client/src/components/MultiTenantSection.tsx` | Gestão multi-tenant (4 sub-abas) | 1.486 | -| `client/src/hooks/use-tenant-features.ts` | Hook de features no frontend | 59 | -| `server/retail/routes.ts` (L25) | Middleware requireModule | ~25 | -| `server/storage.ts` (getEnrichedUser) | Enriquece user com tenant info | — | - ---- - -## 14. Resumo Visual - -``` -┌─────────────────────────────────────────────────────────────────────┐ -│ ARCÁDIA MULTI-TENANT STACK │ -│ │ -│ ┌───── Autenticação ──────────────────────────────────────────┐ │ -│ │ Login → getEnrichedUser → user + tenantId + tenantType │ │ -│ │ + tenantRole + features │ │ -│ └─────────────────────────────────────────┬───────────────────┘ │ -│ │ │ -│ ┌─────────────────────────────────────────▼───────────────────┐ │ -│ │ Middleware │ │ -│ │ ┌──────────┐ ┌─────────────┐ ┌────────────────────┐ │ │ -│ │ │requireAuth│ │requireModule │ │getAllowedTenantIds │ │ │ -│ │ │role check │ │feature check │ │canAccessTenant │ │ │ -│ │ └──────────┘ └─────────────┘ └────────────────────┘ │ │ -│ └─────────────────────────────────────────┬───────────────────┘ │ -│ │ │ -│ ┌─────────────────────────────────────────▼───────────────────┐ │ -│ │ API /api/admin/* │ │ -│ │ 33 endpoints: Tenants, Plans, Empresas, Comissões │ │ -│ └─────────────────────────────────────────┬───────────────────┘ │ -│ │ │ -│ ┌─────────────────────────────────────────▼───────────────────┐ │ -│ │ PostgreSQL │ │ -│ │ 6 tabelas: tenants, tenant_users, tenant_plans, │ │ -│ │ tenant_empresas, partner_clients, partner_commissions │ │ -│ └─────────────────────────────────────────────────────────────┘ │ -│ │ -│ ┌───── Frontend ──────────────────────────────────────────────┐ │ -│ │ Admin.tsx (6 abas) → MultiTenantSection (4 sub-abas) │ │ -│ │ useTenantFeatures() hook → GET /api/soe/tenant/modules │ │ -│ └─────────────────────────────────────────────────────────────┘ │ -└─────────────────────────────────────────────────────────────────────┘ -``` diff --git a/SESSAO_2026-03-18.md b/SESSAO_2026-03-18.md deleted file mode 100644 index 1365d87..0000000 --- a/SESSAO_2026-03-18.md +++ /dev/null @@ -1,167 +0,0 @@ -# Sessão de Desenvolvimento — 2026-03-18 - -**Branch:** `claude/analyze-project-0mXjP` -**Commits desta sessão:** `8d14fc0`, `20a0237` -**Contexto:** Continuação do ciclo iniciado em 2026-03-13 (auditoria A-Z + desenvolvimento das fases XOS) - ---- - -## 1. O que foi feito nesta sessão - -### 1.1 Correção de erros TypeScript críticos no `App.tsx` - -Três classes de erros impediam o build limpo do frontend: - -| Erro | Arquivo | Correção | -|---|---|---| -| `Cannot find module '@/contexts/SoeMotorContext'` | `App.tsx:8` | Criado `client/src/contexts/SoeMotorContext.tsx` | -| `Cannot find module '@/pages/SOE'` | `App.tsx:39` | Criado `client/src/pages/SOE.tsx` | -| `LazyExoticComponent` não atribuível a `() => Element` (20x) | `protected-route.tsx` | Tipo alterado para `React.ComponentType` | - -**Arquivos criados/modificados:** -- `client/src/contexts/SoeMotorContext.tsx` — context global com `SoeMotorProvider` e hook `useSoeMotor` -- `client/src/pages/SOE.tsx` — página SOE (Sistema de Operações Empresariais), re-export do módulo Plus/ERP -- `client/src/lib/protected-route.tsx` — tipo do prop `component` corrigido - -**Resultado:** `npx tsc --noEmit` zerou todos os erros do `App.tsx`. Erros remanescentes são pré-existentes em outros arquivos e não relacionados às correções. - ---- - -### 1.2 Guia de deploy no Coolify (`DEPLOY_COOLIFY.md`) - -Documento completo de 359 linhas cobrindo: - -- **Arquitetura de serviços** — mapa visual de todos os containers e redes -- **Variáveis de ambiente** — obrigatórias e opcionais por módulo (Core, IA, Superset, Plus, ERPNext) -- **Profiles Docker** — como habilitar `ai`, `bi`, `plus`, `erpnext` via `COMPOSE_PROFILES` -- **Sequência de inicialização** — ordem garantida pelos `depends_on` e healthchecks -- **Traefik + HTTPS** — labels prontas para Let's Encrypt via Coolify -- **Volumes e persistência** — tabela de criticidade + comandos de backup PostgreSQL -- **Stack de IA** — 3 tiers LiteLLM (LLMFit → Ollama → externos), como baixar modelos, como habilitar LLMFit -- **Pós-deploy** — migrations, verificação de saúde -- **Checklist final** — antes, durante e após o deploy -- **Comandos de referência rápida** - ---- - -### 1.3 Relatório de comparação Auditoria vs Desenvolvimento - -Análise completa cruzando o `ARCADIA_AUDIT_EXECUCAO.md` (auditoria de 13/Mar) com todos os 18 commits do branch: - -**Resultado geral: 44% concluído, 17% parcial, 38% pendente** - -| Sprint | ✅ | ⚠️ | ❌ | -|---|---|---|---| -| S — Segurança (10 itens) | 7 | 3 | 0 | -| 0 — Deploy (6 itens) | 2 | 1 | 3 | -| 1 — Inteligência (6 itens) | 2 | 2 | 2 | -| 2 — App Store (4 itens) | 3 | 0 | 1 | -| 3 — Compass IA (4 itens) | 1 | 1 | 2 | -| 4 — ERP Real (6 itens) | 0 | 0 | 6 | -| 5 — Soberania IA (4 itens) | 3 | 1 | 0 | -| 6 — Qualidade (7 itens) | 3 | 0 | 4 | -| 7 — ERPNext (5 itens) | 2 | 1 | 2 | - ---- - -## 2. Estado do Superset BI (análise técnica) - -Levantamento completo da integração Apache Superset: - -**Funcionando:** -- Gateway Node.js com 4 endpoints (`/guest-token`, `/dashboards`, `/health`, proxy `/superset/*`) -- Guest Token JWT via service account com cache de 50 min -- Componente React `` reutilizável com fallback iframe -- Docker: init automático, banco `arcadia` registrado somente leitura, admin criado -- Feature flags: embed, drill-to-detail, cross-filters, alerts, templates Jinja - -**Pendente / stub:** -- RLS por tenant — `rls: []` vazio, todos veem todos os dados -- Nenhum dashboard pré-criado — criação manual pelo usuário -- Cache Redis — usando `SimpleCache` em memória -- SSO/OAuth — auth local apenas - ---- - -## 3. Contexto acumulado do ciclo completo (desde 13/Mar) - -### O que foi construído no branch (18 commits, 71 arquivos, +9.399 linhas) - -| Área | Principais entregas | -|---|---| -| **Segurança** | Auth em todas as rotas XOS, CORS Python corrigido, credentials removidas, timeout+retry, approval guard Manus | -| **XOS CRM** | Fases 1–4 completas: automações, SLA, horário comercial, campanhas, Socket.IO tempo real | -| **Novas páginas React** | `XosSupervisor`, `XosReports`, `XosProtocols` | -| **SOE Rule Engine** | Motor de regras contábil/fiscal + importador ERPNext | -| **Superset BI** | Integração completa embed + proxy + guest token | -| **Infra Docker** | `docker-compose.prod.yml` com profiles: `ai`, `bi`, `plus`, `erpnext` | -| **IA Soberania** | LiteLLM 3 tiers + Ollama + slot LLMFit pronto | -| **Qualidade** | Rate limiting, logging estruturado (`server/logger.ts`), paginação | -| **App Store** | `GET /api/marketplace/my-apps` + AppCenter por subscription | -| **Docs** | `DEPLOY_COOLIFY.md`, `INTEGRACAO_IA.md`, `PLANO_BI_SUPERSET.md`, `PLANO_SOE_CENTRAL_v2.md` | - ---- - -## 4. Demandas prioritárias pendentes - -### Críticas (bloqueia produção estável) - -1. **LMS e Quality** — auth ainda incompleta (SEC-02, SEC-03) - - `server/lms/routes.ts` — 8 rotas ainda públicas - - `server/quality/routes.ts` — ~50 rotas revisão insuficiente - -2. **WhatsApp auto-reply** — configuração ainda em `Map` na memória - - Reiniciar servidor = perda total da configuração sem aviso - - Persistir em tabela `whatsapp_auto_reply_config` (migration já existe) - -3. **`pg_dump` do Replit** — exportar banco antes de encerrar o plano - - Risco de perda de dados de produção atual - -### Altas (produto incompleto) - -4. **Ciclo de aprendizado Manus** — embeddings não são populados automaticamente - - Busca semântica retorna vazio, sistema não aprende das interações - -5. **Páginas placeholder** — `Agent.tsx`, `CentralApis.tsx`, `ApiHub.tsx` - - Três das páginas mais estratégicas ainda sem implementação - -6. **Sprint 4 inteiro — Integrações ERP reais** - - Adaptadores Omie e TOTVS: zero implementado - - Todos os conectores da Central de API ainda mockados - - Estrutura fragmentada em 4 lugares (`server/erpnext/`, `server/crm/frappe-service.ts`, `server/api-central/`, `server/migration/`) - -### Médias (qualidade de engenharia) - -7. **Error boundaries globais no React** — sem captura de erros em cascata -8. **Testes automatizados** — zero no projeto inteiro -9. **Connection pooling Python** — nova conexão DB por request nos 6 microserviços -10. **Consolidar sistemas de comunicação** — legacy (`whatsapp_*`, `chat_*`) e moderno (`comm_*`, `xosConversations`) duplicados -11. **36 tabelas sem insert schema** — risco de runtime errors no Drizzle -12. **40+ tabelas sem `createdAt`/`updatedAt`** — auditoria e ordenação impossíveis - -### Decisões arquiteturais abertas - -| # | Decisão | -|---|---| -| D1 | BI padrão: Metabase (existente) vs Superset (integrado)? | -| D2 | LMS: tabelas dinâmicas vs schema.ts fixo? | -| D3 | Sistema de comunicação canônico: legacy vs moderno vs XOS? | -| D4 | Marketplace público ou autenticado (hoje público — intencional)? | - ---- - -## 5. Próxima sessão recomendada - -**Sequência sugerida por impacto/risco:** - -``` -1. Corrigir auth LMS + Quality (2–3h) → fecha todas as vulnerabilidades SEC -2. Persistir WhatsApp auto-reply no banco (1h) → estabilidade em produção -3. Fechar ciclo embeddings Manus (2h) → IA começa a aprender de verdade -4. Implementar Agent.tsx com UI real (3–4h) → página mais estratégica -5. Adaptador Omie — primeira integração ERP real (4–6h) -``` - ---- - -*Sessão registrada em 2026-03-18 | Branch: `claude/analyze-project-0mXjP`* diff --git a/package-lock.json b/package-lock.json index d35b215..1ec6276 100644 --- a/package-lock.json +++ b/package-lock.json @@ -129,6 +129,7 @@ "@types/connect-pg-simple": "^7.0.3", "@types/express": "4.17.21", "@types/express-session": "^1.18.0", + "@types/http-proxy-middleware": "^0.19.3", "@types/node": "^20.19.0", "@types/passport": "^1.0.16", "@types/passport-local": "^1.0.38", @@ -7488,6 +7489,18 @@ "@types/node": "*" } }, + "node_modules/@types/http-proxy-middleware": { + "version": "0.19.3", + "resolved": "https://registry.npmjs.org/@types/http-proxy-middleware/-/http-proxy-middleware-0.19.3.tgz", + "integrity": "sha512-lnBTx6HCOUeIJMLbI/LaL5EmdKLhczJY5oeXZpX/cXE4rRqb3RmV7VcMpiEfYkmTjipv3h7IAyIINe4plEv7cA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/connect": "*", + "@types/http-proxy": "*", + "@types/node": "*" + } + }, "node_modules/@types/imap": { "version": "0.8.43", "resolved": "https://registry.npmjs.org/@types/imap/-/imap-0.8.43.tgz", diff --git a/server/bi/Dockerfile b/server/bi/Dockerfile new file mode 100644 index 0000000..f0dd278 --- /dev/null +++ b/server/bi/Dockerfile @@ -0,0 +1,36 @@ +# BI-API Gateway - Node.js +# Arcádia Suite - Port 8004 +# Roda com tsx (TypeScript runtime) + +FROM node:20-alpine + +LABEL maintainer="Arcádia Suite" +LABEL description="BI-API Gateway - Proxy para MetaSet e FDB-Bridge" + +WORKDIR /app + +# Instalar tsx globalmente +RUN npm install -g tsx + +# Criar package.json mínimo com as dependências necessárias +RUN npm init -y && \ + npm install express@4 cors@2 helmet@7 http-proxy-middleware@2 && \ + npm cache clean --force + +# Copiar apenas o arquivo do gateway +COPY server/bi/index.ts ./server/bi/index.ts + +# Variáveis de ambiente padrão +ENV NODE_ENV=production +ENV PORT=8004 +ENV METASET_HOST=metaset +ENV METASET_PORT=8100 +ENV FDB_BRIDGE_HOST=fdb-bridge +ENV FDB_BRIDGE_PORT=8200 + +EXPOSE 8004 + +HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \ + CMD wget -qO- http://localhost:8004/health || exit 1 + +CMD ["tsx", "server/bi/index.ts"] diff --git a/server/bi/metaset/init-db.sql b/server/bi/metaset/init-db.sql new file mode 100644 index 0000000..618c5e4 --- /dev/null +++ b/server/bi/metaset/init-db.sql @@ -0,0 +1,5 @@ +-- Criar banco de dados MetaSet +CREATE DATABASE metaset_db OWNER arcadia; + +-- Comentário +COMMENT ON DATABASE metaset_db IS 'MetaSet BI - Apache Superset metadata database';