You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
svelte-kit-vice/scripts/__names-verify-diff.ts

101 lines
3.8 KiB

refactor(eidos): el catálogo habla un idioma — 269 claves al vocabulario firmado D-TH.6, ejecutada. El slot de tinta pasa a `fg` y el modificador interactivo se pone delante, que es lo que theming §6.7 r7 documentaba sin guard desde que se escribió. Value-preserving: renombra la clave en `recipes/base.ts` y sus 793 referencias en 101 ficheros; no toca un solo valor. claves renombradas 269 en 66 componentes referencias 793 en 101 ficheros censo antes/después 162 recetas · 5.203 knobs · 1.841 públicos (37 %) · 56 sin contrato — IDÉNTICO, como debe ser un rename --names antes/después 269 desviadas → 0 Qué NO entra, y por qué: 47 `{rol}-{slot-de-rol}` canónicas: COLOR_ROLE_SLOTS pone el modificador detrás POR CONSTRUCCIÓN (`primary-solid-hover`) 13 exentas firmadas `--focus-ring-*` es familia del sistema; el color de `aura` es un sustantivo; `stop-color` ES una parte de gradient-builder 47 hovers neutros por VALOR: migran a la capa de estado (§38 + R-4.3), no se renombran — firma 3 6 ocurrencias en historia changelog, errores-toxico, PLAN-affix/background: reescribir un registro fechado lo vuelve mentira El clasificador vive en el censo (`--names`), no en un script suelto, para que el guard R-5.3 consuma la MISMA gramática que el codemod. Su muta-prueba (`__names-mutatest.ts`, 27 casos) es lo que hizo el trabajo: cazó que yo promovía al frente CUALQUIER valor declarado por el morfo, y así `--sidebar-width-icon` (la anchura del raíl colapsado) se convertía en `--sidebar-icon-width` (la anchura de un icono), que es otra cosa. La firma dice «delante lo interactivo, detrás lo dimensional y contextual»: ahora sólo promociona el vocabulario interactivo cerrado, y lo contextual —`below`, `loaded`, `vertical`, `icon`— se queda donde estaba. Los cinco casos de regresión están en la muta-prueba. También cazó que `dropdown-menu.item-bg-hover` lee `var(--color-primary-element)`: es un hover CON VALENCIA (el palette swap de recipe-contract §2), no el hover bespoke que §38 deprecó. Clasificar por el nombre lo habría metido en una migración que no le toca; se clasifica por el VALOR. Verificación (§7.4, artefacto por paso): diff de generated/ 269 renombres 1:1 · 0 cambios de valor · 22 privados reapuntados a los nombres nuevos (`__names-verify-diff`) computed tag-group · field · tabs: 6.467 valores en 23 estados, 0 diffs — y comprobado en el navegador que sirve el CSS nuevo, para que ese 0 no sea el de una copia cacheada huérfanos 0 en código suite eidos 434 pasan · 1 rojo, el conocido (`skin-media-player`). `recipe-css-contract` verde: es el guard que caza el `var()` sin fallback a un nombre que ya no se emite, o sea el fallo exacto de un rename a medias component:audit 163 PASS · 3 NEEDS-WORK, los tres SIN TOCAR por esto check 0 errores en ficheros tocados (los 73 globales son de otras sesiones de la rama; se atribuye por fichero) rtl:check 0 · docs:check 0 formato el renombrado no alarga ninguna línea: ningún fichero tiene más líneas de 100 chars que antes, así que no se pasa prettier — hacerlo reformateaba 300 ficheros de deriva ajena Entra aquí la corrección del repaso de los 7 ya hechos: `gradient-builder.checker-color` → `checker-fg` (el damero de transparencia; ahí `color` era slot). Sus `stop-color-*` no se tocan. Queda para el paso siguiente: R-5.3 no puede graduar a `error` directo mientras los 47 hovers neutros sigan hablando el idioma viejo — o migran antes (firma 3, ya firmada), o el guard necesita una exención greppable. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
/**
* Gate del paso 2 (codemod D-TH.6): el diff de `generated/base.css` son
* renombres 1:1 y NADA más — cero cambios de valor.
*
* Dos formas legítimas de aparecer en el diff, y ninguna más:
*
* 1. RENOMBRE la declaración cambia de nombre; su valor, salvo las
* referencias que el propio plan reapunta, es idéntico.
* 2. REAPUNTADA la declaración conserva su nombre (típicamente un privado
* `--_c-*`) y su valor sólo cambia porque REFERENCIA un
* token renombrado.
*
* El plan se lee del registro que el codemod escribió ANTES de tocar nada:
* releer el clasificador aquí daría cero desviaciones —ya están renombradas—
* y el gate pasaría sobre el vacío.
*/
import { execSync } from 'node:child_process';
import { readFileSync } from 'node:fs';
import { resolve } from 'node:path';
interface Decl {
name: string;
value: string;
}
const parse = (line: string): Decl | null => {
const m = line.slice(1).match(/^\s*(--[a-z0-9_-]+)\s*:\s*(.*?);?\s*$/);
return m ? { name: m[1], value: m[2] } : null;
};
const diff = execSync('git diff -U0 src/uix/eidos/generated/base.css', {
encoding: 'utf8',
maxBuffer: 1 << 28
}).split('\n');
const removedLines = diff.filter((l) => l.startsWith('-') && !l.startsWith('---'));
const addedLines = diff.filter((l) => l.startsWith('+') && !l.startsWith('+++'));
const plan = new Map<string, string>();
for (const r of JSON.parse(readFileSync(resolve('scripts/__names-plan.json'), 'utf8')) as Array<{
component: string;
from: string;
to: string;
}>)
plan.set(`--${r.component}-${r.from}`, `--${r.component}-${r.to}`);
const ordered = [...plan].sort((a, b) => b[0].length - a[0].length);
const applyPlan = (value: string) => {
let out = value;
for (const [from, to] of ordered)
out = out.replace(new RegExp(from.replace(/-/g, '\\-') + '(?![a-zA-Z0-9-])', 'g'), to);
return out;
};
const removed = removedLines.map(parse);
const added = addedLines.map(parse);
const unparsed = [...removed, ...added].filter((d) => d === null).length;
/** name → todos los valores añadidos bajo ese nombre. */
const addedByName = new Map<string, string[]>();
for (const a of added) if (a) addedByName.set(a.name, [...(addedByName.get(a.name) ?? []), a.value]);
let renamed = 0;
let rewired = 0;
const problems: string[] = [];
for (const r of removed) {
if (!r) continue;
const to = plan.get(r.name);
if (to) {
const vals = addedByName.get(to) ?? [];
if (vals.includes(r.value) || vals.includes(applyPlan(r.value))) renamed++;
else
problems.push(
`VALOR CAMBIÓ ${r.name} → ${to}\n antes: ${r.value}\n ahora: ${vals.join(' | ') || '(ausente)'}`
);
continue;
}
// Sin renombre: sólo vale que su valor se haya reapuntado por el plan.
const vals = addedByName.get(r.name) ?? [];
const rewiredValue = applyPlan(r.value);
if (rewiredValue !== r.value && vals.includes(rewiredValue)) rewired++;
else problems.push(`RETIRADA SIN PLAN ${r.name}: ${r.value}`);
}
/** Ningún nombre añadido puede ser una invención. */
const legalNames = new Set([...plan.values(), ...removed.filter(Boolean).map((d) => d!.name)]);
const invented = added.filter((a) => a && !legalNames.has(a.name)) as Decl[];
console.log(`líneas retiradas ${removedLines.length} · añadidas ${addedLines.length}`);
console.log(`renombres 1:1 ${renamed} / ${plan.size} planificados · reapuntadas ${rewired}`);
console.log(`sin parsear ${unparsed} · añadidos inventados ${invented.length} · problemas ${problems.length}`);
for (const p of problems.slice(0, 8)) console.log(' XX ' + p);
for (const i of invented.slice(0, 8)) console.log(' XX INVENTADO ' + i.name);
const ok =
problems.length === 0 && invented.length === 0 && unparsed === 0 && renamed === plan.size;
console.log(ok ? '\nGATE VERDE: renombres 1:1, cero cambios de valor' : '\nGATE ROJO');
process.exit(ok ? 0 : 1);

Powered by TurnKey Linux.