- Implemented `workstationEquipment` to manage workstation asset assignments, including principal and secondary assets. - Created tests for `workstationEquipment` to ensure correct behavior with various scenarios. - Developed `workstationOrganizationalAssignments` to retrieve current assignments for a responsible person in a company. - Added tests for `workstationOrganizationalAssignments` to validate assignment retrieval logic. - Introduced UI components for displaying workstation profile configurations and responsible person details. - Created compact UI components for displaying lists and tables, enhancing the user interface for asset management. - Added utility functions for handling cell content in tables, ensuring proper rendering of data.
82 KiB
Dashboard de puesto de trabajo: implementación
Fecha: 22 de octubre de 2026. Ruta real: /companies/:companyId/workstations/:id.
Estado actual: WD04.3 — Consolidación de Responsable y contexto, 24 de octubre de 2026. Los apartados anteriores conservan la evolución de las entregas previas.
Resultado y referencias
La ficha presenta ordenador principal, configuraciones pendientes, personas y perfiles, responsable y contexto, equipamiento, software, configuraciones por perfil, soporte/acceso remoto y último cambio. El historial completo, edición, renombrado, alta de perfil y ciclo de vida siguen usando las operaciones existentes.
La implementación utiliza consultas reales. El JSON de la auditoría solo se importa en pruebas; no alimenta la aplicación ni se inserta en una BD. No hay endpoints, modelos, esquemas, migraciones ni dependencias nuevos.
Se han conservado los ocho entregables de la auditoría como descripción del estado anterior y base funcional. No existe una imagen aprobada accesible en esta conversación o adjunta a la tarea: la comparación se realiza con la especificación textual del usuario. No se afirma fidelidad de píxel respecto a una imagen no disponible.
Composición y diferencias justificadas
- El shell, sus sidebars, búsqueda superior y navegación conservan su implementación.
- Cabecera con breadcrumb, nombre editable, estado, compañía, sede y responsable. Editar, historial y menú de ciclo de vida permanecen accesibles.
- La primera banda reserva al ordenador la columna izquierda y sitúa pendientes al extremo derecho, sin ocupar el hueco con estadísticas. No se han creado las cuatro tarjetas eliminadas.
- El grid inferior utiliza
minmax(0,1.6fr)yminmax(0,1fr)desde 1000 px de contenedor: aproximadamente 62/38. La primera banda cambia desde 900 px. Por debajo se conserva una columna y el orden lógico pedido. - Paneles compactos con borde, radio y espaciado del sistema existente; sin sombras decorativas ni gráficos.
- Se utiliza el catálogo propio de iconos Tabler. La especificación menciona Lucide, pero prioriza el design system instalado para componentes/tokens. No se ha introducido otra biblioteca ni cambiado vendor.
- El azul de la ficha utiliza los tokens existentes
secondaryysecondary-foreground, asignados localmente a los roles primarios dentro de su contenedor. El tema global y los portales de diálogos conservan su configuración. No se añade otra paleta. - Las plantillas, nombres y fechas visibles proceden del servidor; no se fuerza «Portátil corporativo» ni la fecha de la ilustración cuando el catálogo o las revisiones reales dicen otra cosa.
- Las celdas sin valor usan «—». Responsable ausente en cabecera se expresa como «Sin responsable», un estado semántico fuera de una celda de listado.
Componentes reutilizados y componentes nuevos
| Unidad | Reutilización / motivo |
|---|---|
DetailPanel, DetailField |
Estructura común. DetailPanel incorpora density="compact"; el valor por defecto conserva sus recetas anteriores |
EntityTable, EntityStatus, entityListState |
Tablas con búsqueda, orden, paginación, columnas configurables y estados inicial/actualización/error/datos anteriores |
WorkstationNameEditor, WorkstationActions, WorkstationEditorDialog, WorkProfileEditorDialog |
Operaciones reales conservadas. WorkstationActions.children permite intercalar la acción de historial sin duplicar el menú |
WorkstationHistoryDialog, WorkstationHistory, TimeLine |
Historial completo real. Se exporta el diálogo desde la API pública de Assets; añade altura estable y destino de foco de retorno |
SoftwareInstallationsPanel |
Gestión completa de instalaciones dentro de WorkstationSoftwareDialog; conserva alta, edición, borrado, cerradas e historial |
AssetSupport, RemoteSummary, TeleworkAuthorizationSummary |
Consulta y gestión de soporte/contexto con semántica existente |
buildEnvironment |
Reutiliza el cálculo de configuraciones y sus detalles, sin copiar políticas de autorización |
WorkstationComputer, WorkstationResponsible, WorkstationLatestChange |
Presentación específica de responsabilidades distintas de la ficha |
WorkstationPendingConfigurations, WorkstationProfileConfigurations, WorkstationConfigurationFamily |
Conteo verificable, selección explícita y grupos con estado independiente |
WorkstationSoftware, WorkstationSupport |
Integración de fuentes/operaciones existentes con contexto del equipo y la persona seleccionados |
WorkstationQueryFeedback, WorkstationDashboardSkeleton |
Feedback repetido por fuente y geometría de carga inicial de esta pantalla |
WorkstationAssets y WorkstationProfiles se adaptan en sus ubicaciones existentes. El antiguo WorkstationPeople se retira tras buscar sus referencias: solo lo utilizaban la composición anterior y sus pruebas. La distinción entre responsable y personas usuarias se presenta ahora en los bloques de perfiles y contexto. Sus referencias en la auditoría son históricas, no importaciones activas.
Los componentes nuevos viven en modules/companies/src/web/workstations/detail/; no se ha creado un framework de widgets ni trasladado lógica específica a la biblioteca visual genérica.
Consultas, relaciones y selección
El controller conserva inventario, puesto y operaciones locales. useWorkstationConfigurationQueries consulta recursos, Access, carpetas, correo, aplicaciones, impresoras, certificados, remoto y teletrabajo con claves centralizadas. Software utiliza su clave por compañía y soporte su clave por activo. No se crea una consulta por perfil o tarjeta de equipamiento.
Las consultas del detalle de perfiles/configuraciones/software/soporte no se habilitan sin un ordenador principal confirmado dentro de assetIds. El shell puede conservar sus consultas propias por compañía. Se ha retirado del controller la consulta de catálogo que ya no necesitaba esta composición; las especificaciones de activos proporcionan su plantilla legible.
Las relaciones se resuelven por ID y compañía. Los perfiles pertenecen al ordenador principal; el responsable procede de personId. Los activos actuales proceden exclusivamente de assetIds. Las impresoras configuradas por perfil y los activos históricos no se incorporan a ese equipamiento.
Perfiles activos y archivados se distinguen explícitamente; el acceso a archivados amplía la tabla existente. La ausencia de cuenta no invalida un perfil. El selector de configuraciones utiliza perfiles activos, conserva el ID seleccionado durante refetch y, si deja de ser válido, muestra el primer activo con una explicación. No se sincroniza estado remoto mediante efectos.
Cada configuración conserva su familia, perfil y procedencia. Aplicación del perfil e instalación de equipo son registros distintos. Las carpetas muestran estado y cobertura documental por separado, incluida cobertura desconocida. Cuando faltan metadatos de recursos/Access, se informa de esa dependencia y no se presenta una lista vacía como si fuese un resultado completo.
El soporte corresponde al ordenador. El contexto remoto identifica a la persona del perfil seleccionado y limita conexiones a las que usan ese activo como origen o destino. La autorización de teletrabajo es de esa persona. No se inicia conexión ni se deduce presencia, VPN activa o permiso efectivo sobre SMB.
Indicadores y revisiones
La única tarjeta estadística es «Configuraciones pendientes». Cuenta IDs distintos por familia de carpetas, correo, aplicaciones, impresoras y certificados en estado pending, con profileId de un perfil activo del principal y la misma compañía. Excluye legacy sin perfil, archivados, otras compañías, removal_pending, revisión y software instalado.
El total solo se presenta si perfiles y las cinco consultas necesarias tienen datos sin fallo. Ante fallo deja de ser definitivo, aunque se conserven datos anteriores. Sin ordenador la población de perfiles del principal es vacía y el total es cero. El botón de pendientes selecciona un perfil con pendientes, activa el filtro y lleva el foco a la sección.
Estado técnico y asignación de uso se distinguen: values.status describe el estado técnico; assigned indica reserva en un puesto activo. Un equipo averiado puede conservar su asignación y no debe aparecer como disponible. No se usa un semáforo global de salud.
Último cambio compara las dos últimas revisiones por fecha, sin mutar arrays: nombre, estado, sede, responsable, principal y miembros añadidos/retirados. Solo describe diferencias verificadas. No se mezclan eventos de otras entidades; las etiquetas relacionadas se resuelven con sus nombres disponibles actualmente.
Carga, errores y accesibilidad
La carga inicial conserva una geometría próxima al dashboard. Cada consulta secundaria presenta skeleton, actualización o error con reintento propio; no derriba la cabecera ni las otras tarjetas. Las tablas conservan datos y controles si falla una actualización con caché. No se desmonta el selector durante refetch ni se oculta la diferencia entre cero y total desconocido.
Se reutilizan enlaces reales, regiones nombradas, un h1, paneles h2 y subgrupos h3/h4. No hay contenedores con clic que sustituyan a enlaces. Los estados tienen texto, los iconos decorativos están ocultos y las tablas mantienen cabeceras. Las rutas largas se pueden leer completas mediante ajuste de línea; el overflow de tablas queda dentro de su zona.
El historial devuelve el foco al disparador concreto; el acceso a pendientes mueve el foco a una sección identificada. Las primitivas existentes gestionan teclado, menús, selectores y diálogos. La verificación interactiva y sus límites se registran abajo; no se declara cumplimiento WCAG global.
Entorno de pruebas y reproducción
Se utilizó el preparador aislado scripts/visual-audit.py, sin conectar a la BD habitual. Su MariaDB desechable utiliza exclusivamente metis_desk_test, API/Vite en puertos libres y sesión real de usuario ordinario. El origen anunciado de esta ejecución fue http://localhost:49383.
Preparación y pruebas reproducibles, desde WSL:
bash scripts/setup-playwright-wsl.sh
python3 scripts/visual-audit.py
# En otra terminal, con la ruta privada anunciada por el preparador:
METIS_PLAYWRIGHT_STORAGE_STATE=.artifacts/playwright/authenticated-ID/session.json \
PYTHONDONTWRITEBYTECODE=1 python3 scripts/visual-audit-volume.py
METIS_PLAYWRIGHT_STORAGE_STATE=.artifacts/playwright/authenticated-ID/session.json \
PYTHONDONTWRITEBYTECODE=1 python3 scripts/workstation-dashboard-fixtures.py
METIS_PLAYWRIGHT_STORAGE_STATE=.artifacts/playwright/authenticated-ID/session.json \
PYTHONDONTWRITEBYTECODE=1 python3 scripts/workstation-dashboard-ui.test.py
Los nuevos preparadores rechazan sesiones fuera de la ubicación privada y escenarios de otra instalación. Crean datos mediante HTTP real y CSRF. Las comprobaciones que sustituyen el principal o modifican la cuenta de carpeta restauran sus valores en finally. No se guardan credenciales en el informe ni se instala Chromium en WSL.
Volumen inicial de la auditoría interactiva: 15 compañías, 59 personas, 135 activos y 73 recursos en la compañía principal. La variante S04 tiene 80 miembros y 60 perfiles (50 activos y 10 archivados). S10 añade un activo sintético de sustitución, elevando después el inventario a 136; queda dentro del mismo entorno desechable.
Verificaciones y límites
Verificaciones ejecutadas sobre esta implementación:
| Comprobación | Resultado |
|---|---|
| Tipos de Companies, Assets, RDX UI y Web | Correctos con comandos dirigidos |
| Pruebas dirigidas de dashboard, relaciones y ficha | 20 pruebas correctas, usando --test-isolation=none para exponer cada caso |
| Biome sobre archivos del cambio | Correcto, sin supresiones |
| ESLint de espaciado sobre archivos del cambio | Correcto |
pnpm build |
Correcto; Vite conserva advertencia de bundle mayor de 500 kB |
| Playwright MCP | 11 métodos interactivos verificados mediante pasadas completas y dirigidas; cubren S01–S11, teclado, contraste, paginación y guardados reales |
pnpm typecheck global |
Se detiene en packages/shadcn-ui/src/components/calendar.tsx:165, por opcionalidad exacta de locale; vendor no modificado |
pnpm lint global |
15 errores fuera del cambio, principalmente bloques sin llaves en código de fotos; también diagnósticos de ejemplos de skills |
pnpm check global |
167 errores fuera del cambio, incluyendo formato de ejemplos/fixtures y código de fotos |
pnpm test global |
La última pasada completa deja 41 de 42 archivos de Companies correctos; falla únicamente companies-page.test.tsx, con las dos aserciones ajenas descritas abajo. El test del dashboard detectado inicialmente se corrigió y pasa |
Las dos aserciones ajenas esperan los literales Personas (1) y Esta persona no tiene acceso a Metis Desk; los archivos de compañías/personas afectados no se han modificado en esta tarea. No se amplía el alcance para corregirlas. Los fallos globales impiden declarar todo el monorepo en verde; las comprobaciones dirigidas distinguen el dashboard de esa deuda.
La primera pasada interactiva detectó etiquetas de prueba antiguas, una espera de refetch que no provocaba un evento de reconexión real y una comprobación de texto que incluía una etiqueta oculta al lector. Se corrigieron los recorridos sin ocultar fallos ni introducir esperas arbitrarias. También se corrigieron una etiqueta de compañía sin traducir y las cabeceras extensas de perfiles observadas en las capturas.
Quedan fuera de lo acreditado: comparación con la imagen original ausente, lector de pantalla real, zoom 200/400 %, modo oscuro y auditoría WCAG completa. No se implementa autorización granular por compañía: se conservan autenticación y comprobaciones de pertenencia existentes, con el límite documentado en la auditoría.
Evidencias visuales
Las capturas e informes sintéticos se guardan en .artifacts/playwright/workstation-dashboard-implementation/, fuera de Git. Se abrieron capturas de escritorio, móvil y fallos parciales para revisar la composición; la inspección final se detalla al cerrar la pasada.
Se generan S01 en 1600, 1440, 1280, 1024, 768 y 390 px; vistas de configuraciones; S02, S03, S04 de alta densidad, S05, S06, S07 con datos anteriores, S08 sin coincidencias, S10 y S11. measurements.json registra geometría, hashes y comprobaciones; no contiene cookies. Se han inspeccionado también S01 de 1600 px, configuraciones en 390 px, cobertura desconocida y desmantelado. Las mediciones no detectaron desbordamiento horizontal global en los seis anchos. El muestreo de 38 textos/acciones/enlaces dio contraste mínimo 5,03:1. No hubo excepciones JavaScript de página; los HTTP 503 simulados son parte de los escenarios de error. La ubicación local no garantiza conservación portable: al compartir el trabajo hay que adjuntar los PNG elegidos, nunca session.json.
Archivos del cambio
Los siguientes archivos contienen la implementación, sus pruebas o su documentación. Los ocho entregables originales de auditoría permanecen fuera de estos cambios.
- docs/componentes-de-interfaz.md
- docs/workplace-dashboard-implementacion.md
- modules/assets/src/common/locales/en.json
- modules/assets/src/common/locales/es.json
- modules/assets/src/web/index.ts
- modules/assets/src/web/workstations/history/ui/workstation-history-dialog.tsx
- modules/assets/src/web/workstations/shared/ui/workstation-actions.tsx
- modules/companies/package.json
- modules/companies/src/web/workstations/detail/controllers/use-workstation-configuration-queries.ts
- modules/companies/src/web/workstations/detail/controllers/use-workstation-detail-controller.ts
- modules/companies/src/web/workstations/detail/helpers/workstation-dashboard.test.ts
- modules/companies/src/web/workstations/detail/helpers/workstation-dashboard.ts
- modules/companies/src/web/workstations/detail/ui/workstation-assets.tsx
modules/companies/src/web/workstations/detail/ui/workstation-computer.tsx(componente histórico retirado en WD04.1)- modules/companies/src/web/workstations/detail/ui/workstation-configuration-family.tsx
- modules/companies/src/web/workstations/detail/ui/workstation-dashboard-skeleton.tsx
- modules/companies/src/web/workstations/detail/ui/workstation-detail-content.tsx
- modules/companies/src/web/workstations/detail/ui/workstation-detail-page.tsx
- modules/companies/src/web/workstations/detail/ui/workstation-detail.test.tsx
- modules/companies/src/web/workstations/detail/ui/workstation-latest-change.tsx
- modules/companies/src/web/workstations/detail/ui/workstation-pending-configurations.tsx
modules/companies/src/web/workstations/detail/ui/workstation-people.tsx— retirado; responsabilidad integrada en los bloques actuales.modules/companies/src/web/workstations/detail/ui/workstation-profile-configurations.tsx(componente histórico sustituido en WD04.2 por workstation-profile-configuration-details.tsx)- modules/companies/src/web/workstations/detail/ui/workstation-profiles.tsx
- modules/companies/src/web/workstations/detail/ui/workstation-query-feedback.tsx
modules/companies/src/web/workstations/detail/ui/workstation-responsible.tsx(componente histórico retirado en WD04.3; su información contextual pasa a workstation-responsible-context.tsx)- modules/companies/src/web/workstations/detail/ui/workstation-software-dialog.tsx
- modules/companies/src/web/workstations/detail/ui/workstation-software.tsx
- modules/companies/src/web/workstations/detail/ui/workstation-support.tsx
- packages/rdx-ui/src/components/detail-panel.tsx
- scripts/workstation-dashboard-fixtures.py
- scripts/workstation-dashboard-ui.test.py
Skills consultadas
frontend-design guio la composición específica y su revisión visual;
ux-dashboard, la jerarquía y la exclusión de estadísticas decorativas;
ux-tables, las cabeceras breves, comparación y manejo de volumen;
shadcn, la comprobación de APIs Base UI y composición de primitivas;
vercel-composition-patterns, los slots y la separación de responsabilidades;
vercel-react-best-practices, la caché compartida, la ausencia de efectos para datos
derivados y las consultas sin N+1. No se instaló ninguna skill ni auditor externo.
Comandos dirigidos adicionales
pnpm --filter @metis/companies typecheck
pnpm --filter @metis/assets typecheck
pnpm --filter @repo/rdx-ui typecheck
pnpm --filter @metis/web typecheck
TSX_TSCONFIG_PATH=tsconfig.json node --import tsx --test --test-isolation=none \
modules/companies/src/web/workstations/detail/helpers/workstation-dashboard.test.ts \
modules/companies/src/web/workstations/detail/helpers/workstation-relations.test.ts \
modules/companies/src/web/workstations/detail/ui/workstation-detail.test.tsx
Se comprobaron Biome y ESLint sobre la lista de archivos de código anterior y
git diff --check. Los comandos globales ejecutados fueron pnpm typecheck,
pnpm lint, pnpm test, pnpm check y pnpm build, con los resultados y límites
indicados. La sintaxis de los dos scripts Python se comprobó con ast.parse, sin
instalar paquetes ni dejar bytecode en el repositorio.
Capturas seleccionadas para revisión
- S01, escritorio 1600 px.
- S01, móvil 390 px.
- Configuraciones en móvil.
- Cobertura documental desconocida.
- Errores parciales.
- Puesto desmantelado.
Se conservan 18 PNG y el informe de medidas en esa carpeta estable. No incluye sesiones ni credenciales. El preparador y su contenedor se han retirado al terminar; se comprobó que la sesión privada ya no existe y las capturas permanecen para revisión local.
Refinamiento visual y adopción del listado compacto
Segunda iteración, 22 de octubre de 2026. Se mantiene el dashboard real y sus contratos.
El refinamiento sustituye la infraestructura de exploración dentro de las tarjetas por
el patrón compacto.
La captura anterior S01-1600.png se conserva y se ha inspeccionado. No se dispone del
mockup original aprobado: se aplica la especificación textual, sin afirmar fidelidad
exacta de píxeles. Los ocho documentos históricos de auditorias/workplace-dashboard/
permanecen intactos.
Componentes y operaciones
| Cambio | Resultado |
|---|---|
Nuevos CompactTable, CompactList, CompactListItem en rdx-ui |
Primitivas compartidas sobre Table/listas nativas, con identidad estable, nombres accesibles y textos aportados por el consumidor. Sin DTO, consultas ni dependencia de Workstation. |
Nuevo CollectionPreview en rdx-ui |
Resumen inicial de cinco elementos en perfiles, equipamiento y software; Mostrar todos/Mostrar menos permite acceder al conjunto cargado completo, sin paginación ni recorte silencioso. |
collection-cell-content.ts |
Extrae sin cambiar su lógica el criterio de ausencia de EntityTableContent; ambas tablas conservan —, cero, controles y contenido compuesto. |
WorkstationProfiles |
Compact Table con Perfil, Persona, Cuenta, Estado y Configuraciones; sin búsqueda, barras, Columnas, ordenación visible, rangos o pie de paginación. Orden estable por nombre e idioma. |
| Archivados | Acción compacta en la cabecera, con flecha decorativa y estado pulsado. Desaparece la línea adicional de nombres archivados. Se mantiene su consulta; el resumen inicial sigue mostrando perfiles activos. |
| Categorías | Etiquetas es/en breves según las familias reales: Correo, Carpeta, Aplicación, Impresora y Certificado. Se mantiene el enlace al perfil completo y sus avisos de revisión. |
WorkstationAssets |
Compact Item List con enlace, icono, plantilla, Principal y badges de estado técnico y uso. Miembros deduplicados por identidad; no se añaden impresoras de configuración ni miembros históricos. |
WorkstationSoftware |
Lista compartida con versión, licencia, estado y revisión. Conserva Gestionar software y su diálogo con alta, edición, borrado e historial. Sigue siendo software del principal, distinto de aplicaciones por perfil. |
WorkstationComputer |
Identidad/icono, estados técnicos/de uso como badges y botón secundario real para abrir el activo. Composición horizontal adaptable sin imágenes externas. |
DetailField density="compact" |
Variante opcional sin separadores, padding vertical de 4 px y columnas etiqueta/valor 0,7/1,3; solo Responsable y contexto la adopta. Default anterior intacto. |
WorkstationConfigurationFamily |
Adopta CompactList/CompactListItem y Badge. Mantiene nombres, rutas UNC, detalles, estados, revisión y destinos de gestión; reduce el espaciado y conserva metadatos a 12 px. |
| Cabecera y cuadrícula | Separación principal de 16 a 12 px; metadatos flexibles y cabecera con menor separación. Primera banda conserva exclusivamente ordenador y pendientes, con espacio libre intencional. |
| Tokens | Se retira el alias local de primary a secondary de la primera implementación. Acciones y enlaces usan los tokens reales de Metis, sin paleta propia ni cambios globales. |
| Soporte y último cambio | Se conservan sus componentes, subbloques, gestión y algoritmos. Se inspecciona su presentación completa; el soporte sigue siendo registro documental y el remoto se limita a la persona del perfil seleccionado. |
Se reutilizan DetailPanel, EntityListState/EntityListStatus, Badge, Button, Table,
BrowserLink, PersonAvatar, Skeleton y las primitivas Base UI instaladas. EntityTable
no cambia su composición ni comportamiento por defecto; solo comparte el helper de
contenido ausente. No se añaden dependencias, APIs, modelos, migraciones ni consultas.
Navegación contextual
La barra global la compone WorkspaceSidebar y la contextual CompanyFixedNavigation,
coordinadas por WorkspaceMobileNavigationProvider y los presupuestos de capacidad
vigentes. La global persiste metis-desk:sidebar-collapsed; companyHidden es estado de
sesión del provider. Ambas se usan en las rutas del workspace/compañía, no son un
componente exclusivo de la ficha del puesto.
Existe un mecanismo oficial: Ocultar secciones libera la columna contextual; la franja
con compañía/sección mantiene el contexto y abre la navegación completa en Sheet.
Fijar secciones permite volver a la columna cuando hay capacidad. Se comprueban ambos,
Escape, teclado y retorno de foco. A 1600 px, el ancho de main pasa de 1288 a 1528 px
al ocultarla manualmente y vuelve a 1288 al fijarla.
No se cambia el shell, ni se fuerza colapso por ruta, ni se añade otra preferencia. La captura comparable conserva la navegación fija anterior. El modo oculto es una elección explícita ya existente, evitando cambios inesperados de ancho al abrir la ficha.
Medidas antes y después
Misma instalación desechable, mismos datos S01 y ancho de 1600 px; coordenadas respecto al viewport con la página al inicio. Capturas a 1600×1000. Son mediciones de estos datos, no alturas CSS fijas ni garantías para todo contenido.
| Medida | Antes | Después |
|---|---|---|
| Alto Ordenador principal | 177 px | 113 px |
| Alto Personas y perfiles | 510,5 px | 221,5 px (−57 %) |
| Alto Responsable y contexto | 289 px | 197 px (−32 %) |
| Alto Equipamiento | 462,5 px | 186 px |
| Alto Software | 215 px | 185 px |
| Inicio de Equipamiento y Software | Y=959,5 | Y=618,5 (341 px antes) |
| Inicio de Configuraciones y Soporte | Y=1438 | Y=816,5 |
| Ancho de main, navegación fija | 1288 px | 1288 px |
| Proporción de columnas | 1,6:1 | 1,6:1, aproximadamente 62/38 |
| Separación entre tarjetas | 16 px | 12 px |
La mejora procede de retirar herramientas y separadores redundantes, no de reducir el texto principal. Equipamiento y software caben completos en la primera pantalla de escritorio, además de identidad, primera banda y perfiles/contexto; comienza a verse la siguiente banda. Las rutas y nombres completos mantienen acceso legible.
| Ancho | Scroll global antes/después | Alto Perfiles antes/después | Comportamiento |
|---|---|---|---|
| 1600 | 1600/1600 px | 510,5/221,5 px | Dos columnas, primera banda con separación libre. |
| 1440 | 1440/1440 px | 558,5/261,5 px | Dos columnas; encabezado y nombres se adaptan al espacio. |
| 1280 | 1280/1280 px | 474,5/221,5 px | Bandas adaptadas al contenedor; sin comprimir columnas de comparación. |
| 1024 | 1024/1024 px | 474,5/221,5 px | Navegación responsive existente, contenido apilado cuando corresponde. |
| 768 | 768/768 px | 526,5/221,5 px | Acciones flexibles y flujo vertical. |
| 390 | 390/390 px | 739,5/294,5 px | Tabla con ancho comparativo mínimo de 36 rem y desplazamiento propio; listas apiladas y texto completo consultable. |
El objetivo orientativo de 160–220 px queda próximo en escritorio con dos perfiles; a 1440 px el encabezado/filas requieren más espacio. Se conserva altura natural, sin recortar nombres, botones o estados para cumplir una cifra. Los rangos 0/1/2/10/60 se cubren en pruebas de componente; S04 comprueba 50 activos y diez archivados, 60 perfiles en total, y 80 miembros alcanzables desde la ampliación.
Evidencias y pruebas
Las capturas están en .artifacts/playwright/workstation-dashboard-refinement/, con
subdirectorios before y after, excluidos de Git. Se copian solo PNG y mediciones
sanitizadas, nunca la sesión. Los enlaces requieren conservar esa carpeta para compartir
el informe con sus imágenes.
- S01: antes a 1600, después a 1600, 1440, 1280, 1024, 768, 390.
- Secciones: Personas y perfiles, Equipamiento, Software, Configuraciones, Soporte, Último cambio.
- Página completa, S04 denso, navegación contextual oculta, compañía larga en móvil.
La captura completa expande temporalmente los contenedores de scroll solo durante la captura y restaura estilos/coordenadas en finally. Las medidas responsive se toman con el layout normal. Las capturas de secciones de antes se obtuvieron antes de modificar las tarjetas y se conservan junto a las nuevas. Se abren e inspeccionan capturas reales; una ejecución correcta de tests no se presenta como una revisión visual automática.
Preparación: setup-playwright-wsl.sh, visual-audit.py, visual-audit-volume.py y
workstation-dashboard-fixtures.py, mediante el servidor MCP Docker oficial fijado en
la configuración del proyecto. Únicamente MariaDB desechable metis_desk_test, API y
Vite temporal en puertos libres. Volumen inicial: 15 compañías, principal con 59 personas,
135 activos y 73 recursos; la sustitución de principal crea un activo adicional. El
usuario ordinario entra mediante el formulario real, con CSRF y contratos existentes.
Validación dirigida:
- 34 pruebas de colecciones correctas: cinco nuevas y 29 de EntityTable; semántica, enlaces, ausencia de herramientas, escenarios de volumen, carga/error/caché, ausencias, cero y contrato completo de EntityTable conservado.
- 20 pruebas dirigidas del dashboard y sus relaciones correctas en es/en.
- 15 métodos interactivos MCP comprobados: los primeros 14 pasan en la ejecución conjunta final y el caso de compañía larga pasa en ejecución dirigida tras corregir su fixture para respetar el máximo real de 100 caracteres. Se verifican los seis anchos, todos los elementos de S04, estados parciales, gestión y guardados reales. Sin excepciones JavaScript de página; 38 muestras de contraste de texto/enlaces/acciones, mínimo 4,53:1 en el tema claro.
- Tipos de Companies, Assets, rdx-ui y Web correctos; Biome del código/JSON afectado y ESLint de espaciado correctos. Paridad de claves es/en y sintaxis Python comprobadas.
pnpm build: correcto; conserva el aviso anterior de chunks superiores a 500 kB.- Checks globales ejecutados:
pnpm typechecksigue fallando en vendor calendar.tsx:165;pnpm lintypnpm check, con 15/167 errores previos fuera del cambio.pnpm testmantiene el fallo anterior de companies-page.test.tsx (41/42 ficheros Companies pasan; los otros siete paquetes completan correctamente). No se corrige código ajeno ni vendor.
La suite MCP actualiza los recorridos anteriores al contrato compacto, sin eliminar la cobertura de operaciones: archivados, alta, selector, software, gestión, historial, renombrado, responsable/composición, errores parciales, caché obsoleta, reintento, conteo, principal sustituido, autenticación, teclado, foco y contraste. Las pruebas de búsqueda paginada del resumen se sustituyen por ausencia de esas herramientas y ampliación con acceso a todos los elementos; los listados completos conservan sus pruebas propias.
Las primeras ampliaciones del script necesitaron corregir selectores de regiones anidadas y la etiqueta accesible «Secciones de [compañía]». El perfil creado se retira siguiendo su ciclo de vida (desactivar antes de eliminar). Fueron ajustes del recorrido, sin nuevos defectos demostrados del producto. Las modificaciones sintéticas de los escenarios de escritura se restauran en finally.
Skills, diferencias y límites
Se consultaron las seis skills instaladas solicitadas: frontend-design (composición y jerarquía), ux-dashboard (relevancia y densidad), ux-tables (comparación/lista y lectura), shadcn (primitivas, tokens y Base UI), vercel-composition-patterns (composiciones distintas sin flags de EntityTable) y vercel-react-best-practices (sin duplicar estado remoto ni consultas por fila). Se revisó su matriz y referencias aplicables. El CLI shadcn no está expuesto como ejecutable local; se contrastaron las APIs reales instaladas, sin instalar ni regenerar componentes. No se invocaron auditores especializados ausentes.
Tabler, Inter, el primario rojo, las primitivas Badge existentes y la navegación del producto prevalecen sobre cualquier detalle no verificable del mockup. No se han inventado estados, salud del equipo, conexiones en tiempo real o permisos efectivos. No se cambia la cobertura documental, el conteo de pendientes, la selección durante refetch, el algoritmo de diferencias ni los contratos de acceso.
Continúan fuera de la verificación práctica completa lector de pantalla, zoom 200/400 %, modo oscuro, rendimiento bajo cientos de filas y cumplimiento WCAG global. Las nuevas colecciones no implementan búsqueda, ordenación interactiva o paginación remota; esas capacidades no se afirman por estar contempladas como opcionales en el estándar.
Cierre de la entrega: 20 archivos de código/JSON pasan Biome y los TS/TSX afectados
pasan ESLint de espaciado; git diff --check correcto. Se comprueban 231 enlaces locales
y doce anclas de la documentación afectada, incluidos los destinos de capturas.
Las evidencias conservan 14 PNG anteriores y 28 posteriores, además de mediciones.
El preparador se cerró mediante SIGINT: retiró sus servicios, contenedor y sesión privada;
se comprobó que session.json ya no existe. Las capturas sanitizadas permanecen disponibles.
WD04.1 — Equipamiento unificado
Fecha: 23 de octubre de 2026. Alcance limitado a la unificación de la representación de los miembros del puesto. Se conservan los cambios locales de las entregas anteriores. Los ocho documentos históricos de auditoría no se modifican.
Composición y componentes
Antes se mostraban una tarjeta de Ordenador principal y otra de Equipamiento que volvía
a incluirlo. Ahora existe una sola tarjeta Equipamiento, inmediatamente después de
la cabecera, junto a Configuraciones pendientes. El principal es su primer miembro
válido, con icono de plantilla, nombre enlazado, tipo y badge Principal en la misma
línea de metadatos. Conserva los badges técnico y de uso sin un tamaño especial ni
una tarjeta anidada. Los secundarios mantienen el orden declarado en assetIds.
Después se conservan Personas y perfiles y Responsable y contexto; Configuraciones por perfil queda a la izquierda de Software y Soporte. Último cambio se sitúa después de la cuadrícula, a ancho completo. Solo cambia la colocación de esos componentes, no su presentación interna, sus acciones ni sus cálculos. El shell y la cabecera no se rediseñan.
| Archivo / componente | Cambio WD04.1 |
|---|---|
workstation-detail-content.tsx |
Una única instancia de WorkstationAssets en la primera banda; elimina su ubicación anterior y el render de WorkstationComputer. Recoloca Software y Último cambio según la composición objetivo. |
workstation-assets.tsx |
Reutiliza CompactList, CompactListItem, CollectionPreview, DetailPanel, Badge y EmptyState. Añade avisos de consistencia y feedback de inventario. |
workstation-equipment.ts y su test |
Selector presentacional de referencias actuales, con resolución por ID/compañía, deduplicación, principal válido primero y diagnóstico de referencias. No sustituye el modelo funcional del dashboard. |
workstation-computer.tsx |
Retirado. Búsqueda en el monorepo: solo tenía un consumidor de código, WorkstationDetailContent; los demás resultados eran referencias documentales. WorkstationComputerField del editor es otro componente y se conserva. |
use-workstation-detail-controller.ts |
Conserva íntegros computer, perfiles, fuentes y conteo. Reutiliza la consulta de catálogo de activos por compañía para resolver iconos reales. |
modules/assets/src/web/index.ts |
Expone el AssetTemplateIcon existente para el consumidor real de Companies; no se duplica la correspondencia entre claves e iconos. |
workstation-detail-page.tsx |
En fallo inicial sin datos muestra Equipamiento con error/reintento. Con inventario conocido, el feedback vive en la tarjeta, no en una lista vacía. |
workstation-dashboard-skeleton.tsx |
Retira el placeholder de ordenador independiente y conserva un único espacio de equipamiento. |
| Locales es/en de Assets | Dos avisos de principal inconsistente/no disponible; retira la etiqueta openAsset sin consumidores después de eliminar la tarjeta independiente. |
| Tests de detalle, nuevo test de equipamiento y script MCP | Añaden cobertura de unicidad, posición, errores, consistencia, navegación y estados; conservan los recorridos de gestión anteriores. El script de tests de Companies incluye el nuevo fichero. |
La consulta de catálogo utiliza catalogKeys.scope(company.id) y catalogApi.get,
compartida y deduplicada por TanStack Query. Se habilita cuando el puesto tiene
miembros; no es una consulta por activo ni depende de que exista principal. Usa el
icono de la plantilla por ID; si los metadatos todavía no están disponibles, utiliza
la caja genérica y conserva el tipo legible de la especificación. No infiere el
principal por nombre, icono, tipo o posición del inventario. No hay endpoints,
contratos HTTP, dependencias, modelos, migraciones o políticas de acceso nuevos.
Datos, acciones y estados
La composición procede exclusivamente de values.assetIds actuales, deduplicados.
computerAssetId identifica al principal solo cuando esa referencia pertenece a la
composición y resuelve un activo de la compañía. No se incorporan activos históricos
ni impresoras asociadas únicamente a configuraciones de perfil. El selector no modifica
los arrays recibidos; los secundarios conservan un orden determinista independiente
del orden de llegada del inventario.
Se conserva Editar puesto en la cabecera de Equipamiento como acción contextual de composición. Abre el mismo editor y utiliza el mismo callback que la acción global; no crea otro diálogo ni otra operación. En vacío se ofrece una única acción dentro del estado vacío, sin repetirla también en la cabecera de esa tarjeta. En fallo inicial sin puesto conocido no se inventa una acción de edición.
El nombre de cada activo sigue siendo un BrowserLink a su ficha real. Esa navegación conserva la capacidad anterior de Abrir ficha del activo; no queda un botón redundante para el principal ni se usan contenedores clicables en lugar de enlaces.
| Caso | Presentación |
|---|---|
| Principal válido | Primera fila, una única vez, badge Principal y estados del activo real. |
| Miembros sin principal | Muestra los miembros, indica discretamente que no hay ordenador principal y conserva edición. No elige el primer portátil como sustituto. |
| Sin activos | EmptyState dentro de Equipamiento con descripción y edición de composición. |
| Inactivo/desmantelado | Solo composición actual; el historial sigue disponible por la operación existente. No recupera miembros de revisiones. |
| Principal fuera de assetIds | Aviso explícito para revisar el puesto, sin incorporarlo ni marcar otro miembro como principal. |
| Referencia ausente o de otra compañía | Aviso de principal no disponible y fila de referencia no resuelta, sin inventar nombre, tipo o estados; no se muestra el badge Principal. |
| Fallo de inventario sin caché | Equipamiento con error recuperable; no muestra vacío, contador cero ni detalles de un puesto desconocido. El resto requiere recuperar los datos del puesto. |
| Refetch / error con datos previos | Mantiene la composición y la ampliación existentes y muestra el feedback de consulta. |
Estado técnico sigue siendo asset.values.status; uso sigue siendo asset.assigned.
Un activo averiado puede continuar asignado. No se deriva disponibilidad del estado
técnico ni se modifica la condición de asignación de puestos inactivos.
workstationDashboard.computer y la resolución del controller permanecen. Software,
soporte, perfiles y configuraciones siguen dependiendo del principal confirmado dentro
de assetIds. La nueva función de presentación conserva también referencias no resueltas
para explicarlas; no cambia los miembros resueltos que usa el modelo funcional. La
selección de perfil, el algoritmo de diferencias, cobertura documental y políticas de
Access permanecen intactos. Los nombres del equipo que aparecen como contexto de una
conexión remota no son otra tarjeta ni otro listado de miembros.
Responsive y comparación visual
Se conservaron capturas del estado anterior en esta misma instalación, antes de modificar las tarjetas. Las posteriores se inspeccionaron visualmente: S01 de escritorio y móvil, S03, S06, S04 denso, casos sin principal, inconsistencias y fallo/recuperación. Se mantiene la cuadrícula por contenedor, el espacio libre antes del indicador de pendientes y la proporción 1,6:1 en escritorio. En móvil Equipamiento ocupa el ancho y Pendientes aparece después. No hay alturas fijas de filas ni recortes de activos.
Medidas S01 a 1600×1000, al inicio de la página:
| Medida | Antes | WD04.1 |
|---|---|---|
| Paneles del dashboard | 9 | 8 |
| Representaciones del principal como miembro/resumen | 2 | 1 |
| Inicio de Equipamiento | Y=618,5 px | Y=228 px |
| Alto de Equipamiento, dos miembros | 186 px | 169 px |
| Ordenador principal separado | 113 px | Retirado |
| Pendientes: inicio / alto | Y=228 / 145 px | Y=228 / 145 px |
| Inicio de Configuraciones por perfil | Y=816,5 px | Y=642,5 px |
| Alto de Personas y perfiles | 221,5 px | 221,5 px |
| Alto de Responsable y contexto | 197 px | 197 px |
| Inicio de Software | Y=618,5 px | Y=642,5 px |
El objetivo es eliminar duplicación y fragmentación, no forzar una altura total menor. En escritorio la mayor primera banda y el último cambio a ancho completo dejan la altura total prácticamente equivalente en esta muestra. En móvil se reduce el recorrido al retirar el resumen duplicado. Las últimas revisiones cambian durante los guardados de prueba, por lo que la altura de su resumen también responde a datos reales.
| Ancho | Alto Equipamiento WD04.1 | Borde inferior de Último cambio antes/después | Overflow global |
|---|---|---|---|
| 1600 | 169 px | 1770,5 / 1773,5 px | Ninguno |
| 1440 | 169 px | 1862,5 / 1866,5 px | Ninguno |
| 1280 | 169 px | 2827,5 / 2617,5 px | Ninguno |
| 1024 | 169 px | 2877,5 / 2667,5 px | Ninguno |
| 768 | 169 px | 3014,5 / 2852,5 px | Ninguno |
| 390 | 229 px | 3895,5 / 3605,5 px | Ninguno |
S04 conserva vista inicial de cinco miembros y permite ampliar hasta los 80. El principal sigue primero y el botón de ampliación conserva foco/estado durante una recarga. No se introduce paginación ni se hacen inaccesibles los miembros restantes.
Evidencias sanitizadas, fuera de Git, en .artifacts/playwright/workstation-dashboard-wd041/:
- Antes S01 1600, WD04.1 S01 1600, 1440, 1280, 1024, 768, 390.
- Página completa, S03 vacío, S06 desmantelado, S04 denso.
- Miembros sin principal, principal fuera de composición, referencia no resuelta, referencia de otra compañía, inventario fallido, inventario recuperado.
Las capturas completas utilizan el procedimiento temporal ya documentado, restaurando los estilos después. Las medidas normales se registran en measurements.json de cada fase. Para compartir las imágenes hay que conservar la carpeta de evidencias; no se copia la sesión privada.
Validación WD04.1
Entorno: Node 24.20.0 y PNPM 11.25.0. Se reutilizan los preparadores existentes de auditoría
con MariaDB independiente exclusivamente metis_desk_test, API/Vite en puertos libres
y usuario ordinario autenticado por el formulario real. Volumen: 15 compañías, principal
con 59 personas, 135 activos y 73 recursos; S04 con 80 miembros y 60 perfiles. El escenario
de sustitución de principal añade un activo temporal más.
- 29 pruebas dirigidas correctas, incluidas seis nuevas del selector y tres nuevas de presentación. Cubren orden principal/secundarios, deduplicación, ámbito, vacío, desmantelado, falta de principal, inconsistencias, estado técnico/uso, unicidad de la sección y navegación; se conservan las pruebas previas de relaciones y funcionalidades.
- 20 métodos MCP comprobados. El pase inicial de 15 tuvo una interrupción de browser_navigate y un timeout al fijar la navegación contextual; ambos recorridos pasaron al repetirse sin modificar navegación o Access. El pase complementario de esos dos y los cinco escenarios nuevos fue correcto (7/7). La captura/medición de los seis anchos se repitió correctamente con la presentación final.
- Edición real de responsable/composición, renombrado, alta/retirada de perfil, archivados, selector y refetch, gestión de software, soporte registrado visible, pendientes y su foco/filtrado, historial, principal sustituido y cobertura desconocida siguen verificados. Las escrituras sintéticas restauran valores en finally.
- Los casos incoherentes o referencias ajenas se simulan interceptando respuestas GET de la instalación desechable; no se saltan invariantes para persistirlos. El caso sin principal se prepara con el update real y se restaura después. El error 503 se retira y se comprueba recuperación con Reintentar.
- Tipos dirigidos de Assets, Companies y Web correctos. Biome y ESLint dirigidos, paridad es/en y comprobaciones documentales se ejecutan sobre los archivos afectados.
pnpm buildcorrecto. Permanecen el aviso previo de chunks grandes y los fallos globales ya existentes: typecheck en calendar.tsx:165 de vendor; lint/check con 15/167 errores ajenos; test en companies-page.test.tsx. En Companies pasan 42/43 ficheros, incluidos todos los del dashboard; los otros siete paquetes de tests completan correctamente.
No se afirma un pase global limpio ni una validación WCAG completa. La muestra de contraste contiene 36 elementos, mínimo 4,53:1; no hubo excepciones JavaScript de página. Lector de pantalla, zoom 200/400 %, modo oscuro y rendimiento con más volumen permanecen fuera de las comprobaciones prácticas de esta entrega.
Skills aplicadas: ux-dashboard como principal para agrupar la composición sin duplicar información; frontend-design y ux-tables para jerarquía y densidad; shadcn para reutilizar las APIs/tokens instalados; composición y React para mantener un único consumidor de Equipamiento y estado remoto en TanStack Query. Se consultaron la matriz y los criterios instalados pertinentes, sin instalar skills ni dependencias ni modificar vendor.
No se integra Configuraciones en Perfiles, no se retira Responsable y contexto, no se reestructura Soporte y no se modifica la cabecera ni la navegación lateral. Esas tareas quedan para entregas posteriores.
Cierre WD04.1: 12 archivos TS/TSX/JSON pasan Biome y los TS/TSX afectados pasan ESLint.
git diff --check correcto; 73 enlaces locales y dos anclas del informe comprobados,
paridad es/en y sintaxis Python correctas. Se conservan 14 PNG anteriores y 34 posteriores.
El preparador retiró sus servicios y contenedor al recibir SIGINT; se comprobó la retirada
de session.json. Las capturas y mediciones sanitizadas permanecen disponibles.
WD04.2 — Personas, perfiles y configuraciones unificados
Fecha: 23 de octubre de 2026. Implementación sobre la composición WD04.1.
Arquitectura e interacción
Antes, Personas y perfiles y Configuraciones por perfil eran dos tarjetas. La segunda
mostraba automáticamente el primer perfil y añadía un selector independiente. Ahora
una única tarjeta combina WorkstationProfiles (CompactTable) y
WorkstationProfileConfigurationDetails (contenido contextual). Desaparecen la tarjeta
y el selector anteriores. El antiguo componente solo tenía un consumidor; se retira
tras buscar sus referencias. Los ocho entregables históricos de auditoría se conservan.
La primera banda mantiene Equipamiento y Pendientes. El segundo grid conserva los umbrales y proporción 1,6:1; la izquierda contiene Personas y perfiles y la derecha apila Responsable y contexto, Software, Soporte y Último cambio. Las alturas son independientes. Equipamiento, cabecera, navegación y operaciones de software mantienen sus componentes existentes; no se implementa WD04.3.
La tabla conserva Perfil, Persona, Cuenta, Estado y Configuraciones, con sus enlaces
independientes, alta y acceso a archivados. El resumen muestra categorías reales o el
estado confirmado sin configuraciones; una fuente incompleta muestra «—». Cada perfil activo
tiene un botón explícito Ver/Ocultar con nombre accesible que incluye el perfil,
aria-expanded, aria-controls e indicador de dirección. La fila conserva semántica
HTML de tabla y no se convierte en un control interactivo.
La expansión empieza cerrada, es única, permite contraer y sustituye el detalle al
abrir otro perfil. Se reutiliza Collapsible de Base UI mediante el wrapper vendor,
controlado por la selección; los activadores explícitos están en las celdas y el
panel único aparece debajo de la tabla, dentro de DetailPanel y fuera de su scroll
horizontal. El panel controlado permanece como destino de aria-controls; el contenido
de configuración solo se monta para el perfil abierto. No se modifica CompactTable
ni se crea infraestructura genérica de acordeones.
Estado y navegación contextual
useWorkstationProfileExpansion conserva exclusivamente contexto, identidad expandida,
filtro, solicitud de foco y aviso de retirada. reconcileProfileExpansion restablece
el estado ante cambio de compañía, puesto o principal; conserva selección y filtro
ante refetch/error y solo una respuesta válida puede cerrar un perfil eliminado,
archivado o retirado del host. Muestra un aviso y no abre otro detalle automáticamente.
Soporte conserva su contrato: contexto del perfil expandido cuando lo hay y primer
perfil activo como contexto predeterminado al estar contraídos; su persona sigue
identificada explícitamente. Esto no abre otro detalle tras una retirada.
Las transiciones se comprueban durante render; no se copian datos de consulta mediante
efectos. Los efectos nuevos sincronizan únicamente foco y scroll con el DOM.
Pendientes sigue contando las cinco familias de todos los perfiles activos. Su acción elige el primero con pendientes en el mismo orden estable del resumen: nombre por idioma, comparación numérica y sin distinguir tildes/mayúsculas; ID desempata. Abre el perfil, activa Solo pendientes y enfoca/desplaza el detalle una vez montado. Cambiar manualmente de perfil reinicia el filtro. Cero no ofrece esta acción; una fuente fallida mantiene el total desconocido. El filtro no altera el contador global.
CollectionPreview sigue ofreciendo cinco filas y Mostrar todos. Si el destino de pendientes está fuera del resumen, se añade su fila contextual a esas cinco, sin cargar los detalles de los demás perfiles ni desplegar todo el conjunto. Mostrar todos permite alcanzar los 50 activos y los 60 perfiles al incluir archivados en S04. Los archivados conservan estado y enlace a su ficha histórica; no reciben expansión operativa y no contribuyen a pendientes actuales.
Datos, familias, operaciones y fallos parciales
Se reutilizan las consultas agregadas por compañía y sus claves actuales: inventario,
perfiles, Access, Recursos y las cinco familias. No hay consultas por fila, endpoints,
contratos HTTP, schemas, migraciones ni dependencias nuevos. El perfil se resuelve en
el host actual y la misma compañía; buildEnvironment conserva el cálculo del entorno.
WorkstationConfigurationFamily mantiene Carpetas, Correo, Aplicaciones, Impresoras y
Certificados, sus estados, notas, revisión y enlaces Gestionar a las rutas reales del
perfil. Los encabezados pasan a h4 dentro del detalle h3 de la tarjeta h2. Carpetas
conserva ruta UNC, unidad, cuenta y cobertura documental; no se representa acceso SMB
efectivo. Aplicaciones se mantiene separada del software del equipo. Las impresoras
configuradas no se agregan a Equipamiento y los certificados conservan sus fechas y
revisiones calculadas por las fuentes existentes.
Los perfiles se muestran sin esperar las fuentes secundarias. Al abrir el detalle, cada familia conserva su indicador de carga, datos anteriores, error y reintento. Un fallo de Carpetas no oculta perfiles, correo o certificados. Recursos y Access mantienen su feedback y las familias dependientes no aparentan resolución completa sin sus datos. El vacío global del perfil solo se anuncia tras confirmar todas las fuentes y mantiene los cinco enlaces reales de gestión, sin repetir cinco mensajes vacíos. Alta, edición de puesto, historial y gestión de familias reutilizan las pantallas y diálogos existentes, sin formularios paralelos.
La expansión es estado local de la ficha. Se conserva durante mutaciones/refetch que mantienen montado el dashboard, incluidos los diálogos de puesto y alta de perfil. Las rutas de gestión de familias conservan la navegación existente; abandonar y abrir de nuevo la ficha inicia sus perfiles contraídos. No se añade persistencia ni otra URL de selección.
Accesibilidad, responsive y criterios consultados
Botones nativos activables con Enter/Espacio; enlaces de persona, cuenta y perfil
independientes; sin controles anidados. El salto de pendientes enfoca una sección
nombrada y con tabIndex=-1. Contraer manualmente conserva el foco del activador.
Si un refetch retira el detalle enfocado y el navegador deja el foco en body, el aviso
recibe el foco. Los errores conservan alertas y acciones de recuperación por fuente.
Todos los textos nuevos están en es/en.
Se conserva CompactTable. Por debajo de 600 px del contenedor, Perfil reúne persona,
cuenta y estado; Configuraciones conserva el resumen y Ver/Ocultar a la vista. Las
columnas separadas de Persona/Cuenta/Estado se ocultan en esa presentación, conservando
sus datos en la celda de identidad. WorkstationProfilePerson comparte la misma
identidad enlazada en ambas distribuciones. No se duplica el detalle expandido.
El scroll de tabla queda contenido si algún contenido excepcional lo requiere. El
detalle utiliza todo el ancho de la tarjeta, permite partir nombres/rutas y no fuerza
alturas. La composición se reduce a una columna por capacidad del contenedor.
Skill principal consultada: ux-dashboard, para reunir perfil y entorno y desplegar
el detalle bajo demanda. Complementarias: ux-tables (semántica y acciones explícitas),
frontend-design (jerarquía y superficies del sistema existente), shadcn (contratos
Base UI instalados), vercel-composition-patterns (composición mediante children),
vercel-react-best-practices (estado mínimo y consultas agregadas) y ux-error-recovery
(recuperación local y conservación del contexto). Se consultaron DESIGN, matriz de
skills, patrón compacto, catálogo de componentes, procedimiento Playwright y documentos
01/02/04/05/06/07 de auditoría. Los auditores especializados *-audit y la política de
orquestación citada por las skills no están instalados; no se instalan herramientas.
Pruebas y evidencias WD04.2
Entorno WSL/bash, Node 24.20.0 y PNPM 11.25.0. Preparador desechable autenticado con
usuario ordinario, MariaDB exclusivamente metis_desk_test. Se prepararon 15 compañías;
la principal alcanzó 59 personas, 135 activos y 73 recursos. El caso S04 tiene 80
miembros y 60 perfiles (50 activos y 10 archivados). El recorrido de sustitución creó
un activo sintético adicional, por lo que algunas capturas muestran 136 activos. No se
poblaron bases reales ni se consultaron secretos locales.
| Comprobación ejecutada | Resultado |
|---|---|
| Cinco archivos de pruebas del detalle: dashboard, relaciones, equipamiento, expansión y renderizado es/en | 35 pruebas correctas |
pnpm --filter @metis/companies typecheck, Assets y Web |
Correctos |
| Biome sobre los 15 TS/TSX/JSON afectados; ESLint sobre sus TS/TSX | Correctos |
pnpm build |
Correcto; permanece el aviso de tamaño de chunks |
pnpm typecheck global |
Bloqueado por el error previo de calendar.tsx:165 en vendor (exactOptionalPropertyTypes y locale) |
pnpm lint / pnpm check globales |
Persisten los 15 / 167 errores previos, respectivamente; no se modifican los archivos ajenos |
pnpm test global |
Siete paquetes correctos; Companies pasa 43/44 archivos. Falla el archivo previo companies-page.test.tsx |
git diff --check, sintaxis del runner Python y paridad de claves nuevas es/en |
Correctos |
Las pruebas nuevas verifican transición inicial/abrir/contraer/sustituir, selección
única, conservación en refetch y fallo, invalidación por retirada/archivo y reset por
compañía/puesto/host; orden determinista, pendientes de varios perfiles, aislamiento,
resumen cero y contenido contextual. Las pruebas existentes de buildEnvironment
conservan los contratos documentales y de estados en la suite del módulo.
Playwright MCP completó una ejecución conjunta de 24/24 recorridos. Después de los ajustes de vacío y móvil se repitieron los recorridos afectados y se añadieron cuatro: 28 métodos diferentes comprobados satisfactoriamente entre las ejecuciones, sin afirmar una ejecución conjunta única de los 28. La última tanda de cierre pasó 3/3.
Se comprobó expansión de los dos perfiles S01, contracción, sustitución, vacío, archivados, pendientes/certificado/filtro, contador global con varios perfiles, destino fuera de las cinco filas de S04, conservación de selección/filtro/foco, cambio de principal en vivo, retirada de un perfil abierto con aviso y foco, error recuperable de Carpetas y Recursos, carga de Certificados dentro del detalle, recuperación y metadatos incompletos. Cambiar entre perfiles produjo 5 consultas antes y 5 después, sin consultas por fila.
Las cinco acciones Gestionar se navegaron hasta sus pantallas reales. Se guardaron notas de certificado y el nombre de un perfil mediante los formularios existentes, se verificó su lectura en el dashboard y se restauraron sus valores por HTTP. Alta, edición de puesto/responsable/composición, historial, software, navegación contextual, enlaces, teclado y aislamiento de sesión conservaron sus recorridos de regresión. Las mutaciones sintéticas añaden revisiones aunque se restauren los valores actuales.
Se midieron las seis anchuras (1600, 1440, 1280, 1024, 768 y 390), contraído y expandido, sin overflow horizontal global. A 390, la tabla final mide 326 px tanto de contenido como de viewport, con scrollLeft 0: persona, estado y expansión visibles. Tab recorre perfil → persona → cuenta → expansión; Espacio abre el detalle. Enter, Espacio, foco visible y retorno desde diálogos se verificaron en los recorridos de teclado. Se midieron 30 muestras de texto/acciones: contraste mínimo observado 4,53:1 en tema claro, no una certificación global de accesibilidad. No hubo errores JavaScript no capturados en página; los 503 de los escenarios de fallo fueron deliberados.
Las primeras iteraciones de pruebas necesitaron adaptar selectores al nuevo detalle, esperar el render tras refetch, usar el contrato real de certificado al restaurar y liberar la petición retenida mediante su Route. El retorno contextual del perfil vuelve al dashboard; para editar se utiliza el enlace al listado completo y su búsqueda. La prueba móvil detectó 2 px de overflow interno, corregidos ampliando la columna de acciones y permitiendo ajustar el nombre. Esos casos se repitieron hasta obtener los resultados indicados; no se silencian sus fallos anteriores como si hubieran pasado a la primera.
Comparación visual y capturas WD04.2
Se conservan 14 PNG anteriores y 49 posteriores, incluidas iteraciones y escenarios
funcionales, con measurements.json y huellas SHA-256 en los directorios ignorados de
Playwright. Las capturas se abrieron y revisaron: escritorio, móvil, detalle integrado,
vacío compacto y carga parcial. No se guardan sesiones en estos directorios estables.
| Aspecto | Antes | WD04.2 |
|---|---|---|
| Tarjetas del dashboard | 8 | 7 |
| Selector independiente de perfil | 1 | 0 |
| Relación visual de configuraciones | Tarjeta separada | Detalle contextual dentro de Personas y perfiles |
| Detalles de configuración montados | Primer perfil seleccionado por defecto | Ninguno inicialmente; uno al expandir |
| Vacío de perfil | Cinco mensajes por familia | Una explicación y cinco accesos de gestión |
| Móvil | Control fuera del ancho inicial de la tabla | Identidad agrupada y expansión visible |
| Columnas inferiores | Filas del grid compartidas | Dos pilas de altura independiente |
En las capturas iniciales de 390, el borde inferior del último bloque pasa de 3642 a 2818 px; a 1280, de 2638 a 1930 px. Son muestras de la presentación inicial contraída, no una promesa de reducción fija: el detalle expandido crece con sus datos y las pruebas de guardado modifican el historial mostrado en Último cambio. No se igualan alturas ni se recorta contenido para obtener esas diferencias.
- Antes a 1600, después a 1600 y página completa.
- Detalle integrado, perfil vacío y pendientes.
- Móvil final, móvil expandido, 1440, 1280, 1024 y 768.
- Carga del detalle, Recursos no disponibles, archivo durante refetch, certificado guardado y pendiente fuera del resumen S04.
Limitaciones y cierre WD04.2
No se certifica WCAG, uso con lector de pantalla, zoom, tema oscuro ni dispositivos físicos: las evidencias corresponden a Chromium/MCP y los tamaños indicados. Las lecturas agregadas siguen siendo independientes y no forman una fotografía transaccional. La selección local se restablece al abandonar la ficha; no se introduce persistencia de expansión entre rutas.
No se modificaron vendor, los ocho documentos históricos, Equipamiento WD04.1, Responsable y contexto, Soporte, Software, cabecera ni navegación global. Los cambios de composición solo recolocan sus consumidores. Se conservan los cambios previos del árbol sin crear commits ni revertir trabajo ajeno. Las incidencias globales anteriores quedan fuera de WD04.2 y se declaran arriba.
El preparador recibió SIGINT y retiró exclusivamente sus servicios y MariaDB desechable.
Se comprobó que session.json ya no existe. Las capturas y mediciones sanitizadas
permanecen en los directorios estables indicados.
WD04.3 — Consolidación de Responsable y contexto
Fecha: 24 de octubre de 2026. Cambios limitados a la presentación y resolución de su contexto, sobre Equipamiento WD04.1 y Perfiles/configuraciones WD04.2 efectivamente implementados. Se conservan los cambios previos del árbol de trabajo.
Presentación y componentes
Se retira la tarjeta Responsable y contexto. La cabecera conserva breadcrumb, nombre editable, estado, compañía, sede, responsable y sus acciones originales. Compañía, sede y persona mantienen enlaces reales independientes; no se anidan botones dentro de enlaces ni se hace clicable la banda completa. El nombre del responsable permanece visible y permite ajuste de línea, incluido el caso largo. Sin responsable se muestra «Sin responsable», sin inferirlo de los usuarios de perfiles.
WorkstationResponsibleContext añade junto al nombre un activador de información con
nombre accesible traducido y Tooltip. Popover, Tooltip y Button se componen mediante
render según Base UI instalado, con un único botón nativo. El Popover presenta nombre,
rol Responsable del puesto, departamento y cargo vigentes, y Abrir ficha de persona.
No añade una segunda fila fija con información organizativa secundaria.
workstation-detail-content.tsx elimina el render/import del panel anterior; Software,
Soporte y Último cambio ocupan la pila derecha desde el inicio del segundo grid. No se
estiran tarjetas ni se reserva un hueco. La proporción y los umbrales responsive existentes
se conservan. La carga inicial pasa a seis placeholders. Tras buscar referencias en el
monorepo, se retiran WorkstationResponsible y el resolver anterior, que solo utilizaban
ese panel y sus pruebas.
Relaciones organizativas y asignaciones múltiples
El responsable procede exclusivamente de Workstation.personId y de la compañía de la ficha. Sede procede de siteId del puesto; no se obtiene del activo ni de la persona. La persona responsable sigue separada de los perfiles y del contexto remoto de Soporte. No se modifican DTOs, relaciones, asignaciones, validaciones de dominio ni persistencia.
workstationOrganizationalAssignments deriva las relaciones desde CompanyDTO:
misma compañía/persona y periodo semiabierto startDate <= hoy < endDate, o sin fecha
de fin. Conserva el criterio de fecha UTC del resolver anterior. No filtra relaciones
vigentes arbitrariamente por el estado actual de departamento/persona: una relación
existente puede conservarse conforme al contrato del dominio.
Se muestran todas las asignaciones vigentes, con las principales primero y una etiqueta Principal; fecha de inicio e ID estabilizan el orden restante. De ese modo no se descartan las secundarias ni se elige la primera de varias sin principal. Si hay más de una, se anuncia su cantidad. Tampoco se oculta una segunda principal: el modelo puede admitir periodos finitos solapados en departamentos diferentes. La presentación no introduce otra política de elección ni modifica esas relaciones.
Sin asignación vigente, departamento y cargo muestran «—». El cargo procede de la asignación presentada. El campo general Person.position continúa en la ficha de persona; no se usa para atribuir un cargo a una relación organizativa inexistente. Esta decisión sustituye el fallback del panel anterior y evita presentar información genérica como si perteneciera a una asignación vigente.
Fuente, carga, fallo y actualización
Personas, departamentos y asignaciones llegan juntos en CompanyDTO, mediante la
query centralizada companyKeys.detail(company.id). No existe endpoint independiente
de asignaciones ni estado de carga separado. El contexto observa esa misma query con
enabled: false: no inicia otra lectura al montarse o abrirse; su reintento usa la API
existente y actualiza la caché compartida. Los campos se derivan de las props actuales,
sin copiarlos a estado local.
Durante refetch se conservan los datos anteriores y se indica Actualizando dentro del Popover. Si falla, cabecera y responsable siguen visibles y el contexto muestra aviso y Reintentar. Tras recuperar la fuente, desaparece el aviso y el foco pasa al título contextual después del commit, mediante un efecto exclusivo de sincronización de foco. Si el reintento vuelve a fallar, el foco retorna a Reintentar. Cambiar responsable/compañía/puesto restablece el Popover por identidad; actualizar datos de la misma persona conserva su contexto.
Límite del contrato actual: CompanyDetail monta esta ficha cuando dispone de compañía. Por ello los casos de compañía inicialmente ausente o asignaciones inicialmente cargando por separado no se pueden reproducir como fuentes independientes. Se conserva ese contrato y su feedback global; no se fabrica una compañía parcial ni se reestructura el shell para simularlos. Sí se verifican refetch, fallo y recuperación de la fuente organizativa real con datos previos. Sin responsable no se monta el contexto ni se resuelven sus asignaciones.
Accesibilidad, responsive y skills
Se reutilizan las primitivas instaladas, sin cambiar vendor. La información contextual se abre explícitamente con ratón, Enter o Espacio; Escape cierra y devuelve el foco al activador. Título/descripción nombran el contenido y el botón mantiene relación ARIA con el Popover. Tooltip explica el icono también al foco. El enlace a persona es independiente y el detalle tiene un segundo acceso explícito a su ficha.
La misma cabecera se adapta por flex-wrap. El Popover conserva el posicionamiento y las colisiones de Base UI, anchura limitada al viewport y altura/desplazamiento limitados al espacio disponible. Nombres y valores largos pueden partirse sin truncamiento irreversible. Los vacíos son «—» y los estados son textuales. Todo texto nuevo mantiene es/en.
Skills consultadas: ux-dashboard para jerarquía/detalle progresivo; ux-navigation para metadatos, enlaces y teclado; frontend-design para continuidad visual y densidad; shadcn para APIs reales de Popover/Tooltip y render; vercel-composition-patterns para encapsular la interacción; vercel-react-best-practices para derivación y caché compartida; ui-ux-pro-max, mediante búsqueda local «popover keyboard focus», para indicadores de foco visibles y no ocultos. Se revisaron la matriz, skills-lock y sus APIs/referencias aplicables. No existe auditor especializado de accesibilidad instalado; se utilizan las verificaciones disponibles de navegador, sin instalar skills, dependencias, ni aplicar cambios globales de navegación, color o tipografía.
Validaciones y comparación WD04.3
Se ejecutaron las comprobaciones desde WSL/bash con Node 24.20.0 y PNPM 11.25.0.
La instalación autenticada desechable utiliza exclusivamente metis_desk_test, con
usuario ordinario y volumen reproducible: 15 compañías, 59 personas, 135 activos y 73
recursos; S04 incluye 80 miembros y 60 perfiles (50 activos y 10 archivados). Los casos
organizativos múltiples/largos/históricos se simulan sobre respuestas GET de esa compañía
en el navegador, sin poblar bases reales ni alterar sus relaciones persistidas.
| Validación ejecutada | Resultado |
|---|---|
| Pruebas dirigidas de dashboard, organización, relaciones, equipamiento, expansión y renderizado es/en | 42 pruebas correctas |
| Typechecks de Companies, Assets y Web | Correctos |
| Biome de los 12 TS/TSX/JSON afectados y ESLint de sus TS/TSX | Correctos |
pnpm build |
Correcto; permanece aviso de tamaño de chunks |
pnpm typecheck global |
Persiste el error previo del vendor calendar.tsx:165 sobre locale y exactOptionalPropertyTypes |
pnpm lint / pnpm check |
Persisten 15 / 167 errores previos, sin corregir archivos ajenos |
pnpm test global |
Siete paquetes correctos; Companies pasa 44/45 archivos, con fallo previo en companies-page.test.tsx |
Las pruebas nuevas cubren responsable presente/ausente y nombre largo, seis tarjetas, enlaces separados, periodo semiabierto, histórico/futuro, varias asignaciones, principal, principales ambiguas, ausencia, cambio de datos/persona/compañía y referencias incompletas. El renderizado SSR es/en verifica la cabecera; los estados de fuente se verifican con su query real en navegador, dado el contrato atómico descrito arriba.
Se completaron 20 métodos distintos de Playwright MCP en recorridos seleccionados, no una única ejecución conjunta: el primer bloque pasó 4/4; el bloque de regresión pasó 15/16 y su caso restante (selector de Sin responsable) pasó tras corregir la selección. La recuperación organizativa final pasó tres veces consecutivas, incluida una repetición 2/2. Durante la revisión se ajustaron el tamaño heredado del título contextual y la sincronización del foco posterior al commit; también se corrigió el bloqueo de peticiones del propio harness para liberar las rutas dentro de la misma operación MCP.
Se comprobaron S01 completo, S02 sin responsable, S04 de alta densidad, S05 con fallos y S06 desmantelado; edición y renombrado persistidos y restaurados, cambio de responsable, historial, navegación a compañía/sede/persona, software, soporte, equipamiento, pendientes, perfiles, expansión y configuraciones. Las operaciones de guardado restauran sus valores, aunque generan revisiones de historial en la base desechable.
El contexto se probó en 1600, 1440, 1280, 1024, 768 y 390 px: Enter/Espacio, Escape, retorno de foco, relación ARIA, controles independientes, geometría dentro del viewport y sin nuevas peticiones al abrirlo. Los casos largos no presentan scroll horizontal global. Se verificaron datos conservados durante refetch, fallo recuperable, Reintentar, foco al título tras recuperación y actualización del cargo manteniendo abierto el Popover y el foco de su enlace. También se comprobaron ausencia de asignación, histórico/futuro, secundarias y dos principales vigentes sin ocultar ninguna.
El muestreo de contraste observado en navegador obtuvo mínimo 4,648:1 en los nueve textos del Popover y 4,531:1 en los controles/enlaces muestreados de la pantalla. Las ejecuciones finales no registraron excepciones JavaScript de página. Estos muestreos y las pruebas de teclado no equivalen a una certificación integral de accesibilidad.
Comparación visual WD04.3
Las capturas iniciales comparan el mismo escenario S01 antes de los guardados de regresión. Se pasa de siete a seis tarjetas y desaparece la repetición informativa de compañía, sede y responsable dentro de Responsable y contexto. La cabecera mantiene cuatro grupos de metadatos y el contexto secundario se consulta bajo demanda.
| Ancho | Software: Y antes / después | Soporte: Y antes / después |
|---|---|---|
| 1600 | 618 / 421 px | 815 / 618 px |
| 1440 | 658 / 421 px | 888 / 651 px |
| 1280 | 876 / 678 px | 1072 / 876 px |
| 1024 | 926 / 728 px | 1122 / 926 px |
| 768 | 1126 / 958 px | 1324 / 1154 px |
| 390 | 1574 / 1282 px | 1824 / 1532 px |
Las alturas responden al contenido; no se promete un desplazamiento fijo para otros nombres o datos. No se incorporan indicadores para rellenar espacios ni se igualan artificialmente las columnas.
Evidencias y limitaciones finales
Evidencias locales sin credenciales: 13 PNG anteriores y 51 posteriores, más mediciones
por escenario, en .artifacts/playwright/workstation-dashboard-wd043/. Se inspeccionaron
visualmente las capturas de escritorio, móvil, asignaciones múltiples, valores largos,
fallo y actualización. Ejemplos:
- Antes, 1600 px y después, 1600 px.
- Página completa posterior.
- Contexto a 1600, 1440, 1280, 1024, 768 y 390 px.
- Varias asignaciones, dos principales, solo histórico/futuro, sin asignaciones y valores largos en móvil.
- Fallo recuperable, refetch conservando datos y cargo actualizado sin cerrar.
- Sin responsable, desmantelado y mediciones posteriores.
Las capturas son estados observados, no una garantía de instantánea transaccional entre fuentes. Los casos de carga inicial independiente quedan sujetos al contrato atómico CompanyDTO descrito arriba. No se ejecutaron lector de pantalla, zoom, tema oscuro ni un auditor WCAG especializado. Persisten los fallos globales ajenos indicados en la tabla. No se modificaron vendor ni los ocho documentos históricos de auditoría.
El preparador autenticado y sus servicios temporales se cerraron al terminar; el archivo de sesión se retiró. Se conservaron únicamente las evidencias sanitizadas en la ruta estable indicada. No se instalaron dependencias ni se cambió configuración global.