xonecode 0.17.2 → 0.20.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. package/apps/web/dist/assets/{index-BRVuyPBf.js → index-BvPUqjUm.js} +72 -72
  2. package/apps/web/dist/assets/{index-DLfF2uEK.css → index-CGEXMJBx.css} +1 -1
  3. package/apps/web/dist/assets/{php-B5LpMCn-.js → php-Dk28VW45.js} +1 -1
  4. package/apps/web/dist/assets/{ruby-Clm-qfwM.js → ruby-CPzEcmdp.js} +1 -1
  5. package/apps/web/dist/index.html +2 -2
  6. package/dist/agent/config/iconosEnRed.js +47 -0
  7. package/dist/agent/config/iconosEnRed.js.map +1 -0
  8. package/dist/agent/config/modelos.js +13 -8
  9. package/dist/agent/config/modelos.js.map +1 -1
  10. package/dist/agent/dispositivos/decodificarImagen.js +62 -0
  11. package/dist/agent/dispositivos/decodificarImagen.js.map +1 -0
  12. package/dist/agent/grafo/atributosXone.js +58 -0
  13. package/dist/agent/grafo/atributosXone.js.map +1 -0
  14. package/dist/agent/grafo/buscarIcono.js +92 -0
  15. package/dist/agent/grafo/buscarIcono.js.map +1 -0
  16. package/dist/agent/grafo/compararCapturas.js +103 -0
  17. package/dist/agent/grafo/compararCapturas.js.map +1 -0
  18. package/dist/agent/grafo/criticaVisual.js +23 -3
  19. package/dist/agent/grafo/criticaVisual.js.map +1 -1
  20. package/dist/agent/grafo/diferenciaDeCapturas.js +88 -0
  21. package/dist/agent/grafo/diferenciaDeCapturas.js.map +1 -0
  22. package/dist/agent/grafo/generarFondoSvg.js +83 -0
  23. package/dist/agent/grafo/generarFondoSvg.js.map +1 -0
  24. package/dist/agent/grafo/lectorDeReferencias.js +19 -0
  25. package/dist/agent/grafo/lectorDeReferencias.js.map +1 -0
  26. package/dist/agent/grafo/xoneAgent.js +11 -3
  27. package/dist/agent/grafo/xoneAgent.js.map +1 -1
  28. package/dist/agent/motores/trueforge/capacidades.js +49 -1
  29. package/dist/agent/motores/trueforge/capacidades.js.map +1 -1
  30. package/dist/agent/motores/trueforge/esperas.js +61 -0
  31. package/dist/agent/motores/trueforge/esperas.js.map +1 -0
  32. package/dist/agent/motores/trueforge/eventosTrueforge.js +11 -1
  33. package/dist/agent/motores/trueforge/eventosTrueforge.js.map +1 -1
  34. package/dist/agent/motores/trueforge/informesDeHijos.js +63 -0
  35. package/dist/agent/motores/trueforge/informesDeHijos.js.map +1 -0
  36. package/dist/agent/motores/trueforge/medidaAutomatica.js +118 -0
  37. package/dist/agent/motores/trueforge/medidaAutomatica.js.map +1 -0
  38. package/dist/agent/motores/trueforge/memoriaDeEspecialistas.js +186 -0
  39. package/dist/agent/motores/trueforge/memoriaDeEspecialistas.js.map +1 -0
  40. package/dist/agent/motores/trueforge/modeloLangchain.js +5 -0
  41. package/dist/agent/motores/trueforge/modeloLangchain.js.map +1 -1
  42. package/dist/agent/motores/trueforge/resumenSeguro.js +52 -0
  43. package/dist/agent/motores/trueforge/resumenSeguro.js.map +1 -0
  44. package/dist/agent/motores/trueforge/sesionTrueforge.js +545 -26
  45. package/dist/agent/motores/trueforge/sesionTrueforge.js.map +1 -1
  46. package/dist/agent/motores/trueforge/toolsDeFichero.js +69 -3
  47. package/dist/agent/motores/trueforge/toolsDeFichero.js.map +1 -1
  48. package/dist/agent/subagentes/agentesEnDisco.js +88 -19
  49. package/dist/agent/subagentes/agentesEnDisco.js.map +1 -1
  50. package/dist/agent/turno/diagnosticoDeTools.js +44 -3
  51. package/dist/agent/turno/diagnosticoDeTools.js.map +1 -1
  52. package/dist/agent/turno/informeDeTraza.js +66 -4
  53. package/dist/agent/turno/informeDeTraza.js.map +1 -1
  54. package/dist/agent/turno/registroDeFallos.js +6 -1
  55. package/dist/agent/turno/registroDeFallos.js.map +1 -1
  56. package/dist/agent/turno/resumenDeTool.js +12 -0
  57. package/dist/agent/turno/resumenDeTool.js.map +1 -1
  58. package/dist/agent/turno/turnoReal.js +8 -2
  59. package/dist/agent/turno/turnoReal.js.map +1 -1
  60. package/dist/cli/run.js +11 -0
  61. package/dist/cli/run.js.map +1 -1
  62. package/dist/core/agentes.js +36 -2
  63. package/dist/core/agentes.js.map +1 -1
  64. package/dist/core/analisisDeSesion.js +198 -0
  65. package/dist/core/analisisDeSesion.js.map +1 -0
  66. package/dist/core/atributosXone.js +187 -0
  67. package/dist/core/atributosXone.js.map +1 -0
  68. package/dist/core/compararCapturas.js +405 -0
  69. package/dist/core/compararCapturas.js.map +1 -0
  70. package/dist/core/esfuerzo.js +33 -0
  71. package/dist/core/esfuerzo.js.map +1 -1
  72. package/dist/core/fallos.js.map +1 -1
  73. package/dist/core/fondosSvg.js +223 -0
  74. package/dist/core/fondosSvg.js.map +1 -0
  75. package/dist/core/iconos.js +140 -0
  76. package/dist/core/iconos.js.map +1 -0
  77. package/dist/core/modoDeEscritura.js +40 -0
  78. package/dist/core/modoDeEscritura.js.map +1 -1
  79. package/dist/core/notify.js +8 -0
  80. package/dist/core/notify.js.map +1 -1
  81. package/dist/core/nucleoXone.js +113 -0
  82. package/dist/core/nucleoXone.js.map +1 -0
  83. package/dist/core/paqueteDeSoporte.js +118 -0
  84. package/dist/core/paqueteDeSoporte.js.map +1 -0
  85. package/dist/core/ports.js +31 -0
  86. package/dist/core/ports.js.map +1 -1
  87. package/dist/core/referenciasDeImagen.js +55 -0
  88. package/dist/core/referenciasDeImagen.js.map +1 -0
  89. package/dist/core/selectorDeCarpeta.js +15 -1
  90. package/dist/core/selectorDeCarpeta.js.map +1 -1
  91. package/dist/core/settings.js +19 -4
  92. package/dist/core/settings.js.map +1 -1
  93. package/dist/core/shellDeAgente.js +39 -0
  94. package/dist/core/shellDeAgente.js.map +1 -1
  95. package/dist/core/tareasDelPlan.js +69 -7
  96. package/dist/core/tareasDelPlan.js.map +1 -1
  97. package/dist/web/servidor/arranque.js +110 -0
  98. package/dist/web/servidor/arranque.js.map +1 -1
  99. package/dist/web/servidor/sesiones.js +8 -0
  100. package/dist/web/servidor/sesiones.js.map +1 -1
  101. package/dist/web/servidor/soporte.js +571 -0
  102. package/dist/web/servidor/soporte.js.map +1 -0
  103. package/dist/web/servidor/transporte.js.map +1 -1
  104. package/package.json +4 -1
  105. package/skills/xone-development/references/css/propiedades-y-herencia.md +2 -0
  106. package/skills/xone-development/references/datos/appdata-referencia-ampliada.md +2 -2
  107. package/skills/xone-development/references/datos/appdata.md +5 -3
  108. package/skills/xone-development/references/fundamentos/errores-comunes.md +49 -0
  109. package/skills/xone-development/references/xml-ui/prop-tipos-basicos.md +2 -0
  110. package/skills/xone-hotswap/SKILL.md +4 -0
  111. package/skills/xone-hotswap/scripts/xone-log-android +18 -1
  112. package/skills/xone-plan-builder/SKILL.md +18 -10
  113. package/skills/xone-plan-builder/references/TASKS-FORMAT.md +13 -5
  114. package/skills/xone-project-generator/references/fases-10-12-readmes-y-validacion.md +1 -0
  115. package/skills/xone-spec-builder/SKILL.md +3 -3
