diff --git a/CLAUDE.md b/CLAUDE.md index d451d5252..885dff27a 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -204,39 +204,32 @@ import { dialogMorfo } from '$uix/morfo/components/dialog' ## Sema: intent policy per family -The doctrinal stance on intent declaration is encoded as a policy const, -**`SEMA_FAMILY_POLICY`** in `src/uix/sema/types.ts`: +Per book canon there are **8 families**, encoded in `SEMA_FAMILY_POLICY` at +`src/uix/sema/types.ts`. Each family declares two independent axes: ```ts { - contact: { intentPolicy: 'allowed' }, // intent OPTIONAL — neutral default - commit: { intentPolicy: 'expected' }, // intent REQUIRED — every consummation evaluates - signal: { intentPolicy: 'expected' }, // intent REQUIRED — alarms inherently evaluative - handle: { intentPolicy: 'allowed' }, // intent OPTIONAL — drag/scrub usually neutral - emerge: { intentPolicy: 'optional' }, // intent OPTIONAL — Dialog confirming threat declares - shift: { intentPolicy: 'optional' }, - sustain: { intentPolicy: 'optional' } + contact: { intentRequirement: 'optional', intentGuidance: 'discouraged' }, + commit: { intentRequirement: 'required', intentGuidance: 'expected' }, + signal: { intentRequirement: 'required', intentGuidance: 'expected' }, + handle: { intentRequirement: 'optional', intentGuidance: 'contextual' }, + emerge: { intentRequirement: 'optional', intentGuidance: 'contextual' }, + shift: { intentRequirement: 'optional', intentGuidance: 'contextual' }, + sustain: { intentRequirement: 'optional', intentGuidance: 'contextual' }, + delegate: { intentRequirement: 'optional', intentGuidance: 'contextual' } } ``` -Each entry is an object so future per-family policy fields (sequence -default, allowed channels, hold preferences, gesture phases, …) live -alongside without restructuring consumers. +- **`intentRequirement`** (`'required' | 'optional' | 'forbidden'`) — compile-time gate. `required` → `intent` REQUIRED in `MorfoEventSemantic` (discriminated union). `forbidden` is reserved for future use (no family uses it today). +- **`intentGuidance`** (`'expected' | 'contextual' | 'discouraged'`) — doctrinal hint, not type-enforced. Drives lint warnings and editor tooltips. -Type derivation: `SemaEvent` and `MorfoEventSemantic` discriminate over this -policy. Editing the const reshapes the discriminated union: `'expected'` → -`intent` REQUIRED at compile-time; `'allowed'` / `'optional'` → optional. +Type derivation: `SemaEvent` and `MorfoEventSemantic` discriminate over `intentRequirement`. Editing the const reshapes the discriminated union. -Runtime enforcement: `validateSemaEvent` throws when an `'expected'` family -declares an event without intent. `'optional'` families pass silently when -intent is absent. +Runtime enforcement: `validateSemaEvent` throws when an `intentRequirement: 'required'` family declares an event without intent. Optional families pass silently. -**This replaces the prior valenced/transitional split as the gatekeeper -for intent**. The valenced/transitional distinction still exists as a -family classification but no longer dictates intent rules — the policy -const does. Real-world UX needs (a Dialog opening to confirm a destructive -action carries threat in its very emergence) made the strict rule -counter-productive. +**`delegate`** is the 8th family per book cap. 29 — reparto de iniciativa entre usuario y sistema. Structural; carries no intent of its own. Active channels empty (delegate composes with sustain / signal / commit for perceptual layering, doesn't own a base signature). + +The earlier flat `intentPolicy: 'allowed' | 'expected' | 'optional'` mixed type-requirement with doctrinal guidance. The split was applied in commit `00f0b740`. ## Sema: open channel registry + flat CSS-style cascade @@ -472,6 +465,38 @@ Next concrete steps: Baseline `npm run check` shows 39 pre-existing errors in test files unrelated to this work. Tests are 217/217 green across uix. +## Session hand-off — 2026-05-26 (sema canon + soma emission + READMEs) + +Sprint completing the alignment of the project with the book *Diseñando lo que ocurre*. Nine commits closed P1 #3, P1 #4 and P1 #5 of the audit-codex: + +``` +504780ad expression field + sema coverage check +2d562f37 11 sema packs + doctrina samples (D.5/D.6/D.7) +826ca2bf D.8 channels scope doctrine +43b15372 picker-shell INTERNAL (P1 #5 closed) +66318c47 tree-view target → branch for emerge events +adf89a08 batch A — soma emission for 7 packs-shipped components +0784cae5 batch B — 8 components with sema scope, no pack +cbf76b66 batch C — drag-drop + virtual-list/grid +7afa7057 23 component READMEs with Sema events sections +``` + +**Architectural deltas from this sprint:** + +- **`Morfo.expression`** new field (`'pack' | 'family-default' | 'delegated' | 'none'`) declares how each morfo with declared events materialises its perceptual signature. Schema-validated; lint enforces coverage. See `src/uix/morfo/types.ts` + `LIBRO_VARIACIONES_Y_EXTENSIONES.md` D.4. +- **`SemaFamily` is now 8** (added `delegate` per book cap. 29). `SEMA_FAMILY_POLICY` carries two axes (`intentRequirement` + `intentGuidance`) — see updated section above. +- **`SEMA_VERBS`** extended with `signal.inform`, `commit.unselect`, contextual verbs (`apply`, `partial`, `block`, `move`, `upload`, `acknowledge`, `confirm`). +- **38 sema packs** under `src/uix/sema/components/*.ts` compose 9 canonical tuning profiles (`form.commit.soft/subtle`, `form.toggle.silent`, `tooltip.silent`, `emerge.soft`, `emerge.exit/.soft`, `emerge.medium`, `emerge.dismiss.passive`, `tabs.select.soft`). Apps override at `defineEngineSemantic({ overrides: { cascade: [...] } })`. +- **Soma emission cabled** in 18 components (toggle-group, menubar, navigation-menu, dropdown-menu, context-menu, tree-view, tree-grid, listbox, grid-list, table, feed, command, carousel, announce, clipboard, drag-drop, virtual-list, virtual-grid). Pattern: emit from the central state-mutator with `fallbackTarget` resolving the specific element so the cascade matches the right instance. +- **`handle-scroll*` intentionally NOT emitted** in virtual-list / virtual-grid — family.handle activates haptic only; emitting on every pixel of scroll would buzz the device nonstop. Apps that want scroll-feedback wire their own throttled emit. Documented in both READMEs. +- **picker-shell relocated** from `src/uix/morfo/components/` to `src/uix/morfo/internal/` — declares its INTERNAL status by file location. Apps never write ``; the five composite pickers (date / date-range / time / time-range / color) re-export the shell parts under their own namespace. README added at `src/uix/eidos/components/picker-shell/README.md`. +- **`LIBRO_VARIACIONES_Y_EXTENSIONES.md`** is the authoritative registry for project decisions vs the book canon. Sections D.4 (`expression` field), D.5 (toggles soft-tuned packs), D.6 (menus/trees packs), D.7 (samples doctrine — `SOUND_LIBRARY` = resources, `SOUND_TUNINGS` = canon, packs compose tunings never samples; `sampleOverlay` rejected permanently), D.8 (channels scope — `sound` + `haptic` are the only canonical runtime channels; ARIA structural lives in morfo, ARIA dynamic in soma, visual in eidos — never canonized as channels). +- **23 soma component READMEs** now include a `## Sema events` table with event / family / verb / target / intent / when + pack reference + doctrinal notes for the verb-rename corrections applied across the sprint. + +**Verification at hand-off**: `npm run morfo:vocabulary` EXIT 0 (clean). `npx vitest run src/uix/sema src/uix/morfo` 195/195. `npx vitest run src/uix/soma` 419/419. Pre-existing words/* type errors unchanged (separate dev track). + +**What's left from the audit-codex**: P2 (34 demos NEEDS-WORK) — explicitly out of scope (full refactor of demos + web routes pending separately). + --- # Behavioral Guidelines