4 Commits

Author SHA1 Message Date
alexandrev-tibco 83d61df13b Exportar la comparación en un formato pensado para pegar a un LLM
Pedido: poder llevar la comparativa a una sesión abierta con un modelo para que
la use. Eso, y no un informe para imprimir, decide el formato: los ficheros
iguales se resumen en una linea en vez de listarse, los binarios solo se
mencionan, y las diferencias van en diff unificado, que los modelos leen de
forma nativa. Lo que se omite se dice en voz alta — un informe que se deja la
mitad en silencio es peor que ninguno, porque se lee como completo.

Las cabeceras `--- a/ +++ b/` cuestan dos lineas y convierten cada bloque en un
parche de verdad, asi que el modelo puede devolverlo por `git apply` en vez de
reescribir el cambio a mano. Que lo sea de verdad esta comprobado ejecutando
git sobre la salida en 10 escenarios (sin salto final, insercion al principio,
borrado al final...); dos fallos aparecieron asi: interlineaba `-` y `+` en vez
de agrupar, y contaba la linea fantasma que deja el ultimo `\n`.

Implementado en los dos motores (Swift y TypeScript) con la misma semantica, y
verificado que producen el mismo texto **byte a byte** para un mismo caso.
Tambien hay salida JSON, para alimentar una herramienta en vez de una charla.

UI en las dos apps: copiar al portapapeles primero (que es el gesto real), y
guardar/descargar despues. En web, si el portapapeles se niega, se descarga y
se avisa: un fallo silencioso ahi acaba en pegar contenido viejo sin saberlo.

De paso, un bug que esto destapó: el menu contextual de la web se cerraba en
`pointerdown`, quitando los botones antes de que su click llegara — ninguna
accion del menu funcionaba (tampoco "Set as base" ni "Expand all"). El smoke
test nunca habia pulsado una; ahora si.

Closes #9

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015hEAYuHRKMYz9sSa9zmbzz
2026-08-02 09:19:59 +02:00
alexandrev-tibco 43ab3a6c04 Publicar la web en kotej.alexandre-vazquez.cloud
Arquitectura de siempre: estatico en el LXC 142 (nginx, puerto 8083) con NPM
delante para el TLS del wildcard, y CNAME kotej -> dyn en Namecheap. No hay
backend porque no hace falta: los ficheros no salen del navegador.

El CNAME se anadio releyendo la zona entera y reenviandola con el registro
nuevo — setHosts reemplaza toda la zona, y perder el MX o el DKIM por no
reenviarlos romperia el correo. Verificado que los 39 registros siguen ahi.

deploy.sh deja el despliegue repetible; borra el destino antes de extraer para
que los assets viejos no se acumulen.

Closes #8

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015hEAYuHRKMYz9sSa9zmbzz
2026-07-31 20:59:08 +02:00
alexandrev-tibco 5d4b339b33 Interfaz web de Kotej, con la misma UX y branding que la app de macOS
Mismo layout que la ventana de escritorio: los dos lados arriba, barra de
control, árbol y, debajo, las diferencias del fichero seleccionado. Mismas
cadenas (inglés y español, según el idioma del navegador), mismos colores de
estado y el mismo logo.

- pestañas, atajos (⌘T/⌘W/⌘F, siguiente/anterior diferencia) y ventana Acerca de
- árbol con chevron a ambos lados, tamaño por lado e icono del modo aplicado
- filtros, búsqueda, modos de comparación y tolerancias de texto
- diff lado a lado con resaltado de los caracteres que cambian y leyenda por
  tipo de cambio (contenido / comentarios / espacios)
- carpetas y ficheros por selector o arrastrando; soltar dos rellena ambos lados
- comparar texto pegado sin ficheros

El árbol y el diff sólo tienen en el DOM las filas visibles: un EAR se aplana a
decenas de miles y dibujarlas todas hace que el scroll se arrastre.

Prueba en Chrome real (tests/smoke.mjs, 26 comprobaciones) porque compilar no
demuestra que la página funcione. Encontró dos fallos de layout reales: sin
min-height:0 la comparación se montaba sobre las pestañas, y un `display: flex`
propio ganaba al atributo `hidden`, dejando paneles invisibles ocupando sitio.

Closes #7

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015hEAYuHRKMYz9sSa9zmbzz
2026-07-31 20:40:32 +02:00
alexandrev-tibco 3754abe694 Portar el motor de comparación a TypeScript para la versión web
Mismo motor que la app de escritorio, pero client-side: los ficheros nunca
salen del navegador. Listar un EAR sólo lee la cola del fichero y las entradas
se inflan bajo demanda con DecompressionStream, que es lo que hace usable un
archivo grande en una pestaña.

- zip.ts: lector del directorio central, ZIP64, detección por firma
- content.ts: binario/texto/semántico; JSON por estructura y XML canónico con
  hermanos repetidos tratados como conjunto
- diff.ts: alineación LCS con recorte de prefijo/sufijo y clasificación de la
  diferencia (espacios / comentario / contenido)
- tree.ts: árboles de carpetas y archivos, emparejado por nombre y CRC32 del
  directorio central para resolver iguales sin leer bytes

34 tests portados de los del motor Swift: existen para probar que ambas
implementaciones dan el mismo veredicto.

Closes #5
Closes #6

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015hEAYuHRKMYz9sSa9zmbzz
2026-07-31 20:24:09 +02:00