Saltar a contenido

ADR 002: Plan de distribución pip (core + framework + main + plugins)

Estado

Propuesto — 2026-06 · No implementado (documento de planificación)

Relacionado con ADR 001 (stack HIVE) y con el auto-discovery de plugins (cortex.plugins entry points).

Objetivo

Permitir instalar Cortex como plataforma y plugins por separado, sin fragmentar el monorepo en varios repositorios Git:

pip install cortex
pip install cortex-plugin-reference   # To-Do de ejemplo
pip install cortex-plugin-booking    # booking (ADR 008)

export CORTEX_ENABLED_PLUGINS=reference,booking
cortex-api

Desarrollo local sigue siendo uv workspace en un solo repo; PyPI es el canal de consumo en despliegues y sandbox de terceros.

Alcance de este plan

Incluido Excluido (fases posteriores)
Meta-paquete cortex (main) Repos Git separados
Publicación de cortex-core, cortex-framework Lazy load + _plugins.json
Publicación de plugins de dominio Plugin booking en monorepo; pip pendiente
Versionado semver alineado Frontend React como paquete pip
CI publish (borrador) Plugin contabilidad

Situación actual vs objetivo

Hoy (monorepo uv)

pyproject.toml (raíz)     → orquestador workspace; name "cortex" pero NO publicable
core/                     → cortex-core ✓ wheel
framework/                → cortex-framework ✓ wheel + script cortex-api
plugins/reference/        → cortex-plugin-reference ✓ wheel + entry point
plugins/booking/          → cortex-plugin-booking (monorepo; pip pendiente)
  • Discovery: entry points + escaneo plugins/ + sideload (CORTEX_PLUGIN_DIRS).
  • Docker dev: uv sync --all-packages.
  • Framework no depende de plugins concretos (correcto para pip).

Objetivo (monorepo + N wheels PyPI)

pip install cortex              → arrastra cortex-core + cortex-framework
pip install cortex-plugin-*     → plugins opcionales vía entry points

El código no se mueve de carpeta; solo se completa el empaquetado del meta-paquete y la pipeline de publicación.

Mapa de paquetes

Paquete PyPI Carpeta monorepo Módulo Python Rol
cortex (main) raíz / meta/ (vacío o namespace mínimo) Metapaquete: deps + extras opcionales
cortex-core core/ cortex_core SPI, registry, tipos
cortex-framework framework/ cortex_framework FastAPI, tenant, forms, dashboards, loader
cortex-plugin-reference plugins/reference/ cortex_plugin_reference To-Do stub + forms
cortex-plugin-booking plugins/booking/ cortex_plugin_booking Reservas — dominio genérico ADR 008

Dependencias entre paquetes (PyPI)

Leyenda: Grafo de publicación pip (Independiente = plugins; Dependiente = core + framework). Estado: Plan propuesto (ADR 002).

flowchart TB
  main[cortex main]
  core[cortex-core]
  fw[cortex-framework]
  ref[cortex-plugin-reference]
  bk[cortex-plugin-booking]

  main --> core
  main --> fw
  fw --> core
  ref --> core
  bk --> core
  • cortex-framework depende de cortex-core (rango semver, p. ej. >=0.1,<0.2).
  • Plugins dependen de cortex-core (y FastAPI/Pydantic); no de cortex-framework en runtime (evita ciclos). El hook register_dashboards importa tipos del framework en algunos plugins — revisar en implementación: extraer protocolos a core o declarar cortex-framework como dependencia opcional/documentada del plugin.

Entry points (grupo cortex.plugins)

Plugin id (CORTEX_ENABLED_PLUGINS) Entry point Valor
reference reference cortex_plugin_reference:create_plugin
booking booking cortex_plugin_booking:create_plugin

El id del plugin es el nombre del entry point, no el nombre del paquete pip.

Meta-paquete cortex (main)

pyproject.toml objetivo (raíz o meta/)

[project]
name = "cortex"
version = "0.1.0"
description = "Cortex / HIVE — plataforma por plugins"
requires-python = ">=3.12"
dependencies = [
    "cortex-core>=0.1.0,<0.2.0",
    "cortex-framework>=0.1.0,<0.2.0",
]

[project.optional-dependencies]
reference = ["cortex-plugin-reference>=0.1.0,<0.2.0"]
booking = ["cortex-plugin-booking>=0.1.0,<0.2.0"]
all = [
    "cortex-plugin-reference>=0.1.0,<0.2.0",
    "cortex-plugin-booking>=0.1.0,<0.2.0",
]

