Roadmap autónomo: Slack bot, creative pipeline, analyst y lab scaffold
Ejecución autónoma de las 4 fases del roadmap acordado. Todas entran en verde con 167/167 tests.
Fase 1 — Slack como interfaz principal
- `slack_bot.py`: carga de config por env (`SLACK_SIGNING_SECRET` mínimo, `SLACK_BOT_TOKEN` + `SLACK_MARKETING_CHANNEL` para notificaciones salientes), verificación HMAC v0 con tolerancia de replay, parsing form + split de subcomando, helpers ephemeral/in_channel, cliente `chat.postMessage` y `response_url` async.
- `slack_handlers.py`: dispatcher con comandos `status`, `digest`, `approve `, `pause`, `resume`, `budget`, `brief`, `analyst`, `help`.
- `POST /api/slack/commands` cableado al handler del portal, con bypass de basic auth (Slack autentica con HMAC).
- CLI `cmoagent slack ping` para smoke-testear el envío saliente.
- README con manifest mínimo de la Slack app.
Fase 2 — Creative pipeline con upstream externo + librería visual
- `creative_pipeline.py`: protocolo `CreativeProvider` + `StubCreativeProvider` (3 assets deterministas) + `BridgeCreativeProvider` (adapter HTTP genérico para Scenario/Layer/Seeles/…). Fallback al stub si no hay URL provisionada.
- `CreativeLibrary` persiste briefs + assets atómicamente bajo `runtime/`, con filtros por juego/plataforma/formato/status.
- `GET /api/creatives` y `POST /api/creatives/process` listos.
- Portal visual en `/creatives/` estilo Pinterest (masonry + filtros + "Procesar cola").
- Comando `/cmo brief : ` encola directamente en la misma cola que consume el pipeline.
Fase 3 — Analyst en lenguaje natural
- `analyst.py`: protocolo `Datasource` con `PostgresDatasource` (asyncpg) y `InMemoryDatasource` (tests/offline), `ClaudePlanner` (si hay `ANTHROPIC_API_KEY`) y `RuleBasedPlanner` (CPI, rollbacks, budget, reviews, competencia, digests), `guard_sql` que fuerza SELECT-only, rechaza verbos peligrosos, valida tabla allow-list (CTE aliases permitidos) e inyecta `LIMIT` por defecto.
- `POST /api/analyst` listo, con fix de serialización Decimal/datetime/UUID en el handler.
- Verificado en vivo: `cómo va el presupuesto?` → SQL guardado → ejecuta contra la DB real → interpretación.
Fase 4 — Experimentation lab scaffold
- `experimentation_lab.py`: value objects `Hypothesis`/`ExperimentDefinition`/`ExperimentResult`/`PromotionDecision`, `PromotionGuardrail` con defaults SOTA 2026 (p ≤ 0.1, incrementalidad requerida, sample size/duration mínimos, lift observado ≥ 50% del esperado), `ExperimentationLab` con persistencia JSON atómica y hooks `incrementality_hook`/`mmm_hook`/`promotion_hook` como no-ops seguros.
- Scaffold explícito — no se construye el lab completo; queda el seam listo para plugear MMM, promoción real y reflection agents.
Test plan
-
167/167 pytest green (64 añadidos en esta rama: 31 slack_bot + handlers, 17 creative_pipeline, 23 analyst, 17 experimentation_lab, 3 fixes previos indirectos). -
Verificado en producción `https://cmo.laparedita.com`: - `/onboarding/`, `/creatives/` → 200.
- `POST /api/analyst` → devuelve SQL + rows + interpretación (testeado con `"cómo va el presupuesto?"`).
- `POST /api/slack/commands` → 501 sin `SLACK_SIGNING_SECRET` (comportamiento esperado).
-
Slack app real + bot token (pendiente de que el CEO cree la app en Slack y pegue los valores a `.env`). -
Provider creativo real (Scenario / Layer / Seeles). El bridge está listo.
Bloqueos / pendientes por provisioning externo
- Slack app: sin crear en el workspace aún. El bot queda "off" hasta que se configure; todo el cableado interno está listo.
- Creative provider: sin credenciales. Stub genera placeholders realistas para que el UI y la cola sigan funcionando.
- ANTHROPIC_API_KEY para el analyst: no configurada en el container. El planner rule-based cubre las preguntas habituales; Claude planner se activa automáticamente cuando se añada la key.
Siguiente paso sugerido
- Crear la Slack app en el workspace (manifest en el README) y poblar `.env` con los tokens.
- Proveer un upstream creativo (aunque sea Scenario free tier) para reemplazar el stub.
- Abrir Fase 5: cablear el lab de experimentación al campaign_runs real (seguimiento automático de rollbacks → hipótesis nuevas).