basquetWi + New ticket
movilba MOVILBA-767

Decidir la vigencia del catálogo categoria_regulatoria antes de cambiar su resolver

Blocked normal unassigned ⛔ Waiting for Elazar's catalog-policy decision: both bases have 0 live categoria_regulatoria options, and filtering the writer now would break existing PROD flows. PM carries the question; no resolver edit authorized.

Decision de Elazar pendiente; NO cambiar src/repositories/vehiculos.ts:299-322 por el criterio original. db03 midió en PROD y DEV los mismos 10 valores vehiculo/categoria_regulatoria, 10/10 soft-deleteados desde 2026-07-02 y 0 vivos; v_opciones devuelve 0. Los 5558 períodos PROD con M3/id72 son TODOS origen=import, no ejecuciones observadas del resolver; DEV sí tiene 2 períodos app M3/id72. El resolver de escritura actual consulta public.opciones sin filtro; sus llamadas de alta, historial, edición y transferencia pueden elegir/reutilizar un ID retirado. Filtrar por borrado_en ahora haría fallar altas y las ediciones/transferencias del libro PROD y vaciaría el selector; por eso el criterio anterior 'sólo elegir opción vigente' queda RETIRADO. Existe FK compuesta (carroceria_categoria_id, grupo, campo) a opciones en ambas bases, pero no impone vigencia. La atribución de una excepción deliberada a MOVILBA-546 en route.ts:206 no está respaldada por ese item (es un ticket PDF), así que la divergencia respecto de docs/reference/opciones-catalogo.md requiere decisión explícita. Preguntas: ¿debe categoria_regulatoria volver a tener opciones vivas? Si sigue retirada, ¿se permite al escritor reutilizar esos IDs y con qué regla de admisión para un colectivo? La respuesta debe distinguir catálogo de dato histórico y servir como nuevo criterio de aceptación antes de cualquier código o datos. No hubo DDL ni escritura por este item; el censo de db03 fue SELECT-only. MOVILBA-400 replica el resolver instalado sólo para medir chasis_marca y no decide esta política.

Sub-tickets

No sub-tickets.
+ Add sub-ticket

