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/src/uix/sema/exports.ts

130 lines
3.3 KiB

export type {
SemaValencedFamily,
SemaTransitionalFamily,
SemaFamily,
IntentPolicy,
sema/morfo/eidos: typed selector builder + dialog wrapper + emerge color sema architecture - sema-map: 5-channel registry (motion / sound / color / presence / haptic) via SemaChannelSignatures declaration merging; engine stamps data-event-* tokens; flat CSS-style cascade replaces the eventLabel-overrides middle layer. - sema-map: emerge family gains base.color so intent deltas can shift hue / saturation / intensity. Without a base, the resolver was skipping the channel and Dialog open with intent='threat' rendered as neutral blue in the Sema tab visualisation. - types: SEMA_FAMILY_POLICY const drives compile-time + runtime intent requirements per family. Object shape so future per-family policy fields fit alongside. Emerge events MAY now declare intent (canon update — a Dialog confirming threat carries it in its very appearance). - chans: rename vibra→haptic, add HapticChannel V1 (Vibration API); SoundChannel eager-init on first user gesture (autoplay race fix). morfo selector discipline - morfo/selectors.ts (new): semaSelector(morfo, partKebab, matchers?) — type-checked against morfo.parts and morfo.events. Sema cascade rules MUST use it; hand-written strings are an architecture violation that breaks silently when morfo renames a part. - dialog morfo: open carries intent via fromProp; close-cancel / close-dismiss / close-dismiss-outside drop intent (cancellation has no evaluative load); close-save stays hardcoded fulfill (commit fulfils the user's decision regardless of dialog context). eidos dialog migration (4th pilot) - eidos/components/dialog/: full subdirectory wrapper — flat <Dialog> + compound Provider/Trigger/Overlay/Content/Title/Description/Close/Header/ Footer; size + position responsive props; sheet auto-form on narrow viewports; closePosition for the auto-X. - sema/components/dialog.ts: cascade rules use semaSelector(dialogMorfo, 'content', matchers?). Intent block adds character (haptic kind / pattern) but never overrides pitch / gain / contour — those are intent.deltas signature ownership and overriding flattens per-intent perceptual difference. demo controls + dialog page - src/lib/_demo (DemoSwitch / DemoEnum / DemoText / DemoRange) — unified controls reused across all component demos. - web/routes/dialog: live preview always rendered above tabs; per-event Sema tab with independent intent probe; signature visualisation + Play buttons with fallback target chain. documentation - CLAUDE.md: intent.deltas signature ownership rule; eidos drift defense doctrine (types over lint); 2026-05-09 hand-off entry. - morfo/README: Typed selector builder section. - eidos/README: linter section reframed as opt-in safety net for plain CSS recipes; the architectural mechanism is compile-time typing. - sema/README: open channel registry + flat cascade docs + override semantics + intent policy const + selector builder discipline. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
IntentExpectedFamily,
IntentOptionalFamily,
SemaMode,
SemaRegime,
SemaScope,
SemaCause,
SemaEventKey,
SemaEventLabel,
IntentBinding,
SemaEvent,
sema/morfo/eidos: typed selector builder + dialog wrapper + emerge color sema architecture - sema-map: 5-channel registry (motion / sound / color / presence / haptic) via SemaChannelSignatures declaration merging; engine stamps data-event-* tokens; flat CSS-style cascade replaces the eventLabel-overrides middle layer. - sema-map: emerge family gains base.color so intent deltas can shift hue / saturation / intensity. Without a base, the resolver was skipping the channel and Dialog open with intent='threat' rendered as neutral blue in the Sema tab visualisation. - types: SEMA_FAMILY_POLICY const drives compile-time + runtime intent requirements per family. Object shape so future per-family policy fields fit alongside. Emerge events MAY now declare intent (canon update — a Dialog confirming threat carries it in its very appearance). - chans: rename vibra→haptic, add HapticChannel V1 (Vibration API); SoundChannel eager-init on first user gesture (autoplay race fix). morfo selector discipline - morfo/selectors.ts (new): semaSelector(morfo, partKebab, matchers?) — type-checked against morfo.parts and morfo.events. Sema cascade rules MUST use it; hand-written strings are an architecture violation that breaks silently when morfo renames a part. - dialog morfo: open carries intent via fromProp; close-cancel / close-dismiss / close-dismiss-outside drop intent (cancellation has no evaluative load); close-save stays hardcoded fulfill (commit fulfils the user's decision regardless of dialog context). eidos dialog migration (4th pilot) - eidos/components/dialog/: full subdirectory wrapper — flat <Dialog> + compound Provider/Trigger/Overlay/Content/Title/Description/Close/Header/ Footer; size + position responsive props; sheet auto-form on narrow viewports; closePosition for the auto-X. - sema/components/dialog.ts: cascade rules use semaSelector(dialogMorfo, 'content', matchers?). Intent block adds character (haptic kind / pattern) but never overrides pitch / gain / contour — those are intent.deltas signature ownership and overriding flattens per-intent perceptual difference. demo controls + dialog page - src/lib/_demo (DemoSwitch / DemoEnum / DemoText / DemoRange) — unified controls reused across all component demos. - web/routes/dialog: live preview always rendered above tabs; per-event Sema tab with independent intent probe; signature visualisation + Play buttons with fallback target chain. documentation - CLAUDE.md: intent.deltas signature ownership rule; eidos drift defense doctrine (types over lint); 2026-05-09 hand-off entry. - morfo/README: Typed selector builder section. - eidos/README: linter section reframed as opt-in safety net for plain CSS recipes; the architectural mechanism is compile-time typing. - sema/README: open channel registry + flat cascade docs + override semantics + intent policy const + selector builder discipline. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
SemaEventExtensions,
SemaActionEvent,
SemaAttrWrite,
feat(uix): persistence + a11ySemantic + polymorphic core (book §5.3, §6, §9) Three book canon items codified in code: **Persistence (libro §6.1)** — separa `hold` (perceptual min) de `persistence` (lifecycle real): - New `SignalPersistence = 'transient' | 'untilAction' | 'untilFix' | 'stateBound'` - New `SEMA_HOLDS_BY_INTENT` canonical lookup table (`src/uix/sema/holds.ts`) - `EngineSemantic.emit()` returns the resolved signal id; keeps projection alive past hold for non-transient. Exposes `clear(id)`, `clearTarget(target)`, `hasActive(id)`. - `SomaRuntime.trigger()` returns `TriggerResult { id?, persistence? }`. Exposes `clearSignal(id)`, `clearTarget(target)`, `partRef(part)`. **a11ySemantic (libro §9.1)**: - New `MorfoA11ySemantic` (requiresPersistentTrace, requiresLiveRegion, requiresFocusMove, keyboardEquivalent, reducedMotionFallback) on MorfoEvent. - `ActiveDom.prefersReducedMotion`: reactive tracker via media query (`src/arts/adom/reduced-motion.svelte.ts`). - `ActiveUix.announce(msg, priority?, timeout?)`: lazy-created live region via `dom.writeNode`. - `Soma.runtime()` auto-wires `sources.announce`. - `SomaRuntime.trigger()` honors a11ySemantic after emit (live region, focus, reduced-motion fallback including `channels: []` for 'state'). **Polymorphic events (libro §5.3)** — ADITIVO sobre shape concreto: - `allowedFamilies?: readonly SemaFamily[]` opcional en MorfoEventSemantic. - Provider override via `runtime.trigger(name, { semantic })`. - Default family of the morfo is implicitly allowed. - New `SomaRuntimePolymorphicError`. - New `isPolymorphicSemantic` type guard. Synthetic `prewriteFixtureMorfo` (src/uix/morfo/test-fixtures.ts) decouples compile + runtime tests from the production morfo catalogue. 671 tests pass in sema + morfo + soma + adom scopes. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
SemaCommit,
SignalPersistence
} from './types';
feat(uix): persistence + a11ySemantic + polymorphic core (book §5.3, §6, §9) Three book canon items codified in code: **Persistence (libro §6.1)** — separa `hold` (perceptual min) de `persistence` (lifecycle real): - New `SignalPersistence = 'transient' | 'untilAction' | 'untilFix' | 'stateBound'` - New `SEMA_HOLDS_BY_INTENT` canonical lookup table (`src/uix/sema/holds.ts`) - `EngineSemantic.emit()` returns the resolved signal id; keeps projection alive past hold for non-transient. Exposes `clear(id)`, `clearTarget(target)`, `hasActive(id)`. - `SomaRuntime.trigger()` returns `TriggerResult { id?, persistence? }`. Exposes `clearSignal(id)`, `clearTarget(target)`, `partRef(part)`. **a11ySemantic (libro §9.1)**: - New `MorfoA11ySemantic` (requiresPersistentTrace, requiresLiveRegion, requiresFocusMove, keyboardEquivalent, reducedMotionFallback) on MorfoEvent. - `ActiveDom.prefersReducedMotion`: reactive tracker via media query (`src/arts/adom/reduced-motion.svelte.ts`). - `ActiveUix.announce(msg, priority?, timeout?)`: lazy-created live region via `dom.writeNode`. - `Soma.runtime()` auto-wires `sources.announce`. - `SomaRuntime.trigger()` honors a11ySemantic after emit (live region, focus, reduced-motion fallback including `channels: []` for 'state'). **Polymorphic events (libro §5.3)** — ADITIVO sobre shape concreto: - `allowedFamilies?: readonly SemaFamily[]` opcional en MorfoEventSemantic. - Provider override via `runtime.trigger(name, { semantic })`. - Default family of the morfo is implicitly allowed. - New `SomaRuntimePolymorphicError`. - New `isPolymorphicSemantic` type guard. Synthetic `prewriteFixtureMorfo` (src/uix/morfo/test-fixtures.ts) decouples compile + runtime tests from the production morfo catalogue. 671 tests pass in sema + morfo + soma + adom scopes. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
export {
SEMA_HOLDS_BY_INTENT,
resolveHoldsByIntent,
type HoldsPolicy
} from './holds';
export { SEMA_FAMILY_POLICY } from './types';
sema/morfo/eidos: typed selector builder + dialog wrapper + emerge color sema architecture - sema-map: 5-channel registry (motion / sound / color / presence / haptic) via SemaChannelSignatures declaration merging; engine stamps data-event-* tokens; flat CSS-style cascade replaces the eventLabel-overrides middle layer. - sema-map: emerge family gains base.color so intent deltas can shift hue / saturation / intensity. Without a base, the resolver was skipping the channel and Dialog open with intent='threat' rendered as neutral blue in the Sema tab visualisation. - types: SEMA_FAMILY_POLICY const drives compile-time + runtime intent requirements per family. Object shape so future per-family policy fields fit alongside. Emerge events MAY now declare intent (canon update — a Dialog confirming threat carries it in its very appearance). - chans: rename vibra→haptic, add HapticChannel V1 (Vibration API); SoundChannel eager-init on first user gesture (autoplay race fix). morfo selector discipline - morfo/selectors.ts (new): semaSelector(morfo, partKebab, matchers?) — type-checked against morfo.parts and morfo.events. Sema cascade rules MUST use it; hand-written strings are an architecture violation that breaks silently when morfo renames a part. - dialog morfo: open carries intent via fromProp; close-cancel / close-dismiss / close-dismiss-outside drop intent (cancellation has no evaluative load); close-save stays hardcoded fulfill (commit fulfils the user's decision regardless of dialog context). eidos dialog migration (4th pilot) - eidos/components/dialog/: full subdirectory wrapper — flat <Dialog> + compound Provider/Trigger/Overlay/Content/Title/Description/Close/Header/ Footer; size + position responsive props; sheet auto-form on narrow viewports; closePosition for the auto-X. - sema/components/dialog.ts: cascade rules use semaSelector(dialogMorfo, 'content', matchers?). Intent block adds character (haptic kind / pattern) but never overrides pitch / gain / contour — those are intent.deltas signature ownership and overriding flattens per-intent perceptual difference. demo controls + dialog page - src/lib/_demo (DemoSwitch / DemoEnum / DemoText / DemoRange) — unified controls reused across all component demos. - web/routes/dialog: live preview always rendered above tabs; per-event Sema tab with independent intent probe; signature visualisation + Play buttons with fallback target chain. documentation - CLAUDE.md: intent.deltas signature ownership rule; eidos drift defense doctrine (types over lint); 2026-05-09 hand-off entry. - morfo/README: Typed selector builder section. - eidos/README: linter section reframed as opt-in safety net for plain CSS recipes; the architectural mechanism is compile-time typing. - sema/README: open channel registry + flat cascade docs + override semantics + intent policy const + selector builder discipline. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
export {
SEMA_VALENCED_FAMILIES,
SEMA_TRANSITIONAL_FAMILIES,
SEMA_FAMILIES,
SEMA_EVENT_LABELS,
isSemaFamily,
isSemaValencedFamily,
isSemaTransitionalFamily,
isIntent,
isSemaEventLabel,
isIntentBinding,
isSemaEvent,
parseSemaEventLabel,
resolveIntent,
normalizeSemaEvent,
toSemaEventLabel
} from './event';
export type { EngineSemanticOptions, EngineSemanticOverrides } from './engine';
export { EngineSemantic } from './engine';
export { defineEngineSemantic } from './define-engine-semantic';
export type { SemanticSignal } from './signal';
// ── Perceptual duration scale ──────────────────────────────────────────────
export {
SEMA_DURATIONS,
resolveSemaDuration,
type SemaDurationLabel,
type SemaDurationSpec
} from './durations';
sema: refactor into channel modules — engine becomes registry + dispatch Reorganización estructural según el spec acordado: cada canal perceptivo vive como módulo simétrico dentro de `chans/`. El engine queda mínimo (registry + dispatch); la lógica de escribir `data-event*` al DOM, mantener hold y retirar pasa al `VisualChannel`. La API pública que ven los providers (`semantic.emit(signal)`) se mantiene idéntica. Estructura nueva src/uix/sema/ ├── engine.ts registry + dispatch (ya no conoce DOM ni hold) ├── signal.ts SemanticSignal + nuevo campo opcional `id?` ├── exports.ts barrel actualizado (chans + drop publish + drop perception) └── chans/ ├── types.ts interfaz Channel { id, handle, dispose? } ├── visual.ts VisualChannel — escribe data-event*, hold, cleanup ├── visual.test.ts 9 tests del canal aislado ├── sound.ts SoundChannel placeholder (V1 no-op) └── vibra.ts VibraChannel placeholder (V1 no-op) Cambios al engine - Constructor: `new SemanticEngine(opts?)`. `opts.visual` controla el built-in (false / VisualChannelOptions / Channel custom). `opts.dom` desaparece — ya no es responsabilidad del engine. - Métodos: `register(channel)`, `getChannel(id)`, `emit(signal)`, `destroy()`. Nada más. - emit despacha a TODOS los canales registrados: - Canales no-visuales (sound, vibra, futuros): fire-and-forget. Errores se loguean pero no propagan (Sema es ornamental). - Canal visual: el único cuya Promise se awaitea — comparte plano DOM con el commit estructural posterior. - emit genera el `id` de la ocurrencia y lo pasa a todos los canales, garantizando coherencia cross-canal para tooling futuro. Cambios al VisualChannel (lógica heredada del emit() anterior) - 5 atributos: `data-event` + `data-event-id` + `data-event-phase` (siempre) + `data-event-family` y `data-intent` (opcionales si vienen en el signal). Los opcionales son la proyección al DOM de la metadata semántica que Eidos consume. - Hold defaults internos por familia (no exportados): emerge/commit/handle: 240ms · alert/sustain: 600ms · contact: 120ms Justificación técnica (rangos típicos de CSS transitions), no escala perceptiva universal. Override per signal vía `signal.hold` o global vía `new SemanticEngine({ visual: { defaultHold } })`. - Semántica secuencial estricta: cleanup ANTES del resolve. Eliminado - `src/uix/sema/perception.ts` — escalas perceptivas no son concepto cross-canal. La tabla de defaults por familia se movió al VisualChannel como detalle interno con justificación técnica. - `engine.publish()` y todo el sistema legacy: - `SemanticEventDecl`, `SemanticComponentContract`, `SemanticPublishContext`, `PublishedSemanticEvent`, `SemanticEventFilter` - `onEvent()` y subscribers - `applyPrewrites()` interno - dependencia opcional de `ActiveDom` por construcción - Tests de `publish()` reemplazados por tests del nuevo registry/dispatch. Bootstrap (App + defaults) - `src/lib/ext/app/app.svelte.ts:52` — `new SemanticEngine({ dom: this.dom })` → `new SemanticEngine()` - `src/lib/ext/app/defaults.ts:45` — mismo cambio Tests - emit.test.ts ajustado: sin createActiveDom, sin SEMA_PERCEPTION/HOLD_DEFAULTS, test "throws without dom" eliminado, números literales (240, 600). Añadido test "resolves immediately when visual: false". 7 tests. - engine.test.ts reescrito: register / getChannel / emit dispatch a múltiples canales / id propagation / id override / fire-and-forget para non-visual / error en canal no aborta dispatch / visual: false desactiva built-in / custom Channel reemplaza built-in / destroy. 13 tests. - chans/visual.test.ts nuevo: 5 attrs vs 3 / signal.hold respetado / family default fallback / global default fallback / constructor defaultHold / cleanup / sequential strict (resolve tras cleanup) / id field. 9 tests. - 39 tests sema verdes en total. Documentación - src/uix/sema/README.md — reescrito alrededor del modelo de canales - src/uix/eidos/events.css — comentario actualizado, referencia a chans/visual.ts - src/uix/active_architecture.md — sección Sema reescrita Componentes NO requieren cambios — la API `semantic.emit(signal)` es idéntica externamente. Toast / runtime.trigger / providers funcionan igual. Verificación - 121/121 tests focused suite (sema 39 + adom + lib/dom + morfo + soma/morfo) - 66/66 morfo-check - 68/68 smoke routes - svelte-check: 155 errors (baseline, sin nuevos) Pendientes en doc del spec marcados como "no-objetivos": - Implementación real de SoundChannel / VibraChannel (placeholders V1) - Arbitraje propio del VisualChannel (deuda heredada del emit anterior) - Cancelación si el target se desconecta durante el hold
6 months ago
// ── Channels ───────────────────────────────────────────────────────────────
export type { Channel } from './chans/types';
export { VisualChannel, type VisualChannelOptions } from './chans/visual';
export { SoundChannel, type SoundChannelOptions } from './chans/sound';
export { HapticChannel, type HapticChannelOptions } from './chans/haptic';
sema: perceptually-anchored hold + sequential strict emit semantics Two architectural fixes surfaced by the eidos demo: 1. The previous default hold (1 rAF + 1 hold frame, ~30ms) was a technical timing decision — invisible to humans. Signals must be anchored to perceptual scales so they can actually be perceived. 2. The previous lifecycle resolved emit AFTER 1 rAF (caller's structural change ran in parallel with cleanup, ~30ms later). That's an implicit parallelism between event and state. The author has no way to say "wait for the announcement to be perceived before changing state". Sequential strict semantics (NEW) - emit writes the signal, awaits the full author-specified hold, cleans up, then resolves. State change happens AFTER cleanup — strictly sequential. - `signal.hold` is in milliseconds anchored to `SEMA_PERCEPTION` scales: subliminal 50ms below conscious threshold glimpse 120ms minimum perceptible without effort brief 240ms comfortable acknowledgement noticed 600ms sustained signal insistent 1200ms demands attention persistent 3000ms until acknowledged - Defaults per family in `SEMA_HOLD_DEFAULTS`: emerge: brief sustain: noticed contact: glimpse commit: brief alert: noticed handle: brief - Authors override per event via `SemanticSignal.hold` based on: - their CSS animation duration (so it completes before cleanup) - the perceptual scale they want - critical attention requirements (use insistent/persistent) Files - src/uix/sema/perception.ts (new) — SEMA_PERCEPTION + SEMA_HOLD_DEFAULTS + SEMA_OBSERVE_FRAME_MS constants with rationale anchored on Bloch's law, Material/Apple HIG motion guidelines, toast UX literature. - src/uix/sema/signal.ts — `hold` JSDoc updated to explain ms semantics + defaults + override pattern. - src/uix/sema/engine.ts — emit() refactored from rAF chain to setTimeout(holdMs); cleanup happens BEFORE resolve (sequential strict); `nextFrame()` helper removed; `resolveHoldMs(signal)` added with the 3-tier fallback (signal.hold → family default → SEMA_PERCEPTION.brief). - src/uix/sema/exports.ts — re-exports SEMA_PERCEPTION + SEMA_HOLD_DEFAULTS + SEMA_OBSERVE_FRAME_MS + SemaPerception type. - src/uix/sema/emit.test.ts — rewritten around fakeTimers + setTimeout (no more rAF queue); new test verifies cleanup runs BEFORE resolve. 7/7 tests green. - src/uix/sema/README.md — new "Duración del signal" section with the full perception scale + per-family defaults tables + override pattern. - src/uix/eidos/events.css — comment updated to explain the new hold windows; rule `[data-event^='dismiss']` etc. clarified. - src/uix/active_architecture.md — replaced "~13ms" prose with explicit perception-anchored scales; added explanation of "perceptual by design, not framerate". - src/uix/soma/components/toast/toast-provider.svelte.ts — new $effect that fires `present` + `announce` events when item ref attaches (one-shot guarded), so toasts emit signals on appear. The flash on /test/eidos is now visible thanks to (a) the perceptual hold and (b) the wired events. Channel parallelism note - Hold is the DOM channel duration only. - Future sound / vibra / motion engines subscribe to sema events independently; each owns its own timing relative to the event id. - Sema does not coordinate cross-channel sync — that's an integrator decision per app. Verification - 22/22 sema tests green. - 22/22 morfo runtime tests green. - 66/66 morfo-check + 68/68 smoke (verified before commit). - Probe shows announce signal on toast appear lasting ~600ms (alert family default) — visible in DevTools attribute panel. - svelte-check unchanged at 155. Pre-existing failure in src/uix/air/internal/canvas/layout.test.ts (`bun:test` import) is in the dead-branch air layer and unrelated.
6 months ago
sema: revive resolver + signatures + real SoundChannel Restores the resolver-driven architecture that was deleted in the channel-modules refactor (commit a0a1485b). Each signal now flows through a single resolution that produces an `EffectiveSignature`, and each channel reads its own slice — so the visual hold, the sound earcon, and (future) motion / color / presence channels all share a single family-level perceptual budget defined in `SEMA_MAP`. New surfaces: - `src/uix/sema/sema-map.ts` — typed perceptual map (port of the legacy `sema-map.json`) with per-family `base` (motion / sound / color / presence) + `activeChannels` and per-intent `deltas` using the number / `{op:'add'}` / `{op:'multiply'}` / `{op:'replace'}` / recursive-merge semantics from before. - `src/uix/sema/resolver.ts` — pure `resolveSignature(signal)` that returns an `EffectiveSignature`. Empty signature when family is missing so channels skip rather than throw. Intent deltas only apply to valenced families. Optional `soundPack` per-event sample URLs. - `src/uix/sema/chans/sound.ts` — real `SoundChannel` (~290 lines, ported from a0a1485b^). Single AudioContext + master GainNode, auto-unlock for Safari/iOS via `click` / `touchstart` / `keydown` with capture, ADSR-lite synthesis (sine + 5th → biquad lowpass → envelope, AM modulator when roughness > 0.2), contour via `osc.detune`, optional sample playback with `AudioBuffer` cache. Errors absorbed silently — sema is ornamental. Architectural changes: - `Channel.handle(signal, effective)` — every channel now receives the resolved signature alongside the signal. Channels can ignore it. - `EngineSemantic.emit` resolves once per emit, dispatches both args. - `VisualChannel` hold resolution chain is now (highest priority first): 1. `signal.hold` 2. `effective.motion.duration` ← NEW: from sema-map 3. family fallback table (SEMA_DURATIONS) 4. engine `defaultHold` Behavior change: families with motion in the map (alert: 220ms, contact: 80ms, commit: 180ms, …) now use those values instead of the previous label-based 600ms / 120ms / 240ms fallbacks. The fallback table remains as a safety net for families without motion (sustain). - `EngineSemanticOptions` adds `sound?: true | false | SoundChannelOptions | Channel`. Sound is opt-in (audible side effects). Layouts wire `defineEngineSemantic({ sound: true })`. Tests: - New `resolver.test.ts` (7 tests) — locks down family base, intent deltas, multiplicative ops, transitional-family no-op, deep-clone. - `visual.test.ts` — every `handle` call now passes a stub `EffectiveSignature`. Two new tests: motion.duration takes the hold, and signal.hold overrides effective.motion.duration. - `engine.test.ts` — `makeChannel` mock signature updated. - `emit.test.ts` — alert family default test now expects 220ms (from sema-map) instead of 600ms. Verified: - vitest: 6 files / 53 tests green - smoke: 68/68 soma routes 200 OK - morfo-check: 66/66 morfos validate
5 months ago
// ── Resolver + perceptual map ─────────────────────────────────────────────
export {
resolveSignature,
sema/morfo/eidos: typed selector builder + dialog wrapper + emerge color sema architecture - sema-map: 5-channel registry (motion / sound / color / presence / haptic) via SemaChannelSignatures declaration merging; engine stamps data-event-* tokens; flat CSS-style cascade replaces the eventLabel-overrides middle layer. - sema-map: emerge family gains base.color so intent deltas can shift hue / saturation / intensity. Without a base, the resolver was skipping the channel and Dialog open with intent='threat' rendered as neutral blue in the Sema tab visualisation. - types: SEMA_FAMILY_POLICY const drives compile-time + runtime intent requirements per family. Object shape so future per-family policy fields fit alongside. Emerge events MAY now declare intent (canon update — a Dialog confirming threat carries it in its very appearance). - chans: rename vibra→haptic, add HapticChannel V1 (Vibration API); SoundChannel eager-init on first user gesture (autoplay race fix). morfo selector discipline - morfo/selectors.ts (new): semaSelector(morfo, partKebab, matchers?) — type-checked against morfo.parts and morfo.events. Sema cascade rules MUST use it; hand-written strings are an architecture violation that breaks silently when morfo renames a part. - dialog morfo: open carries intent via fromProp; close-cancel / close-dismiss / close-dismiss-outside drop intent (cancellation has no evaluative load); close-save stays hardcoded fulfill (commit fulfils the user's decision regardless of dialog context). eidos dialog migration (4th pilot) - eidos/components/dialog/: full subdirectory wrapper — flat <Dialog> + compound Provider/Trigger/Overlay/Content/Title/Description/Close/Header/ Footer; size + position responsive props; sheet auto-form on narrow viewports; closePosition for the auto-X. - sema/components/dialog.ts: cascade rules use semaSelector(dialogMorfo, 'content', matchers?). Intent block adds character (haptic kind / pattern) but never overrides pitch / gain / contour — those are intent.deltas signature ownership and overriding flattens per-intent perceptual difference. demo controls + dialog page - src/lib/_demo (DemoSwitch / DemoEnum / DemoText / DemoRange) — unified controls reused across all component demos. - web/routes/dialog: live preview always rendered above tabs; per-event Sema tab with independent intent probe; signature visualisation + Play buttons with fallback target chain. documentation - CLAUDE.md: intent.deltas signature ownership rule; eidos drift defense doctrine (types over lint); 2026-05-09 hand-off entry. - morfo/README: Typed selector builder section. - eidos/README: linter section reframed as opt-in safety net for plain CSS recipes; the architectural mechanism is compile-time typing. - sema/README: open channel registry + flat cascade docs + override semantics + intent policy const + selector builder discipline. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
applyMapOverrides,
sema: revive resolver + signatures + real SoundChannel Restores the resolver-driven architecture that was deleted in the channel-modules refactor (commit a0a1485b). Each signal now flows through a single resolution that produces an `EffectiveSignature`, and each channel reads its own slice — so the visual hold, the sound earcon, and (future) motion / color / presence channels all share a single family-level perceptual budget defined in `SEMA_MAP`. New surfaces: - `src/uix/sema/sema-map.ts` — typed perceptual map (port of the legacy `sema-map.json`) with per-family `base` (motion / sound / color / presence) + `activeChannels` and per-intent `deltas` using the number / `{op:'add'}` / `{op:'multiply'}` / `{op:'replace'}` / recursive-merge semantics from before. - `src/uix/sema/resolver.ts` — pure `resolveSignature(signal)` that returns an `EffectiveSignature`. Empty signature when family is missing so channels skip rather than throw. Intent deltas only apply to valenced families. Optional `soundPack` per-event sample URLs. - `src/uix/sema/chans/sound.ts` — real `SoundChannel` (~290 lines, ported from a0a1485b^). Single AudioContext + master GainNode, auto-unlock for Safari/iOS via `click` / `touchstart` / `keydown` with capture, ADSR-lite synthesis (sine + 5th → biquad lowpass → envelope, AM modulator when roughness > 0.2), contour via `osc.detune`, optional sample playback with `AudioBuffer` cache. Errors absorbed silently — sema is ornamental. Architectural changes: - `Channel.handle(signal, effective)` — every channel now receives the resolved signature alongside the signal. Channels can ignore it. - `EngineSemantic.emit` resolves once per emit, dispatches both args. - `VisualChannel` hold resolution chain is now (highest priority first): 1. `signal.hold` 2. `effective.motion.duration` ← NEW: from sema-map 3. family fallback table (SEMA_DURATIONS) 4. engine `defaultHold` Behavior change: families with motion in the map (alert: 220ms, contact: 80ms, commit: 180ms, …) now use those values instead of the previous label-based 600ms / 120ms / 240ms fallbacks. The fallback table remains as a safety net for families without motion (sustain). - `EngineSemanticOptions` adds `sound?: true | false | SoundChannelOptions | Channel`. Sound is opt-in (audible side effects). Layouts wire `defineEngineSemantic({ sound: true })`. Tests: - New `resolver.test.ts` (7 tests) — locks down family base, intent deltas, multiplicative ops, transitional-family no-op, deep-clone. - `visual.test.ts` — every `handle` call now passes a stub `EffectiveSignature`. Two new tests: motion.duration takes the hold, and signal.hold overrides effective.motion.duration. - `engine.test.ts` — `makeChannel` mock signature updated. - `emit.test.ts` — alert family default test now expects 220ms (from sema-map) instead of 600ms. Verified: - vitest: 6 files / 53 tests green - smoke: 68/68 soma routes 200 OK - morfo-check: 66/66 morfos validate
5 months ago
type EffectiveSignature,
sema/morfo/eidos: typed selector builder + dialog wrapper + emerge color sema architecture - sema-map: 5-channel registry (motion / sound / color / presence / haptic) via SemaChannelSignatures declaration merging; engine stamps data-event-* tokens; flat CSS-style cascade replaces the eventLabel-overrides middle layer. - sema-map: emerge family gains base.color so intent deltas can shift hue / saturation / intensity. Without a base, the resolver was skipping the channel and Dialog open with intent='threat' rendered as neutral blue in the Sema tab visualisation. - types: SEMA_FAMILY_POLICY const drives compile-time + runtime intent requirements per family. Object shape so future per-family policy fields fit alongside. Emerge events MAY now declare intent (canon update — a Dialog confirming threat carries it in its very appearance). - chans: rename vibra→haptic, add HapticChannel V1 (Vibration API); SoundChannel eager-init on first user gesture (autoplay race fix). morfo selector discipline - morfo/selectors.ts (new): semaSelector(morfo, partKebab, matchers?) — type-checked against morfo.parts and morfo.events. Sema cascade rules MUST use it; hand-written strings are an architecture violation that breaks silently when morfo renames a part. - dialog morfo: open carries intent via fromProp; close-cancel / close-dismiss / close-dismiss-outside drop intent (cancellation has no evaluative load); close-save stays hardcoded fulfill (commit fulfils the user's decision regardless of dialog context). eidos dialog migration (4th pilot) - eidos/components/dialog/: full subdirectory wrapper — flat <Dialog> + compound Provider/Trigger/Overlay/Content/Title/Description/Close/Header/ Footer; size + position responsive props; sheet auto-form on narrow viewports; closePosition for the auto-X. - sema/components/dialog.ts: cascade rules use semaSelector(dialogMorfo, 'content', matchers?). Intent block adds character (haptic kind / pattern) but never overrides pitch / gain / contour — those are intent.deltas signature ownership and overriding flattens per-intent perceptual difference. demo controls + dialog page - src/lib/_demo (DemoSwitch / DemoEnum / DemoText / DemoRange) — unified controls reused across all component demos. - web/routes/dialog: live preview always rendered above tabs; per-event Sema tab with independent intent probe; signature visualisation + Play buttons with fallback target chain. documentation - CLAUDE.md: intent.deltas signature ownership rule; eidos drift defense doctrine (types over lint); 2026-05-09 hand-off entry. - morfo/README: Typed selector builder section. - eidos/README: linter section reframed as opt-in safety net for plain CSS recipes; the architectural mechanism is compile-time typing. - sema/README: open channel registry + flat cascade docs + override semantics + intent policy const + selector builder discipline. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
type SemaCascadeRule,
type SemaResolveOptions
} from './resolver';
export type {
HapticSignature,
SemaChannelId,
SemaChannelSignatures,
SemaSignatureOverride,
SemaRuntimeChannelId,
SoundSignature
} from './channels';
sema/morfo/eidos: typed selector builder + dialog wrapper + emerge color sema architecture - sema-map: 5-channel registry (motion / sound / color / presence / haptic) via SemaChannelSignatures declaration merging; engine stamps data-event-* tokens; flat CSS-style cascade replaces the eventLabel-overrides middle layer. - sema-map: emerge family gains base.color so intent deltas can shift hue / saturation / intensity. Without a base, the resolver was skipping the channel and Dialog open with intent='threat' rendered as neutral blue in the Sema tab visualisation. - types: SEMA_FAMILY_POLICY const drives compile-time + runtime intent requirements per family. Object shape so future per-family policy fields fit alongside. Emerge events MAY now declare intent (canon update — a Dialog confirming threat carries it in its very appearance). - chans: rename vibra→haptic, add HapticChannel V1 (Vibration API); SoundChannel eager-init on first user gesture (autoplay race fix). morfo selector discipline - morfo/selectors.ts (new): semaSelector(morfo, partKebab, matchers?) — type-checked against morfo.parts and morfo.events. Sema cascade rules MUST use it; hand-written strings are an architecture violation that breaks silently when morfo renames a part. - dialog morfo: open carries intent via fromProp; close-cancel / close-dismiss / close-dismiss-outside drop intent (cancellation has no evaluative load); close-save stays hardcoded fulfill (commit fulfils the user's decision regardless of dialog context). eidos dialog migration (4th pilot) - eidos/components/dialog/: full subdirectory wrapper — flat <Dialog> + compound Provider/Trigger/Overlay/Content/Title/Description/Close/Header/ Footer; size + position responsive props; sheet auto-form on narrow viewports; closePosition for the auto-X. - sema/components/dialog.ts: cascade rules use semaSelector(dialogMorfo, 'content', matchers?). Intent block adds character (haptic kind / pattern) but never overrides pitch / gain / contour — those are intent.deltas signature ownership and overriding flattens per-intent perceptual difference. demo controls + dialog page - src/lib/_demo (DemoSwitch / DemoEnum / DemoText / DemoRange) — unified controls reused across all component demos. - web/routes/dialog: live preview always rendered above tabs; per-event Sema tab with independent intent probe; signature visualisation + Play buttons with fallback target chain. documentation - CLAUDE.md: intent.deltas signature ownership rule; eidos drift defense doctrine (types over lint); 2026-05-09 hand-off entry. - morfo/README: Typed selector builder section. - eidos/README: linter section reframed as opt-in safety net for plain CSS recipes; the architectural mechanism is compile-time typing. - sema/README: open channel registry + flat cascade docs + override semantics + intent policy const + selector builder discipline. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
export {
SEMA_MAP,
type SemaMap,
type FamilyMapEntry,
type IntentMapEntry,
type Sema
} from './sema-map';
export {
SOUND_LIBRARY,
SOUND_TUNINGS,
sample,
sound,
soundSampleUrls,
soundTuning,
resolveSoundDefinition,
resolveHandleDragSound,
resolveSliderDragSound,
feat(splitter): sema + dynamic drag-signal sound infrastructure Splitter previously had no sema bindings — handle-pick / handle-drag / commit-set fired silently. Closes the asymmetry with Slider and Drawer. Sema (src/uix/sema/components/splitter.ts): - handle-pick → sound('handle.pickup.air', gain 0.10) + tick haptic - handle-drag → channels: ['sound', 'haptic'] (channels-only; per-emit signal.overrides from soma own the dynamic curve so cascade doesn't clobber them) - commit-set → sound('handle.snap.chime', gain 0.14) + tap haptic Sound resolver (src/uix/sema/sounds.ts): - resolveSplitterDragSound — heavier sonic register than slider since splitters move whole panels, not a thumb: pitch 480..820 Hz (slider: 760..1280) centroid 2400..4800 (slider: 3600..6800) — less brilliant roughness 0.006 (slider: 0.003) — woody texture, not metallic envelope attack 16 / decay 72 / duration 76 — perceptual mass gain 0.025 + velocity*0.03 — restrained ceiling, long swipes ok Soma drag-signal infrastructure (splitter-provider.svelte.ts): - Mirrors slider's frame-throttled signal pipeline: dragSignalFrame / pendingDragPercent / lastDragSignalAt / lastDragPercent DRAG_SIGNAL_MS = 72ms throttle (≈14 Hz emit cadence) - dragSignalOverrides(percent01) computes velocity01 from frame delta, builds SemaSignatureOverride with sound (via resolveSplitterDragSound) and haptic (tick scaled by velocity). - queueHandleDrag / cancelQueuedHandleDrag wrap requestFrame so each pointermove only schedules one trigger per throttle window. - onpointerdown calls resetDragSignal(startSizeA/100) to anchor the velocity baseline at grab time. - onpointerup / onlostpointercapture / unmount $effect all cancel the queued frame so we don't fire post-release. Verified in browser at /uix/components/splitter: handle-pick → 1 event (family: handle) handle-drag → frame-throttled across 6 pointermoves commit-set → 1 event (family: commit, intent: neutral) Checks: svelte-check 0 errors, 133/133 vitest (splitter + sema), component:audit 91/91 PASS. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
resolveSplitterDragSound,
type DragSoundParams,
type SampleSoundDefinition,
type SoundDefinition,
type SoundDirection,
type SoundName,
type SoundOverride,
type SoundTuningName,
type SynthSoundDefinition
} from './sounds';
sema/morfo/eidos: typed selector builder + dialog wrapper + emerge color sema architecture - sema-map: 5-channel registry (motion / sound / color / presence / haptic) via SemaChannelSignatures declaration merging; engine stamps data-event-* tokens; flat CSS-style cascade replaces the eventLabel-overrides middle layer. - sema-map: emerge family gains base.color so intent deltas can shift hue / saturation / intensity. Without a base, the resolver was skipping the channel and Dialog open with intent='threat' rendered as neutral blue in the Sema tab visualisation. - types: SEMA_FAMILY_POLICY const drives compile-time + runtime intent requirements per family. Object shape so future per-family policy fields fit alongside. Emerge events MAY now declare intent (canon update — a Dialog confirming threat carries it in its very appearance). - chans: rename vibra→haptic, add HapticChannel V1 (Vibration API); SoundChannel eager-init on first user gesture (autoplay race fix). morfo selector discipline - morfo/selectors.ts (new): semaSelector(morfo, partKebab, matchers?) — type-checked against morfo.parts and morfo.events. Sema cascade rules MUST use it; hand-written strings are an architecture violation that breaks silently when morfo renames a part. - dialog morfo: open carries intent via fromProp; close-cancel / close-dismiss / close-dismiss-outside drop intent (cancellation has no evaluative load); close-save stays hardcoded fulfill (commit fulfils the user's decision regardless of dialog context). eidos dialog migration (4th pilot) - eidos/components/dialog/: full subdirectory wrapper — flat <Dialog> + compound Provider/Trigger/Overlay/Content/Title/Description/Close/Header/ Footer; size + position responsive props; sheet auto-form on narrow viewports; closePosition for the auto-X. - sema/components/dialog.ts: cascade rules use semaSelector(dialogMorfo, 'content', matchers?). Intent block adds character (haptic kind / pattern) but never overrides pitch / gain / contour — those are intent.deltas signature ownership and overriding flattens per-intent perceptual difference. demo controls + dialog page - src/lib/_demo (DemoSwitch / DemoEnum / DemoText / DemoRange) — unified controls reused across all component demos. - web/routes/dialog: live preview always rendered above tabs; per-event Sema tab with independent intent probe; signature visualisation + Play buttons with fallback target chain. documentation - CLAUDE.md: intent.deltas signature ownership rule; eidos drift defense doctrine (types over lint); 2026-05-09 hand-off entry. - morfo/README: Typed selector builder section. - eidos/README: linter section reframed as opt-in safety net for plain CSS recipes; the architectural mechanism is compile-time typing. - sema/README: open channel registry + flat cascade docs + override semantics + intent policy const + selector builder discipline. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
export { stampEventAttrs, unstampEventAttrs } from './stamp';
sema: revive resolver + signatures + real SoundChannel Restores the resolver-driven architecture that was deleted in the channel-modules refactor (commit a0a1485b). Each signal now flows through a single resolution that produces an `EffectiveSignature`, and each channel reads its own slice — so the visual hold, the sound earcon, and (future) motion / color / presence channels all share a single family-level perceptual budget defined in `SEMA_MAP`. New surfaces: - `src/uix/sema/sema-map.ts` — typed perceptual map (port of the legacy `sema-map.json`) with per-family `base` (motion / sound / color / presence) + `activeChannels` and per-intent `deltas` using the number / `{op:'add'}` / `{op:'multiply'}` / `{op:'replace'}` / recursive-merge semantics from before. - `src/uix/sema/resolver.ts` — pure `resolveSignature(signal)` that returns an `EffectiveSignature`. Empty signature when family is missing so channels skip rather than throw. Intent deltas only apply to valenced families. Optional `soundPack` per-event sample URLs. - `src/uix/sema/chans/sound.ts` — real `SoundChannel` (~290 lines, ported from a0a1485b^). Single AudioContext + master GainNode, auto-unlock for Safari/iOS via `click` / `touchstart` / `keydown` with capture, ADSR-lite synthesis (sine + 5th → biquad lowpass → envelope, AM modulator when roughness > 0.2), contour via `osc.detune`, optional sample playback with `AudioBuffer` cache. Errors absorbed silently — sema is ornamental. Architectural changes: - `Channel.handle(signal, effective)` — every channel now receives the resolved signature alongside the signal. Channels can ignore it. - `EngineSemantic.emit` resolves once per emit, dispatches both args. - `VisualChannel` hold resolution chain is now (highest priority first): 1. `signal.hold` 2. `effective.motion.duration` ← NEW: from sema-map 3. family fallback table (SEMA_DURATIONS) 4. engine `defaultHold` Behavior change: families with motion in the map (alert: 220ms, contact: 80ms, commit: 180ms, …) now use those values instead of the previous label-based 600ms / 120ms / 240ms fallbacks. The fallback table remains as a safety net for families without motion (sustain). - `EngineSemanticOptions` adds `sound?: true | false | SoundChannelOptions | Channel`. Sound is opt-in (audible side effects). Layouts wire `defineEngineSemantic({ sound: true })`. Tests: - New `resolver.test.ts` (7 tests) — locks down family base, intent deltas, multiplicative ops, transitional-family no-op, deep-clone. - `visual.test.ts` — every `handle` call now passes a stub `EffectiveSignature`. Two new tests: motion.duration takes the hold, and signal.hold overrides effective.motion.duration. - `engine.test.ts` — `makeChannel` mock signature updated. - `emit.test.ts` — alert family default test now expects 220ms (from sema-map) instead of 600ms. Verified: - vitest: 6 files / 53 tests green - smoke: 68/68 soma routes 200 OK - morfo-check: 66/66 morfos validate
5 months ago
// ── DOM signal projection (Phase 3 of the codex refactor) ──────────────────
export { DomSignalProjector, type ProjectionHandle, type SignalProjector } from './projection';
sema: canonical action verb vocabulary (SEMA_VERBS) Cross-component verb names that morfo `events[].name` should preferably align with. Lets sema / sound / vibra engines subscribe by verb instead of by component-specific event name, and lets eidos write transversal selectors like `[data-event^="dismiss"]`. Vocabulary (24 verbs, grouped by family alignment) - emerge: present, dismiss, open, close, expand, collapse - commit: commit, cancel, confirm, submit, reset, fail - alert: announce, alert - contact: activate, select, toggle - handle: acknowledge, edit, drag, resize - sustain: tick, progress Composite event names follow `{verb}-{variant}` (e.g. `commit-save`, `dismiss-outside`). The verb is the head; the rest is component-specific nuance the validator extracts and reports separately. `validateEventName(name)` returns `{ name, head, matchesCanonical, variant }`. Advisory — doesn't reject morfos, just surfaces drift for tooling / review (a future `sema:vocabulary` script can use it to flag composite event names whose head isn't canonical). Existing event names already align well - Toast: `present`, `announce`, `dismiss` — all canonical bare verbs. - Dialog: `open`, `close-save`, `close-cancel`, `close-dismiss`, `close-dismiss-outside`, `close-after-fail` — all canonical heads (`open`, `close`) with variants. Tests: 10 unit tests covering vocabulary integrity, isSemaVerb guard, validateEventName splitting/matching, and a snapshot of current dialog + toast event names against the catalog (all match). This is the second extension justified under the "2-of-3 rule": verbs are consumed by sema (subscription routing) AND eidos (selector generation), with the original morfo authoring as the third producer.
6 months ago
export {
SEMA_VERBS,
validateEventName,
isSemaVerb,
sema/morfo/eidos: align with GUIA_IMPLEMENTACION_SEMAUIX (canonical guide) The new doctrinal guide at src/docs/GUIA_IMPLEMENTACION_SEMAUIX.md supersedes src/docs/sema-implementation-guide.md and locks the canonical vocabulary, event shape and color tokens. This commit aligns the codebase to that canon in three concrete moves. Phase 1 — sema/verbs.ts vocabulary: - Restructured from flat array to family-keyed Record per the guide. - Moved select / toggle / acknowledge → commit (these fix state, not contact). Removed edit from handle (it's shift.enter-mode now). - Added new verbs per the canon: contact (tap, focus, trigger, release), commit (complete, restore, expire, set, remove, reorder), signal (remind), handle (rotate, scroll, reorder), shift (route, step, return, context), sustain (start, loading, waiting, syncing, processing, streaming, pending, retrying, end). - validateEventName now recognises both naming shapes: {verb}-{variant} (head=verb) and {family}-{verb} (head=family). - New helper familyForVerb. Tests rewritten — 16/16 green. Phase 2 — morfo event shape: - target moved from event-level into event.semantic. Adds optional semantic.verb (advisory, validated against SEMA_VERBS[family]) and optional semantic.sequence ('pre' | 'coincident' | 'post'). - compile.ts and schema.ts updated. The 22 events across toggle, toast, popover, drawer, dialog refactored to the new shape with explicit verb + sequence. - Polymorphic capability (allowedFamilies + defaultSemantic) and a11ySemantic deferred — no current consumer needs them; will land when the first concrete usage appears. Phase 5 — color tokens (doctrinal 8): - themes/base/light.css and dark.css rewritten to expose primary, secondary, neutral, affirm, fulfill, risk, threat, loss. Renames success→fulfill, warning→risk, danger→threat (same hex). New primitives for secondary (slate-blue), affirm (teal-mint, low activation), loss (deep violet-grave, posterior). info palette deleted entirely — per guide, "info no es intent, es signal.announce + neutral". - _static.css legacy compatibility aliases (--color-bg, --color-success, --color-error, --color-accent, ...) deleted. Clean cut, no transition. Consumers reference doctrinal palettes directly. - 29 consumers (token files + recipes) migrated: - All --*-color-info-* declarations dropped. - Component palettes extended with secondary / affirm / loss. - switch + checkbox recipes updated to use [data-color='affirm'| 'risk'|'threat'|'secondary'] (was 'success'|'warning'|'danger'| 'info'). - toast tokens + recipe renamed to affirm/fulfill/risk/threat/loss (was success/error/warning/info). - meter, progress, mark, badge, button tokens renamed. - Contracts (contracts/contract.css + contracts/components/*) updated. - focus-ring-color-error in themes now points to --color-risk-border (validation errors are signal.warn + risk per doctrina, not threat). Phase 4 (partial): - src/docs/sema-implementation-guide.md deleted (superseded by the canonical guide). Tests: 217/217 green across uix. npm run check holds at the 39-error baseline (all pre-existing in unrelated test files; none introduced). Pending in follow-up commits: - Update active_architecture.md, sema/README.md, morfo/README.md, CLAUDE.md to reflect the canon. - Switch component migration to the eidos wrapper pattern. - Persistence field (untilAction / untilFix / stateBound) and holds-by-intent — defer until the first signal.warn / signal.alert consumer appears. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
familyForVerb,
sema: canonical action verb vocabulary (SEMA_VERBS) Cross-component verb names that morfo `events[].name` should preferably align with. Lets sema / sound / vibra engines subscribe by verb instead of by component-specific event name, and lets eidos write transversal selectors like `[data-event^="dismiss"]`. Vocabulary (24 verbs, grouped by family alignment) - emerge: present, dismiss, open, close, expand, collapse - commit: commit, cancel, confirm, submit, reset, fail - alert: announce, alert - contact: activate, select, toggle - handle: acknowledge, edit, drag, resize - sustain: tick, progress Composite event names follow `{verb}-{variant}` (e.g. `commit-save`, `dismiss-outside`). The verb is the head; the rest is component-specific nuance the validator extracts and reports separately. `validateEventName(name)` returns `{ name, head, matchesCanonical, variant }`. Advisory — doesn't reject morfos, just surfaces drift for tooling / review (a future `sema:vocabulary` script can use it to flag composite event names whose head isn't canonical). Existing event names already align well - Toast: `present`, `announce`, `dismiss` — all canonical bare verbs. - Dialog: `open`, `close-save`, `close-cancel`, `close-dismiss`, `close-dismiss-outside`, `close-after-fail` — all canonical heads (`open`, `close`) with variants. Tests: 10 unit tests covering vocabulary integrity, isSemaVerb guard, validateEventName splitting/matching, and a snapshot of current dialog + toast event names against the catalog (all match). This is the second extension justified under the "2-of-3 rule": verbs are consumed by sema (subscription routing) AND eidos (selector generation), with the original morfo authoring as the third producer.
6 months ago
type SemaVerb,
sema/morfo/eidos: align with GUIA_IMPLEMENTACION_SEMAUIX (canonical guide) The new doctrinal guide at src/docs/GUIA_IMPLEMENTACION_SEMAUIX.md supersedes src/docs/sema-implementation-guide.md and locks the canonical vocabulary, event shape and color tokens. This commit aligns the codebase to that canon in three concrete moves. Phase 1 — sema/verbs.ts vocabulary: - Restructured from flat array to family-keyed Record per the guide. - Moved select / toggle / acknowledge → commit (these fix state, not contact). Removed edit from handle (it's shift.enter-mode now). - Added new verbs per the canon: contact (tap, focus, trigger, release), commit (complete, restore, expire, set, remove, reorder), signal (remind), handle (rotate, scroll, reorder), shift (route, step, return, context), sustain (start, loading, waiting, syncing, processing, streaming, pending, retrying, end). - validateEventName now recognises both naming shapes: {verb}-{variant} (head=verb) and {family}-{verb} (head=family). - New helper familyForVerb. Tests rewritten — 16/16 green. Phase 2 — morfo event shape: - target moved from event-level into event.semantic. Adds optional semantic.verb (advisory, validated against SEMA_VERBS[family]) and optional semantic.sequence ('pre' | 'coincident' | 'post'). - compile.ts and schema.ts updated. The 22 events across toggle, toast, popover, drawer, dialog refactored to the new shape with explicit verb + sequence. - Polymorphic capability (allowedFamilies + defaultSemantic) and a11ySemantic deferred — no current consumer needs them; will land when the first concrete usage appears. Phase 5 — color tokens (doctrinal 8): - themes/base/light.css and dark.css rewritten to expose primary, secondary, neutral, affirm, fulfill, risk, threat, loss. Renames success→fulfill, warning→risk, danger→threat (same hex). New primitives for secondary (slate-blue), affirm (teal-mint, low activation), loss (deep violet-grave, posterior). info palette deleted entirely — per guide, "info no es intent, es signal.announce + neutral". - _static.css legacy compatibility aliases (--color-bg, --color-success, --color-error, --color-accent, ...) deleted. Clean cut, no transition. Consumers reference doctrinal palettes directly. - 29 consumers (token files + recipes) migrated: - All --*-color-info-* declarations dropped. - Component palettes extended with secondary / affirm / loss. - switch + checkbox recipes updated to use [data-color='affirm'| 'risk'|'threat'|'secondary'] (was 'success'|'warning'|'danger'| 'info'). - toast tokens + recipe renamed to affirm/fulfill/risk/threat/loss (was success/error/warning/info). - meter, progress, mark, badge, button tokens renamed. - Contracts (contracts/contract.css + contracts/components/*) updated. - focus-ring-color-error in themes now points to --color-risk-border (validation errors are signal.warn + risk per doctrina, not threat). Phase 4 (partial): - src/docs/sema-implementation-guide.md deleted (superseded by the canonical guide). Tests: 217/217 green across uix. npm run check holds at the 39-error baseline (all pre-existing in unrelated test files; none introduced). Pending in follow-up commits: - Update active_architecture.md, sema/README.md, morfo/README.md, CLAUDE.md to reflect the canon. - Switch component migration to the eidos wrapper pattern. - Persistence field (untilAction / untilFix / stateBound) and holds-by-intent — defer until the first signal.warn / signal.alert consumer appears. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
type SemaFamilyName,
sema: canonical action verb vocabulary (SEMA_VERBS) Cross-component verb names that morfo `events[].name` should preferably align with. Lets sema / sound / vibra engines subscribe by verb instead of by component-specific event name, and lets eidos write transversal selectors like `[data-event^="dismiss"]`. Vocabulary (24 verbs, grouped by family alignment) - emerge: present, dismiss, open, close, expand, collapse - commit: commit, cancel, confirm, submit, reset, fail - alert: announce, alert - contact: activate, select, toggle - handle: acknowledge, edit, drag, resize - sustain: tick, progress Composite event names follow `{verb}-{variant}` (e.g. `commit-save`, `dismiss-outside`). The verb is the head; the rest is component-specific nuance the validator extracts and reports separately. `validateEventName(name)` returns `{ name, head, matchesCanonical, variant }`. Advisory — doesn't reject morfos, just surfaces drift for tooling / review (a future `sema:vocabulary` script can use it to flag composite event names whose head isn't canonical). Existing event names already align well - Toast: `present`, `announce`, `dismiss` — all canonical bare verbs. - Dialog: `open`, `close-save`, `close-cancel`, `close-dismiss`, `close-dismiss-outside`, `close-after-fail` — all canonical heads (`open`, `close`) with variants. Tests: 10 unit tests covering vocabulary integrity, isSemaVerb guard, validateEventName splitting/matching, and a snapshot of current dialog + toast event names against the catalog (all match). This is the second extension justified under the "2-of-3 rule": verbs are consumed by sema (subscription routing) AND eidos (selector generation), with the original morfo authoring as the third producer.
6 months ago
type VerbValidation
} from './verbs';
sema: canonical action verb vocabulary (SEMA_VERBS) Cross-component verb names that morfo `events[].name` should preferably align with. Lets sema / sound / vibra engines subscribe by verb instead of by component-specific event name, and lets eidos write transversal selectors like `[data-event^="dismiss"]`. Vocabulary (24 verbs, grouped by family alignment) - emerge: present, dismiss, open, close, expand, collapse - commit: commit, cancel, confirm, submit, reset, fail - alert: announce, alert - contact: activate, select, toggle - handle: acknowledge, edit, drag, resize - sustain: tick, progress Composite event names follow `{verb}-{variant}` (e.g. `commit-save`, `dismiss-outside`). The verb is the head; the rest is component-specific nuance the validator extracts and reports separately. `validateEventName(name)` returns `{ name, head, matchesCanonical, variant }`. Advisory — doesn't reject morfos, just surfaces drift for tooling / review (a future `sema:vocabulary` script can use it to flag composite event names whose head isn't canonical). Existing event names already align well - Toast: `present`, `announce`, `dismiss` — all canonical bare verbs. - Dialog: `open`, `close-save`, `close-cancel`, `close-dismiss`, `close-dismiss-outside`, `close-after-fail` — all canonical heads (`open`, `close`) with variants. Tests: 10 unit tests covering vocabulary integrity, isSemaVerb guard, validateEventName splitting/matching, and a snapshot of current dialog + toast event names against the catalog (all match). This is the second extension justified under the "2-of-3 rule": verbs are consumed by sema (subscription routing) AND eidos (selector generation), with the original morfo authoring as the third producer.
6 months ago
export { SemaDuplicateChannelError, SemaInvariantError } from './errors';
export { validateSemaEvent, validateIntentBinding } from './validation';

Powered by TurnKey Linux.