Pendientes P1 — instrucciones de avance¶
Este documento es el encargo de implementación para las vistas P1 de
inventario-ui.md que aún no existen en mmi/src/views/, a fecha
2026-09-20. No repite lo que ya está en el inventario (props, componentes propuestos,
comportamiento legacy): asume que se leyó esa vista primero. Lo que añade este documento es
qué backend real hay detrás de cada una hoy, qué falta y de quién depende, y el orden
de trabajo recomendado.
Lista cubierta: C5, D6, D8, E1, E2, E3, E4, E5, E6, E7, E11, E12, F1, F2, F3, G1, G2, G3, G4, G5, G7, G8, I6. (E8, E9, E10, F4, F5, F6, G6 son P2, fuera de este documento.)
Antes de tocar código¶
Leer AGENTS.md completo si no se hizo ya. Dos reglas de ahí son las que más se van a violar por
descuido en este bloque de trabajo:
- El contrato RCP↔DSP lo posee el proyecto DSP. Un campo que "falta" en
contract/vendor/no se añade aquí a mano. Se pide al proyecto DSP, se espera el re-vendorizado, se sube el ancla encontract/vendor/UPSTREAM.toml. src/core/no importa nada desrc/adapters/. Cualquier endpoint nuevo de gateway que lea hardware pasa por la interfazHardwareAbstractionLayer(src/core/contracts/hal.py), nunca llama a Modbus directo.
Diagnóstico de fondo: la familia E depende de un contrato que hoy no tiene la mayoría de estos¶
campos
Esto no es una nota al pie, es la razón de que el orden de trabajo recomendado empiece por otro
lado. docs/interfaces/mapeo-parametros-dsp.md (829 líneas, ya escrito, léase antes de tocar
cualquier vista E) hace el mapeo campo a campo contra contract/vendor/dsp_rcp_v0_1.py y contra
el repo lamula-dsp. Resultado cuantitativo (§ Resumen cuantitativo del propio documento): de 209
filas, 10 tienen equivalente literal hoy, 46 "difieren" (existe algo parecido pero no es el
campo — env var de despliegue, unidad distinta, alcance distinto), 82 son funcionalidad que el
contrato de hoy no expone en absoluto, y el resto no aplica o no es decidible desde este repo.
Verificado en código: src/core/contracts/dsp.py solo modela RadialMoments (radiales de
momentos) — no hay un solo campo de configuración (umbral, filtro, trigger) en el contrato de
dominio. Esto confirma el mapeo: hoy no hay dónde escribir la mayoría de los parámetros de
E2–E7, no es cuestión de tiempo de desarrollo en este repo.
Por tanto, para cada vista de la familia E este documento distingue:
- Ya expuesto (
ExisteoDifiereen el mapeo) → se puede construir el endpoint de gateway y la vista ya, con el campo real o con el más cercano documentado como aproximación (marcar// PEND-nn). - No expuesto (
Falta) → la vista se puede diseñar y maquetar contra datos simulados enuseGateway.mock.ts, pero no cablear a datos reales hasta que el proyecto DSP publique el campo. Abrir la pregunta en el canal del proyecto DSP citando la fila exacta del mapeo, no reinventar el campo localmente.
Receta común para una vista nueva de estado/configuración¶
Igual en las ~20 vistas de este documento salvo excepción marcada. Referencia concreta: la
implementación de B7 (git show a217461) y de B4/B5/C2 (git show d0848ce).
- Contrato de dominio — añadir el modelo Pydantic en
src/core/contracts/mmi.py(snapshot de lectura) y, si hay escritura, el modelo de comando. No endsp.py/hal.pysalvo que el dato venga realmente de ahí. - Endpoint de gateway —
src/adapters/gateway/app.py. PatrónGETpara snapshot,POSTparaSet(aplica, volátil) yPOST .../saveparaSave(persiste), calcado del bloquepower-monitor(líneas 627–660 a fecha de este documento). Si el dato sale del HAL, pasar siempre porhal.read_analog/hal.read_digital, envolver entry/excepty degradar astale/None, nunca lanzar 500 por una lectura de campo caída. - Test de endpoint —
tests/test_<vista>.py, un test por estado (ok, sin dato, error de guardado). Vertests/test_power_monitor.pycomo plantilla. - Tipo espejo en MMI —
mmi/src/types/mmi.ts, mismo nombre de interfaz que el modelo Pydantic (regla ya seguida en todommi.ts, no romperla). - Composable — función
fetchX/setXenmmi/src/composables/useGateway.tsy su doble enuseGateway.mock.tscon datos sintéticos plausibles (verlamula_rcp_diseno_storybook_mock_gatewayen memoria: el doble atrapó un bug real en BiteMessagesView — no es un trámite). - Vista —
mmi/src/views/<Nombre>View.vue+.stories.ts. Ancho de referencia 960×480 px (mosaico a un cuarto) y pantalla completa, los dos, per requisito transversal 4 del inventario. - Registro — añadir la entrada en el registro de vistas de
App.vue(línea ~50 en adelante,{ id, label, available: true }) y quitar el placeholderavailable: falsesi esta vista ya estaba ahí como stub. - Verificación real — Storybook (
pnpm --filter mmi storybooko el script equivalente del repo) contra el mock, y contra el HAL-simulador real si el dato viene de Modbus. No dar por completa una vista sin haberla visto en Storybook, per regla general de "probar antes de reportar terminado".
Patrones transversales que no se rediseñan por vista — si la vista los necesita, reutilizar lo que ya exista o construirlo una sola vez y enlazarlo desde aquí:
SetSaveActions(Set volátil / Save persistente) — patrón ya usado en B7, replicar tal cual.BlockedActionExplainer(acción bloqueada por condición física, p. ej. "Save solo con radiación apagada") — ya existe el caso de uso en B7, generalizar si la segunda vista lo necesita en vez de duplicar.ParameterGroupCard/ConditionalFieldGroup(formulario cuyo layout depende de otro campo) — necesario en E4, E6, E7; construir una vez.ConfirmDangerDialog— ya existe (A3). Reutilizar para toda acción irreversible de esta lista (G-family sobre todo).
Familia D — pendientes P1¶
D6 — Color Management y Color Composer¶
Estado hoy: no hay tabla de color ni en el backend ni en D2/D3/D4 — las vistas de datos
pintan con una paleta fija en el frontend. Cero contrato de por medio; esto es trabajo 100 %
mmi/.
Pasos:
- Definir el espacio de color perceptual (OKLCH) como fuente de verdad para las paletas por defecto — decisión ya tomada en el inventario, no reabrir la discusión de RGB vs perceptual. Empezar por reflectividad (secuencial) y velocidad (divergente centrada en cero), que son las dos que D2/D3/D4 ya usan.
mmi/src/lib/colorScales.ts(nuevo): funciónbuildSequentialScale/buildDivergentScaleen OKLCH → array de stops RGB para el canvas de D2–D4. Verificar contraste con un chequeo de deuteranopía/protanopía (simular, no solo mirar).ColorTableEditor/ColorComposercomo vista o panel lateral (D1 ya decidió que las auxiliares viven dentro del panel de su vista de datos, no como panel propio) — construir después del punto 2, no antes: sin las paletas por defecto no hay nada que editar.InterpolateActioninterpola en el mismo espacio OKLCH, nunca en RGB — es la razón de ser de esta reescritura, no un detalle de implementación.- Cablear D2/D3/D4 a las nuevas paletas al final, con story de comparación antes/después en Storybook.
No depende de nada externo. Candidata a empezar ya si se quiere trabajo P1 sin bloqueos.
D8 — Scan Parameter Popup¶
Estado hoy: el Scan Worksheet (ScanWorksheetView.vue) ya tiene el modelo completo de
parámetros de scan enviados (src/core/contracts/scan.py, cableado). D8 es de solo lectura: los
mismos parámetros, congelados junto con el dato que se está viendo.
Pasos:
- Verificar que el snapshot de scan actual (el que ya usa
ScanWorksheetView) se puede pedir sin abrir esa vista — si el endpoint ya devuelve el estado global, D8 solo necesita reusarfetchScanWorksheet(o el nombre real enuseGateway.ts, verificar en el fichero) desde un popover, no un endpoint nuevo. - Componente
Popover/panel lateral conKeyValueTable, invocable desde D2/D3/D4 (menú → "parámetros de scan"). - Congelar el snapshot en el momento de abrir el popover (copia local), no suscribirlo a cambios en vivo — la vista es "¿con qué se tomó esto?", no un segundo Scan Worksheet.
No depende de nada externo.
C5 — Sector Blanking Editor¶
Estado hoy: ni el HAL-simulador ni el contrato DSP tienen noción de sectores de blanking; el
mapeo (mapeo-parametros-dsp.md §E5) confirma que la generación de triggers, y con ella el
blanking, es del DRx/FPGA y el DSP solo expone 4 pares fijos de retardo/anchura, sin banco
configurable. Antes de construir la vista hay que decidir dónde vive el estado de los
sectores: si el blanking real ocurre en el DRx y el DSP no lo expone, el RCP puede como mucho
guardar la configuración deseada (perfil) sin poder aplicarla al hardware todavía.
Pasos:
- Confirmar con el proyecto DSP si existe o se puede pedir un campo de blanking por sector — no
asumir que aparecerá; documentar la respuesta en
docs/alcance/pendientes.mdcon su propioPEND-nn. - Mientras tanto: construir
SectorBlankingEditor+AzimuthSectorDialcontra estado local persistido en el RCP (perfil de sectores en NVRAM propia, no en el DSP), con un badge visible de "no aplicado al hardware" si no hay backend real. Es preferible a no construir nada, porque el componente gráfico (círculo de azimut con sectores) es reutilizable el día que el DSP exponga el campo. - Ocho sectores (convención RVP900, no los cuatro de Ravis — ya decidido en el inventario), cada
uno con
InUse+ rango AZ + rango EL.
Bloqueado en parte por upstream. Empezar por el punto 2 (componente + persistencia local) sin esperar la respuesta del punto 1.
Familia E — Configuración del DSP¶
Leer primero docs/interfaces/mapeo-parametros-dsp.md completo. Cada vista de abajo cita sus
filas relevantes; no se repite el detalle campo a campo que ya está ahí.
E1 — DSP Setup Hub¶
Estado: sin contrato específico; es el índice de E2–E12. Se puede construir en cuanto exista al menos una vista E real a la que enlazar (recomendado: después de E3, que es la más barata).
Pasos: SetupHubGrid con un badge "modificado respecto a saved" por grupo — depende de E11
(Config Profiles) para saber qué es "saved" vs "current"; construir E11 primero o en paralelo.
ExportConfigButton reutiliza el patrón transversal I6 (Export/Snapshot) — no lo dupliques,
constrúyelo ahí y consume desde aquí.
E2 — Processing Options (Mp)¶
Estado: el mapeo marca la mayoría de este grupo como Falta (ver §E2, líneas ~116–159). Los
pocos campos con equivalente son de umbral/corrección, no de este grupo específico.
Pasos: maquetar completo contra mock (useGateway.mock.ts), sin cablear escritura real todavía.
Sí vale la pena construir ya el componente TernaryOverrideField (Never/User/Always) que el
inventario pide — se repite 5 veces en esta vista sola y reaparece en otras.
E3 — Thresholds Matrix (Vp)¶
Estado: la más avanzada de la familia. Del mapeo (§E3):
sqi_threshold→ Existe, validado 0–1 (lamula-dsp/crates/rcp-link/src/validate.rs:60-63).log_threshold→ Difiere: existe pero es global, no por momento, sin rango publicado.ccor_threshold→ Difiere: equivale a CSR, documentado algebraicamente, también global.
Pasos:
- Confirmar que
contract/vendor/dsp_rcp_v0_1.pyya trae estos tres campos (debería, según el mapeo) — si no, es lo primero a re-vendorizar. - Endpoint de solo lectura (la vista es read-only también en el RVP900 — decisión ya tomada de no
abrir edición). Snapshot con los tres umbrales, marcados global, no por fila de la matriz de
19 parámetros — la matriz completa del legacy no tiene respaldo real; mostrar solo lo que hay y
dejar el resto de filas com
no disponible, no inventar valores. ThresholdMatrix/ThresholdCellcon el patrónTCF(expresión booleana legible) diferido — no hay campoTCFreal hoy, omitir esa columna en vez de fingirla.
La vista más barata de construir con datos reales de toda la familia E — empezar por aquí.
E4 — Clutter Filters (Mf)¶
Estado: clutter_width_ms → Existe (mapeo §E4, …toml:316), pero solo para el modelo
gaussiano (filtros #5–#7 del inventario). Los filtros fijos (#1–#3) y variable (#4) no tienen
campo.
Pasos: construir solo el bloque gaussiano contra dato real (Win, Spectrum width); el resto
del formulario (ConditionalFieldGroup por tipo de filtro) se maqueta contra mock y se marca
explícitamente "sin backend" en la UI, no oculto — el operador necesita saber que ese control no
hace nada todavía si lo toca.
E5 — Trigger Setup general (Mt)¶
Estado: confirmado por diseño (no falta de dato, decisión de arquitectura): "cuatro pares fijos
de retardo y anchura, sin polaridad, sin término proporcional al PRT" — no los seis triggers libres
del RVP900 (nota ya en el inventario, §E). El mapeo confirma que el número de triggers de salida
no aplica (drx_dsp_v0_1.rs:133-147, fijo).
Pasos: TriggerTimingTable de solo lectura, 4 filas fijas — nada de Pretrigger/polaridad/
término PRT porque no existen en este hardware. Blank output triggers within AZ/EL sectors
enlaza a C5 (mismo componente SectorBlankingEditor, ver nota del inventario) — construir después
de C5.
E6 — Trigger Setup por pulse width (Mt<n>)¶
Estado: casi todo Falta salvo gate_spacing_m → Existe (mapeo §E6, …toml:310, :126).
Pasos: por ahora, esta vista se reduce en la práctica a mostrar Range mask spacing real
dentro de una ficha por ancho de pulso; el resto (tabla de 6 triggers Start/Width/High, IF de
Tx/Rx, etc.) es exactamente lo que el mapeo lista en "Falta en el contrato" puntos 3 y 10 — no
construir esos campos como formulario editable todavía. Selector de ancho de pulso persistente sí
se puede construir ya (es navegación, no dato).
E7 — Burst Pulse & AFC (Mb)¶
Estado: el mapeo es explícito (§E7, línea 282): "el ciclo AFC/burst está punta a punta [en
lamula-dsp], pero el contrato no expone ni una sola perilla suya". Único hallazgo aprovechable:
LAMULA_DSP_AFC_AMP_THRESHOLD existe como config de despliegue (variable de entorno del lado
DSP, no del contrato) — no es legible ni escribible desde el RCP.
Pasos: esta vista no tiene nada que cablear a datos reales hoy. Maquetar completa contra
mock; documentar en la propia vista (comentario de cabecera, convención ya usada en el resto de
mmi/src/views/) que depende de que el proyecto DSP publique telemetría de AFC/burst (mapeo
§"Falta en el contrato", puntos 1 y 2). No empezar esta vista hasta que E3/E4 estén hechas — es la
de menor retorno inmediato de toda la familia.
E11 — Config Profiles¶
Estado: sin contrato de "current vs saved vs factory" en ningún lado del backend hoy — es concepto nuevo, no legacy directo de RVP900 vía nuestro DSP.
Pasos:
- Decidir alcance real: ¿el RCP guarda sus propios perfiles de lo que sí controla (E3, E4 parcial,
límites de B7, sectores de C5), o se espera a que exista más superficie editable en E? Recomendado:
construir ya sobre lo poco editable que hay (B7
PowerMeasurementLimitsya tiene su propio Set/Save — generalizar ese patrón a "perfil" en vez de reinventar). ConfigDiffView(diff entre current y saved) es la pieza de más valor y la más barata: es comparación de JSON, no requiere contrato nuevo.
E12 — DSP Internal Status (V / Vz)¶
Estado: la mejor cubierta de la familia después de E3. Del mapeo (§E12): número de celdas,
periodo de trigger (medido vs mandado, con deriva — mejor que el legacy), ruido por canal,
pulsos/rayo, celdas ok/total y espaciado de máscara de rango → todos Existen ya en
status/moment_ray/config del contrato de cable.
Pasos:
- Extender
SystemStatusView/B10 (que ya expone un subconjunto agregado) o crearE12como su "modo detallado MANT" — decidir si es vista separada o un nivel de detalle de B10; el inventario ya dice "versión de mantenimiento de B10". RawStatusWordsPanelcon decodificación simbólica de bits — patrón que también hace falta en I3 (WFG System Status); construir el componenteBitmaskStatusListuna vez y reusarlo en las dos.- Contadores de trigger con reset (
Vz) → acción conConfirmDangerDialog, no botón directo.
Segunda vista más barata de construir con dato real, después de E3.
Familia F — Ajuste asistido por gráfico¶
Estado general (mapeo §"Familia F", líneas ~430–466): F2 tiene captura oportunista de espectro
del burst cableada (spectrum_frame msg 2, mandato request_spectrum msg 7). Las tres
limitaciones que tenía documentadas —solo canal RX_0, center_freq_hz/span_hz en 0 por falta
de campos de IF/muestreo, sin promediado entre peticiones— caen con el pin v1.9
(re-vendorizado 2026-09-28, antes v1.3):
request_spectrumparametrizado (msg 11, nuevo en v1.9):channel(cualquier canal físico dedrx_dsp::channel, no soloRX_0) yn_averages(radiales sucesivos acumulados en potencia antes de responder). El mandato viejo sin parámetros (command::request_spectrum, msg 7) sigue existiendo con el mismo comportamiento de siempre.capabilitiespublicatx_if_hz,rx_if_hz,rx_nco_fs_hzyrx_nco_word_bits(v1.8), así que el eje de frecuencias de F2 ya tiene escala real:spectrum_frame.center_freq_hzsale derx_if_hzyspan_hzde1/fast_time_dt_s.statuspublica telemetría de AFC/burst (v1.4):afc_freq_meas_hz,afc_control_freq_hz,afc_burst_amplitudey el bitafc_bite. No son los seis estados del inventario: la máquina de estados con histéresis sigue sin existir aguas arriba.configrelaya parámetros del DRx escribibles (v1.6/v1.7):pulse_width_idx,cell_mode,prf_divytrigger_delay_0..3/trigger_width_0..3en microsegundos — el DSP hace la conversión a ciclos del reloj del DRx (ray::build_drx_config), el RCP nunca ve ese reloj.transmitter_type(v1.6) y los modos de barrido compuestossplit_cut/batch_cut/doppler_cut(v1.5).
F1 — Burst Pulse Timing (Pb)¶
Estado: la premisa de esta sección cambió con el pin v1.9. El temporizado de triggers ya está
en el contrato y es escribible: config.trigger_delay_0..3/trigger_width_0..3, en
microsegundos (v1.6/v1.7), y el DSP los baja al DRx en ray::build_drx_config. La decisión de
dejarlos de solo lectura se reabrió por instrucción explícita — ver
../interfaces/plan-pendientes-drx-dsp.md, §"Decisión
que este documento reabre". Lo que sigue faltando para F1 no es dónde escribir, sino la captura
de forma de onda del burst: hoy no existe ningún mensaje que la transporte (el ítem A.8 de ese
plan, burst_waveform_frame, no está construido), y la captura ADC de alta resolución depende de
un buffer que el DRx tampoco tiene (ítem B.13, condicionado a medir recursos en ZU9).
Pasos: replantear el alcance antes de construir: no un editor de temporizado (no hay dónde escribir), sino una visualización del pulso capturado (reusar lo que F2 ya resuelve para captura de espectro, si hay una captura de forma de onda equivalente) con los valores de trigger actuales en modo lectura. Confirmar con el equipo si esta vista sigue teniendo sentido en su forma actual o se fusiona con F2/F3 en una sola "vista de verificación de RF". No empezar sin esa conversación — es la única de este documento donde el riesgo de construir algo sin uso es alto.
F2 — Burst Spectra & Matched Filter (Ps)¶
Estado: la única de la familia F con dato real parcial.
Pasos:
- Nota: con el pin v1.9 hay dos mandatos, no uno.
command::request_spectrum(msg 7, sin parámetros, canalRX_0, sin promediar) yrequest_spectrum(msg 11, conchannelyn_averages). Para esta vista usar el msg 11: es el que permite el selector de canal y el promediado que pide el inventario. - Endpoint de gateway que dispare
request_spectrumy devuelva el últimospectrum_framerecibido — patrón "pedir y esperar" distinto del resto (no es snapshot inmediato); usar el mismo patrón de job asíncrono que ya existe para las rutinas de control (JobActionPanel,src/core/control_routines/). - Selector de canal y de número de promedios, ya que el msg 11 los admite. El eje de frecuencia ya
puede ir en MHz reales:
center_freq_hzviene derx_if_hzyspan_hzde1/fast_time_dt_s(v1.8). Lo que sí hay que seguir marcando como tal:rx_if_hzes constante de instalación, no medida, y no incluye el offset que el lazo de AFC tenga aplicado en ese instante. - Los seis estados de AFC (
Disabled/Manual/NoBurst/Wait/Track/Locked) del inventario siguen sin existir aguas arriba — pero desde v1.4 sí hay telemetría parcial enstatus(afc_freq_meas_hz,afc_control_freq_hz,afc_burst_amplitude, bitafc_bite). Mostrar esos cuatro como lo que son, no derivar de ellos una máquina de estados que el DSP no calcula.
F3 — Receiver Waveforms (Pr)¶
Estado: sin fila específica en el mapeo — depende de si existe una captura de forma de onda de
receptor equivalente a spectrum_frame. Verificar con el proyecto DSP si algo así está en su
roadmap antes de estimar esfuerzo.
Pasos: no empezar sin esa confirmación. Si no hay captura posible, esta vista queda en el mismo estado que F1: replantear alcance, no construir contra mock como si fuera a cablearse pronto.
Familia G — Calibración y alineación de receptor/transmisor¶
Estado de fondo, verificado en código: src/core/contracts/hal.py no tiene un solo concepto de
calibración (ni SignalReading ni HardwareAbstractionLayer mencionan cal/zero-check/radar
constant). El catálogo de señales Modbus del HAL-simulador
(src/adapters/hal_sim/rd100s_signal_catalog.json, 112 señales) tampoco tiene ningún punto de
calibración, ITSG, zero-check o constante de radar — solo estado/comandos de TX, antena, RX y
sistema. Toda la familia G es trabajo nuevo de HAL, no solo de MMI. El único precedente es
tx.tx_reflected_power_sample, vendorizado para B7 con unit_id/module inventados y marcado
PEND-29 (git show a217461 — commit de referencia) porque no hay sensor real confirmado
todavía. Cualquier señal nueva de esta familia sigue ese mismo patrón: inventar el punto Modbus,
marcarlo PEND-nn, y dejarlo para confirmación con el fabricante/hardware real.
Precondición de UI común a toda la familia (ya en el inventario, repetirla aquí porque es fácil
de saltarse): modo de mantenimiento activo (A4) y autoridad de control activa (A3) y
ACU/LCU en Remote. Construir el chequeo de precondiciones una sola vez (extender
PrecheckList, que ya existe para C4) y reusarlo en G1–G8, no reimplementarlo por vista.
G1 — Calibration Hub¶
Pasos: índice puro — estado de precondiciones (arriba) + fecha/resultado de última calibración
por tipo (requiere que G2–G8 ya persistan resultado en alguna parte, aunque sea un registro simple
en src/core/contracts/mmi.py tipo CalibrationRecord). Construir después de al menos una de
G2/G4/G5, no antes — si no, el hub no tiene nada que agregar.
G2 — TX Sampling Adjust¶
Estado: requiere TX pulse como tipo de dato del Scan Worksheet (ya existe en el contrato de
scan, verificar en src/core/contracts/scan.py) mostrado en ASCOPE (D2, ya existe) — la parte de
lectura cruzada ya está. Lo que falta es el HAL: TX Start/Stop Sample, TX Sample, TX
Frequency, Commanded LO Freq., etc. no están en el catálogo de señales.
Pasos: definir los puntos Modbus nuevos con el mismo criterio PEND-nn de B7. El patrón de
"aceptación por campo se pinta de verde" (ParameterField con estado de aceptación) es
reutilizable en G3/G4 — construirlo una vez aquí.
G3 — TX Power Calibration¶
Estado: procedimiento guiado (wizard) con entrada manual del operador — no es solo lectura de
HAL, es un flujo con RoutineStepper/WizardStepper. El patrón ya existe para las rutinas de
control (src/core/control_routines/, C4) — extender ese mismo motor de rutinas, no crear uno
nuevo. WarmupTimer (20 min de radiación antes de empezar) es un requisito duro, no cosmético:
bloquear el botón de inicio, no solo avisar.
G4 — Single Point Calibration¶
Pasos: dos escenarios (generador interno automático / externo con intervención). Empezar por
el escenario automático — reusa el motor de rutinas de G3. El escenario externo necesita
OperatorPromptDialog (nuevo, compartido con G3). Resultado volátil hasta guardar — el estado
"obtenido pero no guardado" tiene que ser imposible de ignorar visualmente (banner persistente, no
un toast que desaparece).
G5 — Zero Check¶
Estado: la única de la familia que ya se ejecuta automáticamente según el inventario ("al
arrancar el RCP y luego a intervalos fijos") — verificar si eso ya está implementado en
src/core/ (buscar en control_routines/ o bite/) antes de asumir que hay que construirlo desde
cero; puede que solo falte la vista sobre un mecanismo que ya corre.
Pasos: si el mecanismo periódico existe, esta es la vista más barata de la familia G —
JobActionPanel (ya existe) + NoiseLevelReadout + ScheduleInfoRow. Si no existe, construir
primero el job periódico en src/core/, con su propio test, antes de la vista.
G7 — Radar Constant Parameters¶
Estado: parámetros mayormente estáticos de instalación (pérdidas, ganancia de antena, wavelength) — candidatos a vivir en configuración del RCP, no en HAL. Solo los de Zero Check se actualizan solos (depende de G5).
Pasos: empezar por el formulario estático (sin dependencia de hardware) — ParameterGroupCard
+ persistencia local. EquationPanel (mostrar la ecuación de la constante del radar con los
términos resaltados) es trabajo de contenido, no de datos; se puede hacer en paralelo por
cualquiera sin esperar al resto de la familia.
G8 — Calibration Log¶
Pasos: depende de que G2–G5/G7 emitan eventos de log estructurados. Definir el modelo
CalibrationLogEntry en src/core/contracts/mmi.py antes de empezar cualquier otra vista de
G, para que todas escriban al mismo sitio desde el principio en vez de migrar después.
LogStream/LogToolbar reutilizan patrón de A5 (Event Log) — no reinventar el componente de
lista con severidad, ya existe en EventLogPanel.
Orden recomendado dentro de G, dado lo anterior: G8 (modelo de log) → G5 (verificar si ya hay mecanismo) → G2 → G4 → G3 → G7 (en paralelo, sin dependencias) → G1 (hub, al final).
I6 — Export / Snapshot¶
P1 · transversal. No es una vista, es un servicio compartido. Construir antes de tocar cualquier vista de arriba que lo mencione (D1, D6, G6, I2...) para no reimplementarlo por pieza.
Pasos:
ExportMenu/SnapshotActionenmmi/src/components/(no enviews/) — exportar el panel activo del mosaico como PNG (usar el mismo canvas que ya renderiza D2/D3/D4 cuando aplique, ohtml-to-image/similar para vistas de formulario) y los datos subyacentes como CSV/JSON.MeasurementFilePickerpara el caso "guardar y recargar un conjunto de resultados" (BiTE ya tiene su propio guardar/cargar en B9 — verificar si ese código es reusable aquí en vez de duplicarlo).- Integrar en
PanelFrame(A1) como acción de cabecera de panel, disponible en todas las vistas por construcción, no añadida vista por vista.
No depende de nada externo. Candidata a hacerse en paralelo con D6 al principio del bloque P1.
Resumen: qué se puede hacer ya vs qué espera a otro equipo¶
| Sin bloqueo externo | Bloqueado o parcial por contrato DSP/HAL ausente |
|---|---|
| D6 Color Management | E2 Processing Options (Falta casi todo) |
| D8 Scan Parameter Popup | E5/E6 Trigger Setup (triggers son del DRx/FPGA) |
| I6 Export/Snapshot | E7 Burst Pulse & AFC (Falta todo salvo env var no legible) |
| E3 Thresholds Matrix (parcial real) | F1 Burst Pulse Timing (replantear alcance) |
| E12 DSP Internal Status (parcial real) | F3 Receiver Waveforms (confirmar si existe captura) |
| E11 Config Profiles (diff, sin contrato nuevo) | F2 Burst Spectra (necesita re-vendorizar request_spectrum) |
| G7 parámetros estáticos | G1–G5, G8 (necesitan HAL nuevo, puntos Modbus inventados PEND-nn) |
| C5 Sector Blanking (componente + persistencia local) | C5 aplicación real al hardware (mismo límite que E5) |
Orden global recomendado: I6 → D6/D8 (en paralelo) → E3 → E12 → E11 → G8 → G5 → resto de G → C5 (componente) → E1 → E2/E4/E6 parciales contra mock → F2 (tras re-vendorizar) → E5/E7/F1/F3 (replantear con el equipo DSP antes de construir).