basquetWi + New ticket
movilba MOVILBA-290

Los LATERAL de los catalogos que NO son tramite siguen eligiendo en silencio con ORDER BY id LIMIT 1

Done normal dmdb03-mba-l-cc

Observado por audit-mba-l-cc el 2026-09-05 09:25 mientras releia los hunks de MOVILBA-284, y explicitamente fuera de los cinco requisitos de ese item. Los dos LATERAL de tramite ya se corrigieron a SELECT min(id) ... HAVING count(*)=1, que es lo que ya hacen los dos aterrizajes del mismo lookup del lado de la app (MOVILBA-268 en src/lib/reportes/liquidacion.ts y MOVILBA-281 en src/repositories/vehiculos.ts). Pero en el mismo archivo del loader siguen con ORDER BY id LIMIT 1 los LATERAL de respuesta_binaria, estandar_emisiones, estado, lineas, entidades y vehiculos. Es la misma enfermedad: si el catalogo alguna vez tiene dos filas vivas con el mismo texto, se elige una en silencio y nada lo dice. No cambia nada hoy y por eso no bloqueo la corrida de 284; cambia todo el dia que uno de esos catalogos gane un duplicado, y carrocerias YA tiene esa enfermedad segun reference_un_catalogo_duplicado_hace_ver_conflicto_de_datos_donde_no_hay. Tratamiento: exactamente-una-o-aborta, nombrando el catalogo y el texto que resolvio de mas. Hacerlo en una pasada sola sobre los seis, despues de que 284 corra, no antes.

Sub-tickets

No sub-tickets.
+ Add sub-ticket

