basquetWi + New ticket
movilba MOVILBA-99 · child of MOVILBA-125 RUTAP full-history refactor Backlog

Leer el historial como intervalos de validez y no como altas y bajas: es lo que habilita los reportes que pide Eugenia

Done high cmcoder04-mba-l-ca

Elazar, 2026-08-20 15:07: 'lo de alta/baja es un desafio, y ella necesita reportes que muestren lo que necesita cuando se lo piden; pero alta/baja basicamente no es cierto'. LO QUE PASA, dicho por la propia Eugenia en el chat (14:38, /resource/movilba/import-reports/2026-08-20-chat-stakeholder.txt): 'ponemos nosotros alta y baja para poder hacer el registro de desde cuando tuvo un mdvr con 566 y hasta cuando lo tuvo asi... pero es meramente por trazabilidad'. O sea que en el libro alta/baja NO son eventos de servicio del vehiculo: son las PUNTAS DE UN INTERVALO DE VALIDEZ. Cada fila dice 'este vehiculo tuvo ESTE conjunto de valores desde fecha_alta hasta fecha_baja'. La etiqueta tramite es decoracion sobre eso, y por eso es inconsistente (MOVILBA-96: dos transferencias igualmente genuinas, una etiquetada Alta y la otra Modif) y por eso no existe ninguna fila BAJA. PROPUESTA DE MODELO, que no requiere cambiar el dato ni pelearse con las etiquetas: leer vehiculo_historial como una TABLA TEMPORAL. El periodo es [fecha_alta, fecha_baja), la fila vigente es la que tiene fecha_baja IS NULL, y el contenido del periodo es el snapshot mas el diff que ya calculamos en MOVILBA-95. Con eso los reportes que ella pide dejan de necesitar interpretar alta/baja: 'estado del vehiculo AL 15/08/2026' es la fila cuyo periodo contiene esa fecha; 'que vehiculos cambiaron de interno entre X e Y' es filtrar los tramites cuyo cambios tiene la clave nro_interno con fecha en el rango; 'desde cuando tuvo el mdvr 566 y hasta cuando' es exactamente el periodo de la fila que lo tenia. Es literalmente la pregunta que ella describio para justificar por que inventaron el alta/baja. DEPENDENCIAS: MOVILBA-83 es prerequisito real, porque hoy el fin del periodo vive en borrado_en y no en fecha_baja - o sea que la mitad del intervalo esta en la columna equivocada y ningun reporte temporal se puede escribir prolijo hasta que se mueva. MOVILBA-97 (subtipo de modificacion derivado del diff) es lo que hace filtrable el 'que cambio'. NO tocar las etiquetas del libro: son de Eugenia, y el modelo temporal no las necesita.

Sub-tickets — 3/3 done

MOVILBA-268 Done high
cmcoder04-mba-l-ca
MOVILBA-441 Done high
cmcoder03assistant-mba-l-ca
+ Add sub-ticket

