basquetWi + New ticket
movilba MOVILBA-167

EPIC: unificar modificaciones de vehículo y normalizar Entidad → Línea → Vehículo

Backlog high dmdb04-mba-l-ca

Elazar decision, 2026-08-31. Replace the two conflicting vehicle-change workflows with one post-handoff modification form. Remove the standalone user-facing 'Historial del Vehículo / Registrar Expediente' form and the duplicate edit-page constancia workflow. The only modification path must collect expediente number, expediente date, and the user’s field changes; changing any vehicle field (WiFi, Pantallas, carrocería, línea, entidad-facing ownership, interno, estado, equipment, etc.) follows the same transaction and creates one app change-history entry. No separate Cambio de Entidad workflow. Normalize ownership as entidad → línea → vehículo: remove vehiculo_historial.entidad_id as current ownership carrier; derive entity through the vehicle’s line. A line→entity transfer changes the line assignment and thereby its vehicles; an individual vehicle transfer changes only vehicle→line, with expediente/dates. Simplify/rebuild current-state views so there is one canonical vehicle→line source and derived entity, rather than v_vehiculos_hist_ultimo duplicating relationship/current/history roles. Pre-handoff RUTAP/Parodi records remain raw provenance; user-facing app history is zero at handoff and starts with app changes. Deliverable phases: (1) exact schema/view/API/UI dependency inventory; (2) additive normalized relationship schema + backfill/reconciliation plan; (3) single-form UX/server-action contract; (4) DEV migration/rehearsal and behavior tests; (5) fresh-GO PROD migration with rollback/verification. No direct DDL or data mutation under this epic without child item, rehearsal, lock, and fresh GO.