Activity

  • wi-cli-venus created · 5w ago
  • wi-cli-venus assigned · 4w ago
    db03-mba-l-cc
  • wi-cli-venus assigned · 4w ago
    db02-mba-l-cc
  • wi-cli-venus note · 4w ago
    MEDIDO CONTRA EL ARCHIVO VIVO Y CONTRA LOS DOS ENTORNOS - db02-mba-l-cc, 2026-09-12, SOLO LECTURA. LA LISTA DE SEIS DE ESTE ITEM YA NO EXISTE: los seis LATERAL que nombra ya fueron corregidos. Quedan OTROS CINCO, y uno de ellos no es la misma enfermedad sino una peor. FUENTE: docs/migrations/2026-09-04-movilba-227-full-loader-dry-run-DEV.sql leido de origin/dev (ultimo commit que lo toca: 671c26c8, MOVILBA-370, 09-08). No del checkout compartido, que esta atrasado. LOS SEIS DEL ITEM ESTAN HECHOS. respuesta_binaria (siete LATERAL: adas, cabina, mdvr, pantallas, wifi, usb, identidad), estandar_emisiones, estado, lineas, entidades y vehiculos usan hoy min(id) ... HAVING count(*)=1. El bloque de historial del final tambien (vehiculos, lineas, entidades, tramite). Son 17 lugares con HAVING count(*)=1 en el archivo. LO QUE QUEDA CON ORDER BY ... LIMIT 1, cuatro lugares, todos en el bloque de datos de colectivo (lineas 255-301): 1. carrocerias, por upper(btrim(carroceria_modelo)) 2. fabricantes, resolviendo la marca de MOTOR 3. vehiculos_subtipos_transporte, por split_part(codigo,'-',1) 4. v_opciones campo unidad_propulsora Los cuatro eligen en silencio si el catalogo gana un duplicado vivo. Mismo tratamiento que ya se aplico: min(id) ... HAVING count(*)=1, nombrando el catalogo y el texto que resolvio de mas. EL LATENTE NO ESTA DISPARADO HOY, medido en LOS DOS entornos: cero textos duplicados vivos en carrocerias, cero en fabricantes, cero prefijos de codigo duplicados en subtipos y cero en unidad_propulsora. O sea la correccion sigue siendo preventiva, como decia el item. EL QUINTO, Y ESTE NO ES PREVENTIVO - YA ELIGE MAL HOY. La resolucion de chasis (linea ~250) es: ORDER BY (ch.borrado_en IS NULL) DESC, ch.id LIMIT 1 sin ningun filtro de borrado_en. El ORDER BY pone los vivos primero, pero cuando NO hay ninguno vivo que matchee, la fila igual sale: resuelve a un chasis BORRADO y lo asigna. Medido: hay 69 pares (marca, modelo) en DEV y 80 en PROD cuyas filas de chasis estan TODAS borradas. Para cualquiera de esos pares que aparezca en el libro, el loader escribe un FK a una fila de catalogo borrada, sin error y sin log. Eso no es un empate mal desempatado: es una eleccion fuera del conjunto valido. Y engancha con la trampa ya registrada de que 'borrado_en IS NULL' contesta 'disponible', no 'existe' - hay chasis borrados con vehiculos vivos encima. TRATAMIENTO DISTINTO AL DE LOS CUATRO: aca no alcanza con exigir unicidad. Hay que decidir que pasa cuando el unico match esta borrado: o resuelve a NULL y el caso va al reporte, o aborta nombrando el par. Las dos son legitimas; elegir una es decision, no limpieza. Si se aplica ciegamente min(id) HAVING count(*)=1 sobre las vivas, esos pares pasan de 'apunta a una fila borrada' a 'no resuelve', que probablemente sea lo correcto pero cambia el resultado del import y por eso no lo hago yo. RECOMENDACION DE ORDEN: los cuatro son una sola pasada mecanica. El de chasis va aparte, con la decision escrita primero. NO EJERCITADO: no corri el loader, no medi cuantos pares de los 69/80 aparecen efectivamente en el libro vigente, y no revise migraciones de loader posteriores a 671c26c8. Nada ejecutado.
  • wi-cli-venus assigned · 3w ago
    db04-mba-l-ca
  • db04-mba-l-ca progress · 3w ago
    db04-mba-l-ca 2026-09-24 04:05 -03 — Status sweep limitation: The six old LATERAL resolvers and the five later residual paths were not checked against the currently installed loader function or its negative fixtures. BWI show and recent events were read; status unchanged and no DB write.
  • coder03-mba-l-cc assigned · 1w ago
    db03-mba-l-cc / db
  • db03-mba-l-cc note · 1w ago
    RE-DERIVADO CONTRA EL PIPELINE ACTUAL (rutap.proyectar_snapshot, SQL function) - db03-mba-l-cc 2026-10-08. La nota de 2026-09-12 (db02) ya estaba parada sobre una arquitectura superada: midio contra el loader viejo basado en script, no contra la funcion SQL instalada hoy. ARQUITECTURA HOY: grep completo de proyectar_snapshot por ORDER BY|LIMIT 1|HAVING count - CERO ocurrencias de "ORDER BY ... LIMIT 1" como mecanismo de eleccion. Los seis resolvers originales del ticket (respuesta_binaria/estandar_emisiones/estado/lineas/entidades/vehiculos, loader viejo) no existen mas - la reescritura a funcion SQL los reemplazo por LEFT JOIN de igualdad pura (grupo_nombre+campo_nombre+valor_opcion/nombre_mostrable+borrado_en IS NULL) para tramite, unidad_propulsora, piso, estandar_emisiones. RED DE SEGURIDAD ACTUAL (no es silent-pick, es hard-abort): un LEFT JOIN de igualdad que matchea >1 fila viva hace FAN-OUT de la CTE, no elije una - el INSERT subsiguiente pisa el UNIQUE vh_norm_raw_key (snapshot_id, fila_excel) y aborta TODO el projection con una excepcion. Confirmado por comentario en linea del propio autor (MOVILBA-342, em) citando exactamente este mecanismo como diseño. ALTA/SI/NO tienen ademas un chequeo G0 explicito con RAISE EXCEPTION nombrado; GNC tiene un chequeo W3 post-insert nombrado. El resto (unidad_propulsora no-GNC, piso, estandar_emisiones, fabricantes, subtipo) NO tiene un chequeo nombrado propio - dependen solo del UNIQUE generico. Correctitud equivalente (nunca eligen en silencio), diagnosticabilidad peor (unique-violation opaco vs RAISE EXCEPTION con mensaje). CARROCERIA: ya resuelto distinto de lo que asumia el ticket - rutap.resolver_carroceria aborta con RAISE EXCEPTION 'MOVILBA-492' si cardinality(v_ids)>1 (array_agg + check), no por ORDER BY. CHASIS (el hallazgo mas severo del ticket original, "no es la misma enfermedad sino una peor" - chasis resuelve a una fila borrada): YA NO es un JOIN directo a texto contra public.chasis vivo. Pasa por tablas de resolucion curadas-y-aprobadas: rutap.unidad_propulsora_resolver + rutap.chasis_resolver, filtradas por estado='aprobado', mapeadas por texto normalizado + unidad_propulsora_id ya resuelta. Medido PROD (SUPERUSER, solo lectura): 0 filas aprobadas de chasis_resolver apuntan a un chasis_id con borrado_en IS NOT NULL. La duplicacion de clave aprobada es ademas estructuralmente IMPOSIBLE, no solo vacia hoy: chasis_resolver_pkey = PRIMARY KEY (fabricante_normalizado, modelo_normalizado, unidad_propulsora_id) - el PK cubre TODAS las filas, aprobadas o no, asi que dos aprobaciones con la misma clave no pueden coexistir. El defecto original no reproduce bajo la arquitectura actual. MEDICION DE CANDIDATOS VIVOS (PROD, hoy, 0 en los cinco): opciones duplicadas por (grupo_nombre,campo_nombre,valor_opcion) borrado_en IS NULL en motor/unidad_propulsora, carroceria/piso, motor/estandar_emisiones = 0. fabricantes duplicados por upper(fabricante) borrado_en IS NULL = 0. vehiculos_subtipos_transporte duplicados por codigo bajo vehiculo_tipo_id=1 borrado_en IS NULL = 0. LIMITE DE LA MEDICION (control no forzado - igual que el patron de MOVILBA-240): el UNIQUE vh_norm_raw_key como red de seguridad nunca fue EJERCITADO con un fan-out real; es una linea verde sin forzar, igual que advierte measurement-discipline. No pide fix de datos porque no hay datos hoy que fanout. VEREDICTO: la premisa original (silent-pick via ORDER BY id LIMIT 1) no existe en el codigo instalado - superada por la reescritura a rutap.proyectar_snapshot. Lo que queda es una mejora opcional de diagnostico, no un bug de hoy: agregar un chequeo G0 nombrado (RAISE EXCEPTION tipo MOVILBA-269) para unidad_propulsora completo (no solo GNC), piso, estandar_emisiones, fabricantes y subtipo, para que un futuro duplicado de catalogo aborte con mensaje legible en vez de un unique-violation opaco. Sin ese chequeo HOY no hay riesgo de silent-pick (el UNIQUE lo evita), solo de peor mensaje de error el dia que ocurra. Decision para coder03/Elazar: implementar la mejora de diagnostico o cerrar el ticket por arquitectura superada.
  • db03-mba-l-cc completed · 1w ago
    Premisa original (ORDER BY id LIMIT 1, silent-pick) no existe en rutap.proyectar_snapshot - reescritura la superó. Fan-out hoy es hard-abort via UNIQUE vh_norm_raw_key, no silent-pick; 0 candidatos duplicados medidos en PROD (opciones/fabricantes/subtipo); chasis_resolver fan-out estructuralmente imposible (PK). Queda solo una mejora opcional de diagnostico (chequeos G0 nombrados) - ver nota.
  • audit-mba-l-cc audited · 1w ago
    audit pass: grep + 5-catalog duplicate SELECTs PROD
    payload
    {"scope":"grep + 5-catalog duplicate SELECTs PROD","outcome":"pass","evidence":"0 ORDER BY...LIMIT1 in proyectar_snapshot source; 0 live dup candidates opciones(motor/unidad_propulsora,carroceria/piso,motor/estandar_emisiones)+fabricantes+subtipos; chasis_resolver PK confirmed via pg_constraint. UNEXERCISED: approved-chasis-to-deleted-chasis join blocked by permission denied for svc_nextjs on rutap.chasis_resolver - not independently verified, claim unconfirmed not refuted","reportRef":null}
  • db04-mba-l-ca verified · 1w ago
    2026-10-08 11:35 ART, SELECT-only PROD current_database()=movilba. Query: SELECT count(*) AS approved_total, count(*) FILTER (WHERE c.id IS NULL) AS missing_target, count(*) FILTER (WHERE c.borrado_en IS NOT NULL) AS approved_to_soft_deleted FROM rutap.chasis_resolver AS r LEFT JOIN public.chasis AS c ON c.id = r.chasis_id WHERE r.estado = 'aprobado'; Result: approved_total=101, missing_target=0, approved_to_soft_deleted=0. Positive denominator 101; agrees with db03's zero, not a vacuous count. No DB write.
  • audit-mba-l-cc audit-finding · 1w ago
    Gap closed by db04's independent SELECT (not mine): 101 approved chasis_resolver rows, 0 missing target, 0 pointing to a borrado_en chasis. Confirms the chasis_resolver part of db03's original claim.
bug
5w ago by wi-cli-venus
1w ago
2026-10-08 14:22