@@ -0,0 +1,187 @@
1
+ /**
2
+ * Un ÍNDICE DE CONSULTA RÁPIDA de los atributos XML de XOne por nodo, sacado de las tablas de la referencia de la skill.
3
+ * No la sustituye: dice si un atributo está en las tablas y DÓNDE leer el detalle.
4
+ *
5
+ * Existe por una medida: en cuatro pasadas de la misma calculadora los agentes leyeron las referencias de la skill 45-61
6
+ * veces, 15-25 ficheros distintos, los mismos releídos una y otra vez (`atributos-prop.md` son 34 KB), casi siempre para
7
+ * contestar «¿existe este atributo en este nodo?». Esa pregunta es la cara del bug mudo de XOne: un atributo inventado o
8
+ * puesto en el nodo equivocado no da error, se ignora.
9
+ *
10
+ * Tres reglas, para que el índice no contradiga a la skill:
11
+ * - **Se lee de las tablas, no se escribe a mano**: una copia se desfasa y entonces miente.
12
+ * - **Si dos ficheros de la skill no coinciden, se enseñan LOS DOS** con el aviso, en vez de quedarse con uno. La skill
13
+ * se contradice a sí misma (medido: `imgbk` en `<group>` está en `nodos-group-y-frame.md` y no en
14
+ * `atributos-coll-group-frame.md`; `border` en `<frame>` es una máscara en uno y un booleano en el otro).
15
+ * - **Nunca afirma «no existe»**: que no esté en estas tablas no lo prueba —la skill documenta atributos también en texto,
16
+ * en el CSS y por tipo de control—, así que dice «no está en las tablas» y da la búsqueda en la skill.
17
+ *
18
+ * La forma que se reconoce: una sección `## N. Nodo \`<x>\`` (o `## N. Nodo x - …`), o el nodo del fichero entero cuando
19
+ * su título no lo parte en secciones; filas `| \`atributo\` | …` en tablas cuya primera columna es «Atributo»; la
20
+ * descripción es la columna «Descripción» (o la última); «Tipo» y «Default» si la cabecera las trae. Una fila puede nombrar
21
+ * varios (`\`a\` / \`b\``). Puro: `core/` no lee disco.
22
+ */
23
+ const NODO = /^##\s+\d+\.\s+Nodo\s+`?<?([a-z][a-z-]*)>?`?/i;
24
+ const SECCION = /^###\s+(\d+(?:\.\d+)*[a-z]?)\s+(.+?)\s*$/;
25
+ const TOPE_DE_DESCRIPCION = 160;
26
+ const celdas = (fila) => fila
27
+ .trim()
28
+ .replace(/^\|/, "")
29
+ .replace(/\|$/, "")
30
+ .split(/(?<!\\)\|/)
31
+ .map((c) => c.trim());
32
+ const limpio = (t) => t
33
+ .replace(/\*\*/g, "")
34
+ .replace(/\\\|/g, "|")
35
+ .replace(/\s+/g, " ")
36
+ .trim();
37
+ /** Las filas de atributos de UN fichero de referencia. `nodoDelFichero`: el nodo cuando el fichero no lo parte por secciones. */
38
+ export function interpretarReferenciaDeAtributos(texto, fichero, nodoDelFichero) {
39
+ const salida = [];
40
+ let nodo = nodoDelFichero;
41
+ let seccion;
42
+ let cabecera;
43
+ for (const linea of texto.split("\n")) {
44
+ const n = NODO.exec(linea);
45
+ if (n !== null) {
46
+ nodo = n[1].toLowerCase();
47
+ seccion = undefined;
48
+ cabecera = undefined;
49
+ continue;
50
+ }
51
+ if (/^##\s/.test(linea) && nodoDelFichero === undefined) {
52
+ // Otra sección de nivel 2 que no es un nodo (introducción, ejemplos): sus tablas no son de un nodo.
53
+ nodo = undefined;
54
+ cabecera = undefined;
55
+ continue;
56
+ }
57
+ const s = SECCION.exec(linea);
58
+ if (s !== null) {
59
+ seccion = `§${s[1]} ${s[2]}`;
60
+ cabecera = undefined;
61
+ continue;
62
+ }
63
+ if (!linea.trim().startsWith("|")) {
64
+ cabecera = undefined;
65
+ continue;
66
+ }
67
+ const c = celdas(linea);
68
+ if (cabecera === undefined) {
69
+ cabecera = c.map((x) => limpio(x).toLowerCase());
70
+ continue;
71
+ }
72
+ if (c.every((x) => /^:?-+:?$/.test(x)))
73
+ continue;
74
+ if (nodo === undefined || !/^atributo/.test(cabecera[0] ?? ""))
75
+ continue;
76
+ const nombres = [...(c[0] ?? "").matchAll(/`([^`]+)`/g)].map((m) => m[1].trim()).filter((x) => /^[a-z][\w-]*$/i.test(x));
77
+ if (nombres.length === 0)
78
+ continue;
79
+ const col = (...nombresDeColumna) => {
80
+ const i = cabecera.findIndex((h) => nombresDeColumna.includes(h));
81
+ const v = i > 0 ? limpio(c[i] ?? "") : undefined;
82
+ return v === undefined || v === "" || v === "—" ? undefined : v.replace(/`/g, "");
83
+ };
84
+ let descripcion = col("descripción", "descripcion") ?? limpio(c[c.length - 1] ?? "").replace(/`/g, "");
85
+ if (descripcion.length > TOPE_DE_DESCRIPCION)
86
+ descripcion = `${descripcion.slice(0, TOPE_DE_DESCRIPCION - 1).trimEnd()}…`;
87
+ const tipo = col("tipo");
88
+ const defecto = col("default");
89
+ for (const atributo of nombres) {
90
+ salida.push({
91
+ atributo,
92
+ nodo,
93
+ descripcion,
94
+ fichero,
95
+ ...(tipo === undefined ? {} : { tipo }),
96
+ ...(defecto === undefined ? {} : { defecto }),
97
+ ...(seccion === undefined ? {} : { seccion }),
98
+ });
99
+ }
100
+ }
101
+ return salida;
102
+ }
103
+ export function indiceDeAtributos(entradas) {
104
+ const porAtributo = new Map();
105
+ const porNodo = new Map();
106
+ for (const e of entradas) {
107
+ const a = e.atributo.toLowerCase();
108
+ const nodos = porAtributo.get(a) ?? new Map();
109
+ const lista = nodos.get(e.nodo) ?? [];
110
+ if (!lista.some((x) => x.fichero === e.fichero))
111
+ lista.push(e);
112
+ nodos.set(e.nodo, lista);
113
+ porAtributo.set(a, nodos);
114
+ const deNodo = porNodo.get(e.nodo) ?? [];
115
+ if (!deNodo.some((x) => x.atributo === e.atributo))
116
+ deNodo.push(e);
117
+ porNodo.set(e.nodo, deNodo);
118
+ }
119
+ return { porAtributo, porNodo, ficheros: [...new Set(entradas.map((e) => e.fichero))] };
120
+ }
121
+ const tipoNormal = (t) => t?.toLowerCase().replace(/\s+/g, " ").trim();
122
+ /** ¿Los ficheros que documentan este atributo en este nodo dicen TIPOS distintos? */
123
+ export function tiposQueNoCoinciden(fuentes) {
124
+ const tipos = new Set(fuentes.map((f) => tipoNormal(f.tipo)).filter((t) => t !== undefined));
125
+ return tipos.size > 1;
126
+ }
127
+ const donde = (e) => `${e.fichero}${e.seccion === undefined ? "" : ` ${e.seccion}`}`;
128
+ function lineas(nodo, fuentes) {
129
+ const [primera, ...otras] = fuentes;
130
+ if (primera === undefined)
131
+ return [];
132
+ const detalle = (e) => `${e.tipo === undefined ? "" : `${e.tipo}${e.defecto === undefined ? "" : `, por omisión ${e.defecto}`}: `}${e.descripcion}`;
133
+ return [
134
+ `- \`${primera.atributo}\` en <${nodo}> — ${detalle(primera)} [${donde(primera)}]`,
135
+ ...otras.map((e) => ` también en ${donde(e)}: ${detalle(e)}`),
136
+ ...(tiposQueNoCoinciden(fuentes) ? [" ⚠ la skill NO coincide en el tipo entre esos ficheros: lee los dos antes de usarlo."] : []),
137
+ ];
138
+ }
139
+ /** Los parecidos a un nombre que no está: el mismo prefijo, o el nombre dentro de otro. */
140
+ function parecidos(indice, nombre) {
141
+ const n = nombre.toLowerCase();
142
+ const raiz = n.split("-")[0] ?? n;
143
+ return [...indice.porAtributo.keys()].filter((a) => a !== n && (a.includes(n) || n.includes(a) || a.startsWith(raiz))).slice(0, 8);
144
+ }
145
+ export const PIE_DEL_INDICE = "(Índice de consulta rápida de las tablas de la skill: el detalle, los ejemplos y lo que cambia por tipo de control están en el fichero citado, y si discrepan manda la skill.)";
146
+ /**
147
+ * La respuesta, en texto para el modelo. Con `atributo` (y opcionalmente `nodo`): en qué nodos está, con tipo, omisión,
148
+ * descripción corta y fichero; si otro fichero dice otra cosa, también. Con solo `nodo`: sus atributos por nombre,
149
+ * agrupados por subsección. `busqueda` compone la búsqueda en la skill para cuando no está (la da quien monta la tool).
150
+ */
151
+ export function consultarAtributos(indice, pregunta, busqueda = (a) => `busca \`${a}\` en las referencias de la skill`) {
152
+ const nodo = pregunta.nodo?.replace(/[<>]/g, "").trim().toLowerCase();
153
+ const nodos = [...indice.porNodo.keys()];
154
+ if (nodo !== undefined && nodo !== "" && !indice.porNodo.has(nodo)) {
155
+ return `Las tablas indexadas no traen el nodo <${nodo}>. Traen: ${nodos.map((x) => `<${x}>`).join(", ")}.\n${PIE_DEL_INDICE}`;
156
+ }
157
+ const atributo = pregunta.atributo?.trim();
158
+ if (atributo !== undefined && atributo !== "") {
159
+ const todos = indice.porAtributo.get(atributo.toLowerCase()) ?? new Map();
160
+ const elegidos = [...todos.entries()].filter(([n]) => nodo === undefined || nodo === "" || n === nodo);
161
+ if (elegidos.length > 0)
162
+ return [...elegidos.flatMap(([n, f]) => lineas(n, f)), PIE_DEL_INDICE].join("\n");
163
+ const otros = [...todos.keys()].map((n) => `<${n}>`);
164
+ const cerca = parecidos(indice, atributo);
165
+ return [
166
+ `\`${atributo}\` no aparece en las tablas de atributos${nodo === undefined || nodo === "" ? "" : ` de <${nodo}>`} que indexo. Eso NO prueba que no exista: ` +
167
+ "la skill documenta atributos también en su texto, en el CSS y por tipo de control.",
168
+ ...(otros.length > 0 ? [`En las tablas sí está en: ${otros.join(", ")}.`] : []),
169
+ ...(cerca.length > 0 ? [`Parecidos que sí están: ${cerca.map((x) => `\`${x}\``).join(", ")}.`] : []),
170
+ `Antes de usarlo, o de descartarlo: ${busqueda(atributo)}. Si la skill tampoco lo trae, no lo pongas: XOne ignora en silencio lo que no conoce.`,
171
+ ].join("\n");
172
+ }
173
+ if (nodo === undefined || nodo === "") {
174
+ return `Pregunta por \`atributo\` (en qué nodos está y qué hace) o por \`nodo\` (${nodos.map((x) => `<${x}>`).join(", ")}: su lista de atributos).`;
175
+ }
176
+ const porSeccion = new Map();
177
+ for (const e of indice.porNodo.get(nodo) ?? []) {
178
+ const s = `${e.fichero}${e.seccion === undefined ? "" : ` ${e.seccion}`}`;
179
+ porSeccion.set(s, [...(porSeccion.get(s) ?? []), e.atributo]);
180
+ }
181
+ return [
182
+ `Atributos de <${nodo}> en las tablas de la skill (${indice.porNodo.get(nodo)?.length ?? 0}), por fichero y sección; pregunta por uno para su tipo y descripción:`,
183
+ ...[...porSeccion.entries()].map(([s, as]) => `${s}: ${as.join(", ")}`),
184
+ PIE_DEL_INDICE,
185
+ ].join("\n");
186
+ }
187
+ //# sourceMappingURL=atributosXone.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"atributosXone.js","sourceRoot":"","sources":["../../src/core/atributosXone.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,405 @@
1
+ /**
2
+ * Comparar la ESTRUCTURA de dos pantallas con aritmética de píxeles (IXCODE-18).
3
+ *
4
+ * ## Por qué existe, medido
5
+ *
6
+ * Pidiendo a un agente «haz este diseño» (una calculadora de Stitch), el turno cerró diciendo «sin
7
+ * solape ni recorte: los controles caben» mientras el teclado ocupaba un tercio de la pantalla y
8
+ * las teclas salían cortadas. El crítico visual había dicho rojo y el propio agente lo descartó
9
+ * como «no fiable»: dos opiniones de modelos, ninguna cifra. Con cifras el desacuerdo no cabe: la
10
+ * maqueta ocupaba el 96 % del alto y la captura el 33 %.
11
+ *
12
+ * ## Qué mide, y por qué solo eso
13
+ *
14
+ * Es DETERMINISTA: las mismas dos imágenes dan siempre los mismos números, y no depende de que el
15
+ * modelo tenga visión (DeepSeek no la tiene). Mide **dónde hay contenido**, no cómo es:
16
+ *
17
+ * 1. El FONDO es el color más frecuente (una pantalla de app es un fondo liso con cosas encima).
18
+ * 2. «Contenido» es todo píxel que se aparta del fondo más que `UMBRAL_DE_CONTENIDO`.
19
+ * 3. La ocupación por FRANJAS horizontales (`FRANJAS_DE_FILAS`) y verticales
20
+ * (`FRANJAS_DE_COLUMNAS`), y hasta dónde llega el contenido.
21
+ *
22
+ * Todo en PORCENTAJES del área útil, así que una maqueta de 390 px y una captura de 1080 px se
23
+ * comparan sin escalar. Se recorta un margen arriba y abajo (barra de estado y de navegación).
24
+ *
25
+ * **Lo que NO hace, y se dice en cada respuesta**: no ve texto cortado, ni estilo (píldoras contra
26
+ * lápidas), ni colores. Y **no cuenta teclas**: se probó y no es fiable (las teclas oscuras sobre
27
+ * fondo oscuro se funden: 12 manchas en una maqueta de unas 20). Da el ESQUELETO; el parecido y las
28
+ * roturas siguen siendo cosa del crítico con visión.
29
+ *
30
+ * `core/` no decodifica imágenes: recibe los píxeles ya en RGBA (`agent/dispositivos/
31
+ * decodificarImagen.ts` los saca de un PNG o un JPEG).
32
+ */
33
+ /** Fracción del alto que se recorta arriba y abajo: barra de estado y barra de navegación. */
34
+ export const RECORTE_DE_BARRAS = 0.05;
35
+ export const FRANJAS_DE_FILAS = 10;
36
+ export const FRANJAS_DE_COLUMNAS = 8;
37
+ /** Suma de diferencias por canal a partir de la cual un píxel ya no es el fondo. */
38
+ export const UMBRAL_DE_CONTENIDO = 24;
39
+ /** Una franja «tiene contenido» si al menos esta fracción de sus píxeles no es fondo. */
40
+ const DENSIDAD_MINIMA_DE_FILA = 0.02;
41
+ /** En una franja, una columna tiene contenido si al menos esta fracción de su alto no es fondo. */
42
+ const DENSIDAD_MINIMA_DE_COLUMNA_EN_FRANJA = 0.05;
43
+ /**
44
+ * El ENCAJE: cuánto puede separarse cada borde del contenido (arriba, abajo, izquierda, derecha) del de la maqueta, en
45
+ * fracción de la pantalla. Existe porque las distancias por franjas PROMEDIAN: calc12 cumplía el 10 % en horizontal
46
+ * (8 %) con el teclado acabando al 85 % del ancho donde la maqueta llega al 96 %, y 12 puntos vacíos abajo. Calibrado
47
+ * contra las capturas de las pasadas: la mejor (calc9) queda en 0-1,6 puntos por lado.
48
+ */
49
+ export const TOLERANCIA_DE_ENCAJE = 0.03;
50
+ /** Diferencia de ocupación (en puntos de 0 a 1) a partir de la cual una franja se señala. */
51
+ export const DIFERENCIA_QUE_SE_SEÑALA = 0.3;
52
+ /** Diferencia media de perfil bajo la que dos pantallas se dan por parecidas en estructura. */
53
+ export const DISTANCIA_PARECIDA = 0.12;
54
+ /** Se mira uno de cada tantos píxeles al buscar el fondo: no hace falta ver los 2,6 millones. */
55
+ const PASO_DE_MUESTREO = 7;
56
+ const pct = (n) => `${Math.round(n * 100)} %`;
57
+ /** Fracción del ancho, a cada lado, donde se busca el fondo: los márgenes de una pantalla. */
58
+ const BORDE_PARA_EL_FONDO = 0.03;
59
+ /** Si el color más frecuente del borde no llega a esta fracción de los píxeles del borde, el borde no es fiable. */
60
+ const FRACCION_MINIMA_DEL_BORDE = 0.3;
61
+ function modaDeColor(img, desde, hasta, dentro) {
62
+ const cuentas = new Map();
63
+ const { ancho, datos } = img;
64
+ let total = 0;
65
+ for (let y = desde; y < hasta; y += PASO_DE_MUESTREO) {
66
+ for (let x = 0; x < ancho; x++) {
67
+ if (!dentro(x))
68
+ continue;
69
+ const i = (y * ancho + x) * 4;
70
+ // Cuantizado a 6 bits por canal para tolerar el ruido de un JPEG.
71
+ const clave = ((datos[i] >> 2) << 16) | ((datos[i + 1] >> 2) << 8) | (datos[i + 2] >> 2);
72
+ cuentas.set(clave, (cuentas.get(clave) ?? 0) + 1);
73
+ total++;
74
+ }
75
+ }
76
+ let mejor = 0;
77
+ let cuenta = -1;
78
+ for (const [clave, n] of cuentas) {
79
+ if (n > cuenta) {
80
+ cuenta = n;
81
+ mejor = clave;
82
+ }
83
+ }
84
+ return {
85
+ color: [((mejor >> 16) & 63) << 2, ((mejor >> 8) & 63) << 2, (mejor & 63) << 2],
86
+ fraccion: total === 0 ? 0 : cuenta / total,
87
+ };
88
+ }
89
+ /**
90
+ * El color de FONDO: el más frecuente en los MÁRGENES laterales, no en toda la imagen.
91
+ *
92
+ * **Lo de «el más frecuente de todos» falló, y se midió**: en una calculadora cuyas teclas redondas
93
+ * ocupaban más superficie que el fondo, eligió el gris de las teclas, y toda la barra superior y la
94
+ * tarjeta del display contaron como contenido al cien por cien (una distancia del 46 % a una pantalla
95
+ * que a la vista estaba mucho más cerca de la maqueta). Incluso en la maqueta y en una captura buena
96
+ * eligió el color de la tarjeta del display, con menos de un tercio de los píxeles. Los márgenes
97
+ * laterales, en cambio, son fondo casi siempre —el contenido de una app deja margen a los lados— y
98
+ * dieron el mismo color en las cuatro imágenes probadas. Si el borde no es uniforme (contenido a
99
+ * sangre), se cae al más frecuente global, que es lo que había.
100
+ */
101
+ function colorDeFondo(img, desde, hasta) {
102
+ const margen = img.ancho * BORDE_PARA_EL_FONDO;
103
+ const borde = modaDeColor(img, desde, hasta, (x) => x < margen || x >= img.ancho - margen);
104
+ if (borde.fraccion >= FRACCION_MINIMA_DEL_BORDE)
105
+ return borde.color;
106
+ return modaDeColor(img, desde, hasta, () => true).color;
107
+ }
108
+ /**
109
+ * La ocupación de una imagen. **Lanza si no se puede medir** (vacía o diminuta): quien llama lo
110
+ * convierte en texto.
111
+ */
112
+ export function medirPantalla(img, recorte = RECORTE_DE_BARRAS) {
113
+ if (img.ancho < FRANJAS_DE_COLUMNAS || img.alto < FRANJAS_DE_FILAS * 4) {
114
+ throw new Error("la imagen es demasiado pequeña para medirla");
115
+ }
116
+ if (img.datos.length < img.ancho * img.alto * 4)
117
+ throw new Error("la imagen está incompleta");
118
+ const desde = Math.floor(img.alto * recorte);
119
+ const hasta = img.alto - Math.floor(img.alto * recorte);
120
+ const alto = hasta - desde;
121
+ const fondo = colorDeFondo(img, desde, hasta);
122
+ const { ancho, datos } = img;
123
+ const densidadDeFila = new Float64Array(alto);
124
+ const cuentaDeColumna = new Float64Array(ancho);
125
+ for (let y = 0; y < alto; y++) {
126
+ let n = 0;
127
+ const base = (desde + y) * ancho * 4;
128
+ for (let x = 0; x < ancho; x++) {
129
+ const i = base + x * 4;
130
+ const d = Math.abs(datos[i] - fondo[0]) + Math.abs(datos[i + 1] - fondo[1]) + Math.abs(datos[i + 2] - fondo[2]);
131
+ if (d > UMBRAL_DE_CONTENIDO) {
132
+ n++;
133
+ cuentaDeColumna[x] += 1;
134
+ }
135
+ }
136
+ densidadDeFila[y] = n / ancho;
137
+ }
138
+ let primera = -1;
139
+ let ultima = -1;
140
+ for (let y = 0; y < alto; y++) {
141
+ if (densidadDeFila[y] > DENSIDAD_MINIMA_DE_FILA) {
142
+ if (primera < 0)
143
+ primera = y;
144
+ ultima = y;
145
+ }
146
+ }
147
+ const media = (v, a, b) => {
148
+ let s = 0;
149
+ for (let i = a; i < b; i++)
150
+ s += v[i];
151
+ return b > a ? s / (b - a) : 0;
152
+ };
153
+ const filas = Array.from({ length: FRANJAS_DE_FILAS }, (_, k) => media(densidadDeFila, Math.floor((k * alto) / FRANJAS_DE_FILAS), Math.floor(((k + 1) * alto) / FRANJAS_DE_FILAS)));
154
+ const columnas = Array.from({ length: FRANJAS_DE_COLUMNAS }, (_, k) => media(cuentaDeColumna, Math.floor((k * ancho) / FRANJAS_DE_COLUMNAS), Math.floor(((k + 1) * ancho) / FRANJAS_DE_COLUMNAS)) /
155
+ alto);
156
+ // Dónde empieza y acaba el contenido por los LADOS: la MEDIANA de cada franja del alto, no el recuadro de la pantalla
157
+ // entera, que lo fija el elemento más ancho (la barra de arriba ocupa todo) y no dice si el teclado llega al borde.
158
+ const bordesDeFranja = [];
159
+ for (let k = 0; k < FRANJAS_DE_FILAS; k++) {
160
+ const y0 = Math.floor((k * alto) / FRANJAS_DE_FILAS);
161
+ const y1 = Math.floor(((k + 1) * alto) / FRANJAS_DE_FILAS);
162
+ const cuenta = new Float64Array(ancho);
163
+ for (let y = y0; y < y1; y++) {
164
+ const base = (desde + y) * ancho * 4;
165
+ for (let x = 0; x < ancho; x++) {
166
+ const i = base + x * 4;
167
+ const d = Math.abs(datos[i] - fondo[0]) + Math.abs(datos[i + 1] - fondo[1]) + Math.abs(datos[i + 2] - fondo[2]);
168
+ if (d > UMBRAL_DE_CONTENIDO)
169
+ cuenta[x] += 1;
170
+ }
171
+ }
172
+ let a = -1;
173
+ let b = -1;
174
+ for (let x = 0; x < ancho; x++) {
175
+ if (cuenta[x] / Math.max(y1 - y0, 1) > DENSIDAD_MINIMA_DE_COLUMNA_EN_FRANJA) {
176
+ if (a < 0)
177
+ a = x;
178
+ b = x;
179
+ }
180
+ }
181
+ if (a >= 0)
182
+ bordesDeFranja.push([a / ancho, (b + 1) / ancho]);
183
+ }
184
+ const mediana = (v) => {
185
+ if (v.length === 0)
186
+ return 0;
187
+ const o = [...v].sort((x, y) => x - y);
188
+ const m = Math.floor(o.length / 2);
189
+ return o.length % 2 === 1 ? o[m] : (o[m - 1] + o[m]) / 2;
190
+ };
191
+ return {
192
+ fondo,
193
+ inicioDelContenido: primera < 0 ? 0 : primera / alto,
194
+ finDelContenido: ultima < 0 ? 0 : (ultima + 1) / alto,
195
+ izquierdaDelContenido: mediana(bordesDeFranja.map(([a]) => a)),
196
+ derechaDelContenido: mediana(bordesDeFranja.map(([, b]) => b)),
197
+ filas,
198
+ columnas,
199
+ };
200
+ }
201
+ const distancia = (a, b) => a.reduce((s, v, i) => s + Math.abs(v - b[i]), 0) / a.length;
202
+ /** Franjas consecutivas que difieren, juntadas en un rango: «franjas 5–10 (40–100 % del alto)». */
203
+ function rangos(dif, total) {
204
+ const salida = [];
205
+ let abierto;
206
+ dif.forEach((d, k) => {
207
+ if (Math.abs(d) >= DIFERENCIA_QUE_SE_SEÑALA) {
208
+ if (abierto !== undefined && abierto.hasta === k)
209
+ abierto.hasta = k + 1;
210
+ else {
211
+ abierto = { desde: k, hasta: k + 1 };
212
+ salida.push(abierto);
213
+ }
214
+ }
215
+ });
216
+ return salida.map((r) => ({ desde: r.desde / total, hasta: r.hasta / total }));
217
+ }
218
+ function describirRangos(nombre, ref, cap) {
219
+ const dif = cap.map((c, k) => c - ref[k]);
220
+ return rangos(dif, ref.length).map((r) => {
221
+ const a = Math.floor(r.desde * ref.length);
222
+ const b = Math.ceil(r.hasta * ref.length);
223
+ const media = (v) => v.slice(a, b).reduce((s, x) => s + x, 0) / Math.max(b - a, 1);
224
+ const donde = `entre el ${pct(r.desde)} y el ${pct(r.hasta)} del ${nombre}`;
225
+ const r0 = media(ref);
226
+ const c0 = media(cap);
227
+ // «Casi nada» solo si de verdad lo es: un 45 % frente a un 89 % es la MITAD, no nada.
228
+ if (c0 < r0) {
229
+ return c0 < r0 * 0.25
230
+ ? `${donde} la referencia tiene contenido (${pct(r0)} de ocupación) y la captura casi nada (${pct(c0)})`
231
+ : `${donde} la captura tiene bastante menos contenido (${pct(c0)}) que la referencia (${pct(r0)})`;
232
+ }
233
+ return `${donde} la captura tiene mucho más contenido (${pct(c0)}) que la referencia (${pct(r0)})`;
234
+ });
235
+ }
236
+ /** El peor borde, en valor absoluto: lo que decide si encaja. */
237
+ export function desajusteDeEncaje(e) {
238
+ return Math.max(Math.abs(e.arriba), Math.abs(e.abajo), Math.abs(e.izquierda), Math.abs(e.derecha));
239
+ }
240
+ /** Un hallazgo por borde que se sale de la tolerancia, dicho como lo que hay que hacer para que ocupe la pantalla como la maqueta. */
241
+ function hallazgosDeEncaje(e, ref, cap) {
242
+ const salida = [];
243
+ const fuera = (d) => Math.abs(d) > TOLERANCIA_DE_ENCAJE;
244
+ if (fuera(e.derecha)) {
245
+ salida.push(`ENCAJE a la derecha: el contenido acaba al ${pct(cap.derechaDelContenido)} del ancho y en la maqueta al ${pct(ref.derechaDelContenido)} ` +
246
+ (e.derecha < 0 ? `(le faltan ${pct(-e.derecha)}: ensánchalo hasta el borde de la maqueta)` : `(se pasa ${pct(e.derecha)})`));
247
+ }
248
+ if (fuera(e.izquierda)) {
249
+ salida.push(`ENCAJE a la izquierda: el contenido empieza al ${pct(cap.izquierdaDelContenido)} del ancho y en la maqueta al ${pct(ref.izquierdaDelContenido)}`);
250
+ }
251
+ if (fuera(e.abajo)) {
252
+ salida.push(`ENCAJE abajo: el contenido acaba al ${pct(cap.finDelContenido)} del alto útil y en la maqueta al ${pct(ref.finDelContenido)} ` +
253
+ (e.abajo < 0 ? `(queda una banda vacía de ${pct(-e.abajo)}: el contenido tiene que llegar abajo como en la maqueta)` : `(se pasa ${pct(e.abajo)})`));
254
+ }
255
+ if (fuera(e.arriba)) {
256
+ salida.push(`ENCAJE arriba: el contenido empieza al ${pct(cap.inicioDelContenido)} del alto útil y en la maqueta al ${pct(ref.inicioDelContenido)}`);
257
+ }
258
+ return salida;
259
+ }
260
+ /** Compara dos pantallas ya medidas. Puro: los números salen de `medirPantalla`. */
261
+ export function compararMedidas(referencia, captura) {
262
+ const dv = distancia(referencia.filas, captura.filas);
263
+ const dh = distancia(referencia.columnas, captura.columnas);
264
+ const hallazgos = [];
265
+ const encaje = {
266
+ arriba: captura.inicioDelContenido - referencia.inicioDelContenido,
267
+ abajo: captura.finDelContenido - referencia.finDelContenido,
268
+ izquierda: captura.izquierdaDelContenido - referencia.izquierdaDelContenido,
269
+ derecha: captura.derechaDelContenido - referencia.derechaDelContenido,
270
+ };
271
+ hallazgos.push(...hallazgosDeEncaje(encaje, referencia, captura));
272
+ hallazgos.push(...describirRangos("alto", referencia.filas, captura.filas));
273
+ hallazgos.push(...describirRangos("ancho", referencia.columnas, captura.columnas));
274
+ const parecida = dv <= DISTANCIA_PARECIDA && dh <= DISTANCIA_PARECIDA && hallazgos.length === 0;
275
+ return {
276
+ referencia,
277
+ captura,
278
+ distanciaVertical: dv,
279
+ distanciaHorizontal: dh,
280
+ encaje,
281
+ hallazgos,
282
+ veredicto: parecida ? "parecida" : "distinta",
283
+ };
284
+ }
285
+ /** Medir las dos y compararlas. */
286
+ export function compararPantallas(referencia, captura) {
287
+ return compararMedidas(medirPantalla(referencia), medirPantalla(captura));
288
+ }
289
+ /**
290
+ * El informe en texto, que es lo que lee el modelo. **Termina diciendo lo que esto NO mide**: un
291
+ * «parecida» de aquí es «la estructura coincide», y se leería como «se ve bien» si no se dijera.
292
+ */
293
+ const pp = (x) => `${x >= 0 ? "+" : "−"}${Math.round(Math.abs(x) * 100)}`;
294
+ export function informeDeComparacion(c) {
295
+ const filas = (m) => m.filas.map((f) => String(Math.round(f * 100)).padStart(3)).join("");
296
+ const lineas = [
297
+ `Estructura ${c.veredicto === "parecida" ? "PARECIDA" : "DISTINTA"} (distancia vertical ${pct(c.distanciaVertical)}, horizontal ${pct(c.distanciaHorizontal)}; se da por parecida bajo ${pct(DISTANCIA_PARECIDA)}).`,
298
+ `Encaje de los bordes del contenido frente a la maqueta (tolerancia ${pct(TOLERANCIA_DE_ENCAJE)} por lado): arriba ${pp(c.encaje.arriba)}, abajo ${pp(c.encaje.abajo)}, izquierda ${pp(c.encaje.izquierda)}, derecha ${pp(c.encaje.derecha)} → ${desajusteDeEncaje(c.encaje) <= TOLERANCIA_DE_ENCAJE ? "ENCAJA" : "NO ENCAJA"}.`,
299
+ `Ocupación por franjas del alto, de arriba abajo (%):`,
300
+ ` referencia:${filas(c.referencia)}`,
301
+ ` captura: ${filas(c.captura)}`,
302
+ ];
303
+ if (c.hallazgos.length > 0) {
304
+ lineas.push("Diferencias que se señalan:", ...c.hallazgos.map((h) => ` - ${h}`));
305
+ }
306
+ else {
307
+ lineas.push("Ninguna franja difiere más de lo tolerado.");
308
+ }
309
+ lineas.push("OJO, esto mide DÓNDE hay contenido y no CÓMO es: no ve texto cortado, ni el estilo de las formas (píldoras o rectángulos), " +
310
+ "ni colores, ni cuenta teclas. Para eso está xone_critica_visual, pasándole esta misma referencia.");
311
+ return lineas;
312
+ }
313
+ /** Fracción de píxeles de la zona que tienen que diferir para dar la zona por CAMBIADA. */
314
+ export const UMBRAL_DE_CAMBIO = 0.003;
315
+ const IMAGEN_ENTERA = { x: 0, y: 0, ancho: 1, alto: 1 };
316
+ /** Por qué una zona no vale, o `undefined`. */
317
+ export function motivoDeRegionInaceptable(r) {
318
+ const finitos = [r.x, r.y, r.ancho, r.alto].every((n) => Number.isFinite(n));
319
+ if (!finitos || r.x < 0 || r.y < 0 || r.ancho <= 0 || r.alto <= 0 || r.x + r.ancho > 1.0001 || r.y + r.alto > 1.0001) {
320
+ return "la zona va en fracciones de la imagen (0 a 1): x e y de la esquina y su ancho y su alto, sin salirse";
321
+ }
322
+ return undefined;
323
+ }
324
+ /**
325
+ * Cuánto cambió una zona entre dos capturas. **Lanza** si no son comparables: las dos tienen que ser
326
+ * del MISMO tamaño (dos capturas del mismo aparato); comparar tamaños distintos es la pregunta de
327
+ * `compararPantallas`, no ésta.
328
+ *
329
+ * Es lo que un agente escribía a mano cada pasada (46 scripts de Python con PIL y 31 `md5`): un
330
+ * `md5` igual solo dice que TODA la imagen es igual, no si cambió lo que importaba, y uno distinto
331
+ * puede ser solo un cursor parpadeando.
332
+ */
333
+ export function medirCambio(antes, despues, region = IMAGEN_ENTERA) {
334
+ if (antes.ancho !== despues.ancho || antes.alto !== despues.alto) {
335
+ throw new Error(`las dos capturas no tienen el mismo tamaño (${antes.ancho}×${antes.alto} frente a ${despues.ancho}×${despues.alto})`);
336
+ }
337
+ const motivo = motivoDeRegionInaceptable(region);
338
+ if (motivo !== undefined)
339
+ throw new Error(motivo);
340
+ if (antes.datos.length < antes.ancho * antes.alto * 4 || despues.datos.length < despues.ancho * despues.alto * 4) {
341
+ throw new Error("una de las imágenes está incompleta");
342
+ }
343
+ const x0 = Math.floor(region.x * antes.ancho);
344
+ const y0 = Math.floor(region.y * antes.alto);
345
+ const x1 = Math.min(antes.ancho, Math.ceil((region.x + region.ancho) * antes.ancho));
346
+ const y1 = Math.min(antes.alto, Math.ceil((region.y + region.alto) * antes.alto));
347
+ let cambiados = 0;
348
+ let minX = Infinity, minY = Infinity, maxX = -1, maxY = -1;
349
+ for (let y = y0; y < y1; y++) {
350
+ for (let x = x0; x < x1; x++) {
351
+ const i = (y * antes.ancho + x) * 4;
352
+ const d = Math.abs(antes.datos[i] - despues.datos[i]) +
353
+ Math.abs(antes.datos[i + 1] - despues.datos[i + 1]) +
354
+ Math.abs(antes.datos[i + 2] - despues.datos[i + 2]);
355
+ if (d > UMBRAL_DE_CONTENIDO) {
356
+ cambiados++;
357
+ if (x < minX)
358
+ minX = x;
359
+ if (x > maxX)
360
+ maxX = x;
361
+ if (y < minY)
362
+ minY = y;
363
+ if (y > maxY)
364
+ maxY = y;
365
+ }
366
+ }
367
+ }
368
+ const total = Math.max((x1 - x0) * (y1 - y0), 1);
369
+ const fraccion = cambiados / total;
370
+ const cambio = fraccion >= UMBRAL_DE_CAMBIO;
371
+ return {
372
+ region,
373
+ cambiados: fraccion,
374
+ ...(cambio
375
+ ? {
376
+ cajaDelCambio: {
377
+ x: minX / antes.ancho,
378
+ y: minY / antes.alto,
379
+ ancho: (maxX - minX + 1) / antes.ancho,
380
+ alto: (maxY - minY + 1) / antes.alto,
381
+ },
382
+ }
383
+ : {}),
384
+ veredicto: cambio ? "cambio" : "igual",
385
+ };
386
+ }
387
+ const pct1 = (n) => `${(n * 100).toFixed(n < 0.1 ? 1 : 0)} %`;
388
+ /** El informe en texto. En «igual» dice las DOS explicaciones posibles, para que no se elija una sin mirar. */
389
+ export function informeDeCambio(c) {
390
+ const zona = `zona x ${pct1(c.region.x)}, y ${pct1(c.region.y)}, ${pct1(c.region.ancho)} de ancho por ${pct1(c.region.alto)} de alto`;
391
+ if (c.veredicto === "cambio" && c.cajaDelCambio !== undefined) {
392
+ const b = c.cajaDelCambio;
393
+ return [
394
+ `CAMBIÓ: el ${pct1(c.cambiados)} de los píxeles de la ${zona} son distintos.`,
395
+ `Lo que cambió cabe en x ${pct1(b.x)}, y ${pct1(b.y)}, ${pct1(b.ancho)} de ancho por ${pct1(b.alto)} de alto.`,
396
+ ];
397
+ }
398
+ return [
399
+ `IGUAL: solo el ${pct1(c.cambiados)} de los píxeles de la ${zona} difieren, bajo el ${pct1(UMBRAL_DE_CAMBIO)} que se da por un cambio.`,
400
+ "Si esperabas un cambio hay DOS explicaciones y no se distinguen con estas dos capturas: que la app no repinta,",
401
+ "o que la segunda captura se tomó antes del repintado (que es asíncrono). Toma otra unos 500 ms después y vuelve a medir;",
402
+ "si sigue igual, es que no se repinta. No la des por «cacheada» sin haberlo hecho.",
403
+ ];
404
+ }
405
+ //# sourceMappingURL=compararCapturas.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compararCapturas.js","sourceRoot":"","sources":["../../src/core/compararCapturas.ts"],"names":[],"mappings":"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"}