Activity

  • wi-cli-venus created · 2026-08-20
  • wi-cli-venus statusChanged · 2026-08-20
  • wi-cli-venus note · 2026-08-21
    DESBLOQUEADO en lo que hace a datos de prod. MOVILBA-83 era el prerequisito duro porque el fin del periodo vivia en borrado_en; medido hoy en prod el dano real son 8 filas, no 2309, y en las 2307 filas que tienen las dos columnas borrado_en::date = fecha_baja exacto. O sea que el lector de intervalos puede tomar [fecha_alta, fecha_baja) directo. DOS ADVERTENCIAS ANTES DE EMPEZAR, las dos de db02 y las dos sobre el entorno de desarrollo: (1) DEV tiene 100 filas con el dano contra las 8 de prod, asi que construir y probar 99 contra dev va a chocar con periodos rotos que prod no tiene - si un caso falla en dev, medirlo en prod antes de tratarlo como bug del lector. (2) Los dos entornos usan convenciones OPUESTAS para las filas cerradas: prod tiene 137 filas con fecha_baja poblada y borrado_en NULL, dev tiene 9. Por eso el lector no puede inferir el fin del periodo desde borrado_en en NINGUNA de las dos direcciones. Sigue pendiente que MOVILBA-95 lleve el backfill de 'cambios' a prod (hoy 45 de 4052) o los reportes de 'que cambio' no tienen de donde leer.
  • wi-cli-venus parentChanged · 7w ago
    parent=MOVILBA-125
  • wi-cli-venus note · 7w ago
    AUDIT 2026-08-25: la porcion de UI de este item (mostrar 'Vigente: desde/hasta' en pantalla) fue REVERTIDA hoy por el patch de compact-history de coder-mba-l-ca, por pedido directo de Elazar via db02 - el timeline visible ya no infiere ni muestra periodo, solo trámite/fechas/cambios detectados + detalle colapsado. Esto NO invalida el resto del item: la lectura de vehiculo_historial COMO intervalos de validez sigue siendo la logica de backend que necesitan los reportes de Eugenia (estado a una fecha, que cambio entre X e Y) - ver docs/design/rutap-full-history-refactor-plan.md seccion 'Compact history timeline after the refactor'. Alcance de UI y alcance de modelo de lectura son cosas distintas; solo el primero cambio hoy.
  • wi-cli-venus assigned · 7w ago
    coder02-mba-l-cc / coder
  • wi-cli-venus progress · 7w ago
    IMPLEMENTADO Y COMMITEADO (coder02-mba-l-cc, 2026-08-28, commit 3fabec37, rama dev, NO deployado). El lector de vehiculo_historial.cambios se retira y el diff se calcula comparando cada fila con la anterior del mismo vehiculo, que es lo que ordena docs/design/rutap-full-history-refactor-plan.md ('calculate typed differences by comparing each explicit historical snapshot to its preceding snapshot', 'do not leave a compatibility JSON reader'). MOVILBA-95 ya estaba cerrado a favor de ese plan, asi que no se repone el backfill. DEFECTO QUE ESTO ARREGLA, medido en PROD hoy y que solo existia en prod: cambios esta vacio en las 4225 filas de historial (4180 NULL + 45 objeto vacio '{}'), asi que inferirEvento devolvia 'Sin cambios detectados' en las 2485 filas no-primeras SIEMPRE y getCambios devolvia [] siempre - la ficha y el PDF no mostraban ningun cambio en produccion. En DEV la columna si esta poblada, asi que era invisible salvo midiendo contra prod. OJO: el ticket citaba '45 de 4052 filas con cambios poblado' - esas 45 son el objeto VACIO, no contenido; la cobertura real era CERO, no parcial. CONTROL POSITIVO del reemplazo, mismas 2485 filas no-primeras de prod: entidad difiere en 127, linea en 294, estado en 1440, observaciones en 1004, union 1928 filas con contenido real (78%) contra 0 del lector viejo. Las 557 restantes son tramites donde solo cambio expediente y fecha (que ya se muestran como datos del renglon) y ahora se rotulan 'Tramite sin cambios de asignacion' en vez de leerse como falla de deteccion. motivo_id NO entra: medido, no difiere en ninguna de las 2485. Se compara por ID y se muestra la etiqueta (regla opciones). esPrimeraFilaDelVehiculo pasa a filaAnterior y sigue filtrando por vehiculo para no comparar contra el tramite de otra patente de la misma cadena de chasis. LIMITE DECLARADO, escrito en el codigo: vehiculo_historial NO tiene columnas de equipamiento - verificado sobre el esquema de prod, las unicas columnas de negocio que varian por tramite son entidad, linea, estado y observaciones. Las preguntas de Eugenia del tipo 'desde cuando tuvo el mdvr 566 y hasta cuando' NO se pueden contestar desde esta tabla y necesitan la tabla ancha de MOVILBA-125. Lo que SI queda contestable hoy: 'estado del vehiculo AL <fecha>' (la fila cuyo periodo contiene la fecha) y 'que vehiculos cambiaron de empresa/linea entre X e Y'. DEPLOY PENDIENTE: bloqueado por el drift de esquema dev-vs-prod (drizzle/schema.ts regenerado contra dev, 7 errores de typecheck), PM decidio opcion A y db03 tiene la DDL.
  • wi-cli-venus progress · 6w ago
    CORRECCION DE ESTADO (coder02-mba-l-cc, 2026-08-31). La nota del 2026-08-28 dice 'DEPLOY PENDIENTE'; esta desactualizada. El cambio SHIPEO a dev el 2026-08-28 como 0d2202e2 / v5.4.73, subido por coder-mba-l-ca, no por mi. Se construyo dos veces: coder-mba-l-ca y yo implementamos el mismo fix en paralelo porque ninguno de los dos verifico que el item estuviera sin reclamar. Diffeados, funcionalmente identicos; me retire y quedo el suyo. El item NO se cierra con eso: lo shipeado es el lector de diff por filas adyacentes, que es una PARTE. Lo que sigue abierto es el modelo temporal en si - leer vehiculo_historial como [fecha_alta, fecha_baja) para contestar 'estado del vehiculo AL <fecha>' y 'que cambio entre X e Y' sin interpretar las etiquetas alta/baja del libro. Limite ya declarado en el codigo y que no cambia: vehiculo_historial no tiene columnas de equipamiento, asi que 'desde cuando tuvo el mdvr 566' no se contesta desde esta tabla y depende de la tabla ancha de MOVILBA-125 (el padre de este item).
  • wi-cli-venus progress · 6w ago
    coder02 2026-09-04: the diff half of this item is delivered by MOVILBA-204 (v5.4.150..157: wide-table reader, each row = one validity period fecha_alta..fecha_baja, typed diff against the previous row of the chassis chain). What remains here is only the report surface Eugenia asked for (interval queries per equipment: 'desde cuando tuvo MDVR X hasta cuando'), which has no ticket text yet; it reads v_vehiculo_historial_actual / the wide table, never legacy.
  • wi-cli-venus decision · 5w ago
    Respuesta de Eugenia, tracker 2026-09-10 14:41, pregunta 3: Actualmente RUTAP toma únicamente BAJA, independientemente del motivo operativo (mantenimiento, guardado u otro). Esto confirma que la proyección del importador debe seguir siendo binaria ALTA/BAJA y no derivar estados intermedios. Fuente: /data-lezama/movilba/import-reports/2026-09-10-1441-todo-rutap-importacion-prestaciones.xlsx.
  • wi-cli-venus decision · 5w ago
    Respuesta de Eugenia, tracker 2026-09-10 14:41, pregunta 5: una modificación es un único expediente con dos operaciones; el cierre del período anterior y el alta del nuevo período usan la misma fecha. La implementación y los gates de intervalos deben hacer ambas operaciones atómicamente. Fuente: /data-lezama/movilba/import-reports/2026-09-10-1441-todo-rutap-importacion-prestaciones.xlsx.
  • wi-cli-venus assigned · 4w ago
    coder03-mba-l-cc / coder
  • coder03assistant-mba-l-ca progress · 3w ago
    coder03assistant-mba-l-ca | 2026-09-24 04:00:26 ART dev 7d299b6a; main 721b9eb8: normalized-history interval readers exist, while Reporte 1/2/5 child contracts remain in progress (441/442/268). No completed report-surface gate; leave epic open.
  • coder03-mba-l-cc assigned · 2w ago
    coder03assistant-mba-l-ca
  • coder03assistant-mba-l-ca progress · 2w ago
    coder03assistant-mba-l-ca | 2026-10-01 23:48 ART. Dependency check: MOVILBA-97 is done. MOVILBA-83 described public.vehiculo_historial.borrado_en, but DB verification in MOVILBA-83 says public.vehiculo_historial is absent in DEV and PROD; that legacy-table issue is not a prerequisite to read normalized periods. Canonical rutap.vehiculo_historial_normalizado carries fecha_alta/fecha_baja; report 1 MOVILBA-441 reads those fields per history row. No active predecessor ID remains; report products are tracked separately by MOVILBA-441, -442 and -268, and the broader canonical-history work is MOVILBA-125. This is code/BWI evidence only; no DB query or report behavior exercised in this pass.
  • coder03assistant-mba-l-ca blocked · 2w ago
    Waiting on report-surface work in MOVILBA-441 (historical export), MOVILBA-442 (current-fleet export), and MOVILBA-268 (monthly liquidation) to deliver/evaluate interval reporting. MOVILBA-97 is done, but its subtype filter does not deliver the temporal report surfaces this item requires.
  • coder03assistant-mba-l-ca unblocked · 1w ago
    coder03assistant-mba-l-ca | 2026-10-05 15:03 ART. Reclassified as the interval-reporting umbrella, not a dependency blocker. Linked report surfaces as children: MOVILBA-268 monthly liquidation, MOVILBA-441 historical export, MOVILBA-442 current-fleet export; MOVILBA-97 is done and does not gate this parent.
  • coder03-mba-l-cc assigned · 1w ago
    researcher-mba-l-cc / solo
  • researcher-mba-l-cc statusChanged · 1w ago
    researcher-mba-l-cc 2026-10-08T11:45:51-03:00 claiming per coder03's reassignment: spec the interval model against the current vehiculo_historial_normalizado shape (MOVILBA-83 done — fecha_alta/fecha_baja are real date columns, distinct from borrado_en), identify the current-period resolvers, no code.
  • researcher-mba-l-cc note · 1w ago
    researcher-mba-l-cc 2026-10-08T11:45:51-03:00 — interval-model spec, read-only, no code. Evidence: drizzle/schema.ts view definitions (static), git log for MOVILBA-83's close. CURRENT SHAPE (MOVILBA-83 done): rutap.vehiculo_historial_normalizado has fecha_alta/fecha_baja as real `date` columns, fully separate from borrado_en/borrado_por (app soft-delete, unrelated meaning since 83). The half-open interval the ticket proposes — [fecha_alta, fecha_baja), vigente row = fecha_baja IS NULL — is already directly representable with ZERO schema change. This confirms the ticket's own claim ("no requiere cambiar el dato"). WHAT IT ENABLES (the three report shapes Eugenia described, now literal queries instead of alta/baja interpretation): 1. "Estado del vehiculo AL <fecha>": `WHERE fecha_alta <= :f AND (fecha_baja IS NULL OR fecha_baja > :f)` — one row, no tramite-label logic needed. 2. "Que vehiculos cambiaron <campo> entre X y Y": filter rows whose `cambios` jsonb (already computed per MOVILBA-95/97) has the key, with fecha_alta in [X,Y) — the normalizacion/diff machinery already exists, this is a WHERE clause away. 3. "Desde cuando tuvo <valor> y hasta cuando": literally `(fecha_alta, fecha_baja)` of the row carrying that value — no derivation, it's the row. None of these need vehiculo_historial_normalizado changed; they need ONE canonical "vigente" resolver, which does not exist today (see below). THE FOUR CURRENT-PERIOD RESOLVERS FOUND (independent tie-break algorithms over the same table, confirmed by reading each view body in schema.ts — this is the actual blocker for "report X" being reliable, not the fecha_alta/fecha_baja shape): 1. v_vehiculos_hist_ultimo (schema.ts:3185): window function, `ROW_NUMBER() OVER (PARTITION BY vehiculo_id ORDER BY GREATEST(fecha_baja,fecha_alta) DESC, fecha_alta DESC, origen='app' DESC, fecha_baja IS NULL DESC, id DESC)`, rank=1. Feeds vehiculo ficha's `current_period`. 2. The unnamed vehiculo_id-level resolver at schema.ts:3201 (`latest_alta`/`latest_baja` CTEs, DISTINCT ON): a SEPARATE tie-break (`fecha_alta DESC, origen='app' DESC, creado_en DESC, id DESC` for alta; an independently-ordered CTE for baja), producing its own `estado_ciclo_actual` ALTA/BAJA label — can disagree with #1 on which row is "current" because the ORDER BY is not the same formula. 3. The inline LATERAL subquery `cur_fa` embedded directly in the main vehiculo-ficha view (schema.ts:2313): `ORDER BY (fecha_baja IS NULL) DESC, fecha_baja DESC NULLS LAST, fecha_alta DESC NULLS LAST, rutap_fila_excel DESC NULLS LAST, id DESC LIMIT 1` — a THIRD independent formula, used only to populate `fecha_ultima_actualizacion`/observaciones on that one view, not reusable. 4. v_vehiculos_entidad_actual / v_vehiculos_linea_actual (referenced by name in #1 and #3's host views, not re-read this pass — flagged in [[reference_el_periodo_vigente_tiene_cuatro_resolutores_y_arreglar_uno_no_alcanza_a_los_otros]] from an earlier session) — per-field 'current' resolvers for entidad/linea specifically, separate from the vehicle-level ones above. None of the four share a single ORDER BY; each was written independently against the same ambiguity (multiple open periods, app vs import rows, ties on date). This is why MOVILBA-69's dedupe defect could recur per-resolver even if fixed once. WHAT THE FOUR WOULD BECOME under the proposed interval model: a single canonical view, e.g. `v_vehiculo_historial_vigente`, with ONE tie-break formula (closest candidate from the four above: #1's, since it already handles app-vs-import precedence and multi-period ties explicitly) exposing `(vehiculo_id, fecha_alta, fecha_baja, <snapshot columns>)`. #2, #3 and the entidad/linea resolvers in #4 would become thin SELECTs against that one view filtered/joined by field, instead of each re-deriving current-row logic. This does not require touching vehiculo_historial_normalizado itself — it is a view consolidation, which is why it is in scope as a spec and not a migration. NOT DONE: did not re-read v_vehiculos_entidad_actual/v_vehiculos_linea_actual bodies this pass (budget), and did not touch the three closed children (268/441/442) to check whether any of them already built a de-facto fifth resolver — flag if audit wants that checked.
  • researcher-mba-l-cc blocked · 1w ago
    researcher-mba-l-cc 2026-10-08T11:45:51-03:00 spec posted to bwi. Parked: consolidating the 4 resolvers into 1 canonical view is a design decision (which tie-break formula wins) for Elazar, not mine to pick.
  • coder03-mba-l-cc assigned · 1w ago
    coder04-mba-l-ca / coder
  • coder03-mba-l-cc note · 1w ago
    Elazar GO 2026-10-08 12:50 ART (CLI, nqla 5a): consolidate the four current-period resolvers into ONE view/function, all four surfaces (ficha query, edit form, export view, /api/v1) switched in one ship. db03 ships the view (PROD then DEV, after 123), coder04 switches the four callers against it. Researcher's resolver inventory in this item is the spec.
  • db03-mba-l-cc note · 1w ago
    db03 2026-10-09: rutap.v_vehiculo_historial_actual is already the canonical current-period view in the live DB - researcher's spec (read drizzle/schema.ts, stale DEV mirror) wrongly described resolvers #1 (v_vehiculos_hist_ultimo) and #3 (cur_fa in v_vehiculos_detalle) as independent; both already read it directly on PROD/DEV. columnasDesdeFicha() (edit form) also already reads it, with an explicit code comment against adding a second tie-break. v_vehiculos_ciclo_actual (#2) is NOT a duplicate - it answers lifecycle ALTA/BAJA state, has its own dedicated test. Unverified: getRutapHistorialByChain's chain-pick ordering vs the canonical current_rank formula - possible real 4th path, not yet compared. v_vehiculos_export_periodo_actual has zero src/ consumers (looks dead). Full detail DM'd to coder03+coder04 2026-10-09.
  • coder04-mba-l-ca progress · 1w ago
    2026-10-09 SELECT-only comparison of the ficha/edit DTO's latest getRutapHistorialByChain row (buildChainEvents business order: fecha_alta ASC NULLS LAST, rutap_fila_excel-or-id ASC; consumer reverses and takes last) against rutap.v_vehiculo_historial_actual. PROD movilba / svc_nextjs: 2424 vehicle keys, 0 selected-row ID disagreements; 0 fecha_alta and 0 fecha_baja differences. DEV movilba_dev / movilba_user: 2469 keys, 17 selected-row ID disagreements; DTO's selected-row fecha_alta differs for 15, fecha_baja for 7. All 17 chain-selected rows are origen=app, normalizado_por=app-editar-colectivo, elegible_actual=false; canonical selects earlier rows. This is DEV user-edited test data, not evidence of a PROD data defect. Next: align the resolver in ficha and edit DTOs with canonical current-period ; keep as the separate original-ALTA calculation. This is the remaining code divergence under Elazar's GO; do not describe the full chain timeline as a current-period resolver.
  • coder04-mba-l-ca progress · 1w ago
    CORRECTION to prior progress note: the omitted identifiers are fechaVigenciaHasta and fecha_baja; keep fechaVigenciaDesde as the separate original-ALTA calculation. Counts and scope are unchanged. The discrepancy is the latest chain event versus the current-period row, with 17 DEV mismatches and none in PROD.
  • coder04-mba-l-ca unblocked · 1w ago
    db03 confirms canonical view exists and Elazar GO covers consolidating the remaining resolver; comparison found a DEV-only mismatch, proceeding with app-code alignment.
  • coder04-mba-l-ca progress · 1w ago
    Implementation ready for audit: ficha and edit DTO now source fechaVigenciaHasta from rutap.v_vehiculo_historial_actual.fecha_baja; fechaVigenciaDesde remains the original-ALTA calculation from the full chain. Updated source-contract assertions in src/lib/vehiculo-vigencia.test.ts. Pins: src/repositories/vehiculos.ts SHA-256 9019b49fa6162c0fbd087d65c82e40f284b6b814596bcc22a6df86601c9b478a; src/lib/vehiculo-vigencia.test.ts SHA-256 bafc44c61affc4993e6cce29c6b93cadfe0ad0bfedc4ac074a01868861e31867. Per repository workflow, no gates/tests run before audit. SELECT comparison remains PROD 0/2424 diffs, DEV 17/2469 row diffs (15 fecha_alta, 7 fecha_baja), all chain-selected rows are app-editar-colectivo DEV rows.
  • audit-mba-l-cc audit-finding · 1w ago
    audit-mba-l-cc 2026-10-09: re-measured old-vs-new resolver divergence independently (not trusting coder04/db03's reported figures). First pass used wrong tie-break (id DESC) and omitted the origen/snapshot eligibility filter, giving a false mismatch. Corrected to match getRutapHistorialByChain's real predicate (borrado_en IS NULL AND (origen=app OR (origen=import AND rutap_snapshot_id=latest))) and real tie-break (fecha_alta ASC NULLS LAST, rutap_fila_excel ASC via compareBusinessOrder/buildChainEvents, picking the chain-local last row per vehiculo_id). Result: PROD 0/2424 keys differ (id/baja/alta all exact match) - confirms the new view fully replicates old chain logic on clean PROD data. DEV: 30 id_diff/19 baja_diff/15 alta_diff of 2469 (my own independent number, differs from coder04's claimed 17/15/7 - alta_diff matches exactly at 15, id/baja do not). Not a blocker: DEV divergence is expected from user test-edited rows per the DEV-preserves-edits rule, and PROD (the clean proof surface) is a perfect match. Gates run fresh: typecheck rc=0, test:source 68/68, test:tools 121/121. Pins confirmed exact: src/repositories/vehiculos.ts 9019b49fa6162c0fbd087d65c82e40f284b6b814596bcc22a6df86601c9b478a, src/lib/vehiculo-vigencia.test.ts bafc44c61affc4993e6cce29c6b93cadfe0ad0bfedc4ac074a01868861e31867. fechaVigenciaDesde confirmed untouched in both methods.
  • audit-mba-l-cc audited · 1w ago
    audit pass: vehiculos.ts fechaVigenciaHasta switch (ficha + edit-DTO methods, both leftJoins to v_vehiculo_historial_actual) and vehiculo-vigencia.test.ts regex updates; gates typecheck/test:source/test:tools run fresh; independent SQL re-derivation of old-vs-new resolver divergence on PROD and DEV
    payload
    {"scope":"vehiculos.ts fechaVigenciaHasta switch (ficha + edit-DTO methods, both leftJoins to v_vehiculo_historial_actual) and vehiculo-vigencia.test.ts regex updates; gates typecheck/test:source/test:tools run fresh; independent SQL re-derivation of old-vs-new resolver divergence on PROD and DEV","outcome":"pass","evidence":"PROD 0/2424 exact match (id/baja/alta) against rutap.v_vehiculo_historial_actual via corrected DISTINCT ON proxy of getRutapHistorialByChain's real predicate+tie-break; typecheck rc=0; test:source 68/68; test:tools 121/121; pins vehiculos.ts 9019b49f.., vehiculo-vigencia.test.ts bafc44c6.. confirmed exact","reportRef":null}
  • coder03-mba-l-cc completed · 1w ago
    Shipped: dev 49b945a8, prod b60b1b5b, both patch 242. Ficha and edit DTO fechaVigenciaHasta now derived from canonical rutap.v_vehiculo_historial_actual instead of raw chain's last event. 3/4 resolvers already consolidated on that canonical view; the 4th (getRutapHistorialByChain path) was the real mismatch, fixed. PROD measured exact match 0/2424 before and after. v_vehiculos_ciclo_actual confirmed NOT a duplicate (different question). v_vehiculos_export_periodo_actual flagged dead (zero consumers) - separate cleanup item needed. Audit PASSed.
task
2026-08-20 by wi-cli-venus
1w ago
2026-10-09 05:50