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/eidos-lint-all.ts

205 lines
6.5 KiB

eidos: lint a CSS file against its morfo contract Consumes `compileMorfo(morfo).contracts.cssSelectors` to classify every `[data-*]` selector in an eidos CSS file: - morfo-backed: the runtime writes the attr; eidos reacts to it. - eidos-only: the marker is present (`[data-toggle]`) but at least one `data-*` is not declared on the morfo part. Legitimate design tokens (`data-color`, `data-size`, `data-variant`) and drift cases (`data-dialog-header` — a part the morfo no longer declares) both land here; the lint tool reports them so authors can decide. - invalid: the attr IS declared on the morfo, but with a value outside the declared enum. Bug. Also reports `unusedFromContract`: selectors the compiler promises that no eidos rule consumes — the inverse direction of drift. Two CLI entry points: - `scripts/eidos-lint.ts <component>` — single-component report - `scripts/eidos-lint-all.ts` — sweep across every eidos component Initial sweep finds 0 invalid, 134 eidos-only, 82 unused contract selectors across 11 components. Real drift hotspots: dialog/drawer `header`/`footer` (eidos parts the morfos don't declare), popover's `data-side × data-last-action` compounds, tooltip's `data-state='delayed-open'`. Deliberate left as-is for the user to triage — fixes belong in a separate commit. Tests cover toggle (clean baseline), dialog (drift detector for header/footer + dead `data-disabled`), and a synthetic invalid case. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
/**
* Lint every eidos component CSS against its morfo contract.
*
* Usage: npx tsx scripts/eidos-lint-all.ts
*
* Prints a per-component summary so the drift between eidos and the
* morfo declarations is visible at a glance.
feat(morfo,sema,eidos): todo evento dice de que familia es, y el cruce por fin se ve El framework llamaba a la misma cosa de dos maneras: `open` pelado en ocho componentes y `emerge-open` en tres. No era estetica — un preset de movimiento engancha el nombre con `^=`, asi que el dialecto pelado no casaba con ninguna firma y simplemente no animaba, sin romper una sola prueba. Los 40 nombres sin prefijo pasan a `{familia}-{verbo}[-{matiz}]`: 256 eventos, 256 con prefijo, 0 ambiguos. El plan decia 36 y decia `handle-drag-start`; eran 40, y el canon (c25) dice que esos verbos son `pick` y `drop` — `handle-pick` y `handle-drop` ya existian en 10 y 4 componentes. `validateMorfo` cierra la puerta: un `events[].name` que no empiece por su familia ahora lanza. Visto fallar antes con un nombre pelado inyectado. Lo que el renombrado destapo, y va aqui tambien: - La receta del splitter enganchaba `commit-resize`, muerto desde `bd2e40366`. No casaba desde mayo y nadie chillo. Reescrita por FAMILIA, como slider y knob, y `eidos-lint` valida ahora el VALOR de `data-event*` contra el catalogo de morfos — el guard que lo habria cazado en su dia. - La familia `shift` era muda en el canal visual, contra su propia doctrina (c27: el cruce debe percibirse; c34 tipifica el «shift invisible»). Su mapa ya describia la firma que le faltaba y su sonido por defecto es `slide`. Ahora tiene firma direccional: sexto atributo del sello (`data-event-direction`, `forward`|`backward`, por emision) y deslizamiento de 320ms RTL-safe por `:dir()`. Medido: LTR -30px/+30px, RTL los invierte. - El sello de `shift-navigate` pasa del BOTON al `grid` en los cuatro calendarios. Medido: el boton recibia `contact-activate` y 8,5 ms despues —media trama— el `shift-navigate` pisaba la misma ranura y el `press-squeeze` moria sin pintar un fotograma. Una superficie, una ranura (A-36). - 101 contradicciones docs<->morfo adjudicadas con evidencia (git log, docs de decision, el componente vivo). Las docs desfasadas, corregidas; los nueve DEFECTOS de codigo obsoleto quedan abiertos y sin tocar. - `SoundDirection` -> `SoundContour`: era un contorno de tono, no un sentido, y habia tres cosas distintas deletreadas «direction». check en su linea base con 0 errores nuevos por diferencia de conjuntos · docs:check 0/0 · eidos-lint invalid 0 · el censo y las escenas de navegador medidas con raton real y rAF vivo. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
*
* Also validates the `data-event*` VALUES against the morfo catalogue and
* the sema canon — see `scripts/eidos-event-vocabulary.ts`.
eidos: lint a CSS file against its morfo contract Consumes `compileMorfo(morfo).contracts.cssSelectors` to classify every `[data-*]` selector in an eidos CSS file: - morfo-backed: the runtime writes the attr; eidos reacts to it. - eidos-only: the marker is present (`[data-toggle]`) but at least one `data-*` is not declared on the morfo part. Legitimate design tokens (`data-color`, `data-size`, `data-variant`) and drift cases (`data-dialog-header` — a part the morfo no longer declares) both land here; the lint tool reports them so authors can decide. - invalid: the attr IS declared on the morfo, but with a value outside the declared enum. Bug. Also reports `unusedFromContract`: selectors the compiler promises that no eidos rule consumes — the inverse direction of drift. Two CLI entry points: - `scripts/eidos-lint.ts <component>` — single-component report - `scripts/eidos-lint-all.ts` — sweep across every eidos component Initial sweep finds 0 invalid, 134 eidos-only, 82 unused contract selectors across 11 components. Real drift hotspots: dialog/drawer `header`/`footer` (eidos parts the morfos don't declare), popover's `data-side × data-last-action` compounds, tooltip's `data-state='delayed-open'`. Deliberate left as-is for the user to triage — fixes belong in a separate commit. Tests cover toggle (clean baseline), dialog (drift detector for header/footer + dead `data-disabled`), and a synthetic invalid case. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
*/
fix(waveform): el buffered vuelve a ser banda recta, y la demo estrena material real BUFFERED — segunda correccion por MIRADA, y la definitiva. Las dos formas se construyeron y se miraron. Primero fue el SecondaryRange del Slider con un velo neutro al 14%: rechazado ("el secundario no puede ser del mismo color"), y la medicion le dio la razon — velo y onda eran alfas del MISMO token (--color-content-primary al 14% vs 28%), o sea el mismo gris. Se paso entonces a una tercera copia recortada del path, con la idea de que "el buffered ES la onda un escalon mas alla". TAMBIEN rechazado, y por un motivo mas fuerte: "se hace inapreciable y confunde visualmente". La leccion, que queda escrita en los dos README: al compartir silueta con la senal, el ojo lee la banda COMO la senal — es ilegible POR CONSTRUCCION y ningun color la salva. La forma recta es legible precisamente porque NO es la onda. Asi que el buffered vuelve al Slider.SecondaryRange (G-2), la parte canonica que ya existia para esto, en vez de que el waveform pinte lo suyo. El COLOR si sobrevive de la iteracion anterior: acento lavado (color-mix del primary-solid con content-primary), que se separa del gris en TONO y no solo en luminosidad. Tokens de paleta, cero literales. Los tres colores de la onda son publicos y retunables por el disenador. Nota de metodo: la distancia RGB avalo un gris que el ojo rechazo al instante (esa metrica esta dominada por la luminosidad y es ciega al croma), y ademas un bug propio en la alfa del color-mix dio numeros inflados que se corrigieron. Dos recordatorios de que la medicion informa pero no decide. DEMO — material real. El control se llamaba `signal`, que es una de las 8 FAMILIAS del canon, en un componente que declara CERO eventos (expression: 'delegated'): ensenaba lo contrario de la verdad. Renombrado a `sample`. Y el material eran los earcons de sema (pitidos de 80-220 ms, `pop` salia casi plano) porque eran el unico audio del repo; ahora arranca en una pista real de 2:45 (static/music/t2.wav, aportada por el usuario). Y un defecto que 30 MB destaparon: el efecto de carga dependia de `source` Y de `buckets`, asi que mover el slider de buckets volvia a DESCARGAR el fichero entero. Separado en dos: decode una vez por fuente (caro), rebucketing puro y barato. Medido: t2 (5 MB, 86 ms) frente al master de 48 kHz/16 bit (30 MB, 186 ms); sus envolventes NO son identicas — delta maximo 0.298 por cubo, medio 0.048, porque los 8 bits suben el suelo de ruido y aplanan los pasajes suaves. Se elige t2 igualmente: 6x mas ligero por una envolvente marginalmente mas fiel. Verificado: check 75 = baseline, 0 propios; 35 tests; eidos-lint 0 invalidos; recipe-css-contract verde; component:audit --only waveform PASS; docs:check 0; sonda en vivo — 2 paths en la onda, banda recta al 66% en rgb(130,95,161). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
import { existsSync, readFileSync, readdirSync } from 'node:fs';
import { resolve } from 'node:path';
eidos: lint a CSS file against its morfo contract Consumes `compileMorfo(morfo).contracts.cssSelectors` to classify every `[data-*]` selector in an eidos CSS file: - morfo-backed: the runtime writes the attr; eidos reacts to it. - eidos-only: the marker is present (`[data-toggle]`) but at least one `data-*` is not declared on the morfo part. Legitimate design tokens (`data-color`, `data-size`, `data-variant`) and drift cases (`data-dialog-header` — a part the morfo no longer declares) both land here; the lint tool reports them so authors can decide. - invalid: the attr IS declared on the morfo, but with a value outside the declared enum. Bug. Also reports `unusedFromContract`: selectors the compiler promises that no eidos rule consumes — the inverse direction of drift. Two CLI entry points: - `scripts/eidos-lint.ts <component>` — single-component report - `scripts/eidos-lint-all.ts` — sweep across every eidos component Initial sweep finds 0 invalid, 134 eidos-only, 82 unused contract selectors across 11 components. Real drift hotspots: dialog/drawer `header`/`footer` (eidos parts the morfos don't declare), popover's `data-side × data-last-action` compounds, tooltip's `data-state='delayed-open'`. Deliberate left as-is for the user to triage — fixes belong in a separate commit. Tests cover toggle (clean baseline), dialog (drift detector for header/footer + dead `data-disabled`), and a synthetic invalid case. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
fix(waveform): el buffered vuelve a ser banda recta, y la demo estrena material real BUFFERED — segunda correccion por MIRADA, y la definitiva. Las dos formas se construyeron y se miraron. Primero fue el SecondaryRange del Slider con un velo neutro al 14%: rechazado ("el secundario no puede ser del mismo color"), y la medicion le dio la razon — velo y onda eran alfas del MISMO token (--color-content-primary al 14% vs 28%), o sea el mismo gris. Se paso entonces a una tercera copia recortada del path, con la idea de que "el buffered ES la onda un escalon mas alla". TAMBIEN rechazado, y por un motivo mas fuerte: "se hace inapreciable y confunde visualmente". La leccion, que queda escrita en los dos README: al compartir silueta con la senal, el ojo lee la banda COMO la senal — es ilegible POR CONSTRUCCION y ningun color la salva. La forma recta es legible precisamente porque NO es la onda. Asi que el buffered vuelve al Slider.SecondaryRange (G-2), la parte canonica que ya existia para esto, en vez de que el waveform pinte lo suyo. El COLOR si sobrevive de la iteracion anterior: acento lavado (color-mix del primary-solid con content-primary), que se separa del gris en TONO y no solo en luminosidad. Tokens de paleta, cero literales. Los tres colores de la onda son publicos y retunables por el disenador. Nota de metodo: la distancia RGB avalo un gris que el ojo rechazo al instante (esa metrica esta dominada por la luminosidad y es ciega al croma), y ademas un bug propio en la alfa del color-mix dio numeros inflados que se corrigieron. Dos recordatorios de que la medicion informa pero no decide. DEMO — material real. El control se llamaba `signal`, que es una de las 8 FAMILIAS del canon, en un componente que declara CERO eventos (expression: 'delegated'): ensenaba lo contrario de la verdad. Renombrado a `sample`. Y el material eran los earcons de sema (pitidos de 80-220 ms, `pop` salia casi plano) porque eran el unico audio del repo; ahora arranca en una pista real de 2:45 (static/music/t2.wav, aportada por el usuario). Y un defecto que 30 MB destaparon: el efecto de carga dependia de `source` Y de `buckets`, asi que mover el slider de buckets volvia a DESCARGAR el fichero entero. Separado en dos: decode una vez por fuente (caro), rebucketing puro y barato. Medido: t2 (5 MB, 86 ms) frente al master de 48 kHz/16 bit (30 MB, 186 ms); sus envolventes NO son identicas — delta maximo 0.298 por cubo, medio 0.048, porque los 8 bits suben el suelo de ruido y aplanan los pasajes suaves. Se elige t2 igualmente: 6x mas ligero por una envolvente marginalmente mas fiel. Verificado: check 75 = baseline, 0 propios; 35 tests; eidos-lint 0 invalidos; recipe-css-contract verde; component:audit --only waveform PASS; docs:check 0; sonda en vivo — 2 paths en la onda, banda recta al 66% en rgb(130,95,161). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
import { compileMorfo } from '../src/uix/morfo/compile';
import { lintEidosCss } from '../src/uix/eidos/lint';
import type { Morfo } from '../src/uix/morfo/types';
feat(morfo,sema,eidos): todo evento dice de que familia es, y el cruce por fin se ve El framework llamaba a la misma cosa de dos maneras: `open` pelado en ocho componentes y `emerge-open` en tres. No era estetica — un preset de movimiento engancha el nombre con `^=`, asi que el dialecto pelado no casaba con ninguna firma y simplemente no animaba, sin romper una sola prueba. Los 40 nombres sin prefijo pasan a `{familia}-{verbo}[-{matiz}]`: 256 eventos, 256 con prefijo, 0 ambiguos. El plan decia 36 y decia `handle-drag-start`; eran 40, y el canon (c25) dice que esos verbos son `pick` y `drop` — `handle-pick` y `handle-drop` ya existian en 10 y 4 componentes. `validateMorfo` cierra la puerta: un `events[].name` que no empiece por su familia ahora lanza. Visto fallar antes con un nombre pelado inyectado. Lo que el renombrado destapo, y va aqui tambien: - La receta del splitter enganchaba `commit-resize`, muerto desde `bd2e40366`. No casaba desde mayo y nadie chillo. Reescrita por FAMILIA, como slider y knob, y `eidos-lint` valida ahora el VALOR de `data-event*` contra el catalogo de morfos — el guard que lo habria cazado en su dia. - La familia `shift` era muda en el canal visual, contra su propia doctrina (c27: el cruce debe percibirse; c34 tipifica el «shift invisible»). Su mapa ya describia la firma que le faltaba y su sonido por defecto es `slide`. Ahora tiene firma direccional: sexto atributo del sello (`data-event-direction`, `forward`|`backward`, por emision) y deslizamiento de 320ms RTL-safe por `:dir()`. Medido: LTR -30px/+30px, RTL los invierte. - El sello de `shift-navigate` pasa del BOTON al `grid` en los cuatro calendarios. Medido: el boton recibia `contact-activate` y 8,5 ms despues —media trama— el `shift-navigate` pisaba la misma ranura y el `press-squeeze` moria sin pintar un fotograma. Una superficie, una ranura (A-36). - 101 contradicciones docs<->morfo adjudicadas con evidencia (git log, docs de decision, el componente vivo). Las docs desfasadas, corregidas; los nueve DEFECTOS de codigo obsoleto quedan abiertos y sin tocar. - `SoundDirection` -> `SoundContour`: era un contorno de tono, no un sentido, y habia tres cosas distintas deletreadas «direction». check en su linea base con 0 errores nuevos por diferencia de conjuntos · docs:check 0/0 · eidos-lint invalid 0 · el censo y las escenas de navegador medidas con raton real y rAF vivo. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
import {
formatEventFindings,
lintEventValues,
loadEventVocabulary
} from './eidos-event-vocabulary';
eidos: lint a CSS file against its morfo contract Consumes `compileMorfo(morfo).contracts.cssSelectors` to classify every `[data-*]` selector in an eidos CSS file: - morfo-backed: the runtime writes the attr; eidos reacts to it. - eidos-only: the marker is present (`[data-toggle]`) but at least one `data-*` is not declared on the morfo part. Legitimate design tokens (`data-color`, `data-size`, `data-variant`) and drift cases (`data-dialog-header` — a part the morfo no longer declares) both land here; the lint tool reports them so authors can decide. - invalid: the attr IS declared on the morfo, but with a value outside the declared enum. Bug. Also reports `unusedFromContract`: selectors the compiler promises that no eidos rule consumes — the inverse direction of drift. Two CLI entry points: - `scripts/eidos-lint.ts <component>` — single-component report - `scripts/eidos-lint-all.ts` — sweep across every eidos component Initial sweep finds 0 invalid, 134 eidos-only, 82 unused contract selectors across 11 components. Real drift hotspots: dialog/drawer `header`/`footer` (eidos parts the morfos don't declare), popover's `data-side × data-last-action` compounds, tooltip's `data-state='delayed-open'`. Deliberate left as-is for the user to triage — fixes belong in a separate commit. Tests cover toggle (clean baseline), dialog (drift detector for header/footer + dead `data-disabled`), and a synthetic invalid case. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
const EIDOS_ONLY_ATTRS = new Set([
'data-archetype',
'data-block',
'data-collapsed',
'data-combobox-control',
'data-color',
'data-columns',
'data-dragging',
feat(morfo,sema,eidos): todo evento dice de que familia es, y el cruce por fin se ve El framework llamaba a la misma cosa de dos maneras: `open` pelado en ocho componentes y `emerge-open` en tres. No era estetica — un preset de movimiento engancha el nombre con `^=`, asi que el dialecto pelado no casaba con ninguna firma y simplemente no animaba, sin romper una sola prueba. Los 40 nombres sin prefijo pasan a `{familia}-{verbo}[-{matiz}]`: 256 eventos, 256 con prefijo, 0 ambiguos. El plan decia 36 y decia `handle-drag-start`; eran 40, y el canon (c25) dice que esos verbos son `pick` y `drop` — `handle-pick` y `handle-drop` ya existian en 10 y 4 componentes. `validateMorfo` cierra la puerta: un `events[].name` que no empiece por su familia ahora lanza. Visto fallar antes con un nombre pelado inyectado. Lo que el renombrado destapo, y va aqui tambien: - La receta del splitter enganchaba `commit-resize`, muerto desde `bd2e40366`. No casaba desde mayo y nadie chillo. Reescrita por FAMILIA, como slider y knob, y `eidos-lint` valida ahora el VALOR de `data-event*` contra el catalogo de morfos — el guard que lo habria cazado en su dia. - La familia `shift` era muda en el canal visual, contra su propia doctrina (c27: el cruce debe percibirse; c34 tipifica el «shift invisible»). Su mapa ya describia la firma que le faltaba y su sonido por defecto es `slide`. Ahora tiene firma direccional: sexto atributo del sello (`data-event-direction`, `forward`|`backward`, por emision) y deslizamiento de 320ms RTL-safe por `:dir()`. Medido: LTR -30px/+30px, RTL los invierte. - El sello de `shift-navigate` pasa del BOTON al `grid` en los cuatro calendarios. Medido: el boton recibia `contact-activate` y 8,5 ms despues —media trama— el `shift-navigate` pisaba la misma ranura y el `press-squeeze` moria sin pintar un fotograma. Una superficie, una ranura (A-36). - 101 contradicciones docs<->morfo adjudicadas con evidencia (git log, docs de decision, el componente vivo). Las docs desfasadas, corregidas; los nueve DEFECTOS de codigo obsoleto quedan abiertos y sin tocar. - `SoundDirection` -> `SoundContour`: era un contorno de tono, no un sentido, y habia tres cosas distintas deletreadas «direction». check en su linea base con 0 errores nuevos por diferencia de conjuntos · docs:check 0/0 · eidos-lint invalid 0 · el censo y las escenas de navegador medidas con raton real y rAF vivo. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
// The sema stamp (`src/uix/sema/stamp.ts`), not a morfo part. Allowlisted
// STRUCTURALLY only — the VALUE is validated against the morfo catalogue
// by `lintEventValues` below.
'data-event',
feat(morfo,sema,eidos): todo evento dice de que familia es, y el cruce por fin se ve El framework llamaba a la misma cosa de dos maneras: `open` pelado en ocho componentes y `emerge-open` en tres. No era estetica — un preset de movimiento engancha el nombre con `^=`, asi que el dialecto pelado no casaba con ninguna firma y simplemente no animaba, sin romper una sola prueba. Los 40 nombres sin prefijo pasan a `{familia}-{verbo}[-{matiz}]`: 256 eventos, 256 con prefijo, 0 ambiguos. El plan decia 36 y decia `handle-drag-start`; eran 40, y el canon (c25) dice que esos verbos son `pick` y `drop` — `handle-pick` y `handle-drop` ya existian en 10 y 4 componentes. `validateMorfo` cierra la puerta: un `events[].name` que no empiece por su familia ahora lanza. Visto fallar antes con un nombre pelado inyectado. Lo que el renombrado destapo, y va aqui tambien: - La receta del splitter enganchaba `commit-resize`, muerto desde `bd2e40366`. No casaba desde mayo y nadie chillo. Reescrita por FAMILIA, como slider y knob, y `eidos-lint` valida ahora el VALOR de `data-event*` contra el catalogo de morfos — el guard que lo habria cazado en su dia. - La familia `shift` era muda en el canal visual, contra su propia doctrina (c27: el cruce debe percibirse; c34 tipifica el «shift invisible»). Su mapa ya describia la firma que le faltaba y su sonido por defecto es `slide`. Ahora tiene firma direccional: sexto atributo del sello (`data-event-direction`, `forward`|`backward`, por emision) y deslizamiento de 320ms RTL-safe por `:dir()`. Medido: LTR -30px/+30px, RTL los invierte. - El sello de `shift-navigate` pasa del BOTON al `grid` en los cuatro calendarios. Medido: el boton recibia `contact-activate` y 8,5 ms despues —media trama— el `shift-navigate` pisaba la misma ranura y el `press-squeeze` moria sin pintar un fotograma. Una superficie, una ranura (A-36). - 101 contradicciones docs<->morfo adjudicadas con evidencia (git log, docs de decision, el componente vivo). Las docs desfasadas, corregidas; los nueve DEFECTOS de codigo obsoleto quedan abiertos y sin tocar. - `SoundDirection` -> `SoundContour`: era un contorno de tono, no un sentido, y habia tres cosas distintas deletreadas «direction». check en su linea base con 0 errores nuevos por diferencia de conjuntos · docs:check 0/0 · eidos-lint invalid 0 · el censo y las escenas de navegador medidas con raton real y rAF vivo. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
'data-event-direction',
'data-event-family',
'data-event-id',
'data-event-intent',
'data-event-phase',
'data-fitted',
'data-icon-only',
'data-indicator-placement',
'data-motion',
'data-motion-disabled',
'data-position',
'data-ready',
'data-scrollable',
'data-sheet',
'data-size',
'data-floating-wrapper',
'data-svg',
'data-svg-direction',
'data-variant'
fix(waveform): el buffered vuelve a ser banda recta, y la demo estrena material real BUFFERED — segunda correccion por MIRADA, y la definitiva. Las dos formas se construyeron y se miraron. Primero fue el SecondaryRange del Slider con un velo neutro al 14%: rechazado ("el secundario no puede ser del mismo color"), y la medicion le dio la razon — velo y onda eran alfas del MISMO token (--color-content-primary al 14% vs 28%), o sea el mismo gris. Se paso entonces a una tercera copia recortada del path, con la idea de que "el buffered ES la onda un escalon mas alla". TAMBIEN rechazado, y por un motivo mas fuerte: "se hace inapreciable y confunde visualmente". La leccion, que queda escrita en los dos README: al compartir silueta con la senal, el ojo lee la banda COMO la senal — es ilegible POR CONSTRUCCION y ningun color la salva. La forma recta es legible precisamente porque NO es la onda. Asi que el buffered vuelve al Slider.SecondaryRange (G-2), la parte canonica que ya existia para esto, en vez de que el waveform pinte lo suyo. El COLOR si sobrevive de la iteracion anterior: acento lavado (color-mix del primary-solid con content-primary), que se separa del gris en TONO y no solo en luminosidad. Tokens de paleta, cero literales. Los tres colores de la onda son publicos y retunables por el disenador. Nota de metodo: la distancia RGB avalo un gris que el ojo rechazo al instante (esa metrica esta dominada por la luminosidad y es ciega al croma), y ademas un bug propio en la alfa del color-mix dio numeros inflados que se corrigieron. Dos recordatorios de que la medicion informa pero no decide. DEMO — material real. El control se llamaba `signal`, que es una de las 8 FAMILIAS del canon, en un componente que declara CERO eventos (expression: 'delegated'): ensenaba lo contrario de la verdad. Renombrado a `sample`. Y el material eran los earcons de sema (pitidos de 80-220 ms, `pop` salia casi plano) porque eran el unico audio del repo; ahora arranca en una pista real de 2:45 (static/music/t2.wav, aportada por el usuario). Y un defecto que 30 MB destaparon: el efecto de carga dependia de `source` Y de `buckets`, asi que mover el slider de buckets volvia a DESCARGAR el fichero entero. Separado en dos: decode una vez por fuente (caro), rebucketing puro y barato. Medido: t2 (5 MB, 86 ms) frente al master de 48 kHz/16 bit (30 MB, 186 ms); sus envolventes NO son identicas — delta maximo 0.298 por cubo, medio 0.048, porque los 8 bits suben el suelo de ruido y aplanan los pasajes suaves. Se elige t2 igualmente: 6x mas ligero por una envolvente marginalmente mas fiel. Verificado: check 75 = baseline, 0 propios; 35 tests; eidos-lint 0 invalidos; recipe-css-contract verde; component:audit --only waveform PASS; docs:check 0; sonda en vivo — 2 paths en la onda, banda recta al 66% en rgb(130,95,161). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
]);
const RUNTIME_SIGNAL_ATTRS = new Set([
'data-disabled',
'data-invalid',
'data-last-action',
'data-orientation',
'data-readonly',
'data-side',
'data-state'
fix(waveform): el buffered vuelve a ser banda recta, y la demo estrena material real BUFFERED — segunda correccion por MIRADA, y la definitiva. Las dos formas se construyeron y se miraron. Primero fue el SecondaryRange del Slider con un velo neutro al 14%: rechazado ("el secundario no puede ser del mismo color"), y la medicion le dio la razon — velo y onda eran alfas del MISMO token (--color-content-primary al 14% vs 28%), o sea el mismo gris. Se paso entonces a una tercera copia recortada del path, con la idea de que "el buffered ES la onda un escalon mas alla". TAMBIEN rechazado, y por un motivo mas fuerte: "se hace inapreciable y confunde visualmente". La leccion, que queda escrita en los dos README: al compartir silueta con la senal, el ojo lee la banda COMO la senal — es ilegible POR CONSTRUCCION y ningun color la salva. La forma recta es legible precisamente porque NO es la onda. Asi que el buffered vuelve al Slider.SecondaryRange (G-2), la parte canonica que ya existia para esto, en vez de que el waveform pinte lo suyo. El COLOR si sobrevive de la iteracion anterior: acento lavado (color-mix del primary-solid con content-primary), que se separa del gris en TONO y no solo en luminosidad. Tokens de paleta, cero literales. Los tres colores de la onda son publicos y retunables por el disenador. Nota de metodo: la distancia RGB avalo un gris que el ojo rechazo al instante (esa metrica esta dominada por la luminosidad y es ciega al croma), y ademas un bug propio en la alfa del color-mix dio numeros inflados que se corrigieron. Dos recordatorios de que la medicion informa pero no decide. DEMO — material real. El control se llamaba `signal`, que es una de las 8 FAMILIAS del canon, en un componente que declara CERO eventos (expression: 'delegated'): ensenaba lo contrario de la verdad. Renombrado a `sample`. Y el material eran los earcons de sema (pitidos de 80-220 ms, `pop` salia casi plano) porque eran el unico audio del repo; ahora arranca en una pista real de 2:45 (static/music/t2.wav, aportada por el usuario). Y un defecto que 30 MB destaparon: el efecto de carga dependia de `source` Y de `buckets`, asi que mover el slider de buckets volvia a DESCARGAR el fichero entero. Separado en dos: decode una vez por fuente (caro), rebucketing puro y barato. Medido: t2 (5 MB, 86 ms) frente al master de 48 kHz/16 bit (30 MB, 186 ms); sus envolventes NO son identicas — delta maximo 0.298 por cubo, medio 0.048, porque los 8 bits suben el suelo de ruido y aplanan los pasajes suaves. Se elige t2 igualmente: 6x mas ligero por una envolvente marginalmente mas fiel. Verificado: check 75 = baseline, 0 propios; 35 tests; eidos-lint 0 invalidos; recipe-css-contract verde; component:audit --only waveform PASS; docs:check 0; sonda en vivo — 2 paths en la onda, banda recta al 66% en rgb(130,95,161). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
]);
const EIDOS_ONLY_PART_SUFFIXES = [
'footer',
'handle',
'header',
'indicator',
'label',
'main',
fix(waveform): el buffered vuelve a ser banda recta, y la demo estrena material real BUFFERED — segunda correccion por MIRADA, y la definitiva. Las dos formas se construyeron y se miraron. Primero fue el SecondaryRange del Slider con un velo neutro al 14%: rechazado ("el secundario no puede ser del mismo color"), y la medicion le dio la razon — velo y onda eran alfas del MISMO token (--color-content-primary al 14% vs 28%), o sea el mismo gris. Se paso entonces a una tercera copia recortada del path, con la idea de que "el buffered ES la onda un escalon mas alla". TAMBIEN rechazado, y por un motivo mas fuerte: "se hace inapreciable y confunde visualmente". La leccion, que queda escrita en los dos README: al compartir silueta con la senal, el ojo lee la banda COMO la senal — es ilegible POR CONSTRUCCION y ningun color la salva. La forma recta es legible precisamente porque NO es la onda. Asi que el buffered vuelve al Slider.SecondaryRange (G-2), la parte canonica que ya existia para esto, en vez de que el waveform pinte lo suyo. El COLOR si sobrevive de la iteracion anterior: acento lavado (color-mix del primary-solid con content-primary), que se separa del gris en TONO y no solo en luminosidad. Tokens de paleta, cero literales. Los tres colores de la onda son publicos y retunables por el disenador. Nota de metodo: la distancia RGB avalo un gris que el ojo rechazo al instante (esa metrica esta dominada por la luminosidad y es ciega al croma), y ademas un bug propio en la alfa del color-mix dio numeros inflados que se corrigieron. Dos recordatorios de que la medicion informa pero no decide. DEMO — material real. El control se llamaba `signal`, que es una de las 8 FAMILIAS del canon, en un componente que declara CERO eventos (expression: 'delegated'): ensenaba lo contrario de la verdad. Renombrado a `sample`. Y el material eran los earcons de sema (pitidos de 80-220 ms, `pop` salia casi plano) porque eran el unico audio del repo; ahora arranca en una pista real de 2:45 (static/music/t2.wav, aportada por el usuario). Y un defecto que 30 MB destaparon: el efecto de carga dependia de `source` Y de `buckets`, asi que mover el slider de buckets volvia a DESCARGAR el fichero entero. Separado en dos: decode una vez por fuente (caro), rebucketing puro y barato. Medido: t2 (5 MB, 86 ms) frente al master de 48 kHz/16 bit (30 MB, 186 ms); sus envolventes NO son identicas — delta maximo 0.298 por cubo, medio 0.048, porque los 8 bits suben el suelo de ruido y aplanan los pasajes suaves. Se elige t2 igualmente: 6x mas ligero por una envolvente marginalmente mas fiel. Verificado: check 75 = baseline, 0 propios; 35 tests; eidos-lint 0 invalidos; recipe-css-contract verde; component:audit --only waveform PASS; docs:check 0; sonda en vivo — 2 paths en la onda, banda recta al 66% en rgb(130,95,161). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
// waveform F3: the two copies of the wave path (base + progress-clipped) —
// decorative svg primitives, rule-of-4 compliant.
feat(waveform): F4 eidos + F5 demo — y el buffered pasa a ser la onda F4 (eidos): wrapper raiz que carga slider.css + waveform.css y resuelve data-size por ActiveEidos; Wave passthrough; recipe con bars = stroke en UNIDADES DE VIEWBOX (el svg estira con preserveAspectRatio="none", asi el ciclo barra/hueco sobrevive) y wave = fill sin stroke; espejo RTL en CSS; el Slider embebido en scope con track/range transparentes y el thumb convertido en playhead de 2px a alto completo. Tokens waveform:{height-*, bar-width, color, color-buffered, color-played, playhead-width} — playhead-width y color-buffered van ANADIDOS sobre la lista firmada en el gate, ambos declarados en el README. F5 (demo + dossier): /uix/components/waveform con picos REALES (fetch de /sounds/*.wav -> uix.sound.decode -> uix.sound.peaks), cada prop como control vivo, READMEs de soma y eidos. Fix arrastrado de F3: `dir` no se reenviaba al Slider embebido. BUFFERED — cambio de forma (decision del usuario tras ver el render). El primer intento re-tintaba el SecondaryRange del Slider; el usuario lo rechazo ("el secundario no puede ser del mismo color") y la auditoria encontro por que ningun color lo arreglaba del todo: ese part es una BARRA de 6px con la geometria del track, y sobre una pintura de barras al ~58% de ciclo el 42% de su area cae sobre fondo desnudo, ademas de tenir el tramo ya reproducido. Ahora el buffered es una TERCERA COPIA del mismo path, recortada a su fraccion — es la onda un escalon mas alla, la lectura de SoundCloud/wavesurfer. El waveform ya no monta Slider.SecondaryRange. Escalera: color 28% -> color-buffered 55% -> color-played acento. Guard nuevo (bufferedFraction: ausente sin valor, clampado, dominio degenerado) VISTO EN ROJO desconectando el cableado antes de darlo por bueno. Verificado: check 75 = baseline, 0 propios; 5/5 soma + 4/4 morfo; component:audit --only waveform PASS; eidos-lint 0 invalidos; recipe-css-contract y motion.test verdes; docs:check 0; prettier limpio. Queda F6 (mirada del usuario): el panel del navegador no composita, asi que la verificacion fue por sonda del DOM, sin captura. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
'played',
'remaining',
'row',
'row-label',
'status'
fix(waveform): el buffered vuelve a ser banda recta, y la demo estrena material real BUFFERED — segunda correccion por MIRADA, y la definitiva. Las dos formas se construyeron y se miraron. Primero fue el SecondaryRange del Slider con un velo neutro al 14%: rechazado ("el secundario no puede ser del mismo color"), y la medicion le dio la razon — velo y onda eran alfas del MISMO token (--color-content-primary al 14% vs 28%), o sea el mismo gris. Se paso entonces a una tercera copia recortada del path, con la idea de que "el buffered ES la onda un escalon mas alla". TAMBIEN rechazado, y por un motivo mas fuerte: "se hace inapreciable y confunde visualmente". La leccion, que queda escrita en los dos README: al compartir silueta con la senal, el ojo lee la banda COMO la senal — es ilegible POR CONSTRUCCION y ningun color la salva. La forma recta es legible precisamente porque NO es la onda. Asi que el buffered vuelve al Slider.SecondaryRange (G-2), la parte canonica que ya existia para esto, en vez de que el waveform pinte lo suyo. El COLOR si sobrevive de la iteracion anterior: acento lavado (color-mix del primary-solid con content-primary), que se separa del gris en TONO y no solo en luminosidad. Tokens de paleta, cero literales. Los tres colores de la onda son publicos y retunables por el disenador. Nota de metodo: la distancia RGB avalo un gris que el ojo rechazo al instante (esa metrica esta dominada por la luminosidad y es ciega al croma), y ademas un bug propio en la alfa del color-mix dio numeros inflados que se corrigieron. Dos recordatorios de que la medicion informa pero no decide. DEMO — material real. El control se llamaba `signal`, que es una de las 8 FAMILIAS del canon, en un componente que declara CERO eventos (expression: 'delegated'): ensenaba lo contrario de la verdad. Renombrado a `sample`. Y el material eran los earcons de sema (pitidos de 80-220 ms, `pop` salia casi plano) porque eran el unico audio del repo; ahora arranca en una pista real de 2:45 (static/music/t2.wav, aportada por el usuario). Y un defecto que 30 MB destaparon: el efecto de carga dependia de `source` Y de `buckets`, asi que mover el slider de buckets volvia a DESCARGAR el fichero entero. Separado en dos: decode una vez por fuente (caro), rebucketing puro y barato. Medido: t2 (5 MB, 86 ms) frente al master de 48 kHz/16 bit (30 MB, 186 ms); sus envolventes NO son identicas — delta maximo 0.298 por cubo, medio 0.048, porque los 8 bits suben el suelo de ruido y aplanan los pasajes suaves. Se elige t2 igualmente: 6x mas ligero por una envolvente marginalmente mas fiel. Verificado: check 75 = baseline, 0 propios; 35 tests; eidos-lint 0 invalidos; recipe-css-contract verde; component:audit --only waveform PASS; docs:check 0; sonda en vivo — 2 paths en la onda, banda recta al 66% en rgb(130,95,161). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
] as const;
eidos: lint a CSS file against its morfo contract Consumes `compileMorfo(morfo).contracts.cssSelectors` to classify every `[data-*]` selector in an eidos CSS file: - morfo-backed: the runtime writes the attr; eidos reacts to it. - eidos-only: the marker is present (`[data-toggle]`) but at least one `data-*` is not declared on the morfo part. Legitimate design tokens (`data-color`, `data-size`, `data-variant`) and drift cases (`data-dialog-header` — a part the morfo no longer declares) both land here; the lint tool reports them so authors can decide. - invalid: the attr IS declared on the morfo, but with a value outside the declared enum. Bug. Also reports `unusedFromContract`: selectors the compiler promises that no eidos rule consumes — the inverse direction of drift. Two CLI entry points: - `scripts/eidos-lint.ts <component>` — single-component report - `scripts/eidos-lint-all.ts` — sweep across every eidos component Initial sweep finds 0 invalid, 134 eidos-only, 82 unused contract selectors across 11 components. Real drift hotspots: dialog/drawer `header`/`footer` (eidos parts the morfos don't declare), popover's `data-side × data-last-action` compounds, tooltip's `data-state='delayed-open'`. Deliberate left as-is for the user to triage — fixes belong in a separate commit. Tests cover toggle (clean baseline), dialog (drift detector for header/footer + dead `data-disabled`), and a synthetic invalid case. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
async function main() {
fix(waveform): el buffered vuelve a ser banda recta, y la demo estrena material real BUFFERED — segunda correccion por MIRADA, y la definitiva. Las dos formas se construyeron y se miraron. Primero fue el SecondaryRange del Slider con un velo neutro al 14%: rechazado ("el secundario no puede ser del mismo color"), y la medicion le dio la razon — velo y onda eran alfas del MISMO token (--color-content-primary al 14% vs 28%), o sea el mismo gris. Se paso entonces a una tercera copia recortada del path, con la idea de que "el buffered ES la onda un escalon mas alla". TAMBIEN rechazado, y por un motivo mas fuerte: "se hace inapreciable y confunde visualmente". La leccion, que queda escrita en los dos README: al compartir silueta con la senal, el ojo lee la banda COMO la senal — es ilegible POR CONSTRUCCION y ningun color la salva. La forma recta es legible precisamente porque NO es la onda. Asi que el buffered vuelve al Slider.SecondaryRange (G-2), la parte canonica que ya existia para esto, en vez de que el waveform pinte lo suyo. El COLOR si sobrevive de la iteracion anterior: acento lavado (color-mix del primary-solid con content-primary), que se separa del gris en TONO y no solo en luminosidad. Tokens de paleta, cero literales. Los tres colores de la onda son publicos y retunables por el disenador. Nota de metodo: la distancia RGB avalo un gris que el ojo rechazo al instante (esa metrica esta dominada por la luminosidad y es ciega al croma), y ademas un bug propio en la alfa del color-mix dio numeros inflados que se corrigieron. Dos recordatorios de que la medicion informa pero no decide. DEMO — material real. El control se llamaba `signal`, que es una de las 8 FAMILIAS del canon, en un componente que declara CERO eventos (expression: 'delegated'): ensenaba lo contrario de la verdad. Renombrado a `sample`. Y el material eran los earcons de sema (pitidos de 80-220 ms, `pop` salia casi plano) porque eran el unico audio del repo; ahora arranca en una pista real de 2:45 (static/music/t2.wav, aportada por el usuario). Y un defecto que 30 MB destaparon: el efecto de carga dependia de `source` Y de `buckets`, asi que mover el slider de buckets volvia a DESCARGAR el fichero entero. Separado en dos: decode una vez por fuente (caro), rebucketing puro y barato. Medido: t2 (5 MB, 86 ms) frente al master de 48 kHz/16 bit (30 MB, 186 ms); sus envolventes NO son identicas — delta maximo 0.298 por cubo, medio 0.048, porque los 8 bits suben el suelo de ruido y aplanan los pasajes suaves. Se elige t2 igualmente: 6x mas ligero por una envolvente marginalmente mas fiel. Verificado: check 75 = baseline, 0 propios; 35 tests; eidos-lint 0 invalidos; recipe-css-contract verde; component:audit --only waveform PASS; docs:check 0; sonda en vivo — 2 paths en la onda, banda recta al 66% en rgb(130,95,161). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
const eidosDir = resolve('src/uix/eidos/components');
const cssFiles = readdirSync(eidosDir, { withFileTypes: true }).flatMap((entry) => {
if (entry.isFile() && entry.name.endsWith('.css')) {
fix(waveform): el buffered vuelve a ser banda recta, y la demo estrena material real BUFFERED — segunda correccion por MIRADA, y la definitiva. Las dos formas se construyeron y se miraron. Primero fue el SecondaryRange del Slider con un velo neutro al 14%: rechazado ("el secundario no puede ser del mismo color"), y la medicion le dio la razon — velo y onda eran alfas del MISMO token (--color-content-primary al 14% vs 28%), o sea el mismo gris. Se paso entonces a una tercera copia recortada del path, con la idea de que "el buffered ES la onda un escalon mas alla". TAMBIEN rechazado, y por un motivo mas fuerte: "se hace inapreciable y confunde visualmente". La leccion, que queda escrita en los dos README: al compartir silueta con la senal, el ojo lee la banda COMO la senal — es ilegible POR CONSTRUCCION y ningun color la salva. La forma recta es legible precisamente porque NO es la onda. Asi que el buffered vuelve al Slider.SecondaryRange (G-2), la parte canonica que ya existia para esto, en vez de que el waveform pinte lo suyo. El COLOR si sobrevive de la iteracion anterior: acento lavado (color-mix del primary-solid con content-primary), que se separa del gris en TONO y no solo en luminosidad. Tokens de paleta, cero literales. Los tres colores de la onda son publicos y retunables por el disenador. Nota de metodo: la distancia RGB avalo un gris que el ojo rechazo al instante (esa metrica esta dominada por la luminosidad y es ciega al croma), y ademas un bug propio en la alfa del color-mix dio numeros inflados que se corrigieron. Dos recordatorios de que la medicion informa pero no decide. DEMO — material real. El control se llamaba `signal`, que es una de las 8 FAMILIAS del canon, en un componente que declara CERO eventos (expression: 'delegated'): ensenaba lo contrario de la verdad. Renombrado a `sample`. Y el material eran los earcons de sema (pitidos de 80-220 ms, `pop` salia casi plano) porque eran el unico audio del repo; ahora arranca en una pista real de 2:45 (static/music/t2.wav, aportada por el usuario). Y un defecto que 30 MB destaparon: el efecto de carga dependia de `source` Y de `buckets`, asi que mover el slider de buckets volvia a DESCARGAR el fichero entero. Separado en dos: decode una vez por fuente (caro), rebucketing puro y barato. Medido: t2 (5 MB, 86 ms) frente al master de 48 kHz/16 bit (30 MB, 186 ms); sus envolventes NO son identicas — delta maximo 0.298 por cubo, medio 0.048, porque los 8 bits suben el suelo de ruido y aplanan los pasajes suaves. Se elige t2 igualmente: 6x mas ligero por una envolvente marginalmente mas fiel. Verificado: check 75 = baseline, 0 propios; 35 tests; eidos-lint 0 invalidos; recipe-css-contract verde; component:audit --only waveform PASS; docs:check 0; sonda en vivo — 2 paths en la onda, banda recta al 66% en rgb(130,95,161). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
const name = entry.name.replace(/\.css$/, '');
return [{ name, path: resolve(eidosDir, entry.name) }];
}
if (entry.isDirectory()) {
fix(waveform): el buffered vuelve a ser banda recta, y la demo estrena material real BUFFERED — segunda correccion por MIRADA, y la definitiva. Las dos formas se construyeron y se miraron. Primero fue el SecondaryRange del Slider con un velo neutro al 14%: rechazado ("el secundario no puede ser del mismo color"), y la medicion le dio la razon — velo y onda eran alfas del MISMO token (--color-content-primary al 14% vs 28%), o sea el mismo gris. Se paso entonces a una tercera copia recortada del path, con la idea de que "el buffered ES la onda un escalon mas alla". TAMBIEN rechazado, y por un motivo mas fuerte: "se hace inapreciable y confunde visualmente". La leccion, que queda escrita en los dos README: al compartir silueta con la senal, el ojo lee la banda COMO la senal — es ilegible POR CONSTRUCCION y ningun color la salva. La forma recta es legible precisamente porque NO es la onda. Asi que el buffered vuelve al Slider.SecondaryRange (G-2), la parte canonica que ya existia para esto, en vez de que el waveform pinte lo suyo. El COLOR si sobrevive de la iteracion anterior: acento lavado (color-mix del primary-solid con content-primary), que se separa del gris en TONO y no solo en luminosidad. Tokens de paleta, cero literales. Los tres colores de la onda son publicos y retunables por el disenador. Nota de metodo: la distancia RGB avalo un gris que el ojo rechazo al instante (esa metrica esta dominada por la luminosidad y es ciega al croma), y ademas un bug propio en la alfa del color-mix dio numeros inflados que se corrigieron. Dos recordatorios de que la medicion informa pero no decide. DEMO — material real. El control se llamaba `signal`, que es una de las 8 FAMILIAS del canon, en un componente que declara CERO eventos (expression: 'delegated'): ensenaba lo contrario de la verdad. Renombrado a `sample`. Y el material eran los earcons de sema (pitidos de 80-220 ms, `pop` salia casi plano) porque eran el unico audio del repo; ahora arranca en una pista real de 2:45 (static/music/t2.wav, aportada por el usuario). Y un defecto que 30 MB destaparon: el efecto de carga dependia de `source` Y de `buckets`, asi que mover el slider de buckets volvia a DESCARGAR el fichero entero. Separado en dos: decode una vez por fuente (caro), rebucketing puro y barato. Medido: t2 (5 MB, 86 ms) frente al master de 48 kHz/16 bit (30 MB, 186 ms); sus envolventes NO son identicas — delta maximo 0.298 por cubo, medio 0.048, porque los 8 bits suben el suelo de ruido y aplanan los pasajes suaves. Se elige t2 igualmente: 6x mas ligero por una envolvente marginalmente mas fiel. Verificado: check 75 = baseline, 0 propios; 35 tests; eidos-lint 0 invalidos; recipe-css-contract verde; component:audit --only waveform PASS; docs:check 0; sonda en vivo — 2 paths en la onda, banda recta al 66% en rgb(130,95,161). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
const path = resolve(eidosDir, entry.name, `${entry.name}.css`);
return existsSync(path) ? [{ name: entry.name, path }] : [];
}
fix(waveform): el buffered vuelve a ser banda recta, y la demo estrena material real BUFFERED — segunda correccion por MIRADA, y la definitiva. Las dos formas se construyeron y se miraron. Primero fue el SecondaryRange del Slider con un velo neutro al 14%: rechazado ("el secundario no puede ser del mismo color"), y la medicion le dio la razon — velo y onda eran alfas del MISMO token (--color-content-primary al 14% vs 28%), o sea el mismo gris. Se paso entonces a una tercera copia recortada del path, con la idea de que "el buffered ES la onda un escalon mas alla". TAMBIEN rechazado, y por un motivo mas fuerte: "se hace inapreciable y confunde visualmente". La leccion, que queda escrita en los dos README: al compartir silueta con la senal, el ojo lee la banda COMO la senal — es ilegible POR CONSTRUCCION y ningun color la salva. La forma recta es legible precisamente porque NO es la onda. Asi que el buffered vuelve al Slider.SecondaryRange (G-2), la parte canonica que ya existia para esto, en vez de que el waveform pinte lo suyo. El COLOR si sobrevive de la iteracion anterior: acento lavado (color-mix del primary-solid con content-primary), que se separa del gris en TONO y no solo en luminosidad. Tokens de paleta, cero literales. Los tres colores de la onda son publicos y retunables por el disenador. Nota de metodo: la distancia RGB avalo un gris que el ojo rechazo al instante (esa metrica esta dominada por la luminosidad y es ciega al croma), y ademas un bug propio en la alfa del color-mix dio numeros inflados que se corrigieron. Dos recordatorios de que la medicion informa pero no decide. DEMO — material real. El control se llamaba `signal`, que es una de las 8 FAMILIAS del canon, en un componente que declara CERO eventos (expression: 'delegated'): ensenaba lo contrario de la verdad. Renombrado a `sample`. Y el material eran los earcons de sema (pitidos de 80-220 ms, `pop` salia casi plano) porque eran el unico audio del repo; ahora arranca en una pista real de 2:45 (static/music/t2.wav, aportada por el usuario). Y un defecto que 30 MB destaparon: el efecto de carga dependia de `source` Y de `buckets`, asi que mover el slider de buckets volvia a DESCARGAR el fichero entero. Separado en dos: decode una vez por fuente (caro), rebucketing puro y barato. Medido: t2 (5 MB, 86 ms) frente al master de 48 kHz/16 bit (30 MB, 186 ms); sus envolventes NO son identicas — delta maximo 0.298 por cubo, medio 0.048, porque los 8 bits suben el suelo de ruido y aplanan los pasajes suaves. Se elige t2 igualmente: 6x mas ligero por una envolvente marginalmente mas fiel. Verificado: check 75 = baseline, 0 propios; 35 tests; eidos-lint 0 invalidos; recipe-css-contract verde; component:audit --only waveform PASS; docs:check 0; sonda en vivo — 2 paths en la onda, banda recta al 66% en rgb(130,95,161). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
return [];
});
eidos: lint a CSS file against its morfo contract Consumes `compileMorfo(morfo).contracts.cssSelectors` to classify every `[data-*]` selector in an eidos CSS file: - morfo-backed: the runtime writes the attr; eidos reacts to it. - eidos-only: the marker is present (`[data-toggle]`) but at least one `data-*` is not declared on the morfo part. Legitimate design tokens (`data-color`, `data-size`, `data-variant`) and drift cases (`data-dialog-header` — a part the morfo no longer declares) both land here; the lint tool reports them so authors can decide. - invalid: the attr IS declared on the morfo, but with a value outside the declared enum. Bug. Also reports `unusedFromContract`: selectors the compiler promises that no eidos rule consumes — the inverse direction of drift. Two CLI entry points: - `scripts/eidos-lint.ts <component>` — single-component report - `scripts/eidos-lint-all.ts` — sweep across every eidos component Initial sweep finds 0 invalid, 134 eidos-only, 82 unused contract selectors across 11 components. Real drift hotspots: dialog/drawer `header`/`footer` (eidos parts the morfos don't declare), popover's `data-side × data-last-action` compounds, tooltip's `data-state='delayed-open'`. Deliberate left as-is for the user to triage — fixes belong in a separate commit. Tests cover toggle (clean baseline), dialog (drift detector for header/footer + dead `data-disabled`), and a synthetic invalid case. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
fix(waveform): el buffered vuelve a ser banda recta, y la demo estrena material real BUFFERED — segunda correccion por MIRADA, y la definitiva. Las dos formas se construyeron y se miraron. Primero fue el SecondaryRange del Slider con un velo neutro al 14%: rechazado ("el secundario no puede ser del mismo color"), y la medicion le dio la razon — velo y onda eran alfas del MISMO token (--color-content-primary al 14% vs 28%), o sea el mismo gris. Se paso entonces a una tercera copia recortada del path, con la idea de que "el buffered ES la onda un escalon mas alla". TAMBIEN rechazado, y por un motivo mas fuerte: "se hace inapreciable y confunde visualmente". La leccion, que queda escrita en los dos README: al compartir silueta con la senal, el ojo lee la banda COMO la senal — es ilegible POR CONSTRUCCION y ningun color la salva. La forma recta es legible precisamente porque NO es la onda. Asi que el buffered vuelve al Slider.SecondaryRange (G-2), la parte canonica que ya existia para esto, en vez de que el waveform pinte lo suyo. El COLOR si sobrevive de la iteracion anterior: acento lavado (color-mix del primary-solid con content-primary), que se separa del gris en TONO y no solo en luminosidad. Tokens de paleta, cero literales. Los tres colores de la onda son publicos y retunables por el disenador. Nota de metodo: la distancia RGB avalo un gris que el ojo rechazo al instante (esa metrica esta dominada por la luminosidad y es ciega al croma), y ademas un bug propio en la alfa del color-mix dio numeros inflados que se corrigieron. Dos recordatorios de que la medicion informa pero no decide. DEMO — material real. El control se llamaba `signal`, que es una de las 8 FAMILIAS del canon, en un componente que declara CERO eventos (expression: 'delegated'): ensenaba lo contrario de la verdad. Renombrado a `sample`. Y el material eran los earcons de sema (pitidos de 80-220 ms, `pop` salia casi plano) porque eran el unico audio del repo; ahora arranca en una pista real de 2:45 (static/music/t2.wav, aportada por el usuario). Y un defecto que 30 MB destaparon: el efecto de carga dependia de `source` Y de `buckets`, asi que mover el slider de buckets volvia a DESCARGAR el fichero entero. Separado en dos: decode una vez por fuente (caro), rebucketing puro y barato. Medido: t2 (5 MB, 86 ms) frente al master de 48 kHz/16 bit (30 MB, 186 ms); sus envolventes NO son identicas — delta maximo 0.298 por cubo, medio 0.048, porque los 8 bits suben el suelo de ruido y aplanan los pasajes suaves. Se elige t2 igualmente: 6x mas ligero por una envolvente marginalmente mas fiel. Verificado: check 75 = baseline, 0 propios; 35 tests; eidos-lint 0 invalidos; recipe-css-contract verde; component:audit --only waveform PASS; docs:check 0; sonda en vivo — 2 paths en la onda, banda recta al 66% en rgb(130,95,161). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
console.log('component morfo eidos invalid unused');
console.log('─────────────────────────────────────────────────────');
eidos: lint a CSS file against its morfo contract Consumes `compileMorfo(morfo).contracts.cssSelectors` to classify every `[data-*]` selector in an eidos CSS file: - morfo-backed: the runtime writes the attr; eidos reacts to it. - eidos-only: the marker is present (`[data-toggle]`) but at least one `data-*` is not declared on the morfo part. Legitimate design tokens (`data-color`, `data-size`, `data-variant`) and drift cases (`data-dialog-header` — a part the morfo no longer declares) both land here; the lint tool reports them so authors can decide. - invalid: the attr IS declared on the morfo, but with a value outside the declared enum. Bug. Also reports `unusedFromContract`: selectors the compiler promises that no eidos rule consumes — the inverse direction of drift. Two CLI entry points: - `scripts/eidos-lint.ts <component>` — single-component report - `scripts/eidos-lint-all.ts` — sweep across every eidos component Initial sweep finds 0 invalid, 134 eidos-only, 82 unused contract selectors across 11 components. Real drift hotspots: dialog/drawer `header`/`footer` (eidos parts the morfos don't declare), popover's `data-side × data-last-action` compounds, tooltip's `data-state='delayed-open'`. Deliberate left as-is for the user to triage — fixes belong in a separate commit. Tests cover toggle (clean baseline), dialog (drift detector for header/footer + dead `data-disabled`), and a synthetic invalid case. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
fix(waveform): el buffered vuelve a ser banda recta, y la demo estrena material real BUFFERED — segunda correccion por MIRADA, y la definitiva. Las dos formas se construyeron y se miraron. Primero fue el SecondaryRange del Slider con un velo neutro al 14%: rechazado ("el secundario no puede ser del mismo color"), y la medicion le dio la razon — velo y onda eran alfas del MISMO token (--color-content-primary al 14% vs 28%), o sea el mismo gris. Se paso entonces a una tercera copia recortada del path, con la idea de que "el buffered ES la onda un escalon mas alla". TAMBIEN rechazado, y por un motivo mas fuerte: "se hace inapreciable y confunde visualmente". La leccion, que queda escrita en los dos README: al compartir silueta con la senal, el ojo lee la banda COMO la senal — es ilegible POR CONSTRUCCION y ningun color la salva. La forma recta es legible precisamente porque NO es la onda. Asi que el buffered vuelve al Slider.SecondaryRange (G-2), la parte canonica que ya existia para esto, en vez de que el waveform pinte lo suyo. El COLOR si sobrevive de la iteracion anterior: acento lavado (color-mix del primary-solid con content-primary), que se separa del gris en TONO y no solo en luminosidad. Tokens de paleta, cero literales. Los tres colores de la onda son publicos y retunables por el disenador. Nota de metodo: la distancia RGB avalo un gris que el ojo rechazo al instante (esa metrica esta dominada por la luminosidad y es ciega al croma), y ademas un bug propio en la alfa del color-mix dio numeros inflados que se corrigieron. Dos recordatorios de que la medicion informa pero no decide. DEMO — material real. El control se llamaba `signal`, que es una de las 8 FAMILIAS del canon, en un componente que declara CERO eventos (expression: 'delegated'): ensenaba lo contrario de la verdad. Renombrado a `sample`. Y el material eran los earcons de sema (pitidos de 80-220 ms, `pop` salia casi plano) porque eran el unico audio del repo; ahora arranca en una pista real de 2:45 (static/music/t2.wav, aportada por el usuario). Y un defecto que 30 MB destaparon: el efecto de carga dependia de `source` Y de `buckets`, asi que mover el slider de buckets volvia a DESCARGAR el fichero entero. Separado en dos: decode una vez por fuente (caro), rebucketing puro y barato. Medido: t2 (5 MB, 86 ms) frente al master de 48 kHz/16 bit (30 MB, 186 ms); sus envolventes NO son identicas — delta maximo 0.298 por cubo, medio 0.048, porque los 8 bits suben el suelo de ruido y aplanan los pasajes suaves. Se elige t2 igualmente: 6x mas ligero por una envolvente marginalmente mas fiel. Verificado: check 75 = baseline, 0 propios; 35 tests; eidos-lint 0 invalidos; recipe-css-contract verde; component:audit --only waveform PASS; docs:check 0; sonda en vivo — 2 paths en la onda, banda recta al 66% en rgb(130,95,161). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
let totalInvalid = 0;
let totalEidosOnly = 0;
let totalUnused = 0;
const driftHotspots: { name: string; eidosOnly: string[]; invalid: string[] }[] = [];
eidos: lint a CSS file against its morfo contract Consumes `compileMorfo(morfo).contracts.cssSelectors` to classify every `[data-*]` selector in an eidos CSS file: - morfo-backed: the runtime writes the attr; eidos reacts to it. - eidos-only: the marker is present (`[data-toggle]`) but at least one `data-*` is not declared on the morfo part. Legitimate design tokens (`data-color`, `data-size`, `data-variant`) and drift cases (`data-dialog-header` — a part the morfo no longer declares) both land here; the lint tool reports them so authors can decide. - invalid: the attr IS declared on the morfo, but with a value outside the declared enum. Bug. Also reports `unusedFromContract`: selectors the compiler promises that no eidos rule consumes — the inverse direction of drift. Two CLI entry points: - `scripts/eidos-lint.ts <component>` — single-component report - `scripts/eidos-lint-all.ts` — sweep across every eidos component Initial sweep finds 0 invalid, 134 eidos-only, 82 unused contract selectors across 11 components. Real drift hotspots: dialog/drawer `header`/`footer` (eidos parts the morfos don't declare), popover's `data-side × data-last-action` compounds, tooltip's `data-state='delayed-open'`. Deliberate left as-is for the user to triage — fixes belong in a separate commit. Tests cover toggle (clean baseline), dialog (drift detector for header/footer + dead `data-disabled`), and a synthetic invalid case. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
for (const file of cssFiles) {
fix(waveform): el buffered vuelve a ser banda recta, y la demo estrena material real BUFFERED — segunda correccion por MIRADA, y la definitiva. Las dos formas se construyeron y se miraron. Primero fue el SecondaryRange del Slider con un velo neutro al 14%: rechazado ("el secundario no puede ser del mismo color"), y la medicion le dio la razon — velo y onda eran alfas del MISMO token (--color-content-primary al 14% vs 28%), o sea el mismo gris. Se paso entonces a una tercera copia recortada del path, con la idea de que "el buffered ES la onda un escalon mas alla". TAMBIEN rechazado, y por un motivo mas fuerte: "se hace inapreciable y confunde visualmente". La leccion, que queda escrita en los dos README: al compartir silueta con la senal, el ojo lee la banda COMO la senal — es ilegible POR CONSTRUCCION y ningun color la salva. La forma recta es legible precisamente porque NO es la onda. Asi que el buffered vuelve al Slider.SecondaryRange (G-2), la parte canonica que ya existia para esto, en vez de que el waveform pinte lo suyo. El COLOR si sobrevive de la iteracion anterior: acento lavado (color-mix del primary-solid con content-primary), que se separa del gris en TONO y no solo en luminosidad. Tokens de paleta, cero literales. Los tres colores de la onda son publicos y retunables por el disenador. Nota de metodo: la distancia RGB avalo un gris que el ojo rechazo al instante (esa metrica esta dominada por la luminosidad y es ciega al croma), y ademas un bug propio en la alfa del color-mix dio numeros inflados que se corrigieron. Dos recordatorios de que la medicion informa pero no decide. DEMO — material real. El control se llamaba `signal`, que es una de las 8 FAMILIAS del canon, en un componente que declara CERO eventos (expression: 'delegated'): ensenaba lo contrario de la verdad. Renombrado a `sample`. Y el material eran los earcons de sema (pitidos de 80-220 ms, `pop` salia casi plano) porque eran el unico audio del repo; ahora arranca en una pista real de 2:45 (static/music/t2.wav, aportada por el usuario). Y un defecto que 30 MB destaparon: el efecto de carga dependia de `source` Y de `buckets`, asi que mover el slider de buckets volvia a DESCARGAR el fichero entero. Separado en dos: decode una vez por fuente (caro), rebucketing puro y barato. Medido: t2 (5 MB, 86 ms) frente al master de 48 kHz/16 bit (30 MB, 186 ms); sus envolventes NO son identicas — delta maximo 0.298 por cubo, medio 0.048, porque los 8 bits suben el suelo de ruido y aplanan los pasajes suaves. Se elige t2 igualmente: 6x mas ligero por una envolvente marginalmente mas fiel. Verificado: check 75 = baseline, 0 propios; 35 tests; eidos-lint 0 invalidos; recipe-css-contract verde; component:audit --only waveform PASS; docs:check 0; sonda en vivo — 2 paths en la onda, banda recta al 66% en rgb(130,95,161). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
const name = file.name;
const morfoPath = resolve(`src/uix/morfo/components/${name}.ts`);
eidos: lint a CSS file against its morfo contract Consumes `compileMorfo(morfo).contracts.cssSelectors` to classify every `[data-*]` selector in an eidos CSS file: - morfo-backed: the runtime writes the attr; eidos reacts to it. - eidos-only: the marker is present (`[data-toggle]`) but at least one `data-*` is not declared on the morfo part. Legitimate design tokens (`data-color`, `data-size`, `data-variant`) and drift cases (`data-dialog-header` — a part the morfo no longer declares) both land here; the lint tool reports them so authors can decide. - invalid: the attr IS declared on the morfo, but with a value outside the declared enum. Bug. Also reports `unusedFromContract`: selectors the compiler promises that no eidos rule consumes — the inverse direction of drift. Two CLI entry points: - `scripts/eidos-lint.ts <component>` — single-component report - `scripts/eidos-lint-all.ts` — sweep across every eidos component Initial sweep finds 0 invalid, 134 eidos-only, 82 unused contract selectors across 11 components. Real drift hotspots: dialog/drawer `header`/`footer` (eidos parts the morfos don't declare), popover's `data-side × data-last-action` compounds, tooltip's `data-state='delayed-open'`. Deliberate left as-is for the user to triage — fixes belong in a separate commit. Tests cover toggle (clean baseline), dialog (drift detector for header/footer + dead `data-disabled`), and a synthetic invalid case. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
try {
fix(waveform): el buffered vuelve a ser banda recta, y la demo estrena material real BUFFERED — segunda correccion por MIRADA, y la definitiva. Las dos formas se construyeron y se miraron. Primero fue el SecondaryRange del Slider con un velo neutro al 14%: rechazado ("el secundario no puede ser del mismo color"), y la medicion le dio la razon — velo y onda eran alfas del MISMO token (--color-content-primary al 14% vs 28%), o sea el mismo gris. Se paso entonces a una tercera copia recortada del path, con la idea de que "el buffered ES la onda un escalon mas alla". TAMBIEN rechazado, y por un motivo mas fuerte: "se hace inapreciable y confunde visualmente". La leccion, que queda escrita en los dos README: al compartir silueta con la senal, el ojo lee la banda COMO la senal — es ilegible POR CONSTRUCCION y ningun color la salva. La forma recta es legible precisamente porque NO es la onda. Asi que el buffered vuelve al Slider.SecondaryRange (G-2), la parte canonica que ya existia para esto, en vez de que el waveform pinte lo suyo. El COLOR si sobrevive de la iteracion anterior: acento lavado (color-mix del primary-solid con content-primary), que se separa del gris en TONO y no solo en luminosidad. Tokens de paleta, cero literales. Los tres colores de la onda son publicos y retunables por el disenador. Nota de metodo: la distancia RGB avalo un gris que el ojo rechazo al instante (esa metrica esta dominada por la luminosidad y es ciega al croma), y ademas un bug propio en la alfa del color-mix dio numeros inflados que se corrigieron. Dos recordatorios de que la medicion informa pero no decide. DEMO — material real. El control se llamaba `signal`, que es una de las 8 FAMILIAS del canon, en un componente que declara CERO eventos (expression: 'delegated'): ensenaba lo contrario de la verdad. Renombrado a `sample`. Y el material eran los earcons de sema (pitidos de 80-220 ms, `pop` salia casi plano) porque eran el unico audio del repo; ahora arranca en una pista real de 2:45 (static/music/t2.wav, aportada por el usuario). Y un defecto que 30 MB destaparon: el efecto de carga dependia de `source` Y de `buckets`, asi que mover el slider de buckets volvia a DESCARGAR el fichero entero. Separado en dos: decode una vez por fuente (caro), rebucketing puro y barato. Medido: t2 (5 MB, 86 ms) frente al master de 48 kHz/16 bit (30 MB, 186 ms); sus envolventes NO son identicas — delta maximo 0.298 por cubo, medio 0.048, porque los 8 bits suben el suelo de ruido y aplanan los pasajes suaves. Se elige t2 igualmente: 6x mas ligero por una envolvente marginalmente mas fiel. Verificado: check 75 = baseline, 0 propios; 35 tests; eidos-lint 0 invalidos; recipe-css-contract verde; component:audit --only waveform PASS; docs:check 0; sonda en vivo — 2 paths en la onda, banda recta al 66% en rgb(130,95,161). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
readFileSync(morfoPath);
eidos: lint a CSS file against its morfo contract Consumes `compileMorfo(morfo).contracts.cssSelectors` to classify every `[data-*]` selector in an eidos CSS file: - morfo-backed: the runtime writes the attr; eidos reacts to it. - eidos-only: the marker is present (`[data-toggle]`) but at least one `data-*` is not declared on the morfo part. Legitimate design tokens (`data-color`, `data-size`, `data-variant`) and drift cases (`data-dialog-header` — a part the morfo no longer declares) both land here; the lint tool reports them so authors can decide. - invalid: the attr IS declared on the morfo, but with a value outside the declared enum. Bug. Also reports `unusedFromContract`: selectors the compiler promises that no eidos rule consumes — the inverse direction of drift. Two CLI entry points: - `scripts/eidos-lint.ts <component>` — single-component report - `scripts/eidos-lint-all.ts` — sweep across every eidos component Initial sweep finds 0 invalid, 134 eidos-only, 82 unused contract selectors across 11 components. Real drift hotspots: dialog/drawer `header`/`footer` (eidos parts the morfos don't declare), popover's `data-side × data-last-action` compounds, tooltip's `data-state='delayed-open'`. Deliberate left as-is for the user to triage — fixes belong in a separate commit. Tests cover toggle (clean baseline), dialog (drift detector for header/footer + dead `data-disabled`), and a synthetic invalid case. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
} catch {
fix(waveform): el buffered vuelve a ser banda recta, y la demo estrena material real BUFFERED — segunda correccion por MIRADA, y la definitiva. Las dos formas se construyeron y se miraron. Primero fue el SecondaryRange del Slider con un velo neutro al 14%: rechazado ("el secundario no puede ser del mismo color"), y la medicion le dio la razon — velo y onda eran alfas del MISMO token (--color-content-primary al 14% vs 28%), o sea el mismo gris. Se paso entonces a una tercera copia recortada del path, con la idea de que "el buffered ES la onda un escalon mas alla". TAMBIEN rechazado, y por un motivo mas fuerte: "se hace inapreciable y confunde visualmente". La leccion, que queda escrita en los dos README: al compartir silueta con la senal, el ojo lee la banda COMO la senal — es ilegible POR CONSTRUCCION y ningun color la salva. La forma recta es legible precisamente porque NO es la onda. Asi que el buffered vuelve al Slider.SecondaryRange (G-2), la parte canonica que ya existia para esto, en vez de que el waveform pinte lo suyo. El COLOR si sobrevive de la iteracion anterior: acento lavado (color-mix del primary-solid con content-primary), que se separa del gris en TONO y no solo en luminosidad. Tokens de paleta, cero literales. Los tres colores de la onda son publicos y retunables por el disenador. Nota de metodo: la distancia RGB avalo un gris que el ojo rechazo al instante (esa metrica esta dominada por la luminosidad y es ciega al croma), y ademas un bug propio en la alfa del color-mix dio numeros inflados que se corrigieron. Dos recordatorios de que la medicion informa pero no decide. DEMO — material real. El control se llamaba `signal`, que es una de las 8 FAMILIAS del canon, en un componente que declara CERO eventos (expression: 'delegated'): ensenaba lo contrario de la verdad. Renombrado a `sample`. Y el material eran los earcons de sema (pitidos de 80-220 ms, `pop` salia casi plano) porque eran el unico audio del repo; ahora arranca en una pista real de 2:45 (static/music/t2.wav, aportada por el usuario). Y un defecto que 30 MB destaparon: el efecto de carga dependia de `source` Y de `buckets`, asi que mover el slider de buckets volvia a DESCARGAR el fichero entero. Separado en dos: decode una vez por fuente (caro), rebucketing puro y barato. Medido: t2 (5 MB, 86 ms) frente al master de 48 kHz/16 bit (30 MB, 186 ms); sus envolventes NO son identicas — delta maximo 0.298 por cubo, medio 0.048, porque los 8 bits suben el suelo de ruido y aplanan los pasajes suaves. Se elige t2 igualmente: 6x mas ligero por una envolvente marginalmente mas fiel. Verificado: check 75 = baseline, 0 propios; 35 tests; eidos-lint 0 invalidos; recipe-css-contract verde; component:audit --only waveform PASS; docs:check 0; sonda en vivo — 2 paths en la onda, banda recta al 66% en rgb(130,95,161). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
console.log(`${name.padEnd(22)}(no morfo file — skipped)`);
continue;
eidos: lint a CSS file against its morfo contract Consumes `compileMorfo(morfo).contracts.cssSelectors` to classify every `[data-*]` selector in an eidos CSS file: - morfo-backed: the runtime writes the attr; eidos reacts to it. - eidos-only: the marker is present (`[data-toggle]`) but at least one `data-*` is not declared on the morfo part. Legitimate design tokens (`data-color`, `data-size`, `data-variant`) and drift cases (`data-dialog-header` — a part the morfo no longer declares) both land here; the lint tool reports them so authors can decide. - invalid: the attr IS declared on the morfo, but with a value outside the declared enum. Bug. Also reports `unusedFromContract`: selectors the compiler promises that no eidos rule consumes — the inverse direction of drift. Two CLI entry points: - `scripts/eidos-lint.ts <component>` — single-component report - `scripts/eidos-lint-all.ts` — sweep across every eidos component Initial sweep finds 0 invalid, 134 eidos-only, 82 unused contract selectors across 11 components. Real drift hotspots: dialog/drawer `header`/`footer` (eidos parts the morfos don't declare), popover's `data-side × data-last-action` compounds, tooltip's `data-state='delayed-open'`. Deliberate left as-is for the user to triage — fixes belong in a separate commit. Tests cover toggle (clean baseline), dialog (drift detector for header/footer + dead `data-disabled`), and a synthetic invalid case. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
}
fix(waveform): el buffered vuelve a ser banda recta, y la demo estrena material real BUFFERED — segunda correccion por MIRADA, y la definitiva. Las dos formas se construyeron y se miraron. Primero fue el SecondaryRange del Slider con un velo neutro al 14%: rechazado ("el secundario no puede ser del mismo color"), y la medicion le dio la razon — velo y onda eran alfas del MISMO token (--color-content-primary al 14% vs 28%), o sea el mismo gris. Se paso entonces a una tercera copia recortada del path, con la idea de que "el buffered ES la onda un escalon mas alla". TAMBIEN rechazado, y por un motivo mas fuerte: "se hace inapreciable y confunde visualmente". La leccion, que queda escrita en los dos README: al compartir silueta con la senal, el ojo lee la banda COMO la senal — es ilegible POR CONSTRUCCION y ningun color la salva. La forma recta es legible precisamente porque NO es la onda. Asi que el buffered vuelve al Slider.SecondaryRange (G-2), la parte canonica que ya existia para esto, en vez de que el waveform pinte lo suyo. El COLOR si sobrevive de la iteracion anterior: acento lavado (color-mix del primary-solid con content-primary), que se separa del gris en TONO y no solo en luminosidad. Tokens de paleta, cero literales. Los tres colores de la onda son publicos y retunables por el disenador. Nota de metodo: la distancia RGB avalo un gris que el ojo rechazo al instante (esa metrica esta dominada por la luminosidad y es ciega al croma), y ademas un bug propio en la alfa del color-mix dio numeros inflados que se corrigieron. Dos recordatorios de que la medicion informa pero no decide. DEMO — material real. El control se llamaba `signal`, que es una de las 8 FAMILIAS del canon, en un componente que declara CERO eventos (expression: 'delegated'): ensenaba lo contrario de la verdad. Renombrado a `sample`. Y el material eran los earcons de sema (pitidos de 80-220 ms, `pop` salia casi plano) porque eran el unico audio del repo; ahora arranca en una pista real de 2:45 (static/music/t2.wav, aportada por el usuario). Y un defecto que 30 MB destaparon: el efecto de carga dependia de `source` Y de `buckets`, asi que mover el slider de buckets volvia a DESCARGAR el fichero entero. Separado en dos: decode una vez por fuente (caro), rebucketing puro y barato. Medido: t2 (5 MB, 86 ms) frente al master de 48 kHz/16 bit (30 MB, 186 ms); sus envolventes NO son identicas — delta maximo 0.298 por cubo, medio 0.048, porque los 8 bits suben el suelo de ruido y aplanan los pasajes suaves. Se elige t2 igualmente: 6x mas ligero por una envolvente marginalmente mas fiel. Verificado: check 75 = baseline, 0 propios; 35 tests; eidos-lint 0 invalidos; recipe-css-contract verde; component:audit --only waveform PASS; docs:check 0; sonda en vivo — 2 paths en la onda, banda recta al 66% en rgb(130,95,161). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
const mod = (await import(`../src/uix/morfo/components/${name}`)) as Record<string, unknown>;
const exportName = `${name.replace(/-([a-z])/g, (_, c: string) => c.toUpperCase())}Morfo`;
const morfo = mod[exportName] as Morfo | undefined;
eidos: lint a CSS file against its morfo contract Consumes `compileMorfo(morfo).contracts.cssSelectors` to classify every `[data-*]` selector in an eidos CSS file: - morfo-backed: the runtime writes the attr; eidos reacts to it. - eidos-only: the marker is present (`[data-toggle]`) but at least one `data-*` is not declared on the morfo part. Legitimate design tokens (`data-color`, `data-size`, `data-variant`) and drift cases (`data-dialog-header` — a part the morfo no longer declares) both land here; the lint tool reports them so authors can decide. - invalid: the attr IS declared on the morfo, but with a value outside the declared enum. Bug. Also reports `unusedFromContract`: selectors the compiler promises that no eidos rule consumes — the inverse direction of drift. Two CLI entry points: - `scripts/eidos-lint.ts <component>` — single-component report - `scripts/eidos-lint-all.ts` — sweep across every eidos component Initial sweep finds 0 invalid, 134 eidos-only, 82 unused contract selectors across 11 components. Real drift hotspots: dialog/drawer `header`/`footer` (eidos parts the morfos don't declare), popover's `data-side × data-last-action` compounds, tooltip's `data-state='delayed-open'`. Deliberate left as-is for the user to triage — fixes belong in a separate commit. Tests cover toggle (clean baseline), dialog (drift detector for header/footer + dead `data-disabled`), and a synthetic invalid case. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
if (!morfo) {
fix(waveform): el buffered vuelve a ser banda recta, y la demo estrena material real BUFFERED — segunda correccion por MIRADA, y la definitiva. Las dos formas se construyeron y se miraron. Primero fue el SecondaryRange del Slider con un velo neutro al 14%: rechazado ("el secundario no puede ser del mismo color"), y la medicion le dio la razon — velo y onda eran alfas del MISMO token (--color-content-primary al 14% vs 28%), o sea el mismo gris. Se paso entonces a una tercera copia recortada del path, con la idea de que "el buffered ES la onda un escalon mas alla". TAMBIEN rechazado, y por un motivo mas fuerte: "se hace inapreciable y confunde visualmente". La leccion, que queda escrita en los dos README: al compartir silueta con la senal, el ojo lee la banda COMO la senal — es ilegible POR CONSTRUCCION y ningun color la salva. La forma recta es legible precisamente porque NO es la onda. Asi que el buffered vuelve al Slider.SecondaryRange (G-2), la parte canonica que ya existia para esto, en vez de que el waveform pinte lo suyo. El COLOR si sobrevive de la iteracion anterior: acento lavado (color-mix del primary-solid con content-primary), que se separa del gris en TONO y no solo en luminosidad. Tokens de paleta, cero literales. Los tres colores de la onda son publicos y retunables por el disenador. Nota de metodo: la distancia RGB avalo un gris que el ojo rechazo al instante (esa metrica esta dominada por la luminosidad y es ciega al croma), y ademas un bug propio en la alfa del color-mix dio numeros inflados que se corrigieron. Dos recordatorios de que la medicion informa pero no decide. DEMO — material real. El control se llamaba `signal`, que es una de las 8 FAMILIAS del canon, en un componente que declara CERO eventos (expression: 'delegated'): ensenaba lo contrario de la verdad. Renombrado a `sample`. Y el material eran los earcons de sema (pitidos de 80-220 ms, `pop` salia casi plano) porque eran el unico audio del repo; ahora arranca en una pista real de 2:45 (static/music/t2.wav, aportada por el usuario). Y un defecto que 30 MB destaparon: el efecto de carga dependia de `source` Y de `buckets`, asi que mover el slider de buckets volvia a DESCARGAR el fichero entero. Separado en dos: decode una vez por fuente (caro), rebucketing puro y barato. Medido: t2 (5 MB, 86 ms) frente al master de 48 kHz/16 bit (30 MB, 186 ms); sus envolventes NO son identicas — delta maximo 0.298 por cubo, medio 0.048, porque los 8 bits suben el suelo de ruido y aplanan los pasajes suaves. Se elige t2 igualmente: 6x mas ligero por una envolvente marginalmente mas fiel. Verificado: check 75 = baseline, 0 propios; 35 tests; eidos-lint 0 invalidos; recipe-css-contract verde; component:audit --only waveform PASS; docs:check 0; sonda en vivo — 2 paths en la onda, banda recta al 66% en rgb(130,95,161). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
console.log(`${name.padEnd(22)}(${exportName} not exported — skipped)`);
continue;
eidos: lint a CSS file against its morfo contract Consumes `compileMorfo(morfo).contracts.cssSelectors` to classify every `[data-*]` selector in an eidos CSS file: - morfo-backed: the runtime writes the attr; eidos reacts to it. - eidos-only: the marker is present (`[data-toggle]`) but at least one `data-*` is not declared on the morfo part. Legitimate design tokens (`data-color`, `data-size`, `data-variant`) and drift cases (`data-dialog-header` — a part the morfo no longer declares) both land here; the lint tool reports them so authors can decide. - invalid: the attr IS declared on the morfo, but with a value outside the declared enum. Bug. Also reports `unusedFromContract`: selectors the compiler promises that no eidos rule consumes — the inverse direction of drift. Two CLI entry points: - `scripts/eidos-lint.ts <component>` — single-component report - `scripts/eidos-lint-all.ts` — sweep across every eidos component Initial sweep finds 0 invalid, 134 eidos-only, 82 unused contract selectors across 11 components. Real drift hotspots: dialog/drawer `header`/`footer` (eidos parts the morfos don't declare), popover's `data-side × data-last-action` compounds, tooltip's `data-state='delayed-open'`. Deliberate left as-is for the user to triage — fixes belong in a separate commit. Tests cover toggle (clean baseline), dialog (drift detector for header/footer + dead `data-disabled`), and a synthetic invalid case. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
}
fix(waveform): el buffered vuelve a ser banda recta, y la demo estrena material real BUFFERED — segunda correccion por MIRADA, y la definitiva. Las dos formas se construyeron y se miraron. Primero fue el SecondaryRange del Slider con un velo neutro al 14%: rechazado ("el secundario no puede ser del mismo color"), y la medicion le dio la razon — velo y onda eran alfas del MISMO token (--color-content-primary al 14% vs 28%), o sea el mismo gris. Se paso entonces a una tercera copia recortada del path, con la idea de que "el buffered ES la onda un escalon mas alla". TAMBIEN rechazado, y por un motivo mas fuerte: "se hace inapreciable y confunde visualmente". La leccion, que queda escrita en los dos README: al compartir silueta con la senal, el ojo lee la banda COMO la senal — es ilegible POR CONSTRUCCION y ningun color la salva. La forma recta es legible precisamente porque NO es la onda. Asi que el buffered vuelve al Slider.SecondaryRange (G-2), la parte canonica que ya existia para esto, en vez de que el waveform pinte lo suyo. El COLOR si sobrevive de la iteracion anterior: acento lavado (color-mix del primary-solid con content-primary), que se separa del gris en TONO y no solo en luminosidad. Tokens de paleta, cero literales. Los tres colores de la onda son publicos y retunables por el disenador. Nota de metodo: la distancia RGB avalo un gris que el ojo rechazo al instante (esa metrica esta dominada por la luminosidad y es ciega al croma), y ademas un bug propio en la alfa del color-mix dio numeros inflados que se corrigieron. Dos recordatorios de que la medicion informa pero no decide. DEMO — material real. El control se llamaba `signal`, que es una de las 8 FAMILIAS del canon, en un componente que declara CERO eventos (expression: 'delegated'): ensenaba lo contrario de la verdad. Renombrado a `sample`. Y el material eran los earcons de sema (pitidos de 80-220 ms, `pop` salia casi plano) porque eran el unico audio del repo; ahora arranca en una pista real de 2:45 (static/music/t2.wav, aportada por el usuario). Y un defecto que 30 MB destaparon: el efecto de carga dependia de `source` Y de `buckets`, asi que mover el slider de buckets volvia a DESCARGAR el fichero entero. Separado en dos: decode una vez por fuente (caro), rebucketing puro y barato. Medido: t2 (5 MB, 86 ms) frente al master de 48 kHz/16 bit (30 MB, 186 ms); sus envolventes NO son identicas — delta maximo 0.298 por cubo, medio 0.048, porque los 8 bits suben el suelo de ruido y aplanan los pasajes suaves. Se elige t2 igualmente: 6x mas ligero por una envolvente marginalmente mas fiel. Verificado: check 75 = baseline, 0 propios; 35 tests; eidos-lint 0 invalidos; recipe-css-contract verde; component:audit --only waveform PASS; docs:check 0; sonda en vivo — 2 paths en la onda, banda recta al 66% en rgb(130,95,161). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
const compiled = compileMorfo(morfo);
const partMarkers = new Set(Object.values(compiled.parts.attrs));
const css = readFileSync(file.path, 'utf-8');
const report = lintEidosCss(css, compiled);
eidos: lint a CSS file against its morfo contract Consumes `compileMorfo(morfo).contracts.cssSelectors` to classify every `[data-*]` selector in an eidos CSS file: - morfo-backed: the runtime writes the attr; eidos reacts to it. - eidos-only: the marker is present (`[data-toggle]`) but at least one `data-*` is not declared on the morfo part. Legitimate design tokens (`data-color`, `data-size`, `data-variant`) and drift cases (`data-dialog-header` — a part the morfo no longer declares) both land here; the lint tool reports them so authors can decide. - invalid: the attr IS declared on the morfo, but with a value outside the declared enum. Bug. Also reports `unusedFromContract`: selectors the compiler promises that no eidos rule consumes — the inverse direction of drift. Two CLI entry points: - `scripts/eidos-lint.ts <component>` — single-component report - `scripts/eidos-lint-all.ts` — sweep across every eidos component Initial sweep finds 0 invalid, 134 eidos-only, 82 unused contract selectors across 11 components. Real drift hotspots: dialog/drawer `header`/`footer` (eidos parts the morfos don't declare), popover's `data-side × data-last-action` compounds, tooltip's `data-state='delayed-open'`. Deliberate left as-is for the user to triage — fixes belong in a separate commit. Tests cover toggle (clean baseline), dialog (drift detector for header/footer + dead `data-disabled`), and a synthetic invalid case. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
console.log(
`${name.padEnd(22)}${String(report.counts.morfoBacked).padEnd(7)}${String(report.counts.eidosOnly).padEnd(7)}${String(report.counts.invalid).padEnd(9)}${report.unusedFromContract.length}`
fix(waveform): el buffered vuelve a ser banda recta, y la demo estrena material real BUFFERED — segunda correccion por MIRADA, y la definitiva. Las dos formas se construyeron y se miraron. Primero fue el SecondaryRange del Slider con un velo neutro al 14%: rechazado ("el secundario no puede ser del mismo color"), y la medicion le dio la razon — velo y onda eran alfas del MISMO token (--color-content-primary al 14% vs 28%), o sea el mismo gris. Se paso entonces a una tercera copia recortada del path, con la idea de que "el buffered ES la onda un escalon mas alla". TAMBIEN rechazado, y por un motivo mas fuerte: "se hace inapreciable y confunde visualmente". La leccion, que queda escrita en los dos README: al compartir silueta con la senal, el ojo lee la banda COMO la senal — es ilegible POR CONSTRUCCION y ningun color la salva. La forma recta es legible precisamente porque NO es la onda. Asi que el buffered vuelve al Slider.SecondaryRange (G-2), la parte canonica que ya existia para esto, en vez de que el waveform pinte lo suyo. El COLOR si sobrevive de la iteracion anterior: acento lavado (color-mix del primary-solid con content-primary), que se separa del gris en TONO y no solo en luminosidad. Tokens de paleta, cero literales. Los tres colores de la onda son publicos y retunables por el disenador. Nota de metodo: la distancia RGB avalo un gris que el ojo rechazo al instante (esa metrica esta dominada por la luminosidad y es ciega al croma), y ademas un bug propio en la alfa del color-mix dio numeros inflados que se corrigieron. Dos recordatorios de que la medicion informa pero no decide. DEMO — material real. El control se llamaba `signal`, que es una de las 8 FAMILIAS del canon, en un componente que declara CERO eventos (expression: 'delegated'): ensenaba lo contrario de la verdad. Renombrado a `sample`. Y el material eran los earcons de sema (pitidos de 80-220 ms, `pop` salia casi plano) porque eran el unico audio del repo; ahora arranca en una pista real de 2:45 (static/music/t2.wav, aportada por el usuario). Y un defecto que 30 MB destaparon: el efecto de carga dependia de `source` Y de `buckets`, asi que mover el slider de buckets volvia a DESCARGAR el fichero entero. Separado en dos: decode una vez por fuente (caro), rebucketing puro y barato. Medido: t2 (5 MB, 86 ms) frente al master de 48 kHz/16 bit (30 MB, 186 ms); sus envolventes NO son identicas — delta maximo 0.298 por cubo, medio 0.048, porque los 8 bits suben el suelo de ruido y aplanan los pasajes suaves. Se elige t2 igualmente: 6x mas ligero por una envolvente marginalmente mas fiel. Verificado: check 75 = baseline, 0 propios; 35 tests; eidos-lint 0 invalidos; recipe-css-contract verde; component:audit --only waveform PASS; docs:check 0; sonda en vivo — 2 paths en la onda, banda recta al 66% en rgb(130,95,161). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
);
totalInvalid += report.counts.invalid;
totalEidosOnly += report.counts.eidosOnly;
totalUnused += report.unusedFromContract.length;
eidos: lint a CSS file against its morfo contract Consumes `compileMorfo(morfo).contracts.cssSelectors` to classify every `[data-*]` selector in an eidos CSS file: - morfo-backed: the runtime writes the attr; eidos reacts to it. - eidos-only: the marker is present (`[data-toggle]`) but at least one `data-*` is not declared on the morfo part. Legitimate design tokens (`data-color`, `data-size`, `data-variant`) and drift cases (`data-dialog-header` — a part the morfo no longer declares) both land here; the lint tool reports them so authors can decide. - invalid: the attr IS declared on the morfo, but with a value outside the declared enum. Bug. Also reports `unusedFromContract`: selectors the compiler promises that no eidos rule consumes — the inverse direction of drift. Two CLI entry points: - `scripts/eidos-lint.ts <component>` — single-component report - `scripts/eidos-lint-all.ts` — sweep across every eidos component Initial sweep finds 0 invalid, 134 eidos-only, 82 unused contract selectors across 11 components. Real drift hotspots: dialog/drawer `header`/`footer` (eidos parts the morfos don't declare), popover's `data-side × data-last-action` compounds, tooltip's `data-state='delayed-open'`. Deliberate left as-is for the user to triage — fixes belong in a separate commit. Tests cover toggle (clean baseline), dialog (drift detector for header/footer + dead `data-disabled`), and a synthetic invalid case. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
// Filter eidos-only that look like drift (data-* on a part where the morfo
// never declared the attr — vs design tokens like data-color/-size/-variant).
const drift = report.findings.filter(
(f) =>
f.status === 'eidos-only' &&
(f.eidosOnlyAttrs ?? f.attrs).some(
eidos: lint a CSS file against its morfo contract Consumes `compileMorfo(morfo).contracts.cssSelectors` to classify every `[data-*]` selector in an eidos CSS file: - morfo-backed: the runtime writes the attr; eidos reacts to it. - eidos-only: the marker is present (`[data-toggle]`) but at least one `data-*` is not declared on the morfo part. Legitimate design tokens (`data-color`, `data-size`, `data-variant`) and drift cases (`data-dialog-header` — a part the morfo no longer declares) both land here; the lint tool reports them so authors can decide. - invalid: the attr IS declared on the morfo, but with a value outside the declared enum. Bug. Also reports `unusedFromContract`: selectors the compiler promises that no eidos rule consumes — the inverse direction of drift. Two CLI entry points: - `scripts/eidos-lint.ts <component>` — single-component report - `scripts/eidos-lint-all.ts` — sweep across every eidos component Initial sweep finds 0 invalid, 134 eidos-only, 82 unused contract selectors across 11 components. Real drift hotspots: dialog/drawer `header`/`footer` (eidos parts the morfos don't declare), popover's `data-side × data-last-action` compounds, tooltip's `data-state='delayed-open'`. Deliberate left as-is for the user to triage — fixes belong in a separate commit. Tests cover toggle (clean baseline), dialog (drift detector for header/footer + dead `data-disabled`), and a synthetic invalid case. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
(a) =>
a.attr.startsWith('data-') &&
!partMarkers.has(a.attr) &&
!isAllowedEidosOnlyAttr(a.attr)
eidos: lint a CSS file against its morfo contract Consumes `compileMorfo(morfo).contracts.cssSelectors` to classify every `[data-*]` selector in an eidos CSS file: - morfo-backed: the runtime writes the attr; eidos reacts to it. - eidos-only: the marker is present (`[data-toggle]`) but at least one `data-*` is not declared on the morfo part. Legitimate design tokens (`data-color`, `data-size`, `data-variant`) and drift cases (`data-dialog-header` — a part the morfo no longer declares) both land here; the lint tool reports them so authors can decide. - invalid: the attr IS declared on the morfo, but with a value outside the declared enum. Bug. Also reports `unusedFromContract`: selectors the compiler promises that no eidos rule consumes — the inverse direction of drift. Two CLI entry points: - `scripts/eidos-lint.ts <component>` — single-component report - `scripts/eidos-lint-all.ts` — sweep across every eidos component Initial sweep finds 0 invalid, 134 eidos-only, 82 unused contract selectors across 11 components. Real drift hotspots: dialog/drawer `header`/`footer` (eidos parts the morfos don't declare), popover's `data-side × data-last-action` compounds, tooltip's `data-state='delayed-open'`. Deliberate left as-is for the user to triage — fixes belong in a separate commit. Tests cover toggle (clean baseline), dialog (drift detector for header/footer + dead `data-disabled`), and a synthetic invalid case. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
)
fix(waveform): el buffered vuelve a ser banda recta, y la demo estrena material real BUFFERED — segunda correccion por MIRADA, y la definitiva. Las dos formas se construyeron y se miraron. Primero fue el SecondaryRange del Slider con un velo neutro al 14%: rechazado ("el secundario no puede ser del mismo color"), y la medicion le dio la razon — velo y onda eran alfas del MISMO token (--color-content-primary al 14% vs 28%), o sea el mismo gris. Se paso entonces a una tercera copia recortada del path, con la idea de que "el buffered ES la onda un escalon mas alla". TAMBIEN rechazado, y por un motivo mas fuerte: "se hace inapreciable y confunde visualmente". La leccion, que queda escrita en los dos README: al compartir silueta con la senal, el ojo lee la banda COMO la senal — es ilegible POR CONSTRUCCION y ningun color la salva. La forma recta es legible precisamente porque NO es la onda. Asi que el buffered vuelve al Slider.SecondaryRange (G-2), la parte canonica que ya existia para esto, en vez de que el waveform pinte lo suyo. El COLOR si sobrevive de la iteracion anterior: acento lavado (color-mix del primary-solid con content-primary), que se separa del gris en TONO y no solo en luminosidad. Tokens de paleta, cero literales. Los tres colores de la onda son publicos y retunables por el disenador. Nota de metodo: la distancia RGB avalo un gris que el ojo rechazo al instante (esa metrica esta dominada por la luminosidad y es ciega al croma), y ademas un bug propio en la alfa del color-mix dio numeros inflados que se corrigieron. Dos recordatorios de que la medicion informa pero no decide. DEMO — material real. El control se llamaba `signal`, que es una de las 8 FAMILIAS del canon, en un componente que declara CERO eventos (expression: 'delegated'): ensenaba lo contrario de la verdad. Renombrado a `sample`. Y el material eran los earcons de sema (pitidos de 80-220 ms, `pop` salia casi plano) porque eran el unico audio del repo; ahora arranca en una pista real de 2:45 (static/music/t2.wav, aportada por el usuario). Y un defecto que 30 MB destaparon: el efecto de carga dependia de `source` Y de `buckets`, asi que mover el slider de buckets volvia a DESCARGAR el fichero entero. Separado en dos: decode una vez por fuente (caro), rebucketing puro y barato. Medido: t2 (5 MB, 86 ms) frente al master de 48 kHz/16 bit (30 MB, 186 ms); sus envolventes NO son identicas — delta maximo 0.298 por cubo, medio 0.048, porque los 8 bits suben el suelo de ruido y aplanan los pasajes suaves. Se elige t2 igualmente: 6x mas ligero por una envolvente marginalmente mas fiel. Verificado: check 75 = baseline, 0 propios; 35 tests; eidos-lint 0 invalidos; recipe-css-contract verde; component:audit --only waveform PASS; docs:check 0; sonda en vivo — 2 paths en la onda, banda recta al 66% en rgb(130,95,161). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
);
const invalid = report.findings.filter((f) => f.status === 'invalid');
eidos: lint a CSS file against its morfo contract Consumes `compileMorfo(morfo).contracts.cssSelectors` to classify every `[data-*]` selector in an eidos CSS file: - morfo-backed: the runtime writes the attr; eidos reacts to it. - eidos-only: the marker is present (`[data-toggle]`) but at least one `data-*` is not declared on the morfo part. Legitimate design tokens (`data-color`, `data-size`, `data-variant`) and drift cases (`data-dialog-header` — a part the morfo no longer declares) both land here; the lint tool reports them so authors can decide. - invalid: the attr IS declared on the morfo, but with a value outside the declared enum. Bug. Also reports `unusedFromContract`: selectors the compiler promises that no eidos rule consumes — the inverse direction of drift. Two CLI entry points: - `scripts/eidos-lint.ts <component>` — single-component report - `scripts/eidos-lint-all.ts` — sweep across every eidos component Initial sweep finds 0 invalid, 134 eidos-only, 82 unused contract selectors across 11 components. Real drift hotspots: dialog/drawer `header`/`footer` (eidos parts the morfos don't declare), popover's `data-side × data-last-action` compounds, tooltip's `data-state='delayed-open'`. Deliberate left as-is for the user to triage — fixes belong in a separate commit. Tests cover toggle (clean baseline), dialog (drift detector for header/footer + dead `data-disabled`), and a synthetic invalid case. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
if (drift.length || invalid.length) {
driftHotspots.push({
name,
eidosOnly: drift.map((f) => f.rule),
invalid: invalid.map((f) => `${f.rule} — ${f.reason}`)
fix(waveform): el buffered vuelve a ser banda recta, y la demo estrena material real BUFFERED — segunda correccion por MIRADA, y la definitiva. Las dos formas se construyeron y se miraron. Primero fue el SecondaryRange del Slider con un velo neutro al 14%: rechazado ("el secundario no puede ser del mismo color"), y la medicion le dio la razon — velo y onda eran alfas del MISMO token (--color-content-primary al 14% vs 28%), o sea el mismo gris. Se paso entonces a una tercera copia recortada del path, con la idea de que "el buffered ES la onda un escalon mas alla". TAMBIEN rechazado, y por un motivo mas fuerte: "se hace inapreciable y confunde visualmente". La leccion, que queda escrita en los dos README: al compartir silueta con la senal, el ojo lee la banda COMO la senal — es ilegible POR CONSTRUCCION y ningun color la salva. La forma recta es legible precisamente porque NO es la onda. Asi que el buffered vuelve al Slider.SecondaryRange (G-2), la parte canonica que ya existia para esto, en vez de que el waveform pinte lo suyo. El COLOR si sobrevive de la iteracion anterior: acento lavado (color-mix del primary-solid con content-primary), que se separa del gris en TONO y no solo en luminosidad. Tokens de paleta, cero literales. Los tres colores de la onda son publicos y retunables por el disenador. Nota de metodo: la distancia RGB avalo un gris que el ojo rechazo al instante (esa metrica esta dominada por la luminosidad y es ciega al croma), y ademas un bug propio en la alfa del color-mix dio numeros inflados que se corrigieron. Dos recordatorios de que la medicion informa pero no decide. DEMO — material real. El control se llamaba `signal`, que es una de las 8 FAMILIAS del canon, en un componente que declara CERO eventos (expression: 'delegated'): ensenaba lo contrario de la verdad. Renombrado a `sample`. Y el material eran los earcons de sema (pitidos de 80-220 ms, `pop` salia casi plano) porque eran el unico audio del repo; ahora arranca en una pista real de 2:45 (static/music/t2.wav, aportada por el usuario). Y un defecto que 30 MB destaparon: el efecto de carga dependia de `source` Y de `buckets`, asi que mover el slider de buckets volvia a DESCARGAR el fichero entero. Separado en dos: decode una vez por fuente (caro), rebucketing puro y barato. Medido: t2 (5 MB, 86 ms) frente al master de 48 kHz/16 bit (30 MB, 186 ms); sus envolventes NO son identicas — delta maximo 0.298 por cubo, medio 0.048, porque los 8 bits suben el suelo de ruido y aplanan los pasajes suaves. Se elige t2 igualmente: 6x mas ligero por una envolvente marginalmente mas fiel. Verificado: check 75 = baseline, 0 propios; 35 tests; eidos-lint 0 invalidos; recipe-css-contract verde; component:audit --only waveform PASS; docs:check 0; sonda en vivo — 2 paths en la onda, banda recta al 66% en rgb(130,95,161). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
});
eidos: lint a CSS file against its morfo contract Consumes `compileMorfo(morfo).contracts.cssSelectors` to classify every `[data-*]` selector in an eidos CSS file: - morfo-backed: the runtime writes the attr; eidos reacts to it. - eidos-only: the marker is present (`[data-toggle]`) but at least one `data-*` is not declared on the morfo part. Legitimate design tokens (`data-color`, `data-size`, `data-variant`) and drift cases (`data-dialog-header` — a part the morfo no longer declares) both land here; the lint tool reports them so authors can decide. - invalid: the attr IS declared on the morfo, but with a value outside the declared enum. Bug. Also reports `unusedFromContract`: selectors the compiler promises that no eidos rule consumes — the inverse direction of drift. Two CLI entry points: - `scripts/eidos-lint.ts <component>` — single-component report - `scripts/eidos-lint-all.ts` — sweep across every eidos component Initial sweep finds 0 invalid, 134 eidos-only, 82 unused contract selectors across 11 components. Real drift hotspots: dialog/drawer `header`/`footer` (eidos parts the morfos don't declare), popover's `data-side × data-last-action` compounds, tooltip's `data-state='delayed-open'`. Deliberate left as-is for the user to triage — fixes belong in a separate commit. Tests cover toggle (clean baseline), dialog (drift detector for header/footer + dead `data-disabled`), and a synthetic invalid case. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
}
}
fix(waveform): el buffered vuelve a ser banda recta, y la demo estrena material real BUFFERED — segunda correccion por MIRADA, y la definitiva. Las dos formas se construyeron y se miraron. Primero fue el SecondaryRange del Slider con un velo neutro al 14%: rechazado ("el secundario no puede ser del mismo color"), y la medicion le dio la razon — velo y onda eran alfas del MISMO token (--color-content-primary al 14% vs 28%), o sea el mismo gris. Se paso entonces a una tercera copia recortada del path, con la idea de que "el buffered ES la onda un escalon mas alla". TAMBIEN rechazado, y por un motivo mas fuerte: "se hace inapreciable y confunde visualmente". La leccion, que queda escrita en los dos README: al compartir silueta con la senal, el ojo lee la banda COMO la senal — es ilegible POR CONSTRUCCION y ningun color la salva. La forma recta es legible precisamente porque NO es la onda. Asi que el buffered vuelve al Slider.SecondaryRange (G-2), la parte canonica que ya existia para esto, en vez de que el waveform pinte lo suyo. El COLOR si sobrevive de la iteracion anterior: acento lavado (color-mix del primary-solid con content-primary), que se separa del gris en TONO y no solo en luminosidad. Tokens de paleta, cero literales. Los tres colores de la onda son publicos y retunables por el disenador. Nota de metodo: la distancia RGB avalo un gris que el ojo rechazo al instante (esa metrica esta dominada por la luminosidad y es ciega al croma), y ademas un bug propio en la alfa del color-mix dio numeros inflados que se corrigieron. Dos recordatorios de que la medicion informa pero no decide. DEMO — material real. El control se llamaba `signal`, que es una de las 8 FAMILIAS del canon, en un componente que declara CERO eventos (expression: 'delegated'): ensenaba lo contrario de la verdad. Renombrado a `sample`. Y el material eran los earcons de sema (pitidos de 80-220 ms, `pop` salia casi plano) porque eran el unico audio del repo; ahora arranca en una pista real de 2:45 (static/music/t2.wav, aportada por el usuario). Y un defecto que 30 MB destaparon: el efecto de carga dependia de `source` Y de `buckets`, asi que mover el slider de buckets volvia a DESCARGAR el fichero entero. Separado en dos: decode una vez por fuente (caro), rebucketing puro y barato. Medido: t2 (5 MB, 86 ms) frente al master de 48 kHz/16 bit (30 MB, 186 ms); sus envolventes NO son identicas — delta maximo 0.298 por cubo, medio 0.048, porque los 8 bits suben el suelo de ruido y aplanan los pasajes suaves. Se elige t2 igualmente: 6x mas ligero por una envolvente marginalmente mas fiel. Verificado: check 75 = baseline, 0 propios; 35 tests; eidos-lint 0 invalidos; recipe-css-contract verde; component:audit --only waveform PASS; docs:check 0; sonda en vivo — 2 paths en la onda, banda recta al 66% en rgb(130,95,161). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
console.log('─────────────────────────────────────────────────────');
console.log(
`totals${' '.repeat(16)} ${totalEidosOnly} ${totalInvalid} ${totalUnused}`
);
eidos: lint a CSS file against its morfo contract Consumes `compileMorfo(morfo).contracts.cssSelectors` to classify every `[data-*]` selector in an eidos CSS file: - morfo-backed: the runtime writes the attr; eidos reacts to it. - eidos-only: the marker is present (`[data-toggle]`) but at least one `data-*` is not declared on the morfo part. Legitimate design tokens (`data-color`, `data-size`, `data-variant`) and drift cases (`data-dialog-header` — a part the morfo no longer declares) both land here; the lint tool reports them so authors can decide. - invalid: the attr IS declared on the morfo, but with a value outside the declared enum. Bug. Also reports `unusedFromContract`: selectors the compiler promises that no eidos rule consumes — the inverse direction of drift. Two CLI entry points: - `scripts/eidos-lint.ts <component>` — single-component report - `scripts/eidos-lint-all.ts` — sweep across every eidos component Initial sweep finds 0 invalid, 134 eidos-only, 82 unused contract selectors across 11 components. Real drift hotspots: dialog/drawer `header`/`footer` (eidos parts the morfos don't declare), popover's `data-side × data-last-action` compounds, tooltip's `data-state='delayed-open'`. Deliberate left as-is for the user to triage — fixes belong in a separate commit. Tests cover toggle (clean baseline), dialog (drift detector for header/footer + dead `data-disabled`), and a synthetic invalid case. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
if (driftHotspots.length) {
fix(waveform): el buffered vuelve a ser banda recta, y la demo estrena material real BUFFERED — segunda correccion por MIRADA, y la definitiva. Las dos formas se construyeron y se miraron. Primero fue el SecondaryRange del Slider con un velo neutro al 14%: rechazado ("el secundario no puede ser del mismo color"), y la medicion le dio la razon — velo y onda eran alfas del MISMO token (--color-content-primary al 14% vs 28%), o sea el mismo gris. Se paso entonces a una tercera copia recortada del path, con la idea de que "el buffered ES la onda un escalon mas alla". TAMBIEN rechazado, y por un motivo mas fuerte: "se hace inapreciable y confunde visualmente". La leccion, que queda escrita en los dos README: al compartir silueta con la senal, el ojo lee la banda COMO la senal — es ilegible POR CONSTRUCCION y ningun color la salva. La forma recta es legible precisamente porque NO es la onda. Asi que el buffered vuelve al Slider.SecondaryRange (G-2), la parte canonica que ya existia para esto, en vez de que el waveform pinte lo suyo. El COLOR si sobrevive de la iteracion anterior: acento lavado (color-mix del primary-solid con content-primary), que se separa del gris en TONO y no solo en luminosidad. Tokens de paleta, cero literales. Los tres colores de la onda son publicos y retunables por el disenador. Nota de metodo: la distancia RGB avalo un gris que el ojo rechazo al instante (esa metrica esta dominada por la luminosidad y es ciega al croma), y ademas un bug propio en la alfa del color-mix dio numeros inflados que se corrigieron. Dos recordatorios de que la medicion informa pero no decide. DEMO — material real. El control se llamaba `signal`, que es una de las 8 FAMILIAS del canon, en un componente que declara CERO eventos (expression: 'delegated'): ensenaba lo contrario de la verdad. Renombrado a `sample`. Y el material eran los earcons de sema (pitidos de 80-220 ms, `pop` salia casi plano) porque eran el unico audio del repo; ahora arranca en una pista real de 2:45 (static/music/t2.wav, aportada por el usuario). Y un defecto que 30 MB destaparon: el efecto de carga dependia de `source` Y de `buckets`, asi que mover el slider de buckets volvia a DESCARGAR el fichero entero. Separado en dos: decode una vez por fuente (caro), rebucketing puro y barato. Medido: t2 (5 MB, 86 ms) frente al master de 48 kHz/16 bit (30 MB, 186 ms); sus envolventes NO son identicas — delta maximo 0.298 por cubo, medio 0.048, porque los 8 bits suben el suelo de ruido y aplanan los pasajes suaves. Se elige t2 igualmente: 6x mas ligero por una envolvente marginalmente mas fiel. Verificado: check 75 = baseline, 0 propios; 35 tests; eidos-lint 0 invalidos; recipe-css-contract verde; component:audit --only waveform PASS; docs:check 0; sonda en vivo — 2 paths en la onda, banda recta al 66% en rgb(130,95,161). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
console.log('\nDrift hotspots (eidos uses data-* attrs the morfo does not declare):');
eidos: lint a CSS file against its morfo contract Consumes `compileMorfo(morfo).contracts.cssSelectors` to classify every `[data-*]` selector in an eidos CSS file: - morfo-backed: the runtime writes the attr; eidos reacts to it. - eidos-only: the marker is present (`[data-toggle]`) but at least one `data-*` is not declared on the morfo part. Legitimate design tokens (`data-color`, `data-size`, `data-variant`) and drift cases (`data-dialog-header` — a part the morfo no longer declares) both land here; the lint tool reports them so authors can decide. - invalid: the attr IS declared on the morfo, but with a value outside the declared enum. Bug. Also reports `unusedFromContract`: selectors the compiler promises that no eidos rule consumes — the inverse direction of drift. Two CLI entry points: - `scripts/eidos-lint.ts <component>` — single-component report - `scripts/eidos-lint-all.ts` — sweep across every eidos component Initial sweep finds 0 invalid, 134 eidos-only, 82 unused contract selectors across 11 components. Real drift hotspots: dialog/drawer `header`/`footer` (eidos parts the morfos don't declare), popover's `data-side × data-last-action` compounds, tooltip's `data-state='delayed-open'`. Deliberate left as-is for the user to triage — fixes belong in a separate commit. Tests cover toggle (clean baseline), dialog (drift detector for header/footer + dead `data-disabled`), and a synthetic invalid case. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
for (const h of driftHotspots) {
fix(waveform): el buffered vuelve a ser banda recta, y la demo estrena material real BUFFERED — segunda correccion por MIRADA, y la definitiva. Las dos formas se construyeron y se miraron. Primero fue el SecondaryRange del Slider con un velo neutro al 14%: rechazado ("el secundario no puede ser del mismo color"), y la medicion le dio la razon — velo y onda eran alfas del MISMO token (--color-content-primary al 14% vs 28%), o sea el mismo gris. Se paso entonces a una tercera copia recortada del path, con la idea de que "el buffered ES la onda un escalon mas alla". TAMBIEN rechazado, y por un motivo mas fuerte: "se hace inapreciable y confunde visualmente". La leccion, que queda escrita en los dos README: al compartir silueta con la senal, el ojo lee la banda COMO la senal — es ilegible POR CONSTRUCCION y ningun color la salva. La forma recta es legible precisamente porque NO es la onda. Asi que el buffered vuelve al Slider.SecondaryRange (G-2), la parte canonica que ya existia para esto, en vez de que el waveform pinte lo suyo. El COLOR si sobrevive de la iteracion anterior: acento lavado (color-mix del primary-solid con content-primary), que se separa del gris en TONO y no solo en luminosidad. Tokens de paleta, cero literales. Los tres colores de la onda son publicos y retunables por el disenador. Nota de metodo: la distancia RGB avalo un gris que el ojo rechazo al instante (esa metrica esta dominada por la luminosidad y es ciega al croma), y ademas un bug propio en la alfa del color-mix dio numeros inflados que se corrigieron. Dos recordatorios de que la medicion informa pero no decide. DEMO — material real. El control se llamaba `signal`, que es una de las 8 FAMILIAS del canon, en un componente que declara CERO eventos (expression: 'delegated'): ensenaba lo contrario de la verdad. Renombrado a `sample`. Y el material eran los earcons de sema (pitidos de 80-220 ms, `pop` salia casi plano) porque eran el unico audio del repo; ahora arranca en una pista real de 2:45 (static/music/t2.wav, aportada por el usuario). Y un defecto que 30 MB destaparon: el efecto de carga dependia de `source` Y de `buckets`, asi que mover el slider de buckets volvia a DESCARGAR el fichero entero. Separado en dos: decode una vez por fuente (caro), rebucketing puro y barato. Medido: t2 (5 MB, 86 ms) frente al master de 48 kHz/16 bit (30 MB, 186 ms); sus envolventes NO son identicas — delta maximo 0.298 por cubo, medio 0.048, porque los 8 bits suben el suelo de ruido y aplanan los pasajes suaves. Se elige t2 igualmente: 6x mas ligero por una envolvente marginalmente mas fiel. Verificado: check 75 = baseline, 0 propios; 35 tests; eidos-lint 0 invalidos; recipe-css-contract verde; component:audit --only waveform PASS; docs:check 0; sonda en vivo — 2 paths en la onda, banda recta al 66% en rgb(130,95,161). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
if (!h.eidosOnly.length && !h.invalid.length) continue;
console.log(`\n ${h.name}`);
for (const r of h.invalid) console.log(` ✗ ${r}`);
for (const r of h.eidosOnly) console.log(` · ${r}`);
eidos: lint a CSS file against its morfo contract Consumes `compileMorfo(morfo).contracts.cssSelectors` to classify every `[data-*]` selector in an eidos CSS file: - morfo-backed: the runtime writes the attr; eidos reacts to it. - eidos-only: the marker is present (`[data-toggle]`) but at least one `data-*` is not declared on the morfo part. Legitimate design tokens (`data-color`, `data-size`, `data-variant`) and drift cases (`data-dialog-header` — a part the morfo no longer declares) both land here; the lint tool reports them so authors can decide. - invalid: the attr IS declared on the morfo, but with a value outside the declared enum. Bug. Also reports `unusedFromContract`: selectors the compiler promises that no eidos rule consumes — the inverse direction of drift. Two CLI entry points: - `scripts/eidos-lint.ts <component>` — single-component report - `scripts/eidos-lint-all.ts` — sweep across every eidos component Initial sweep finds 0 invalid, 134 eidos-only, 82 unused contract selectors across 11 components. Real drift hotspots: dialog/drawer `header`/`footer` (eidos parts the morfos don't declare), popover's `data-side × data-last-action` compounds, tooltip's `data-state='delayed-open'`. Deliberate left as-is for the user to triage — fixes belong in a separate commit. Tests cover toggle (clean baseline), dialog (drift detector for header/footer + dead `data-disabled`), and a synthetic invalid case. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
}
} else {
fix(waveform): el buffered vuelve a ser banda recta, y la demo estrena material real BUFFERED — segunda correccion por MIRADA, y la definitiva. Las dos formas se construyeron y se miraron. Primero fue el SecondaryRange del Slider con un velo neutro al 14%: rechazado ("el secundario no puede ser del mismo color"), y la medicion le dio la razon — velo y onda eran alfas del MISMO token (--color-content-primary al 14% vs 28%), o sea el mismo gris. Se paso entonces a una tercera copia recortada del path, con la idea de que "el buffered ES la onda un escalon mas alla". TAMBIEN rechazado, y por un motivo mas fuerte: "se hace inapreciable y confunde visualmente". La leccion, que queda escrita en los dos README: al compartir silueta con la senal, el ojo lee la banda COMO la senal — es ilegible POR CONSTRUCCION y ningun color la salva. La forma recta es legible precisamente porque NO es la onda. Asi que el buffered vuelve al Slider.SecondaryRange (G-2), la parte canonica que ya existia para esto, en vez de que el waveform pinte lo suyo. El COLOR si sobrevive de la iteracion anterior: acento lavado (color-mix del primary-solid con content-primary), que se separa del gris en TONO y no solo en luminosidad. Tokens de paleta, cero literales. Los tres colores de la onda son publicos y retunables por el disenador. Nota de metodo: la distancia RGB avalo un gris que el ojo rechazo al instante (esa metrica esta dominada por la luminosidad y es ciega al croma), y ademas un bug propio en la alfa del color-mix dio numeros inflados que se corrigieron. Dos recordatorios de que la medicion informa pero no decide. DEMO — material real. El control se llamaba `signal`, que es una de las 8 FAMILIAS del canon, en un componente que declara CERO eventos (expression: 'delegated'): ensenaba lo contrario de la verdad. Renombrado a `sample`. Y el material eran los earcons de sema (pitidos de 80-220 ms, `pop` salia casi plano) porque eran el unico audio del repo; ahora arranca en una pista real de 2:45 (static/music/t2.wav, aportada por el usuario). Y un defecto que 30 MB destaparon: el efecto de carga dependia de `source` Y de `buckets`, asi que mover el slider de buckets volvia a DESCARGAR el fichero entero. Separado en dos: decode una vez por fuente (caro), rebucketing puro y barato. Medido: t2 (5 MB, 86 ms) frente al master de 48 kHz/16 bit (30 MB, 186 ms); sus envolventes NO son identicas — delta maximo 0.298 por cubo, medio 0.048, porque los 8 bits suben el suelo de ruido y aplanan los pasajes suaves. Se elige t2 igualmente: 6x mas ligero por una envolvente marginalmente mas fiel. Verificado: check 75 = baseline, 0 propios; 35 tests; eidos-lint 0 invalidos; recipe-css-contract verde; component:audit --only waveform PASS; docs:check 0; sonda en vivo — 2 paths en la onda, banda recta al 66% en rgb(130,95,161). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
console.log('\nNo drift hotspots beyond documented Eidos-only attrs/parts.');
eidos: lint a CSS file against its morfo contract Consumes `compileMorfo(morfo).contracts.cssSelectors` to classify every `[data-*]` selector in an eidos CSS file: - morfo-backed: the runtime writes the attr; eidos reacts to it. - eidos-only: the marker is present (`[data-toggle]`) but at least one `data-*` is not declared on the morfo part. Legitimate design tokens (`data-color`, `data-size`, `data-variant`) and drift cases (`data-dialog-header` — a part the morfo no longer declares) both land here; the lint tool reports them so authors can decide. - invalid: the attr IS declared on the morfo, but with a value outside the declared enum. Bug. Also reports `unusedFromContract`: selectors the compiler promises that no eidos rule consumes — the inverse direction of drift. Two CLI entry points: - `scripts/eidos-lint.ts <component>` — single-component report - `scripts/eidos-lint-all.ts` — sweep across every eidos component Initial sweep finds 0 invalid, 134 eidos-only, 82 unused contract selectors across 11 components. Real drift hotspots: dialog/drawer `header`/`footer` (eidos parts the morfos don't declare), popover's `data-side × data-last-action` compounds, tooltip's `data-state='delayed-open'`. Deliberate left as-is for the user to triage — fixes belong in a separate commit. Tests cover toggle (clean baseline), dialog (drift detector for header/footer + dead `data-disabled`), and a synthetic invalid case. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
}
feat(morfo,sema,eidos): todo evento dice de que familia es, y el cruce por fin se ve El framework llamaba a la misma cosa de dos maneras: `open` pelado en ocho componentes y `emerge-open` en tres. No era estetica — un preset de movimiento engancha el nombre con `^=`, asi que el dialecto pelado no casaba con ninguna firma y simplemente no animaba, sin romper una sola prueba. Los 40 nombres sin prefijo pasan a `{familia}-{verbo}[-{matiz}]`: 256 eventos, 256 con prefijo, 0 ambiguos. El plan decia 36 y decia `handle-drag-start`; eran 40, y el canon (c25) dice que esos verbos son `pick` y `drop` — `handle-pick` y `handle-drop` ya existian en 10 y 4 componentes. `validateMorfo` cierra la puerta: un `events[].name` que no empiece por su familia ahora lanza. Visto fallar antes con un nombre pelado inyectado. Lo que el renombrado destapo, y va aqui tambien: - La receta del splitter enganchaba `commit-resize`, muerto desde `bd2e40366`. No casaba desde mayo y nadie chillo. Reescrita por FAMILIA, como slider y knob, y `eidos-lint` valida ahora el VALOR de `data-event*` contra el catalogo de morfos — el guard que lo habria cazado en su dia. - La familia `shift` era muda en el canal visual, contra su propia doctrina (c27: el cruce debe percibirse; c34 tipifica el «shift invisible»). Su mapa ya describia la firma que le faltaba y su sonido por defecto es `slide`. Ahora tiene firma direccional: sexto atributo del sello (`data-event-direction`, `forward`|`backward`, por emision) y deslizamiento de 320ms RTL-safe por `:dir()`. Medido: LTR -30px/+30px, RTL los invierte. - El sello de `shift-navigate` pasa del BOTON al `grid` en los cuatro calendarios. Medido: el boton recibia `contact-activate` y 8,5 ms despues —media trama— el `shift-navigate` pisaba la misma ranura y el `press-squeeze` moria sin pintar un fotograma. Una superficie, una ranura (A-36). - 101 contradicciones docs<->morfo adjudicadas con evidencia (git log, docs de decision, el componente vivo). Las docs desfasadas, corregidas; los nueve DEFECTOS de codigo obsoleto quedan abiertos y sin tocar. - `SoundDirection` -> `SoundContour`: era un contorno de tono, no un sentido, y habia tres cosas distintas deletreadas «direction». check en su linea base con 0 errores nuevos por diferencia de conjuntos · docs:check 0/0 · eidos-lint invalid 0 · el censo y las escenas de navegador medidas con raton real y rAF vivo. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
// `data-event*` VALUE check. Its own pass over the same files: it needs no
// compiled morfo, so it also covers the CSS skipped above for lack of one.
const vocabulary = await loadEventVocabulary();
let deadEvents = 0;
const eventBlocks: string[] = [];
for (const file of cssFiles) {
const findings = lintEventValues(readFileSync(file.path, 'utf-8'), vocabulary, file.name);
if (!findings.length) continue;
deadEvents += findings.filter((f) => f.level === 'error').length;
eventBlocks.push(` ${file.name}\n${formatEventFindings(findings, ' ')}`);
}
if (eventBlocks.length) {
console.log('\ndata-event* vocabulary (value must exist in a morfo / the canon):');
for (const block of eventBlocks) console.log(`\n${block}`);
} else {
console.log('\nEvery data-event* value in a recipe exists in the morfo catalogue.');
}
if (totalInvalid > 0 || deadEvents > 0) process.exit(1);
eidos: lint a CSS file against its morfo contract Consumes `compileMorfo(morfo).contracts.cssSelectors` to classify every `[data-*]` selector in an eidos CSS file: - morfo-backed: the runtime writes the attr; eidos reacts to it. - eidos-only: the marker is present (`[data-toggle]`) but at least one `data-*` is not declared on the morfo part. Legitimate design tokens (`data-color`, `data-size`, `data-variant`) and drift cases (`data-dialog-header` — a part the morfo no longer declares) both land here; the lint tool reports them so authors can decide. - invalid: the attr IS declared on the morfo, but with a value outside the declared enum. Bug. Also reports `unusedFromContract`: selectors the compiler promises that no eidos rule consumes — the inverse direction of drift. Two CLI entry points: - `scripts/eidos-lint.ts <component>` — single-component report - `scripts/eidos-lint-all.ts` — sweep across every eidos component Initial sweep finds 0 invalid, 134 eidos-only, 82 unused contract selectors across 11 components. Real drift hotspots: dialog/drawer `header`/`footer` (eidos parts the morfos don't declare), popover's `data-side × data-last-action` compounds, tooltip's `data-state='delayed-open'`. Deliberate left as-is for the user to triage — fixes belong in a separate commit. Tests cover toggle (clean baseline), dialog (drift detector for header/footer + dead `data-disabled`), and a synthetic invalid case. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
}
function isAllowedEidosOnlyAttr(attr: string): boolean {
fix(waveform): el buffered vuelve a ser banda recta, y la demo estrena material real BUFFERED — segunda correccion por MIRADA, y la definitiva. Las dos formas se construyeron y se miraron. Primero fue el SecondaryRange del Slider con un velo neutro al 14%: rechazado ("el secundario no puede ser del mismo color"), y la medicion le dio la razon — velo y onda eran alfas del MISMO token (--color-content-primary al 14% vs 28%), o sea el mismo gris. Se paso entonces a una tercera copia recortada del path, con la idea de que "el buffered ES la onda un escalon mas alla". TAMBIEN rechazado, y por un motivo mas fuerte: "se hace inapreciable y confunde visualmente". La leccion, que queda escrita en los dos README: al compartir silueta con la senal, el ojo lee la banda COMO la senal — es ilegible POR CONSTRUCCION y ningun color la salva. La forma recta es legible precisamente porque NO es la onda. Asi que el buffered vuelve al Slider.SecondaryRange (G-2), la parte canonica que ya existia para esto, en vez de que el waveform pinte lo suyo. El COLOR si sobrevive de la iteracion anterior: acento lavado (color-mix del primary-solid con content-primary), que se separa del gris en TONO y no solo en luminosidad. Tokens de paleta, cero literales. Los tres colores de la onda son publicos y retunables por el disenador. Nota de metodo: la distancia RGB avalo un gris que el ojo rechazo al instante (esa metrica esta dominada por la luminosidad y es ciega al croma), y ademas un bug propio en la alfa del color-mix dio numeros inflados que se corrigieron. Dos recordatorios de que la medicion informa pero no decide. DEMO — material real. El control se llamaba `signal`, que es una de las 8 FAMILIAS del canon, en un componente que declara CERO eventos (expression: 'delegated'): ensenaba lo contrario de la verdad. Renombrado a `sample`. Y el material eran los earcons de sema (pitidos de 80-220 ms, `pop` salia casi plano) porque eran el unico audio del repo; ahora arranca en una pista real de 2:45 (static/music/t2.wav, aportada por el usuario). Y un defecto que 30 MB destaparon: el efecto de carga dependia de `source` Y de `buckets`, asi que mover el slider de buckets volvia a DESCARGAR el fichero entero. Separado en dos: decode una vez por fuente (caro), rebucketing puro y barato. Medido: t2 (5 MB, 86 ms) frente al master de 48 kHz/16 bit (30 MB, 186 ms); sus envolventes NO son identicas — delta maximo 0.298 por cubo, medio 0.048, porque los 8 bits suben el suelo de ruido y aplanan los pasajes suaves. Se elige t2 igualmente: 6x mas ligero por una envolvente marginalmente mas fiel. Verificado: check 75 = baseline, 0 propios; 35 tests; eidos-lint 0 invalidos; recipe-css-contract verde; component:audit --only waveform PASS; docs:check 0; sonda en vivo — 2 paths en la onda, banda recta al 66% en rgb(130,95,161). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
if (EIDOS_ONLY_ATTRS.has(attr)) return true;
if (RUNTIME_SIGNAL_ATTRS.has(attr)) return true;
fix(waveform): el buffered vuelve a ser banda recta, y la demo estrena material real BUFFERED — segunda correccion por MIRADA, y la definitiva. Las dos formas se construyeron y se miraron. Primero fue el SecondaryRange del Slider con un velo neutro al 14%: rechazado ("el secundario no puede ser del mismo color"), y la medicion le dio la razon — velo y onda eran alfas del MISMO token (--color-content-primary al 14% vs 28%), o sea el mismo gris. Se paso entonces a una tercera copia recortada del path, con la idea de que "el buffered ES la onda un escalon mas alla". TAMBIEN rechazado, y por un motivo mas fuerte: "se hace inapreciable y confunde visualmente". La leccion, que queda escrita en los dos README: al compartir silueta con la senal, el ojo lee la banda COMO la senal — es ilegible POR CONSTRUCCION y ningun color la salva. La forma recta es legible precisamente porque NO es la onda. Asi que el buffered vuelve al Slider.SecondaryRange (G-2), la parte canonica que ya existia para esto, en vez de que el waveform pinte lo suyo. El COLOR si sobrevive de la iteracion anterior: acento lavado (color-mix del primary-solid con content-primary), que se separa del gris en TONO y no solo en luminosidad. Tokens de paleta, cero literales. Los tres colores de la onda son publicos y retunables por el disenador. Nota de metodo: la distancia RGB avalo un gris que el ojo rechazo al instante (esa metrica esta dominada por la luminosidad y es ciega al croma), y ademas un bug propio en la alfa del color-mix dio numeros inflados que se corrigieron. Dos recordatorios de que la medicion informa pero no decide. DEMO — material real. El control se llamaba `signal`, que es una de las 8 FAMILIAS del canon, en un componente que declara CERO eventos (expression: 'delegated'): ensenaba lo contrario de la verdad. Renombrado a `sample`. Y el material eran los earcons de sema (pitidos de 80-220 ms, `pop` salia casi plano) porque eran el unico audio del repo; ahora arranca en una pista real de 2:45 (static/music/t2.wav, aportada por el usuario). Y un defecto que 30 MB destaparon: el efecto de carga dependia de `source` Y de `buckets`, asi que mover el slider de buckets volvia a DESCARGAR el fichero entero. Separado en dos: decode una vez por fuente (caro), rebucketing puro y barato. Medido: t2 (5 MB, 86 ms) frente al master de 48 kHz/16 bit (30 MB, 186 ms); sus envolventes NO son identicas — delta maximo 0.298 por cubo, medio 0.048, porque los 8 bits suben el suelo de ruido y aplanan los pasajes suaves. Se elige t2 igualmente: 6x mas ligero por una envolvente marginalmente mas fiel. Verificado: check 75 = baseline, 0 propios; 35 tests; eidos-lint 0 invalidos; recipe-css-contract verde; component:audit --only waveform PASS; docs:check 0; sonda en vivo — 2 paths en la onda, banda recta al 66% en rgb(130,95,161). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
return EIDOS_ONLY_PART_SUFFIXES.some((suffix) => attr.endsWith(`-${suffix}`));
}
eidos: lint a CSS file against its morfo contract Consumes `compileMorfo(morfo).contracts.cssSelectors` to classify every `[data-*]` selector in an eidos CSS file: - morfo-backed: the runtime writes the attr; eidos reacts to it. - eidos-only: the marker is present (`[data-toggle]`) but at least one `data-*` is not declared on the morfo part. Legitimate design tokens (`data-color`, `data-size`, `data-variant`) and drift cases (`data-dialog-header` — a part the morfo no longer declares) both land here; the lint tool reports them so authors can decide. - invalid: the attr IS declared on the morfo, but with a value outside the declared enum. Bug. Also reports `unusedFromContract`: selectors the compiler promises that no eidos rule consumes — the inverse direction of drift. Two CLI entry points: - `scripts/eidos-lint.ts <component>` — single-component report - `scripts/eidos-lint-all.ts` — sweep across every eidos component Initial sweep finds 0 invalid, 134 eidos-only, 82 unused contract selectors across 11 components. Real drift hotspots: dialog/drawer `header`/`footer` (eidos parts the morfos don't declare), popover's `data-side × data-last-action` compounds, tooltip's `data-state='delayed-open'`. Deliberate left as-is for the user to triage — fixes belong in a separate commit. Tests cover toggle (clean baseline), dialog (drift detector for header/footer + dead `data-disabled`), and a synthetic invalid case. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
main().catch((err) => {
fix(waveform): el buffered vuelve a ser banda recta, y la demo estrena material real BUFFERED — segunda correccion por MIRADA, y la definitiva. Las dos formas se construyeron y se miraron. Primero fue el SecondaryRange del Slider con un velo neutro al 14%: rechazado ("el secundario no puede ser del mismo color"), y la medicion le dio la razon — velo y onda eran alfas del MISMO token (--color-content-primary al 14% vs 28%), o sea el mismo gris. Se paso entonces a una tercera copia recortada del path, con la idea de que "el buffered ES la onda un escalon mas alla". TAMBIEN rechazado, y por un motivo mas fuerte: "se hace inapreciable y confunde visualmente". La leccion, que queda escrita en los dos README: al compartir silueta con la senal, el ojo lee la banda COMO la senal — es ilegible POR CONSTRUCCION y ningun color la salva. La forma recta es legible precisamente porque NO es la onda. Asi que el buffered vuelve al Slider.SecondaryRange (G-2), la parte canonica que ya existia para esto, en vez de que el waveform pinte lo suyo. El COLOR si sobrevive de la iteracion anterior: acento lavado (color-mix del primary-solid con content-primary), que se separa del gris en TONO y no solo en luminosidad. Tokens de paleta, cero literales. Los tres colores de la onda son publicos y retunables por el disenador. Nota de metodo: la distancia RGB avalo un gris que el ojo rechazo al instante (esa metrica esta dominada por la luminosidad y es ciega al croma), y ademas un bug propio en la alfa del color-mix dio numeros inflados que se corrigieron. Dos recordatorios de que la medicion informa pero no decide. DEMO — material real. El control se llamaba `signal`, que es una de las 8 FAMILIAS del canon, en un componente que declara CERO eventos (expression: 'delegated'): ensenaba lo contrario de la verdad. Renombrado a `sample`. Y el material eran los earcons de sema (pitidos de 80-220 ms, `pop` salia casi plano) porque eran el unico audio del repo; ahora arranca en una pista real de 2:45 (static/music/t2.wav, aportada por el usuario). Y un defecto que 30 MB destaparon: el efecto de carga dependia de `source` Y de `buckets`, asi que mover el slider de buckets volvia a DESCARGAR el fichero entero. Separado en dos: decode una vez por fuente (caro), rebucketing puro y barato. Medido: t2 (5 MB, 86 ms) frente al master de 48 kHz/16 bit (30 MB, 186 ms); sus envolventes NO son identicas — delta maximo 0.298 por cubo, medio 0.048, porque los 8 bits suben el suelo de ruido y aplanan los pasajes suaves. Se elige t2 igualmente: 6x mas ligero por una envolvente marginalmente mas fiel. Verificado: check 75 = baseline, 0 propios; 35 tests; eidos-lint 0 invalidos; recipe-css-contract verde; component:audit --only waveform PASS; docs:check 0; sonda en vivo — 2 paths en la onda, banda recta al 66% en rgb(130,95,161). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2 months ago
console.error(err);
process.exit(2);
});

Powered by TurnKey Linux.