[project.scripts]
cortex-api = "cortex_framework.api.main:run"

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

Instalaciones equivalentes:

pip install cortex
pip install "cortex[booking]"
pip install cortex cortex-plugin-reference cortex-plugin-booking

Responsabilidades del main

  • Punto de entrada único para usuarios finales (pip install cortex).
  • Extras opcionales para bundles de plugins.
  • No contiene lógica de negocio; solo dependencias y scripts.
  • El workspace uv puede seguir en el mismo pyproject.toml raíz (patrón común: [tool.uv] + [project] publicable).

Convenciones de versionado

  • Un tag Git = una versión compartida en el primer major (p. ej. 0.1.0 en core, framework, main y plugins).
  • Cambio breaking en SPI (cortex-core) → major bump en todos los paquetes afectados.
  • Plugins pueden minor/patch independientes solo si el SPI backward-compatible lo permite.
  • Publicar desde el monorepo con matriz CI (un job por paquete o uv build por member).

Flujos de consumo

Desarrollo (sin cambios conceptuales)

uv sync --all-packages
uv run cortex-api
uv run pytest

Producción / sandbox pip

pip install cortex cortex-plugin-booking
export CORTEX_ENABLED_PLUGINS=booking
export CORTEX_TENANT_HEADER=X-Tenant-Id
cortex-api   # http://0.0.0.0:8000

Docker (fase posterior al plan)

  • Imagen base: pip install cortex + plugins requeridos por ARG.
  • Alternativa multi-stage: copiar wheels construidos en CI.

Fases de implementación

Fase A — Empaquetado main (prioridad)

  1. Añadir [build-system] y dependencies al pyproject.toml raíz (meta cortex).
  2. Definir [project.optional-dependencies] (reference, booking, all).
  3. Verificar uv build / python -m build genera wheel de cortex instalable.
  4. Probar en venv limpio: pip install dist/cortex-*.whl + wheels de plugins locales.

Fase B — Publicación PyPI

  1. Cuentas/proyectos PyPI (o índice privado) para los 5 nombres.
  2. Workflow GitHub Actions: build matrix + twine upload en tag v*.
  3. Eliminar [tool.uv.sources] de los artefactos publicados (solo en monorepo dev).
  4. Documentar rangos de compatibilidad en README.

Fase C — Ajustes plugins

  1. Revisar dependencia cortex-framework en plugins que importan DashboardRegistry (mover protocolo a core o documentar dep).
  2. Publicar cortex-plugin-booking cuando ADR 008 esté implementado.
  3. Plantilla plugins/_template/ con pyproject.toml + entry point de ejemplo.

Fase D — Operaciones

  1. Actualizar deploy/Dockerfile.api para modo pip o híbrido.
  2. Variables de entorno documentadas en deploy/COOLIFY.md.
  3. Política de deprecación de plugins (semver + changelog por paquete).

Criterios de éxito

  • [ ] pip install cortex en venv vacío instala core + framework y expone cortex-api.
  • [ ] pip install cortex-plugin-reference registra entry point discoverable sin código en plugins/ en disco.
  • [ ] CORTEX_ENABLED_PLUGINS=reference carga solo el plugin reference vía pip.
  • [ ] uv sync --all-packages sigue funcionando para desarrollo en monorepo.
  • [ ] Cinco wheels publicables desde el mismo repo sin editar loader.py al añadir plugins.

Riesgos

Riesgo Mitigación
Nombre cortex ocupado en PyPI Verificar PyPI; alternativa cortex-hive o org propia
Import circular plugin → framework SPI de dashboards/forms solo en core; framework implementa registries
Version skew pip Extras con upper bound; meta-paquete fija rango compatible
Confusión id vs nombre pip Tabla en README; bookingcortex-plugin-booking

Decisiones diferidas

  1. Índice PyPI público vs privado (Coderic/AbanQ).
  2. Prioridad de publicación pipbooking tras ADR 008.
  3. Incluir cortex-api solo en main o también en framework (duplicar script vs single source).
  4. Frontend como paquete npm/CDN separado (fuera de pip).

Referencias internas

  • Loader: framework/cortex_framework/plugins/loader.py
  • Discovery: framework/cortex_framework/plugins/discovery.py
  • ADR stack: docs/adr/001-hive-stack.md
  • README sección “Crear un plugin”

Este documento describe el plan; la implementación se hará en una iteración dedicada sin bloquear el desarrollo de features en plugins.