Activity

  • coder04-mba-l-ca created · 1w ago
  • db03-mba-l-cc note · 1w ago
    db03-mba-l-cc, 2026-10-08. MEASUREMENT ONLY, zero writes in either base. Instrument tools/movilba-767-censo-categoria-regulatoria.sql sha256 ed202fde, report docs/reference/movilba-767-censo-categoria-regulatoria.md sha256 62bae53f. Both are untracked and currently parked in stash@{0}^3 (38b72a59, coder03 park-765-prod-leg of 19:46:08 ART) - they are not in the worktree right now. NOT a DEV finding. PROD is in the same state row for row: the same 10 ids, the same valor_opcion, the same borrado_en 2026-07-02 04:06:53.288668 and the same borrado_por 20247094211 in movilba and movilba_dev. 10 of 10 soft-deleted, 0 live, in both. vehiculo/marca_motor was soft-deleted in the same instant by the same user, 12 of 12, in both. Control for the zero: the same predicate over the other campos of grupo vehiculo does NOT return zero - motivo_asignacion_linea 6/6 live, motivo_transferencia 6/6, estado 2 live. A predicate-made zero would have swept those too. Positive control for the verdict: the resolver's exact SELECT against TEXTO-QUE-NO-EXISTE-MB749X returns 0 rows and says THROWS in both bases, while L1 says RESOLVES. The resolver at src/repositories/vehiculos.ts:311 is LIVE in PROD, not latent. PROD has exactly one shape: 5558 rows, origen=import, texto M3, carroceria_categoria_id 72. M3 resolves to one row, id 72, soft-deleted. So it resolves on every colectivo create/edit/transfer in PROD and writes a soft-deleted id - which is the id already stored, so observable behaviour does not change. It never throws on this catalog, because all ten values return exactly one row. The item's own acceptance criterion, applied literally, BREAKS PROD. Live options number zero, so a resolver requiring borrado_en IS NULL would throw on the entire PROD population, not on an edge case. The same filter would leave the dropdown with nothing to offer and break both validators in src/services/vehiculos.ts (:408, :838). The item says it does not assert such a period was ever persisted; the measurement closes that the other way - it is persisted in 100% of PROD, and it is what MOVILBA-546 chose deliberately for a retired catalog that is still the authoritative source of captured values. All five surfaces of this field read opciones unfiltered, consistently: dropdowns/route.ts:206 (carrying the MOVILBA-546 comment that decides it), services/vehiculos.ts:408 and :838, repositories/vehiculos.ts:311 and :511. The filtered path, OpcionesRepository.findByCategory over v_opciones, is NOT reachable for this field: its only caller is services/opciones.ts:126, which addresses through CATEGORY_MAPPINGS at :44-53, and that map has eight entries, none of them categoria_regulatoria - verified by reading the whole map, not by grepping for an absence. v_opciones itself returns 0 rows for this field (body read with pg_get_viewdef in both bases; control: 2, 6 and 6 rows for estado, motivo_asignacion_linea, motivo_transferencia). DEV population, which PROD does not have: 2 app rows M3 with id 72, 12 app rows M3 with id NULL, 1 app row L1 with id NULL - the MOVILBA-709 legacy case the resolver exists for - and 154 app rows whose texto is NULL. Measured NULL vs empty string explicitly, because the resolver treats them differently: texto == null returns NULL without querying, while an empty string would query and throw. No row in either base holds an empty string. So what is left to decide is not the resolver's predicate but the catalog: whether categoria_regulatoria should have live rows at all. That is a data change on a retired catalog, with marca_motor in the same state and deleted in the same instant. A decision, not an obvious fix - I am not proposing DDL or a data change here. Lateral: rutap.vehiculo_historial_normalizado.carroceria_categoria_id has NO FK to public.opciones in either base, although thirteen sibling columns of the same table do. It is one of the FK-less columns in MOVILBA-738's scope. No damage measured today - zero stored ids fail to resolve to an option of the group, in both bases. PENDING on the report file: one section stating the acceptance-criterion finding above is drafted but NOT yet in the .md, because the park removed the file from the worktree mid-edit. It goes in once coder03 restores stash@{0}; this note carries the finding in full in the meantime. SIN EJERCITAR: no live HTTP request against the colectivo add/edit form, so the dropdown actually painting the ten labels is inferred from the select at route.ts:206 plus the catalog census, not seen on screen. No write was executed - that the resolver writes 72 is measured as the result of its exact SELECT, not observed in an INSERT. vehiculos_datos_colectivos has no regulatory-category column and was not censused. Why the two catalogs were soft-deleted on 2026-07-02, and who 20247094211 is, was not investigated.
  • db03-mba-l-cc note · 1w ago
    db03-mba-l-cc CORRECTION to my note of 22:47:14Z. Three claims there were wrong or over-stated; the rest stands. New pins RETIRE the old ones: instrument sha256 9c855f46 (was ed202fde, now with the section-E fix below), report sha256 16020788 (was 62bae53f). Both files are back in the worktree - coder03 restored the park. Still zero writes in either base. 1. WRONG, and it is the mother shape of this project: I wrote that rutap.vehiculo_historial_normalizado.carroceria_categoria_id has NO FK to public.opciones and is one of MOVILBA-738's FK-less columns. It has the STRONGEST FK in the schema - vh_norm_categoria_catalogo_fk, FOREIGN KEY (carroceria_categoria_id, carroceria_categoria_grupo, carroceria_categoria_campo) REFERENCES opciones(id, grupo_nombre, campo_nombre) - in BOTH bases. My census filtered array_length(conkey,1)=1, so it structurally could not see a composite FK: a key too narrow to see the distinguishing field, reporting 'no FK' about the best-constrained column there is. The column is NOT in 738's scope. Instrument corrected: section E no longer filters by column count, prints n_cols, and carries a control that the composite branch is not empty - 38 single-column FKs and 1 three-column, identical in both bases. The same narrow filter is at tools/movilba-371-censo-unidad-propulsora.sql:49, so that census shares the hole; for unidad_propulsora the measured result does not change, since none of its columns carry a composite FK, but the instrument's limit is now written down in the 371 report's successor section here. What the composite FK does NOT do: require the option to be live. 5558 rows in PROD and 5560 in DEV satisfy it today pointing at a deleted option, measured by joining on all three columns. 2. OVER-STATED: 'the resolver is LIVE in PROD' and 'persisted in 100% of PROD' conflated two writers. PROD has 5558 rows in rutap.vehiculo_historial_normalizado and ALL of them are origen='import'; there is not one origen='app' row. So the 5558 rows carrying id 72 were written by the importer/projector and the resolver has ZERO executions in PROD history. The new period the item is about exists only in DEV - the 2 app rows with M3/72. Correct reading: the resolver is reachable on the next PROD create/edit/transfer and can only resolve to deleted ids, because live options number zero. The item's 'no se afirma que ya haya persistido tal periodo' is therefore TRUE for PROD and false for DEV. Per-path scope, which I had flattened: on edit (:1186, :1392) and line transfer (:1594) the resolved id is the 72 already stored, so the stored value does not change. On create (:967) it writes whatever the form picked, any of the ten - DEV's app row with L1, a low-displacement motorcycle category, on a colectivo form, is that case and nothing filtered it. The criterion-breaks-PROD finding is unaffected: every PROD colectivo edit and transfer inherits 72, so a resolver requiring borrado_en IS NULL throws on the whole population, not an edge case. 3. MISATTRIBUTED: I repeated the code comment's claim that MOVILBA-546 deliberately chose to include the retired catalog's rows. bwi show MOVILBA-546 --full does NOT record that decision - 546 is the PDF printing 'Categoria de la Carroceria: No especificada', reported by Eugenia, closed 2026-10-05, and its description is about the PDF and MOVILBA-505. Nothing in it about filtering borrado_en on a write path. So the resolver's unfiltered predicate is an UNDOCUMENTED divergence from docs/reference/opciones-catalogo.md's 'choose ids from v_opciones', not a settled exception. The dropdown half of that comment defends itself (reading the label of an already-stored id is the legitimate exception); extending it to the writer is what nobody decided. That is a rule question for Elazar, not something I settle. Unchanged and now read in full in BOTH bases, not through a truncated pipe: the catalog is identical (same 10 ids, same borrado_en 2026-07-02 04:06:53.288668, same borrado_por 20247094211, 10 of 10 soft-deleted, 0 live); marca_motor 12 of 12 in the same instant by the same user; the live-field control (motivo_asignacion_linea 6/6, motivo_transferencia 6/6, estado 2); v_opciones' body carries WHERE borrado_en IS NULL and returns 0 rows for this field against a control of 2/6/6, the two bases' bodies differing only in the table prefix each deparser prints (17.6 vs 15.17); findByCategory is unreachable for this field because CATEGORY_MAPPINGS (src/services/opciones.ts:44-53) has eight entries and none is categoria_regulatoria, read whole rather than grepped for absence; the resolver's exact SELECT says THROWS on a nonexistent text and RESOLVES on L1, in both bases; no row in either base holds an empty string for the text. What is left to decide is the catalog, not the predicate: whether categoria_regulatoria should have live rows, with marca_motor in the same state. A data decision, not an obvious fix, and I am proposing no DDL and no data change. SIN EJERCITAR, added to the earlier list: no live HTTP request against the colectivo forms; no write executed; no search for a path reaching findByCategory from outside src/ (a script, a job); and the composite-FK correction covers this column only - it does not assert that no other column was misclassified by the same narrow filter in earlier censuses.
  • coder04-mba-l-ca titleChanged · 1w ago
    Decidir la vigencia del catálogo categoria_regulatoria antes de cambiar su resolver
  • coder04-mba-l-ca descriptionChanged · 1w ago
    was: src/repositories/vehiculos.ts:299-322 categoriaCarroceriaIdParaPeriodo elige un ID a guardar en rutap.vehiculo_historial_normalizado.carroceria_categoria_id. Consulta public.opciones sin filtrar borrado_en y exige una sola fila; los cuatro call sites de alta/historial/edición (aprox. 967, 1186, 1392, 1594) almacenan el resultado. docs/reference/opciones-catalogo.md exige elegir IDs desde v_opciones, que excluye soft-deleteados; la lectura de la etiqueta de un FK ya almacenado es una excepción distinta. db04 midió en DEV 10 opciones vehiculo/categoria_regulatoria, todas soft-deleteadas: el resolver actual puede aceptar una de ellas; no se afirma que ya haya persistido tal período. Separado de MOVILBA-400, cuyo verificador replica intencionalmente el resolver instalado para medir chasis_marca. Criterio: el writer sólo elige una opción vigente, rechaza texto/ID sin opción vigente y prueba la rama contra catálogo borrado sin modificar datos existentes. No DDL ni arreglo de las 10 opciones DEV sin decisión de datos.
  • coder04-mba-l-ca blocked · 1w ago
    Waiting for Elazar's catalog-policy decision: both bases have 0 live categoria_regulatoria options, and filtering the writer now would break existing PROD flows. PM carries the question; no resolver edit authorized.
  • coder04-mba-l-ca note · 1w ago
    Attribution trace, read-only: src/app/api/dropdowns/route.ts:207-208 was introduced by commit e11c2188d, whose message cites MOVILBA-546 for required catalog-backed category input and persistence; MOVILBA-546 event 2026-10-05T19:15Z explicitly says service validation included retired category rows. That supports attribution of the IMPLEMENTED route branch to 546. It does not show an Elazar decision that a fully retired catalog remains authoritative indefinitely: the 546 decision event requires a catalog category and says no hardcoded M3/backfill, while the catalog-lifecycle/admission rule remains blocked on this 767 decision. The comment overstates policy authority even though its implementation history is real; propose replacing that policy claim with factual behavior plus 767 pending, without changing the query.
  • coder04-mba-l-ca progress · 1w ago
    Read-only trace found commit e11c2188d and MOVILBA-546's 2026-10-05T19:15Z event supporting that 546 IMPLEMENTED category selection including retired rows. No recorded Elazar decision declares the retired catalog authoritative indefinitely. Comment-only correction in src/app/api/dropdowns/route.ts SHA256 1bdd983a20fa8cfa433131ed077295e779958ae813f4d7bf2b5a9d4c2af17b95: names 546 as implementation history and 767 as the open new-selection policy. Query and behavior unchanged. Audit verdict owed on this hunk; 767 remains blocked on Elazar's catalog decision.
bug
1w ago by coder04-mba-l-ca
1w ago