Activity

  • wi-cli-venus created · 6w ago
  • wi-cli-venus note · 6w ago
    INVENTARIO DE DEPENDENCIAS (fase 1) - ya medido, no rehacerlo desde cero. coder02-mba-l-cc, 2026-08-31, contra PROD (10.78.42.168, PG17.6) por SELECT y contra el arbol de codigo. MOVILBA-166 pasa a ser hijo de este epic: es exactamente la fase 2 (esquema normalizado del portador de estado actual). Ya tiene el diseño y las mediciones; no duplicar. MOVILBA-165 fue un duplicado mio, cancelado y fusionado en 166. == BASE DE DATOS == vehiculo_historial: 4225 filas en PROD (4338 en DEV). Porta hoy linea_id, entidad_id, estado_id, motivo_id, tramite_id, vehiculo_id. FKs entrantes: 0 - o sea que ningun cambio aca rompe integridad referencial. Triggers: 1. 11 VISTAS dependen de la tabla: v_vehiculo_historial, v_vehiculo_cadena, v_vehiculos_hist_ultimo, v_vehiculos_detalle, v_vehiculos_export, v_monitor_historial_anomalias, v_db_users_footprint_detalle, v_audit_entidades_sin_vinculo, v_audit_lineas_sin_vinculo, v_audit_vehiculos_sin_vinculo, v_audit_vinculos_a_padre_borrado. La UNICA relacion vehiculo<->entidad del sistema es la FK vehiculo_historial.entidad_id. No hay columna de entidad ni de linea en vehiculos ni en vehiculos_datos_colectivos. v_vehiculos_lineas_entidades arma vehiculos+entidades+lineas A TRAVES de v_vehiculos_hist_ultimo, que a su vez lee FROM vehiculo_historial. == CODIGO (11 archivos tocan vehiculo_historial) == src/actions/vehiculos.ts · src/lib/historial-vehiculo.ts · src/repositories/vehiculos.ts · src/repositories/parque-movil.ts · src/services/vehiculos.ts · src/types/vehiculos.ts · src/components/ExpedienteForm.tsx · src/app/vehiculos/[id]/page.tsx · src/app/api/vehiculos/[id]/entidad/history/route.ts · src/app/api/vehiculos/[id]/linea/history/route.ts · src/lib/openapi/components.ts == LOS DOS CAMINOS DUPLICADOS QUE ESTE EPIC RETIRA: CONFIRMADOS EN DISCO == ExpedienteForm esta montado en DOS lugares, que es exactamente la duplicacion descrita: - src/app/vehiculos/[id]/page.tsx:921 (la ficha) - src/app/vehiculos/[id]/editar/colectivo/page.tsx:1179 (la pagina de edicion) El layout de la entrada en pantalla ademas esta espejado en src/components/pdf/GenericReport.tsx:107, asi que el PDF se rompe si cambia la forma de la entrada. == FUERA DEL ALCANCE DECLARADO, PERO ES LA MISMA FORMA - DECIDIR SI ENTRA == ChoferExpedienteForm es el analogo para personas y esta montado DOS veces igual: src/app/personas/[id]/page.tsx:580 y src/app/personas/[id]/editar/page.tsx:824. El epic habla solo de vehiculos. Si la unificacion es un principio y no un arreglo puntual, choferes tiene el mismo defecto y conviene decidirlo ahora, no descubrirlo despues. == CONSUMIDOR EXTERNO QUE CONDICIONA EL ORDEN == La API de Rendiciones (MOVILBA-144, shipeada 08-31, key ya minteada) lee v_vehiculos_lineas_entidades. Si el historial queda vacio antes de que la cadena nueva este poblada, esa API responde 200 con entidad y linea VACIAS: no falla, MIENTE. == SIGUE VIGENTE == Baja es un ESTADO, no un borrado: DELETE / DISABLE TRIGGER sobre vehiculo_historial esta prohibido aun con GO.
  • wi-cli-venus priorityChanged · 6w ago
    1
  • wi-cli-venus note · 6w ago
    REGLA FIJADA ANTES DE QUE ARRANQUE LA FASE 2 (la pide db02-mba-l-cc y la comparto; es lo unico de este hilo que se reabre en silencio si se pierde): EL BASELINE SALE DEL LIBRO, NUNCA DE PROYECTAR EL HISTORIAL EXISTENTE. Medido en PROD el 2026-08-31 sobre 2388 vehiculos vivos: 1570 tienen linea en su ultima fila viva de historial; los 818 restantes se parten en dos poblaciones que se cierran por MECANISMOS DISTINTOS: - 648 no tienen NINGUNA fila viva de historial. Cierran por INSERT: el import los trae. Verificado: los 648 estan todos en el libro del 08-31. - 170 si tienen filas vivas pero ninguna con linea_id. Su unica linea vive en filas SOFT-DELETED. NO cierran por insert: cierran porque la proyeccion baseline lee la columna 'Linea' del libro. Verificado: los 170 estan en el libro con esa columna poblada. CONSECUENCIA OPERATIVA: si el backfill de la fase 2 se construye proyectando v_vehiculos_hist_ultimo (o cualquier cosa derivada del historial) en vez del libro, los 170 SE REABREN mientras los 648 quedan arreglados, y un chequeo que cuente 'vehiculos sin linea' vera el numero bajar y no lo notara. El gate post-migracion tiene que contar las DOS poblaciones por separado. Y ojo con el atajo que parece gratis: 'tomar el ultimo linea_id NO NULO' resucita filas borradas en los 170 casos. Se descarto por eso, no por el ordering de la vista. Detalle y verificacion en MOVILBA-166.
  • wi-cli-venus assigned · 6w ago
    coder02-mba-l-cc
  • wi-cli-venus note · 6w ago
    Mediciones de PROD que sobreviven al retiro de MOVILBA-169 parte 1 (db02-mba-l-cc, 2026-08-31, SELECT, 10.78.42.168 PG17.6). Traerlas al diseno del epic. 1. borrado_en esta usado en vehiculo_historial para significar 'periodo RUTAP cerrado': 4225 filas totales, 1740 vivas, 2485 borradas, 2476 de esas con fecha_baja NOT NULL. borrado_por es NULL en las 2485 y no-NULL en 0: ningun usuario las borro, las borro el importer. Es el mismo defecto ya reparado en vehiculos el 08-25 (la baja guardada como borrado_en que escondio 650 vehiculos), NUNCA reparado en vehiculo_historial, y contradice el contrato ya escrito en rutap-full-history-refactor-plan.md ('borrado_en significa borrado de app, no el fin de un periodo RUTAP'). Retirar 169 no elimina el defecto: lo congela dentro del diseno de 167. 2. El criterio de des-ocultado 'borrado_en NOT NULL AND borrado_por IS NULL AND fecha_baja IS NOT NULL' tiene una clausula MUERTA: borrado_por IS NULL no discrimina nada (NULL en las 2485). No protege contra barrer un borrado real de app. El unico discriminante es fecha_baja, que excluye 9 filas - suficientemente pocas para leerlas a mano. Verificar si el path de borrado de la app escribe borrado_por antes de confiar en esa clausula en cualquier diseno futuro. 3. Impacto de des-ocultar las 2476 sobre v_vehiculos_hist_ultimo: 3 vehiculos de 1740 cambian de fila elegida. linea_id cambia en 0. entidad_id cambia en 0. Simulado sustituyendo el set de filas dentro de la propia definicion de la vista, sin escribir. La razon es estructural y hay que conservarla: el ORDER BY de la vista arranca con EXISTS(successor.expte_alta = h.expte_baja) y ESA SUBCONSULTA NO FILTRA borrado_en - ya ve todas las filas borradas. Des-ocultar cambia que filas son ELEGIBLES, no cual gana. Consecuencia: la API de Rendiciones (MOVILBA-144), que resuelve linea y entidad a traves de esa vista, no se mueve. 4. Distincion de diseno que hace falta en 167: almacenamiento vs display. Que las filas del libro esten ocultas con borrado_en es un problema de ALMACENAMIENTO; que el stakeholder no vea periodos pre-handoff en la ficha es un problema de VISTA. Marcar la fila por procedencia (snapshot/origen de import) y filtrar en v_vehiculo_historial satisface el contrato de handoff SIN sobrecargar borrado_en. Si en cambio se sigue ocultando con borrado_en, el contrato queda escrito en la capa equivocada: todo consumidor que filtre correctamente borrado_en IS NULL pierde la historia del libro en silencio, y ningun chequeo de cantidad lo ve. PREGUNTA ABIERTA PARA ELAZAR, decide la forma del filtro: la ficha muestra periodos pre-handoff o el libro RUTAP es el unico lugar donde alguien los lee? Todo lo demas se deriva de esa respuesta.
  • wi-cli-venus note · 6w ago
    1.1b (filtrar filas pre-handoff en la vista de usuario) SE PUEDE CONSTRUIR HOY. Medido por coder02-mba-l-cc contra PROD 2026-08-31, SELECT. EL PROBLEMA QUE PARECIA HABER: la secuencia acordada por db02/db03/pm es 1.1b (filtro de display por provenance) ANTES de 1.1a (des-esconder) y despues 1.2 (import). Pero vehiculo_historial NO TIENE NINGUNA COLUMNA DE PROVENANCE: no existe rutap_snapshot_id, ni rutap_fila_excel, ni ningun marcador de origen. Las 18 columnas son id, vehiculo_id, expte_alta, observaciones, entidad_id, linea_id, estado_id, cambios, creado_en, creado_por, fecha_alta, borrado_en, borrado_por, motivo_id, expte_baja, tramite, fecha_baja, tramite_id. Esas columnas de provenance son parte del diseño de MOVILBA-125 (tabla ancha) y todavia no existen. O sea que 1.1b, tal como esta especificado, dependeria de 125 y toda la cadena quedaria bloqueada detras del refactor de esquema. NO HACE FALTA: EL DISCRIMINADOR YA EXISTE. esta poblado en las 4225 filas (0 nulos) y tiene 9 valores distintos: import-rutap-2026-08-14-prod 2274 system_import 1599 db-mba-l-cc-snapshot5-nuevos-eslabones-2026-08-25 171 import-movilba-19 164 movilba-104-prod 7 import-movilba-18 4 import-movilba-24 3 Elazar (GO 2026-08-25 via db02-mba-l-ca) 2 20394678369 1 4224 de 4225 filas las escribio un importador o una migracion. UNA SOLA fila (creado_por '20394678369', que es un id de usuario) parece escrita por la app. CONSECUENCIA PARA EL CONTRATO DE HANDOFF: 'historial de usuario en cero al handoff' es practicamente el estado actual. Una vista de usuario que muestre solo lo post-handoff mostraria UNA fila en toda la flota. El contrato no exige borrar nada. FORMA RECOMENDADA PARA 1.1b, y no usa creado_por: pre-handoff = . Es una comparacion de fecha, no parseo de strings. Filtrar por seria un filtro por texto libre sobre una columna que nadie garantiza - la trampa de siempre en este proyecto. El marcador propio (rutap_snapshot_id) sigue perteneciendo a MOVILBA-125; para el corte del handoff no hace falta. O sea que 1.1b no depende de 125, y la secuencia 1.1b -> 1.1a -> 1.2 se puede ejecutar sin esperar el refactor de esquema. La decision que falta es de Elazar y ya esta planteada: la ficha muestra periodos pre-handoff o el libro es el unico lugar donde un usuario los lee.
  • wi-cli-venus note · 6w ago
    CORRECCION de formato a la nota anterior: dos fragmentos se perdieron porque compuse el mensaje con backticks en shell (mi propia regla feedback_no_backticks_in_shell_composed_messages). El contenido completo de los dos huecos: 1. Donde dice "EL DISCRIMINADOR YA EXISTE. esta poblado en las 4225 filas": la columna es creado_por. Esta poblada en las 4225 filas, cero nulos, 9 valores distintos. 2. La recomendacion final, que quedo cortada. FORMA RECOMENDADA PARA 1.1b, y NO usa creado_por: pre-handoff = creado_en ANTERIOR al timestamp del handoff. Es una comparacion de fecha, no parseo de strings. Filtrar por creado_por con un LIKE de "import%" seria un filtro por texto libre sobre una columna que nadie garantiza, y es la trampa recurrente de este proyecto: una clave demasiado angosta que parece discriminar. El marcador propio (rutap_snapshot_id) sigue perteneciendo a MOVILBA-125; para el corte del handoff no hace falta. CONCLUSION QUE NO CAMBIA: 1.1b no depende de MOVILBA-125, asi que la secuencia acordada 1.1b luego 1.1a luego 1.2 se puede ejecutar sin esperar el refactor de esquema. La decision que falta sigue siendo de Elazar: si la ficha muestra periodos pre-handoff, o si el libro RUTAP es el unico lugar donde un usuario los lee.
  • wi-cli-venus note · 6w ago
    ORIGEN DE LAS 2476 FILAS OCULTAS - RESUELTO (db02-mba-l-cc, 2026-08-31, SELECT en PROD). No es el importer y no es la app. borrado_en::date = fecha_baja en 2476 de 2476; difieren en 0. Las 2485 filas borradas estan a las 00:00:00; con hora real, 0. Solo 142 timestamps distintos en 14 meses. Un borrado de app estampa now() con hora real: esto es una fecha de NEGOCIO casteada a timestamp, violacion directa de la regla dura 'las columnas de auditoria no son fechas de negocio'. Fuente documentada: docs/migrations/2026-08-14-movilba-19-carga-131-dominios-cerrados.sql, repetida como 'criterio movilba-19' en las migraciones del 08-21. Los tramites cerrados se escribieron con borrado_en = fecha_baja para satisfacer uq_vehiculo_historial_activo, indice unico parcial que prohibia dos filas de historial no borradas por vehiculo. Era la unica forma de cargar la cadena completa bajo esa restriccion. ESE INDICE YA NO EXISTE EN PROD. pg_indexes sobre vehiculo_historial devuelve hoy solo vehiculo_historial_pkey, idx_vehiculo_historial_vehiculo_id, idx_vehiculo_historial_cambios. Se dropeo con la decision de append-only. CONSECUENCIA PARA EL DISENO DE 167: las 2476 no son un defecto del importer a corregir ni una regla que alguien siga sosteniendo - son residuo de una restriccion que ya no esta. El workaround sobrevivio a su motivo. Nada en la base rechazaria hoy varias filas vivas por vehiculo. El importer actual ya es correcto: tools/rutap-sync-prod.sql:477 documenta que NO toca borrado_en al cerrar un periodo. ABIERTO, para coder-mba-l-ca (no es respondible desde la base): 1) escribe algun path de la app borrado_en sobre vehiculo_historial? 2) al soft-deletear, la app puebla borrado_por? decide si borrado_por IS NULL puede significar 'no fue un usuario' - en PROD es NULL en las 2485, audit encontro 53 filas en DEV donde SI esta poblado. 3) asume algo en la app como maximo una fila viva de historial por vehiculo, ahora que el indice que lo garantizaba no esta? Ese es el riesgo real de un des-ocultado y es invisible del lado de la base.
  • wi-cli-venus note · 6w ago
    Traza de codigo de coder-mba-l-ca + verificacion en PROD de db02-mba-l-cc (2026-08-31). Cierra las tres preguntas abiertas de la nota anterior. 1. Ningun path de la app hace UPDATE ni DELETE sobre vehiculo_historial: solo inserts y lecturas. El unico write de borradoEn/borradoPor en vehiculos.ts toca la fila padre de vehiculos. 2. Las 53 filas de DEV con borrado_por poblado NO son borrados de app: vienen del trigger de MOVILBA-91 (docs/migrations/2026-08-26-movilba91-cascade-vehiculo-historial-DEV.sql), que redefine fn_cascade_soft_delete_vehiculo para cascadear el soft-delete de vehiculos a vehiculo_historial copiando NEW.borrado_por. 3. CORRECCION IMPORTANTE: PROD YA TIENE ESA CASCADA. Verificado con pg_get_functiondef: la funcion de PROD referencia vehiculo_historial. La migracion se llama DEV pero el cambio esta vivo en prod. Entonces borrado_por es NULL en las 2485 filas de PROD no porque falte el mecanismo sino porque TODAVIA NO SE DISPARO - ningun vehiculo se soft-deleteo en prod desde que aterrizo. CONSECUENCIA PARA CUALQUIER DISENO DE DES-OCULTADO: la seguridad del criterio es DEPENDIENTE DEL TIEMPO. Un criterio validado hoy contra 2485 filas sin ninguna fila de cascada no queda validado contra la tabla sobre la que va a correr manana. El criterio sobrevive, y la razon hay que dejarla escrita: la cascada solo toca filas WHERE borrado_en IS NULL, o sea la fila ABIERTA, que por definicion tiene fecha_baja NULL. Las filas de cascada son borrado_por NOT NULL + fecha_baja NULL, asi que fecha_baja IS NOT NULL las excluye correctamente cuando aparezcan. fecha_baja es la clausula que sostiene el peso; borrado_por IS NULL es redundante hoy y empieza a trabajar recien el primer soft-delete de un vehiculo en prod. 4. La app asume UNA PROYECCION CORRIENTE, no una fila viva unica: getCurrentHistorial, cambio de estado, ficha/detalle y v_vehiculos_lineas_entidades leen v_vehiculos_hist_ultimo y hacen .limit(1). Los endpoints de historial crudo devuelven todas las filas sin filtrar borrado_en. El gate de regresion es la DETERMINISMO DE LA VISTA, no una restriccion de fila viva unica. Y la vista ES determinista: DISTINCT ON (vehiculo_id) ordenado por vehiculo_id, el EXISTS de sucesor, fecha_alta DESC NULLS LAST, id DESC. id es la PK, asi que el desempate es total: exactamente una fila por vehiculo sin importar cuantas se hagan visibles. Con la simulacion (3 de 1740 cambian, linea 0, entidad 0), los consumidores con .limit(1) quedan cubiertos. ABIERTO Y CHICO: 9 filas de PROD tienen borrado_en con fecha_baja NULL y borrado_por NULL. Coinciden con la FORMA de la cascada pero son anteriores al sello de actor, asi que no son ni periodos cerrados ni borrados atribuibles. Son 9: leerlas una por una en vez de razonar sobre ellas.
  • wi-cli-venus note · 6w ago
    LAS 9 FILAS QUE FALTABAN LEER A MANO: leidas, y ninguna es un borrado de la app. Cierra el ultimo cabo suelto del analisis de MOVILBA-169 / 170. coder02-mba-l-cc, 2026-08-31, PROD, SELECT. Son 9 filas con borrado_en poblado y fecha_baja NULL, o sea las que el predicado "fecha_baja IS NOT NULL" excluye del des-escondido. OCHO DE LAS NUEVE SON CUATRO PARES, uno por dominio, todas escritas por import-rutap-2026-08-14-prod: AD919PL ids 8933 / 8934 AE922FX ids 8247 / 9028 AE971FE ids 8222 / 8972 AE971FF ids 8244 / 8965 Dentro de cada par, fecha_alta y expte_alta son IDENTICOS, pero linea_id y entidad_id NO: una fila resuelve linea 77 / entidad 41 y la otra linea 131 / entidad 65. Es el MISMO tramite importado dos veces y resuelto de dos maneras distintas. Esos cuatro dominios son exactamente los 4 que ya tenia medidos como "tenemos MAS filas que el libro" (el doble import conocido). Queda confirmada la identidad de los dos conjuntos: no son dos problemas, es uno. LA NOVENA ES AG732SW (id 4608, system_import) y es de otra clase: borrado_en 2025-12-12 es ANTERIOR a creado_en 2026-06-22, lo cual es imposible como fecha de auditoria y es otra prueba de que borrado_en esta llevando una fecha de negocio. AG732SW ademas ya esta registrado como roto EN EL LIBRO (alta de la fila vigente anterior a la baja de su propio tramite anterior, chasis partido en dos lineas) y es pregunta abierta a Eugenia, no defecto nuestro. VARIANTE NUEVA DEL MISMO DEFECTO, vale anotarla: en una fila de cada par borrado_en es igual a FECHA_ALTA, no a fecha_baja (8933: borrado 2025-07-24 = fecha_alta 2025-07-24; 8247: 2025-07-08 = 2025-07-08). O sea que borrado_en no se uso solo para "periodo cerrado": tambien se uso para tapar la fila perdedora de un empate de import. La sobrecarga es mas amplia de lo que decia el hallazgo original de db02. CONSECUENCIA: las 9 estan todas explicadas y ninguna es un borrado de usuario ni residuo del cascade. El predicado fecha_baja IS NOT NULL las excluye correctamente. Los 4 pares NO se arreglan des-escondiendo - se arreglan resolviendo el doble import, que es trabajo de MOVILBA-155 y del carril de db03.
  • wi-cli-venus note · 6w ago
    LAS 9 FILAS ANOMALAS - leidas una por una y clasificadas (db02-mba-l-cc, 2026-08-31, SELECT en PROD). Decision de db03-mba-l-ca: set manual explicito bajo 167/166, NO candidatas a des-ocultado masivo, NO entran al write set de MOVILBA-155, NO son el gate de chasis de MOVILBA-89. Son una TERCERA categoria: ni periodos cerrados (fecha_baja NULL) ni borrados (vehiculo padre VIVO en los 5 casos, borrado_por NULL en las 9). Ninguna cascada ni ningun usuario las explica. 5 vehiculos. AD919PL, AE922FX, AE971FE, AE971FF con 2 filas ocultas cada uno; AG732SW con 1. Las 8 filas de los cuatro primeros son PARES con el mismo expte_alta y la misma fecha_alta, que difieren solo en linea/entidad: AD919PL tiene el par identico (linea 131 / entidad 65); AE922FX, AE971FE y AE971FF tienen una fila en linea 77 / entidad 41 y otra en linea 131 / entidad 65, mismo expediente, misma fecha_alta, ninguna cerrada. Es la forma Tipo-B de coder02 (fila importada dos veces, la copia vieja nunca removida) salvo que aca se ocultaron LAS DOS copias en vez de limpiar una. AG732SW es otro caso: fila unica, expte_alta VACIO, estado 116 coincidiendo con su ficha. Composicion por vehiculo (vivas / cerradas / anomalas): AD919PL 1/3/2 · AE922FX 1/4/2 · AE971FE 1/3/2 · AE971FF 1/4/2 · AG732SW 1/2/1. Todos conservan exactamente una fila viva, asi que hoy no se renderiza nada mal: la anomalia es invisible y solo apareceria en un des-ocultado. POR QUE IMPORTA MAS ALLA DE LAS 9: des-ocultar por fecha_baja IS NOT NULL las deja correctamente ocultas, o sea que el criterio es seguro. Pero eso mismo significa que un des-ocultado masivo dejaria residuo de import duplicado invisible para siempre - exactamente el modo de falla de la regla snapshot-no-ledger: una fila que nadie puede ver sobrevive a todo import futuro y ningun chequeo de cantidad la encuentra. Hay que resolverlas como duplicados, no conservarlas ocultas.
  • wi-cli-venus assigned · 4w ago
    coder03-mba-l-cc / coder
  • coder03-mba-l-cc assigned · 2w ago
    db03-mba-l-cc
  • coder03-mba-l-cc assigned · 2w ago
    db04-mba-l-ca
  • db04-mba-l-ca statusChanged · 1w ago
    No implementation started; epic remains broad and child MOVILBA-166 is blocked. Keep backlog until a scoped next child is selected.
epic
6w ago by wi-cli-venus
1w ago