El '0' de relleno del libro: DEV lo guarda como NULL y PROD como '0'. Nadie declaro cual gana
RETRACTO el planteo original. Dije que algo en DEV manglaba id_canbus e id_adas. No hay mangling: los dos entornos son internamente coherentes y aplican reglas DISTINTAS a la misma celda, y ninguna de las dos esta escrita. QUE DICE EL LIBRO, filas abiertas del 2026-09-01-1440: ID CANBUS trae 0 en 1455 de 1600 y un identificador real en 145. ID ADAS trae 0 en 510 y valor real en 1090. QUE GUARDA CADA ENTORNO, sobre v_vehiculos_export: id_canbus - DEV 2222 nulos y 4 ceros · PROD 559 nulos y 1663 ceros id_adas - DEV 980 nulos y 2 ceros · PROD 430 nulos y 552 ceros PROD copia el 0 tal cual. DEV lo convierte a NULL. Esa es toda la diferencia, y explica exactamente los 1445 y 513 dominios que MOVILBA-186 contaba como drift de DEV. POR QUE APARECIO COMO DRIFT: el medidor pliega NULL a cadena vacia, y '' no es '0'. Es la septima trampa de reference_como_reconciliar_el_libro_rutap_contra_prod, aplicada contra mi propia medicion. LA DECISION NO ES MIA. tools/rutap-snapshot-import.py:545-567 ya clasifica ese 0 como relleno - 'sin identificador cargado' - y lo reporta AL LIBRO, con el conteo de todo el libro: id_canbus 4884, id_adas 2792, camaras_adas 2123, id_mdvr 1126, camaras_internas 861, total 11786 celdas. O sea que alguien ya decidio que el 0 no es un numero. Pero NO esta en docs/reference/rutap-transform-rules.md, y ese archivo abre diciendo que una correccion que aplicamos y no documentamos es drift, no prolijidad. DOS OPCIONES, y hay que elegir una y escribirla: a) FIEL - se guarda '0' como lo trae el libro. PROD ya esta asi; DEV se corrige. El campo dice 0 y quien lo lea interpreta. b) NORMALIZADA - el 0 de relleno se guarda como NULL en COLS_ID (id_canbus, id_adas, id_mdvr, camaras_adas, camaras_internas). DEV ya esta asi; PROD se corrige. Va a rutap-transform-rules.md como regla de clase y el medidor la aplica de los dos lados. Cualquiera sirve. Lo que no sirve es que los dos entornos contesten distinto y que el gate de MOVILBA-186 cuente como drift una diferencia que en realidad es una regla sin escribir. Bloqueado en Elazar.
Activity
-
parent=#3268
-
El '0' de relleno del libro: DEV lo guarda como NULL y PROD como '0'. Nadie declaro cual gana
-
was: id_canbus difiere en 1445 dominios vigentes de DEV y en 1 de PROD. id_adas difiere en 513 de DEV y en 7 de PROD. id_mdvr 51 en DEV contra 22 en PROD. Dos ordenes de magnitud de diferencia entre entornos sobre las mismas columnas y el mismo libro: hay algo en el camino de carga de DEV que las rompe y que en PROD no existe. Hay que encontrarlo ANTES del re-import, o el import lo hereda. Es la forma inversa de la trampa conocida (el defecto vive donde no desarrollas): aca vive donde SI desarrollamos, y por eso es barato de diagnosticar.
-
Decision de Elazar: el 0 de relleno se guarda tal cual (fiel) o como NULL (normalizado). Los dos entornos difieren y la regla no esta escrita.
-
Implementation decision: identifier placeholders 0 -> NULL; count fields retain numeric 0. Document and test the type-specific rule.
-
Elazar decision (2026-09-03): preserve literal source '0' for all relevant RUTAP fields. Do not fold identifier '0' to NULL. Source importer tools/rutap-snapshot-import.py already preserves it (clean() only NBSP/edge whitespace/empty); divergence is downstream: rutap.v_rutap_latest_norm currently maps id_adas/id_mdvr/id_canbus and motor_nro '0' to NULL, and DEV migration docs/migrations/2026-08-27-movilba30-textual-zero-to-null-DEV.sql did the same for VDC IDs. Required scope: replace those 0->NULL rules with source-faithful projections; do not treat textual 0 as an import error. Corrective backfill must be derived from raw snapshot evidence, never inferred from existing NULLs. Acceptance: raw '0' remains '0' through normalized comparison and historical/application projection; source blank alone becomes NULL.
-
Decidido por Elazar 2026-09-03: opcion FIEL, el 0 se guarda como 0 en las cinco columnas y NULL queda para la celda vacia. T8 reescrita en docs/reference/rutap-transform-rules.md. Se corrige DEV, no PROD. La mitad de UI es MOVILBA-221.
-
Cerrado: la decision existe, esta escrita y esta shipeada en las dos mitades. REGLA (Elazar 2026-09-03, revierte el veredicto anterior): el 0 del libro se guarda como 0 en las cinco columnas y NULL queda reservado a la celda VACIA. Sus palabras: 'if camaras or whatever never gets a value is null but if it goes from 4 to 0 gets a 0, so we have null and 0, i say 0 to all'. Razon: NULL desaparece de SUM/AVG/GROUP BY y 0 cuenta, asi que plegar borra la diferencia entre 'no tiene camaras' y 'no sabemos cuantas'. MITAD DE REGLA: T8 reescrita en docs/reference/rutap-transform-rules.md, v5.4.105. MITAD DE UI: MOVILBA-221, cerrado, commits 055d9c85 y c0ff22d6 (dev v5.4.108/109), verificado con escrituras reales contra DEV. BACKFILL: no hay item de backfill de PROD porque PROD YA CUMPLE - guarda el 0 verbatim (ip_canbus 1665 celdas, identificacion_camaras_adas 553, sobre 2396 fichas, medido por db02 el 09-03). El que no cumple es DEV, y eso va dentro del re-import de db03 (MOVILBA-155/190), no como pasada aparte. LO QUE QUEDA VIVO EN OTROS ITEMS: MOVILBA-222 (10 celdas de PROD en NULL donde el libro trae un identificador real - hueco de fidelidad anterior a esta regla, no esta regla). NO EJERCITADO: la rama NULL. El libro vigente no tiene NINGUNA celda vacia en esas cinco columnas, asi que ningun import la ejerce; solo se prueba a mano.