--- id: "0107e" title: "uses_modules con min_version + codegen fail-loud" status: pendiente type: feature domain: - meta - cpp-stack - tooling scope: registry priority: media depends: - "0107a" blocks: [] related: - "0107" created: 2026-05-17 updated: 2026-05-17 tags: [modules, versioning, codegen, fail-loud] --- # 0107e — Version pinning + codegen fail-loud Parte del issue principal [0107](0107-modules-standardization.md). ## Objetivo Permitir que `app.md` declare version minima del modulo y que el codegen falle ruidosamente si: 1. Modulo declarado en `uses_modules` tiene `version < min_version`. 2. Python3 no disponible y `uses_modules` no vacio. 3. Codegen produce `count = 0` cuando `uses_modules` declara N>0 modulos. ## Schema extendido `app.md::uses_modules` ```yaml # Forma corta (back-compat, sin pinning): uses_modules: [data_table_cpp] # Forma larga (con pinning): uses_modules: - name: data_table_cpp min_version: "1.4" # SemVer minor — acepta 1.4.x, 1.5.x, ..., NO 2.0.0 - name: chat_ia_cpp min_version: "0.1" # Mixed permitido: uses_modules: - data_table_cpp # sin pin - name: framework_cpp # con pin min_version: "1.1" ``` Reglas: - `min_version` formato `MAJOR.MINOR` (no patch — patch siempre bug fix compatible). - Comparacion: `module.md::version >= min_version` AND `module.md::version.major == min_version.major`. Esto previene saltos de major silenciosos. ## Tareas - [ ] **5.1** `python/functions/infra/codegen_app_modules.py`: parser acepta string corto Y dict largo. - [ ] **5.2** Codegen lee `module.md::version` y compara contra `min_version` declarado en `uses_modules`. Si falla → exit 3 con mensaje claro. - [ ] **5.3** `cpp/CMakeLists.txt::add_imgui_app`: si codegen exit != 0 AND != 2 → `message(FATAL_ERROR ...)` (no WARNING como hoy). - [ ] **5.4** Si Python3 NO encontrado AND `app.md` tiene `uses_modules` no vacio → `message(FATAL_ERROR "Python3 required to parse uses_modules; install python3.")`. - [ ] **5.5** Si codegen devuelve count=0 cuando `uses_modules` declara N>0 → `message(FATAL_ERROR ...)` con apunta a la app.md. - [ ] **5.6** Indexer `registry/parser.go`: parsea ambas formas y persiste en `apps.uses_modules_json` con shape canonico `[{name, min_version}]` (min_version null si no declarado). - [ ] **5.7** Test: app sintetica con dict largo + modulo sintetico con version 1.3 y min_version 1.4 → cmake configure falla con mensaje esperado. - [ ] **5.8** Migrar 7 apps consumidoras de data_table a usar dict largo con `min_version: "1.4"` (o lo que sea v actual cuando 0107e cierre). ## Mensajes de error esperados ``` CMake Error at cpp/CMakeLists.txt:289 (message): codegen_app_modules failed for services_monitor: module 'data_table_cpp' version 1.3.0 does not satisfy min_version 1.4 declared in apps/services_monitor/app.md::uses_modules. Either bump module version (via /version) or relax pin in app.md. ``` ``` CMake Error at cpp/CMakeLists.txt:289 (message): codegen_app_modules: app 'dag_engine_ui' declares uses_modules: [data_table_cpp] but generated module manifest has count=0. Likely cause: Python parser failed silently. Re-run with verbose: python3 python/functions/infra/codegen_app_modules.py \ --app-md apps/dag_engine_ui/app.md \ --modules-root modules/ \ --app-name dag_engine_ui \ --out /tmp/test.cpp ``` ## Riesgos - **Apps existentes sin pinning rompen?**: NO. La forma corta sigue valida y trata `min_version` como null = sin chequeo. Solo apps que opten explicitamente reciben gate. - **Build se vuelve ruidoso si modulo no se actualizo**: deliberado. Es el sentido del fail-loud.