Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

21 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Aztec Ops Console

Consola de seguimiento y priorización para un portafolio con muchos proyectos activos a la vez. Responde una sola pregunta: ¿qué atiendo hoy, en qué orden y por qué?


Arrancar

Requisitos: Node 22+ y pnpm.

pnpm install
pnpm db:reset   # crea la base SQLite y la puebla desde el archivo de origen
pnpm dev        # → http://localhost:3000

Important

Detené el servidor antes de correr pnpm db:reset (Ctrl+C). SQLite en modo WAL no tolera que le borren el archivo con una conexión abierta.

Otros comandos y variables de entorno
Comando Qué hace
pnpm test Motor de detección y score (46 tests). Reimporta la base antes, solo.
pnpm build Build de producción
pnpm lint ESLint
pnpm db:import Reimporta sin borrar la base (idempotente)
pnpm tsx scripts/verify.ts Vuelca el estado de la base tras importar
pnpm tsx scripts/sensitivity.ts Recalcula el ranking con otros pesos, para ver cuánto dependen de ellos

Para comprobar que una reimportación no pisa el trabajo humano — la garantía que separa a un importador de un seed — hay que correr los tres pasos en orden:

pnpm tsx scripts/check-reimport.ts edit   # simula una edición manual
pnpm db:import                            # reimporta encima
pnpm tsx scripts/check-reimport.ts        # → "OK: la edición humana sobrevivió"

Ninguna variable es obligatoria; todas tienen un default razonable.

Variable Para qué
APP_TODAY Congela la fecha contra la que se calcula el riesgo (YYYY-MM-DD). Sin ella usa la fecha real, así la detección no envejece.
DB_PATH Ruta del SQLite. Default: data/aztec.db
SOURCE_XLSX Archivo de origen a importar. Default: el incluido en el repo

El problema

Con muchos frentes abiertos, la pregunta del día no es "¿cómo va cada proyecto?" sino "¿qué necesito atender ahora?". Eso pide dos cosas que rara vez conviven:

  • un criterio de priorización que se pueda explicar en una frase;
  • una detección de riesgo que no dependa de que alguien actualice un campo a mano.

La decisión de diseño que ordena todo lo demás

Los campos declarados por el origen no se toman como verdad.

Cualquier sistema que ingiera datos de otra fuente —un CRM, un export periódico— termina con campos que quedaron viejos o que se contradicen entre sí. Así que la consola:

Recalcula riesgo, bloqueo y urgencia contra la fecha de hoy, en cada lectura
No persiste ningún valor derivado: si se guardara, volvería a envejecer
Muestra la discrepancia cuando lo declarado y lo real no coinciden, en vez de taparla

Ejemplo real del dataset incluido: un proyecto declarado "Sano" que en realidad lleva más de 170 días vencido y no tiene ni una sola tarea abierta.

La auditoría completa del archivo de origen —con las cifras contadas que sostienen cada regla del motor— está en docs/analisis-de-datos.md.


Qué hace

🔥 Detecta riesgo con severidad graduada Bloqueado · en riesgo · sin siguiente paso, cada uno de 0 a 100 en vez de sí/no. Lo binario no ordena: si media cartera está en rojo, el conteo no dice por dónde empezar.
📊 Prioriza a la vista Cada proyecto tiene un score desglosado y expandible. Sin caja negra.
🗂️ Separa tipos de trabajo Proyecto, diagnóstico y mantenimiento tienen colas propias: no compiten por el mismo orden.
👥 Calcula la carga real Por persona, desde las tareas asignadas — no desde un reporte de capacidad que puede estar viejo.
📋 Tablero por proyecto Tareas por estado, con responsable, dependencias y prioridad. Dos acciones puntuales: desbloquear y fijar como siguiente paso.
🕐 Historial de cambios Cada edición queda registrada, no solo el valor final.
🔎 Notas de calidad de datos Qué se normalizó y qué se contradice, por proyecto y global. Nada se corrige en silencio.

Criterio de priorización

score = 0.5 · urgencia  +  0.3 · prioridad  +  0.2 · flags

Urgencia — curva continua sobre los días de atraso, no escalones. Con escalones, todo lo "muy vencido" empata y se pierde el orden dentro del grupo.

Prioridad — conteo ponderado de tareas abiertas por nivel, con override manual. Un proyecto vencido y sin tareas no es de baja prioridad: es uno que nadie replanificó.

Flags — bloqueado o sin siguiente paso suman puntos, además de marcarse.

Desempate — mayor valor de negocio conocido. Un valor desconocido nunca cuenta como cero: eso lo pondría antes que uno de valor real bajo.

Los pesos son una decisión de diseño, no una verdad matemática — y se puede medir cuánto dependen de ellos los resultados: pnpm tsx scripts/sensitivity.ts recalcula el ranking bajo esquemas deliberadamente distintos. Moviéndolos poco, el orden casi no cambia; llevándolos a un extremo, cambian 3 de los 10 primeros.

El script también imprime por qué: los términos están correlacionados en esta cartera (prioridad y flags, 0.76) y el de flags solo toma tres valores. Con insumos que apuntan en la misma dirección, los pesos tienen poca palanca. Eso acota cuánto está en juego al elegirlos aquí — no prueba que la fórmula aguante cualquier portafolio.


Cómo está armado

lib/engine/     ← motor puro: detección, score, dependencias, carga (46 tests)
lib/import/     ← normalización del archivo de origen
lib/data/       ← única puerta de lectura para la UI
lib/actions.ts  ← únicas escrituras, en transacción y con bitácora
app/            ← 3 rutas: consola, detalle de proyecto, alta

Stack: Next.js (App Router) · TypeScript · SQLite vía Drizzle · Tailwind + shadcn/ui.

lib/engine/ no depende del framework ni de la base: son funciones puras a las que se les inyecta la fecha, por eso se pueden testear sin levantar nada.

El diagrama entidad-relación y las razones detrás de cada separación de tablas están en docs/modelo-de-datos.md.

Datos incluidos

El repo trae el archivo de origen con 22 proyectos, 82 tareas y 6 personas. Al importarlo, el sistema levanta 64 notas de calidad de datos y detecta 17 proyectos bloqueados, 18 en riesgo y 2 sin siguiente paso.

Como el origen trae poca variedad de estados, se agregan 3 proyectos de ejemplo para poder evaluar el sistema desde el primer arranque: uno en pausa con prioridad baja, uno cerrado con fecha vencida (para confirmar que no dispara alertas) y uno crítico sin siguiente paso.


Qué quedó fuera, a propósito

Decisión Por qué
Sin IA en el producto La señal de los datos es estructural (fechas, estados, dependencias). No hay texto lo bastante variado como para que un resumen automático aporte algo que la estructura no muestre ya.
Tareas de solo lectura, salvo dos acciones El proyecto es la unidad sobre la que se decide; la tarea es la evidencia que alimenta esa decisión.
Sin auth, sin deploy, sin tiempo real Corre local con SQLite. Alcanza para un prototipo, no para producción.
Sin edición del equipo La carga se calcula, no se administra.

Uso interno. Todos los derechos reservados.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages